diff --git a/docs/tutorials/index.md b/docs/tutorials/index.md index e69de29..f172438 100644 --- a/docs/tutorials/index.md +++ b/docs/tutorials/index.md @@ -0,0 +1,10 @@ +## Mod tutorials with ModAPI + +Prerequisites: + - Basic knowledge of JavaScript + - A good code editor (recommended: https://vscode.dev) + +### Beginner +- [Step Hack](step.md) +- [Spider Hack](spider.md) +- [VClip Exploit](comingsoon) \ No newline at end of file diff --git a/docs/tutorials/spider.md b/docs/tutorials/spider.md new file mode 100644 index 0000000..cd99e35 --- /dev/null +++ b/docs/tutorials/spider.md @@ -0,0 +1,41 @@ +## Spider Hack with ModAPI +A spider hack allows players to climb up any wall like a spider. + +Start by creating a new file in your code editor. Save it to a folder on your device, ensuring that the file extension is `.js`. + +The spider hack has a lot of similarities to the step hack, so lets copy the step hack and rename the `stepHackUpdateCode` function to `spiderHackUpdateCode`: +```javascript +ModAPI.require("player"); + +function spiderHackUpdateCode() { + //We will add code here. +} +ModAPI.addEventListener("update", spiderHackUpdateCode); +``` + +Most spider hacks work by checking if the player is walking into a wall, and then setting their vertical velocity to a constant amount (usually `0.2`, for parity with ladders). +Let's start by checking if the player is walking into a wall, by adding an if statement inside the `spiderHackUpdateCode` function: +```javascript +if (ModAPI.player.isCollidedHorizontally) { + +} +``` + +Now, let's set the player's vertical velocity: +```javascript +if (ModAPI.player.isCollidedHorizontally) { + ModAPI.player.motionY = 0.2; //Feel free to change this value to something bigger, smaller or even negative. +} +``` + +Time to see the final code: +```javascript +ModAPI.require("player"); + +function spiderHackUpdateCode() { + if (ModAPI.player.isCollidedHorizontally) { + ModAPI.player.motionY = 0.2; //Feel free to change this value to something bigger, smaller or even negative. + } +} +ModAPI.addEventListener("update", spiderHackUpdateCode); +``` \ No newline at end of file diff --git a/docs/tutorials/step.md b/docs/tutorials/step.md new file mode 100644 index 0000000..eed3453 --- /dev/null +++ b/docs/tutorials/step.md @@ -0,0 +1,33 @@ +## Step Hack with ModAPI +A step hack allows a player to walk up full blocks (or more) as if they were slabs. + +Start by creating a new file in your code editor. Save it to a folder on your device, ensuring that the file extension is `.js`. + +Let's start by requiring the player. This will allow us to change attributes on the player: +```javascript +ModAPI.require("player"); +``` + +Now, we have to detect when the player in a world. This will be done with the `update` event, which runs every tick while the player is in a world. In EaglerForge's ModAPI, to run code on an event, you have to create a function. Then, you register the function to an event. +```javascript +ModAPI.require("player"); + +function stepHackUpdateCode() { + //We will add code here. +} +ModAPI.addEventListener("update", stepHackUpdateCode); +``` + +Inside this method, lets change the player's `stepHeight`, which controls how high they can step. By default this is `0.5`, to alow players to walk up slabs or stairs. I'll change it to `2` for demonstration purposes. You can also try any other number, like `0`, `6`, etc. +```javascript +ModAPI.require("player"); + +function stepHackUpdateCode() { + ModAPI.player.stepHeight = 2; +} +ModAPI.addEventListener("update", stepHackUpdateCode); +``` + +Now, to load this mod, open your EaglerForge build, and in the start screen select `Upload Mod (.js)`. Upload the mod you created, and you should now be able to walk up two block tall pillars, or more depending on what `stepHeight` you selected. + +Disclaimer: using this on servers may get you banned/kicked for cheating! \ No newline at end of file diff --git a/examplemods/npcspawnertest.js b/examplemods/npcspawnertest.js new file mode 100644 index 0000000..1a6587e --- /dev/null +++ b/examplemods/npcspawnertest.js @@ -0,0 +1,52 @@ +(() => { + PluginAPI.dedicatedServer.appendCode(function () { + PluginAPI.addEventListener("processcommand", (event) => { + if (!ModAPI.reflect.getClassById("net.minecraft.entity.player.EntityPlayerMP").instanceOf(event.sender.getRef())) { return; } + + if (event.command.toLowerCase().startsWith("/spawnnpc2")) { + AsyncSink.startDebuggingFS(); + const world = event.sender.getServerForPlayer(); + const senderPos = event.sender.getPosition(); + + // Create a fake player GameProfile + const GameProfileClass = ModAPI.reflect.getClassById("net.lax1dude.eaglercraft.v1_8.mojang.authlib.GameProfile"); + var UUID = ModAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.lax1dude.eaglercraft.v1_8.EaglercraftUUID", "randomUUID")](); + + //Not using UUID to make patching easier for now + + const fakeProfile = GameProfileClass.constructors[1](null, ModAPI.util.str("Steve")); + + // Get the PlayerInteractionManager class + const PlayerInteractionManagerClass = ModAPI.reflect.getClassById("net.minecraft.server.management.ItemInWorldManager"); + const playerInteractionManager = PlayerInteractionManagerClass.constructors[0](world.getRef()); + + // Get the EntityPlayerMP class to spawn the fake player + const EntityPlayerMPClass = ModAPI.reflect.getClassById("net.minecraft.entity.player.EntityPlayerMP"); + const fakePlayer = ModAPI.util.wrap(EntityPlayerMPClass.constructors[0]( + ModAPI.server.getRef(), world.getRef(), fakeProfile, playerInteractionManager + )); + ModAPI.hooks._teavm.$rt_startThread(() => { + return EntityPlayerMPClass.constructors[0](ModAPI.server.getRef(), world.getRef(), fakeProfile, playerInteractionManager); + }, function (...args) { + console.log(this, args); + var fakePlayer = ModAPI.util.wrap(args[0]); + + // Set the fake player position to be near the command sender + console.log(senderPos); + fakePlayer.setPosition(senderPos.getX(), senderPos.getY(), senderPos.getZ()); + + // Add the fake player to the world + world.spawnEntityInWorld(fakePlayer.getRef()); + + // Notify the player that the fake player has been spawned + const ChatComponentTextClass = ModAPI.reflect.getClassById("net.minecraft.util.ChatComponentText"); + event.sender.addChatMessage(ChatComponentTextClass.constructors[0](ModAPI.util.str("Fake Steve has been spawned!"))); + }); + + + // Prevent the command from executing further + event.preventDefault = true; + } + }); + }); +})(); diff --git a/postinit.js b/postinit.js index b299311..95fcb83 100644 --- a/postinit.js +++ b/postinit.js @@ -667,6 +667,17 @@ globalThis.modapi_postinit = "(" + (() => { return x; }; + var desktopServerStartup = ModAPI.util.getMethodFromPackage("net.lax1dude.eaglercraft.v1_8.sp.internal.ClientPlatformSingleplayer", "startIntegratedServer"); + const desktopServerStartupMethod = ModAPI.hooks.methods[desktopServerStartup]; + ModAPI.hooks.methods[desktopServerStartup] = function (...args) { + var x = desktopServerStartupMethod.apply(this, args); + ModAPI.dedicatedServer._data.forEach((code)=>{ + (new Function(code))(); + }); + console.log("[ModAPI] Hooked into external integrated server."); + return x; + }; + ModAPI.events.newEvent("load", "client"); ModAPI.events.newEvent("sendchatmessage", "client");