Merge pull request #69 from eaglerforge/main

EFServer alpha release
This commit is contained in:
ZXMushroom63 2025-03-17 20:03:54 +08:00 committed by GitHub
commit 685e76dd1c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 377 additions and 23 deletions

View File

@ -1,4 +1,284 @@
function EFServer() {
//Todo: write mod that disables rendering engine, autodisplays gui, and makes run server button.
console.log("hello world");
ModAPI.meta.title("Server Manager");
ModAPI.meta.version("a0");
ModAPI.meta.description("_");
ModAPI.meta.credits("ZXMushroom63 & radmanplays");
const gui = document.createElement("div");
gui.innerText = "EFSERVER CONSOLE";
gui.style.background = "black";
gui.style.fontFamily = "sans-serif";
gui.style.zIndex = 254;
gui.style.position = "fixed";
gui.style.display = "none";
gui.style.height = "calc(100vh - 1rem - 4px)";
gui.style.overflowY = "scroll";
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.style.height = "1rem";
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);
cmdbox.value = "";
}
}, true);
document.documentElement.appendChild(cmdbox);
function worldUpdate() {
if (ModAPI.mc && ModAPI.mc.theWorld) {
ModAPI.hooks.methods.nmcs_GameSettings_saveOptions = ()=>{};
ModAPI.settings.limitFramerate = 1;
ModAPI.settings.enableVsync = 0;
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 EFB2__defineExecCmdAsGlobal() {
var getServer = ModAPI.reflect.getClassById("net.minecraft.server.MinecraftServer").staticMethods.getServer.method;
globalThis.efb2__executeCommandAs = function efb2__executeCommandAs($commandsender, command, feedback) {
var server = getServer();
if (!server) { return };
var commandManager = server.$commandManager;
//lie a bit
var x = $commandsender.$canCommandSenderUseCommand;
$commandsender.$canCommandSenderUseCommand = () => 1;
var y = $commandsender.$sendCommandFeedback;
$commandsender.$sendCommandFeedback = feedback ? () => 1 : () => 0;
try {
commandManager.$executeCommand($commandsender, ModAPI.util.str(command));
} catch (error) {
console.error(error);
}
$commandsender.$canCommandSenderUseCommand = x;
$commandsender.$sendCommandFeedback = y;
}
}
ModAPI.dedicatedServer.appendCode(EFB2__defineExecCmdAsGlobal);
ModAPI.hooks.methods.nmc_LoadingScreenRenderer_eaglerShow = ()=>{};
var opening = false;
function openSharedWorld() {
var platform = ModAPI.reflect.getClassById("net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC");
if (!opening && ModAPI.mc.theWorld && !ModAPI.hooks.methods.nlevsl_LANServerController_isLANOpen()) {
platform.staticVariables.rtcLANServer = ModAPI.reflect.getClassById("net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC$LANServer").constructors[0]();
var worldName = ModAPI.util.unstr(ModAPI.mc.thePlayer.getName().getRef()) + "'s World";
opening = true;
ModAPI.promisify(ModAPI.hooks.methods.nlevsl_LANServerController_shareToLAN)({
$accept: (status)=>{
gui.innerText += "\n" + ModAPI.util.ustr(status);
}
}, ModAPI.util.str(worldName), 0).then(code => {
opening = true; //change to false later
if (code != null) {
ModAPI.hooks.methods.nlevs_SingleplayerServerController_configureLAN(ModAPI.mc.playerController.currentGameType.getRef(), 0);
var msg = "code: " + ModAPI.util.ustr(code) + " relay: " + ModAPI.util.ustr(ModAPI.hooks.methods.nlevsl_LANServerController_getCurrentURI());
alert(msg);
gui.innerText += "\n" + msg;
}
});
} 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) {
if (gui.scrollHeight > (innerHeight * 5)) {
gui.innerText = "Console cleared. Logs were over 5 pages long.";
}
gui.innerText += "\n" + data.replaceAll("§r", "");
gui.scrollTop = gui.scrollHeight;
},
};
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) => {
if (!player) {
return;
}
var nameKey = ModAPI.util.getNearestProperty(
player.$gameProfile,
"$name"
);
return ModAPI.util.ustr(player.$gameProfile[nameKey]) === "HOST";
});
});
return host;
}
const messageHandlers = {
chat: function (data) {
var host = getHostPlayer();
if (!host) {
return;
}
host.$addChatMessage = (comp)=>{toClient("chat", ModAPI.util.ustr(comp.$getUnformattedText()))};
efb2__executeCommandAs(getHostPlayer(), data, true);
},
};
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);
};
ModAPI.addEventListener("tick", ()=>{
var host = ModAPI.util.wrap(getHostPlayer());
if (!host) {
return;
}
host.posY = -10;
host.posX = 0;
host.posZ = 0;
host.capabilities.disableDamage = 1;
host.capabilities.isCreativeMode = 1;
host.capabilities.isFlying = 1;
host.motionY = 0;
host.motionX = 0;
host.motionZ = 0;
host.isDead = 0;
host.setHealth(20);
});
});
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 = () => { };
}

View File

@ -6,11 +6,14 @@
const gui = document.createElement("div");
gui.innerText = "EFSERVER CONSOLE";
gui.style.background = "black";
gui.style.fontFamily = "sans-serif";
gui.style.zIndex = 254;
gui.style.position = "fixed";
gui.style.display = "none";
gui.style.height = "calc(100vh - 1rem - 4px)";
gui.style.overflowY = "scroll";
gui.style.color = "white";
gui.style.top = gui.style.left = gui.style.bottom = gui.style.right = 0;
document.documentElement.appendChild(gui);
@ -26,6 +29,7 @@
cmdbox.style.background = "black";
cmdbox.style.zIndex = 255;
cmdbox.style.color = "white";
cmdbox.style.height = "1rem";
cmdbox.type = "text";
cmdbox.addEventListener("keydown", (e) => {
e.stopPropagation();
@ -37,12 +41,16 @@
if (e.key === "Enter") {
e.preventDefault();
toServer("chat", cmdbox.value);
cmdbox.value = "";
}
}, true);
document.documentElement.appendChild(cmdbox);
function worldUpdate() {
if (ModAPI.mc && ModAPI.mc.theWorld) {
ModAPI.hooks.methods.nmcs_GameSettings_saveOptions = ()=>{};
ModAPI.settings.limitFramerate = 1;
ModAPI.settings.enableVsync = 0;
showgui();
openSharedWorld()
} else {
@ -67,17 +75,53 @@
cmdbox.style.display = "none";
}
function EFB2__defineExecCmdAsGlobal() {
var getServer = ModAPI.reflect.getClassById("net.minecraft.server.MinecraftServer").staticMethods.getServer.method;
globalThis.efb2__executeCommandAs = function efb2__executeCommandAs($commandsender, command, feedback) {
var server = getServer();
if (!server) { return };
var commandManager = server.$commandManager;
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())
}
//lie a bit
var x = $commandsender.$canCommandSenderUseCommand;
$commandsender.$canCommandSenderUseCommand = () => 1;
var y = $commandsender.$sendCommandFeedback;
$commandsender.$sendCommandFeedback = feedback ? () => 1 : () => 0;
try {
commandManager.$executeCommand($commandsender, ModAPI.util.str(command));
} catch (error) {
console.error(error);
}
$commandsender.$canCommandSenderUseCommand = x;
$commandsender.$sendCommandFeedback = y;
}
}
ModAPI.dedicatedServer.appendCode(EFB2__defineExecCmdAsGlobal);
ModAPI.hooks.methods.nmc_LoadingScreenRenderer_eaglerShow = ()=>{};
var opening = false;
function openSharedWorld() {
var platform = ModAPI.reflect.getClassById("net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC");
if (!opening && ModAPI.mc.theWorld && !ModAPI.hooks.methods.nlevsl_LANServerController_isLANOpen()) {
platform.staticVariables.rtcLANServer = ModAPI.reflect.getClassById("net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC$LANServer").constructors[0]();
var worldName = ModAPI.util.unstr(ModAPI.mc.thePlayer.getName().getRef()) + "'s World";
opening = true;
ModAPI.promisify(ModAPI.hooks.methods.nlevsl_LANServerController_shareToLAN)({
$accept: (status)=>{
gui.innerText += "\n" + ModAPI.util.ustr(status);
}
}, ModAPI.util.str(worldName), 0).then(code => {
opening = true; //change to false later
if (code != null) {
ModAPI.hooks.methods.nlevs_SingleplayerServerController_configureLAN(ModAPI.mc.playerController.currentGameType.getRef(), 0);
var msg = "code: " + ModAPI.util.ustr(code) + " relay: " + ModAPI.util.ustr(ModAPI.hooks.methods.nlevsl_LANServerController_getCurrentURI());
alert(msg);
gui.innerText += "\n" + msg;
}
});
} else {
return;
}
@ -100,11 +144,15 @@
var token = crypto.randomUUID();
const clientMessageHandlers = {
chat: function (data) {
gui.innerText += data + "\n";
if (gui.scrollHeight > (innerHeight * 5)) {
gui.innerText = "Console cleared. Logs were over 5 pages long.";
}
gui.innerText += "\n" + data.replaceAll("§r", "");
gui.scrollTop = gui.scrollHeight;
},
};
var client_comms_channel = new BroadcastChannel("efserv:" + token);
client_comms_channel.addEventListener("message", (ev)=>{
client_comms_channel.addEventListener("message", (ev) => {
if (ev.data.audience !== "client") {
return;
}
@ -132,6 +180,9 @@
var host = null;
ModAPI.server.getRef().$worldServers.data.forEach((world) => {
host ||= world.$playerEntities.$array1.data.find((player) => {
if (!player) {
return;
}
var nameKey = ModAPI.util.getNearestProperty(
player.$gameProfile,
"$name"
@ -144,11 +195,12 @@
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
var host = getHostPlayer();
if (!host) {
return;
}
host.$addChatMessage = (comp)=>{toClient("chat", ModAPI.util.ustr(comp.$getUnformattedText()))};
efb2__executeCommandAs(getHostPlayer(), data, true);
},
};
@ -166,9 +218,27 @@
toClient("chat", ModAPI.util.ustr(args[2]));
return oldLog.apply(this, args);
};
ModAPI.addEventListener("tick", ()=>{
var host = ModAPI.util.wrap(getHostPlayer());
if (!host) {
return;
}
host.posY = -10;
host.posX = 0;
host.posZ = 0;
host.capabilities.disableDamage = 1;
host.capabilities.isCreativeMode = 1;
host.capabilities.isFlying = 1;
host.motionY = 0;
host.motionX = 0;
host.motionZ = 0;
host.isDead = 0;
host.setHealth(20);
});
});
function renameButton(array, originalName, newName) {
array.find(

View File

@ -99,8 +99,8 @@
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code id="status">Awaiting input...</code></span>
<br /><br />
<button class="btn btn-primary" id="giveme">Make modded client</button>
<button class="btn btn-primary" id="givemeserver" disabled>
Make modded server (coming soonish maybe)
<button class="btn btn-primary" id="givemeserver">
Make modded server (cALPHA)
</button>
</div>

View File

@ -387,8 +387,12 @@ document.querySelector("#givemeserver").addEventListener("click", () => {
patchedFile = await shronk(patchedFile);
}
patchedFile.replace(`{"._|_libserverside_|_."}`, `(${EFServer.toString()})()`);
patchedFile = patchedFile.replace(`{"._|_libserverside_|_."}`, `(${EFServer.toString()})()`);
backgroundLog("[EFSERVER] Injecting libserverside corelib");
patchedFile = patchedFile.replace("<title>EFI", "<title>EF Server");
backgroundLog("[EFSERVER] Patching title");
var blob = new Blob([patchedFile], { type: file.type });
saveAs(blob, "efserver." + fileType);
backgroundLog("Saving file...", true);
});
});