Dylko's Bumpy Mod

Unlimiter, chat hotkeys, and chat panel script

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

You will need to install an extension such as Tampermonkey to install this script.

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name Dylko's Bumpy Mod
// @description Unlimiter, chat hotkeys, and chat panel script
// @author Dylko
// @version 1.24.1
// @match https://www.pucks.io/*
// @match https://www.bumpyball.io/*
// @icon https://www.google.com/s2/favicons?domain=bumpyball.io
// @run-at document-end
// @namespace https://greasyfork.org/users/1574974
// @grant none
// @license MIT
// @require https://greasyfork.org/scripts/438620-workertimer/code/WorkerTimer.js
// @require https://greasyfork.org/scripts/448029-rblu/code/RBLU.js
// ==/UserScript==

// hi
document.documentElement.style.overflow = 'hidden';
document.body.style.overflow = 'hidden';
document.addEventListener('DOMContentLoaded', e => document.body.style.overflow = 'hidden');
window.logout = () => {
    window.indexedDB.databases().then(d=>d[2]).then(d=>window.indexedDB.deleteDatabase(d.name))
};
// try { window.logout(); } catch (e) {}
const r7bit = arr => {let r=0,e=0;for(;35!=e;){let f=arr[e/7];if(r|=(127&f)<<e,0==(128&f))return[r,e/7+1];e+=7}};
const int7 = (arr, start) => {
    let [value, bytes] = r7bit(arr.slice(start));
    return [value, start+bytes];
};
const float = (arr, start) => {
    let value = new Float32Array(new Uint8Array(arr.slice(start, start+4)).buffer)[0]
    return [value, start+4];
};
const w7bit = num => {let r=[];for(;num>=128;num>>=7)r.push((128|num)%256);return r.push(num%256),r};
const client = window.client = {
    bots: [],
    num: 15,
    team: 2,
    enabled: false,
    chatEnabled: false,
    moveEnabled: true,
    antiAfk: WorkerTimer.setInterval(()=>{
        const hiddenForward = new Uint8Array([8,7,18,10,18,5,13,0,0,128,63,24,200,1]).buffer;
        if (client.ws && client.ws.readyState === 1 && client.ws.id > -1) client.ws._send(hiddenForward);
        client.bots.forEach(b => {
            if (b.readyState === 1 && b.id > -1) b._send(hiddenForward);
        });
    }, 1000),
    sendMessage(text='') {
        if (!this.ws || !this.ws.constId) return;
        const msg = new TextEncoder().encode(text);
        const body = [8,...w7bit(this.ws.constId), 18,...w7bit(msg.length),...msg];
        const head = [8,5, 18,...w7bit(body.length)];
        const data = new Uint8Array([...head, ...body]);
        this.ws.send(data);
    },
    bot(num=15, team=2){
        this.team = team;
        this.num = num;
        return this.enabled = !this.enabled
    },
    move(on = null){
        if (on == null) return this.moveEnabled = !this.moveEnabled;
        return this.moveEnabled = !!on;
    },
    chatBot(on = null){
        if (on == null) return this.chatEnabled = !this.chatEnabled;
        return this.chatEnabled = !!on;
    },
    // 0 - blue, 1 - red
    close(team=2){
        this.bots.forEach(b=>{
            if (team === 2 || team === b.team) {
                WorkerTimer.clearInterval(b.inter);
                b.close();
            }
        });
        this.bots = this.bots.filter(b => team !== b.team);
        if (team === 2) this.bots = [];
    },
    setup(data, num=this.num){
        if (!this.ws.url || !this.enabled) return false;
        for(;num--;){
            WorkerTimer.setTimeout(()=>{
                const ws = new WebSocket(this.ws.url);
                this.bots.push(ws);
                ws.query = [data];
                ws.onopen=function(){
                    ws.inter = WorkerTimer.setInterval(()=>{
                        if (!ws.query.length) return;
                        let data = [...new Uint8Array(ws.query.shift())];
                        ws.send(new Uint8Array(data).buffer);
                    }, 17);
                }
            }, 57*num);
        }
    }
};
const packet = {};
packet.open = (arr, pos=0) => {
    packet.cancel = false;
    packet.arr = arr;
    packet.value = undefined;
    packet.pos = pos;
    return packet;
}
packet.null = () => {
    packet.cancel = true;
    packet.value = null;
    return packet;
}
packet.len = () => {
    if (packet.cancel) return packet;
    let {arr, pos, value} = packet;
    if (arr[pos++] !== 10) return packet.null();
    [value, pos] = int7(arr, pos);
    return Object.assign(packet, {pos, value});
}
packet.code = () => {
    if (packet.cancel) return packet;
    let {arr, pos, value} = packet;
    if (arr[pos++] !== 8) return packet.null();
    [value, pos] = int7(arr, pos);
    return Object.assign(packet, {pos, value});
}
packet.player = () => {
    if (packet.cancel) return packet;
    let {arr, pos, value} = packet;
    let data = {
        id: null,
        constId: null,
        team: null,
        x: null,
        z: null
    };
    if (arr[pos++] !== 10) return packet.null();
    [value, pos] = int7(arr, pos);
    if (arr[pos++] !== 8) return packet.null();
    if (arr[pos++] !== 8) return packet.null();
    if (arr[pos++] !== 18) return packet.null();
    [value, pos] = int7(arr, pos);
    if (arr[pos++] !== 16) return packet.null();
    [value, pos] = int7(arr, pos);
    data.id = value;
    if (arr[pos++] !== 26) return packet.null();
    [value, pos] = int7(arr, pos);
    if (arr[pos++] !== 10) return packet.null();
    [value, pos] = int7(arr, pos);
    if (arr[pos++] !== 13) return packet.null();
    [value, pos] = float(arr, pos);
    data.x = value;
    if (arr[pos++] !== 21) return packet.null();
    [value, pos] = float(arr, pos);
    data.z = value;
    if (arr[pos++] !== 24) return packet.null();
    [value, pos] = int7(arr, pos);
    data.constId = value;
    if (arr[pos] === 42) { //42,0
        data.team = 0;
        pos += 2;
        packet.value = data;
        return Object.assign(packet, {pos});
    }
    //37,219,15,73,192, 42,0
    data.team = 1;
    pos += 5+2;
    packet.value = data;
    return Object.assign(packet, {pos});
}
packet.players = () => {
    if (packet.cancel) return packet;
    let {arr, pos, value} = packet;
    const players = [];
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] !== 10) continue;
        packet.pos = i;
        let data = packet.player().value;
        if (data === null) {
            packet.cancel = false;
            continue;
        }
        players.push(data);
        i = packet.pos-1;
    }
    packet.value = players;
    return packet;
}
const isConnected = arr => {
    packet.open(arr);
    const code = packet.len().code().value;
    if (code === null) return false;
    if (code === 3) return true;
    return false;
}
const isJoinOther = arr => {
    packet.open(arr);
    const code = packet.len().code().value;
    if (code === null) return false;
    if (code === 2) return true;
    return false;
}
const isSpawn = arr => {
    packet.open(arr);
    const code = packet.len().code().value;
    if (code === null) return false;
    if (code === 8) return packet.player().value;
    return false;
}
const getId = arr => {
    // 10,x, 8,8,18,x, 16,id, 26,x, 10,10,13,... ,0,42];
    if (isConnected(arr)) return packet.id(arr).value;
    if (isJoinOther(arr)) return null;
    if (isSpawn(arr)) return packet.id(arr).value;
}
window.r7bit = r7bit;
window.w7bit = w7bit;
window.getId = getId;
(()=>{
    const proto = WebSocket.prototype;
    proto._send = proto.send;
    proto.send = function (data) {
        if (!this.event) {
            this.event = true;
            this.addEventListener('message', async function(e){
                const data = [...new Uint8Array(await e.data.arrayBuffer())];
                const players = packet.open(data).players().value;
                if (players == null) return;
                if (players.length) {
                    if (this.constId == null) Object.assign(this, players[0]);
                    const player = players.find(p => p.constId === this.constId);
                    if (player) Object.assign(this, player);
                }
                if (client.team !== 2 && client.bots.every(b => b.team > -1)) client.close(+(!client.team));
            });
        }
        if (!client.ws) {
            client.ws = this;
            this.addEventListener('close', e=>{
                delete client.ws;
                client.close();
            });
            this.own = true;
            client.setup(data);
        }
        if (this.own) {
            const d = [...new Uint8Array(data)];
            let move = false;
            let packet = d;
            if (
                (d[0]==8&&d[1]==7&&d[2]==18) // move
            ) {
                move = true;
                packet = d.slice(0, d.length-w7bit(this.id||0).length);
            }
            if (
                client.moveEnabled&&
                !(!client.chatEnabled&&d[0]==8&&d[1]==5&&d[2]==18) // chat
            ) {
                client.bots.forEach(b=>{
                    if (move && b.id == null) return;
                    if (b.readyState===3) return;
                    if (b.readyState!==1) return b.query.push(packet);
                    if (move) b.send(new Uint8Array([...packet, ...w7bit(b.id)]));
                    else b.send(new Uint8Array(packet));
                })
            }
        }
        //if (this.own) console.log('own', new Uint8Array(data));
        //else console.log('bot', new Uint8Array(data));
        this._send(data);
    }
})();
window.genMatrix = () => {
    const steps = 10;
    const fps = 1000/20;
    const time = performance.now()/100;
    const step = time/fps>>0;
    const light = num => {
        const gradient = "_O";
        const max = gradient.length-1;
        num = Math.min(100, Math.max(num, 0));
        const x = max*num/100>>0;
        return gradient[x];
    }
    const matrix = Array(10).fill(0).map((a,y)=>{
        //y = y + step%steps >> 0;
        return Array(10).fill(0).map((a,x)=>{
            //x = x + step%steps >> 0;
            const dxy = x^y;
            const drawIf = dxy>time%25 || x==0 || x == 9 || y == 0 || y == 9;
            const formula = drawIf*100;
            const color = light(formula);
            return color;
        }).join('');
    });
    return matrix;
};
const numpadMessages = {
    // Directional
    NumpadDivide: 'On your left!',
    NumpadMultiply: 'On your right!',
    NumpadAdd: 'gg',
    NumpadSubtract: 'stop trying to score on me it wont work',
    // Tactical
    Numpad0: 'Push!',
    Numpad1: 'Pass!',
    Numpad2: 'Get in goal!',
    Numpad3: "I've got the net.",
    Numpad4: "I've got it!",
    Numpad5: "Take it!",
    Numpad6: 'Cover me!',
    Numpad7: 'where going',
    Numpad8: 'Careful.',
    Numpad9: 'Be aggressive!'
};
const keyCooldown = 150;
const lastKeyUse = {};
document.addEventListener('keydown', e => {
    if (e.repeat) return;
    const now = Date.now();
    if (lastKeyUse[e.code] && now - lastKeyUse[e.code] < keyCooldown) return;
    lastKeyUse[e.code] = now;
    const msg = numpadMessages[e.code];
    if (msg) {
        client.sendMessage(msg);
    }
});
(function() {
    'use strict';

    let playername = "";
    let usernamearray = [];
    let loaded = false;

    // ─── WebSocket hook ────────────────────────────────────────────────────────
    const OriginalWebSocket = window.WebSocket;
    window.WebSocket = function(...args) {
        const ws = new OriginalWebSocket(...args);
        client.ws = ws;

        const originalSend = ws.send;
        ws.send = function(data) {
            if (data instanceof ArrayBuffer && !loaded) {
                loaded = true;
                const uint8 = new Uint8Array(data);
                const decoder = new TextDecoder();
                let start = 6;
                let end = start;
                while (end < uint8.length && uint8[end] >= 32 && uint8[end] <= 126) end++;
                const nameBytes = uint8.slice(start, end);
                usernamearray = Array.from(nameBytes);
                playername = decoder.decode(nameBytes).trim().replace(/[^\x20-\x7E]/g, '');
                console.log("[Chat Panel] Username detected:", playername);
            }
            originalSend.apply(this, arguments);
        };

        return ws;
    };

    // ─── Helpers ────────────────────────────────────────────────────────────────
    const id = el => document.getElementById(el);
    const crt = tag => document.createElement(tag);

    // ─── Chat functions ─────────────────────────────────────────────────────────
    const cheat = {
        unknownmessage: (prefix) => {
            const message = id('cheatinput')?.value?.trim();
            if (!message || !client.ws) return;
            const fullText = prefix + message;
            const encoder = new TextEncoder();
            const encoded = encoder.encode(fullText);
            const len = encoded.length;
            const header = [8, 5, 18, len + 5, 8, 223, 18, 18, len];
            const packet = new Uint8Array(header.length + len);
            packet.set(header);
            packet.set(encoded, header.length);
            client.ws.send(packet);
            if (id('cheatinput')) id('cheatinput').value = '';
        },

        clearchat: () => {
            if (!client.ws) return;
            const clear = [8, 5, 18, 9, 8, 223, 18, 18, 4, 32, 227, 133, 164];
            const arr = new Uint8Array(clear);
            for (let i = 0; i < 13; i++) client.ws.send(arr);
        }
    };

    // ─── Styles ─────────────────────────────────────────────────────────────────
    const styles = `
        #chatWindow {
            position: fixed; top: 20px; left: 1080px; transform: none);
            width: 440px; height: 260px; background: #1a1b16; border: 1px solid #646464;
            border-radius: 15px; box-shadow: 0 0 10px #000; z-index: 99999; color: white;
            font-family: Arial; display: none; overflow: hidden;
        }
        #titleBar {
            height: 36px; background: #161616; text-align: center; line-height: 36px;
            font-size: 18px; border-top-left-radius: 15px; border-top-right-radius: 15px;
            user-select: none; position: relative;
        }
        #closeBtn {
            position: absolute; right: 0; top: 0; width: 36px; height: 36px;
            background: #c00; color: white; font-size: 22px; cursor: pointer;
            border-top-right-radius: 15px;
        }
        #cpage2 {
            padding: 16px; height: calc(100% - 36px); box-sizing: border-box;
        }
        #cheatinput {
            width: 100%; max-width: 380px; padding: 10px; margin: 12px 0 16px 0;
            border-radius: 8px; background: #252525; border: none; color: white;
            font-size: 15px; display: block;
        }
        .button-row {
            display: flex; gap: 12px; flex-wrap: wrap; margin: 12px 0;
        }
        .cheatBtn {
            padding: 10px 24px; border: none; border-radius: 8px;
            color: white; cursor: pointer; font-size: 14px; flex: 1;
            min-width: 140px; text-align: center;
        }
        .cheatBtn:hover { opacity: 0.9; }
        #sendBtn { background: #0066cc; }
        #clearBtn { background: #555; }
        #chkDiv { margin: 12px 0; font-size: 14px; }
    `;

    const styleEl = crt('style');
    styleEl.textContent = styles;
    document.head.appendChild(styleEl);

    // ─── Build UI ───────────────────────────────────────────────────────────────
    const win = crt('div');
    win.id = 'chatWindow';
    document.body.appendChild(win);

    const title = crt('div');
    title.id = 'titleBar';
    title.textContent = 'Chat Panel';
    win.appendChild(title);

    const close = crt('div');
    close.id = 'closeBtn';
    close.textContent = 'X';
    close.onclick = () => win.style.display = 'none';
    title.appendChild(close);

    const page = crt('div');
    page.id = 'cpage2';
    win.appendChild(page);

    const input = crt('input');
    input.id = 'cheatinput';
    input.placeholder = 'Enter message...';
    page.appendChild(input);

    // Row with both buttons side by side
    const buttonRow = crt('div');
    buttonRow.className = 'button-row';
    page.appendChild(buttonRow);

    const send = crt('button');
    send.id = 'sendBtn';
    send.className = 'cheatBtn';
    send.textContent = 'Send Message';
    buttonRow.appendChild(send);

    const clearBtn = crt('button');
    clearBtn.id = 'clearBtn';
    clearBtn.className = 'cheatBtn';
    clearBtn.textContent = 'Clear Chat';
    buttonRow.appendChild(clearBtn);

    // ─── Team Command Row ─────────────────────────────────────────────
const teamRow = crt('div');
teamRow.className = 'button-row';
page.appendChild(teamRow);

const redBtn = crt('button');
redBtn.className = 'cheatBtn';
redBtn.style.background = '#b30000';
redBtn.textContent = 'Join Red';
teamRow.appendChild(redBtn);

const blueBtn = crt('button');
blueBtn.className = 'cheatBtn';
blueBtn.style.background = '#0033cc';
blueBtn.textContent = 'Join Blue';
teamRow.appendChild(blueBtn);

const specBtn = crt('button');
specBtn.className = 'cheatBtn';
specBtn.style.background = '#444';
specBtn.textContent = 'Spectate';
teamRow.appendChild(specBtn);

    const chkDiv = crt('div');
    chkDiv.id = 'chkDiv';
    page.appendChild(chkDiv);

    const chk = crt('input');
    chk.type = 'checkbox';
    chk.id = 'checkbox';
    chkDiv.appendChild(chk);

    const label = crt('label');
    label.htmlFor = 'checkbox';
    label.textContent = 'Send With Name';
    chkDiv.appendChild(label);

    // ─── Event listeners ────────────────────────────────────────────────────────
    send.onclick = () => {
        const prefix = chk.checked && playername ? playername + ": " : "";
        cheat.unknownmessage(prefix);
    };

    clearBtn.onclick = cheat.clearchat;
    redBtn.onclick = () => client.sendMessage('/team red');
    blueBtn.onclick = () => client.sendMessage('/team blue');
    specBtn.onclick = () => client.sendMessage('/team spectator');

    input.addEventListener('keydown', e => {
        if (e.key === 'Enter') {
            e.preventDefault();
            send.click();

        }
    });

    document.addEventListener('keydown', e => {
        if (e.key === '[' && !e.ctrlKey && !e.altKey && !e.metaKey && !e.shiftKey) {
            e.preventDefault();
            win.style.display = win.style.display === 'block' ? 'none' : 'block';
            if (win.style.display === 'block') input.focus();
        }
    });

    console.log("[Chat Panel] Ready – press [ to open");
})();