From 846eb6533b106c699b9a8703cbacd9b21db26428 Mon Sep 17 00:00:00 2001 From: ZXMushroom63 Date: Thu, 5 Sep 2024 18:59:54 +0800 Subject: [PATCH] dedicatedserver, events, teavm quirks doc --- docs/apidoc/dedicatedserver.md | 31 ++++++++++++++- docs/apidoc/events.md | 70 +++++++++++++++++++++++++++++++++- docs/apidoc/index.md | 2 +- docs/quirks.md | 8 ++++ postinit.injector.js | 10 ++--- postinit.js | 2 +- 6 files changed, 113 insertions(+), 10 deletions(-) diff --git a/docs/apidoc/dedicatedserver.md b/docs/apidoc/dedicatedserver.md index cbdcd2c..3127e94 100644 --- a/docs/apidoc/dedicatedserver.md +++ b/docs/apidoc/dedicatedserver.md @@ -1 +1,30 @@ -## ModAPI.dedicatedServer \ No newline at end of file +## ModAPI.dedicatedServer + +This is the dedicated server module, used for modding singleplayer in more powerful ways. + +ModAPI.dedicatedServer has the following methods: + +- `appendCode(code: Function | String) : void` + - Injects provided code into the dedicated server. + + +### Modding the dedicated server +Eaglercraft runs the dedicated server in a service worker. This means that in order to run code to mod the dedicated server, you have to change context into the service worker. + +`ModAPI.dedicatedServer.appendCode()` allows you to inject code into the dedicates server before startup. The code injected will throw errors if it attempts to access resources outside the functions context. + +For example, take a look at this mod, which will inject some code that does nothing into the dedicated server: +```javascript +var myVariable = 4; +function myServerSideModCode() { + function subfunction() { + console.log("serverside!!!"); + } + subfunction(); + //Successfully running serverside + //However, we cannot access `myVariable` +} +ModAPI.dedicatedServer.appendCode(myServerSideModCode); +``` + +Once serverside, you can only access server side events, like `serverstart` or `tick`. \ No newline at end of file diff --git a/docs/apidoc/events.md b/docs/apidoc/events.md index 4ae110c..6e79485 100644 --- a/docs/apidoc/events.md +++ b/docs/apidoc/events.md @@ -1 +1,69 @@ -## Events \ No newline at end of file +## Events +Events broadcast data for use in mods. + +- `ModAPI.addEventListener(eventName: String, callback: Function) : void` + - Used to register an event handler. Eg: + - ```javascript + function myHandler(event) { + console.log(event); + } + ModAPI.addEventListener("update", myHandler); + ``` +- `ModAPI.removeEventListener(eventName: String, callback: Function) : void` + - Used to unregister an event handler. Eg: + - ```javascript + function myHandler(event) { + console.log(event); + } + ModAPI.removeEventListener("update", myHandler); + ``` + +### Basic Events +- `update`: + - Called every client side tick. + - Event object is blank. +- `load`: + - Called when all mods have finished loading. + - Event object is blank. +- `sendchatmessage`: + - Called just before the player sends a chat message. + - Passes an object with properties: + - `message: String` + - String representing the chat message. + - `preventDefault: Boolean` + - Boolean representing whether or not to cancel processing the chat message. Default is `false`. +- `event`: + - Called when any event is called. Passes an object with properties: + - Passes an object with properties: + - `event: String` + - String representing the type of event being fired. + - `data: Object` + - Object representing the original arguments to be passed to the callback. + +### Server Side Events +Can only be used in the context of the dedicated server. More: [DedicatedServerDocumentation](dedicatedserver.md) +- `serverstart`: + - Called when the dedicated server starts. + - Event object is blank. +- `serverstop`: + - Called when the dedicated server stops. + - Event object is blank. +- `tick`: + - Called when the server ticks. + - Passes an object with properties: + - `preventDefault: Boolean` + - Boolean representing whether or not to cancel the tick. Default is `false`. +- `receivechatmessage`: + - Called when the server receives a chat message. + - Passes an object with properties: + - `message: String` + - String representing the chat message. + - `preventDefault: Boolean` + - Boolean representing whether or not to cancel processing the chat message. Default is `false`. +- `processcommand`: + - Called when the server receives a command. + - Passes an object with properties: + - `command: String` + - String representing the command. + - `preventDefault: Boolean` + - Boolean representing whether or not to cancel processing the command. Default is `false`. \ No newline at end of file diff --git a/docs/apidoc/index.md b/docs/apidoc/index.md index ac43769..52125a6 100644 --- a/docs/apidoc/index.md +++ b/docs/apidoc/index.md @@ -35,7 +35,7 @@ The global object has the following properties: - It can only be accessed in the dedicated server's context. (See `ModAPI.dedicatedServer`) - It can also be accessed using `ModAPI.serverInstance` - `ModAPI.rawServer: MinecraftServer` - - This is the dedicated minecraft server in the service worker, generated when the `serverstart`. + - This is the dedicated minecraft server in the service worker, generated when the `serverstart` event is fired. - It can only be accessed in the dedicated server's context. (See `ModAPI.dedicatedServer`) - It can also be accessed using `ModAPI.server.getRef()` - `ModAPI.hooks` diff --git a/docs/quirks.md b/docs/quirks.md index e69de29..411a7d4 100644 --- a/docs/quirks.md +++ b/docs/quirks.md @@ -0,0 +1,8 @@ +## Quirks in TeaVM +When TeaVM compiles code, it sometimes does strange things. + +#### Property Suffixes +TeaVM will add suffixes to some variables, seemingly randomly. An example is the property `inGround` of any entity. When accessing this on the `ModAPI.player.fishEntity` object, TeaVM has renamed it to `inGround2`. + +#### Collapsing Methods +When I was trying to hook into the server-side processing of chat messages, I found that chat packets were handled by the method `processChatMessage` in `NetHandlerPlayServer`. However, in the compiled JavaScript, this method no longer exists. This is because it is only used once, in the `processPacket` method of `C01PacketChatMessage`. TeaVM automatically saw this, and collapsed one method into the other. \ No newline at end of file diff --git a/postinit.injector.js b/postinit.injector.js index d304685..7cc7668 100644 --- a/postinit.injector.js +++ b/postinit.injector.js @@ -141,10 +141,8 @@ globalThis.modapi_postinit = `(() => { } targetMethodMap[method.replace(compiledName + "_", "")] = { method: ModAPI.hooks.methods[method], - proxiedMethod: function (...args) { - return ModAPI.hooks.methods[method].apply(this, args); - }, - methodName: method + methodName: method, + methodNameShort: method.replace(compiledName + "_", "") }; //Prototype Injection, allows for far easier access to methods @@ -165,7 +163,7 @@ globalThis.modapi_postinit = `(() => { } ModAPI.reflect.getClassByName = function (className) { var classKeys = Object.keys(ModAPI.hooks._classMap); - var key = classKeys.filter(k => {k.endsWith("_" + className)})[0]; + var key = classKeys.filter(k => {return ModAPI.hooks._classMap[k].name === className})[0]; return key ? ModAPI.hooks._classMap[key] : null; } var reloadDeprecationWarnings = 0; @@ -444,7 +442,7 @@ globalThis.modapi_postinit = `(() => { return x; }; - var integratedServerStartup = ModAPI.util.getMethodFromPackage("net.lax1dude.eaglercraft.v1_8.sp.internal.ClientPlatformSingleplayer", "loadIntegratedServerSourceInline"); + var integratedServerStartup = ModAPI.util.getMethodFromPackage("net.lax1dude.eaglercraft.v1_8.sp.internal.ClientPlatformSingleplayer", "createBlobObj"); //Integrated server setup has a randomised suffix on the end integratedServerStartup = ModAPI.hooks._rippedMethodKeys.filter(key => { return key.startsWith(integratedServerStartup); })[0]; const integratedServerStartupMethod = ModAPI.hooks.methods[integratedServerStartup]; diff --git a/postinit.js b/postinit.js index cf1a229..f9573f1 100644 --- a/postinit.js +++ b/postinit.js @@ -442,7 +442,7 @@ return x; }; - var integratedServerStartup = ModAPI.util.getMethodFromPackage("net.lax1dude.eaglercraft.v1_8.sp.internal.ClientPlatformSingleplayer", "loadIntegratedServerSourceInline"); + var integratedServerStartup = ModAPI.util.getMethodFromPackage("net.lax1dude.eaglercraft.v1_8.sp.internal.ClientPlatformSingleplayer", "createBlobObj"); //Integrated server setup has a randomised suffix on the end integratedServerStartup = ModAPI.hooks._rippedMethodKeys.filter(key => { return key.startsWith(integratedServerStartup); })[0]; const integratedServerStartupMethod = ModAPI.hooks.methods[integratedServerStartup];