您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Have a better UI interface!
// ==UserScript== // @name Bonk Panel // @version 0.4.2 // @author KOOKY WARIROR // @description Have a better UI interface! // @match https://bonk.io/gameframe-release.html // @icon https://bonk.io/graphics/tt/favicon-32x32.png // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/split.js/1.6.5/split.min.js // @license MIT // @namespace https://greasyforks.org/users/999838 // @grant none // ==/UserScript== /* Features --------------------- - Command Helper (type "/" and it will show up) - Show scores and rounds to win when in game - Show system chat in game - Show players in game - Import skin - Image overlay - Choose Hex Colour (Skin Editor) And more... (discover it urself🕵️♀️) */ // SKINS class BYTEBUFFER { constructor() { this.index = 0 this.buffer = new ArrayBuffer(102400) this.view = new DataView(this.buffer) this.implicitClassAliasArray = [] this.implicitStringArray = [] this.bodgeCaptureZoneDataIdentifierArray = [] } readByte() { let returnval = this.view.getUint8(this.index) this.index += 1 return returnval } writeByte(val) { this.view.setUint8(this.index, val) this.index += 1 } readInt() { let returnval = this.view.getInt32(this.index) this.index += 4 return returnval } writeInt(val) { this.view.setInt32(this.index, val) this.index += 4 } readShort() { let returnval = this.view.getInt16(this.index) this.index += 2 return returnval } writeShort(val) { this.view.setInt16(this.index, val) this.index += 2 } readBoolean() { return this.readByte() == 1 } writeBoolean(val) { if (val) { this.writeByte(1) } else { this.writeByte(0) } } readFloat() { let returnval = this.view.getFloat32(this.index) this.index += 4 return returnval } writeFloat(val) { this.view.setFloat32(this.index, val) this.index += 4 } toBase64() { let tmpstring = "" let tmparray = new Uint8Array(this.buffer) for (let i = 0; i < this.index; i++) { tmpstring += String.fromCharCode(tmparray[i]) } return window.btoa(tmpstring) } fromBase64(val1, val2) { let tmpatob = window.atob(val1) let tmplength = tmpatob.length let tmparray = new Uint8Array(tmplength) for (let i = 0; i < tmplength; i++) { tmparray[i] = tmpatob.charCodeAt(i) } if (val2 === true) { tmparray = window.pako.inflate(tmparray) } this.buffer = tmparray.buffer.slice(tmparray.byteOffset, tmparray.byteLength + tmparray.byteOffset) this.view = new DataView(this.buffer) this.index = 0 } } class AVATAR { constructor() { this.layers = [] this.bc = 4492031 } randomBC(val) { this.bc = val.colors[Math.floor(Math.random() * val.colors.length)] } makeSafe() { if (!(this.bc >= 0 && this.bc <= 16777215)) { this.bc = 4492031 } for (let i = 0; i < this.layers.length; i++) { let layer = this.layers[i] if (layer) { if (!(layer.id >= 1 && layer.id <= 115)) { layer.id = 1 } if (!(layer.x >= -99999 && layer.x <= 99999)) { layer.x = 0 } if (!(layer.y >= -99999 && layer.y <= 99999)) { layer.y = 0 } if (!(layer.scale >= -10 && layer.scale <= 10)) { layer.scale = 0.25 } if (!(layer.angle >= -9999 && layer.angle <= 9999)) { layer.angle = 0 } if (typeof layer.flipX != "boolean") { layer.flipX = false } if (typeof layer.flipY != "boolean") { layer.flipY = false } if (!(layer.color >= 0 && layer.color <= 16777215)) { layer.color = 0 } } } for (let i = 0; i < this.layers.length; i++) { if (this.layers[i] == null) { this.layers.splice(i, 1) i-- } } } fromObject(val) { if (val) { if (val.layers && typeof val.layers == "object" && val.layers.length >= 0 && val.layers.length <= 16) { this.layers = val.layers } this.bc = val.bc } this.makeSafe() } toString() { let tmpbuffer = new BYTEBUFFER() tmpbuffer.writeByte(10) tmpbuffer.writeByte(7) tmpbuffer.writeByte(3) tmpbuffer.writeByte(97) tmpbuffer.writeShort(2) tmpbuffer.writeByte(9) tmpbuffer.writeByte(this.layers.length * 2 + 1) tmpbuffer.writeByte(1) for (let i = 0; i < this.layers.length; i++) { let layer = this.layers[i] tmpbuffer.writeByte(10) if (i == 0) { tmpbuffer.writeByte(7) tmpbuffer.writeByte(5) tmpbuffer.writeByte(97) tmpbuffer.writeByte(108) } else { tmpbuffer.writeByte(5) } tmpbuffer.writeShort(1) tmpbuffer.writeShort(layer.id) tmpbuffer.writeFloat(layer.scale) tmpbuffer.writeFloat(layer.angle) tmpbuffer.writeFloat(layer.x) tmpbuffer.writeFloat(layer.y) tmpbuffer.writeBoolean(layer.flipX) tmpbuffer.writeBoolean(layer.flipY) tmpbuffer.writeInt(layer.color) } tmpbuffer.writeInt(this.bc) return encodeURIComponent(tmpbuffer.toBase64()) } fromString(val) { if (val == "") { return } try { let tmpdecoded = decodeURIComponent(val) let tmpbuffer = new BYTEBUFFER() tmpbuffer.fromBase64(tmpdecoded) function tmpfunction(functionval) { var P5t = [arguments] let tmpobj = {} if (functionval.readByte().toString(16) == "a") { if (functionval.readByte() == 7) { functionval.readByte() functionval.readByte() functionval.readByte() } else { } P5t[3] = functionval.readShort() tmpobj.id = functionval.readShort() tmpobj.scale = functionval.readFloat() tmpobj.angle = functionval.readFloat() tmpobj.x = functionval.readFloat() tmpobj.y = functionval.readFloat() tmpobj.flipX = functionval.readBoolean() tmpobj.flipY = functionval.readBoolean() tmpobj.color = functionval.readInt() } else { tmpobj = null } return tmpobj } let tmpbyte = tmpbuffer.readByte() let tmpbyte2 = tmpbuffer.readByte() let tmpbyte3 = tmpbuffer.readByte() let tmpbyte4 = tmpbuffer.readByte() let tmpbyte5 = tmpbuffer.readByte() let tmpbyteover2 = (tmpbuffer.readByte() - 1) / 2 let tmpbyte6 = tmpbuffer.readByte() while (tmpbyte6 != 1) { let tmpnumber = 0 if (tmpbyte6 == 3) { tmpnumber = tmpbuffer.readByte() - 48 } else { if (tmpbyte6 == 5) { tmpnumber = (tmpbuffer.readByte() - 48) * 10 + (tmpbuffer.readByte() - 48) } } this.layers[tmpnumber] = tmpfunction(tmpbuffer) tmpbyte6 = tmpbuffer.readByte() } for (let i = 0; i < tmpbyteover2; i++) { this.layers[i] = tmpfunction(tmpbuffer) } if (tmpbuffer.readShort() >= 2) { this.bc = tmpbuffer.readInt() } this.makeSafe() } catch (M8n) { this.layers = [] this.bc = 4492031 } } } fetch("https://raw.githubusercontent.com/kookywarrior/bonkio-skins/main/skins.js") .then((response) => response.text()) .then((response) => { eval(response) }) .catch((err) => console.log(err)) // REMOVE ANNOYING STUFF function removeEleByID(id) { let e = window.top.document.getElementById(id) if (e !== null) e.remove() } removeEleByID("descriptioncontainer") removeEleByID("bonk_d_1") removeEleByID("bonk_d_2") window.top.document.body.getElementsByTagName("style")[0].innerHTML += ` #maingameframe { margin: 0 !important; margin-top: 0 !important; } #adboxverticalleftCurse { display: none !important; } #adboxverticalCurse { display: none !important; } #bonkioheader { display: none !important; } body { overflow: hidden !important; }` // FIX CHAT STUFF function hideEleByID(id) { let e = document.getElementById(id) if (e !== null) e.hidden = true } hideEleByID("newbonklobby_chat_lowerline") hideEleByID("newbonklobby_chat_lowerinstruction") hideEleByID("ingamechatbox") hideEleByID("newbonklobby_chat_content") document.getElementById("newbonklobby_chat_content").style.height = "calc(100% - 36px)" document.body.appendChild(document.getElementById("newbonklobby_chat_input")) document.body.appendChild(document.getElementById("ingamechatinputtext")) document.getElementById("newbonklobby_chatbox").getElementsByClassName("newbonklobby_boxtop newbonklobby_boxtop_classic")[0].textContent = "More Coming Soon..." // APPEND FPS TO TOP BAR const FPS = document.createElement("div") FPS.innerText = 0 FPS.style = `color: var(--bonk_theme_top_bar_text, #ffffff8f) !important;font-family:"futurept_b1";line-height:35px;display:inline-block;padding-left:15px;padding-right:15px;` FPS.className = "niceborderright" document.getElementById("pretty_top_bar").appendChild(FPS) function fpsUpdate() { const updateDelay = 500 let lastFpsUpdate = 0 let frames = 0 function updateFPS() { let now = Date.now() let elapsed = now - lastFpsUpdate if (elapsed < updateDelay) { ++frames } else { FPS.innerText = `${Math.round(frames / (elapsed / 1000))} FPS` frames = 0 lastFpsUpdate = now } window.requestAnimationFrame(updateFPS) } lastFpsUpdate = Date.now() window.requestAnimationFrame(updateFPS) } fpsUpdate() // ADD MAIN CONTAINER const container = document.createElement("div") container.id = "bonkpanelcontainer" document.getElementById("pagecontainer").insertBefore(container, document.getElementById("xpbarcontainer")) container.appendChild(document.getElementById("bonkiocontainer")) // ADD PANEL CONTAINER const panelLeft = document.createElement("div") panelLeft.style.visibility = "hidden" panelLeft.className = "panelcontainer" container.insertBefore(panelLeft, document.getElementById("bonkiocontainer")) const panelRight = document.createElement("div") panelRight.style.visibility = "hidden" panelRight.className = "panelcontainer" container.appendChild(panelRight) // ADD PANELS for (let index = 1; index < 5; index++) { const panel = document.createElement("div") panel.id = `panel${index}` panel.className = "panel" const injectTO = index % 2 == 0 ? panelRight : panelLeft injectTO.appendChild(panel) } let leftSize = localStorage.getItem("panel-left-size") ? JSON.parse(localStorage.getItem("panel-left-size")) : [40, 60] let rightSize = localStorage.getItem("panel-right-size") ? JSON.parse(localStorage.getItem("panel-right-size")) : [40, 60] let leftSplit, rightSplit setTimeout(() => { leftSplit = Split(["#panel1", "#panel3"], { sizes: leftSize, direction: "vertical", gutterSize: 15, snapOffset: 0, onDragEnd: function (e) { localStorage.setItem("panel-left-size", JSON.stringify(e)) } }) rightSplit = Split(["#panel2", "#panel4"], { sizes: rightSize, direction: "vertical", gutterSize: 15, snapOffset: 0, onDragEnd: function (e) { localStorage.setItem("panel-right-size", JSON.stringify(e)) } }) }, 0) // ADD COMMAND PANEL let haveWS = false const commandContainer = document.createElement("div") commandContainer.id = "commandcontainer" commandContainer.style.display = "none" const commandBackground = document.createElement("div") commandBackground.id = "commandbackground" commandContainer.appendChild(commandBackground) const commandWindow = document.createElement("div") commandWindow.id = "commandpanel" commandWindow.classList.add("windowShadow") const commandTopBar = document.createElement("div") commandTopBar.className = "newbonklobby_boxtop newbonklobby_boxtop_classic" commandTopBar.textContent = "Command Helper" commandWindow.appendChild(commandTopBar) const commandListContainer = document.createElement("div") commandListContainer.id = "commandlistcontainer" commandListContainer.className = "chatcontainer" commandWindow.appendChild(commandListContainer) commandContainer.appendChild(commandWindow) document.getElementById("bonkiocontainer").appendChild(commandContainer) let COMMANDS = { kick: (id) => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } id = parseInt(id) if (id == null || typeof id != "number") { FUNCTIONS.showSystemMessage("Failed, playerID not found", "#b53030") return } if (ROOM_VAR.myID == id) { FUNCTIONS.showSystemMessage("Failed, you can't use this command to yourself", "#b53030") return } if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } if (ROOM_VAR.players[id] == null) { FUNCTIONS.showSystemMessage("Failed, player not found in this room", "#b53030") return } iosend([ 9, { banshortid: id, kickonly: true } ]) }, ban: (id) => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } id = parseInt(id) if (id == null || typeof id != "number") { FUNCTIONS.showSystemMessage("Failed, playerID not found", "#b53030") return } if (ROOM_VAR.myID == id) { FUNCTIONS.showSystemMessage("Failed, you can't use this command to yourself", "#b53030") return } if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } if (ROOM_VAR.players[id] == null) { FUNCTIONS.showSystemMessage("Failed, player not found in this room", "#b53030") return } iosend([ 9, { banshortid: id, kickonly: false } ]) }, mute: (id) => { id = parseInt(id) if (id == null || typeof id != "number") { FUNCTIONS.showSystemMessage("Failed, playerID not found", "#b53030") return } if (ROOM_VAR.myID == id) { FUNCTIONS.showSystemMessage("Failed, you can't use this command to yourself", "#b53030") return } if (ROOM_VAR.players[id] == null) { FUNCTIONS.showSystemMessage("Failed, player not found in this room", "#b53030") return } ROOM_VAR.players[id].mute = true PROCESSCOMMAND(`/mute '${ROOM_VAR.players[id].userName}'`) }, unmute: (id) => { id = parseInt(id) if (id == null || typeof id != "number") { FUNCTIONS.showSystemMessage("Failed, playerID not found", "#b53030") return } if (ROOM_VAR.myID == id) { FUNCTIONS.showSystemMessage("Failed, you can't use this command to yourself", "#b53030") return } if (ROOM_VAR.players[id] == null) { FUNCTIONS.showSystemMessage("Failed, player not found in this room", "#b53030") return } ROOM_VAR.players[id].mute = false PROCESSCOMMAND(`/unmute '${ROOM_VAR.players[id].userName}'`) }, balance: (id, size) => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } id = parseInt(id) size = parseInt(size) if (id == null || typeof id != "number") { FUNCTIONS.showSystemMessage("Failed, playerID not found", "#b53030") return } if (size == null || typeof size != "number") { FUNCTIONS.showSystemMessage("Failed, size not found", "#b53030") return } if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } if (ROOM_VAR.players[id] == null) { FUNCTIONS.showSystemMessage("Failed, player not found in this room", "#b53030") return } if (size < -100 || size > 100) { FUNCTIONS.showSystemMessage("Failed, size must be between -100 and 100", "#b53030") return } iosend([ 29, { sid: id, bal: size } ]) }, balanceall: (size) => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } size = parseInt(size) if (size == null || typeof size != "number") { FUNCTIONS.showSystemMessage("Failed, size not found", "#b53030") return } if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } if (size < -100 || size > 100) { FUNCTIONS.showSystemMessage("Failed, size must be between -100 and 100", "#b53030") return } for (let i = 0; i < ROOM_VAR.players.length; i++) { const element = ROOM_VAR.players[i] if (element == null) continue iosend([ 29, { sid: i, bal: size } ]) } }, roomname: (name) => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } if (!name) { FUNCTIONS.showSystemMessage("Failed, name not found", "#b53030") return } if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } iosend([ 52, { newName: name } ]) }, roompass: (password) => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } if (!password) { FUNCTIONS.showSystemMessage("Failed, password not found", "#b53030") return } if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } iosend([ 53, { newPass: password } ]) }, clearroompass: () => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } iosend([ 53, { newPass: "" } ]) }, move: (id, teamid) => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } id = parseInt(id) teamid = parseInt(teamid) if (id == null || typeof id != "number") { FUNCTIONS.showSystemMessage("Failed, playerID not found", "#b53030") return } if (teamid == null || typeof teamid != "number") { FUNCTIONS.showSystemMessage("Failed, teamID not found", "#b53030") return } if (![0, 1, 2, 3, 4, 5].includes(teamid)) { FUNCTIONS.showSystemMessage("Failed, team not found", "#b53030") return } if (ROOM_VAR.players[id] == null) { FUNCTIONS.showSystemMessage("Failed, player not found in this room", "#b53030") return } if (id == ROOM_VAR.myID) { iosend([ 6, { targetTeam: teamid } ]) } else if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } else { iosend([ 26, { targetID: id, targetTeam: teamid } ]) } if (ROOM_VAR.myID == ROOM_VAR.hostID) { if (teamid < 0) { ROOM_VAR.stateFunction.hostHandlePlayerJoined(id, ROOM_VAR.players.length, teamid) } else { ROOM_VAR.stateFunction.hostHandlePlayerLeft(id) } } }, moveall: (teamid) => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } teamid = parseInt(teamid) if (teamid == null || typeof teamid != "number") { FUNCTIONS.showSystemMessage("Failed, teamID not found", "#b53030") return } if (![0, 1, 2, 3, 4, 5].includes(teamid)) { FUNCTIONS.showSystemMessage("Failed, team not found", "#b53030") return } if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } for (let i = 0; i < ROOM_VAR.players.length; i++) { const element = ROOM_VAR.players[i] if (element == null) continue if (i == ROOM_VAR.myID) { iosend([ 6, { targetTeam: teamid } ]) } else { iosend([ 26, { targetID: i, targetTeam: teamid } ]) } if (teamid < 0) { ROOM_VAR.stateFunction.hostHandlePlayerJoined(i, ROOM_VAR.players.length, teamid) } else { ROOM_VAR.stateFunction.hostHandlePlayerLeft(i) } } }, mode: (modeid) => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } modeid = modeid.replace(" ", "") if (!modeid) { FUNCTIONS.showSystemMessage("Failed, modeID not found", "#b53030") return } if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } iosend([ 20, { ga: modeid == "f" ? "f" : "b", mo: modeid } ]) }, team: (option) => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } option = option.replace(" ", "") if (!option) { FUNCTIONS.showSystemMessage("Failed, option not found", "#b53030") return } if (!["on", "off"].includes(option)) { FUNCTIONS.showSystemMessage("Failed, invalid option", "#b53030") return } if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } iosend([ 32, { t: option == "on" ? true : false } ]) }, lock: (option) => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } option = option.replace(" ", "") if (!option) { FUNCTIONS.showSystemMessage("Failed, option not found", "#b53030") return } if (!["on", "off"].includes(option)) { FUNCTIONS.showSystemMessage("Failed, invalid option", "#b53030") return } if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } iosend([ 7, { teamLock: option == "on" ? true : false } ]) }, skin: (id) => { id = parseInt(id) if (id == null || typeof id != "number") { FUNCTIONS.showSystemMessage("Failed, playerID not found", "#b53030") return } if (ROOM_VAR.players[id] == null) { FUNCTIONS.showSystemMessage("Failed, player not found in this room", "#b53030") return } const a = document.createElement("a") const file = new Blob([JSON.stringify(ROOM_VAR.players[id].avatar)], { type: "text/plain" }) a.href = URL.createObjectURL(file) a.download = `avatar_${ROOM_VAR.players[id].userName}_${Date.now()}` a.click() }, link: () => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } document.getElementById("newbonklobby_linkbutton").click() }, start: () => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } STARTGAME() }, round: (number) => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } number = parseInt(number) if (number == null || typeof number != "number") { FUNCTIONS.showSystemMessage("Failed, invalid number", "#b53030") return } if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } iosend([ 21, { w: number } ]) }, clear: () => { document.getElementById("messagecontainer").innerHTML = "" }, clearsys: () => { document.getElementById("systemcontainer").innerHTML = "" }, size: (option, topsize, bottomsize) => { option = option.replace(" ", "") topsize = parseInt(topsize) bottomsize = parseInt(bottomsize) if (!["left", "right"].includes(option)) { FUNCTIONS.showSystemMessage("Failed, invalid option", "#b53030") return } if (topsize == null || typeof topsize != "number" || bottomsize == null || typeof bottomsize != "number") { FUNCTIONS.showSystemMessage("Failed, invalid number", "#b53030") return } if (topsize + bottomsize != 100) { FUNCTIONS.showSystemMessage("Failed, the sum of top and bottom size must be 100", "#b53030") return } let sizes = [topsize, bottomsize] if (option == "left") { leftSplit.setSizes(sizes) localStorage.setItem("panel-left-size", JSON.stringify(sizes)) } else { rightSplit.setSizes(sizes) localStorage.setItem("panel-right-size", JSON.stringify(sizes)) } }, fav: () => { PROCESSCOMMAND("/fav") }, unfav: () => { PROCESSCOMMAND("/unfav") }, givehost: (id) => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } id = parseInt(id) if (id == null || typeof id != "number") { FUNCTIONS.showSystemMessage("Failed, playerID not found", "#b53030") return } if (ROOM_VAR.myID == id) { FUNCTIONS.showSystemMessage("Failed, you can't use this command to yourself", "#b53030") return } if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } if (ROOM_VAR.players[id] == null) { FUNCTIONS.showSystemMessage("Failed, player not found in this room", "#b53030") return } iosend([ 34, { id: id } ]) }, countdown: (option) => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } option = option.replace(" ", "") if (!["1", "2", "3"].includes(option)) { FUNCTIONS.showSystemMessage("Failed, invalid option", "#b53030") return } iosend([36, { num: parseInt(option) }]) }, abort: () => { if (ROOM_VAR.quick) { FUNCTIONS.showSystemMessage("Failed, unavailable in quick play", "#b53030") return } if (ROOM_VAR.myID != ROOM_VAR.hostID) { FUNCTIONS.showSystemMessage("Failed, you must be room host", "#b53030") return } iosend([37]) }, xp: () => { FUNCTIONS.showSystemMessage(`${ROOM_VAR.xpEarned}xp earned`, "#0955c7") }, earnxp: () => { iosend([38]) }, ready: (option) => { option = option.replace(" ", "") if (!["true", "false"].includes(option)) { FUNCTIONS.showSystemMessage("Failed, invalid option", "#b53030") return } iosend([16, { ready: option === "true" }]) }, zoom: (number) => { number = parseFloat(number) if (number == null || typeof number != "number") { FUNCTIONS.showSystemMessage("Failed, invalid number", "#b53030") return } scaler = number RESCALESTAGE() } } let SEARCH = { addInput: (addText = "", setInstead = false) => { if (addText == "") return if (setInstead) { document.getElementById("bonkpanelchatinput").value = addText } else { document.getElementById("bonkpanelchatinput").value += addText } FUNCTIONS.showCommandHelper(document.getElementById("bonkpanelchatinput").value) }, remove: () => { commandListContainer.innerHTML = "" }, commands: (filterText = "") => { SEARCH.remove() COMMANDLIST.forEach((e) => { if (!e.name.startsWith(filterText)) return if (ROOM_VAR.hostID != ROOM_VAR.myID && e.host) return if (ROOM_VAR.quick && e.noQuick) return let params = "" e.param.forEach((a) => { params += ` <${a}>` }) const card = document.createElement("div") card.className = "windowShadow commandscardcontainer" card.addEventListener("click", () => { SEARCH.addInput("/" + e.name + " ", true) document.getElementById("bonkpanelchatinput").focus() }) if (document.getElementById("bonkpanelchatinput").onkeydown == null) { document.getElementById("bonkpanelchatinput").onkeydown = function (event) { if (event.code == "Tab") { event.preventDefault() document.getElementById("bonkpanelchatinput").onkeydown = null SEARCH.addInput("/" + e.name + " ", true) document.getElementById("bonkpanelchatinput").focus() } } } const title = document.createElement("div") title.className = "commandscardtitle" title.textContent = e.name + params card.appendChild(title) const description = document.createElement("div") description.className = "commandscarddescription" description.textContent = e.des card.appendChild(description) commandListContainer.appendChild(card) }) }, players: (command) => { SEARCH.remove() for (let i = 0; i < ROOM_VAR.players.length; i++) { if (command.withoutMe && i == ROOM_VAR.myID) continue if (command.checkHost && ROOM_VAR.myID != ROOM_VAR.hostID && i != ROOM_VAR.myID) continue const element = ROOM_VAR.players[i] if (element == null) continue const card = document.createElement("div") card.className = "windowShadow commandscardcontainer" card.style.flexDirection = "row" card.addEventListener("click", () => { SEARCH.addInput(i.toString() + " ") document.getElementById("bonkpanelchatinput").focus() }) if (document.getElementById("bonkpanelchatinput").onkeydown == null) { document.getElementById("bonkpanelchatinput").onkeydown = function (event) { if (event.code == "Tab") { event.preventDefault() document.getElementById("bonkpanelchatinput").onkeydown = null SEARCH.addInput(i.toString() + " ") document.getElementById("bonkpanelchatinput").focus() } } } const img = document.createElement("div") img.classList.add("commandplayerimgcontainer") card.appendChild(img) const textcontainer = document.createElement("div") textcontainer.style = `width: calc(100% - 100px); display: flex; flex-direction: column; justify-content: space-evenly` const name = document.createElement("div") name.className = "commandscardtitle" name.textContent = element.userName textcontainer.appendChild(name) const id = document.createElement("div") id.style.marginBottom = "0" id.className = "commandscarddescription" id.textContent = `ID: ${i.toString()}` textcontainer.appendChild(id) const levelorguest = document.createElement("div") levelorguest.className = "commandscarddescription" levelorguest.textContent = element.guest ? "Guest" : `Level ${element.level}` textcontainer.appendChild(levelorguest) card.appendChild(textcontainer) commandListContainer.appendChild(card) if (ROOM_VAR.commandAvatarCache[element.userName] && ROOM_VAR.commandAvatarCache[element.userName][1]) { img.appendChild(ROOM_VAR.commandAvatarCache[element.userName][1].cloneNode(true)) } else { try { FUNCTIONS.createAvatarImage(element.avatar, 1, img, "newbonklobby_chat_msg_avatar", 100, 100, ROOM_VAR.commandAvatarCache, i, 1, 1, 0.25) } catch (error) { console.error(error) } } } }, teams: () => { SEARCH.remove() Array.from([ ["Spectate", 0], ["Free for all", 1], ["Red", 2], ["Blue", 3], ["Green", 4], ["Yellow", 5] ]).forEach((e) => { const card = document.createElement("div") card.className = "windowShadow commandscardcontainer" card.addEventListener("click", () => { SEARCH.addInput(e[1].toString() + " ") document.getElementById("bonkpanelchatinput").focus() }) if (document.getElementById("bonkpanelchatinput").onkeydown == null) { document.getElementById("bonkpanelchatinput").onkeydown = function (event) { if (event.code == "Tab") { event.preventDefault() document.getElementById("bonkpanelchatinput").onkeydown = null SEARCH.addInput(e[1].toString() + " ") document.getElementById("bonkpanelchatinput").focus() } } } const title = document.createElement("div") title.className = "commandscardtitle" title.textContent = e[0] card.appendChild(title) const id = document.createElement("div") id.className = "commandscarddescription" id.textContent = "ID: " + e[1].toString() card.appendChild(id) commandListContainer.appendChild(card) }) }, modes: () => { SEARCH.remove() Array.from([ ["Classic", "b"], ["Arrows", "ar"], ["Death arrows", "ard"], ["Grapple", "sp"], ["Football", "f"], ["VTOL", "v"] ]).forEach((e) => { const card = document.createElement("div") card.className = "windowShadow commandscardcontainer" card.addEventListener("click", () => { SEARCH.addInput(e[1].toString() + " ") document.getElementById("bonkpanelchatinput").focus() }) if (document.getElementById("bonkpanelchatinput").onkeydown == null) { document.getElementById("bonkpanelchatinput").onkeydown = function (event) { if (event.code == "Tab") { event.preventDefault() document.getElementById("bonkpanelchatinput").onkeydown = null SEARCH.addInput(e[1].toString() + " ") document.getElementById("bonkpanelchatinput").focus() } } } const title = document.createElement("div") title.className = "commandscardtitle" title.textContent = e[0] card.appendChild(title) const id = document.createElement("div") id.className = "commandscarddescription" id.textContent = "ID: " + e[1].toString() card.appendChild(id) commandListContainer.appendChild(card) }) }, option: (command) => { SEARCH.remove() Array.from(command.option).forEach((e) => { const card = document.createElement("div") card.className = "windowShadow commandscardcontainer" card.addEventListener("click", () => { SEARCH.addInput(e + " ") document.getElementById("bonkpanelchatinput").focus() }) if (document.getElementById("bonkpanelchatinput").onkeydown == null) { document.getElementById("bonkpanelchatinput").onkeydown = function (event) { if (event.code == "Tab") { event.preventDefault() document.getElementById("bonkpanelchatinput").onkeydown = null SEARCH.addInput(e + " ") document.getElementById("bonkpanelchatinput").focus() } } } const title = document.createElement("div") title.style.paddingBottom = "8px" title.className = "commandscardtitle" title.textContent = e card.appendChild(title) commandListContainer.appendChild(card) }) }, nothing: () => { SEARCH.remove() } } let COMMANDLIST = [ { name: "kick", des: "Removes a player from the game", param: ["player:ID"], func: ["players"], withoutMe: true, host: true, noQuick: true }, { name: "ban", des: "Removes and prevents a player from joining the game", param: ["player:ID"], func: ["players"], withoutMe: true, host: true, noQuick: true }, { name: "mute", des: "Prevents the chat messages of a player from registering on your screen", param: ["player:ID"], func: ["players"], withoutMe: true, host: false }, { name: "unmute", des: "Allows for future chat messages of a player to register on your screen again", param: ["player:ID"], func: ["players"], withoutMe: true, host: false }, { name: "balance", des: "Changes the size of a player", param: ["player:ID", "size:number"], func: ["players", "nothing"], host: true, noQuick: true }, { name: "balanceall", des: "Change the size of all players", param: ["size:number"], func: ["nothing"], host: true, noQuick: true }, { name: "roomname", des: "Changes the name of the room", param: ["name:string"], func: ["nothing"], host: true, noQuick: true }, { name: "roompass", des: "Changes the password of the room", param: ["name:string"], func: ["nothing"], host: true, noQuick: true }, { name: "clearroompass", des: "The room no longer need a password to join", param: [], func: [], host: true, noQuick: true }, { name: "move", des: "Move a player to another team", param: ["player:ID", "team:ID"], func: ["players", "teams"], checkHost: true, host: false, noQuick: true }, { name: "moveall", des: "Move all players to a team", param: ["team:ID"], func: ["teams"], host: true, noQuick: true }, { name: "mode", des: "Changes the game mode of the room", param: ["mode:ID"], func: ["modes"], host: true, noQuick: true }, { name: "team", des: "Enable or disable teams", param: ["teams:option"], func: ["option"], option: ["on", "off"], host: true, noQuick: true }, { name: "lock", des: "Allow or prevent players from moving themselves", param: ["lock:option"], func: ["option"], option: ["on", "off"], host: true, noQuick: true }, { name: "link", des: "Copy the auto join link to your clipboard", param: [], func: [], host: false, noQuick: true }, { name: "skin", des: "Download the skin of a player", param: ["player:ID"], func: ["players"], host: false }, { name: "start", des: "Instantly start the game without countdown", param: [], func: [], host: true, noQuick: true }, { name: "round", des: "Set the rounds to win", param: ["rounds:number"], func: ["nothing"], host: true, noQuick: true }, { name: "clear", des: "Clears the chat", param: [], func: [], host: false }, { name: "clearsys", des: "Clears the system chat", param: [], func: [], host: false }, { name: "size", des: ["Set the size of the panels"], param: ["panel:option", "topsize:number", "bottomsize:number"], func: ["option", "nothing", "nothing"], option: ["left", "right"], host: false }, { name: "fav", des: ["Adds the current map to your favourites list"], param: [], func: [], host: false }, { name: "unfav", des: ["Removes the current map from your favourites list"], param: [], func: [], host: false }, { name: "givehost", des: ["Gives host to a player"], param: ["player:id"], func: ["players"], withoutMe: true, host: true, noQuick: true }, { name: "countdown", des: ["Sends a countdown message"], param: ["countdown:option"], func: ["option"], option: ["1", "2", "3"], host: true, noQuick: true }, { name: "abort", des: ["Sends an abort countdown message"], param: [], func: [], host: true, noQuick: true }, { name: "xp", des: ["Tells you how much xp you earned in this room"], param: [], func: [], host: false }, { name: "earnxp", des: ["Instantly gain xp"], param: [], func: [], host: false }, { name: "ready", des: ["Change your ready state"], param: ["state:option"], func: ["option"], option: ["true", "false"], host: false }, { name: "zoom", des: "Set the scale of the stage", param: ["scale:number"], func: ["nothing"], host: false } ] // SCENE let ROOM_VAR = { xpEarned: 0, myID: 0, hostID: 0, autoJoinID: null, autoJoinPassBypass: null, players: [], quick: false, bal: [], tmpImgTextPing: [], state: null, stateFunction: null, chatAvatarCache: [], commandAvatarCache: [], playersAvatarCache: [] } let FUNCTIONS = { showCommandHelper: (value = "") => { if (value == "" || !value.startsWith("/") || value.startsWith("/ ")) { commandContainer.style.display = "none" return } const stage = value.split(" ") if (stage.length == 1) { commandContainer.style.display = "flex" commandTopBar.textContent = stage[0].substring(1) || "Command Helper" SEARCH.commands(stage[0].substring(1)) } else { let index = COMMANDLIST.findIndex((z) => z.name === stage[0].substring(1)) if (index == -1) { commandContainer.style.display = "none" } else { commandContainer.style.display = "flex" let command = COMMANDLIST[index] let params = "" for (let i = 0; i < stage.length - 1; i++) { if (command.param[i]) { params += ` <${command.param[i]}>` } } if (params == "") { SEARCH["nothing"]() } else if (command.func[stage.length - 2]) { SEARCH[command.func[stage.length - 2]](command) } else { SEARCH["nothing"]() } commandTopBar.textContent = command.name + params } } }, processCommand: (value = "") => { if (value == "/" || value.startsWith("/ ")) { FUNCTIONS.showSystemMessage("Failed, invalid command", "#b53030") commandContainer.style.display = "none" return } const stage = value.substring(1).split(" ") if (COMMANDS[stage[0]] == null) { FUNCTIONS.showSystemMessage("Failed, invalid command", "#b53030") commandContainer.style.display = "none" return } if (stage.length == 1) { COMMANDS[stage[0]]() } else { let index = COMMANDLIST.findIndex((z) => z.name === stage[0]) if (index == -1) { FUNCTIONS.showSystemMessage("Failed, invalid command", "#b53030") } else { let command = COMMANDLIST[index] if (command.param.length == 0) { COMMANDS[stage[0]]() } else { function splitWithTail(str, delim, count) { var parts = str.split(delim) var tail = parts.slice(count).join(delim) var result = parts.slice(0, count) result.push(tail) return result } let val = splitWithTail(value, " ", command.param.length) val.shift() COMMANDS[stage[0]](...val) } } } commandContainer.style.display = "none" }, createAvatarImage: ( avatar, team_number, appendlocation, classList, image_width, image_height, cache_storage, cache_id, cache_team, shadow_thickness, opacity ) => { const hexToHSL = (hex) => { // Convert hex string to RGB values let r = parseInt(hex.slice(1, 3), 16) let g = parseInt(hex.slice(3, 5), 16) let b = parseInt(hex.slice(5, 7), 16) // Normalize RGB values r /= 255 g /= 255 b /= 255 // Find the minimum and maximum RGB values let min = Math.min(r, g, b) let max = Math.max(r, g, b) let diff = max - min // Initialize HSL values let h, s, l // Calculate hue if (diff === 0) { h = 0 } else if (max === r) { h = ((g - b) / diff) % 6 } else if (max === g) { h = (b - r) / diff + 2 } else { h = (r - g) / diff + 4 } h = Math.round(60 * h) if (h < 0) { h += 360 } // Calculate lightness l = (min + max) / 2 // Calculate saturation s = diff === 0 ? 0 : diff / (1 - Math.abs(2 * l - 1)) s = +(s * 100).toFixed(1) l = +(l * 100).toFixed(1) // Return HSL values as an object return { h, s, l } } const HSLtoHex = (hue, saturation, lightness) => { saturation /= 100 lightness /= 100 let s = (1 - Math.abs(2 * lightness - 1)) * saturation, h = s * (1 - Math["abs"](((hue / 60) % 2) - 1)), l = lightness - s / 2, red = 0, green = 0, blue = 0 if (0 <= hue && hue < 60) { red = s green = h blue = 0 } else if (60 <= hue && hue < 120) { red = h green = s blue = 0 } else if (120 <= hue && hue < 180) { red = 0 green = s blue = h } else if (180 <= hue && hue < 240) { red = 0 green = h blue = s } else if (240 <= hue && hue < 300) { red = h green = 0 blue = s } else if (300 <= hue && hue < 360) { red = s green = 0 blue = h } red = Math.round((red + l) * 255) green = Math.round((green + l) * 255) blue = Math.round((blue + l) * 255) const rgbToHex = (r, g, b) => "#" + [r, g, b] .map((x) => { const hex = x.toString(16) return hex.length === 1 ? "0" + hex : hex }) .join("") return rgbToHex(red, green, blue) } const hueify = (hexcolour, hue_value) => { let hsl = hexToHSL("#" + hexcolour.toString(16)["padStart"](6, "0")) hsl.h = hue_value return HSLtoHex(hsl.h, hsl.s, hsl.l) } const teamify = (colour) => { if (team_number == 2) { return hueify(colour, 4) } else if (team_number == 3) { return hueify(colour, 207) } else if (team_number == 4) { return hueify(colour, 122) } else if (team_number == 5) { return hueify(colour, 54) } return "#" + colour.toString(16)["padStart"](6, "0") } let svgcode = ` <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="36" height="36"> <clipPath id="clipCircle"><circle cx="18" cy="18" r="15"/></clipPath>` if (shadow_thickness > 0) { svgcode += `<circle fill="#000000" fill-opacity="${opacity}" cx="${18 + shadow_thickness}" cy="${18 + shadow_thickness}" r="15"/>` } svgcode += ` <circle fill="${teamify(avatar.bc)}" cx="18" cy="18" r="15"/> <g id="base" clip-path="url(#clipCircle)">` avatar.layers .slice() .reverse() .forEach((layer) => { svgcode += window.bonkpanel_skins[layer.id - 1] .match(/<g.+<\/g>/gs)[0] .replace(/fill=".+?"/, `fill="${teamify(layer.color)}"`) .replace( /transform=".+?"/, ` transform="matrix(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) translate(${layer.x + 18}, ${layer.y + 18}) rotate(${layer.angle}) scale(${layer.scale}) scale(${layer.flipX ? -1 : 1}, ${layer.flipY ? -1 : 1})" ` ) }) svgcode += "</g>" if (team_number >= 2 && team_number <= 5) { svgcode += `<circle clip-path="url(#clipCircle)" fill="none" cx="18" cy="18" r="15" stroke-width="1.8" stroke="#` if (team_number == 2) { svgcode += `f44336"/>` } else if (team_number == 3) { svgcode += `2196f3"/>` } else if (team_number == 4) { svgcode += `4caf50"/>` } else if (team_number == 5) { svgcode += `ffeb3b"/>` } } svgcode += "</svg>" const image = document.createElement("img") image.src = `data:image/svg+xml;base64,${window.btoa(unescape(encodeURIComponent(svgcode)))}` image.style.width = image_width + "px" image.style.height = image_height + "px" if (document.body.contains(appendlocation)) { while (appendlocation.firstChild) { appendlocation.removeChild(appendlocation.firstChild) } appendlocation.appendChild(image) if (classList != "") { image.classList.add(classList) } } if (cache_storage) { if (!cache_storage[cache_id]) { cache_storage[cache_id] = [] } cache_storage[cache_id][cache_team] = image } return image }, urlify: (text) => { let urlRegex = /(((https?:\/\/)|(www\.))[^\s]+)/g return text.replace(urlRegex, function (url, b, c) { let url2 = c == "www." ? "https://" + url : url return '<a href="' + url2 + '" target="_blank">' + url + "</a>" }) }, showSystemMessage: (message, colour, inChat = false) => { const systemcontainer = inChat ? document.getElementById("messagecontainer") : document.getElementById("systemcontainer") if (systemcontainer == null) return const needToScroll = systemcontainer.scrollTop + systemcontainer.clientHeight >= systemcontainer.scrollHeight - 5 const msgcontainer = document.createElement("div") const msg = document.createElement("span") msg.style.color = colour msg.classList.add("newbonklobby_chat_status") msg.appendChild(document.createTextNode("* " + message)) msgcontainer.appendChild(msg) systemcontainer.appendChild(msgcontainer) if (systemcontainer.childElementCount > 250) { systemcontainer.removeChild(systemcontainer.firstChild) } if (needToScroll) { systemcontainer.scrollTop = systemcontainer.scrollHeight } }, showChatMessage: (message, ID) => { const messagecontainer = document.getElementById("messagecontainer") if (messagecontainer == null) return const messager = ROOM_VAR.players[ID] if (messager == null) return if (messager.mute) return const needToScroll = messagecontainer.scrollTop + messagecontainer.clientHeight >= messagecontainer.scrollHeight - 5 const messageholder = document.createElement("div") messagecontainer.appendChild(messageholder) const colourbox = document.createElement("div") colourbox.classList.add("newbonklobby_chat_msg_colorbox") messageholder.appendChild(colourbox) if (ROOM_VAR.chatAvatarCache[messager.userName] && ROOM_VAR.chatAvatarCache[messager.userName][1]) { colourbox.appendChild(ROOM_VAR.chatAvatarCache[messager.userName][1].cloneNode(true)) } else { try { FUNCTIONS.createAvatarImage(messager.avatar, 1, colourbox, "newbonklobby_chat_msg_avatar", 12, 12, ROOM_VAR.chatAvatarCache, ID, 1, 2, 0.1) } catch (error) { console.error(error) } } const name = document.createElement("span") name.classList.add("newbonklobby_chat_msg_name") name.innerText = `${messager.userName}: ` messageholder.append(name) const msg = document.createElement("span") msg.classList.add("newbonklobby_chat_msg_txt") msg.innerHTML = FUNCTIONS.urlify(message) messageholder.appendChild(msg) if (needToScroll.childElementCount > 300) { needToScroll.removeChild(needToScroll.firstChild) } if (needToScroll) { messagecontainer.scrollTop = messagecontainer.scrollHeight } } } let SCENES = { system: (panelID = "panel1") => { document.getElementById(panelID).innerHTML = "" const container = document.createElement("div") container.id = "systemcontainer" container.className = "chatcontainer" document.getElementById(panelID).appendChild(container) }, chat: (panelID = "panel3") => { document.getElementById(panelID).innerHTML = "" const container = document.createElement("div") container.id = "messagecontainer" container.className = "chatcontainer" container.style.height = "calc(100% - 26px)" document.getElementById(panelID).appendChild(container) const lowerline = document.createElement("div") lowerline.id = "bonkpanellowerline" document.getElementById(panelID).appendChild(lowerline) const lowerinstruction = document.createElement("div") lowerinstruction.id = "bonkpanellowerinstruction" lowerinstruction.innerText = "Press enter to send a message" lowerinstruction.style.display = "block" document.getElementById(panelID).appendChild(lowerinstruction) const input = document.createElement("input") input.id = "bonkpanelchatinput" input.type = "text" input.setAttribute("autocomplete", "off") input.setAttribute("aria-autocomplete", "none") input.style.pointerEvents = "none" input.addEventListener("input", (e) => { input.onkeydown = null FUNCTIONS.showCommandHelper(e.target.value) }) document.getElementById(panelID).appendChild(input) }, leaderboard: (panelID = "panel2") => { document.getElementById(panelID).innerHTML = "" const container = document.createElement("div") container.style = "width: 100%; height: 100%; display: flex; flex-direction: column; scroll-y: auto; font-family: futurept_b1;" if (inLobby || ROOM_VAR.state == null || ROOM_VAR.state[4]?.wl == null) return const div = document.createElement("div") div.style = "font-size: 17px; padding: 5px 5px 0px; overflow: hidden;" div.textContent = "Rounds to win: " + ROOM_VAR.state[4]?.wl container.appendChild(div) if (ROOM_VAR.state[0].scores.length <= 0) return let leaderboardData = [] for (let i = 0; i < ROOM_VAR.state[0].scores.length; i++) { const score = ROOM_VAR.state[0].scores[i] if (score == null) continue let scoreOwner = "" if (ROOM_VAR.state[4].tea) { switch (i) { case 2: scoreOwner = "Red Team" break case 3: scoreOwner = "Blue Team" break case 4: scoreOwner = "Green Team" break case 5: scoreOwner = "Yellow Team" break } } else if (ROOM_VAR.players[i]?.userName) { scoreOwner = ROOM_VAR.players[i].userName } if (scoreOwner.length == 0) continue leaderboardData.push({ owner: scoreOwner, score: score }) } leaderboardData.sort((a, b) => b.score - a.score) leaderboardData.forEach((e) => { const div = document.createElement("div") div.style = "font-size: 17px; padding: 5px 5px 0px; overflow: hidden;" div.textContent = e.owner + ": " + e.score container.appendChild(div) }) document.getElementById(panelID).appendChild(container) }, players: (panelID = "panel4") => { document.getElementById(panelID).innerHTML = "" const container = document.createElement("div") container.id = "playerscontainer" container.style = "width: 100%; height: 100%; display: flex; flex-direction: column; scroll-y: auto;" ROOM_VAR.tmpImgTextPing = [] for (let i = 0; i < ROOM_VAR.players.length; i++) { const player = ROOM_VAR.players[i] if (player == null) continue const playerContainer = document.createElement("div") playerContainer.className = "newbonklobby_playerentry" playerContainer.style = "border-left: 4px solid var(--bonk_theme_primary_background, #e2e2e2) !important; border-right: 4px solid var(--bonk_theme_primary_background, #e2e2e2) !important; border-top: 4px solid var(--bonk_theme_primary_background, #e2e2e2) !important; background-color: var(--bonk_theme_primary_background, #e2e2e2); cursor: auto;" const avatar = document.createElement("div") avatar.className = "newbonklobby_playerentry_avatar" avatar.style = `opacity: ${player.team === 0 ? "0.5" : "1"};` if (ROOM_VAR.playersAvatarCache?.[player.userName]?.[player.team]) { avatar.innerHTML = ROOM_VAR.commandAvatarCache[player.userName][player.team] } else { try { avatar.innerHTML = FUNCTIONS.createAvatarImage( player.avatar, player.team, null, "", 36, 36, ROOM_VAR.playersAvatarCache, i, player.team, 1.1, 0.3 ).outerHTML } catch (error) { console.error(error) } } playerContainer.appendChild(avatar) const name = document.createElement("div") name.className = "newbonklobby_playerentry_name" name.textContent = player.userName playerContainer.appendChild(name) const level = document.createElement("div") level.className = "newbonklobby_playerentry_level" level.textContent = player.guest ? "Guest" : `Level ${player.level}` playerContainer.appendChild(level) const size = document.createElement("div") let sizeclass = "" let sizetext = "" if (ROOM_VAR.bal[i] && ROOM_VAR.bal[i] != 0) { if (ROOM_VAR.bal[i] > 0) { sizeclass = " newbonklobby_playerentry_balance_buff" sizetext = "+" + ROOM_VAR.bal[i] + "%" } else { sizeclass = " newbonklobby_playerentry_balance_nerf" sizetext = ROOM_VAR.bal[i] + "%" } } size.className = "newbonklobby_playerentry_balance" + sizeclass size.textContent = sizetext playerContainer.appendChild(size) const pingImg = document.createElement("img") pingImg.src = "graphics/ping_5.png" pingImg.className = "newbonklobby_playerentry_ping" playerContainer.appendChild(pingImg) const pingText = document.createElement("div") pingText.className = "newbonklobby_playerentry_pingtext" playerContainer.appendChild(pingText) const hostImg = document.createElement("img") hostImg.src = "graphics/host_0.png" hostImg.className = "newbonklobby_playerentry_host" playerContainer.appendChild(hostImg) ROOM_VAR.tmpImgTextPing[i] = { img: pingImg, text: pingText, host: hostImg } if (player.ready) { const ready = document.createElement("img") ready.className = "newbonklobby_playerentry_ready" ready.src = "graphics/readytick.png" playerContainer.appendChild(ready) } container.appendChild(playerContainer) } SCENES.updatePlayersPing() document.getElementById(panelID).appendChild(container) }, updatePlayersPing: () => { for (let i = 0; i < ROOM_VAR.players.length; i++) { const player = ROOM_VAR.players[i] const element = ROOM_VAR.tmpImgTextPing[i] if (element == null || player == null) continue let imgSrc = 1 if (player.ping <= 100) { imgSrc = 5 } if (player.ping > 100 && player.ping <= 200) { imgSrc = 4 } if (player.ping > 200 && player.ping <= 300) { imgSrc = 3 } if (player.ping > 300 && player.ping <= 400) { imgSrc = 2 } if (player.ping > 400) { imgSrc = 1 } if (player.tabbed) { imgSrc = "tab" } if (element.lastSet != imgSrc) { element.lastSet = imgSrc element.img.src = "graphics/ping_" + imgSrc + ".png" } if (imgSrc == "tab") { element.text.textContent = "Tab" } else if (player.ping === undefined) { element.text.textContent = "-ms" } else { element.text.textContent = player.ping + "ms" } if (ROOM_VAR.hostID == i) { if (element.hostLastSet != imgSrc) { element.hostLastSet = imgSrc element.host.src = "graphics/host_" + imgSrc + ".png" } } else { if (element.hostLastSet !== 0) { element.hostLastSet = 0 element.host.src = "graphics/host_0.png" } } } } } let inLobby = true // ADD STYLE const style = document.createElement("style") style.innerHTML += /*css*/ ` *:focus { outline: none; } .newbonklobby_chat_msg_colorbox { user-select: none; } #bonkiocontainer { margin: 10px !important; flex: 0 0 auto; } #bonkpanelcontainer { width: 100%; height: 100%; display: flex; align-items: center; justify-content: space-between; } #newbonklobby_chat_input { width: 0px !important; height: 0px !important; } #ingamechatinputtext { width: 0px !important; height: 0px !important; } #skinColourPickerContainerButton { display: flex; justify-content: space-between; } #skinColourPickerContainerButton > div { padding: 0 10; width: inherit; margin-top: 7px; margin-bottom: 2px; display: inline-block; height: 25px; line-height: 25px; } #imageOverlayContainer { position: absolute; margin: auto; left: 0; right: 0; top: 55px; width: 245px; height: 245px; cursor: grab; pointer-events: none; overflow: hidden; } #imageOverlay { width: 100%; aspect-ratio: 1; position: absolute; top: 0; left: 0; background-repeat: no-repeat; background-size: 100%; background-position: center; background-image: none; transform: scale(100%); opacity: 50%; } .panelcontainer { flex: 1; height: 100%; background-color: var(--bonk_theme_primary_background, #e2e2e2) !important; color: var(--bonk_theme_primary_text, #000000) !important; } .gutter { background-color: var(--bonk_theme_window_color, #009688) !important; background-repeat: no-repeat; background-position: 50%; } .gutter.gutter-vertical { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII='); cursor: row-resize; } .panel { position: relative; } #commandcontainer { position: absolute; width: 100%; height: 100%; top: 0; display: flex; align-items: center; justify-content: center; font-family: "futurept_b1"; } #commandbackground { width: 100%; height: 100%; background-color: black; opacity: 0.6; } #commandpanel { position: absolute; background-color: var(--greyWindowBGColor); width: 80%; height: 70%; border-radius: 7px; } #commandtoptext { font-family: "futurept_b1"; color: #ffffff; text-align: center; font-size: 20px; line-height: 32px; padding: 0px; margin: 0px; } #commandlistcontainer { height: calc(100% - 36px) !important; } .commandscardcontainer { background-color: #eeeeee; color: #222222; border-radius: 5px; user-select: none; margin: 10px; display: flex; flex-direction: column; cursor: pointer; } .commandscardtitle { display: block; text-align: left; font-size: 20px; padding-left: 10px; padding-top: 8px; } .commandscarddescription { display: block; text-align: left; font-size: 15px; padding-left: 10px; padding-right: 10px; line-height: 20px; white-space: pre-wrap; margin-bottom: 5px; } .commandplayerimgcontainer { width: 100px; height: 100px; } .chatcontainer { width: 100%; height: 100%; box-sizing: border-box; margin: auto; overflow-y: scroll; overflow-x: hidden; word-break: break-word; user-select: text; padding: 4px; } .chatcontainer::-webkit-scrollbar {width: 0.6em;} .chatcontainer::-webkit-scrollbar-thumb {background-color: var(--bonk_theme_scrollbar_thumb, #757575) !important;} .chatcontainer::-webkit-scrollbar-track {background-color: var(--bonk_theme_scrollbar_background) !important;} #bonkpanellowerline { background-color: #a5acb0; width: 97%; height: 1px; } #bonkpanellowerinstruction { width: 97%; height: 24px; margin: auto; color: #656565; font-size: 16px; font-family: "futurept_b1"; pointer-events: none; } #bonkpanelchatinput { width: 97%; height: 24px; margin: auto; border: 0px solid; background: none; font-family: "futurept_b1"; font-size: 16px; color: #171717; pointer-events: none; } ` document.body.appendChild(style) // MONKEY PATCH SHAKE TWEEN OBJECT var canvasStage = null const symbolshakeTweenObject = Symbol("shakeTweenObject") Object.defineProperty(Object.prototype, "shakeTweenObject", { get() { return this[symbolshakeTweenObject] }, set(value) { canvasStage = this const original = this.createGradientBackground this.createGradientBackground = function () { original.call(this, arguments) RESCALESTAGE() } this[symbolshakeTweenObject] = value }, configurable: true }) var scaler = 1 function RESCALESTAGE() { if (canvasStage == null || canvasStage.stage == null) return canvasStage.stage.scale.x = scaler canvasStage.stage.scale.y = scaler var tmpWidth = 730 * canvasStage.scaleRatio var tmpHeight = 500 * canvasStage.scaleRatio canvasStage.stage.x = tmpWidth / 2 - (tmpWidth * scaler) / 2 canvasStage.stage.y = tmpHeight / 2 - (tmpHeight * scaler) / 2 var superWidth = (780 * canvasStage.scaleRatio) / scaler var superHeight = (550 * canvasStage.scaleRatio) / scaler canvasStage.bgGradient.beginFill(0x3b536b) canvasStage.bgGradient.drawRect(0, 0, superWidth, superHeight) canvasStage.bgGradient.x = -(superWidth - tmpWidth) / 2 canvasStage.bgGradient.y = -(superHeight - tmpHeight) / 2 } // MONKEY PATCH AVATAR SHOW let showFunction = () => {} const symbolShow = Symbol("show") Object.defineProperty(Object.prototype, "show", { get() { return this[symbolShow] }, set(value) { if (typeof value == "function") { const original = value value = function () { if (arguments[0]?.bc) { showFunction = original } return original.apply(this, arguments) } } this[symbolShow] = value }, configurable: true }) // MONKEY PATCH showColorPicker var showColorPicker = null var showColorPickerArguments = [] const symbolshowColorPicker = Symbol("showColorPicker") Object.defineProperty(Object.prototype, "showColorPicker", { get() { return this[symbolshowColorPicker] }, set(value) { if (typeof value == "function") { const original = value value = function () { showColorPicker = original showColorPickerArguments = arguments return original.apply(this, arguments) } } this[symbolshowColorPicker] = value } }) // MONKEY PATCH hostHandlePlayerJoined const symbolhostHandlePlayerJoined = Symbol("hostHandlePlayerJoined") Object.defineProperty(Object.prototype, "hostHandlePlayerJoined", { get() { return this[symbolStep] }, set(value) { ROOM_VAR.stateFunction = this this[symbolStep] = value }, configurable: true }) // MONKEY PATCH STEP const symbolStep = Symbol("step") Object.defineProperty(Object.prototype, "step", { get() { return this[symbolStep] }, set(value) { if (typeof value == "function") { const original = value value = function () { if (arguments[0]?.scores) { if (ws) { ROOM_VAR.state = arguments } } return original.apply(this, arguments) } } this[symbolStep] = value }, configurable: true }) // MONKEY PATCH APPEND CHILD let originalAppendChild = Element.prototype.appendChild Element.prototype.appendChild = function () { if (this == document.getElementById("newbonklobby_chat_content") || this == document.getElementById("ingamechatcontent")) { if ( (arguments[0].firstChild?.className == "newbonklobby_chat_status" && inLobby) || (arguments[0].firstChild?.className == "ingamechatstatus" && !inLobby) ) { let text = arguments[0].textContent if (text.startsWith("* Map added to favourites")) { FUNCTIONS.showSystemMessage("Map added to favourites", "#b53030") } else if (text.startsWith("* Couldn't favourite map because it isn't public")) { FUNCTIONS.showSystemMessage("Failed, couldn't favourite map because it isn't public", "#b53030") } else if (text.startsWith("* This map is already in your favourites!")) { FUNCTIONS.showSystemMessage("This map is already in your favourites", "#b53030") } else if (text.startsWith("* Couldn't favourite, something went wrong")) { FUNCTIONS.showSystemMessage("Failed, something went wrong", "#b53030") } else if (text.startsWith("* You must be logged in and the map must be a Bonk 2 map")) { FUNCTIONS.showSystemMessage("Failed, you must be logged in and the map must be a Bonk 2 map", "#b53030") } else if (text.startsWith("* Map removed from favourites")) { FUNCTIONS.showSystemMessage("Map removed from favourites", "#b53030") } else if (text.startsWith("* Couldn't unfavourite map because it isn't public")) { FUNCTIONS.showSystemMessage("Failed, couldn't unfavourite map because it isn't public", "#b53030") } else if (text.startsWith("* This map isn't in your favourites!")) { FUNCTIONS.showSystemMessage("This map isn't in your favourites", "#b53030") } else if (text.startsWith("* Couldn't unfavourite, something went wrong")) { FUNCTIONS.showSystemMessage("Failed, something went wrong", "#b53030") } else if (text.startsWith("* No replays in Football mode")) { FUNCTIONS.showSystemMessage("Failed, no replays in football mode", "#b53030") } else if (text.startsWith("* Please wait at least")) { FUNCTIONS.showSystemMessage(text.substring(2).replace("Please", "Failed,"), "#b53030") } else if (text.startsWith("* Recording failed")) { FUNCTIONS.showSystemMessage("Failed, something went wrong", "#b53030") } else if (text.startsWith("* Replay must be at least")) { FUNCTIONS.showSystemMessage(text.substring(2).replace("Replay", "Failed, replay"), "#b53030") } else if (text.startsWith("* The last")) { FUNCTIONS.showSystemMessage(text.substring(2), "#b53030") } else if (text.startsWith("* You and")) { FUNCTIONS.showSystemMessage(text.substring(2), "#00675d") } else if (text.endsWith("accepted your friend request ")) { FUNCTIONS.showSystemMessage(text.substring(2), "#00675d") } else if (text.startsWith("* Your clipboard has been set to:")) { FUNCTIONS.showSystemMessage(`Link copied`, "#0955c7") } } else if (arguments[0].firstChild?.className == "newbonklobby_chat_status") { let text = arguments[0].textContent if (text.startsWith("* You and")) { FUNCTIONS.showSystemMessage(text.substring(2), "#00675d") } else if (text.endsWith("accepted your friend request ")) { FUNCTIONS.showSystemMessage(text.substring(2), "#00675d") } else if (text.startsWith("* Your clipboard has been set to:")) { FUNCTIONS.showSystemMessage(`Link copied`, "#0955c7") } } if (this == document.getElementById("newbonklobby_chat_content") && arguments[0].firstChild?.className == "newbonklobby_chat_msg_name") { const systemcontainer = document.getElementById("systemcontainer") if (systemcontainer) { const needToScroll = systemcontainer.scrollTop + systemcontainer.clientHeight >= systemcontainer.scrollHeight - 5 systemcontainer.appendChild(arguments[0]) if (systemcontainer.childElementCount > 250) { systemcontainer.removeChild(systemcontainer.firstChild) } if (needToScroll) { systemcontainer.scrollTop = systemcontainer.scrollHeight } return } } if (this == document.getElementById("newbonklobby_chat_content") && arguments[0].lastChild?.textContent == "[Accept]") { const systemcontainer = document.getElementById("systemcontainer") if (systemcontainer) { const needToScroll = systemcontainer.scrollTop + systemcontainer.clientHeight >= systemcontainer.scrollHeight - 5 systemcontainer.appendChild(arguments[0]) if (systemcontainer.childElementCount > 250) { systemcontainer.removeChild(systemcontainer.firstChild) } if (needToScroll) { systemcontainer.scrollTop = systemcontainer.scrollHeight } return } } } else if ( (arguments[0].textContent == "Unmute" || arguments[0].textContent == "Mute") && (arguments[0].className == "newbonklobby_playerentry_menu_button brownButton buttonShadow newbonklobby_playerentry_menu_button_warn" || arguments[0].className == "newbonklobby_playerentry_menu_button brownButton buttonShadow brownButton_classic") ) { arguments[0].addEventListener("click", () => { const tmpelement = document.getElementsByClassName("newbonklobby_playerentry_menuhighlighted")[0] if (tmpelement) { const tmpname = tmpelement.getElementsByClassName("newbonklobby_playerentry_name")[0].textContent for (let i = 0; i < ROOM_VAR.players.length; i++) { if (ROOM_VAR.players[i].userName === tmpname) { ROOM_VAR.players[i].mute = !ROOM_VAR.players[i].mute break } } } }) } else if (this == document.body && arguments[0].tagName == "DIV") { return } return originalAppendChild.apply(this, arguments) } // MONKEY PATCH ARRAY PUSH let STARTGAME = null let PROCESSCOMMAND = null let originalArrayPush = Array.prototype.push Array.prototype.push = function () { if (arguments[0]?.eventName === "startGame") { STARTGAME = arguments[0].callback } else if (arguments[0]?.eventName === "processCommand") { PROCESSCOMMAND = arguments[0].callback } originalArrayPush.apply(this, arguments) } // MONKEY PATCH EVENT LISTENER let lockKeyboard = true let _listeners = [] let originalAddEventListener = EventTarget.prototype.addEventListener EventTarget.prototype.addEventListener = function (type, listener, useCapture) { if (this == window && type == "keydown") { let originalListener = listener lockKeyboard = document.activeElement !== document.getElementById("bonkpanelchatinput") listener = function () { if (lockKeyboard) { originalListener.apply(null, arguments) } } } _listeners.push({ type: type, listener: listener }) originalAddEventListener.apply(this, [type, listener, useCapture]) } let originalRemoveEventListener = EventTarget.prototype.removeEventListener EventTarget.prototype.removeEventListener = function (type, listener) { if (this == window && type == "keydown") { _listeners.forEach((e) => { if (e.type == type) { originalRemoveEventListener.apply(window, [type, e.listener]) } }) _listeners = [] } originalRemoveEventListener.apply(this, [type, listener]) } let chatInputEvent = null setTimeout(() => { let originalOn = $.fn.on $.fn.on = function (types, func) { if (ws && types == "keydown") { chatInputEvent = func return false } else { return originalOn.apply(this, arguments) } } }, 0) // CUSTOM EVENT LISTENER document.addEventListener("keydown", (e) => { if (ws == null) return if (e.code != "Enter") return let chatinput = document.getElementById("bonkpanelchatinput") let instruction = document.getElementById("bonkpanellowerinstruction") if (inLobby) { if (document.activeElement == document.getElementById("maploadwindowsearchinput")) { document.getElementById("maploadwindowsearchbutton").click() } else if (document.activeElement == chatinput) { if (chatinput.value.startsWith("/")) { FUNCTIONS.processCommand(chatinput.value) } else if (chatinput.value != "") { iosend([10, { message: chatinput.value }]) } chatinput.value = "" chatinput.blur() instruction.style.display = "block" chatinput.style.pointerEvents = "none" } else { chatinput.focus() instruction.style.display = "none" chatinput.style.pointerEvents = "auto" } } else { if (document.activeElement == chatinput) { if (chatinput.value.startsWith("/")) { FUNCTIONS.processCommand(chatinput.value) } else if (chatinput.value != "") { iosend([10, { message: chatinput.value }]) } chatinput.value = "" chatinput.blur() instruction.style.display = "block" chatinput.style.pointerEvents = "none" lockKeyboard = true } else { chatinput.focus() instruction.style.display = "none" chatinput.style.pointerEvents = "auto" lockKeyboard = false } } }) document.addEventListener("mouseup", (e) => { if (ws && !inLobby) { if (commandContainer.style.display != "none") { lockKeyboard = false } else if (typeof window.getSelection != "undefined" && window.getSelection().toString() != "") { lockKeyboard = false } else if (e.target.tagName == "INPUT") { lockKeyboard = false } else { lockKeyboard = true } } }) document.addEventListener("mousedown", (e) => { if (ws && !inLobby) { if (commandContainer.style.display != "none") { lockKeyboard = false } else if (e.target == document.getElementById("bonkpanelcontainer") || e.target == document.querySelector("#gamerenderer > canvas")) { lockKeyboard = true } else if (e.target.tagName == "INPUT") { lockKeyboard = false } } }) // ADD SKIN BUTTONS const skinButtonsContainer = document.createElement("div") skinButtonsContainer.style = "width: 100%; height: 30px; bottom: 15px; position: absolute; display: flex; justify-content: space-around;" document.getElementById("skineditor_previewbox").appendChild(skinButtonsContainer) const tmpEle = document.createElement("input") tmpEle.type = "file" tmpEle.style.display = "none" tmpEle.addEventListener("change", () => { let fr = new FileReader() fr.onload = function () { const result = JSON.parse(fr.result) const tmpAvatar = new AVATAR() tmpAvatar.bc = result.bc tmpAvatar.layers = result.layers showFunction(tmpAvatar) } fr.readAsText(tmpEle.files[0]) }) document.body.appendChild(tmpEle) var overlayEditing = false var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0, overlayScale = 100, overlayOpacity = 50 const tmpEle2 = document.createElement("input") tmpEle2.type = "file" tmpEle2.style.display = "none" tmpEle2.addEventListener("change", () => { let fr = new FileReader() fr.onload = function () { importImageOverlay.style.backgroundImage = "url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iNDhweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iNDhweCIgZmlsbD0iI0ZGRkZGRiI+PHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTkgMTYuMTdMNC44MyAxMmwtMS40MiAxLjQxTDkgMTkgMjEgN2wtMS40MS0xLjQxTDkgMTYuMTd6Ii8+PC9zdmc+)" imageOverlayContainer.style.pointerEvents = "auto" imageOverlay.style.backgroundImage = `url(${fr.result})` imageOverlay.style.top = "0px" imageOverlay.style.left = "0px" overlayScale = 100 overlayOpacity = 50 imageOverlay.style.transform = `scale(${overlayScale}%)` imageOverlay.style.opacity = `${overlayOpacity}%` imageOverlayContainer.onmousedown = function (event) { pos3 = event.clientX pos4 = event.clientY window.onmousemove = function (e) { pos1 = pos3 - e.clientX pos2 = pos4 - e.clientY pos3 = e.clientX pos4 = e.clientY imageOverlay.style.top = imageOverlay.offsetTop - pos2 + "px" imageOverlay.style.left = imageOverlay.offsetLeft - pos1 + "px" } window.onmouseup = () => { window.onmousemove = null window.onmouseup = null } } imageOverlayContainer.onwheel = function (event) { if (event.shiftKey) { if (event.deltaY < 0) { overlayOpacity = Math.min(overlayOpacity + 1, 100) } else { overlayOpacity = Math.max(overlayOpacity - 1, 0) } imageOverlay.style.opacity = `${overlayOpacity}%` } else { if (event.deltaY < 0) { overlayScale += 1 } else { overlayScale -= 1 } imageOverlay.style.transform = `scale(${overlayScale}%)` } } document.getElementById("skineditor_previewbox_skincontainer").style.pointerEvents = "none" overlayEditing = true } fr.readAsDataURL(tmpEle2.files[0]) }) const importSkin = document.createElement("div") importSkin.className = "brownButton brownButton_classic" importSkin.style.width = "30px" importSkin.style.height = "30px" importSkin.addEventListener("click", () => { tmpEle.click() }) importSkin.style.backgroundImage = "url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyNy4zLjEsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCA0OCA0OCIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDggNDg7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoJLnN0MHtmaWxsOiNGRkZGRkY7fQ0KPC9zdHlsZT4NCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xMSw0MGMtMC44LDAtMS41LTAuMy0yLjEtMC45QzguMywzOC41LDgsMzcuOCw4LDM3di03LjFoM1YzN2gyNnYtNy4xaDNWMzdjMCwwLjgtMC4zLDEuNS0wLjksMi4xDQoJQzM4LjUsMzkuNywzNy44LDQwLDM3LDQwSDExeiBNMjIuNSwzMi4zVjEzLjhsLTYsNmwtMi4xLTIuMUwyNCw4bDkuNyw5LjZsLTIuMiwyLjFsLTYtNnYxOC41SDIyLjV6Ii8+DQo8L3N2Zz4NCg==)" const importImageOverlay = document.createElement("div") importImageOverlay.className = "brownButton brownButton_classic" importImageOverlay.style.width = "30px" importImageOverlay.style.height = "30px" importImageOverlay.style.backgroundSize = "80%" importImageOverlay.style.backgroundPosition = "center" importImageOverlay.style.backgroundRepeat = "no-repeat" importImageOverlay.style.backgroundImage = "url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iNDhweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iNDhweCIgZmlsbD0iI0ZGRkZGRiI+PHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTIyIDE4VjJINnYxNmgxNnptLTExLTZsMi4wMyAyLjcxTDE2IDExbDQgNUg4bDMtNHpNMiA2djE2aDE2di0ySDRWNkgyeiIvPjwvc3ZnPg==)" importImageOverlay.addEventListener("click", () => { if (overlayEditing) { importImageOverlay.style.backgroundImage = "url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iNDhweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iNDhweCIgZmlsbD0iI0ZGRkZGRiI+PHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTIyIDE4VjJINnYxNmgxNnptLTExLTZsMi4wMyAyLjcxTDE2IDExbDQgNUg4bDMtNHpNMiA2djE2aDE2di0ySDRWNkgyeiIvPjwvc3ZnPg==)" imageOverlayContainer.style.pointerEvents = null document.getElementById("skineditor_previewbox_skincontainer").style.pointerEvents = null overlayEditing = false } else { imageOverlay.style.backgroundImage = null tmpEle2.click() } }) document.getElementById("skineditor_cancelbutton").style.position = "initial" document.getElementById("skineditor_savebutton").style.position = "initial" skinButtonsContainer.appendChild(document.getElementById("skineditor_cancelbutton")) skinButtonsContainer.appendChild(document.getElementById("skineditor_savebutton")) skinButtonsContainer.appendChild(importImageOverlay) skinButtonsContainer.appendChild(importSkin) const skinColourPickerContainerButton = document.createElement("div") skinColourPickerContainerButton.id = "skinColourPickerContainerButton" const skinHexColourPicker = document.createElement("div") skinHexColourPicker.className = "brownButton brownButton_classic buttonShadow" skinHexColourPicker.innerText = "#" skinHexColourPicker.onclick = () => { const hexCode = window.prompt("Hex Code", "#") try { showColorPickerArguments[0] = parseInt(hexCode.replace("#", ""), 16) showColorPicker(...showColorPickerArguments) } catch (error) {} } skinColourPickerContainerButton.appendChild(skinHexColourPicker) skinColourPickerContainerButton.appendChild(document.getElementById("skineditor_colorpicker_cancelbutton")) skinColourPickerContainerButton.appendChild(document.getElementById("skineditor_colorpicker_savebutton")) document.getElementById("skineditor_colorpicker").appendChild(skinColourPickerContainerButton) // SKIN IMAGE OVERLAY const imageOverlayContainer = document.createElement("div") imageOverlayContainer.id = "imageOverlayContainer" const imageOverlay = document.createElement("div") imageOverlay.id = "imageOverlay" imageOverlayContainer.appendChild(imageOverlay) document.getElementById("skineditor_previewbox").appendChild(imageOverlayContainer) // WS SENDER AND RECEIVER let wsextra = [] let ws = null let originalSend = window.WebSocket.prototype.send window.WebSocket.prototype.send = function (args) { if (this.url.includes(".bonk.io/socket.io/?EIO=3&transport=websocket&sid=")) { if (typeof args == "string" && !wsextra.includes(this)) { if (!ws) { ws = this } try { if (args.startsWith("42[")) { let data = JSON.parse(/42(.*)/.exec(args)[1]) handleOwnData(data, this) } } catch (error) { console.log(args) console.log(error) } } } else if (args.includes("rport")) { return } if (this.url.includes(".bonk.io/socket.io/?EIO=3&transport=websocket&sid=") && !this.injected) { this.injected = true let originaReceiveMessage = this.onmessage this.onmessage = (e) => { if (!wsextra.includes(this)) { if (typeof e.data == "string") { try { if (e.data.startsWith("42[")) { handleData(JSON.parse(/42(.*)/.exec(e.data)[1]), this) } } catch (error) { console.log(e.data) console.log(error) } } } return originaReceiveMessage.call(this, e) } let originalClose = this.onclose this.onclose = function () { if (wsextra.includes(this)) { wsextra.splice(wsextra.indexOf(this), 1) } else { ws = null panelLeft.style.visibility = "hidden" panelRight.style.visibility = "hidden" } return originalClose.call(this) } } return originalSend.call(this, args) } function iosend(data) { if (ws == null) return ws.send(`42${JSON.stringify(data)}`) } function ioreceive(data) { if (ws == null) return ws.onmessage({ data: `42${JSON.stringify(data)}` }) } // HANDLE DATA function handleData(data, websocket) { switch (data[0]) { case 1: // got ping data originalSend.call(websocket, `42[1,{"id":${data[1]}}]`) for (const id in data[1]) { if (ROOM_VAR.players[id]) { ROOM_VAR.players[id].ping = data[1][id] } } SCENES.updatePlayersPing() break case 2: // room Created inLobby = true ROOM_VAR.quick = false ROOM_VAR.bal = [] ROOM_VAR.chatAvatarCache = [] ROOM_VAR.commandAvatarCache = [] ROOM_VAR.playersAvatarCache = [] ROOM_VAR.xpEarned = 0 SCENES.system() SCENES.chat() SCENES.players() SCENES.leaderboard() break case 3: // joined Room panelLeft.style.visibility = "visible" panelRight.style.visibility = "visible" ROOM_VAR.players = data[3] ROOM_VAR.hostID = data[2] ROOM_VAR.quick = false ROOM_VAR.xpEarned = 0 ROOM_VAR.chatAvatarCache = [] ROOM_VAR.commandAvatarCache = [] ROOM_VAR.playersAvatarCache = [] SCENES.system() SCENES.chat() SCENES.players() if (ROOM_VAR.players[data[1]].userName == document.getElementById("pretty_top_name").textContent) { ROOM_VAR.myID = data[1] ws = websocket } else { wsextra.push(websocket) } break case 4: // new player joined FUNCTIONS.showSystemMessage(data[3] + " has joined the game", "#b53030", true) ROOM_VAR.players[data[1]] = { peerID: data[2], userName: data[3], guest: data[4], level: data[5], team: data[6], avatar: data[7] } SCENES.players() break case 5: // someone left FUNCTIONS.showSystemMessage(ROOM_VAR.players[data[1]].userName + " has left the game", "#b53030", true) ROOM_VAR.players[data[1]] = null SCENES.players() break case 6: // host left ROOM_VAR.hostID = data[2] if (data[2] == -1) { FUNCTIONS.showSystemMessage(`${ROOM_VAR.players[data[1]].userName} has left the game and closed the room`, "#b53030", true) } else { FUNCTIONS.showSystemMessage( `${ROOM_VAR.players[data[1]].userName} has left the game and ${ROOM_VAR.players[data[2]].userName} is now the game host`, "#b53030", true ) } if (data[2] == ROOM_VAR.myID) { FUNCTIONS.showSystemMessage("You are now the host of this game", "#800d6e") } ROOM_VAR.players[data[1]] = null SCENES.players() break case 8: // ready change ROOM_VAR.players[data[1]].ready = data[2] SCENES.players() break case 13: // return to lobby inLobby = true SCENES.leaderboard() break case 15: // game started inLobby = false SCENES.leaderboard() break case 16: // status (something like chat rate limited) if (["rate_limit_ready", "chat_rate_limit"].includes(data[1])) { FUNCTIONS.showSystemMessage("You're doing that too much!", "#cc4444") } else if (data[1] == "teams_locked") { FUNCTIONS.showSystemMessage("Failed, teams have been locked, only the host can assign teams", "#cc4444") } break case 18: // team changed ROOM_VAR.players[data[1]].team = data[2] SCENES.players() break case 19: // team lock changed if (data[1]) { FUNCTIONS.showSystemMessage("Teams have been locked, only the host can assign teams", "#b53030") } else { FUNCTIONS.showSystemMessage("Teams have been unlocked", "#b53030") } break case 20: // chat messages FUNCTIONS.showChatMessage(data[2], data[1]) break case 21: // game settings first load inLobby = true SCENES.leaderboard() ROOM_VAR.bal = data[1].bal break case 24: // kicked FUNCTIONS.showSystemMessage(`${ROOM_VAR.players[data[1]].userName} was ${data[2] ? "kicked" : "banned"}!`, "#b53030") break case 26: // change gamo let mode = "Classic" switch (data[2]) { case "b": mode = "Classic" break case "ar": mode = "Arrows" break case "ard": mode = "Death Arrows" break case "sp": mode = "Grapple" break case "f": mode = "Football" break case "v": mode = "VTOL" break } FUNCTIONS.showSystemMessage("Game mode changed to: " + mode, "#800d6e") break case 27: // change win lose FUNCTIONS.showSystemMessage("Rounds to win changed to: " + data[1], "#800d6e") break case 32: // afk warn FUNCTIONS.showSystemMessage("STOP AFK, WAKE UP!!!", "#b53030") break case 36: // balance ROOM_VAR.bal[data[1]] = data[2] SCENES.players() break case 39: // team settings change let onoroff = data[1] ? "on" : "off" FUNCTIONS.showSystemMessage(`Teams ${onoroff}`, "#800d6e") break case 40: // arm record if (data[1] != ROOM_VAR.myID) { FUNCTIONS.showSystemMessage(`${ROOM_VAR.players[data[1]].userName} requests record gameplay`, "#b53030") } break case 41: // host changed FUNCTIONS.showSystemMessage( ROOM_VAR.players[data[1].oldHost].userName + " has given host privileges to " + ROOM_VAR.players[data[1].newHost].userName + ", who is now the game host", "#b53030" ) if (data[1].newHost == ROOM_VAR.myID) { FUNCTIONS.showSystemMessage("You are now the host of this game", "#800d6e") } ROOM_VAR.hostID = data[1].newHost SCENES.players() break case 43: // countdown FUNCTIONS.showSystemMessage("Game starting in " + data[1], "#0955c7") break case 44: // countdown aborted FUNCTIONS.showSystemMessage("Countdown aborted!", "#0955c7") break case 45: // player leveled up ROOM_VAR.players[data[1].sid].level = data[1].lv SCENES.players() break case 46: // gained xp ROOM_VAR.xpEarned += 100 break case 48: // show in game data if just joined inLobby = false SCENES.leaderboard() ROOM_VAR.bal = data[1].gs.bal ROOM_VAR.quick = data[1].gs.q break case 49: // autojoin ROOM_VAR.autoJoinID = data[1] ROOM_VAR.autoJoinPassBypass = data[2] break case 52: // tabbed update ROOM_VAR.players[data[1]].tabbed = data[2] SCENES.updatePlayersPing() break case 58: // room name changed FUNCTIONS.showSystemMessage("Room name changed to: " + data[1], "#800d6e") break case 59: // room password changed if (data[1]) { FUNCTIONS.showSystemMessage("A new password has been set for this room", "#800d6e") } else { FUNCTIONS.showSystemMessage("This room no longer requires a password to join.", "#800d6e") } break } } // HANDLE OWN DATA function handleOwnData(data, websocket) { switch (data[0]) { case 5: ROOM_VAR.quick = data[1].gs.q break case 14: // Own quit game inLobby = true SCENES.leaderboard() break case 12: // Created room ROOM_VAR.myID = 0 ROOM_VAR.hostID = 0 ws = websocket panelLeft.style.visibility = "visible" panelRight.style.visibility = "visible" ROOM_VAR.players = [] let tmpdata = data[1] tmpdata.userName = document.getElementById("pretty_top_name").innerText if (!data[1].guest) { tmpdata.level = parseInt(document.getElementById("pretty_top_level").innerText.substring(3)) } ROOM_VAR.players.push(tmpdata) break case 20: // Change GAMO ioreceive([26, data[1].ga, data[1].mo]) break case 21: // Change win lose ioreceive([27, data[1].w]) break case 32: // Change teamchain ioreceive([39, data[1].t]) break case 29: // Change balance ioreceive([36, data[1].sid, data[1].bal]) break } } setInterval(() => { SCENES.leaderboard() }, 1000)