bonk editor

Makes editor a bit better

当前为 2025-02-09 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         bonk editor
// @version      e1.1_t1.2
// @description  Makes editor a bit better
// @author       Apx
// @match        https://bonk.io/gameframe-release.html
// @match        https://bonkisback.io/gameframe-release.html
// @run-at       document-end
// @namespace    https://greasyfork.org/users/1272759
// @grant        none
// ==/UserScript==


const scriptName = "editer";

const guiSettings = {
    noWindow: true,
    settingsContent: null,
    bonkLIBVersion: "1.1.3",
    modVersion: "1.0_1.2",
}

window.bonkEditor = {
    rangeView: 100 * 1024,
    lineWidth: function (width) {
        console.log(arguments)
        return window.bonkEditor.arguments[1] == "editor"? width*2/arguments[1].transform.scale.x : width;
    },

}

function injector(src){
    let newSrc = src;
    let CSS = document.createElement('style');
    CSS.innerHTML = `
        #mapeditor_colorpicker_transparency_slider{
	        margin-left: 0px;
	        background-color: transparent;
	        margin-top: -2px;
        }
        #mapeditor_colorpicker_alphalabel{
            color:#ffffff;
        }
    `;
    document.getElementsByTagName('head')[0].appendChild(CSS);

    let label = document.createElement('span');
    document.getElementById('mapeditor_colorpicker').insertBefore(label, document.getElementById("mapeditor_colorpicker_existingcontainer"));
    label.outerHTML = `<span id="mapeditor_colorpicker_alphalabel">Alpha (0)</span>`;
    let slider = document.createElement('input');
    document.getElementById('mapeditor_colorpicker').insertBefore(slider, document.getElementById("mapeditor_colorpicker_existingcontainer"));
    slider.outerHTML = `<input type="range" class="compactSlider compactSlider_classic" min="0" max="1" value="0.5" step="0.01" id="mapeditor_colorpicker_transparency_slider">`;

    function patch (src, newsrc) {
        newSrc = newSrc.replace(src, newsrc);
    };
    function log(regex){
        console.log(typeof(regex) == "string"?regex:(Array.isArray(regex)?regex:newSrc.match(regex)));
    };

    // bonk alpha (only v49 support)
    let r1 = newSrc.match(/E80\[5]\[E80\[9]\[116]] <= 0xffffff/);
    let r2 = newSrc.match(/this\[m\$J\[1571]]\[m\$J\[430]]\(I80\[m\$J\[116]]\);/);
    let r3 = newSrc.match(/x6Z\[840]\[x6Z\[8]\[430]]\(x6Z\[519]\[x6Z\[8]\[116]]\);/); // editor
    let r4 = newSrc.match(/T_U\[8]\[T_U\[6]\[1017]]/g);
    let r5 = newSrc.match(/\(1,T_U\[89]\)\(a2T\(T_U\[14],T_U\[77],T_U\[47]\)\);/);
    let r6 = newSrc.match(/function\(x6s\){var H\$J=\[arguments];H\$J\[1]=M\$QCc;R3M\[9]\[H\$J\[1]\[116]]=H\$J\[0]\[0];N_A\(true\);k7V\.t8H\(\);R3M\[31]\[H\$J\[1]\[461]]\[H\$J\[1]\[1025]]=t\$e\[61]\[H\$J\[1]\[1029]]\(H\$J\[0]\[0]\);}/);
    let r7 = newSrc.match(/var J22=\[arguments];/);
    let r8 = newSrc.match(/\(1,T_U\[89]\)\(T_U\[71]\);/);
    // editor
    const widthRoundingRegex = newSrc.match(/[a-zA-Z0-9\$_]{3}\[[0-9]{1,3}]]\[[a-zA-Z0-9\$_]{3}\[[0-9]{1,3}]\[[0-9]{1,3}]]=Math\[[a-zA-Z0-9\$_]{3}\[[0-9]{1,3}]\[[0-9]{1,3}]]\([a-zA-Z0-9\$_]{3}\[[0-9]{2,3}]\);[a-zA-Z0-9\$_]{3}\(true\)/)[0];
    const rectPosRegex = newSrc.match(/[a-zA-Z0-9\$_]{3}\[[0-9]{1,3}]\[[a-zA-Z0-9\$_]{3}\[[0-9]{1,3}]\[[0-9]{1,3}]]\[[0-1]]=Math\[[a-zA-Z0-9\$_]{3}\[[0-9]{1,3}]\[[0-9]{1,3}]]\([a-zA-Z0-9\$_\[\]]+\);/g).map((x) => {return x.split("=")});
    const platZindex = newSrc.match(/function [a-zA-Z0-9\$_]{3}\(\){[a-zA-Z0-9-+=_ \$;\(\)[\]{}\.,!]*?}}[a-zA-Z0-9\$_]{3}\(\);[a-zA-Z0-9\$_]{3}\(true\);}/g)[0];
    const arrayBufferRegex = newSrc.match(/(?<=new ArrayBuffer\()k7V\.Q5\$\(100,1024\)/)[0];
    const spawnId = newSrc.match(/[a-zA-Z0-9\$_]{3}\[[0-9]{1,3}](?=--;}else {(?!if))/)[0];

    patch(r5, `(1,T_U[89])(a2T(T_U[14],T_U[77],T_U[47]),document.getElementById("mapeditor_colorpicker_transparency_slider").value);`);
    patch(r6, `function(x6s,alph){var H$J=[arguments];H$J[1]=M$QCc;R3M[9][H$J[1][116]]=H$J[0][0]+(alph==1?0:(Math.round((alph*100+1))*0x1000000));let textValue = alph;if(alph==1){textValue = "Opaque";}else if(alph==0){textValue = "Invisible";}document.getElementById("mapeditor_colorpicker_alphalabel").textContent = \`Transparency (\${textValue})\`;N_A(true);k7V.t8H();R3M[31][H$J[1][461]][H$J[1][1025]]=t$e[61][H$J[1][1029]](H$J[0][0]);}`);
    patch(r7, r7+`document.getElementById("mapeditor_colorpicker_transparency_slider").value = ((J22[0][0] >> 24 & 255)-1)/100<0?1:((J22[0][0] >> 24 & 255)-1)/100;`);
    patch(r8, `(1,T_U[89])(T_U[71],document.getElementById("mapeditor_colorpicker_transparency_slider").value);`);
    patch(r4, `document.getElementById("mapeditor_colorpicker_transparency_slider").onchange = function () {h1N(false)};document.getElementById("mapeditor_colorpicker_transparency_slider").oninput = function () {h1N(false)};`+r4);
    patch(r1, r1+`ff`);
    patch(r2, `let alpha = ((I80[m$J[116]] >> 24 & 255)-1)/100;this[m$J[1571]][m$J[430]](parseInt(t$e[61].numToHex(I80[m$J[116]]).substring(1),16),(alpha<0?1:Math.min(alpha,1)));`);
    patch(r3, `let alpha = ((x6Z[519][x6Z[8][116]] >> 24 & 255)-1)/100;x6Z[840][x6Z[8][430]](parseInt(t$e[61].numToHex(x6Z[519][x6Z[8][116]]).substring(1),16),(alpha<0?1:Math.min(alpha,1)));`);

    // move up / down spawns
    const vars = platZindex.match(/(?<![\.a-zA-Z])(?:[a-zA-Z0-9\$_]{3})(?=[\[=]{1})(?:\[[0-9]{1,3}])?/g);
    const modifiedPlatZindex = platZindex
    .replace(/}}(?!else)/, `
                }
            }
        }
        else{
            if(this==${vars[10]}){
                if(${vars[4]}.spawns[${spawnId}-1]!=undefined){
                    ${vars[15]}=${vars[4]}.spawns[${spawnId}-1];
                    ${vars[4]}.spawns[${spawnId}-1]=${vars[0]}[100];
                    ${vars[4]}.spawns[${spawnId}]=${vars[15]};
                    ${spawnId}--;
                }
            }
            else if(this==${vars[33]}){
                if(${vars[4]}.spawns[${spawnId}+1]!=undefined){
                    ${vars[38]}=${vars[4]}.spawns[${spawnId}+1];
                    ${vars[4]}.spawns[${spawnId}+1]=${vars[0]}[100];
                    ${vars[4]}.spawns[${spawnId}]=${vars[38]};
                    ${spawnId}++;
                }
            }
        }`)
    .replace(/if\(.*?\){.*?}/, "")
    .replace(/;if\(.*?\){.*?}/, `;${vars[0]}[100]=${vars[4]}.spawns[${spawnId}];if(${vars[3]} == -1 && ${vars[4]}.spawns.indexOf(${vars[0]}[100]) == -1){return;}if(${vars[3]}!=-1){`);
    patch(platZindex,modifiedPlatZindex);

    // disable width rounding to integers
    patch(widthRoundingRegex.split(";")[0] + ";", `${widthRoundingRegex.split("=")[0]}=${widthRoundingRegex.split("=")[1].split(";")[0].match(/.{7}(?=\))/)};`);

    // disable rectangle position rounding to integers
    for(let i = 0; i < 4; i++) patch(rectPosRegex[i].join("="), `${rectPosRegex[i][0]}=${rectPosRegex[i][1].match(/.{6}(?=\))/)};`);

    // replace the minimum number of width, height and radius with MIN_VALUE (values lower than 1e-100 are not recommended)
    const precission = newSrc.match(/function [a-zA-Z0-9\$_]{3}\([a-zA-Z0-9\$_]{3}\){[a-zA-Z0-9\$_\[\]= ]+;[a-zA-Z0-9\$_\[\]=]+;[a-zA-Z0-9\$_\[\]=]+\*=10000;[a-zA-Z0-9\$_\[\]=]+\([a-zA-Z0-9\$_\[\]=]+\);[a-zA-Z0-9\$_\[\]=]+\/=10000;return [a-zA-Z0-9\$_\[\]=]+;}/)[0];
    patch(`min:1,`, `min:0.0001,`);
    patch(precission ,`function ${precission.split(" ")[1].substring(0,3)}(arg_){return arg_;}`);

    // make range view changeable
    patch(arrayBufferRegex ,`window.bonkEditor.rangeView`);


    // anti-crash type 1
    const anticrash1 = newSrc.match(/(?<=null)\){var [a-zA-Z0-9\$_]{3}=[a-zA-Z0-9\$_]{3}\..*?;/g);
    for(let i = 1; i < anticrash1.length; i++) {
        patch(anticrash1[i], `&&this.shapes[${anticrash1[i].split("=")[1].replace(";","")}]!=undefined${anticrash1[i]}`);
    }
    // anti-crash type 2
    const anticrash2 = newSrc.match(/(?<=0xccbbaa;)if\(this...../g);
    patch(anticrash2,`if(this.capFill==null){return;ау}${anticrash2}`);

    // menu
    const menuRegex = newSrc.match(/== 13\){...\(\);}}/)[0];
    patch(menuRegex, menuRegex + "window.bonkEditor.menu = this;");

    // anti lobby kick
    const ws = window.WebSocket.prototype.send;
    window.WebSocket.prototype.send = function(args){
        if(this.url.includes("socket.io/?EIO=3&transport=websocket&sid=") && typeof(args) == "string" && args.length > 250000){
            window.bonkEditor.menu.showStatusMessage("* Protected from being kicked out of the room.","#b53030",false);
            return;
        }
        ws.call(this,args);
    }

    if(src === newSrc) throw "Injection failed!";
    console.log(`${scriptName} injector run`);
    return newSrc;
}

if(!window.bonkCodeInjectors) window.bonkCodeInjectors = [];
window.bonkCodeInjectors.push(bonkCode => {
    try {
        return injector(bonkCode);
    } catch (error) {
        alert(`Whoops! ${scriptName} was unable to load.`);
        throw error;
    }
});

if (window.bonkHUD) {
    const label = (target, text, ...elements) => {
        let div = document.createElement("div");
        let labelElement = document.createElement("label");
        labelElement.classList.add("bonkhud-settings-label");
        labelElement.textContent = text;
        labelElement.style.marginRight = "5px";
        labelElement.style.display = "inline-block";
        labelElement.style.verticalAlign = "middle";
        target.appendChild(div);
        div.appendChild(labelElement);
        for(let element in elements) div.appendChild(elements[element])
    }
    const option = (target, text, value) => {
        let option = document.createElement("option");
        option.value = value;
        option.textContent = text;
        target.appendChild(option)
    }
    let settings = window.bonkHUD.generateSection();
	guiSettings.settingsContent = settings;
    const ind = window.bonkHUD.createMod("bonk editor & transparency", guiSettings);

	let rangeView = document.createElement("input");
    rangeView.style.width = "40px";
    rangeView.style.height = "19px";
    rangeView.value = "100";
    rangeView.oninput = (event) => {
        event.target.value = event.target.value.replaceAll(/[^0-9]+/g, '');
        event.target.value = String(Math.min(Math.max(parseInt(event.target.value) || 0, 0), 1024));

        if(event.target.parentNode.lastChild.nodeName == "SPAN") return;
        let span = document.createElement("span");
        span.textContent = "* not applied";
        span.style["margin-left"] = "5px";
        span.style.color = "#000000aa";
        event.target.parentNode.appendChild(span);
    }

    let unit = document.createElement("select");
    option(unit, "KB", "1");
    option(unit, "MB", "2");
    unit.onchange = (event) => {
        if(event.target.parentNode.lastChild.nodeName == "SPAN") return;
        let span = document.createElement("span");
        span.textContent = "* not applied";
        span.style["margin-left"] = "5px";
        span.style.color = "#000000aa";
        event.target.parentNode.appendChild(span);
    };

    let applyButton = window.bonkHUD.generateButton("Apply");
    applyButton.style.display = "inline-block";
    applyButton.style.padding = "0 5px";
    applyButton.onclick = () => {
        window.bonkEditor.rangeView = parseInt(rangeView.value) * (1024 ** parseInt(unit.value));
        if(unit.parentNode.lastChild.nodeName == "SPAN") unit.parentNode.removeChild(unit.parentNode.lastChild);
    }

    label(settings, "Array buffer range view", rangeView, unit, applyButton);
    settings.appendChild(applyButton);

	
	window.bonkHUD.updateStyleSettings();
}