// ==UserScript==
// @name KeyTable
// @version 1.4.2
// @description Add a customizable key table overlay to the bonk.io game
// @author BZD + Clarifi
// @namespace http://tampermonkey.net/
// @license MIT
// @match https://bonk.io/gameframe-release.html
// @run-at document-end
// @grant none
// ==/UserScript==
// ! Compitable with Bonk Version 49
window.KeyTable = {}; // Namespace for encapsulating the UI functions and variables
// Use 'strict' mode for safer code by managing silent errors
'use strict';
KeyTable.windowConfigs = {
windowName: "KeyTable",
windowId: "keytable_window",
modVersion: "1.4.2",
bonkLIBVersion: "1.1.3",
bonkVersion: "49",
};
// Variable to track the most recent key input by the user
KeyTable.latestInput = 0;
KeyTable.currentPlayerID = 0;
KeyTable.frameCount = [0, 0, 0, 0, 0, 0];
// !could make these arrays but better visibly (specific naming)
KeyTable.keys = {};
KeyTable.keyFilter = {
'left': 1, 'right': 2, 'up': 4, 'down': 8, 'heavy': 16, 'special': 32
};
// Refresh the styles for all keys on the UI
KeyTable.updateKeyStyles = () => {
Object.entries(KeyTable.keys).forEach(([dir, element]) => {
// Change the key's background color if it's currently pressed
element.style.backgroundColor = KeyTable.latestInput & KeyTable.keyFilter[dir] ? bonkHUD.styleHold.buttonColorHover.color : bonkHUD.styleHold.buttonColor.color;
});
};
// Reset the background color of all keys to the default state
KeyTable.keyTableReset = () => {
Object.entries(KeyTable.keys).forEach(([dir, element]) => {
element.style.backgroundColor = bonkHUD.styleHold.buttonColor.color;
});
};
// Event listener function to change the player selected in the player selector
KeyTable.select_player = () => {
let player_selector = document.getElementById("player_selector");
let player_id = player_selector.options[player_selector.selectedIndex].value;
KeyTable.currentPlayerID = player_id;
KeyTable.updateKeyStyles();
//console.log("current Player ID: " + player_id);
};
// Create a new option in the player selector
KeyTable.create_option = (userID) => {
//console.log("userID:" + userID);
let playerName = bonkAPI.getPlayerNameByID(userID);
let player_selector = document.getElementById("player_selector");
let newOption = document.createElement("option");
newOption.textContent = playerName;
newOption.value = userID;
newOption.id = "selector_option_" + userID;
player_selector.appendChild(newOption);
KeyTable.updateKeyStyles();
//console.log("selector_option_" + userID + " added to player_selector");
};
// Remove an option from the player selector
KeyTable.remove_option = (userID) => {
let player_selector = document.getElementById("player_selector");
let option = document.getElementById("selector_option_" + userID);
player_selector.removeChild(option);
};
// Reset the player selector to the default state
KeyTable.reset_selector = () => {
// Remove all options except the default one
let player_selector = document.getElementById("player_selector");
Array.from(player_selector.options).forEach((option) => {
if (option.id !== "selector_option_user") {
player_selector.removeChild(option);
}
// Reset the current player ID
KeyTable.currentPlayerID = bonkAPI.getMyID();
// Set the selector to the first option as default
player_selector.selectedIndex = bonkAPI.getMyID();
});
};
// Update the player list in the player selector
KeyTable.update_players = () => {
// Get the list of players and the current player ID
let playerList = bonkAPI.getPlayerList();
let myID = bonkAPI.getMyID();
// Reset the player selector
KeyTable.reset_selector();
// Add all player to the player selector
playerList.forEach((player, id) => {
if (player && id !== myID) {
KeyTable.create_option(id);
}
});
};
// Process input data and invoke style updates
bonkAPI.addEventListener("gameInputs", (e) => {
// console.log("gameInputs event received", e);
if (e.userID == KeyTable.currentPlayerID) {
// console.log("Updating latestInput for player", readingPlayerID, "with input", e.rawInput);
KeyTable.latestInput = e.rawInput;
KeyTable.updateKeyStyles();
}
});
/*bonkAPI.addEventListener("stepEvent", (e) => {
for(int i = 0; i < KeyTable.keys) {
}
});*/
// Event listener for when a user joins the game
bonkAPI.addEventListener("userJoin", (e) => {
//console.log("User join event received", e);
//console.log("User ID", e.userID);
// Add the player to the player selector
KeyTable.create_option(e.userID);
});
// Event listener for when a user leaves the game
bonkAPI.addEventListener("userLeave", (e) => {
//console.log("User Leave event received", e);
//console.log("User ID", e.userID);
// Remove the player from the player selector
let playerName = bonkAPI.getPlayerNameByID(e.userID);
let player_selector = document.getElementById("player_selector");
// If the player is the current player, set the current player to 0 and reset the selector
if (player_selector.options[player_selector.selectedIndex].value === playerName) {
KeyTable.currentPlayerID = bonkAPI.getMyID();
// Set the selector to the first option as default
player_selector.selectedIndex = 0;
}
KeyTable.remove_option(e.userID);
});
// Event listener for when user(mod user) creates a room
bonkAPI.addEventListener("createRoom", (e) => {
//console.log("create Room event received", e);
//console.log("User ID", e);
// Set the player name in the player selector to the current user
let option = document.getElementById("selector_option_user");
let playerName = bonkAPI.getPlayerNameByID(e.userID);
option.textContent = playerName;
option.value = e.userID;
KeyTable.currentPlayerID = e.userID;
// Reset the player selector to the default state
KeyTable.reset_selector();
});
// Event listener for when user(mod user) joins a room
bonkAPI.addEventListener("joinRoom", (e) => {
//console.log("on Join event received", e);
//console.log("User ID", e.userID);
// Set the player name in the player selector to the current user
let option = document.getElementById("selector_option_user");
let playerName = bonkAPI.getPlayerNameByID(bonkAPI.getMyID());
option.textContent = playerName;
option.value = bonkAPI.getMyID();
KeyTable.currentPlayerID = bonkAPI.getMyID();
// Update the player list in the player selector
KeyTable.update_players();
});
// Main function to construct and add the key table UI to the DOM
const addKeyTable = () => {
// Create the key table
let keyTable = document.createElement("div");
let keyHold = document.createElement("table");
keyHold.style.flex = "1 1 auto";
let tableBody = document.createElement("tbody");
let topRow = document.createElement("tr");
KeyTable.keys["special"] = document.createElement("td");
KeyTable.keys["special"].classList.add("bonkhud-button-color");
KeyTable.keys["special"].classList.add("bonkhud-text-color");
KeyTable.keys["special"].style.width = "34%";
KeyTable.keys["special"].style.textAlign = "center";
KeyTable.keys["special"].textContent = "Special";
KeyTable.keys["up"] = document.createElement("td");
KeyTable.keys["up"].classList.add("bonkhud-button-color");
KeyTable.keys["up"].classList.add("bonkhud-text-color");
KeyTable.keys["up"].style.width = "34%";
KeyTable.keys["up"].style.textAlign = "center";
KeyTable.keys["up"].textContent = "↑";
KeyTable.keys["heavy"] = document.createElement("td");
KeyTable.keys["heavy"].classList.add("bonkhud-button-color");
KeyTable.keys["heavy"].classList.add("bonkhud-text-color");
KeyTable.keys["heavy"].style.width = "34%";
KeyTable.keys["heavy"].style.textAlign = "center";
KeyTable.keys["heavy"].textContent = "Heavy";
let botRow = document.createElement("tr");
KeyTable.keys["left"] = document.createElement("td");
KeyTable.keys["left"].classList.add("bonkhud-button-color");
KeyTable.keys["left"].classList.add("bonkhud-text-color");
KeyTable.keys["left"].style.width = "34%";
KeyTable.keys["left"].style.textAlign = "center";
KeyTable.keys["left"].textContent = "←";
KeyTable.keys["down"] = document.createElement("td");
KeyTable.keys["down"].classList.add("bonkhud-button-color");
KeyTable.keys["down"].classList.add("bonkhud-text-color");
KeyTable.keys["down"].style.width = "34%";
KeyTable.keys["down"].style.textAlign = "center";
KeyTable.keys["down"].textContent = "↓";
KeyTable.keys["right"] = document.createElement("td");
KeyTable.keys["right"].classList.add("bonkhud-button-color");
KeyTable.keys["right"].classList.add("bonkhud-text-color");
KeyTable.keys["right"].style.width = "34%";
KeyTable.keys["right"].style.textAlign = "center";
KeyTable.keys["right"].textContent = "→";
let pSelectorHold = document.createElement("div");
pSelectorHold.style.flex = "0 1 auto";
pSelectorHold.style.padding = "10px";
let pSelector = document.createElement("select");
pSelector.id = "player_selector";
let pOption = document.createElement("option");
pOption.id = "selector_option_user";
pOption.textContent = "......";
topRow.appendChild(KeyTable.keys["special"]);
topRow.appendChild(KeyTable.keys["up"]);
topRow.appendChild(KeyTable.keys["heavy"]);
botRow.appendChild(KeyTable.keys["left"]);
botRow.appendChild(KeyTable.keys["down"]);
botRow.appendChild(KeyTable.keys["right"]);
tableBody.appendChild(topRow);
tableBody.appendChild(botRow);
pSelector.appendChild(pOption);
pSelectorHold.appendChild(pSelector);
keyHold.appendChild(tableBody);
keyTable.appendChild(keyHold);
keyTable.appendChild(pSelectorHold);
let keyTableSettings = document.createElement('div');
keyTableSettings.style.margin = "10px";
let inputTopRow = document.createElement('div');
inputTopRow.style.display = "flex";
let heavyInput = document.createElement('input');
heavyInput.setAttribute("type", "text");
heavyInput.value = "Heavy";
heavyInput.style.minWidth = "0";
let upInput = document.createElement('input');
upInput.setAttribute("type", "text");
upInput.value = "↑";
upInput.style.minWidth = "0";
let specialInput = document.createElement('input');
specialInput.setAttribute("type", "text");
specialInput.value = "Special";
specialInput.style.minWidth = "0";
let inputBottomRow = document.createElement('div');
inputBottomRow.style.display = "flex";
let leftInput = document.createElement('input');
leftInput.setAttribute("type", "text");
leftInput.value = "←";
leftInput.style.minWidth = "0";
let downInput = document.createElement('input');
downInput.setAttribute("type", "text");
downInput.value = "↓";
downInput.style.minWidth = "0";
let rightInput = document.createElement('input');
rightInput.setAttribute("type", "text");
rightInput.value = "→";
rightInput.style.minWidth = "0";
inputTopRow.appendChild(specialInput);
inputTopRow.appendChild(upInput);
inputTopRow.appendChild(heavyInput);
inputBottomRow.appendChild(leftInput);
inputBottomRow.appendChild(downInput);
inputBottomRow.appendChild(rightInput);
keyTableSettings.appendChild(inputTopRow);
keyTableSettings.appendChild(inputBottomRow);
KeyTable.windowConfigs.settingsContent = keyTableSettings;
let keytable_index = bonkHUD.createWindow(
KeyTable.windowConfigs.windowName,
keyTable,
KeyTable.windowConfigs
);
let keytable_window = bonkHUD.getElementByIndex(keytable_index);
keytable_window.style.width = "100%";
keytable_window.style.height = "calc(100% - 32px)";
keytable_window.style.padding = "0";
keytable_window.style.display = "flex";
keytable_window.style.flexFlow = "column";
bonkHUD.loadUISetting(keytable_index);
let recoveredSetting = bonkHUD.getModSetting(keytable_index);
if(recoveredSetting) {
KeyTable.keys["heavy"].textContent = recoveredSetting["heavy"];
KeyTable.keys["up"].textContent = recoveredSetting["up"];
KeyTable.keys["special"].textContent = recoveredSetting["special"];
KeyTable.keys["left"].textContent = recoveredSetting["left"];
KeyTable.keys["down"].textContent = recoveredSetting["down"];
KeyTable.keys["right"].textContent = recoveredSetting["right"];
heavyInput.value = recoveredSetting["heavy"];
upInput.value = recoveredSetting["up"];
specialInput.value = recoveredSetting["special"];
leftInput.value = recoveredSetting["left"];
downInput.value = recoveredSetting["down"];
rightInput.value = recoveredSetting["right"];
}
let saveFunction = function() {
let setting = {
"heavy": heavyInput.value,
"up": upInput.value,
"special": specialInput.value,
"left": leftInput.value,
"down": downInput.value,
"right": rightInput.value,
};
bonkHUD.saveModSetting(keytable_index, setting);
KeyTable.keys["heavy"].textContent = heavyInput.value;
KeyTable.keys["up"].textContent = upInput.value;
KeyTable.keys["special"].textContent = specialInput.value;
KeyTable.keys["left"].textContent = leftInput.value;
KeyTable.keys["down"].textContent = downInput.value;
KeyTable.keys["right"].textContent = rightInput.value;
KeyTable.updateKeyStyles();
}
heavyInput.onchange = saveFunction;
upInput.onchange = saveFunction;
specialInput.onchange = saveFunction;
leftInput.onchange = saveFunction;
downInput.onchange = saveFunction;
rightInput.onchange = saveFunction;
// Initialize the key styles
KeyTable.updateKeyStyles();
};
// Initialization logic to set up the UI once the document is ready
const init = () => {
addKeyTable();
let playerSelector = document.getElementById("player_selector");
if (playerSelector) {
playerSelector.addEventListener("change", KeyTable.select_player);
} else {
console.error("player_selector element not found!");
}
};
if (document.readyState === "complete" || document.readyState === "interactive") {
init();
} else {
document.addEventListener("DOMContentLoaded", init);
}