(function servermod() { ModAPI.meta.title("Server Manager"); ModAPI.meta.version("a0"); ModAPI.meta.description("_"); ModAPI.meta.credits("ZXMushroom63 & radmanplays"); const gui = document.createElement("div"); gui.style.background = "black"; gui.style.fontFamily = "sans-serif"; gui.style.zIndex = 254; gui.style.position = "fixed"; gui.style.display = "none"; gui.style.color = "white"; gui.style.top = gui.style.left = gui.style.bottom = gui.style.right = 0; document.documentElement.appendChild(gui); var cmdbox = document.createElement("input"); cmdbox.style.position = "absolute"; cmdbox.style.left = "0"; cmdbox.style.bottom = "0"; cmdbox.style.right = "0"; cmdbox.style.position = "inline-block"; cmdbox.style.border = "0"; cmdbox.style.borderTop = "2px solid white"; cmdbox.style.background = "black"; cmdbox.style.zIndex = 255; cmdbox.style.color = "white"; cmdbox.type = "text"; cmdbox.addEventListener("keydown", (e) => { e.stopPropagation(); e.stopImmediatePropagation(); }, true); cmdbox.addEventListener("keyup", (e) => { e.stopPropagation(); e.stopImmediatePropagation(); if (e.key === "Enter") { e.preventDefault(); toServer("chat", cmdbox.value); } }, true); document.documentElement.appendChild(cmdbox); function worldUpdate() { if (ModAPI.mc && ModAPI.mc.theWorld) { showgui(); openSharedWorld() } else { hidegui(); } } setInterval(() => { worldUpdate(); }, 100); function showgui() { gui.style.opacity = "1"; gui.style.display = "block"; cmdbox.style.opacity = "1"; cmdbox.style.display = "block"; } function hidegui() { gui.style.opacity = "0"; gui.style.display = "none"; cmdbox.style.opacity = "0"; cmdbox.style.display = "none"; } function openSharedWorld(){ if(ModAPI.mc.theWorld && !ModAPI.hooks.methods.nlevsl_LANServerController_isLANOpen()){ ModAPI.hooks.methods.nlevi_PlatformWebRTC_startRTCLANServer(); var worldName = ModAPI.util.unstr(ModAPI.mc.thePlayer.getName()) + "'s World"; var ls = ModAPI.mc.loadingScreen; var code = ModAPI.hooks.methods.nlevsl_LANServerController_shareToLAN(ls.resetProgressAndMessage, worldName, false) if (code != null) { ModAPI.hooks.methods.nlevs_SingleplayerServerController_configureLAN(ModAPI.mc.playerController.getCurrentGameType(), false); alert("code: " + code +" relay: " + ModAPI.hooks.methods.nlevsl_LANServerController_getCurrentURI()) } } else { return; } } /* NETWORKING OPCODES chat - bidirectional, send chat to server/client */ function toServer(opcode, data) { client_comms_channel.postMessage({ opcode: opcode, audience: "server", data: data, }); } var token = crypto.randomUUID(); const clientMessageHandlers = { chat: function (data) { gui.innerText += data + "\n"; }, }; var client_comms_channel = new BroadcastChannel("efserv:" + token); client_comms_channel.addEventListener("message", (ev)=>{ if (ev.data.audience !== "client") { return; } if (clientMessageHandlers[ev.data.opcode]) { clientMessageHandlers[ev.data.opcode](ev.data.data); } }); ModAPI.dedicatedServer.appendCode( `globalThis.efhost_security_token = "${token}";` ); ModAPI.dedicatedServer.appendCode(function () { var comms = new BroadcastChannel( "efserv:" + globalThis.efhost_security_token ); function toClient(opcode, data) { comms.postMessage({ opcode: opcode, audience: "client", data: data, }); } function getHostPlayer() { var host = null; ModAPI.server.getRef().$worldServers.data.forEach((world) => { host ||= world.$playerEntities.$array1.data.find((player) => { var nameKey = ModAPI.util.getNearestProperty( player.$gameProfile, "$name" ); return ModAPI.util.ustr(player.$gameProfile[nameKey]) === "HOST"; }); }); return host; } const messageHandlers = { chat: function (data) { ModAPI.hooks.methods.nmc_CommandHandler_executeCommand( ModAPI.server.commandManager.getRef(), getHostPlayer(), ModAPI.util.str(data) ); //host has to use /say }, }; comms.addEventListener("message", (ev) => { if (ev.data.audience !== "server") { return; } if (messageHandlers[ev.data.opcode]) { messageHandlers[ev.data.opcode](ev.data.data); } }); var oldLog = ModAPI.hooks.methods.nlevl_Logger_log; ModAPI.hooks.methods.nlevl_Logger_log = function (...args) { toClient("chat", ModAPI.util.ustr(args[2])); return oldLog.apply(this, args); }; }); function renameButton(array, originalName, newName) { array.find( (x) => ModAPI.util.ustr(x.displayString.getRef()) === originalName ).displayString = ModAPI.util.str(newName); } const mainmenuinit = ModAPI.hooks.methods.nmcg_GuiMainMenu_initGui; ModAPI.hooks.methods.nmcg_GuiMainMenu_initGui = function (...args) { var result = mainmenuinit.apply(this, args); var wrappedGuiObject = ModAPI.util.wrap(args[0], args[0], false, false); wrappedGuiObject.splashText = ModAPI.util.str("Server Hosting Mode"); var btnarray = wrappedGuiObject.buttonList.array1; renameButton(btnarray, "Singleplayer", "Host Server"); return result; }; const GuiSelectWorldinit = ModAPI.hooks.methods.nmcg_GuiSelectWorld_initGui; ModAPI.hooks.methods.nmcg_GuiSelectWorld_initGui = function (...args) { var result = GuiSelectWorldinit.apply(this, args); var wrappedGuiObject = ModAPI.util.wrap(args[0], args[0], false, false); var btnarray = wrappedGuiObject.buttonList.array1.data; //renameButton(btnarray, "Create", "Create Server"); return result; }; const mainmenuactions = ModAPI.hooks.methods.nmcg_GuiMainMenu_actionPerformed; ModAPI.hooks.methods.nmcg_GuiMainMenu_actionPerformed = function (...args) { ModAPI.hooks.methods.nlevp_EaglerProfile_setName(ModAPI.util.str("HOST")); var idKey = ModAPI.util.getNearestProperty(args[1], "$id"); var guiButtonid = args[1][idKey]; var blockedIds = [2]; // put the blocked/disabled button ids in there if (blockedIds.includes(guiButtonid)) { return 0; } return mainmenuactions.apply(this, args); }; // disable rendering ModAPI.hooks.methods.nmcr_EntityRenderer_renderWorld = () => { }; })();