- // ==UserScript==
- // @name Bonk Host
- // @version 4.0
- // @author Salama
- // @description Makes hosting rooms in bonk.io better
- // @match https://bonk.io/gameframe-release.html
- // @match https://bonkisback.io/gameframe-release.html
- // @run-at document-start
- // @grant none
- // @supportURL https://discord.gg/Dj6usq7ww3
- // @namespace https://greatest.deepsurf.us/users/824888
- // ==/UserScript==
-
- // for use as a userscript ensure you have Excigma's code injector userscript
- // https://greatest.deepsurf.us/en/scripts/433861-code-injector-bonk-io
-
- let injector = (str) => {
- let newStr = str;
- window.bonkHost = {};
- window.bonkHost.playerManagement = {};
- window.bonkHost.freejoin = false;
- window.bonkHost.bans = [];
- window.bonkHost.inGame = false;
- window.bonkHost.playerManagement.canBeVisible = false;
- window.bonkHost.bonkCallbacks = {};
- window.bonkHost.playerHistory = {};
- window.bonkHost.playerSus = [];
- window.bonkHost.fig = 0;
- window.bonkHost.cheatDetection = false;
- let mapHistory = [];
- let mapHistoryIndex = 0;
-
- window.bonkCommands = window.bonkCommands.concat(["/kick", "/mute", "/unmute", "/lock", "/unlock", "/balance", "/fav", "/unfav", "/curate", "/curateyes", "/curateno", "/roomname", "/roompass", "/clearroompass", "/hhelp", "/balanceall", "/start", "/freejoin", "/host", "/ban", "/bans", "/unban", "/scoreboard", "/resetpos"]);
-
- if(!localStorage.getItem("bonkHost")) {
- localStorage.setItem("bonkHost", "{}");
- }
-
- let hostPlayerMenuCSS = document.createElement('style');
- hostPlayerMenuCSS.innerHTML = `
- #hostPlayerMenu {
- background-color: #cfd8cd;
- width: calc(35.2vw - 400px);
- min-width: 154px;
- max-width: 200px;
- height: 576px;
- position: absolute;
- left: 10px;
- top: 60px;
- bottom: unset;
- border-radius: 7px;
- display: none;
- transition: ease-in-out 100ms;
- z-index: 100;
- overflow: visible;
- }
-
- #hostPlayerMenuBox {
- top: 32px;
- height: calc(47px * 8);
- }
-
- #hostPlayerMenuCollapse {
- position: absolute;
- left: 3px;
- top: 3px;
- width: 26px;
- height: 26px;
- border-radius: 2px;
- visibility: visible;
- }
-
- #hostPlayerMenuGrab {
- position: absolute;
- right: 3px;
- top: 3px;
- width: 26px;
- height: 26px;
- border-radius: 2px;
- visibility: visible;
- cursor: grab;
- }
-
- #hostPlayerMenuControls {
- position: absolute;
- bottom: 0;
- width: 100%;
- }
-
- #hostPlayerCheatDetection {
- position: absolute;
- left: 0;
- top: 0;
- z-index: -1;
- background-color: #cfd8cd;
- width: inherit;
- min-width: inherit;
- max-width: inherit;
- height: inherit;
- border-radius: 7px;
- transition: ease-in-out 100ms;
- opacity: 70%;
- visibility: hidden;
- }
-
- #hostPlayerCheatDetection canvas {
- background-color: rgb(58, 58, 58);
- margin-left: 5%;
- height: 45px;
- width: 95%;
- margin-top: 1px;
- margin-bottom: 1px;
- }
- #selectionWheel {
- width: 150px;
- height: 150px;
- position: absolute;
- left: 588px;
- top: 181px;
- pointer-events: none;
- display: none;
- z-index: 150;
- }
- #selectionWheelTeams {
- width: 150px;
- height: 150px;
- position: absolute;
- left: 1061px;
- top: 169px;
- pointer-events: none;
- display: none;
- z-index: 150;
- }
-
- #hostPlayerMenuRestartButton {
- width: 100%;
- border-width: 0 !important;
- }
-
- #newbonklobby_hostprevmap {
- width: 27px;
- height: 27px;
- position: absolute;
- top: 106px;
- left: 15px;
- }
-
- #newbonklobby_hostnextmap {
- width: 27px;
- height: 27px;
- position: absolute;
- top: 106px;
- left: 48px;
- }
-
- #newbonklobby_roundsinput {
- height: 50px !important;
- text-align: center !important;
- }
- `;
- document.getElementsByTagName('head')[0].appendChild(hostPlayerMenuCSS);
-
- let hostPlayerMenu = document.createElement('div');
- document.getElementById('pagecontainer').appendChild(hostPlayerMenu);
- hostPlayerMenu.outerHTML = `
- <div class="windowShadow newbonklobby_elementcontainer" 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>
- <span>Player List</span>
- <div id="hostPlayerMenuGrab" class="newbonklobby_settings_button brownButton brownButton_classic buttonShadow">:::</div>
- </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">
- Cheat detection
- </td>
- <td>
- <input type="checkbox" id="hostPlayerMenuCheatDetectionCheckbox">
- </td>
- </tr>
- <tr style="background-color: rgba(58, 58, 58, 0.07);">
- <td>
- <div style="padding-left: 10px;" class="mapeditor_rightbox_table">
- Keep positions
- </div>
- <div style="padding-left: 10px; font-size: 10px; display:none" class="mapeditor_rightbox_table" id="hostPlayerMenuRespawningRequiredWarning">
- Respawning required
- </div>
- </td>
- <td>
- <input type="checkbox" id="hostPlayerMenuKeepPositions">
- </td>
- </tr>
- </tbody>
- </table>
- <div class="newbonklobby_settings_button brownButton brownButton_classic buttonShadow" id="hostPlayerMenuRestartButton">
- RESTART GAME
- </div>
- </div>
- <div class="windowShadow" id="hostPlayerCheatDetection">
- <div class="newbonklobby_boxtop newbonklobby_boxtop_classic" style="background-color: #009688;"></div>
- <div id="hostPlayerMenuCheatBox" class="newbonklobby_elementcontainer">
- <canvas width="1" height="45" class="mapeditor_rightbox_table"></canvas>
- <canvas width="1" height="45" class="mapeditor_rightbox_table"></canvas>
- <canvas width="1" height="45" class="mapeditor_rightbox_table"></canvas>
- <canvas width="1" height="45" class="mapeditor_rightbox_table"></canvas>
- <canvas width="1" height="45" class="mapeditor_rightbox_table"></canvas>
- <canvas width="1" height="45" class="mapeditor_rightbox_table"></canvas>
- <canvas width="1" height="45" class="mapeditor_rightbox_table"></canvas>
- <canvas width="1" height="45" class="mapeditor_rightbox_table"></canvas>
- </div>
- <div class="mapeditor_rightbox_table" style="position:absolute;bottom:0;width:95%;margin-left:5%;text-align:justify;font-size:15;height:170px;overflow-y:scroll;">
- INSTRUCTIONS: The graph shows how laggy someone is compared to how laggy they actually should be. This can be used to detect lag cheats. Being over the first red line is OK. Consistently being under it can happen but it's suspicious. Anything consistent under that is usually just cheats. Random lag spikes can happen. ⚠️ indicates that the player is using a mod that is known to have related cheats.
- </div>
- </div>
- </div>
- <div id="selectionWheel">
- <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">
- <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>
- <div class="newbonklobby_settings_button brownButton brownButton_classic buttonShadow" id="newbonklobby_hostprevmap"><</div>
- <div class="newbonklobby_settings_button brownButton brownButton_classic buttonShadow" id="newbonklobby_hostnextmap">></div>
- <!--
- <div id="teamshufflebutton" class="brownButton brownButton_classic buttonShadow" style="
- width: 16px;
- height: 35px;
- border-radius: 2px;
- position: absolute;
- top: calc(17% - 40px);
- right: calc(33.5% - 8px);
- font-family: monospace;
- ">
- <svg width="16" height="16" fill="currentColor" viewBox="0 0 16 16" style="height: 100%;transform:scaleX(-0.9);">
- <path fill-rule="evenodd" d="M0 3.5A.5.5 0 0 1 .5 3H1c2.202 0 3.827 1.24 4.874 2.418.49.552.865 1.102 1.126 1.532.26-.43.636-.98 1.126-1.532C9.173 4.24 10.798 3 13 3v1c-1.798 0-3.173 1.01-4.126 2.082A9.624 9.624 0 0 0 7.556 8a9.624 9.624 0 0 0 1.317 1.918C9.828 10.99 11.204 12 13 12v1c-2.202 0-3.827-1.24-4.874-2.418A10.595 10.595 0 0 1 7 9.05c-.26.43-.636.98-1.126 1.532C4.827 11.76 3.202 13 1 13H.5a.5.5 0 0 1 0-1H1c1.798 0 3.173-1.01 4.126-2.082A9.624 9.624 0 0 0 6.444 8a9.624 9.624 0 0 0-1.317-1.918C4.172 5.01 2.796 4 1 4H.5a.5.5 0 0 1-.5-.5z"></path>
- <path d="M13 5.466V1.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384l-2.36 1.966a.25.25 0 0 1-.41-.192zm0 9v-3.932a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384l-2.36 1.966a.25.25 0 0 1-.41-.192z"></path>
- </svg>
- </div>
- <div id="teamshufflebox" class="newbonklobby_elementcontainer" style="
- position: absolute;
- top: calc(17% - 42px);
- right: calc(33.5% - 10px);
- width: auto;
- height: auto;
- bottom: unset;
- outline: 3000px solid rgba(0,0,0,0.30);
- visibility: hidden;
- ">
- <div class="newbonklobby_boxtop newbonklobby_boxtop_classic" style="
- height: 39px;
- line-height: 39px;
- ">
- Shuffle Teams
- <div onclick=window.bonkHost.shuffleTeams class="newbonklobby_votewindow_votebutton brownButton brownButton_classic buttonShadow" id="newbonklobby_votewindow_votebutton_up" style="
- margin: 0;
- height: 35px;
- width: 25px;
- position: absolute;
- left: calc(100% - 27px);
- top: 2px;
- "></div>
- <div onclick="()=>{document.getElementById('teamshufflebox').style.visibility='hidden';}" class="newbonklobby_votewindow_votebutton brownButton brownButton_classic buttonShadow" id="newbonklobby_votewindow_votebutton_down" style="
- margin: 0;
- height: 35px;
- width: 25px;
- position: absolute;
- top: 2px;
- left: calc(100% - 55px);
- "></div>
- </div>
- <table id="mapeditor_rightbox_table_simple" class="mapeditor_rightbox_table">
- <tbody>
- <tr>
- <td class="mapeditor_rightbox_table_leftcell">Players per team</td>
- <td class="mapeditor_rightbox_table_rightcell">
- <div class="mapeditor_field_button fieldShadow" style="width:auto;margin:0 3;" onclick="() => {
- document.getElementById('teamshufflebox').value = 'AUTO';
- }">AUTO</div>
- <div class="mapeditor_field_button fieldShadow" style="margin:0 1;">-</div>
- <input id="teamshuffleppt" class="mapeditor_field fieldShadow" value="1" autocomplete="off" style="width:44px;">
- <div class="mapeditor_field_button fieldShadow" style="margin 0 1;" onclick="() => {
- document.getElementById('teamshuffleppt').value = parseInt(document.getElementById('teamshuffleppt').value) + 1;
- }">+</div>
- </td>
- </tr>
- <tr>
- <td class="mapeditor_rightbox_table_leftcell">Teams</td>
- <td class="mapeditor_rightbox_table_rightcell" style="
- display: grid;
- align-content: center;
- justify-content: center;
- align-items: center;
- grid-template-columns: 20px 25px 20px 35px;
- ">
- <input type="checkbox" id="team_shuffle_blue"><label>Blue</label>
- <input type="checkbox" id="team_shuffle_green"><label>Green</label>
- <input type="checkbox" id="team_shuffle_red"><label>Red</label>
- <input type="checkbox" id="team_shuffle_yellow"><label>Yellow</label>
- </td>
- </tr>
- <tr>
- <td class="mapeditor_rightbox_table_leftcell">Autoshuffle</td>
- <td class="mapeditor_rightbox_table_rightcell">
- <input type="checkbox" id="mapeditor_rightbox_table_bullet">
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- `;
- document.getElementById("hostPlayerMenuBox").addEventListener("click", (e) => {
- if(e.target === document.getElementById("hostPlayerMenuBox")) {
- document.getElementById('newbonklobby').click();
- }
- });
-
- document.getElementById("hostPlayerMenuRestartButton").addEventListener("click", () => {
- window.bonkHost.startGame();
- });
-
- /*document.getElementById('newbonklobby').appendChild(document.getElementById('teamshufflebutton'));
- document.getElementById('newbonklobby').appendChild(document.getElementById('teamshufflebox'));
- document.getElementById('teamshufflebutton').addEventListener('click', () => {
- document.getElementById('teamshufflebox').style.visibility = document.getElementById('teamshufflebox').style.visibility == "hidden" ? "visible" : "hidden";
- });
- */
- document.getElementById("newbonklobby_specbutton").addEventListener("dblclick", () => {moveEveryone(0)});
- document.getElementById("newbonklobby_ffabutton").addEventListener("dblclick", () => {moveEveryone(1)});
- document.getElementById("newbonklobby_bluebutton").addEventListener("dblclick", () => {moveEveryone(3)});
- document.getElementById("newbonklobby_redbutton").addEventListener("dblclick", () => {moveEveryone(2)});
- document.getElementById("newbonklobby_greenbutton").addEventListener("dblclick", () => {moveEveryone(4)});
- document.getElementById("newbonklobby_yellowbutton").addEventListener("dblclick", () => {moveEveryone(5)});
-
- document.getElementById("newbonklobby_settingsbox").appendChild(document.getElementById("newbonklobby_hostprevmap"));
- document.getElementById("newbonklobby_settingsbox").appendChild(document.getElementById("newbonklobby_hostnextmap"));
-
- const updateMapHistoryButtons = () => {
- if(window.bonkHost.toolFunctions.getGameSettings().ga === "b") {
- document.getElementById("newbonklobby_hostprevmap").style.display = "";
- document.getElementById("newbonklobby_hostnextmap").style.display = "";
- if(isHost()) {
- document.getElementById("newbonklobby_hostprevmap").classList.toggle("brownButtonDisabled", mapHistoryIndex >= mapHistory.length - 1);
- document.getElementById("newbonklobby_hostnextmap").classList.toggle("brownButtonDisabled", mapHistoryIndex === 0);
-
- // Make sure they are the topmost elements
- document.getElementById("newbonklobby_settingsbox").appendChild(document.getElementById("newbonklobby_hostprevmap"));
- document.getElementById("newbonklobby_settingsbox").appendChild(document.getElementById("newbonklobby_hostnextmap"));
- }
- else {
- document.getElementById("newbonklobby_hostprevmap").classList.add("brownButtonDisabled");
- document.getElementById("newbonklobby_hostnextmap").classList.add("brownButtonDisabled");
- }
- }
- else {
- document.getElementById("newbonklobby_hostprevmap").style.display = "none";
- document.getElementById("newbonklobby_hostnextmap").style.display = "none";
- }
- }
-
- document.getElementById("newbonklobby_hostprevmap").addEventListener("click", () => {
- if(!isHost() || mapHistoryIndex >= mapHistory.length - 1) return;
- mapHistoryIndex++;
- let gs = window.bonkHost.toolFunctions.getGameSettings();
- gs.map = mapHistory[mapHistoryIndex];
- window.bonkHost.menuFunctions.setGameSettings(gs);
- window.bonkHost.menuFunctions.updateGameSettings();
- window.bonkHost.toolFunctions.networkEngine.sendMapAdd(gs.map);
- updateMapHistoryButtons();
- });
-
- document.getElementById("newbonklobby_hostnextmap").addEventListener("click", () => {
- if(!isHost() || mapHistoryIndex == 0) return;
- mapHistoryIndex--;
- let gs = window.bonkHost.toolFunctions.getGameSettings();
- gs.map = mapHistory[mapHistoryIndex];
- window.bonkHost.menuFunctions.setGameSettings(gs);
- window.bonkHost.menuFunctions.updateGameSettings();
- window.bonkHost.toolFunctions.networkEngine.sendMapAdd(gs.map);
- updateMapHistoryButtons();
- });
-
- document.getElementById("newbonklobby_roundsinput").addEventListener("focus", e => {
- e.target.value = "";
- });
- document.getElementById("newbonklobby_roundsinput").addEventListener("blur", e => {
- if(e.target.value == "") {
- e.target.value = window.bonkHost.toolFunctions.getGameSettings().wl;
- }
- });
-
- const moveEveryone = (team) => {
- if(!isHost()) return;
- for(let id of window.bonkHost.toolFunctions.networkEngine.getConnectedPlayers()) {
- window.bonkHost.toolFunctions.networkEngine.changeOtherTeam(id, team);
- }
- }
-
- const BIGVAR = newStr.match(/[A-Za-z0-9$_]+\[[0-9]{6}\]/)[0].split('[')[0];
-
- const isHost = () => {
- return window.bonkHost.toolFunctions.networkEngine.getLSID() === window.bonkHost.toolFunctions.networkEngine.hostID && !window.bonkHost.toolFunctions.getGameSettings().q;
- }
-
- window.bonkHost.wrap = () => {
- // Event for when game finishes loading. Using a setInterval isn't optimal and we might miss some, but it's good enough for now
- const gameLoadedWaiter = setInterval(() => {
- // I hope a better way of doing this exists
- if(window.bonkHost.menuFunctions !== undefined && Object.keys(window.bonkHost.menuFunctions).length >= 27) {
- clearInterval(gameLoadedWaiter);
- }
- else return;
-
- // Wrap menuFunctions
- for(const i of Object.keys(window.bonkHost.menuFunctions)) {
- if(typeof window.bonkHost.menuFunctions[i] !== "function") continue;
- const ogFunc = window.bonkHost.menuFunctions[i];
- window.bonkHost.menuFunctions[i] = function() {
- let response = ogFunc.apply(window.bonkHost.menuFunctions, arguments);
- switch(i) {
- case "returnFromTesting":
- case "show":
- window.bonkHost.playerManagement.canBeVisible = false;
- window.bonkHost.playerManagement.hide();
- if(window[BIGVAR].bonkHost.state) {
- if(Math.max(...window[BIGVAR].bonkHost.state.scores) >= window.bonkHost.toolFunctions.getGameSettings().wl) {
- for(let i = 0; i < window[BIGVAR].bonkHost.state.scores.length; i++) {
- if(window[BIGVAR].bonkHost.state.scores === null) continue;
- window[BIGVAR].bonkHost.state.scores[i] = 0;
- }
- }
- }
- break;
- case "hide":
- window.bonkHost.menuFunctions.visible = true;
- window.bonkHost.playerManagement.canBeVisible = true;
- window.bonkHost.playerManagement.show();
- //Intentional fallthrough to update host status
-
- case "updateGameSettings":
- window.bonkHost.handleHostChange(window.bonkHost.toolFunctions.networkEngine.hostID === window.bonkHost.toolFunctions.networkEngine.getLSID());
- break;
- case "handleHostChange":
- if(isHost()) {
- window.bonkHost.stateFunctions.chatStatus("* You are now the host of this game")
- }
- //Intentional fallthrough to update host status
- case "handleHostLeft":
- window.bonkHost.handleHostChange(arguments[1] === window.bonkHost.toolFunctions.networkEngine.getLSID());
- break;
- case "handlePlayerJoin":
- window.bonkHost.handlePlayerJoin(arguments[1]);
- break;
- case "updatePlayers":
- while(document.getElementById("hostPlayerMenuBox").firstChild) {
- document.getElementById("hostPlayerMenuBox").removeChild(document.getElementById("hostPlayerMenuBox").firstChild);
- }
- [...document.getElementsByClassName("newbonklobby_playerentry")].sort((a, b) => {
- return window.bonkHost.players.filter(p=>p).findIndex(p => a.childNodes[1].textContent === p.userName) - window.bonkHost.players.filter(p=>p).findIndex(p => b.childNodes[1].textContent == p.userName);
- }).filter(p => {
- // Idk if this is needed but it doesn't hurt to have it
- return window.bonkHost.players.filter(pp=>pp).findIndex(pp => p.childNodes[1].textContent === pp.userName) !== -1;
- }).forEach(p => {
- if(p.classList.contains("bonkhost_playerentry")) return;
- window.bonkHost.playerManagement.addPlayer(p);
- })
- window.bonkHost.updatePlayers();
- break;
- case "updatePings":
- let pings = window.bonkHost.players.filter(e=>e).map(e=>e.ping);
- for(let i = 0; i < [...document.getElementById("hostPlayerMenuBox").children].length; i++) {
- document.getElementById("hostPlayerMenuBox").children[i].getElementsByClassName("newbonklobby_playerentry_pingtext")[0].textContent = pings[i] + "ms";
- }
- break;
- }
- return response;
- }
- }
-
- for(const i of Object.keys(window.bonkHost.toolFunctions.networkEngine)) {
- if(typeof window.bonkHost.toolFunctions.networkEngine[i] !== "function") continue;
- const ogFunc = window.bonkHost.toolFunctions.networkEngine[i];
- window.bonkHost.toolFunctions.networkEngine[i] = function() {
- let response = ogFunc.apply(window.bonkHost.toolFunctions.networkEngine, arguments);
- switch(i) {
- case "changeOtherTeam":
- window.bonkHost.playerManagement.movePlayer(arguments[1], arguments[0]);
- break;
- case "changeOwnTeam":
- window.bonkHost.playerManagement.movePlayer(arguments[0]);
- break;
- case "sendMapAdd":
- if(arguments[0].m.dbid !== mapHistory[mapHistoryIndex]?.m.dbid || arguments[0].m.dbv !== mapHistory[mapHistoryIndex]?.m.dbv) {
- mapHistory.splice(0, mapHistoryIndex);
- mapHistoryIndex = 0;
- mapHistory.unshift(arguments[0]);
- }
- updateMapHistoryButtons();
- break;
- case "destroy":
- window.bonkHost.playerManagement.hide();
- window.bonkHost.playerSus = [];
- break;
- }
- return response;
- }
- }
-
- window.bonkHost.toolFunctions.networkEngine.on("teamLockChange", lock => {
- document.getElementById("hostPlayerMenuTeamlock").checked = lock;
- });
-
- let mapUpdateTimeout;
- window.bonkHost.toolFunctions.networkEngine.on("status", code => {
- if(code === "rate_limit_sma") {
- // A second of delay is hopefully enough. This is needed because map history can easily get ratelimited, so we want to update players with the current map before the game begins.
- clearTimeout(mapUpdateTimeout);
- mapUpdateTimeout = setTimeout(() => {
- if(!isHost()) return;
- window.bonkHost.toolFunctions.networkEngine.sendMapAdd(window.bonkHost.toolFunctions.getGameSettings().map);
- }, 1000);
- }
- });
-
- for(const i of Object.keys(window.bonkHost.toolFunctions)) {
- if(typeof window.bonkHost.toolFunctions[i] !== "function") continue;
- const ogFunc = window.bonkHost.toolFunctions[i];
- window.bonkHost.toolFunctions[i] = function() {
- let response = ogFunc.apply(window.bonkHost.toolFunctions, arguments);
- switch(i) {
- case "recvInputs":
- if(arguments[2] !== "node") break;
- let playerId = arguments[0];
- let packet = arguments[1];
-
- if(!window.bonkHost.playerSus[playerId]) {
- window.bonkHost.playerSus[playerId] = {
- lagHistory: [],
- lagginessHistory: [],
- cheatWarning: false
- }
- }
-
- if(packet.type === "commands") {
- window.bonkHost.playerSus[playerId].cheatWarning = true;
- }
-
- if(window.bonkHost.cheatDetection) {
- let ping = (window.bonkHost.players[playerId].ping + window.bonkHost.players[window.bonkHost.toolFunctions.networkEngine.getLSID()].ping) / 2;
-
- if(isNaN(packet.f - window.bonkHost.fig)) {
- return;
- }
-
- window.bonkHost.playerSus[playerId].lagHistory.push(Math.floor(1000*(1/30)*(packet.f - window.bonkHost.fig)) + ping);
- if(window.bonkHost.playerSus[playerId].lagHistory.length > 20) {
- window.bonkHost.playerSus[playerId].lagHistory.shift();
- }
-
- let avgPingDiff = (window.bonkHost.playerSus[playerId].lagHistory.length > 2) ?
- ((
- window.bonkHost.playerSus[playerId].lagHistory.reduce((a, b) => a+b) -
- Math.max.apply(Math, window.bonkHost.playerSus[playerId].lagHistory) -
- Math.min.apply(Math, window.bonkHost.playerSus[playerId].lagHistory)
- ) / window.bonkHost.playerSus[playerId].lagHistory.length - 2) : 0
-
- if(isNaN(avgPingDiff)) return;
- window.bonkHost.playerSus[playerId].lagginessHistory.push(avgPingDiff);
-
- window.bonkHost.drawLagginess(playerId);
- }
- break;
- }
- return response;
- }
- }
-
- for(const i of Object.keys(window.bonkHost.stateFunctions)) {
- if(typeof window.bonkHost.stateFunctions[i] !== "function") continue;
- const ogFunc = window.bonkHost.stateFunctions[i];
- window.bonkHost.stateFunctions[i] = function() {
- let response = ogFunc.apply(window.bonkHost.stateFunctions, arguments);
- switch(i) {
- case "go":
- case "goInProgress":
- window.bonkHost.handleHostChange(false);
- window.bonkHost.playerManagement.canBeVisible = true;
- window.bonkHost.menuFunctions.visible = true;
- window.bonkHost.menuFunctions.updatePlayers();
- window.bonkHost.playerManagement.show();
- document.getElementById("hostPlayerMenuTeamlock").checked = window.bonkHost.toolFunctions.getGameSettings().tl;
- break;
- }
- return response;
- }
- }
- }, 50);
- }
-
-
- const chatHandler = e => {
- if(e.keyCode === 13) {
- if(e.target.value.length > 0) {
- if(e.target.value[0] === "/") {
- let command = e.target.value.split(" ")[0].substring(1);
- let args = e.target.value.split(" ").slice(1);
- newArgs = [];
- for(let i = 0; i < args.length; i++) {
- if(args[i][0] === '"' && args[i][args[i].length - 1] !== '"') {
- let str = args[i];
- for(let j = i + 1; j < args.length; j++) {
- str += " " + args[j];
- if(args[j][args[j].length - 1] === '"') {
- i = j;
- break;
- }
- }
- newArgs.push(str.substring(1, str.length - 1));
- }
- else if(args[i][0] === '"' && args[i][args[i].length - 1] === '"') {
- newArgs.push(args[i].substring(1, args[i].length - 1));
- }
- else {
- newArgs.push(args[i]);
- }
- }
- args = newArgs;
- // Save without reference
- let oldMsg = e.target.value + "";
- e.target.value = "";
- if(command == "hhelp") {
- window.bonkHost.menuFunctions.showStatusMessage("/balance * -100 to 100 -- Balances everyone","#b53030",false);
- window.bonkHost.menuFunctions.showStatusMessage("/balanceall -100 to 100 -- Balances everyone","#b53030",false);
- window.bonkHost.menuFunctions.showStatusMessage("/scoreboard -- Shows the scoreboard from the last game","#b53030",false);
- window.bonkHost.menuFunctions.showStatusMessage("/start -- Starts the game","#b53030",false);
- window.bonkHost.menuFunctions.showStatusMessage("/freejoin on/off -- Lets people join during the game","#b53030",false);
- window.bonkHost.menuFunctions.showStatusMessage('/host "user name" -- Gives host to the player',"#b53030",false);
- window.bonkHost.menuFunctions.showStatusMessage('/ban "user name" -- Kicks the player and prevents them from joining with the same account',"#b53030",false);
- window.bonkHost.menuFunctions.showStatusMessage('/unban "user name" -- Unbans the player but doesn\'t remove kicked status',"#b53030",false);
- window.bonkHost.menuFunctions.showStatusMessage('/bans -- Lists banned players',"#b53030",false);
- window.bonkHost.menuFunctions.showStatusMessage('/resetpos -- Resets host menu position',"#b53030",false);
- }
- else if(command == "start") {
- if(!isHost()) {
- window.bonkHost.menuFunctions.showStatusMessage("* Must be room host to use this command", "#b53030", false);
- return;
- }
- window.bonkHost.startGame();
- }
- else if(command == "freejoin") {
- if(args.length == 0) {
- window.bonkHost.freejoin = !window.bonkHost.freejoin;
- }
- else if(["true", "on", "yes", "enable"].includes(args[0])) {
- window.bonkHost.freejoin = true;
- }
- else if(["false", "off", "no", "disable"].includes(args[0])) {
- window.bonkHost.freejoin = false;
- }
- window.bonkHost.menuFunctions.showStatusMessage("* Freejoin " + (window.bonkHost.freejoin ? "on" : "off"), "#b53030", false);
- document.getElementById('hostPlayerMenuFreejoin').checked = window.bonkHost.freejoin;
- }
- else if(command == "host") {
- if(args.length === 0) {
- window.bonkHost.menuFunctions.showStatusMessage(`* Usage: /${command} "user name"`, "#b53030", false);
- return;
- }
- if(!isHost()) {
- window.bonkHost.menuFunctions.showStatusMessage("* Must be room host to use this command", "#b53030", false);
- return;
- }
- let id = window.bonkHost.players.findIndex(e => {return e && e.userName === args[0]});
- if(id !== -1) {
- window.bonkHost.toolFunctions.networkEngine.sendHostChange(id);
- }
- else {
- window.bonkHost.menuFunctions.showStatusMessage("* Giving host failed, username " + args[0] + " not found in this room", "#b53030", false);
- }
- }
- else if(command == "ban") {
- if(args.length === 0) {
- window.bonkHost.menuFunctions.showStatusMessage(`* Usage: /${command} "user name"`, "#b53030", false);
- return;
- }
- window.bonkHost.ban(args[0]);
- }
- else if(command == "unban") {
- if(args.length === 0) {
- window.bonkHost.menuFunctions.showStatusMessage(`* Usage: /${command} "user name"`, "#b53030", false);
- return;
- }
- if(!window.bonkHost.bans.includes(args[0])) {
- window.bonkHost.menuFunctions.showStatusMessage(`* Username ${args[0]} not found in ban list`, "#b53030", false);
- return;
- }
- window.bonkHost.menuFunctions.showStatusMessage(`* Removing ${args[0]} from ban list`, "#b53030", false);
- window.bonkHost.bans.splice(window.bonkHost.bans.indexOf(args[0]), 1);
- }
- else if(command == "bans") {
- window.bonkHost.menuFunctions.showStatusMessage("* List of banned players:\n" + window.bonkHost.bans.join("\n"), "#b53030", false);
- }
- else if((command == "balance" && args[0] === "*") || command == "balanceall") {
- if(args.length === 0) {
- window.bonkHost.menuFunctions.showStatusMessage(`* Usage: /${command} "user name"`, "#b53030", false);
- return;
- }
- if(!isHost()) {
- window.bonkHost.menuFunctions.showStatusMessage("* Must be room host to use this command", "#b53030", false);
- return;
- }
- let amount = parseInt(args[args.length - 1]);
- if(amount < -100 || amount > 100 || isNaN(amount)) {
- window.bonkHost.menuFunctions.showStatusMessage("* Balance must be between -100 and 100", "#b53030", false);
- return;
- }
- for(let i = 0; i < window.bonkHost.players.length; i++) {
- window.bonkHost.gameInfo[2].bal[i] = amount;
- window.bonkHost.toolFunctions.networkEngine.sendBalance(e, amount);
- };
- if(amount != 0) {
- window.bonkHost.menuFunctions.showStatusMessage("* Buff/nerf changed for all players", "#b53030", false);
- }
- else {
- window.bonkHost.menuFunctions.showStatusMessage("* Buff/nerf reset for all players", "#b53030", false);
- }
- if (window.bonkHost.menuFunctions) {
- window.bonkHost.menuFunctions.updateGameSettings();
- window.bonkHost.menuFunctions.updatePlayers();
- }
- }
- else if(command == "scoreboard") {
- if(window.bonkHost.toolFunctions.getGameSettings().ga === "b") {
- const players = document.getElementById("ingamewinner_scores_left").textContent.slice(0, -1).split(":\r\n");
- const scores = document.getElementById("ingamewinner_scores_right").textContent.split("\r\n");
- const longestScore = scores.reduce((a, b) => {return a.length > b.length ? a : b}).length;
- window.bonkHost.menuFunctions.showStatusMessage("* Scoreboard from the last game:", "#b53030", true);
-
- for(let i = 0; i < players.length; i++) {
- // \u2007 is a figure space (witdh of one digit)
- window.bonkHost.menuFunctions.showStatusMessage(`${scores[i].padStart((longestScore), "\u2007")}\t${players[i]}`, "#b53030", false);
- }
- }
- else if(window.bonkHost.toolFunctions.getGameSettings().ga === "f" && window[BIGVAR].bonkHost.footballState) {
- const scores = window[BIGVAR].bonkHost.footballState.scores.map(s => s.toString());
- const longestScore = (scores[2].length > scores[3].length ? scores[2] : scores[3]).length;
- window.bonkHost.menuFunctions.showStatusMessage(`${scores[3].padStart((longestScore), "\u2007")}\tBLUE TEAM`, "#b53030", false);
- window.bonkHost.menuFunctions.showStatusMessage(`${scores[2].padStart((longestScore), "\u2007")}\tRED TEAM`, "#b53030", false);
- }
- }
- else if(command == "resetpos") {
- document.getElementById("hostPlayerMenu").style.removeProperty("top");
- document.getElementById("hostPlayerMenu").style.removeProperty("bottom");
- document.getElementById("hostPlayerMenu").style.removeProperty("left");
- document.getElementById("hostPlayerMenu").style.removeProperty("right");
- let ls = JSON.parse(localStorage.getItem("bonkHost"));
- ls.position = undefined;
- localStorage.setItem("bonkHost", JSON.stringify(ls));
- }
- else {
- e.target.value = oldMsg;
- }
- }
- }
- }
- }
-
- document.getElementById("newbonklobby_chat_input").addEventListener("keydown", chatHandler, true);
- document.getElementById("ingamechatinputtext").addEventListener("keydown", chatHandler, true);
-
- const chatObserver = new MutationObserver(e => {
- for(let mutation of e) {
- if(mutation.type == "childList") {
- for(let node of mutation.addedNodes) {
- if(node.textContent === "* Accepted commands are listed above ") {
- window.bonkHost.menuFunctions.showStatusMessage(`/hhelp - commands from host mod`, "#b53030", false);
- }
- else if(node.textContent[0] === "*" && node.textContent.endsWith((" has left the game "))) {
- let userName = node.textContent.slice(2).slice(0, -19);
- if(window.bonkHost.playerHistory[userName].guest) return;
- let banButton = document.createElement("span");
- banButton.className = "newbonklobby_mapsuggest_high newbonklobby_chat_link";
- banButton.textContent = "[Click to ban]";
- banButton.style = "color: #b53030 !important;";
- banButton.onclick = () => {
- if(banButton.textContent === "[Click to ban]") {
- window.bonkHost.ban(userName);
- banButton.textContent = "[Click to unban]";
- }
- else {
- window.bonkHost.bans.splice(window.bonkHost.bans.indexOf(userName), 1);
- window.bonkHost.menuFunctions.showStatusMessage(`* Removing ${userName} from ban list`, "#b53030", false);
- banButton.textContent = "[Click to ban]";
- }
- }
- node.appendChild(banButton);
- }
- }
- }
- }
- });
-
- chatObserver.observe(document.getElementById("newbonklobby_chat_content"), {attributes: false, childList: true, subtree: false});
-
- const mapSuggestionModeRegex = newStr.match(/([A-Za-z0-9\$_]{3}\[[0-9]{1,4}\]\[[A-Za-z0-9\$_]{3}(\[[0-9]{1,4}\]){2}\]\([A-Za-z0-9\$_]{3}\[[0-9]{1,4}\]\);){7}if\([A-Za-z0-9\$_]{3}\[[0-9]{1,4}\]\[[A-Za-z0-9\$_]{3}(\[[0-9]{1,4}\]){2}\] > 250/)[0];
-
- let SUGGESTION_MODE_BUTTON = `
- let args = arguments;
- if(!!window.bonkHost.bonkModesObject[args[0].m.mo]) {
- 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";
- smb.onclick = e => {
- smb.parentNode.getElementsByClassName("newbonklobby_mapsuggest_high newbonklobby_chat_link")[0].click();
- window.bonkHost.bonkSetMode(args[0].m.mo);
- };
- ${mapSuggestionModeRegex.split("]")[0] + "]"}.appendChild(space);
- smb.appendChild(document.createTextNode("[" + window.bonkHost.bonkModesObject[args[0].m.mo].lobbyName + "]"));
- ${mapSuggestionModeRegex.split("]")[0] + "]"}.appendChild(smb);
- }
- `;
-
- let APPEND_SUGGESTION_MODE_BUTTON = `
- A7b[31].appendChild(space);
- smb.appendChild(document.createTextNode("[" + r6t[47].modes[A7b[4][I$2[12].suggestID].m.mo].lobbyName + "]"));
- A7b[31].appendChild(smb);
- }
- `;
-
- let modeStuff = newStr.match(/[A-Za-z0-9\$_]{3}\[[0-9]{1,3}\]=class [A-Za-z0-9\$_]{3}\{constructor.{1,400}this\[[A-Za-z0-9\$_]{3}(\[[0-9]{1,3}\]){2}\]=2;/)[0].split("=")[0];
-
- let modesObject =`${modeStuff}.modes`;
-
- window.bonkHost.drawLagginess = (playerId) => {
- if(!window.bonkHost.playerSus[playerId] || !window.bonkHost.playerSus[playerId].lagginessHistory || !window.bonkHost.players[playerId] || window.bonkHost.toolFunctions.networkEngine.getLSID() === playerId) return false;
- let graph = document.getElementById("hostPlayerMenuCheatBox").children[window.bonkHost.players.filter(p=>p).indexOf(window.bonkHost.players[playerId])];
- if(graph.width !== graph.clientWidth && document.getElementById('hostPlayerMenu').style.visibility != "hidden") {
- graph.width = graph.clientWidth;
- }
- while (window.bonkHost.playerSus[playerId].lagginessHistory.length > Math.max(graph.clientWidth, 300)) {
- window.bonkHost.playerSus[playerId].lagginessHistory.shift();
- }
- let ctx = graph.getContext("2d");
- ctx.scale(1, -1);
- ctx.beginPath();
- ctx.clearRect(0, 0, graph.width, graph.height);
- ctx.strokeStyle = "#0f0";
- let lagginessHistory = window.bonkHost.playerSus[playerId].lagginessHistory.slice(-graph.clientWidth);
- let max = Math.max(0, Math.max.apply(Math, lagginessHistory));
- let min = Math.min(-60, Math.min.apply(Math, lagginessHistory)) - max;
- ctx.moveTo(0, (lagginessHistory[0] - max) / min * graph.height);
- for(let i = 1; i < lagginessHistory.length; i++) {
- ctx.lineTo(i, (lagginessHistory[i] - max) / min * graph.height);
- }
- ctx.stroke();
- for(let i = 1; i < 11; i++) {
- if (min - Math.abs(max) < -5 - i * graph.height) {
- ctx.beginPath();
- ctx.strokeStyle = "#f00";
- ctx.moveTo(0, (-5 - i*graph.height - max) / min * graph.height);
- ctx.lineTo(300, (-5 - i*graph.height - max) / min * graph.height);
- ctx.stroke();
- }
- else {
- break;
- }
- }
- if(window.bonkHost.playerSus[playerId].cheatWarning) {
- ctx.font = "16px monospace";
- ctx.fillText("⚠️", 0, 16);
- }
- if(window.bonkHost.playerSus[playerId].lagginessHistory === undefined || !window.bonkHost.players[playerId] || window.bonkHost.toolFunctions.networkEngine.getLSID() === playerId) {
- ctx.clearRect(0, 0, graph.width, graph.height);
- }
- return true;
- }
-
- window.bonkHost.modeDropdownCreated = false;
- window.bonkHost.createModeDropdown = () => {
- if (window.bonkHost.modeDropdownCreated) return;
- window.bonkHost.modeDropdownCreated = true;
- const dropdown = document.createElement("div");
- dropdown.classList = "newbonklobby_settings_button brownButton brownButton_classic buttonShadow";
- const mds = dropdown.style;
- mds.color = "#ffffff";
- mds.position = "absolute";
- mds.right = "15px";
- mds.bottom = "55px";
- mds.display = "flex";
- mds.textAlign = "center";
- mds.flexDirection = "column-reverse";
-
- document.getElementById("newbonklobby_modebutton").remove();
- let title = document.createElement("div");
- title.classList = "dropdown_classic";
- title.innerText = "Mode";
- 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.bonkHost.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.bonkHost.bonkModesObject[mode].lobbyName;
- option.onclick = (e) => {
- window.bonkHost.bonkSetMode(mode);
- toggleVisibility(e);
- };
- options.push(option);
- dropdown.appendChild(option);
- }
-
- title.addEventListener("click", toggleVisibility);
-
- document.getElementById("newbonklobby_settingsbox").appendChild(dropdown);
- };
-
- let stateCreationString = newStr.match(/[A-Za-z]\[...(\[[0-9]{1,4}\]){2}\]\(\[\{/)[0];
- let stateCreationStringIndex = stateCreationString.match(/[0-9]{1,4}/g);
- stateCreationStringIndex = stateCreationStringIndex[stateCreationStringIndex.length - 1];
- let stateCreation = newStr.match(`[A-Za-z0-9\$_]{3}\[[0-9]{1,3}\]=[A-Za-z0-9\$_]{3}\\[[0-9]{1,4}\\]\\[[A-Za-z0-9\$_]{3}\\[[0-9]{1,4}\\]\\[${stateCreationStringIndex}\\]\\].+?(?=;);`)[0];
- stateCreationString = stateCreation.split(']')[0] + "]";
-
- const SET_STATE = `
- if (
- ${BIGVAR}.bonkHost.state &&
- window.bonkHost.keepState &&
- window.bonkHost.toolFunctions.getGameSettings().map.s.re &&
- window.bonkHost.toolFunctions.getGameSettings().ga === "b" &&
- ${BIGVAR}.bonkHost.state.mm.dbid == window.bonkHost.toolFunctions.getGameSettings().map.m.dbid &&
- ${BIGVAR}.bonkHost.state.mm.dbv == window.bonkHost.toolFunctions.getGameSettings().map.m.dbv
- ) {
- for(let i = 0; i < ${BIGVAR}.bonkHost.state.discs.length; i++) {
- if(${BIGVAR}.bonkHost.state.discs[i] != undefined) {
- if(${BIGVAR}.bonkHost.state.discs[i].team !== window.bonkHost.players[i].team) {
- let discInfo = JSON.parse(JSON.stringify(${stateCreationString}.discs[i]));
- ${stateCreationString}.discs[i] = ${BIGVAR}.bonkHost.state.discs[i];
- ${stateCreationString}.discs[i].sx = discInfo.sx;
- ${stateCreationString}.discs[i].sy = discInfo.sy;
- ${stateCreationString}.discs[i].sxv = discInfo.svx;
- ${stateCreationString}.discs[i].syv = discInfo.syv;
- ${stateCreationString}.discs[i].spawnTeamInfo = discInfo.spawnTeamInfo;
- ${stateCreationString}.discs[i].team = discInfo.team;
- }
- else {
- ${stateCreationString}.discs[i] = ${BIGVAR}.bonkHost.state.discs[i];
- }
- if(window.bonkHost.toolFunctions.getGameSettings().mo=='sp') {
- ${stateCreationString}.discs[i].a1a -= Math.min(2*30, 2*30 - ${BIGVAR}.bonkHost.state.ftu)*3;
- }
- }
- }
- for(let i = 0; i < ${BIGVAR}.bonkHost.state.discDeaths.length; i++) {
- if(${BIGVAR}.bonkHost.state.discDeaths[i] != undefined) {
- ${stateCreationString}.discDeaths[i] = ${BIGVAR}.bonkHost.state.discDeaths[i];
- }
- }
- ${stateCreationString}.physics=${BIGVAR}.bonkHost.state.physics;
- ${stateCreationString}.seed=${BIGVAR}.bonkHost.state.seed;
- ${stateCreationString}.rc=${BIGVAR}.bonkHost.state.rc;
- ${stateCreationString}.rl=${BIGVAR}.bonkHost.state.rl - Math.min(60, 60 - ${BIGVAR}.bonkHost.state.ftu);
- ${stateCreationString}.ftu=60;
- ${stateCreationString}.shk=${BIGVAR}.bonkHost.state.shk;
- ${stateCreationString}.projectiles=${BIGVAR}.bonkHost.state.projectiles;
- ${stateCreationString}.capZones=${BIGVAR}.bonkHost.state.capZones;
- window.bonkHost.keepState=false;
- };
- if(${stateCreationString}.scores.length > 0 && document.getElementById('hostPlayerMenuKeepScores').checked) {
- if(window.bonkHost.toolFunctions.getGameSettings().ga === "b" && ${BIGVAR}.bonkHost.state !== undefined) {
- ${stateCreationString}.scores = ${BIGVAR}.bonkHost.state.scores;
- }
- else if(window.bonkHost.toolFunctions.getGameSettings().ga === "f" && ${BIGVAR}.bonkHost.footballState !== undefined) {
- ${stateCreationString}.scores = ${BIGVAR}.bonkHost.footballState.scores;
- }
- }
- `;
-
- // Step function beginning
- // First 2 score indexes are null if teams are on
- const STEP_BEGIN = `
- {
- let state = arguments[0];
- let gs = arguments[4];
- let updatePlayers = false;
- if(${BIGVAR}.bonkHost.state !== undefined) {
- if(gs.tea) {
- let teams = state.players.filter(p=>p).map(p=>p.team);
- for(let i = 2; i < 7; i++) {
- if(state.scores[i] && state.scores[i] === 0 && !teams.includes(i)) {
- state.scores[i] = null;
- }
- }
- state.scores = [null, null, ...state.scores.slice(2, 6)];
- }
- if(document.getElementById("gamerenderer").style.visibility === "inherit" && ${BIGVAR}.bonkHost.state.players.map(p => p?.team).join() != state.players.map(p => p?.team).join()) {
- updatePlayers = true;
- }
- }
- else {
- updatePlayers = true;
- }
- ${BIGVAR}.bonkHost.state = state;
- if(updatePlayers && window.bonkHost.inGame && !window.bonkHost.toolFunctions.getGameSettings().q) {
- window.bonkHost.menuFunctions.updatePlayers();
- }
- }
- `;
-
- const FOOTBALL_STEP_BEGIN = `
- {
- let state = arguments[0];
- let updatePlayers = false;
- if(${BIGVAR}.bonkHost.footballState !== undefined) {
- if(document.getElementById("gamerenderer").style.visibility === "inherit" && ${BIGVAR}.bonkHost.footballState.players.map(p => p?.team).join() != state.players.map(p => p?.team).join()) {
- updatePlayers = true;
- }
- }
- else {
- updatePlayers = true;
- }
- ${BIGVAR}.bonkHost.footballState = state;
- if(updatePlayers) {
- window.bonkHost.menuFunctions.updatePlayers();
- }
- }
- `;
-
- document.getElementById('hostPlayerMenuFreejoin').addEventListener('change', (e) => {
- window.bonkHost.freejoin = e.target.checked;
- });
-
- document.getElementById('hostPlayerMenuTeamlock').addEventListener('change', () => {
- document.getElementById('newbonklobby_teamlockbutton').onclick();
- });
-
- document.getElementById('hostPlayerMenuCheatDetectionCheckbox').addEventListener('change', (e) => {
- window.bonkHost.cheatDetection = e.target.checked;
- if(window.bonkHost.cheatDetection) {
- document.getElementById('hostPlayerCheatDetection').style.left = "95%";
- document.getElementById('hostPlayerCheatDetection').style.visibility = "visible";
- }
- else {
- document.getElementById('hostPlayerCheatDetection').style.left = "0";
- document.getElementById('hostPlayerCheatDetection').style.visibility = "hidden";
- }
- window.bonkHost.menuFunctions.updatePlayers();
- });
-
- window.bonkHost.handlePlayerJoined = (playerID, playerName, guest) => {
- if(!isHost()) return;
- if(!guest && window.bonkHost.bans.includes(playerName)) {
- window.bonkHost.toolFunctions.networkEngine.banPlayer(playerID);
- return;
- }
- if(window.bonkHost.freejoin) {
- let team = 1;
- if(window.bonkHost.toolFunctions.getGameSettings().tea) {
- let teams = window.bonkHost.players.slice(0, -1).filter(p=>p && p.team > 1).map(p=>p.team);
- if(teams.every(t=>t==teams[0])) {
- team = teams[0];
- }
- else return;
- }
- window.bonkHost.stateFunctions.hostHandlePlayerJoined(playerID, window.bonkHost.players.length, team);
- }
- }
-
- window.bonkHost.ban = (playerName) => {
- if(window.bonkHost.bans.includes(playerName)) {
- window.bonkHost.menuFunctions.showStatusMessage("* " + playerName + " is already banned", "#b53030", false);
- return;
- }
- let id = window.bonkHost.players.findIndex(e => {return e && e.userName === playerName});
- if(id !== -1 && isHost()) {
- if(window.bonkHost.players[id].guest) {
- window.bonkHost.menuFunctions.showStatusMessage("* Banning guests doesn't work, so they'll get kicked instead", "#b53030", false);
- }
- else {
- window.bonkHost.bans.push(playerName);
- }
- window.bonkHost.toolFunctions.networkEngine.banPlayer(id);
- }
- else if(id !== -1) {
- window.bonkHost.menuFunctions.showStatusMessage(`* You're not room host, but ${playerName} will be added to ban list`, "#b53030", false);
- window.bonkHost.bans.push(playerName);
- }
- else {
- window.bonkHost.menuFunctions.showStatusMessage(`* Username ${playerName} not found in this room, but they'll be added to ban list`, "#b53030", false);
- window.bonkHost.bans.push(playerName);
- }
- }
-
-
- window.bonkHost.playerManagement.addPlayer = (playerEntry) => {
- for(let player of window.bonkHost.players.filter(p=>p)) {
- window.bonkHost.playerHistory[player.userName] = player;
- }
- 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();
- if(isHost()) {
- playerEntry.addEventListener('click', (e) => {
- let menu = document.getElementsByClassName("newbonklobby_playerentry_menu")[0];
- banButton = document.createElement("div");
- banButton.classList = "newbonklobby_playerentry_menu_button brownButton brownButton_classic buttonShadow";
- banButton.innerHTML = "BAN";
- banButton.onclick = () => {
- if(banButton.innerHTML == "BAN") {
- banButton.innerHTML = "SURE?";
- return;
- }
- window.bonkHost.ban(playerEntry.children[1].textContent);
- menu.style.display = "none";
- };
- for(let child of menu.childNodes) {
- if(child.textContent == "KICK") {
- menu.insertBefore(banButton, child.nextSibling);
- break;
- }
- }
- });
- }
- newPlayerEntry.onclick = e => {
- playerEntry.click();
- let menu = document.getElementsByClassName("newbonklobby_playerentry_menu")[0];
- document.getElementById("hostPlayerMenuBox").parentNode.appendChild(menu);
- newPlayerEntry.playerElement=playerEntry;
- menu.style.removeProperty("left");
- menu.style.right=0;
- menu.style.top=([...playerEntry.parentNode.children].indexOf(playerEntry))*43+"px";
- }
- newPlayerEntry.onmouseenter = playerEntry.onmouseenter;
-
- // Make spectators transparent
- let playerId = window.bonkHost.players.findIndex(p => p && (p.userName === newPlayerEntry.childNodes[1].textContent));
- if(
- !(window.bonkHost.toolFunctions.getGameSettings().ga === "b" && window[BIGVAR].bonkHost.state?.players[playerId]) &&
- !(window.bonkHost.toolFunctions.getGameSettings().ga === "f" && window[BIGVAR].bonkHost.footballState?.players[playerId])
- ) {
- newPlayerEntry.style.filter = "opacity(0.4)";
- }
-
- // Listen for skin render
- let observer = new MutationObserver((mutations) => {
- mutations.forEach((mutation) => {
- // New child
- mutation.addedNodes.forEach((node) => {
- newPlayerEntry.firstChild.appendChild(node.cloneNode(true));
- observer.disconnect();
- });
- });
- });
- observer.observe(playerEntry.children[0], { childList: true });
- hostPlayerMenuBox.appendChild(newPlayerEntry);
- for(let i = 0; i < [...document.getElementById("hostPlayerMenuCheatBox").children].length; i++) {
- let graph = document.getElementById("hostPlayerMenuCheatBox").children[i];
- let playerId = window.bonkHost.players.indexOf(window.bonkHost.players.filter(p=>p)[i]);
- if(!window.bonkHost.drawLagginess(playerId)) {
- let ctx = graph.getContext("2d");
- ctx.scale(1, -1);
- ctx.clearRect(0, 0, graph.width, graph.height);
- }
- }
- }
-
- window.bonkHost.playerManagement.removePlayer = (playerEntry) => {
- let foundPlayerEntry = window.bonkHost.playerManagement.getPlayer(playerEntry);
- if(foundPlayerEntry) {
- hostPlayerMenuBox.removeChild(foundPlayerEntry);
- }
- }
-
- window.bonkHost.playerManagement.show = () => {
- if(!window.bonkHost.playerManagement.canBeVisible || document.getElementById("gamerenderer").style.visibility != "inherit") return;
- if(parent.document.getElementById('adboxverticalleftCurse') != null)
- parent.document.getElementById('adboxverticalleftCurse').style.display = "none";
- document.getElementById("hostPlayerMenuKeepPositions").parentNode.parentNode.style.filter = (window.bonkHost.toolFunctions.getGameSettings().map.s.re ? "" : "brightness(0.5)");
- document.getElementById("hostPlayerMenuKeepPositions").style.pointerEvents = (window.bonkHost.toolFunctions.getGameSettings().map.s.re ? "" : "none");
- document.getElementById("hostPlayerMenuRespawningRequiredWarning").style.display = (window.bonkHost.toolFunctions.getGameSettings().map.s.re ? "none" : "");
- document.getElementById('hostPlayerMenu').style.display = "unset";
- window.bonkHost.menuFunctions.updatePlayers();
- window.bonkHost.inGame = true;
- for(let graph of [...document.getElementById("hostPlayerMenuCheatBox").children]) {
- let ctx = graph.getContext("2d");
- ctx.scale(1, -1);
- ctx.clearRect(0, 0, graph.width, graph.height);
- }
- }
-
- window.bonkHost.playerManagement.hide = () => {
- window.bonkHost.inGame = false;
- document.getElementById('hostPlayerMenu').style.display = "none";
- if(parent.document.getElementById('adboxverticalleftCurse') != null)
- parent.document.getElementById('adboxverticalleftCurse').style.removeProperty("display");
- }
-
- // Can be called in other situations too
- window.bonkHost.handleHostChange = (host) => {
- document.getElementById("hostPlayerMenuRestartButton").classList.toggle("brownButtonDisabled", !host);
- document.getElementById("hostPlayerMenuTeamlock").classList.toggle("brownButtonDisabled", !host);
- updateMapHistoryButtons();
- if(!host) {
- mapHistory = [];
- mapHistoryIndex = 0;
- }
- }
-
- window.bonkHost.playerManagement.collapse = (saveToLocalStorage = true) => {
- 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);
- }
- if(saveToLocalStorage) {
- let ls = JSON.parse(localStorage.getItem("bonkHost"));
- ls.collapse = (document.getElementById('hostPlayerMenu').style.visibility == "hidden");
- localStorage.setItem("bonkHost", JSON.stringify(ls));
- }
- }
-
- if(JSON.parse(localStorage.getItem("bonkHost")).collapse) {
- window.bonkHost.playerManagement.collapse(false);
- }
-
- {
- let position = JSON.parse(localStorage.getItem("bonkHost")).position;
- if(position !== undefined) {
- document.getElementById("hostPlayerMenu").style.left = position.left;
- document.getElementById("hostPlayerMenu").style.right = position.right;
- document.getElementById("hostPlayerMenu").style.top = position.top;
- document.getElementById("hostPlayerMenu").style.bottom = position.bottom;
- }
- }
-
- // Host menu mover
-
- let startGrabPoint = {x:0,y:0};
- let grabbing = false;
- const hostMenuMover = e => {
- if(e.x - startGrabPoint.x < document.body.clientWidth / 2) {
- document.getElementById("hostPlayerMenu").style.left = e.x + startGrabPoint.x - document.getElementById("hostPlayerMenu").clientWidth;
- document.getElementById("hostPlayerMenu").style.right = "unset";
- }
- else {
- document.getElementById("hostPlayerMenu").style.right = document.body.clientWidth - e.x - startGrabPoint.x;
- document.getElementById("hostPlayerMenu").style.left = "unset";
- }
-
- if(e.y - startGrabPoint.y < document.body.clientHeight / 2) {
- document.getElementById("hostPlayerMenu").style.top = e.y - startGrabPoint.y;
- document.getElementById("hostPlayerMenu").style.bottom = "unset";
- }
- else {
- document.getElementById("hostPlayerMenu").style.bottom = document.body.clientHeight - e.y + startGrabPoint.y - document.getElementById("hostPlayerMenu").clientHeight;
- document.getElementById("hostPlayerMenu").style.top = "unset";
- }
- }
-
- window.bonkHost.playerManagement.startGrab = e => {
- grabbing = true;
- document.getElementById("hostPlayerMenuGrab").style.cursor = "grabbing"
- document.getElementById("hostPlayerMenu").style.transition = "unset";
- startGrabPoint.x = e.offsetX;
- startGrabPoint.y = e.offsetY;
- document.body.addEventListener("pointermove", hostMenuMover);
- }
-
- window.bonkHost.playerManagement.endGrab = e => {
- if(!grabbing) return;
- grabbing = false;
- document.getElementById("hostPlayerMenuGrab").style.cursor = "grab";
- document.getElementById("hostPlayerMenu").style.removeProperty("transition");
- document.body.removeEventListener("pointermove", hostMenuMover);
- let ls = JSON.parse(localStorage.getItem("bonkHost"));
- ls.position = {
- left: document.getElementById("hostPlayerMenu").style.left,
- right: document.getElementById("hostPlayerMenu").style.right,
- top: document.getElementById("hostPlayerMenu").style.top,
- bottom: document.getElementById("hostPlayerMenu").style.bottom
- };
- localStorage.setItem("bonkHost", JSON.stringify(ls));
- }
-
- document.getElementById("hostPlayerMenuGrab").addEventListener("pointerdown", window.bonkHost.playerManagement.startGrab);
- document.body.addEventListener("pointerup", window.bonkHost.playerManagement.endGrab);
-
- // Helper functions
-
- 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 = (team, playerID = window.bonkHost.toolFunctions.networkEngine.getLSID()) => {
- if(!window.bonkHost.players[playerID] || !window.bonkHost.inGame || !isHost() || window.bonkHost.toolFunctions.getGameSettings().q) return;
- window.bonkHost.menuFunctions.visible = true;
- if(team > 0)
- window.bonkHost.stateFunctions.hostHandlePlayerJoined(playerID, window.bonkHost.players.length, team);
- else
- window.bonkHost.stateFunctions.hostHandlePlayerLeft(playerID);
- window.bonkHost.menuFunctions.updatePlayers();
- }
-
- window.bonkHost.startGame = () => {
- window.bonkHost.keepState = document.getElementById("hostPlayerMenuKeepPositions").checked;
- for(let callback of Object.keys(window.bonkHost.bonkCallbacks)) {
- window.bonkHost.bonkCallbacks[callback]("startGame");
- }
- }
-
- // Fisher–Yates shuffle
- const shuffle = (array) => {
- let currentIndex = array.length, randomIndex;
-
- // While there remain elements to shuffle.
- while (currentIndex != 0) {
- // Pick a remaining element.
- randomIndex = Math.floor(Math.random() * currentIndex);
- currentIndex--;
-
- // And swap it with the current element.
- [array[currentIndex], array[randomIndex]] = [
- array[randomIndex], array[currentIndex]];
- }
- return array;
- }
-
- window.bonkHost.shufflePlayers = () => {
- document.getElementById("teamshufflebox").style.visibility = "hidden";
-
- //Players per team
- let ppt = document.getElementById("teamshuffleppt").value;
- let teams = 0;
- for(let team of ["red", "blue", "yellow", "green"]) {
- if(document.getElementById("team_shuffle_"+team).checked) {
- teams++;
- }
- }
- if(ppt === "AUTO") {
- ppt = Math.ceil(window.bonkHost.players.length / teams);
- }
- let shuffledPlayers = shuffle(window.bonkHost.players);
- for(let team of ["red", "blue", "yellow", "green"]) {
- if(document.getElementById("team_shuffle_"+team).checked) {
- for(let i = 0; i < ppt; i++) {
- window.bonkHost.toolFunctions.networkEngine.changeOtherTeam(window.bonkHost.players.indexOf(shuffledPlayers.pop()), ["red", "blue", "yellow", "green"].indexOf(team)+2);
- }
- }
- }
- }
-
- let mapSelectionObserver = new MutationObserver(mutations => {
- for(let mutation of mutations) {
- for(let e of mutation.addedNodes) {
- let mode = e.getElementsByClassName('maploadwindowtextmode')[0];
- if(mode === undefined) mode = e.getElementsByClassName('maploadwindowtextmode_picks')[0];
- if(mode === undefined) return;
- 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.bonkHost.bonkSetMode(Object.entries(window.bonkHost.bonkModesObject).filter(e => {return e[1].lobbyName === mode.textContent})[0][0]);
- }
- });
- }
- }
- });
- mapSelectionObserver.observe(document.getElementById('maploadwindowmapscontainer'), {attributes: false, childList: true, subtree: false});
-
- /*Autocomplete*/
-
- const autocomplete = 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) {
- if(chatText[0] !== "/unban") {
- for (let j = 0; j < window.bonkHost.players.filter(p=>p).length; j++) {
- for (let k = i; k >= 0; k--) {
- if (window.bonkHost.players.filter(p=>p).map(p=>p.userName)[j].toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, '\\$&').match("^" + chatText.slice(k, i + 1).join(" ").toLowerCase().replace(/"/g, "").replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))) {
- foundAutocompletes.push(window.bonkHost.players.filter(p=>p).map(p=>p.userName)[j]);
- foundAutocompletesOffsets.push(k);
- }
- }
- }
- }
- else {
- for (let j = 0; j < window.bonkHost.bans.length; j++) {
- for (let k = i; k >= 0; k--) {
- if (window.bonkHost.bans[j].toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, '\\$&').match("^" + chatText.slice(k, i + 1).join(" ").toLowerCase().replace(/"/g, "").replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))) {
- foundAutocompletes.push(window.bonkHost.bans[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++) {
- if(char === undefined) break;
- 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;
- }
- }
- }
- };
- document.getElementById("newbonklobby_chat_input").addEventListener("keydown", autocomplete, true);
- document.getElementById("ingamechatinputtext").addEventListener("keydown", autocomplete, true);
-
- (() => {
- let selectedPlayer = null;
- let start = [], end = [];
- const wheelSize = 150;
- let oldAngle = null;
- const innerWheelRadius = (wheelSize/26.458)/2*8.5;
- window.bonkHost.updatePlayers = () => {
- [...document.getElementsByClassName("newbonklobby_playerentry")].filter(e => {
- return ["newbonklobby_playerbox_leftelementcontainer",
- "newbonklobby_playerbox_rightelementcontainer",
- "newbonklobby_playerbox_elementcontainer",
- "newbonklobby_specbox_elementcontainer",
- "hostPlayerMenuBox"].includes(e.parentNode.id);
- }).forEach(e => {
- e.addEventListener("mousedown", mouse => {
- if(isHost() || (e.children[1].textContent === window.bonkHost.players[window.bonkHost.toolFunctions.networkEngine.getLSID()].userName && !window.bonkHost.inGame)) {
- selectedPlayer = e;
- start = [mouse.clientY, mouse.clientX];
- }
- });
- e.addEventListener("click", mouse => {
- if(!isHost() && e.children[1].textContent === window.bonkHost.players[window.bonkHost.toolFunctions.networkEngine.getLSID()].userName && window.bonkHost.inGame) {
- mouse.stopImmediatePropagation();
- }
- }, true);
- });
- }
- document.addEventListener("mousemove", mouse => {
- if(selectedPlayer) {
- document.body.style.pointerEvents = "none";
- let wheelType = (!window.bonkHost.toolFunctions.getGameSettings().tea) ? "selectionWheel" : "selectionWheelTeams";
- document.getElementById(wheelType).style.display = "block";
- 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(!window.bonkHost.toolFunctions.getGameSettings().tea) {
- 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];
- const sendTeamChange = (i, team) => {
- if(i == window.bonkHost.toolFunctions.networkEngine.getLSID()) {
- window.bonkHost.toolFunctions.networkEngine.changeOwnTeam(team);
- }
- else {
- window.bonkHost.toolFunctions.networkEngine.changeOtherTeam(i, team);
- }
- }
- if(Math.sqrt((end[0]-start[0])**2 + (end[1]-start[1])**2) >= innerWheelRadius) {
- if(!window.bonkHost.toolFunctions.getGameSettings().tea) {
- for(let child of [...document.getElementById("selectionWheel").children[0].children]) {
- child.children[0].style.opacity = 0.5;
- }
- sendTeamChange(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));
- sendTeamChange(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 => {
- let selectedPlayer = (mouse.buttons !== 0 ? selectedPlayer : null);
- if(!selectedPlayer) {
- changeTeam(mouse);
- }
- });
- })();
- let patchCounter = 0;
- const patch = (a, b) => {
- let c = newStr;
- newStr = newStr.replace(a, b);
- /*console.log(`Patch ${patchCounter++}: ${c === newStr ? 'fail' : 'success'}`);
- if(c === newStr) {
- console.log(`Failed to patch ${a} with ${b}`);
- }*/
- return c !== newStr;
- }
-
- //Remove round limit
- document.getElementById('newbonklobby_roundsinput').removeAttribute("maxlength");
- patch(/[A-Za-z0-9\$_]{3}\[[0-9]{1,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}\]\]\(Math\[[A-Za-z0-9\$_]{3}\[[0-9]{1,3}\]\[[0-9]{1,3}\]\]\(1,[A-Za-z0-9\$_]{3}\[[0-9]{1,3}\]\[[0-9]{1,3}\]\[[A-Za-z0-9\$_]{3}\[[0-9]{1,3}\]\[[0-9]{1,3}\]\]\),9\);/, '');
- const roundVal = newStr.match(/[A-Za-z0-9\$_]{3}\[[0-9]{1,4}\]=parseInt\([A-Za-z0-9\$_]{3}(\[0\]){2}\[[A-Za-z0-9\$_]{3}(\[[0-9]{1,4}\]){2}\]\)\;/)[0];
- const roundValVar = roundVal.split('=')[0];
- patch(roundVal, `${roundValVar}=parseInt(document.getElementById('newbonklobby_roundsinput').value);if(isNaN(${roundValVar}) || ${roundValVar} <= 0){return;}`);
-
- //Mode selection menu. Custom patch
- let lastTarget = newStr.match(/editorCanTarget:(true|false)\};/g)
- lastTarget = lastTarget[lastTarget.length - 1];
- newStr = newStr.split(lastTarget);
-
- newStr[newStr.length - 1] = `
- window.bonkHost.bonkModesObject=${modesObject};
- window.bonkHost.bonkSetMode = m => {
- if(m === "f") {
- window.bonkHost.gameInfo[2].ga = "f";
- window.bonkHost.gameInfo[2].tea=true;
- window.bonkHost.toolFunctions.networkEngine.sendTeamSettingsChange(window.bonkHost.gameInfo[2].tea);
- }
- else {
- window.bonkHost.gameInfo[2].ga = "b";
- }
- window.bonkHost.gameInfo[2].mo = m;
- window.bonkHost.menuFunctions.updatePlayers();
- window.bonkHost.toolFunctions.networkEngine.sendGAMO(window.bonkHost.gameInfo[2].ga, window.bonkHost.gameInfo[2].mo);
- window.bonkHost.menuFunctions.updateGameSettings();
- }
- window.bonkHost.createModeDropdown();
- ` + newStr[newStr.length - 1];
-
- newStr = newStr.join(lastTarget);
-
- //Add mode button to map suggestion message
- patch(mapSuggestionModeRegex, mapSuggestionModeRegex.split("if")[0] + SUGGESTION_MODE_BUTTON + "if" + mapSuggestionModeRegex.split("if")[1]);
-
- //Internal var
- patch(`function ${BIGVAR}(){}`, `function ${BIGVAR}(){}${BIGVAR}.bonkHost={};`);
-
- /////////////
- //Host menu//
- /////////////
-
- //Save latest state
- const stateRegex = newStr.match(/[A-Za-z]\[[A-Za-z0-9\$_]{3}(\[[0-9]{1,3}\]){2}\]={discs/)[0];
- patch(stateRegex, STEP_BEGIN + stateRegex);
-
- //Football state
- let footballStateRegex = newStr.match(/=\[\];if\(\![A-Za-z0-9\$_]\[[A-Za-z0-9\$_]{3}\[[0-9]{1,3}\]\[[0-9]{1,3}\]\]\)\{/)[0];
- footballStateRegex = footballStateRegex.split(";");
- patch(footballStateRegex.join(";"), footballStateRegex[0] + ";" + FOOTBALL_STEP_BEGIN + footballStateRegex[1]);
-
- //Apply latest state
- const stateSetRegex = newStr.match(/\* 999\),[A-Za-z0-9\$_]{3}\[[0-9]{1,3}\],null,[A-Za-z0-9\$_]{3}\[[0-9]{1,3}\],true\);/)[0];
- patch(stateSetRegex, stateSetRegex + SET_STATE);
-
- //Handle player joins and rebans
- let playerJoinedCustom = newStr.match(/\[\d\],ping:105\};/)[0];
- patch(playerJoinedCustom, playerJoinedCustom+`window.bonkHost.handlePlayerJoined(...arguments);`);
-
- //Joined room
- let connectionMatch = newStr.match(/reconnection:false\}\);/)[0];
- patch(connectionMatch, connectionMatch + `window.bonkHost.bans=[];`);
-
-
- //Get some useful objects
- let menuRegex = newStr.match(/== 13\){...\(\);}}/)[0];
- patch(menuRegex, menuRegex + "window.bonkHost.menuFunctions = this; window.bonkHost.wrap();");
- let toolRegex = newStr.match(/=new [A-Za-z0-9\$_]{1,3}\(this,[A-Za-z0-9\$_]{1,3}\[0\]\[0\],[A-Za-z0-9\$_]{1,3}\[0\]\[1\]\);/);
- patch(toolRegex, toolRegex + "window.bonkHost.toolFunctions = this;");
- let infoRegex = newStr.match(/[A-Za-z0-9\$_]{3}\[[0-9]{1,3}\]=\{id:-1,element:null\};/)[0];
- patch(infoRegex, infoRegex + "window.bonkHost.gameInfo = arguments;");
- patch("newbonklobby_votewindow_close", "window.bonkHost.players = arguments[1];" + "newbonklobby_votewindow_close");
- // state handling
- patch("{a:0.0};", "{a:0.0};" + `window.bonkHost.stateFunctions = this;`);
-
- //Big class
- let bigClass = newStr.match(/[A-Z]\[[A-Za-z0-9\$_]{1,3}\[[0-9]+\]\[[0-9]+\]\]\([A-Za-z0-9\$_]{1,3}\[0\]\[0\]\);[A-Za-z0-9\$_]{1,3}\[[0-9]+\]\[[A-Za-z0-9\$_]{1,3}\[[0-9]+\]\[[0-9]+\]\]\([A-Za-z0-9\$_]{1,3}\[[0-9]+\],{m:/)[0][0];
- patch(`function ${bigClass}(){}`, `function ${bigClass}(){};window.bonkHost.bigClass=${bigClass};`);
-
- //Function for all callbacks
- let callbacks = [...newStr.match(/[A-Za-z0-9\$_]{3}\(\.\.\./g)];
- for(let callback of callbacks) {
- patch(`function ${callback}`, `window.bonkHost.bonkCallbacks["${callback.split("(")[0]}"] = ${callback.split("(")[0]};` + `function ${callback}`);
- }
-
- //Frames in game
- let fig = newStr.match(/\[[A-Za-z0-9\$_]{3}\[[0-9]{1,3}\] \- 30\]/)[0].split(' ')[0].slice(1);
- patch(`${fig}++;`, `${fig}++;window.bonkHost.fig=${fig};`);
- 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");