您需要先安装一个扩展,例如 篡改猴、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 0.5 // @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== 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 > 240) { 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; const nativeWebSocket = window.WebSocket; var totalServers = 17 - 1; var regionName, allServers = []; var _this = this; window.WebSocket = function (...args) { const socket = new nativeWebSocket(...args); _this.url = socket.url 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() { var wssUrl = this.url.slice(6, 9) var codeA = []; var regionName = ''; this.servers.forEach(function callback(x, index) { if (x.includes(wssUrl)) { codeA = x.split(" ") if (wssUrl == codeA[0]) regionName = "NA" else if (wssUrl == codeA[1]) regionName = "EU" else if (wssUrl == codeA[2]) regionName = "AS" } }); return regionName; } } (function () { 'use strict'; const serv = new ServerId(); const gui = new GUI(serv); let socket = new WebSocket("wss://cyber-glorious-ferry.glitch.me"); 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) socket.onopen = function (e) { console.log("[open] Соединение установлено"); setInterval(() => { socket.send(JSON.stringify({message: "PING", serverName: 'EU'})); }, 60 * 1000) }; socket.onmessage = function (event, isBinary) { const message = JSON.parse(event.data); if (message.message === "PONG") { return } gui.data = message; gui.updateTable(message[document.getElementById('serverIdSelect').value]); }; socket.onclose = function (event) { if (event.wasClean) { console.log(`[close] Соединение закрыто чисто, код=${event.code} причина=${event.reason}`); } else { console.log('[close] Соединение прервано'); } }; socket.onerror = function (error) { console.log(`[error]`); }; var flag = false; function parseText(text, _this) { if (flag) { return } if (text && text.search(/((An Ultra)|(A Super)) (.*) has spawned!?( somewhere!?)?/i) !== -1) { socket.send(JSON.stringify({message: text, serverName: serv.getId()})); console.warn(JSON.stringify({message: text, serverName: serv.getId()})); flag = true; setTimeout(() => { flag = false; }, 10 * 60 * 1000) } //console.log(text, x, y, a) } 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) { parseText(text, this); return this.rewriteStrokeText(text, x, y); } prototype.fillText = function (text, x, y) { parseText(text, this); return this.rewriteFillText((text), x, y); } prototype.measureText = function (text) { parseText(text, this); return this.rewriteMeasureText((text)); } } })();