mirror of
https://github.com/eaglerforge/EaglerForgeInjector
synced 2025-07-26 15:29:26 -09:00
Merge pull request #15 from eaglerforge/main
A lot of new stuff + u38 compat
This commit is contained in:
commit
216309e111
132
examplemods/AsyncSink.js
Normal file
132
examplemods/AsyncSink.js
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
(function AsyncSinkFn() {
|
||||||
|
//AsyncSink is a plugin to debug and override asynchronous methods in EaglercraftX
|
||||||
|
function runtimeComponent() {
|
||||||
|
const booleanResult = (b) => ModAPI.hooks.methods.nlevit_BooleanResult__new(b * 1);
|
||||||
|
const wrap = ModAPI.hooks.methods.otji_JSWrapper_wrap;
|
||||||
|
const unwrap = ModAPI.hooks.methods.otji_JSWrapper_unwrap;
|
||||||
|
function getAsyncHandlerName(name) {
|
||||||
|
var suffix = `$AsyncHandlers_${name}$_asyncCall_$`;
|
||||||
|
return ModAPI.hooks._rippedMethodKeys.find(x => x.endsWith(suffix));
|
||||||
|
}
|
||||||
|
var fs_debugging = false;
|
||||||
|
const encoder = new TextEncoder('utf-8');
|
||||||
|
var filesystemPlatform = ModAPI.hooks.methods.nlevit_IndexedDBFilesystem$AsyncHandlers_readWholeFile ? true : false;
|
||||||
|
if (!filesystemPlatform) {
|
||||||
|
console.error("AsyncSink requires EaglercraftX u37 or greater to work! Attempting to run anyway...");
|
||||||
|
}
|
||||||
|
const AsyncSink = {};
|
||||||
|
const originalSuspend = ModAPI.hooks.TeaVMThread.prototype.suspend;
|
||||||
|
AsyncSink.startDebugging = function hookIntoSuspend() {
|
||||||
|
ModAPI.hooks.TeaVMThread.prototype.suspend = function suspend(...args) {
|
||||||
|
console.log("[AsyncSink] Context suspended! Callback: ", args[0]);
|
||||||
|
return originalSuspend.apply(this, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AsyncSink.stopDebugging = function unhookFromSuspend() {
|
||||||
|
ModAPI.hooks.TeaVMThread.prototype.suspend = originalSuspend;
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncSink.startDebuggingFS = function hookIntoSuspend() {
|
||||||
|
fs_debugging = true;
|
||||||
|
}
|
||||||
|
AsyncSink.stopDebuggingFS = function unhookFromSuspend() {
|
||||||
|
fs_debugging = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @type Map<string, ArrayBuffer>
|
||||||
|
AsyncSink.FS = new Map();
|
||||||
|
AsyncSink.FSOverride = new Set();
|
||||||
|
AsyncSink.MIDDLEWARE = [];
|
||||||
|
AsyncSink.setFile = function setFile(path, data) {
|
||||||
|
if (typeof data === "string") {
|
||||||
|
data = encoder.encode(data).buffer;
|
||||||
|
}
|
||||||
|
AsyncSink.FSOverride.add(path);
|
||||||
|
AsyncSink.FS.set(path, data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncSink.deleteFile = function deleteFile(path) {
|
||||||
|
AsyncSink.FSOverride.delete(path);
|
||||||
|
AsyncSink.FS.delete(path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncSink.getFile = function getFile(path) {
|
||||||
|
return AsyncSink.FS.get(path) || new ArrayBuffer(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncSink.fileExists = function fileExists(path) {
|
||||||
|
return AsyncSink.FS.has(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
var readWholeFileName = getAsyncHandlerName("readWholeFile");
|
||||||
|
var writeWholeFileName = getAsyncHandlerName("writeWholeFile");
|
||||||
|
var deleteFileName = getAsyncHandlerName("deleteFile");
|
||||||
|
var fileExistsName = getAsyncHandlerName("fileExists");
|
||||||
|
|
||||||
|
const originalReadWholeFile = ModAPI.hooks.methods[readWholeFileName];
|
||||||
|
ModAPI.hooks.methods[readWholeFileName] = function (...args) {
|
||||||
|
if (fs_debugging) {
|
||||||
|
console.log("[AsynkSinkFS] File read request sent: " + ModAPI.util.ustr(args[1]));
|
||||||
|
}
|
||||||
|
if (AsyncSink.FSOverride.has(ModAPI.util.ustr(args[1]))) {
|
||||||
|
if (fs_debugging) {
|
||||||
|
console.log("[AsynkSinkFS] Replied with copy from fake filesystem.");
|
||||||
|
}
|
||||||
|
return wrap(AsyncSink.getFile(ModAPI.util.ustr(args[1])));
|
||||||
|
}
|
||||||
|
|
||||||
|
return originalReadWholeFile.apply(this, args);
|
||||||
|
};
|
||||||
|
|
||||||
|
const originalWriteWholeFile = ModAPI.hooks.methods[writeWholeFileName];
|
||||||
|
ModAPI.hooks.methods[writeWholeFileName] = function (...args) {
|
||||||
|
if (fs_debugging) {
|
||||||
|
console.log("[AsynkSinkFS] File write request sent: " + ModAPI.util.ustr(args[1]), args[2]);
|
||||||
|
}
|
||||||
|
if (AsyncSink.FSOverride.has(ModAPI.util.ustr(args[1]))) {
|
||||||
|
if (fs_debugging) {
|
||||||
|
console.log("[AsynkSinkFS] Writing to fake filesystem.");
|
||||||
|
}
|
||||||
|
AsyncSink.setFile(ModAPI.util.ustr(args[1]), args[2]);
|
||||||
|
return booleanResult(true);
|
||||||
|
}
|
||||||
|
return originalWriteWholeFile.apply(this, args);
|
||||||
|
};
|
||||||
|
|
||||||
|
const originalDeleteFile = ModAPI.hooks.methods[deleteFileName];
|
||||||
|
ModAPI.hooks.methods[deleteFileName] = function (...args) {
|
||||||
|
if (fs_debugging) {
|
||||||
|
console.log("[AsynkSinkFS] File delete request sent: " + ModAPI.util.ustr(args[1]));
|
||||||
|
}
|
||||||
|
if (AsyncSink.FSOverride.has(ModAPI.util.ustr(args[1]))) {
|
||||||
|
if (fs_debugging) {
|
||||||
|
console.log("[AsynkSinkFS] Deleting entry from fake filesystem.");
|
||||||
|
}
|
||||||
|
AsyncSink.deleteFile(ModAPI.util.ustr(args[1]));
|
||||||
|
return booleanResult(true);
|
||||||
|
}
|
||||||
|
return originalDeleteFile.apply(this, args);
|
||||||
|
};
|
||||||
|
|
||||||
|
const originalFileExists = ModAPI.hooks.methods[fileExistsName];
|
||||||
|
ModAPI.hooks.methods[fileExistsName] = function (...args) {
|
||||||
|
if (fs_debugging) {
|
||||||
|
console.log("[AsynkSinkFS] File exists request sent: " + ModAPI.util.ustr(args[1]));
|
||||||
|
}
|
||||||
|
if (AsyncSink.FSOverride.has(ModAPI.util.ustr(args[1]))) {
|
||||||
|
if (fs_debugging) {
|
||||||
|
console.log("[AsynkSinkFS] Replying with information from fake filesystem.");
|
||||||
|
}
|
||||||
|
var result = AsyncSink.fileExists(ModAPI.util.ustr(args[1]));
|
||||||
|
return booleanResult(result);
|
||||||
|
}
|
||||||
|
return originalFileExists.apply(this, args);
|
||||||
|
};
|
||||||
|
globalThis.AsyncSink = AsyncSink;
|
||||||
|
ModAPI.events.callEvent("lib:asyncsink", {});
|
||||||
|
}
|
||||||
|
runtimeComponent();
|
||||||
|
ModAPI.dedicatedServer.appendCode(runtimeComponent);
|
||||||
|
})();
|
79
examplemods/advanced_vclip.js
Normal file
79
examplemods/advanced_vclip.js
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
ModAPI.meta.title("Advanced VClip Exploit");
|
||||||
|
ModAPI.meta.description("Use .vclip <offset> to vertically phase through blocks with custom packet handling.");
|
||||||
|
ModAPI.meta.credits("By radmanplays");
|
||||||
|
|
||||||
|
// Custom syntax error function
|
||||||
|
function syntaxError() {
|
||||||
|
ModAPI.displayToChat("[AdvancedVClip] Syntax error: Usage is .vclip <offset>");
|
||||||
|
}
|
||||||
|
|
||||||
|
ModAPI.require("player");
|
||||||
|
ModAPI.addEventListener("sendchatmessage", (ev) => {
|
||||||
|
var msg = ev.message.toLowerCase();
|
||||||
|
if (msg.startsWith(".vclip")) {
|
||||||
|
ev.preventDefault();
|
||||||
|
|
||||||
|
var args = msg.split(" ");
|
||||||
|
if (args.length != 2) {
|
||||||
|
syntaxError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var offset = parseFloat(args[1]);
|
||||||
|
if (isNaN(offset)) {
|
||||||
|
syntaxError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var packetsRequired = Math.ceil(Math.abs(offset / 10));
|
||||||
|
if (packetsRequired > 20) {
|
||||||
|
packetsRequired = 1; // Limit to avoid server kicking for too many packets
|
||||||
|
}
|
||||||
|
|
||||||
|
var player = ModAPI.player;
|
||||||
|
var ridingEntity = player.ridingEntity;
|
||||||
|
|
||||||
|
if (ridingEntity != null) {
|
||||||
|
// Player is riding an entity
|
||||||
|
for (var packetNumber = 0; packetNumber < (packetsRequired - 1); packetNumber++) {
|
||||||
|
// Simulate entity movement
|
||||||
|
ridingEntity.posY += offset / packetsRequired; // Move a fraction of the total offset
|
||||||
|
player.sendQueue.addToSendQueue({
|
||||||
|
"action": "RIDING_JUMP", // Simulate a riding jump action
|
||||||
|
"entityId": ridingEntity.getEntityId(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final move
|
||||||
|
ridingEntity.posY += offset / packetsRequired;
|
||||||
|
player.sendQueue.addToSendQueue({
|
||||||
|
"action": "RIDING_JUMP",
|
||||||
|
"entityId": ridingEntity.getEntityId(),
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Player is not riding any entity
|
||||||
|
for (var packetNumber = 0; packetNumber < (packetsRequired - 1); packetNumber++) {
|
||||||
|
player.getNetHandler().addToSendQueue({
|
||||||
|
"x": player.posX,
|
||||||
|
"y": player.posY,
|
||||||
|
"z": player.posZ,
|
||||||
|
"onGround": true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final move
|
||||||
|
player.getNetHandler().addToSendQueue({
|
||||||
|
"x": player.posX,
|
||||||
|
"y": player.posY + offset,
|
||||||
|
"z": player.posZ,
|
||||||
|
"onGround": true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set the player’s final position
|
||||||
|
player.setPosition(player.posX, player.posY + offset, player.posZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModAPI.displayToChat("[AdvancedVClip] VClipped " + offset + " blocks.");
|
||||||
|
}
|
||||||
|
});
|
@ -4,11 +4,18 @@
|
|||||||
if (!ModAPI.reflect.getClassById("net.minecraft.entity.player.EntityPlayerMP").instanceOf(event.sender.getRef())) { return; }
|
if (!ModAPI.reflect.getClassById("net.minecraft.entity.player.EntityPlayerMP").instanceOf(event.sender.getRef())) { return; }
|
||||||
|
|
||||||
if (event.command.toLowerCase().startsWith("/spawnnpc")) {
|
if (event.command.toLowerCase().startsWith("/spawnnpc")) {
|
||||||
|
if (!globalThis.AsyncSink) {
|
||||||
|
return alert("NPC Spawner relies on the AsyncSink library.");
|
||||||
|
}
|
||||||
const world = event.sender.getServerForPlayer();
|
const world = event.sender.getServerForPlayer();
|
||||||
const senderPos = event.sender.getPosition();
|
const senderPos = event.sender.getPosition();
|
||||||
|
|
||||||
// Create a fake player GameProfile
|
// Create a fake player GameProfile
|
||||||
const GameProfileClass = ModAPI.reflect.getClassById("net.lax1dude.eaglercraft.v1_8.mojang.authlib.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"));
|
const fakeProfile = GameProfileClass.constructors[1](null, ModAPI.util.str("Steve"));
|
||||||
|
|
||||||
// Get the PlayerInteractionManager class
|
// Get the PlayerInteractionManager class
|
||||||
@ -16,8 +23,11 @@
|
|||||||
const playerInteractionManager = PlayerInteractionManagerClass.constructors[0](world.getRef());
|
const playerInteractionManager = PlayerInteractionManagerClass.constructors[0](world.getRef());
|
||||||
|
|
||||||
// Get the EntityPlayerMP class to spawn the fake player
|
// Get the EntityPlayerMP class to spawn the fake player
|
||||||
|
AsyncSink.startDebuggingFS();
|
||||||
const EntityPlayerMPClass = ModAPI.reflect.getClassById("net.minecraft.entity.player.EntityPlayerMP");
|
const EntityPlayerMPClass = ModAPI.reflect.getClassById("net.minecraft.entity.player.EntityPlayerMP");
|
||||||
console.log(ModAPI.server.getConfigurationManager());
|
var worldNameProp = ModAPI.util.getNearestProperty(ModAPI.server.getRef(), "$worldName");
|
||||||
|
var worldName = ModAPI.server.getRef()[worldNameProp];
|
||||||
|
console.log(ModAPI.util.ustr(worldName));
|
||||||
const fakePlayer = EntityPlayerMPClass.constructors[0](
|
const fakePlayer = EntityPlayerMPClass.constructors[0](
|
||||||
ModAPI.server.getRef(), world.getRef(), fakeProfile, playerInteractionManager
|
ModAPI.server.getRef(), world.getRef(), fakeProfile, playerInteractionManager
|
||||||
);
|
);
|
||||||
|
@ -55,6 +55,11 @@ function entriesToStaticVariableProxy(entries, prefix) {
|
|||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
async function processClasses(string) {
|
async function processClasses(string) {
|
||||||
|
if (globalThis.doShronk) {
|
||||||
|
if (!confirm("The minify step is extremely slow, especially on lower-end devices, and can take upwards of 15 minutes.")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
_status("Beginning patch process...");
|
_status("Beginning patch process...");
|
||||||
await wait(50);
|
await wait(50);
|
||||||
var patchedFile = string;
|
var patchedFile = string;
|
||||||
|
22
postinit.js
22
postinit.js
@ -738,7 +738,13 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
sender: new Proxy($sender, TeaVM_to_Recursive_BaseData_ProxyConf),
|
sender: new Proxy($sender, TeaVM_to_Recursive_BaseData_ProxyConf),
|
||||||
command: ModAPI.util.jclStrToJsStr($rawCommand)
|
command: ModAPI.util.jclStrToJsStr($rawCommand)
|
||||||
}
|
}
|
||||||
ModAPI.events.callEvent("processcommand", data);
|
if (data.command.toLowerCase().startsWith("/efdebug")) {
|
||||||
|
// Utility command to debug the dedicated server.
|
||||||
|
data.preventDefault = true;
|
||||||
|
debugger;
|
||||||
|
} else {
|
||||||
|
ModAPI.events.callEvent("processcommand", data);
|
||||||
|
}
|
||||||
if (data.preventDefault) {
|
if (data.preventDefault) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -749,10 +755,16 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModAPI.items = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.init.Items")].staticVariables, StaticProps_ProxyConf);
|
const originalBootstrap = ModAPI.hooks.staticMethods[ModAPI.util.getMethodFromPackage("net.minecraft.init.Bootstrap", "register")];
|
||||||
ModAPI.blocks = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.init.Blocks")].staticVariables, StaticProps_ProxyConf);
|
ModAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.init.Bootstrap", "register")] = function (...args) {
|
||||||
ModAPI.materials = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.block.material.Material")].staticVariables, StaticProps_ProxyConf);
|
var x = originalBootstrap.apply(this, args);
|
||||||
ModAPI.enchantments = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.enchantment.Enchantment")].staticVariables, StaticProps_ProxyConf);
|
ModAPI.items = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.init.Items")].staticVariables, StaticProps_ProxyConf);
|
||||||
|
ModAPI.blocks = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.init.Blocks")].staticVariables, StaticProps_ProxyConf);
|
||||||
|
ModAPI.materials = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.block.material.Material")].staticVariables, StaticProps_ProxyConf);
|
||||||
|
ModAPI.enchantments = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.enchantment.Enchantment")].staticVariables, StaticProps_ProxyConf);
|
||||||
|
console.log("[ModAPI] Hooked into bootstrap. .blocks, .items, .materials and .enchantments are now accessible.");
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
const originalOptionsInit = ModAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.client.gui.GuiOptions", "initGui")];
|
const originalOptionsInit = ModAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.client.gui.GuiOptions", "initGui")];
|
||||||
ModAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.client.gui.GuiOptions", "initGui")] = function (...args) {
|
ModAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.client.gui.GuiOptions", "initGui")] = function (...args) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user