您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
shows 15s timer for mythic egg/yggdrasil
// ==UserScript== // @name florr megg timer // @namespace http://tampermonkey.net/ // @version 0.2 // @description shows 15s timer for mythic egg/yggdrasil // @author bismuth // @match https://florr.io/ // @icon https://www.google.com/s2/favicons?sz=64&domain=florr.io // @grant none // @license none // ==/UserScript== class Automator { constructor() { this.index = 0; this.packet; this.buffer = new ArrayBuffer(4); this._u8 = new Uint8Array(this.buffer); this._i32 = new Int32Array(this.buffer); this._f32 = new Float32Array(this.buffer); this.init(); this.ready = false; } endianSwap(val) { return ((val & 0xff) << 24) | ((val & 0xff00) << 8) | ((val >> 8) & 0xff00) | ((val >> 24) & 0xff) } u8() { return this.packet[this.index++] } vu() { let out = 0, at = 0; while (this.packet[this.index] & 0x80) { out |= (this.u8() & 0x7f) << at; at += 7; } out |= this.u8() << at; return out; } getConfig(bin) { const unreachable = 0x00, block = 0x02, loop = 0x03, if_ = 0x04, else_ = 0x05, end = 0x0b, br = 0x0c, br_if = 0x0d, call = 0x10, drop = 0x1a, local_get = 0x20, local_set = 0x21, local_tee = 0x22, global_set = 0x24, i32_load = 0x28, f32_load = 0x2a, f64_load = 0x2b, i32_load8_s = 0x2c, i32_load8_u = 0x2d, i32_load16_u = 0x2f, i32_store = 0x36, i64_store = 0x37, f32_store = 0x38, i32_store8 = 0x3a, i32_store16 = 0x3b, memory_grow = 0x40, i32_const = 0x41, i64_const = 0x42, f32_const = 0x43, i32_eqz = 0x45, i32_eq = 0x46, i32_lt_s = 0x48, i32_lt_u = 0x49, f32_eq = 0x5b, f32_lt = 0x5d, f32_gt = 0x5e, i32_add = 0x6a, i32_sub = 0x6b, i32_and = 0x71, i32_or = 0x72, i32_xor = 0x73, f32_add = 0x92, f32_sub = 0x93, f32_mul = 0x94, f32_demote_f64 = 0xb6; const i32 = 0x7f, i64 = 0x7e, f32 = 0x7d, f64 = 0x4c; const param = 0x01, local = 0x02; Number.prototype.fromvu = function() { let _ = this; const ret = []; while (_ >= 128) { ret.push((_ & 127) | 128); _ >>= 7; } ret.push(_); return ret; } Number.prototype.fromfloat = function() { return [...new Uint8Array(new Float32Array([this]).buffer)]; } Array.prototype.countingOccurences = function(val) { let count = 0; for (const a of this) if (a === val) count++; return count; } const wasmRegex = (regex, repeat = false, start = 0) => { let ret = [], rets = []; jump: for (let n = start; n < this.packet.length - regex.length; n++) { this.index = n; ret = []; for (let p = 0; p < regex.length; p++) { if (regex[p] === '*') this.vu(); else if (regex[p] === '+') ret.push(this.vu()); else if (this.u8() !== regex[p]) continue jump; } ret.index = n; if (repeat) rets.push(ret); else return ret; } return rets.length? rets: false; } const components = ['GUI','player']; let entListPtr, offset, entSize, componentOffsets = {}, fieldOffsets = {}, animatedBasePtrPtr, animatedOffset, arenaDimAnimated, squadCodeOffset; const c = [], fIndex = []; const funcs = []; const field_func = new Array(150).fill().map((_,ind) => ind & 1? '*': block); let count = 0; this.packet = new Uint8Array(bin); this.index = 8; while (this.index < this.packet.length) { const id = this.vu(); const sectionLen = this.vu(); if (id !== 10) { this.index += sectionLen; continue; } const bodyCount = this.vu(); for (let i = 0; i < bodyCount; i++) { const len = this.vu(); funcs.push(this.packet.subarray(this.index, this.index += len)); } break; } for (let funcIndex = 0; funcIndex < funcs.length; funcIndex++) { let a; this.packet = funcs[funcIndex]; /* if (a = wasmRegex([ f32_const, ...(10).fromfloat(), f32_add, local_set, '*', end], true)) { for (const b of a) { const d = b.index; console.log(this.packet.slice(d,d+9)); this.packet.set([i32_const,0,f32_load,0,0], d); count++; } console.log([ f32_const, ...(10).fromfloat(), f32_add, local_set, '*', end]) console.log(a); } */ if (a = wasmRegex([ 12, i32, local_get, '*', i32_load, '*', '+'])) { c.push(a[0]); fIndex.push(funcIndex+358)} if (a = wasmRegex([i32_add, call, '*', block, '*', i32_const, '*', i32_load8_s, '*', '*', i32_const, 0, i32_lt_s, if_, '*', i32_const, '+', i32_load, '*', '*', i32_const, 0])) squadCodeOffset = a[0]; if (a = wasmRegex([f32_load, '*', '*', f32_mul, local_tee, '*', i32_const, '+', f32_load])) arenaDimAnimated = a[0]; if (a = wasmRegex([br_if, '*', local_get, '*', i32_const, '+', i32_add, local_set, '*', i32_const, 1, local_set, '*', block])) fieldOffsets.petalsCollected = a[0]; if (a = wasmRegex([i32_const, '+', i32_add, local_set, '*', loop, '*', local_get, '*', i32_const, '+', i32_sub, call])) [offset, entSize] = a; if (a = wasmRegex([drop, i32_const, '*', i32_const, '*', i32_store, '*', '*', i32_const, '+', call])) entListPtr = a[0]; if (a = wasmRegex([f64_load, '*', '*', f32_demote_f64, local_get, '*', i32_const, '+', i32_add, f32_load, '*', '*', f32_sub, f32_mul, local_get, '*', i32_const])) animatedOffset = a[0]; if (a = wasmRegex([f32_load, '*', '+', f32_store, '*', '+', local_get, '*', local_get, '*', f32_load, '*', '+', f32_store, '*', '+', end])) { fieldOffsets.x = a[0]; fieldOffsets.prevx = a[1]; fieldOffsets.y = a[2]; fieldOffsets.prevy = a[3]; } } for (let funcIndex = 0; funcIndex < funcs.length; funcIndex++) { let a; this.packet = funcs[funcIndex]; if (a = wasmRegex(field_func)) { const start = this.index; a = wasmRegex([block, '*', local_get, '*', call, '+', local_tee, '*', i32_load8_u, '*', '*', i32_eqz, if_, '*', local_get, '*', f32_load, '*', '+'], true, start) for (const [compFunc, offset] of a) { if (fIndex.indexOf(compFunc) > 6) { componentOffsets.renderable = c[fIndex.indexOf(compFunc)]; fieldOffsets.radius = offset; break; } } a = wasmRegex([end, local_get, '*', call, '+', local_set, '*', block], true, start); a = a.map(_ => _[0]); let b = []; for (let values of a) if (a.countingOccurences(values) === 3 && b.indexOf(values) === -1) b.push(values); if (b[0] < b[1]) componentOffsets.mob = c[fIndex.indexOf(b[0])]; else componentOffsets.mob = c[fIndex.indexOf(b[1])]; a = wasmRegex([end, local_get, '*', call, '+', local_set, '*', local_get, '*', local_get, '*', call, '*', local_get, '*', local_get, '*', i32_load16_u, '*', '*', i32_store16, '*', '+'], true, start); for (const [compFunc, offset] of a) { if (fIndex.indexOf(compFunc) < 10) { componentOffsets.drop = c[fIndex.indexOf(compFunc)]; fieldOffsets.dropID = offset; fieldOffsets.dropRarity = offset+1; break; } } a = wasmRegex([block, '*', local_get, '*', call, '+', local_tee, '*', i32_load8_u], true, start); a = a.map(_ => _[0]); for (let values of a) if (a.countingOccurences(values) === 2) componentOffsets.position = c[fIndex.indexOf(values)]; const mobFunc = fIndex[c.indexOf(componentOffsets.mob)]; const dropFunc = fIndex[c.indexOf(componentOffsets.drop)]; const playerFunc = fIndex[1]; wasmRegex([end, local_get, '*', call, ...dropFunc.fromvu(), local_set, '*', block], false, start); fieldOffsets.dropRenderFlag = wasmRegex([i32_store8, '*', '+', br],false,this.index)[0]; wasmRegex([end, local_get, '*', call, ...dropFunc.fromvu(), local_set, '*', local_get, '*', i32_load], false, start); fieldOffsets.dropCount = wasmRegex([i32_store, '*', '+', br],false,this.index)[0]; fieldOffsets.petalCooldown = wasmRegex([call, ...playerFunc.fromvu(), i32_const, '+', i32_add, local_set, '*', local_get, '*'], false, start)[0]; fieldOffsets.inventory = wasmRegex([call, ...playerFunc.fromvu(), i32_const, '+', i32_add, local_set, '*', i32_const, '*'], false, start)[0]; break; } } for (let funcIndex = 0; funcIndex < funcs.length; funcIndex++) { let a; this.packet = funcs[funcIndex]; if (a = wasmRegex([i32_load, '*', ...componentOffsets.mob.fromvu(), i32_load8_u, '*', '+', local_tee, '*', local_get, '*', i32_load, '*', '*', i32_load8_u, '*', '*'])) { fieldOffsets.mobRarity = a[0]; if (fieldOffsets.isFriendly) fieldOffsets.mobID = 27 - fieldOffsets.isFriendly - fieldOffsets.mobRarity; } if (a = wasmRegex([local_get, '*', if_, '*', local_get, '*', i32_load, '*', ...componentOffsets.mob.fromvu(), i32_load8_u, '*', '+'])) { fieldOffsets.isFriendly = a[0]; if (fieldOffsets.mobRarity) fieldOffsets.mobID = 27 - fieldOffsets.isFriendly - fieldOffsets.mobRarity; } } components.forEach((name,index) => { componentOffsets[name] = c[index]; }) this.config = { entListPtr, offset, entSize, componentOffsets, fieldOffsets, animatedOffset, arenaDimAnimated, squadCodeOffset }; console.log("Done with config", fIndex); } init() { const that = this; WebAssembly.instantiateStreaming = (r, i) => (r.arrayBuffer().then(b => WebAssembly.instantiate(b, i))); const _instantiate = WebAssembly.instantiate; WebAssembly.instantiate = new Proxy(WebAssembly.instantiate, { apply(t,ta,[bin,imports]) { that.getConfig(bin); return _instantiate(bin, imports).then(wasm => { for (const exp of Object.values(wasm.instance.exports)) { if (exp.buffer) { const buffer = exp.buffer; that.HEAPU8 = new Uint8Array(buffer); that.HEAP8 = new Int8Array(buffer); that.HEAPU16 = new Uint16Array(buffer); that.HEAP32 = new Int32Array(buffer); that.HEAPF32 = new Float32Array(buffer); that.HEAPF64 = new Float64Array(buffer); that.ready = true; break; } } that.loop(); return wasm; }); } }); } meggTimer() { const { HEAPF32, HEAP32, HEAPU16, HEAPU8 } = this; const { entListPtr, offset, entSize, animatedOffset, componentOffsets, fieldOffsets, arenaDimAnimated } = this.config; const camInfo = HEAPF32.subarray(entListPtr + animatedOffset >> 2, entListPtr + animatedOffset + 12 >> 2); const { inventory, petalCooldown, dropID, radius, x, y } = fieldOffsets; const { player, drop, renderable, mob, position } = componentOffsets; const {ctx} = this; ctx.setTransform(1,0,0,1,0,0); this.scale = Math.max(this.canvas.width/1920, this.canvas.height/1080); if (!this.playerEnt[player >> 2]) { for (let n = 0; n < 8192; n++) { if (this.entities[n][player >> 2] && HEAP32[this.entities[n][player >> 2] + inventory >> 2]) { this.playerEnt = this.entities[n]; break; } } } const playerComponent = this.playerEnt[player >> 2]; const time = performance.now(); ctx.setTransform(1,0,0,1,0,0); for (let n = 0; n < 8; n++) { if (HEAPU16[playerComponent + petalCooldown + 2 * n >> 1] !== 65535) { this.lastLoaded[n] = time; continue; } if (HEAPU8[playerComponent + inventory + 2 * n] !== 16 && HEAPU8[playerComponent + inventory + 2 * n] !== 30 ) continue; if (camInfo[0] && camInfo[1] && camInfo[2] <= 0.9 && this.toggle) { const timeDiff = Math.min((time - this.lastLoaded[n]) / 1000, 15); ctx.setTransform(1,0,0,1,this.canvas.width/2,this.canvas.height - 200*this.scale); ctx.lineCap = 'round'; ctx.lineWidth = 8; ctx.strokeStyle = '#333333'; ctx.beginPath(); ctx.moveTo((n-3.9)*this.scale*this.length,0); ctx.lineTo((n-3.1)*this.scale*this.length,0); ctx.stroke(); ctx.lineWidth = 5; ctx.strokeStyle = timeDiff < 15? '#ff0000':'#85e37d'; ctx.beginPath(); ctx.moveTo((0.8*this.scale*this.length)/15*timeDiff+(n-3.9)*this.scale*this.length,0); ctx.lineTo((n-3.9)*this.scale*this.length,0); ctx.stroke(); ctx.lineWidth = 0.9; ctx.setTransform(1,0,0,1,0,0); } else if (!(camInfo[0] && camInfo[1] && camInfo[2] <= 0.9)) for (let n = 0; n < 8; n++) this.lastLoaded[n] = performance.now(); } } loop() { this.alive = false; this.canvas = document.getElementById('canvas'); this.ctx = this.canvas.getContext('2d'); const { HEAPF32, HEAP32, HEAPU16, HEAPU8 } = this; const { entListPtr, offset, entSize, animatedOffset, componentOffsets, fieldOffsets, arenaDimAnimated } = this.config; const { inventory, petalCooldown, dropID, radius, x, y } = fieldOffsets; const { player, drop, renderable, mob, position } = componentOffsets; this.camInfo = HEAPF32.subarray(entListPtr + animatedOffset >> 2, entListPtr + animatedOffset + 12 >> 2); this.playerEnt = new Uint8Array(1000); this.lastLoaded = new Float32Array(8); this.length = 90; this.toggle = false; this.scale = 1; //const toX = x => (x - camInfo[0]) * (scale*camInfo[2]) + canvas.width / 2; //const toY = y => (y - camInfo[1]) * (scale*camInfo[2]) + canvas.height / 2; //preload entities with subarray let at = entListPtr + offset; this.entities = []; for (let n = 0; n < 8192; n++) this.entities.push(HEAP32.subarray(at >> 2, (at += entSize) >> 2)); document.onkeydown = ({code}) => { if (code === 'KeyQ') this.toggle ^= true; } const that = this; window.requestAnimationFrame = new Proxy(requestAnimationFrame, { apply(t,ta,a) { that.meggTimer(); that.alive = that.camInfo[2] <= 0.9; return t.apply(ta,a); } }); } } window.automator = new Automator();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址