florr megg timer

shows 15s timer for mythic egg/yggdrasil

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==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();