Bonk Host

Makes hosting rooms in bonk.io better

目前为 2022-06-21 提交的版本。查看 最新版本

// ==UserScript==
// @name         Bonk Host
// @version      1.12
// @author       Salama
// @description  Makes hosting rooms in bonk.io better
// @match        https://bonk.io/gameframe-release.html
// @run-at       document-start
// @grant        none
// @supportURL   https://discord.gg/Dj6usq7ww3
// @namespace    https://gf.qytechs.cn/users/824888
// ==/UserScript==

// for use as a userscript ensure you have Excigma's code injector userscript
// https://gf.qytechs.cn/en/scripts/433861-code-injector-bonk-io

let injector = (str) => {
	let newStr = str;
window.bonkHost = {};
window.bonkHost.playerManagement = {};
window.bonkHost.freejoin = false;
window.bonkHost.playerCount = 0;
window.bonkHost.playerNames = [];
window.bonkHost.scores = [];
window.bonkHost.startGameFunction = () => {return;};

window.bonkCommands = window.bonkCommands.concat(["/kick", "/mute", "/unmute", "/lock", "/unlock", "/balance", "/fav", "/unfav", "/curate", "/curateyes", "/curateno", "/hhelp", "/balanceall", "/start", "/freejoin"]);

let hostPlayerMenuCSS = document.createElement('style');
hostPlayerMenuCSS.innerHTML = `
#hostPlayerMenu {
	background-color: #cfd8cd;
	width: calc(35.2vw - 400px);
	min-width: 154px;
	max-width: 260px;
	height: 551px;
	position: absolute;
	left: 1%;
	top: 60px;
	border-radius: 7px;
	display: none;
    transition: ease-in-out 100ms;
}

#hostPlayerMenuCollapse {
    position: absolute;
    left: 3px;
    top: 3px;
    width: 26px;
    height: 26px;
    border-radius: 2px;
    text-transform: full-width;
    visibility: visible;
}

#hostPlayerMenuControls {
    position:absolute;
    bottom:0;
    width:100%;
}`;
document.getElementsByTagName('head')[0].appendChild(hostPlayerMenuCSS);

let hostPlayerMenu = document.createElement('div');
document.getElementById('pagecontainer').appendChild(hostPlayerMenu);
hostPlayerMenu.outerHTML = `
<div class="windowShadow" id="hostPlayerMenu">
	<div class="newbonklobby_boxtop newbonklobby_boxtop_classic" style="background-color: #009688;">
		<div onclick="window.bonkHost.playerManagement.collapse();" id="hostPlayerMenuCollapse" class="newbonklobby_settings_button brownButton brownButton_classic buttonShadow">-</div>
		Player List</div>
	<div id="hostPlayerMenuBox" class="newbonklobby_elementcontainer"></div>
	<div id="hostPlayerMenuControls">
		<table>
			<tbody>
				<tr style="background-color: rgba(58, 58, 58, 0.07);">
					<td style="padding-left: 10px;" class="mapeditor_rightbox_table">
						Teamlock
					</td>
					<td>
						<input type="checkbox" id="hostPlayerMenuTeamlock">
					</td>
				</tr>
				<tr style="background-color: rgba(58, 58, 58, 0.07);">
					<td style="padding-left: 10px;" class="mapeditor_rightbox_table">
						Freejoin
					</td>
					<td>
						<input type="checkbox" id="hostPlayerMenuFreejoin">
					</td>
				</tr>
				<tr style="background-color: rgba(58, 58, 58, 0.07);">
					<td style="padding-left: 10px;" class="mapeditor_rightbox_table">
						Keep scores
					</td>
					<td>
						<input type="checkbox" id="hostPlayerMenuKeepScores">
					</td>
				</tr>
				<tr style="background-color: rgba(58, 58, 58, 0.07);">
					<td style="padding-left: 10px;" class="mapeditor_rightbox_table">
						Keep positions
					</td>
					<td>
						<input type="checkbox" id="hostPlayerMenuKeepPositions">
					</td>
				</tr>
			</tbody>
		</table>
		<div class="newbonklobby_settings_button brownButton brownButton_classic buttonShadow" style="width:100%;" id="hostPlayerMenuRestartButton">
			RESTART GAME
		</div>
	</div>
</div>
<div id="selectionWheel" style="width: 150px; height: 150px; position: absolute; left: 1061px; top: 169px; pointer-events: none; display: none;">
	<svg width="150" height="150" viewBox="0 0 26.458 26.458"><g><path d="M22.009-13.227a8.78 8.78 0 0 1-13.17 7.605 8.78 8.78 0 0 1-4.39-7.605" transform="rotate(90)" stroke="#fff" style="stroke-linejoin: round; stroke-width: 9; fill: none; opacity: 0.5; stroke: rgb(121, 85, 72);"></path><text class="brownButton_classic" style="
		text-anchor: middle;
		font-family: 'futurept_b1';
		font-size: 3.17496;
		transform: scale(1, 1);
		fill: #fff;
	"><tspan x="4.5" y="14.4">FFA</tspan></text>
	</g><g style="transform: translateX(50%);transform-origin: 100% 0px;"><path d="M22.009-13.227a8.78 8.78 0 0 1-13.17 7.605 8.78 8.78 0 0 1-4.39-7.605" transform="rotate(90)" stroke="#fff" style="stroke-linejoin: round; stroke-width: 9; fill: none; opacity: 0.5; transform: rotate(-90deg); transform-origin: 75% 25%; stroke: rgb(121, 85, 72);"></path><text style="
		text-anchor: middle;
		font-family: 'futurept_b1';
		font-size: 3.17496;
		transform: scale(1, 1);
		fill: #fff;
	"><tspan x="8.8" y="14.4">SPEC</tspan></text></g></svg>
</div>

<div id="selectionWheelTeams" style="width: 150px; height: 150px; position: absolute; left: 588px; top: 181px; pointer-events: none; display: none;">
	<svg width="150" height="150" viewBox="0 0 26.458 26.458" style="
"><g stroke-linejoin="round" stroke-width="9" stroke="#fff" style="transform: rotate(180deg);transform-origin: 50% 0%;"><path d="M6.126-8.066c-2.236-3.078-2.236-7.246 0-10.323" style="opacity: 0.5; stroke: rgb(121, 85, 72);"></path><path d="M6.126-18.39a8.78 8.78 0 0 1 9.816-3.19" style="stroke: rgb(255, 235, 59); opacity: 1;"></path><path d="M15.942-21.58a8.78 8.78 0 0 1 6.067 8.352" style="stroke: rgb(76, 175, 80); opacity: 0.5;"></path><path d="M22.009-13.228a8.78 8.78 0 0 1-6.067 8.352" style="stroke: rgb(33, 150, 243); opacity: 0.5;"></path><path d="M15.942-4.876a8.78 8.78 0 0 1-9.816-3.19" style="stroke: rgb(244, 67, 54); opacity: 0.5;"></path></g><text font-size="6" fill="#000" style="
		text-anchor: middle;
		font-family: 'futurept_b1';
		font-size: 3.17496;
		fill: #fff;
	"><tspan x="22" y="14.4">SPEC</tspan></text><text font-size="6" fill="#000" style="
		text-anchor: middle;
		font-family: 'futurept_b1';
		font-size: 3.17496;
		fill: #fff;
	"><tspan x="16.75" y="22.5">YELLOW</tspan></text><text font-size="6" fill="#000" style="
		text-anchor: middle;
		font-family: 'futurept_b1';
		font-size: 3.17496;
		fill: #fff;
	"><tspan x="16.5" y="6">RED</tspan></text><text font-size="6" fill="#000" style="
		text-anchor: middle;
		font-family: 'futurept_b1';
		font-size: 3.17496;
		fill: #fff;
	"><tspan x="6" y="9.5">BLUE</tspan></text><text font-size="6" fill="#000" style="
		text-anchor: middle;
		font-family: 'futurept_b1';
		font-size: 3.17496;
		fill: #fff;
	"><tspan x="6" y="19.5">GREEN</tspan></text></svg>
</div>`;

let CUSTOM_COMMANDS = `
if(I8H[5][0] == "/hhelp") {
	u6H[29].showStatusMessage("/balance * -100 to 100 -- Balances everyone","#cc3333",false);
	u6H[29].showStatusMessage("/balanceall -100 to 100 -- Balances everyone","#cc3333",false);
	u6H[29].showStatusMessage("/start -- Starts the game","#cc3333",false);
	u6H[29].showStatusMessage("/freejoin on/off -- Lets people join during the game","#cc3333",false);
}
else if(I8H[5][0] == "/start" && !u6H[64]) {
    window.bonkHost.startGame();
}
else if(I8H[5][0] == "/freejoin" && !u6H[64]) {
    if(["true", "on", "yes", "enable"].includes(I8H[5][1])) {
        window.bonkHost.freejoin = true;
	    F5S("* Freejoin on","#cc3333",true);
    }
    else if(["false", "off", "no", "disable"].includes(I8H[5][1])) {
        window.bonkHost.freejoin = false;
	    F5S("* Freejoin off","#cc3333",true);
    }
    else if(I8H[5].length == 1) {
        window.bonkHost.freejoin = !window.bonkHost.freejoin;
	    F5S("* Freejoin " + (window.bonkHost.freejoin ? "on" : "off"),"#cc3333",true);
    }
    document.getElementById('hostPlayerMenuFreejoin').checked = window.bonkHost.freejoin;
}
`;

let BALANCE_ALL_MESSAGE = `
if(I8H[67] == -2) {
	u6H[29].showStatusMessage("* " + "Everyone" + " has had their buff/nerf set to " + I8H[32], "#cc3333", false);
}
else if(I8H[32] == 0)
`;

let BALANCE_SELECTION = `

u6H[36].bal[I8H[17]] = I8H[32];
u6H[11].sendBalance(I8H[17], I8H[32]);
if (u6H[29]) {
	u6H[29].updatePlayers();
}
I8H[67]=-2;
if (u6H[44][I8H[17]].userName.toLowerCase() == I8H[7].toLowerCase()) {
    I8H[67] = I8H[17];
    break;
}
`;

let SUGGESTION_MODE_BUTTON = `
let space = document.createElement("span");
space.classList.add("newbonklobby_mapsuggest_high");
space.appendChild(document.createTextNode(" "));

let smb = document.createElement("span");
smb.classList.add("newbonklobby_mapsuggest_high");
smb.classList.add("newbonklobby_chat_link");
smb.style.color="#ff0000";
v2k[79].setButtonSounds([smb]);

smb.onclick = () => {
	d9G[73].onclick();
	window.bonkSetMode(w3G[2][d9G[73].suggestID].m.mo);
};
`;

let APPEND_SUGGESTION_MODE_BUTTON = `
if(!!v2k[10].modes[w3G[2][d9G[73].suggestID].m.mo]) {
	d9G[8].appendChild(space);
	smb.appendChild(document.createTextNode("[" + v2k[10].modes[w3G[2][d9G[73].suggestID].m.mo].lobbyName + "]"));
	d9G[8].appendChild(smb);
}
`;

let modeStuff = newStr.match(
    new RegExp(
        "(var .{2,4}=\\[arguments\\];.{2,4}\\[\\d{1,2}\\]=.{2,5};).{1,300}\
\\+\\+;\
if.{5,60}=0;\\}\
(.{5,50}=.{5,50})\
\\[.{2,4}\\[\\d{1,4}\\]\\];\
(.{5,200}=true.{5,200}\\(\\);)\
\\}\\}"
    )
);
// 1 is var m7p = [arguments]; m7p[4] = y3uu;
// 2 is G7p[0][2]["mo"] = P1R[43]["lobbyModes"]
// 3 is code that updates the mode
let modeVar =
    modeStuff[2].split("=")[0].match(/.{2,4}\[\d{1,2}\]\[\d{1,2}\]/g)[0] +
    `["mo"]`;
let modesObject =
    modeStuff[2].split("=")[1].match(/.{2,4}\[\d{2,4}\]/g)[0] + `["modes"]`;

window.modeDropdownCreated = false;
window.createModeDropdown = () => {
    if (window.modeDropdownCreated) return;
    window.modeDropdownCreated = true;
    const dropdown = document.createElement("div");
    dropdown.classList = "dropdown-container";
    const mds = dropdown.style;
    mds.color = "#ffffff";
    mds.position = "absolute";
    mds.right = "15px";
    mds.bottom = "55px";
    mds.width = "116px";
    mds.height = "30px";
    mds.display = "flex";
    mds.textAlign = "center";
    mds.flexDirection = "column-reverse";

    document.getElementById("newbonklobby_modebutton").remove();
    let title = document.createElement("div");
    title.classList = "dropdown-title dropdown_classic";
    title.innerText = "MODE";
    title.style.fontSize = "18px";
    title.id = "newbonklobby_modebutton";
    title.style.position = "unset";
    dropdown.appendChild(title);

    const options = [];
    let dropdownOpen = false;

    function toggleVisibility(e) {
        dropdownOpen = !dropdownOpen;
        for (const o of options) {
            o.style.visibility = dropdownOpen ? "" : "hidden";
        }
        e.stopImmediatePropagation();
    }

    for (const mode of Object.keys(window.bonkModesObject)) {
        const option = document.createElement("div");
        option.classList = "dropdown-option dropdown_classic";
        option.style.display = "block";
        option.style.visibility = "hidden";
        option.style.fontSize = "15px";
        option.innerText = window.bonkModesObject[mode].lobbyName;
        option.onclick = (e) => {
            window.bonkSetMode(mode);
            toggleVisibility(e);
        };
        options.push(option);
        dropdown.appendChild(option);
    }

    title.addEventListener("click", toggleVisibility);

    document.getElementById("newbonklobby_settingsbox").appendChild(dropdown);
};

let PLAYER_CLICK_MENU = `
if(playerEntry) {
    playerEntry.parentNode.appendChild(m9G[6]);
}
else` + " ";

let KEEP_SCORES = `
if(window.bonkHost.scores.length > 0 && document.getElementById('hostPlayerMenuKeepScores').checked) {
    k7k[1].scores = window.bonkHost.scores;
}
else` + " ";

let SET_STATE = `
document.getElementById("hostPlayerMenuKeepPositions").parentNode.parentNode.style.display = (u6H[36].map.s.re ? "" : "none");
if(I8yy.bonkHost.state && window.bonkHost.keepState && u6H[36].map.s.re) {
    for(let i = 0; i < I8yy.bonkHost.state.discs.length; i++) {
        if(I8yy.bonkHost.state.discs[i] != undefined) {
            W6H[2].discs[i] = I8yy.bonkHost.state.discs[i];
            if(u6H[36].mo=='sp') {
                W6H[2].discs[i].a1a -= 2*30*3;
            }
        }
    }
    for(let i = 0; i < I8yy.bonkHost.state.discDeaths.length; i++) {
        if(I8yy.bonkHost.state.discDeaths[i] != undefined) {
            W6H[2].discDeaths[i] = I8yy.bonkHost.state.discDeaths[i];
        }
    }
    W6H[2].physics=I8yy.bonkHost.state.physics;
    W6H[2].seed=I8yy.bonkHost.state.seed;
    W6H[2].rc=I8yy.bonkHost.state.rc;
    W6H[2].ftu=60;
    W6H[2].shk=I8yy.bonkHost.state.shk;
    W6H[2].projectiles=I8yy.bonkHost.state.projectiles;
    W6H[2].capZones=I8yy.bonkHost.state.capZones;
    window.bonkHost.keepState=false;
}W6H[2][
`;

let FREEJOIN = `
if(window.bonkHost.freejoin||u6H[64]) {
    let team = u6H[44].filter(e => {return e != null && u6H[44].indexOf(e) !== s6H[0][0] && e.team != 0}).map(e => {return e.team}).reduce((a, b) => {return a == b ? a : false});
    team = team ? team : 0;
    u6H[44][s6H[0][0]].team = team;
    s6H[0][4] = team;
`;

document.getElementById('hostPlayerMenuFreejoin').addEventListener('change', (e) => {
    window.bonkHost.freejoin = e.target.checked;
});

document.getElementById('hostPlayerMenuTeamlock').addEventListener('change', () => {
    document.getElementById('newbonklobby_teamlockbutton').onclick();
});

window.bonkHost.playerManagement.addPlayer = (playerEntry, info) => {
    while(window.bonkHost.playerManagement.getPlayer(playerEntry)) {
        window.bonkHost.playerManagement.removePlayer(playerEntry);
    }
    let newPlayerEntry = playerEntry.cloneNode(true);
    newPlayerEntry.classList.remove('newbonklobby_playerentry_half');
    newPlayerEntry.getElementsByClassName("newbonklobby_playerentry_ping")[0].remove();
    newPlayerEntry.getElementsByClassName("newbonklobby_playerentry_host")[0].remove();
    newPlayerEntry.onclick = playerEntry.onclick;
    newPlayerEntry.onmouseenter = playerEntry.onmouseenter;
    if(
        info.team === 0 ||
        (document.getElementById("newbonklobby_teams_middletext").textContent === "TEAMS ON" && info.team === 1) ||
        (document.getElementById("newbonklobby_teams_middletext").textContent === "TEAMS OFF" && info.team > 1) ||
        (
            !window.bonkHost.freejoin &&
            !window.bonkHost.menuFunctions.visible &&
            I8yy.bonkHost.state.discs[window.bonkHost.players.findIndex(i => {return i && i.userName === newPlayerEntry.children[1].textContent})] == undefined &&
            I8yy.bonkHost.state.discDeaths.findIndex(i => {return i.i === window.bonkHost.players.findIndex(i => {return i && i.userName === newPlayerEntry.children[1].textContent})})
        )
    ) {
        newPlayerEntry.style.filter = "opacity(0.4)";
    }
    hostPlayerMenuBox.appendChild(newPlayerEntry);
    if(!window.bonkHost.playerNames.includes(newPlayerEntry.children[1].textContent)) {
        window.bonkHost.playerNames.push(newPlayerEntry.children[1].textContent);
    }
}

window.bonkHost.redrawSkin = (skinElement) => {
    if(!skinElement.parentNode.classList.contains("newbonklobby_playerentry")) return;
    let playerElement = [...document.getElementById("hostPlayerMenuBox").children].filter(e => {return e.children[1] && e.children[1].textContent === skinElement.parentNode.getElementsByClassName("newbonklobby_playerentry_name")[0].textContent})[0];
    if(!playerElement) return;
    playerElement.removeChild(playerElement.getElementsByClassName("newbonklobby_playerentry_avatar")[0]);
    playerElement.insertBefore(skinElement.cloneNode(true), playerElement.getElementsByClassName("newbonklobby_playerentry_name")[0]);
}

window.bonkHost.playerManagement.removePlayer = (playerEntry) => {
    if((foundPlayerEntry = window.bonkHost.playerManagement.getPlayer(playerEntry)) && foundPlayerEntry) {
        hostPlayerMenuBox.removeChild(foundPlayerEntry);
        if(window.bonkHost.playerNames.includes(foundPlayerEntry.children[1].textContent)) {
            window.bonkHost.playerNames.splice(window.bonkHost.playerNames.indexOf(foundPlayerEntry.children[1].textContent), 1);
        }
    }
}

window.bonkHost.playerManagement.show = () => {
    if(window.bonkHost.menuFunctions.visible) return;
    if(parent.document.getElementById('adboxverticalleftCurse') != null)
        parent.document.getElementById('adboxverticalleftCurse').style.display = "none";
    document.getElementById('hostPlayerMenu').style.display = "unset";
}

window.bonkHost.playerManagement.hide = () => {
    document.getElementById('hostPlayerMenu').style.display = "none";
    if(parent.document.getElementById('adboxverticalleftCurse') != null)
        parent.document.getElementById('adboxverticalleftCurse').style.removeProperty("display");
}

window.bonkHost.playerManagement.collapse = () => {
    if(document.getElementById('hostPlayerMenu').style.visibility != "hidden") {
        document.getElementById('hostPlayerMenuControls').style.display = "none";
        document.getElementById('hostPlayerMenuControls').visibility = "hidden";
        document.getElementById('hostPlayerMenu').style.minWidth = 0;
        document.getElementById('hostPlayerMenu').style.minHeight = 0;
        document.getElementById('hostPlayerMenu').style.width = 0;
        document.getElementById('hostPlayerMenu').style.height = 0;
        document.getElementById('hostPlayerMenu').style.visibility = "hidden";
        document.getElementById('hostPlayerMenuCollapse').textContent = "+";
    }
    else {
        document.getElementById('hostPlayerMenu').style.visibility = "visible";
        document.getElementById('hostPlayerMenu').style.removeProperty("min-width");
        document.getElementById('hostPlayerMenu').style.removeProperty("min-height");
        document.getElementById('hostPlayerMenu').style.removeProperty("width");
        document.getElementById('hostPlayerMenu').style.removeProperty("height");
        document.getElementById('hostPlayerMenu').style.visibility = "visible";
        document.getElementById('hostPlayerMenuCollapse').textContent = "-";
        setTimeout(() => {document.getElementById('hostPlayerMenuControls').style.removeProperty("display");}, 100);
    }
}

window.bonkHost.playerManagement.getPlayer = (playerEntry, exact = false) => {
    if (exact) {
        let child = [...hostPlayerMenuBox.children].indexOf(playerEntry);
        if(child) return hostPlayerMenuBox.children[child];
    }
    for(let child of hostPlayerMenuBox.children) {
        if(child.children[1].textContent == playerEntry.children[1].textContent) {
            return child;
        }
    }
    return false;
}

window.bonkHost.playerManagement.movePlayer = (playerID, playerCount, team) => {
    window.bonkHost.menuFunctions.visible = true;
    if(team > 0)
        window.bonkHost.bonkHandlers.hostHandlePlayerJoined(playerID, playerCount, team);
    else
        window.bonkHost.bonkHandlers.hostHandlePlayerLeft(playerID);
    window.bonkHost.menuFunctions.updatePlayers();
}

window.bonkHost.startGame = () => {
    window.bonkHost.keepState = document.getElementById("hostPlayerMenuKeepPositions").checked;
    window.bonkHost.startGameFunction();
}

document.getElementById('maploadwindowmapscontainer').addEventListener('DOMNodeInserted', e => {
    let mode = e.relatedNode.getElementsByClassName('maploadwindowtextmode')[0];
    if(mode === undefined) mode = e.relatedNode.getElementsByClassName('maploadwindowtextmode_picks')[0];
    if(mode.textContent !== "Any Mode") {
        mode.classList.add('brownButton');
        mode.classList.add('brownButton_classic');
        mode.classList.add('buttonShadow');
        mode.style.padding = "2px";
        mode.style.width = "90px";
    }
    mode.addEventListener("click", e => {
        if(!document.getElementById('newbonklobby_modebutton').classList.contains("brownButtonDisabled")) {
            window.bonkSetMode(Object.entries(window.bonkModesObject).filter(e => {return e[1].lobbyName === mode.textContent})[0][0]);
        }
    })
});

/*Autocomplete*/

document.getElementById('newbonklobby_chat_input').onkeydown = e => {
	if (e.keyCode === 9) {
		e.preventDefault();
		e.stopPropagation();
		let chatText = e.target.value.split(' ');
		let length = 0;
		for (let i = 0; i < chatText.length; i++) {
			length += chatText[i].length + 1;
			if (length <= e.target.selectionStart || chatText[i] === "")
				continue;
			let foundAutocompletes = [];
			let foundAutocompletesOffsets = [];
			for (let j = 0; j < window.bonkCommands.length; j++) {
				if (window.bonkCommands[j].toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, '\\$&').match("^" + chatText[i].toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))) {
					foundAutocompletes.push(window.bonkCommands[j]);
					foundAutocompletesOffsets.push(0);
				}
			}
			if (foundAutocompletes.length === 0) {
				for (let j = 0; j < window.bonkHost.playerNames.length; j++) {
					for (let k = i; k >= 0; k--) {
						if (window.bonkHost.playerNames[j].toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, '\\$&').match("^" + chatText.slice(k, i + 1).join(" ").toLowerCase().replace(/"/g, "").replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))) {
							foundAutocompletes.push(window.bonkHost.playerNames[j]);
							foundAutocompletesOffsets.push(k);
						}
					}
				}
			}
			if (foundAutocompletes.length === 1) {
				let oldlen = chatText.slice(foundAutocompletesOffsets[0], i + 1).join(" ").length;
				for (let j = i; j > foundAutocompletesOffsets[0]; j--) {
					chatText.splice(j, 1);
				}
				if (chatText[0][0] === "/" && i > 0 && foundAutocompletes[0].includes(" ")) {
					chatText[foundAutocompletesOffsets[0]] = `"${foundAutocompletes[0]}" `;
				} else {
					chatText[foundAutocompletesOffsets[0]] = foundAutocompletes[0] + (foundAutocompletesOffsets[0] === (chatText.length - 1) && (chatText[0][0] === "/") && (chatText[foundAutocompletesOffsets[0] + 1] !== "") ? " " : "");
				}
				if(chatText[foundAutocompletesOffsets[0] + 1] === "") {
					chatText.splice(foundAutocompletesOffsets[0] + 1, 1);
				}
				e.target.value = chatText.join(' ');
				e.target.selectionStart = length - oldlen + chatText[foundAutocompletesOffsets[0]].length + ((foundAutocompletesOffsets[0] === chatText.length - 1) && (chatText[0][0] !== "/") ? 0 : 1);
				e.target.selectionEnd = length - oldlen + chatText[foundAutocompletesOffsets[0]].length + ((foundAutocompletesOffsets[0] === (chatText.length - 1)) && (chatText[0][0] !== "/") ? 1 : 0);
				return;
			} else if (foundAutocompletes.length > 1) {
				let maxAutocomplete = "";
				let char = "";
				for (let j = 0; j >= 0; j++) {
					maxAutocomplete += char;
					char = "";
					for (let k = 0; k < foundAutocompletes.length; k++) {
						if (char === "") char = foundAutocompletes[k][j];
						else if (foundAutocompletes[k][j] !== char) {
							j = -Infinity;
							break;
						}
					}
				}
                if(maxAutocomplete === "") return;
				let oldlen = chatText[i].length;
				let quotes = (chatText[0][0] === "/" && foundAutocompletes.some(r => r.includes(" ")));
				if (quotes) {
					chatText[i] = `"${maxAutocomplete}"`;
				} else {
					chatText[i] = maxAutocomplete;
				}
				e.target.value = chatText.join(' ');
				e.target.selectionStart = length - oldlen + chatText[i].length - quotes * 2;
				e.target.selectionEnd = length - oldlen + chatText[i].length - quotes * 2;
				return;
			}
		}
	}
}

(() => {
    let selectedPlayer = null;
    let start = [], end = [];
    const wheelSize = 150;
    let oldAngle = null;
    const innerWheelRadius = (wheelSize/26.458)/2*8.5;
    window.bonkHost.updatePlayers = () => {
        if(window.bonkHost.menuUsage.getLSID() !== window.bonkHost.menuUsage.hostID) return;
        [...document.getElementsByClassName("newbonklobby_playerentry")].filter(e => {return e.parentNode.id === "newbonklobby_playerbox_elementcontainer" || e.parentNode.id === "newbonklobby_specbox_elementcontainer" || e.parentNode.id === "hostPlayerMenuBox"}).forEach(e => {
            e.addEventListener("mousedown", mouse => {
                selectedPlayer = e;
                start = [mouse.clientY, mouse.clientX];
            });
        });
    }
    document.addEventListener("mousemove", mouse => {
        if(selectedPlayer) {
            document.body.style.pointerEvents = "none";
            let wheelType = (document.getElementById("newbonklobby_teams_middletext").textContent === "TEAMS OFF") ? "selectionWheel" : "selectionWheelTeams";
            document.getElementById(wheelType).style.display = "";
            document.getElementById(wheelType).style.top = start[0]-document.getElementById(wheelType).getBoundingClientRect().height/2+"px";
            document.getElementById(wheelType).style.left = start[1]-document.getElementById(wheelType).getBoundingClientRect().width/2+"px";
            end = [mouse.clientY, mouse.clientX];
            if(Math.sqrt((end[0]-start[0])**2 + (end[1]-start[1])**2) >= innerWheelRadius) {
                if(document.getElementById("newbonklobby_teams_middletext").textContent === "TEAMS OFF") {
                    let angle = end[1] < start[1];
                    if(angle) {
                        document.getElementById("selectionWheel").children[0].children[0].children[0].style.opacity = 1;
                        document.getElementById("selectionWheel").children[0].children[1].children[0].style.opacity = 0.5;
                    }
                    else {
                        document.getElementById("selectionWheel").children[0].children[0].children[0].style.opacity = 0.5;
                        document.getElementById("selectionWheel").children[0].children[1].children[0].style.opacity = 1;
                    }
                    selectedPlayer.onmouseenter(angle);
                    oldAngle = angle;
                }
                else {
                    let angle = Math.atan((end[0]-start[0])/(end[1]-start[1]))/Math.PI*180+360/5/2;
                    if(end[1] < start[1]) {
                        angle += 180;
                    }
                    else if(end[0] < start[0]) {
                        angle += 360;
                    }
                    angle = Math.floor((angle%360)/(360/5));
                    if(oldAngle !== angle) {
                        for(let child of [...document.getElementById("selectionWheelTeams").children[0].children[0].children]) {
                            child.style.opacity = 0.5;
                        }
                    }
                    document.getElementById("selectionWheelTeams").children[0].children[0].children[angle].style.opacity = 1;
                    selectedPlayer.onmouseenter(angle);
                    oldAngle = angle;
                }
            }
            else {
                if(oldAngle !== null) {
                    for(let child of [...document.getElementById("selectionWheelTeams").children[0].children[0].children]) {
                        child.style.opacity = 0.5;
                    }
                    for(let child of [...document.getElementById("selectionWheel").children[0].children]) {
                        child.children[0].style.opacity = 0.5;
                    }
                }
                selectedPlayer.onmouseenter(null);
                oldAngle = null;
            }
        }
    });
    const changeTeam = mouse => {
        document.getElementById("selectionWheel").style.display = "none";
        document.getElementById("selectionWheelTeams").style.display = "none";
        if(!selectedPlayer) return;
        document.body.style.removeProperty("pointer-events");
        end = [mouse.clientY, mouse.clientX];
        if(Math.sqrt((end[0]-start[0])**2 + (end[1]-start[1])**2) >= innerWheelRadius) {
            if(document.getElementById("newbonklobby_teams_middletext").textContent === "TEAMS OFF") {
            for(let child of [...document.getElementById("selectionWheel").children[0].children]) {
                child.children[0].style.opacity = 0.5;
            }
            window.bonkHost.menuUsage.changeOtherTeam(window.bonkHost.players.findIndex(i => {return i && i.userName === selectedPlayer.children[1].textContent}), end[1]<start[1] ? 1 : 0);
            }
            else {
                let angle = Math.atan((end[0]-start[0])/(end[1]-start[1]))/Math.PI*180+360/5/2;
                if(end[1] < start[1]) {
                    angle += 180;
                }
                else if(end[0] < start[0]) {
                    angle += 360;
                }
                angle = Math.floor((angle%360)/(360/5));
                window.bonkHost.menuUsage.changeOtherTeam(window.bonkHost.players.findIndex(i => {return i && i.userName === selectedPlayer.children[1].textContent}), [0, 5, 4, 3, 2][angle]);
            }
        }
        else {
            selectedPlayer.click();
        }
        selectedPlayer = null;
    }
    document.addEventListener("mouseup", changeTeam);
    document.addEventListener("mouseenter", mouse => {selectedPlayer = (mouse.buttons !== 0 ? selectedPlayer : null); if(!selectedPlayer)changeTeam(mouse)});
})();

document.getElementById('ingamechatinputtext').onkeydown = document.getElementById('newbonklobby_chat_input').onkeydown;//Remove round limit
document.getElementById('newbonklobby_roundsinput').removeAttribute("maxlength");
newStr = newStr.replace(/...\[[0-9]\]\[[0-9]\]\[...\[[0-9]\]\[[0-9]?[0-9]?[0-9]\]\]=Math\[...\[[0-9]\]\[[0-9]?[0-9]?[0-9]\]\]\(Math\[...\[[0-9]\]\[[0-9]?[0-9]?[0-9]\]\]\(1,...\[[0-9]\]\[[0-9]\]\[...\[[0-9]\]\[[0-9]?[0-9]?[0-9]\]\]\),9\);/, '');

//Mode selection menu
newStr = newStr.replace(modeStuff[0], `${modeStuff[0]};window.bonkModesObject=${modesObject};window.bonkSetMode=m=>{${modeStuff[1]}${modeVar}=m;${modeStuff[3]}};window.createModeDropdown();`);
//Add mode button to map suggestion message
newStr = newStr.replace('v2k[79][d9G[3][624]]([d9G[73]]);', 'v2k[79][d9G[3][624]]([d9G[73]]);' + SUGGESTION_MODE_BUTTON);
//Append mode button
newStr = newStr.replace('d9G[8][d9G[3][455]](d9G[73]);', 'd9G[8][d9G[3][455]](d9G[73]);'+APPEND_SUGGESTION_MODE_BUTTON);

//Balance all
newStr = newStr.replace('I8H[7][I8H[1][645]]()', 'I8H[7][I8H[1][645]]() || I8H[7] === "*" || I8H[5][0] == "/balanceall"');
newStr = newStr.replace('I8H[5][0] == G9b.z43(1869)', 'I8H[5][0] == G9b.z43(1869) || I8H[5][0] == "/balanceall"');
newStr = newStr.replace('I8H[67]=I8H[17];break;', BALANCE_SELECTION);
newStr = newStr.replace('parseInt(I8H[5][2]);', 'parseInt(I8H[5][I8H[5][0] == "/balanceall" ? 1 : 2]);');
newStr = newStr.replace('if(I8H[32] == 0)', BALANCE_ALL_MESSAGE);

newStr = newStr.replace('if(I8H[5][0] == G9b.z43(1869)', CUSTOM_COMMANDS+'else if(I8H[5][0] == G9b.z43(1869)');
newStr = newStr.replace('u6H[29][I8H[1][644]](G9b.A43(1897),G9b.z43(1871),false);', 'u6H[29][I8H[1][644]](G9b.A43(1897),G9b.z43(1871),false);u6H[29].showStatusMessage("/hhelp - commands from host mod","#cc3333",false);');

//Internal var
newStr = newStr.replace('function I8yy(){}', 'function I8yy(){}'+'I8yy.bonkHost={};');

//Let people join mid game
newStr = newStr.replace('if(u6H[64]){u6H[30]', FREEJOIN + 'u6H[30]');

/////////////
//Host menu//
/////////////

//Add players
newStr = newStr.replace('{Q1h();}};', '{Q1h();}};' + 'window.bonkHost.playerManagement.addPlayer(X9G[1], w3G[0][1][X9G[0][0]]);');

//Remove players
newStr = newStr.replace('if(w3G[32][h9G[5]]){', 'if(w3G[32][h9G[5]]){' + 'window.bonkHost.playerManagement.removePlayer(w3G[32][h9G[5]]);');
newStr = newStr.replace('if(w3G[32][c1G[2]]){', 'if(w3G[32][c1G[2]]){' + 'window.bonkHost.playerManagement.removePlayer(w3G[32][c1G[2]]);');

//Player click menu
newStr = newStr.replace('if(X9G[1][m9G[2][1379]]){', PLAYER_CLICK_MENU + 'if(X9G[1][m9G[2][1379]]){')

//Player click menu position and highligh removal
newStr = newStr.replace('if(m9G[4] == false){', 'if(playerEntry){w3G[26].playerElement=playerEntry;m9G[6].style.removeProperty("left");m9G[6].style.right=0;m9G[6].style.top=([...playerEntry.parentNode.children].indexOf(playerEntry)+1)*43+"px";}' + 'if(m9G[4] == false){');

//Highlight
newStr = newStr.replace('X9G[1][m9G[2][457]][m9G[2][456]](G9b.z43(3256));', 'let playerEntry = window.bonkHost.playerManagement.getPlayer(m9G[0][0].target, true); if(playerEntry) {playerEntry.classList.add("newbonklobby_playerentry_menuhighlighted");} else{' + 'X9G[1][m9G[2][457]][m9G[2][456]](G9b.z43(3256));' + '}');

//Some bonk function handlers
newStr = newStr.replace('R2k[0][1]});};}', 'R2k[0][1]});};' + 'window.bonkHost.bonkHandlers = this;' + '}');

//Some menu functions
newStr = newStr.replace('w3G[60]);}};', 'w3G[60]);}};'+ 'window.bonkHost.menuFunctions = this;');

//Player counter
newStr = newStr.replace('if(u6H[5]', 'window.bonkHost.playerCount=s6H[3];if(u6H[5]');

//Change team handlers
newStr = newStr.replace('w8G[9]=v8yy;', 'w8G[9]=v8yy;' + "window.bonkHost.playerManagement.movePlayer(w8G[0][0], window.bonkHost.playerCount, w8G[0][1]);");
newStr = newStr.replace('S8G[8]=v8yy;', 'S8G[8]=v8yy;' + "window.bonkHost.playerManagement.movePlayer(this.getLSID(), window.bonkHost.playerCount, S8G[0][0]);");

//Get start game function
newStr = newStr.replace('function P5S', 'window.bonkHost.startGameFunction=P5S;document.getElementById("hostPlayerMenuRestartButton").addEventListener("click", window.bonkHost.startGame);' + 'function P5S')

//Scores
newStr = newStr.replace(';if(k7k[0][5][k7k[4][114]])', ';' + KEEP_SCORES + 'if(k7k[0][5][k7k[4][114]])');
newStr = newStr.replace('o9k[1][o9k[7][122]]=[0,0,0,0];', 'o9k[1][o9k[7][122]]=' + '(window.bonkHost.scores.length > 0 && document.getElementById("hostPlayerMenuKeepScores").checked) ? window.bonkHost.scores' + ':[0,0,0,0];')

//Score counter
newStr = newStr.replace('G9b.A2k(1000,b2k[6]);', 'G9b.A2k(1000,b2k[6]);window.bonkHost.scores=i2k[7][i2k[1]].scores;');

//Update menu while in game
newStr = newStr.replace('!this[h9G[9][481]]', '!this[h9G[9][481]] && false');
newStr = newStr.replace('!this[V9G[1][481]]', '!this[V9G[1][481]] && false');

//Show menu when in game if host
newStr = newStr.replace('if(u6H[29]){u6H[29][w8H[9][722]]();}', 'if(u6H[29]){u6H[29][w8H[9][722]]();' + `if(u6H[11].hostID == u6H[11].getLSID())window.bonkHost.playerManagement.show();` + '}');

//Hide menu when not in game
newStr = newStr.replace('w1G[5]=v8yy;', 'w1G[5]=v8yy;' + 'window.bonkHost.playerManagement.hide();window.bonkHost.scores=[];');
newStr = newStr.replace('c1G[5]=v8yy;', 'c1G[5]=v8yy;' + 'window.bonkHost.playerManagement.hide();window.bonkHost.scores=[];');
newStr = newStr.replace('O7G[4]=v8yy;', 'O7G[4]=v8yy;' + 'window.bonkHost.playerManagement.hide();window.bonkHost.scores=[];');

//Add default click handler (mainly for closing the dropdown menu)
newStr = newStr.replace('=e6h;', '=e6h;' + 'document.getElementById("hostPlayerMenu").onclick=e6h;');

//Handle host change
newStr = newStr.replace('l5h(G9b.z43(3279),G9b.A43(3276),false);}', 'window.bonkHost.playerManagement.show();' + 'l5h(G9b.z43(3279),G9b.A43(3276),false);}' + 'else{window.bonkHost.playerManagement.hide();}');
newStr = newStr.replace('C0z(G9b.A43(2039));', 'C0z(G9b.A43(2039));' + 'window.bonkHost.playerManagement.show();');

//Teamlock
newStr = newStr.replace('if(w3G[0][2][V9G[1][662]])', 'document.getElementById("hostPlayerMenuTeamlock").checked=w3G[0][2].tl;' + 'if(w3G[0][2][V9G[1][662]])');

//Handle an error when clicking host menu. MIGHT BREAK IN RARE CASES WITH OTHER MODS because it's missing {}, but it should be fine
newStr = newStr.replace('t9G[5]=v8yy;', 't9G[5]=v8yy;' + 'if(w3G[26].element!=null)');

//Update menu when joined
newStr = newStr.replaceAll('=u6H[30];', '=u6H[30];if(!u6H[64]){let oldVisibility=window.bonkHost.menuFunctions.visible;window.bonkHost.menuFunctions.visible=true;window.bonkHost.menuFunctions.updatePlayers();window.bonkHost.menuFunctions.visible = oldVisibility;}');

//Save latest state
newStr = newStr.replace('var T7k=[arguments];', 'I8yy.bonkHost.state=arguments[0];var T7k=[arguments];');

newStr = newStr.replace('W6H[2][', SET_STATE);

//Get useful menu functions
newStr = newStr.replace('w3G[3]=w3G[0][0];', 'w3G[3]=w3G[0][0];window.bonkHost.menuUsage=w3G[3];');

//Get player lists from updatePlayers() and update player elements for radial menu
newStr = newStr.replace('(1,h9G[2])(h9G[3]);}', '(1,h9G[2])(h9G[3]);}' + 'window.bonkHost.players=w3G[0][1];window.bonkHost.updatePlayers();');

newStr = newStr.replace('m9G[1]=w3G[0][1][X9G[0][0]][m9G[2][115]];', 'm9G[1]=w3G[0][1][X9G[0][0]][m9G[2][115]];' + 'if(!window.bonkHost.menuFunctions.visible && I8yy.bonkHost.state.discs[X9G[0][0]] == undefined && I8yy.bonkHost.state.discDeaths.findIndex(i => {return i.i === X9G[0][0]})){m9G[1]=0;}');

//Fix skin bug
newStr = newStr.replace('u9k[2][u9k[5][457]][u9k[5][456]](i9k[42]);}', 'u9k[2][u9k[5][457]][u9k[5][456]](i9k[42]);}' + "window.bonkHost.redrawSkin(i9k[23]);");	console.log("Bonk Host injector run");
	return newStr;
}

if(!window.bonkCommands) window.bonkCommands = [];

if(!window.bonkCodeInjectors) window.bonkCodeInjectors = [];
window.bonkCodeInjectors.push(bonkCode => {
	try {
		return injector(bonkCode);
	} catch (error) {
		alert(
`Whoops! Bonk Host was unable to load.
This may be due to an update to Bonk.io. If so, please report this error!
This could also be because you have an extension that is incompatible with \
Bonk Host, such as the Bonk Leagues Client. You would have to disable it to use \
Bonk Host.`);
		throw error;
	}
});

console.log("Bonk Host injector loaded");

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址