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