您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Show spawn timer, sharing another players. Work In Progress https://discord.gg/4nPjXjVf4t
当前为
// ==UserScript== // @name Ultra Mobs Alert // @namespace http://tampermonkey.net/ // @version 4 // @description Show spawn timer, sharing another players. Work In Progress https://discord.gg/4nPjXjVf4t // @author @jmatg1 // @license MIT // @match https://florr.io // @icon https://www.google.com/s2/favicons?sz=64&domain=florr.io // @grant none // ==/UserScript== const VERSION = "4"; try { let xhr = new XMLHttpRequest(); xhr.open('GET', "https://greasyfork.org/ru/scripts/465457.json"); xhr.send(); xhr.onload = function() { let obj = JSON.parse(xhr.response) if (obj.version !== VERSION){ let t = "New Version!!!" + " (" + VERSION + " -> " + obj.version + ") https://greasyfork.org/ru/scripts/465457-ultra-mobs-alert" window.alert(t) } }; } catch (e){} function createInput() { var array = ["NA", "EU", "AS"]; var selectList = document.createElement("select"); selectList.style.pointerEvents = "auto"; selectList.id = "serverIdSelect"; for (var i = 0; i < array.length; i++) { var option = document.createElement("option"); option.value = array[i]; option.text = array[i]; selectList.appendChild(option); } return selectList; } class GUI { constructor(serv) { this.data = {}; this.bosses = []; const div = document.createElement('div'); div.appendChild(createInput()); this.menu = document.body.appendChild(document.createElement('div')); this.menu.appendChild(div); this.menu.style.padding = '15px'; this.menu.style.background = '#ffffff3f'; this.menu.style['border-radius'] = '10px'; this.menu.style.display = 'block'; this.menu.style.position = 'absolute'; this.menu.style['pointer-events'] = 'none'; this.menu.style.bottom = '5px'; this.menu.style.right = '5px'; this.table = this.menu.appendChild(document.createElement('table')); this.table.style['font-family'] = 'Ubuntu'; this.table.style['border-collapse'] = 'collapse'; this.table.style.width = `100%`; setInterval(() => { this.updateTable(); }, 60 * 1000) } updateTable(bosses = this.bosses) { console.log(bosses); this.bosses = bosses; while (this.table.rows.length > 0) { this.table.deleteRow(0); } bosses.sort((a, b) => { return new Date(a.date).getTime() - new Date(b.date).getTime(); }); bosses = bosses.filter((x) => { const minutes = Math.floor((Date.now() - new Date(x.date).getTime()) / 1000 / 60); if (minutes > 25) { return false } return true; }); bosses.forEach((x, i) => { const tr = this.table.insertRow(); // Mob const td1 = tr.insertCell(); if (i !== 0) { td1.style['padding-top'] = '5px'; } if (i !== bosses.length - 1) { td1.style['padding-bottom'] = '5px'; } td1.style['padding-right'] = '20px'; td1.appendChild(document.createTextNode(x.name)); // minutes ago const td2 = tr.insertCell(); if (i !== 0) { td2.style['padding-top'] = '5px'; } if (i !== bosses.length - 1) { td2.style['padding-bottom'] = '5px'; } td2.style['pointer-events'] = 'auto'; td2.style.cursor = 'pointer'; td2.appendChild(document.createTextNode(this.toTimeSpanString(x.date))); }); } toTimeSpanString(timestamp) { if (timestamp == null) { return 'N/A'; } let minutes = Math.floor((Date.now() - new Date(timestamp).getTime()) / 1000 / 60); let h = Math.floor(minutes / 60); minutes = minutes % 60; return `${String(h).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`; } changeServer(id) { this.updateTable(this.data[id]); } } class ServerId { constructor() { this.servers = []; this.url; this.regionName; const nativeWebSocket = window.WebSocket; var totalServers = 17 - 1; var allServers = []; var _this = this; window.WebSocket = function (...args) { const socket = new nativeWebSocket(...args); _this.url = socket.url; var wb = new TextDecoder("utf8") socket.addEventListener("message", (event) => { //console.log(wb.decode(event.data)); }); return socket; }; const urls = []; for (let i = 0; i <= totalServers; i++) { urls.push(`https://api.n.m28.io/endpoint/florrio-map-${i}-green/findEach/`); } Promise.all(urls.map(url => fetch(url).then(resp => resp.text()) )).then(texts => { if (texts.length === 17) { texts.forEach(el => { const data = JSON.parse(el) this.servers.push(`${data.servers["vultr-miami"].id} ${data.servers["vultr-frankfurt"].id} ${data.servers["vultr-tokyo"].id}`); }) } }) } getId() { if(this.regionName) { return this.regionName } var wssUrl = this.url.slice(6, 9) var codeA = []; this.servers.forEach((x, index) => { if (x.includes(wssUrl)) { codeA = x.split(" ") if (wssUrl == codeA[0]) this.regionName = "NA" else if (wssUrl == codeA[1]) this.regionName = "EU" else if (wssUrl == codeA[2]) this.regionName = "AS" } }); return this.regionName; } } class WebSocketMy { constructor(gui, serv) { this.socket; this.gui = gui; this.serv = serv; this.intervalREconnect = false; this.init(); } init() { this.socket = new WebSocket("wss://cyber-glorious-ferry.glitch.me"); this.socket.onmessage = (event, isBinary) => { const message = JSON.parse(event.data); if (message.message === "PONG") { return } this.gui.data = message; this.gui.updateTable(message[document.getElementById('serverIdSelect').value]); }; this.socket.onopen = (e) => { console.log("[open] Соединение установлено"); if(this.intervalREconnect) { clearInterval(this.intervalREconnect) this.intervalREconnect = false } setInterval(() => { if (this.socket.readyState === 1) { this.socket.send(JSON.stringify({message: "PING", serverName: 'EU'})); } }, 60 * 1000) }; this.socket.onclose = (event) => { if(event.reason === "null") {return} if(this.intervalREconnect) { clearInterval(this.intervalREconnect) this.intervalREconnect = false } this.intervalREconnect = setInterval(() =>{ if (this.socket.readyState !== 1 && this.socket.readyState !==0 && this.socket.readyState !== 2) { this.init() } }, 1000) if (event.wasClean) { console.log(`[close] Соединение закрыто чисто, код=${event.code} причина=${event.reason}`); } else { console.log('[close] Соединение прервано'); } }; this.socket.onerror = (error) => { console.log(`[error]`); this.init(); }; } send(text) { this.socket.send(text) } } (function () { 'use strict'; const serv = new ServerId(); let intervalREconnect = false const gui = new GUI(serv); let socket = new WebSocketMy(gui, serv); document.getElementById('serverIdSelect').onchange = ev => { gui.changeServer(ev.target.value); console.log(ev.target.value) } setTimeout(() => { document.getElementById('serverIdSelect').value = serv.getId(); gui.changeServer(serv.getId()); }, 15000) var flag = []; function parseText(text, _this) { const lastMessage = flag.find(el => el.text === text); if (lastMessage) { const time = new Date().getTime() - lastMessage.date; if ((time / 1000 / 60) <= 8) { return text } } if (text && text.search(/((An Ultra)|(A Super)) (.*) has spawned!?( somewhere!?)?/i) !== -1) { if (lastMessage) { lastMessage.date = new Date().getTime(); } else { flag.push({text: text, date: new Date().getTime()}) } socket.send(JSON.stringify({message: text, serverName: serv.getId()})); console.warn(JSON.stringify({message: text, serverName: serv.getId()})); } return text } function getCompatibleCanvas() { if (typeof (OffscreenCanvasRenderingContext2D) == 'undefined') { return [CanvasRenderingContext2D] } return [OffscreenCanvasRenderingContext2D, CanvasRenderingContext2D]; } for (const {prototype} of getCompatibleCanvas()) { if (prototype.rewriteStrokeText == undefined) { if (false) { prototype.rewriteArc = prototype.arc } prototype.rewriteStrokeText = prototype.strokeText; prototype.rewriteFillText = prototype.fillText; prototype.rewriteMeasureText = prototype.measureText; } else { break } } for (const {prototype} of getCompatibleCanvas()) { prototype.strokeText = function (text, x, y) { return this.rewriteStrokeText(parseText(text, this), x, y); } prototype.fillText = function (text, x, y) { return this.rewriteFillText(parseText(text, this), x, y); } prototype.measureText = function (text) { return this.rewriteMeasureText(parseText(text, this)); } } })();