BumpyBall Unlimiter

Every server is Super Server!

目前為 2021-10-16 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         BumpyBall Unlimiter
// @name:ru      BumpyBall Unlimiter
// @namespace    https://greasyfork.org/users/670183
// @version      2
// @description  Every server is Super Server!
// @description:ru  Каждый сервер это Супер Сервер!
// @author       0vC4
// @match        http://www.pucks.io/
// @match        https://www.pucks.io/
// @match        http://www.bumpyball.io/
// @match        https://www.bumpyball.io/
// @icon         https://www.google.com/s2/favicons?domain=bumpyball.io
// @run-at       document-start
// @grant        none
// ==/UserScript==

//hello from O

//Worker Timer
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).WorkerTimer=e()}}(function(){return function o(i,s,l){function u(r,e){if(!s[r]){if(!i[r]){var t="function"==typeof require&&require;if(!e&&t)return t(r,!0);if(f)return f(r,!0);var n=new Error("Cannot find module '"+r+"'");throw n.code="MODULE_NOT_FOUND",n}var a=s[r]={exports:{}};i[r][0].call(a.exports,function(e){var t=i[r][1][e];return u(t||e)},a,a.exports,o,i,s,l)}return s[r].exports}for(var f="function"==typeof require&&require,e=0;e<l.length;e++)u(l[e]);return u}({1:[function(e,r,t){(function(e){"use strict";var t,n,a,o;e===e.window&&e.URL&&e.Blob&&e.Worker?r.exports=(t=["var timerIds = {}, _ = {};","_.setInterval = function(args) {","  timerIds[args.timerId] = setInterval(function() { postMessage(args.timerId); }, args.delay);","};","_.clearInterval = function(args) {","  clearInterval(timerIds[args.timerId]);","};","_.setTimeout = function(args) {","  timerIds[args.timerId] = setTimeout(function() { postMessage(args.timerId); }, args.delay);","};","_.clearTimeout = function(args) {","  clearTimeout(timerIds[args.timerId]);","};","onmessage = function(e) { _[e.data.type](e.data) };"].join(""),n=0,a={},(o=new e.Worker(e.URL.createObjectURL(new e.Blob([t],{type:"text/javascript"})))).onmessage=function(e){a[e.data]&&a[e.data].callback.apply(null,a[e.data].params)},{setInterval:function(e,t){var r=Array.prototype.slice.call(arguments,2);return n+=1,o.postMessage({type:"setInterval",timerId:n,delay:t}),a[n]={callback:e,params:r},n},setTimeout:function(e,t){var r=Array.prototype.slice.call(arguments,2);return n+=1,o.postMessage({type:"setTimeout",timerId:n,delay:t}),a[n]={callback:e,params:r},n},clearInterval:function(e){o.postMessage({type:"clearInterval",timerId:e}),a[e]=null},clearTimeout:function(e){o.postMessage({type:"clearTimeout",timerId:e}),a[e]=null}}):r.exports=e}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}]},{},[1])(1)});

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),

    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 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 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);
    }
})();

(function() {
    const proto=XMLHttpRequest.prototype;

    if(!proto._open)proto._open=proto.open;
    proto.open=function(){
        const[method,url]=arguments;
        Object.assign(this,{method,url});
        return this._open.apply(this,arguments);
    };

    if(!proto._send)proto._send=proto.send;
    proto.send=function(body){
        if(this.url.match(/Listing\?Game=BumpyBall/)) {
            this._lnd=this.onload;
            this.onload=function(e){
                const table = JSON.parse(new TextDecoder().decode(this.response));
                table.forEach(server=>server.MaxPlayers=999);

                Object.defineProperty(this, 'response', {
                  enumerable: true,
                  configurable: true,
                  writable: true,
                  value: new TextEncoder().encode(JSON.stringify(table)).buffer
                });
                this._lnd(e);
            };
        }
        if(this.url.match(/\/Ping/)) {
            this._lnd=this.onload;
            this.onload=function(e){
                const server = JSON.parse(new TextDecoder().decode(this.response));
                server.MaxPlayers=999;

                Object.defineProperty(this, 'response', {
                  enumerable: true,
                  configurable: true,
                  writable: true,
                  value: new TextEncoder().encode(JSON.stringify(server)).buffer
                });
                this._lnd(e);
            };
        }
        return this._send.apply(this,arguments)
    };
})();
// 0vC4#7152