mirror of
https://github.com/eaglerforge/EaglerForgeInjector
synced 2025-07-26 23:39:25 -09:00
commit
85ad018a15
@ -44,3 +44,15 @@ Methods:
|
|||||||
- Returns a wrapper around native java objects, removing prefixes and fixing method outputs.
|
- Returns a wrapper around native java objects, removing prefixes and fixing method outputs.
|
||||||
- `ModAPI.util.getNearestProperty(object: Object, property: string) : string`
|
- `ModAPI.util.getNearestProperty(object: Object, property: string) : string`
|
||||||
- Finds the nearest property name to the one you specify (suffix based). This is used to mitigate teavm adding random suffixes to properties.
|
- Finds the nearest property name to the one you specify (suffix based). This is used to mitigate teavm adding random suffixes to properties.
|
||||||
|
- `ModAPI.util.modifyFunction(fn: Function, patcherFunction: Function) : string`
|
||||||
|
- Returns a modifies version of a function, where the patcher function can be used to modify the contents of a function. Example:
|
||||||
|
```javascript
|
||||||
|
function add(a, b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
var multiply = ModAPI.util.modifyFunction(add, (code)=>{
|
||||||
|
return code.replaceAll("a + b", "a * b");
|
||||||
|
});
|
||||||
|
console.log(multiply(2, 3));
|
||||||
|
//Logs 6
|
||||||
|
```
|
@ -1,3 +1,7 @@
|
|||||||
|
ModAPI.meta.title("AsyncSink");
|
||||||
|
ModAPI.meta.description("Library for patching and hooking into asynchronous filesystem requests for EaglercraftX.");
|
||||||
|
ModAPI.meta.icon("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAL9JREFUOE9jZGBg+M9ABcAIMsgtPo3hzZ2zYONEVIxJZu9aOIsBbJCRtTHcEJAgLgBSh82ic0fPIgyCKQAJXrx4EcUsfX19sBiIRrYU5gu4Qchew2cQyHSQYehBgdNruFwEcybMZci+gIcRIa+hhxu6LzBiDZvX0A1BDyuivYbLIJK8pqevjze5GlsbMxAdayCT/PQwDRS2gaQror2m36KH4SqjZybwxEl0gsQWRkM01ogpVQh6jaJihBgXEFIDAAIQ9AFDJlrxAAAAAElFTkSuQmCC");
|
||||||
|
ModAPI.meta.credits("By ZXMushroom63");
|
||||||
(function AsyncSinkFn() {
|
(function AsyncSinkFn() {
|
||||||
//AsyncSink is a plugin to debug and override asynchronous methods in EaglercraftX
|
//AsyncSink is a plugin to debug and override asynchronous methods in EaglercraftX
|
||||||
function runtimeComponent() {
|
function runtimeComponent() {
|
||||||
@ -76,7 +80,11 @@
|
|||||||
}
|
}
|
||||||
return wrap(AsyncSink.getFile(ModAPI.util.ustr(args[1])));
|
return wrap(AsyncSink.getFile(ModAPI.util.ustr(args[1])));
|
||||||
}
|
}
|
||||||
|
var ev = {method: "read", file: ModAPI.util.ustr(args[1]), shim: false, shimOutput: new ArrayBuffer()};
|
||||||
|
AsyncSink.MIDDLEWARE.forEach((fn)=>{fn(ev)});
|
||||||
|
if (ev.shim) {
|
||||||
|
return wrap(ev.shimOutput);
|
||||||
|
}
|
||||||
return originalReadWholeFile.apply(this, args);
|
return originalReadWholeFile.apply(this, args);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -92,6 +100,11 @@
|
|||||||
AsyncSink.setFile(ModAPI.util.ustr(args[1]), args[2]);
|
AsyncSink.setFile(ModAPI.util.ustr(args[1]), args[2]);
|
||||||
return booleanResult(true);
|
return booleanResult(true);
|
||||||
}
|
}
|
||||||
|
var ev = {method: "write", file: ModAPI.util.ustr(args[1]), data: args[2], shim: false, shimOutput: true};
|
||||||
|
AsyncSink.MIDDLEWARE.forEach((fn)=>{fn(ev)});
|
||||||
|
if (ev.shim) {
|
||||||
|
return booleanResult(ev.shimOutput);
|
||||||
|
}
|
||||||
return originalWriteWholeFile.apply(this, args);
|
return originalWriteWholeFile.apply(this, args);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -107,6 +120,11 @@
|
|||||||
AsyncSink.deleteFile(ModAPI.util.ustr(args[1]));
|
AsyncSink.deleteFile(ModAPI.util.ustr(args[1]));
|
||||||
return booleanResult(true);
|
return booleanResult(true);
|
||||||
}
|
}
|
||||||
|
var ev = {method: "delete", file: ModAPI.util.ustr(args[1]), shim: false, shimOutput: true};
|
||||||
|
AsyncSink.MIDDLEWARE.forEach((fn)=>{fn(ev)});
|
||||||
|
if (ev.shim) {
|
||||||
|
return booleanResult(ev.shimOutput);
|
||||||
|
}
|
||||||
return originalDeleteFile.apply(this, args);
|
return originalDeleteFile.apply(this, args);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -122,10 +140,16 @@
|
|||||||
var result = AsyncSink.fileExists(ModAPI.util.ustr(args[1]));
|
var result = AsyncSink.fileExists(ModAPI.util.ustr(args[1]));
|
||||||
return booleanResult(result);
|
return booleanResult(result);
|
||||||
}
|
}
|
||||||
|
var ev = {method: "exists", file: ModAPI.util.ustr(args[1]), shim: false, shimOutput: true};
|
||||||
|
AsyncSink.MIDDLEWARE.forEach((fn)=>{fn(ev)});
|
||||||
|
if (ev.shim) {
|
||||||
|
return booleanResult(ev.shimOutput);
|
||||||
|
}
|
||||||
return originalFileExists.apply(this, args);
|
return originalFileExists.apply(this, args);
|
||||||
};
|
};
|
||||||
globalThis.AsyncSink = AsyncSink;
|
globalThis.AsyncSink = AsyncSink;
|
||||||
ModAPI.events.callEvent("lib:asyncsink", {});
|
ModAPI.events.callEvent("lib:asyncsink", {});
|
||||||
|
console.log("[AsyncSink] Loaded!");
|
||||||
}
|
}
|
||||||
runtimeComponent();
|
runtimeComponent();
|
||||||
ModAPI.dedicatedServer.appendCode(runtimeComponent);
|
ModAPI.dedicatedServer.appendCode(runtimeComponent);
|
||||||
|
116
examplemods/astar.js
Normal file
116
examplemods/astar.js
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
(function AStarPathfinding() {
|
||||||
|
ModAPI.meta.title("A* Pathfinding Bot");
|
||||||
|
ModAPI.meta.description("Use #move <x> <y> <z> to instruct the bot to move somewhere. Use #stop to terminate the job.");
|
||||||
|
ModAPI.meta.credits("By ZXMushroom63");
|
||||||
|
|
||||||
|
ModAPI.require("player");
|
||||||
|
ModAPI.require("world");
|
||||||
|
|
||||||
|
var blockBreakCostMultiplier = 2;
|
||||||
|
const costMap = Object.fromEntries(Object.keys(ModAPI.blocks).flatMap(x => {
|
||||||
|
ModAPI.blocks[x].readableId = x;
|
||||||
|
return [x, (Math.floor(ModAPI.blocks[x].blockHardness * 10 * blockBreakCostMultiplier) + 1) || 99999]; //Block hardness is in decimals, unbreakable blocks are negative one, and base movement cost is 1. -1 + 1 = 0, and 0 || 99999 is 99999
|
||||||
|
}));
|
||||||
|
|
||||||
|
var makeBlockPos = ModAPI.reflect.getClassById("net.minecraft.util.BlockPos").constructors.find(x=>x.length === 3);
|
||||||
|
|
||||||
|
function shouldPause(x, y, z) {
|
||||||
|
return !ModAPI.world.isAreaLoaded0(makeBlockPos(x, y, z), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
class APNode {
|
||||||
|
constructor(x, y, z, g, h, parent = null) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
this.g = g;
|
||||||
|
this.h = h;
|
||||||
|
this.f = g + h;
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function heuristic(a, b) {
|
||||||
|
return Math.abs(a.x - b.x) + Math.abs(a.y - b.y) + Math.abs(a.z - b.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNeighbors(node) {
|
||||||
|
const neighbors = [];
|
||||||
|
const directions = [
|
||||||
|
[1, 0, 0], [-1, 0, 0],
|
||||||
|
[0, 1, 0], [0, -1, 0],
|
||||||
|
[0, 0, 1], [0, 0, -1]
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const [dx, dy, dz] of directions) {
|
||||||
|
const x = node.x + dx;
|
||||||
|
const y = node.y + dy;
|
||||||
|
const z = node.z + dz;
|
||||||
|
|
||||||
|
if (ModAPI.world.isBlockLoaded(makeBlockPos(Math.round(x), Math.round(y), Math.round(z)))) {
|
||||||
|
neighbors.push(new APNode(x, y, z, 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return neighbors;
|
||||||
|
}
|
||||||
|
|
||||||
|
function lookupCost(x, y, z) {
|
||||||
|
var block = ModAPI.world.getBlockState(makeBlockPos(Math.round(x), Math.round(y), Math.round(z))).block;
|
||||||
|
return costMap[block.readableId];
|
||||||
|
}
|
||||||
|
|
||||||
|
function* aStar(start, goal) {
|
||||||
|
const openSet = [];
|
||||||
|
const closedSet = new Set();
|
||||||
|
openSet.push(start);
|
||||||
|
|
||||||
|
while (openSet.length > 0) {
|
||||||
|
let current = openSet.reduce((prev, curr) => (prev.f < curr.f ? prev : curr));
|
||||||
|
|
||||||
|
if (current.x === goal.x && current.y === goal.y && current.z === goal.z) {
|
||||||
|
const path = [];
|
||||||
|
while (current) {
|
||||||
|
path.push([current.x, current.y, current.z]);
|
||||||
|
current = current.parent;
|
||||||
|
}
|
||||||
|
yield* path.reverse();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
openSet.splice(openSet.indexOf(current), 1);
|
||||||
|
closedSet.add(`${current.x},${current.y},${current.z}`);
|
||||||
|
|
||||||
|
for (const neighbor of getNeighbors(current)) {
|
||||||
|
if (closedSet.has(`${neighbor.x},${neighbor.y},${neighbor.z}`)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tentativeG = current.g + lookupCost(neighbor.x, neighbor.y, neighbor.z);
|
||||||
|
|
||||||
|
if (!openSet.some(node => node.x === neighbor.x && node.y === neighbor.y && node.z === neighbor.z)) {
|
||||||
|
neighbor.g = tentativeG;
|
||||||
|
neighbor.h = heuristic(neighbor, goal);
|
||||||
|
neighbor.f = neighbor.g + neighbor.h;
|
||||||
|
neighbor.parent = current;
|
||||||
|
openSet.push(neighbor);
|
||||||
|
} else {
|
||||||
|
const existingNode = openSet.find(node => node.x === neighbor.x && node.y === neighbor.y && node.z === neighbor.z);
|
||||||
|
if (tentativeG < existingNode.g) {
|
||||||
|
existingNode.g = tentativeG;
|
||||||
|
existingNode.f = existingNode.g + existingNode.h;
|
||||||
|
existingNode.parent = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yield [current.x, current.y, current.z];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const start = new APNode(0, 0, 0, 0, 0);
|
||||||
|
const goal = new APNode(2, 2, 2, 0, 0);
|
||||||
|
|
||||||
|
const pathGenerator = aStar(start, goal);
|
||||||
|
})();
|
@ -1,3 +1,4 @@
|
|||||||
|
//NOT FUNCTIONAL
|
||||||
ModAPI.meta.title("Advanced VClip Exploit");
|
ModAPI.meta.title("Advanced VClip Exploit");
|
||||||
ModAPI.meta.description("Use .vclip <offset> to vertically phase through blocks with custom packet handling.");
|
ModAPI.meta.description("Use .vclip <offset> to vertically phase through blocks with custom packet handling.");
|
||||||
ModAPI.meta.credits("By radmanplays");
|
ModAPI.meta.credits("By radmanplays");
|
||||||
@ -11,7 +12,7 @@ ModAPI.require("player");
|
|||||||
ModAPI.addEventListener("sendchatmessage", (ev) => {
|
ModAPI.addEventListener("sendchatmessage", (ev) => {
|
||||||
var msg = ev.message.toLowerCase();
|
var msg = ev.message.toLowerCase();
|
||||||
if (msg.startsWith(".vclip")) {
|
if (msg.startsWith(".vclip")) {
|
||||||
ev.preventDefault();
|
ev.preventDefault == true;
|
||||||
|
|
||||||
var args = msg.split(" ");
|
var args = msg.split(" ");
|
||||||
if (args.length != 2) {
|
if (args.length != 2) {
|
||||||
@ -38,7 +39,7 @@ ModAPI.addEventListener("sendchatmessage", (ev) => {
|
|||||||
for (var packetNumber = 0; packetNumber < (packetsRequired - 1); packetNumber++) {
|
for (var packetNumber = 0; packetNumber < (packetsRequired - 1); packetNumber++) {
|
||||||
// Simulate entity movement
|
// Simulate entity movement
|
||||||
ridingEntity.posY += offset / packetsRequired; // Move a fraction of the total offset
|
ridingEntity.posY += offset / packetsRequired; // Move a fraction of the total offset
|
||||||
player.sendQueue.addToSendQueue({
|
ModAPI.network.addToSendQueue({
|
||||||
"action": "RIDING_JUMP", // Simulate a riding jump action
|
"action": "RIDING_JUMP", // Simulate a riding jump action
|
||||||
"entityId": ridingEntity.getEntityId(),
|
"entityId": ridingEntity.getEntityId(),
|
||||||
});
|
});
|
||||||
@ -46,7 +47,7 @@ ModAPI.addEventListener("sendchatmessage", (ev) => {
|
|||||||
|
|
||||||
// Final move
|
// Final move
|
||||||
ridingEntity.posY += offset / packetsRequired;
|
ridingEntity.posY += offset / packetsRequired;
|
||||||
player.sendQueue.addToSendQueue({
|
ModAPI.network.addToSendQueue({
|
||||||
"action": "RIDING_JUMP",
|
"action": "RIDING_JUMP",
|
||||||
"entityId": ridingEntity.getEntityId(),
|
"entityId": ridingEntity.getEntityId(),
|
||||||
});
|
});
|
||||||
@ -54,7 +55,7 @@ ModAPI.addEventListener("sendchatmessage", (ev) => {
|
|||||||
} else {
|
} else {
|
||||||
// Player is not riding any entity
|
// Player is not riding any entity
|
||||||
for (var packetNumber = 0; packetNumber < (packetsRequired - 1); packetNumber++) {
|
for (var packetNumber = 0; packetNumber < (packetsRequired - 1); packetNumber++) {
|
||||||
player.getNetHandler().addToSendQueue({
|
ModAPI.network.addToSendQueue({
|
||||||
"x": player.posX,
|
"x": player.posX,
|
||||||
"y": player.posY,
|
"y": player.posY,
|
||||||
"z": player.posZ,
|
"z": player.posZ,
|
||||||
@ -63,7 +64,7 @@ ModAPI.addEventListener("sendchatmessage", (ev) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Final move
|
// Final move
|
||||||
player.getNetHandler().addToSendQueue({
|
ModAPI.network.addToSendQueue({
|
||||||
"x": player.posX,
|
"x": player.posX,
|
||||||
"y": player.posY + offset,
|
"y": player.posY + offset,
|
||||||
"z": player.posZ,
|
"z": player.posZ,
|
188
examplemods/lib.lcrender.js
Normal file
188
examplemods/lib.lcrender.js
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
ModAPI.meta.title("LibCustomRender");
|
||||||
|
ModAPI.meta.credits("By ZXMushroom63");
|
||||||
|
ModAPI.meta.icon("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAQdJREFUOE9jZGBg+M9AAWAEGbBl2QmyjPCJsmAgaABbdybc8F+l01EswmsATONXLi4GYSkpBgZ+foY1O3cyuHWuhhuC1QBkjf///QMrFtHWZmD4+BHDEBQDUGzU1ITb8ubqVZyGoBjwsCONQYqXl0FYU5MBpAlsKxRgM+STUwoDhgG66upgZ4IAuiEooRcXx/DpCRuqAU97shg0jYzgfsVpSFwcg5mZGcOedRewGDBhAgPDokUohsBthmoE8U+dOoXdBfHHjoElUQxB03i9oABspnTJNFQXgARB3oAbwsAAdirMRmSNMFdhTQcwQ/BpxGsAzCUwRSCn4gJE5QV8uQxuAFlZEaoJAKrYrAHl38o6AAAAAElFTkSuQmCC");
|
||||||
|
ModAPI.meta.description("Library to make retexturing LCI items easier. Requires AsyncSink.");
|
||||||
|
(async function LibRender() {
|
||||||
|
var BreakingFour = ModAPI.reflect.getClassByName("BreakingFour").constructors[0];
|
||||||
|
var BakedQuad = ModAPI.reflect.getClassByName("BakedQuad").constructors[0];
|
||||||
|
var EnumFacing = ModAPI.reflect.getClassByName("EnumFacing");
|
||||||
|
function createBreakingFour(sprite$) {
|
||||||
|
var sprite = ModAPI.util.wrap(sprite$);
|
||||||
|
var vertexData = ModAPI.array.int(28); // 7 integers per vertex, 4 vertices
|
||||||
|
var vertexDataInternal = vertexData.data;
|
||||||
|
|
||||||
|
var vertexDataWithNormals = ModAPI.array.int(32); // 8 integers per vertex, 4 vertices
|
||||||
|
var normalDataInternal = vertexDataWithNormals.data;
|
||||||
|
|
||||||
|
var vertices = [
|
||||||
|
[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]
|
||||||
|
];
|
||||||
|
|
||||||
|
var uvs = [
|
||||||
|
[0, 0], [1, 0], [1, 1], [0, 1]
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
let j = i * 7;
|
||||||
|
vertexDataInternal[j] = ModAPI.hooks.methods.jl_Float_floatToIntBits(vertices[i][0]);
|
||||||
|
vertexDataInternal[j + 1] = ModAPI.hooks.methods.jl_Float_floatToIntBits(vertices[i][1]);
|
||||||
|
vertexDataInternal[j + 2] = ModAPI.hooks.methods.jl_Float_floatToIntBits(vertices[i][2]);
|
||||||
|
vertexDataInternal[j + 3] = rgbToInt(255, 0, 0); // Color (red)
|
||||||
|
vertexDataInternal[j + 4] = ModAPI.hooks.methods.jl_Float_floatToIntBits(sprite.getInterpolatedU(uvs[i][0] * 16));
|
||||||
|
vertexDataInternal[j + 5] = ModAPI.hooks.methods.jl_Float_floatToIntBits(sprite.getInterpolatedV(uvs[i][1] * 16));
|
||||||
|
vertexDataInternal[j + 6] = 0; // Normal
|
||||||
|
|
||||||
|
let k = i * 8;
|
||||||
|
normalDataInternal[k] = vertexDataInternal[j];
|
||||||
|
normalDataInternal[k + 1] = vertexDataInternal[j + 1];
|
||||||
|
normalDataInternal[k + 2] = vertexDataInternal[j + 2];
|
||||||
|
normalDataInternal[k + 3] = vertexDataInternal[j + 3];
|
||||||
|
normalDataInternal[k + 4] = vertexDataInternal[j + 4];
|
||||||
|
normalDataInternal[k + 5] = vertexDataInternal[j + 5];
|
||||||
|
normalDataInternal[k + 6] = vertexDataInternal[j + 6];
|
||||||
|
normalDataInternal[k + 7] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var baseQuad = BakedQuad(vertexData, vertexDataWithNormals, -1, EnumFacing.staticVariables.NORTH);
|
||||||
|
return BreakingFour(baseQuad, sprite$);
|
||||||
|
}
|
||||||
|
function waitUntilPropertyExists(obj, prop) {
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
var timer = setInterval(() => {
|
||||||
|
if (obj[prop]) {
|
||||||
|
clearInterval(timer);
|
||||||
|
res();
|
||||||
|
}
|
||||||
|
}, 50);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function rgbToInt(red, green, blue) {
|
||||||
|
return (red << 16) | (green << 8) | blue;
|
||||||
|
}
|
||||||
|
function rgbaToInt(red, green, blue, alpha) {
|
||||||
|
return (alpha << 24) | (red << 16) | (green << 8) | blue;
|
||||||
|
}
|
||||||
|
function getLore(item) {
|
||||||
|
if (item.$stackTagCompound && item.$stackTagCompound.$hasKey(ModAPI.util.str("display"), 10)) {
|
||||||
|
var displayTag = item.$stackTagCompound.$getCompoundTag(ModAPI.util.str("display"));
|
||||||
|
if (displayTag.$hasKey(ModAPI.util.str("Lore"), 9)) {
|
||||||
|
var loreTag = displayTag.$getTag(ModAPI.util.str("Lore"));
|
||||||
|
if (loreTag.$tagCount() > 0) {
|
||||||
|
return ModAPI.util.ustr(loreTag.$getStringTagAt(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function recursiveAssign(target, patch) {
|
||||||
|
var keys = Object.keys(patch);
|
||||||
|
keys.forEach(k => {
|
||||||
|
if (typeof patch[k] === "object" && patch[k]) {
|
||||||
|
recursiveAssign(target[k], patch[k]);
|
||||||
|
} else if (typeof patch[k] === "number") {
|
||||||
|
target[k] = patch[k];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function cloneBaseModel(baseModel, newTexture, texName) {
|
||||||
|
var sprite = eaglerTextureAtlasSprite(imageDataToLaxImgData(newTexture), ModAPI.util.str(texName));
|
||||||
|
var newBaseModelBuilder = ModAPI.reflect.getClassByName("SimpleBakedModel$Builder").constructors[0](0, 0, ModAPI.reflect.getClassByName("ItemCameraTransforms").constructors.find(x => x.length === 0)());
|
||||||
|
newBaseModelBuilder.$builderTexture = sprite;
|
||||||
|
ModAPI.hooks.methods.nmcrm_SimpleBakedModel$Builder_addGeneralQuad(newBaseModelBuilder, createBreakingFour(sprite));
|
||||||
|
var newBaseModel = ModAPI.hooks.methods.nmcrm_SimpleBakedModel$Builder_makeBakedModel(newBaseModelBuilder);
|
||||||
|
//newBaseModel.$generalQuads = baseModel.$generalQuads.$clone();
|
||||||
|
//newBaseModel.$faceQuads = baseModel.$faceQuads.$clone();
|
||||||
|
//var cameraTransformsId = ModAPI.util.getNearestProperty(newBaseModel, "$cameraTransforms");
|
||||||
|
//recursiveAssign(newBaseModel[cameraTransformsId], baseModel[cameraTransformsId]);
|
||||||
|
return newBaseModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModAPI.events.newEvent("lib:libcustomrender:loaded");
|
||||||
|
await waitUntilPropertyExists(ModAPI.minecraft, "renderItem");
|
||||||
|
var ItemRenderer = ModAPI.minecraft.renderItem;
|
||||||
|
var ItemModelMesher = ItemRenderer.itemModelMesher;
|
||||||
|
var laxImgDataClass = ModAPI.reflect.getClassByName("ImageData").class;
|
||||||
|
var makeLax1dudeImageData = ModAPI.reflect.getClassByName("ImageData").constructors.find(x => x.length === 4);
|
||||||
|
var eaglerTextureAtlasSprite = (imageData, name) => {
|
||||||
|
var atlas = ModAPI.reflect.getClassByName("EaglerTextureAtlasSprite").constructors[0](ModAPI.util.str(name));
|
||||||
|
var alias = ModAPI.util.wrap(atlas);
|
||||||
|
alias.loadSprite(ModAPI.util.makeArray(laxImgDataClass, [imageData]), null);
|
||||||
|
alias.initSprite(1, 1, 0, 0, 0);
|
||||||
|
return atlas;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {ImageData}
|
||||||
|
*/
|
||||||
|
function imageDataToLaxImgData(imageData) {
|
||||||
|
const { data, width, height } = imageData;
|
||||||
|
const intArray = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < data.length; i += 4) {
|
||||||
|
const red = data[i];
|
||||||
|
const green = data[i + 1];
|
||||||
|
const blue = data[i + 2];
|
||||||
|
const alpha = data[i + 3];
|
||||||
|
intArray.push(rgbaToInt(red, green, blue, alpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
return makeLax1dudeImageData(width, height, ModAPI.array.int(intArray), 1);
|
||||||
|
}
|
||||||
|
const LibCustomRender = {};
|
||||||
|
LibCustomRender.map = {};
|
||||||
|
LibCustomRender.addRetextureRule = (loreString, textureBuffer, baseItem) => {
|
||||||
|
baseItem ||= "paper";
|
||||||
|
var actualLoreStr = loreString;
|
||||||
|
loreString = loreString.replaceAll(":", "_").toLowerCase().replace(/[^a-z_]/g, '');
|
||||||
|
if (!(textureBuffer instanceof ImageData)) {
|
||||||
|
return console.error("Texture for retexture rule is not an ImageData.");
|
||||||
|
}
|
||||||
|
if (!(typeof loreString === "string")) {
|
||||||
|
return console.error("loreString for retexture rule is not a string.");
|
||||||
|
}
|
||||||
|
var baseModel = ItemModelMesher.simpleShapesCache.get(ModAPI.hooks.methods.jl_Integer_valueOf(ItemModelMesher.getIndex(ModAPI.items[baseItem].getRef(), 0)));
|
||||||
|
LibCustomRender.map[loreString] = {
|
||||||
|
lore: actualLoreStr,
|
||||||
|
identifier: loreString,
|
||||||
|
model: cloneBaseModel(baseModel.getRef(), textureBuffer, loreString)
|
||||||
|
}
|
||||||
|
return LibCustomRender.map[loreString].model;
|
||||||
|
}
|
||||||
|
|
||||||
|
// override
|
||||||
|
// public IBakedModel getItemModel(ItemStack stack) {
|
||||||
|
// Item item = stack.getItem();
|
||||||
|
// In ItemModelMesher.java
|
||||||
|
|
||||||
|
var methods = Object.keys(ModAPI.hooks.methods);
|
||||||
|
var prefix = ModAPI.util.getMethodFromPackage("net.minecraft.client.renderer.ItemModelMesher", "getItemModel");
|
||||||
|
var methodName = methods.find(x => x.startsWith(prefix) && ModAPI.hooks.methods[x].length === 2);
|
||||||
|
var original = ModAPI.hooks.methods[methodName];
|
||||||
|
ModAPI.hooks.methods[methodName] = function (...args) {
|
||||||
|
var item = args[1];
|
||||||
|
var lore = item ? getLore(item) : "";
|
||||||
|
if (!item) {
|
||||||
|
return original.apply(this, args);
|
||||||
|
}
|
||||||
|
var overrides = Object.values(LibCustomRender.map);
|
||||||
|
for (let i = 0; i < overrides.length; i++) {
|
||||||
|
const override = overrides[i];
|
||||||
|
if (lore === override.lore) {
|
||||||
|
return override.model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return original.apply(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModAPI.events.callEvent("lib:libcustomrender:loaded", {});
|
||||||
|
globalThis.LibCustomRender = LibCustomRender;
|
||||||
|
})();
|
||||||
|
//LibCustomRender.addRetextureRule("mymod:test_item_1", new ImageData(1, 1));
|
||||||
|
|
||||||
|
// const imageData = new ImageData(16, 16);
|
||||||
|
// for (let i = 0; i < imageData.data.length; i += 4) {
|
||||||
|
// imageData.data[i] = Math.floor(Math.random() * 256);
|
||||||
|
// imageData.data[i + 1] = Math.floor(Math.random() * 256);
|
||||||
|
// imageData.data[i + 2] = Math.floor(Math.random() * 256);
|
||||||
|
// imageData.data[i + 3] = 255;
|
||||||
|
// }
|
||||||
|
// LibCustomRender.addRetextureRule("mymod:test_item_1", imageData);
|
41
examplemods/mobnpcspawner.js
Normal file
41
examplemods/mobnpcspawner.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
(() => {
|
||||||
|
PluginAPI.dedicatedServer.appendCode(function () {
|
||||||
|
PluginAPI.addEventListener("processcommand", (event) => {
|
||||||
|
// Check if the sender is a player
|
||||||
|
if (!ModAPI.reflect.getClassById("net.minecraft.entity.player.EntityPlayerMP").instanceOf(event.sender.getRef())) { return; }
|
||||||
|
|
||||||
|
// Check if the command is "/spawnnpc"
|
||||||
|
if (event.command.toLowerCase().startsWith("/spawnnpc")) {
|
||||||
|
const world = event.sender.getServerForPlayer();
|
||||||
|
const senderPos = event.sender.getPosition();
|
||||||
|
|
||||||
|
// Create a sheep entity
|
||||||
|
const EntitySheepClass = ModAPI.reflect.getClassById("net.minecraft.entity.passive.EntitySheep");
|
||||||
|
const sheep = EntitySheepClass.constructors[0](world.getRef());
|
||||||
|
|
||||||
|
// Set sheep's position to player's position
|
||||||
|
sheep.$setLocationAndAngles(senderPos.getX(), senderPos.getY(), senderPos.getZ(), senderPos.rotationYaw, senderPos.rotationPitch);
|
||||||
|
|
||||||
|
// Disable AI (no AI behavior)
|
||||||
|
sheep.$getDataWatcher().$updateObject(15, 1); // AI flag, 15 is the byte for AI, 1 means no AI
|
||||||
|
|
||||||
|
// Disable gravity
|
||||||
|
sheep.$noGravity = 1;
|
||||||
|
|
||||||
|
// Make sheep invincible
|
||||||
|
sheep.$setEntityInvulnerable(1);
|
||||||
|
|
||||||
|
// Add the sheep to the world
|
||||||
|
world.spawnEntityInWorld(sheep);
|
||||||
|
|
||||||
|
// Notify the player that the sheep has been spawned
|
||||||
|
const ChatComponentTextClass = ModAPI.reflect.getClassById("net.minecraft.util.ChatComponentText");
|
||||||
|
event.sender.addChatMessage(ChatComponentTextClass.constructors[0](ModAPI.util.str("A special sheep has been spawned!")));
|
||||||
|
|
||||||
|
|
||||||
|
// Prevent the command from executing further
|
||||||
|
event.preventDefault = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
@ -1,12 +1,28 @@
|
|||||||
(() => {
|
(() => {
|
||||||
PluginAPI.dedicatedServer.appendCode(function () {
|
PluginAPI.dedicatedServer.appendCode(function () {
|
||||||
|
var ready = false;
|
||||||
|
var killFS = false;
|
||||||
|
function setup_filesystem_middleware() {
|
||||||
|
if (!ready) {
|
||||||
|
AsyncSink.MIDDLEWARE.push((ev)=>{
|
||||||
|
if (killFS) {
|
||||||
|
ev.shim = true;
|
||||||
|
if (typeof ev.shimOutput === "boolean") {
|
||||||
|
ev.shimOutput = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ready = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
PluginAPI.addEventListener("processcommand", (event) => {
|
PluginAPI.addEventListener("processcommand", (event) => {
|
||||||
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) {
|
if (!globalThis.AsyncSink) {
|
||||||
return alert("NPC Spawner relies on the AsyncSink library.");
|
return console.error("NPC Spawner relies on the AsyncSink library.");
|
||||||
}
|
}
|
||||||
|
setup_filesystem_middleware();
|
||||||
const world = event.sender.getServerForPlayer();
|
const world = event.sender.getServerForPlayer();
|
||||||
const senderPos = event.sender.getPosition();
|
const senderPos = event.sender.getPosition();
|
||||||
|
|
||||||
@ -23,20 +39,19 @@
|
|||||||
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();
|
killFS = true;
|
||||||
const EntityPlayerMPClass = ModAPI.reflect.getClassById("net.minecraft.entity.player.EntityPlayerMP");
|
const EntityPlayerMPClass = ModAPI.reflect.getClassById("net.minecraft.entity.player.EntityPlayerMP");
|
||||||
var worldNameProp = ModAPI.util.getNearestProperty(ModAPI.server.getRef(), "$worldName");
|
const fakePlayer = ModAPI.util.wrap(EntityPlayerMPClass.constructors[0](
|
||||||
var worldName = ModAPI.server.getRef()[worldNameProp];
|
|
||||||
console.log(ModAPI.util.ustr(worldName));
|
|
||||||
const fakePlayer = EntityPlayerMPClass.constructors[0](
|
|
||||||
ModAPI.server.getRef(), world.getRef(), fakeProfile, playerInteractionManager
|
ModAPI.server.getRef(), world.getRef(), fakeProfile, playerInteractionManager
|
||||||
);
|
));
|
||||||
|
killFS = false;
|
||||||
|
|
||||||
// Set the fake player position to be near the command sender
|
// Set the fake player position to be near the command sender
|
||||||
fakePlayer.setPosition(senderPos.$getX(), senderPos.$getY(), senderPos.$getZ());
|
console.log(senderPos);
|
||||||
|
fakePlayer.setPosition(senderPos.getX(), senderPos.getY(), senderPos.getZ());
|
||||||
|
|
||||||
// Add the fake player to the world
|
// Add the fake player to the world
|
||||||
world.addEntityToWorld(fakePlayer.getEntityId(), fakePlayer);
|
world.spawnEntityInWorld(fakePlayer.getRef());
|
||||||
|
|
||||||
// Notify the player that the fake player has been spawned
|
// Notify the player that the fake player has been spawned
|
||||||
const ChatComponentTextClass = ModAPI.reflect.getClassById("net.minecraft.util.ChatComponentText");
|
const ChatComponentTextClass = ModAPI.reflect.getClassById("net.minecraft.util.ChatComponentText");
|
||||||
|
23
examplemods/slippery.js
Normal file
23
examplemods/slippery.js
Normal file
File diff suppressed because one or more lines are too long
@ -1,4 +1,4 @@
|
|||||||
//SUCCESS - While there is no TeaVM thread actively running, I am able to run an asyncronous function, and get a result.
|
//SUCCESS - While there is no TeaVM thread actively running, I am able to run an asynchronous function, and get a result.
|
||||||
ModAPI.hooks._teavm.$rt_startThread(() => {
|
ModAPI.hooks._teavm.$rt_startThread(() => {
|
||||||
return ModAPI.hooks.methods.nlevi_PlatformRuntime_downloadRemoteURI(ModAPI.util.str("data:text/plain,hi"))
|
return ModAPI.hooks.methods.nlevi_PlatformRuntime_downloadRemoteURI(ModAPI.util.str("data:text/plain,hi"))
|
||||||
}, function (...args) { console.log(this, args) })
|
}, function (...args) { console.log(this, args) })
|
||||||
|
17
examplemods/vclip.js
Normal file
17
examplemods/vclip.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
ModAPI.meta.title("Simple VClip Exploit");
|
||||||
|
ModAPI.meta.description("Use .vclip <offset> to vertically phase through blocks.");
|
||||||
|
ModAPI.meta.credits("By ZXMushroom63");
|
||||||
|
ModAPI.require("player");
|
||||||
|
ModAPI.addEventListener("sendchatmessage", (ev) => {
|
||||||
|
var msg = ev.message.toLowerCase();
|
||||||
|
if (msg.startsWith(".vclip")) {
|
||||||
|
ev.preventDefault = true;
|
||||||
|
var yOffset = 1;
|
||||||
|
if (msg.split(" ")[1]) {
|
||||||
|
yOffset = parseFloat(msg.split(" ")[1]) || 0;
|
||||||
|
}
|
||||||
|
ModAPI.player.setPosition(ModAPI.player.posX, ModAPI.player.posY
|
||||||
|
+ yOffset, ModAPI.player.posZ);
|
||||||
|
ModAPI.displayToChat("[SimpleVClip] VClipped " + yOffset + " blocks.");
|
||||||
|
}
|
||||||
|
});
|
@ -91,7 +91,8 @@
|
|||||||
>
|
>
|
||||||
<br />
|
<br />
|
||||||
<span><label>Minify: </label><input type="checkbox" oninput="globalThis.doShronk = this.checked">
|
<span><label>Minify: </label><input type="checkbox" oninput="globalThis.doShronk = this.checked">
|
||||||
<label>EaglerForge: </label><input checked type="checkbox" oninput="globalThis.doEaglerforge = this.checked">
|
<label>EaglerForge: </label><input checked type="checkbox" oninput="globalThis.doEaglerforge = this.checked">
|
||||||
|
<label>Optimize π: </label><input checked type="checkbox" oninput="globalThis.optimizePi= this.checked">
|
||||||
<code id="status">Awaiting input...</code></span>
|
<code id="status">Awaiting input...</code></span>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<button class="btn btn-primary" id="giveme">Make modded client</button>
|
<button class="btn btn-primary" id="giveme">Make modded client</button>
|
||||||
|
26
injector.js
26
injector.js
@ -1,4 +1,5 @@
|
|||||||
globalThis.doEaglerforge = true;
|
globalThis.doEaglerforge = true;
|
||||||
|
globalThis.optimizePi = true;
|
||||||
function wait(ms) {
|
function wait(ms) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
setTimeout(() => { resolve(); }, ms);
|
setTimeout(() => { resolve(); }, ms);
|
||||||
@ -135,6 +136,29 @@ var main;(function(){`
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if(globalThis.optimizePi){
|
||||||
|
patchedFile = patchedFile.replaceAll(
|
||||||
|
"3.1415927410125732 / 180.0",
|
||||||
|
"0.01745"
|
||||||
|
);
|
||||||
|
|
||||||
|
patchedFile = patchedFile.replaceAll(
|
||||||
|
"180.0 / 3.1415927410125732",
|
||||||
|
"57.2958"
|
||||||
|
);
|
||||||
|
|
||||||
|
patchedFile = patchedFile.replaceAll(
|
||||||
|
"3.1415927410125732",
|
||||||
|
"3.14159"
|
||||||
|
);
|
||||||
|
|
||||||
|
patchedFile = patchedFile.replaceAll(
|
||||||
|
"0.01745329238474369",
|
||||||
|
"0.01745"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const extractInstanceMethodRegex =
|
const extractInstanceMethodRegex =
|
||||||
/^[\t ]*function \S+?_\S+?_\S+?\((\$this)?/gm; // /^[\t ]*function \S+?_\S+?_\S+?\(\$this/gm
|
/^[\t ]*function \S+?_\S+?_\S+?\((\$this)?/gm; // /^[\t ]*function \S+?_\S+?_\S+?\(\$this/gm
|
||||||
const extractInstanceMethodFullNameRegex = /function (\S*?)\(/gm; // /function (\S*?)\(\$this/gm
|
const extractInstanceMethodFullNameRegex = /function (\S*?)\(/gm; // /function (\S*?)\(\$this/gm
|
||||||
@ -197,6 +221,8 @@ var main;(function(){`
|
|||||||
);
|
);
|
||||||
//Edge cases. sigh
|
//Edge cases. sigh
|
||||||
//Done: add support for static properties on classes with constructors like this: function nmcg_GuiMainMenu() {
|
//Done: add support for static properties on classes with constructors like this: function nmcg_GuiMainMenu() {
|
||||||
|
|
||||||
|
|
||||||
patchedFile = patchedFile.replaceAll(
|
patchedFile = patchedFile.replaceAll(
|
||||||
/function [a-z]+?_([a-zA-Z\$]+?)\(\) \{/gm,
|
/function [a-z]+?_([a-zA-Z\$]+?)\(\) \{/gm,
|
||||||
(match) => {
|
(match) => {
|
||||||
|
@ -8,7 +8,8 @@ globalThis.modapi_guikit = `// ModAPI GUI made by TheIdiotPlays
|
|||||||
"https://github.com/EaglerForge",
|
"https://github.com/EaglerForge",
|
||||||
"hey you should check out https://github.com/ZXMushroom63/scratch-gui",
|
"hey you should check out https://github.com/ZXMushroom63/scratch-gui",
|
||||||
"99% of people stop gambling before they win big.",
|
"99% of people stop gambling before they win big.",
|
||||||
"Now with free estradiol!"
|
"Now with free estradiol!",
|
||||||
|
"Now with H.I.V (Hyper Injected Virtual-debugger)"
|
||||||
];
|
];
|
||||||
var gui = \`<div id="modapi_gui_container">
|
var gui = \`<div id="modapi_gui_container">
|
||||||
<header>
|
<header>
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
"https://github.com/EaglerForge",
|
"https://github.com/EaglerForge",
|
||||||
"hey you should check out https://github.com/ZXMushroom63/scratch-gui",
|
"hey you should check out https://github.com/ZXMushroom63/scratch-gui",
|
||||||
"99% of people stop gambling before they win big.",
|
"99% of people stop gambling before they win big.",
|
||||||
"Now with free estradiol!"
|
"Now with free estradiol!",
|
||||||
|
"Now with H.I.V (Hyper Injected Virtual-debugger)"
|
||||||
];
|
];
|
||||||
var gui = `<div id="modapi_gui_container">
|
var gui = `<div id="modapi_gui_container">
|
||||||
<header>
|
<header>
|
||||||
|
57
postinit.js
57
postinit.js
@ -296,6 +296,15 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
}
|
}
|
||||||
var reloadDeprecationWarnings = 0;
|
var reloadDeprecationWarnings = 0;
|
||||||
const TeaVM_to_BaseData_ProxyConf = {
|
const TeaVM_to_BaseData_ProxyConf = {
|
||||||
|
ownKeys(target) {
|
||||||
|
return Reflect.ownKeys(target).flatMap(x => x.substring(1));
|
||||||
|
},
|
||||||
|
getOwnPropertyDescriptor(target, prop) {
|
||||||
|
return Object.getOwnPropertyDescriptor(target, "$" + prop);
|
||||||
|
},
|
||||||
|
has(target, prop) {
|
||||||
|
return ("$" + prop) in target;
|
||||||
|
},
|
||||||
get(target, prop, receiver) {
|
get(target, prop, receiver) {
|
||||||
if (prop === "getRef") {
|
if (prop === "getRef") {
|
||||||
return function () {
|
return function () {
|
||||||
@ -348,6 +357,15 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const TeaVM_to_Recursive_BaseData_ProxyConf = {
|
const TeaVM_to_Recursive_BaseData_ProxyConf = {
|
||||||
|
ownKeys(target) {
|
||||||
|
return Reflect.ownKeys(target).flatMap(x => x.substring(1));
|
||||||
|
},
|
||||||
|
getOwnPropertyDescriptor(target, prop) {
|
||||||
|
return Object.getOwnPropertyDescriptor(target, "$" + prop);
|
||||||
|
},
|
||||||
|
has(target, prop) {
|
||||||
|
return ("$" + prop) in target;
|
||||||
|
},
|
||||||
get(target, prop, receiver) {
|
get(target, prop, receiver) {
|
||||||
if (prop === "getRef") {
|
if (prop === "getRef") {
|
||||||
return function () {
|
return function () {
|
||||||
@ -584,6 +602,25 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
})[0] || null;
|
})[0] || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModAPI.util.modifyFunction = function (fn, patcherFn) {
|
||||||
|
// Convert the original function to a string
|
||||||
|
let functionString = fn.toString();
|
||||||
|
|
||||||
|
// Extract the function body
|
||||||
|
let bodyStart = functionString.indexOf('{') + 1;
|
||||||
|
let bodyEnd = functionString.lastIndexOf('}');
|
||||||
|
let functionBody = functionString.substring(bodyStart, bodyEnd);
|
||||||
|
|
||||||
|
// Replace the function body with new instructions
|
||||||
|
let modifiedFunctionBody = patcherFn(functionBody) || 'return;';
|
||||||
|
|
||||||
|
// Create a new function with the same arguments and the modified body
|
||||||
|
let args = functionString.substring(functionString.indexOf('(') + 1, functionString.indexOf(')'));
|
||||||
|
let modifiedFunction = new Function(args, modifiedFunctionBody);
|
||||||
|
|
||||||
|
return modifiedFunction;
|
||||||
|
}
|
||||||
|
|
||||||
ModAPI.clickMouse = function () {
|
ModAPI.clickMouse = function () {
|
||||||
ModAPI.hooks.methods["nmc_Minecraft_clickMouse"](ModAPI.javaClient);
|
ModAPI.hooks.methods["nmc_Minecraft_clickMouse"](ModAPI.javaClient);
|
||||||
}
|
}
|
||||||
@ -661,6 +698,26 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
return sendChatMessage.apply(this, [$this, $message]);
|
return sendChatMessage.apply(this, [$this, $message]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ModAPI.events.newEvent("render", "client");
|
||||||
|
// const renderMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.client.renderer.EntityRenderer", "renderWorldPass");
|
||||||
|
// const renderMethod = ModAPI.hooks.methods[renderMethodName];
|
||||||
|
// ModAPI.hooks.methods[renderMethodName] = function ($this, $int_pass, $float_partialTicks, $long_finishTimeNano) {
|
||||||
|
// var shouldRenderHand = $this.$renderHand;
|
||||||
|
// $this.$renderHand = 0; //Rendering the hand clears the depth bit, which we don't want to do.
|
||||||
|
// var out = renderMethod.apply(this, [$this, $int_pass, $float_partialTicks, $long_finishTimeNano]);
|
||||||
|
// var data = {
|
||||||
|
// partialTicks: $float_partialTicks
|
||||||
|
// }
|
||||||
|
// ModAPI.events.callEvent("render", data);
|
||||||
|
// if (shouldRenderHand) {
|
||||||
|
// ModAPI.hooks.methods.nlevo_GlStateManager_clear(256); //GL_DEPTH_BUFFER_BIT, found in class RealOpenGLEnums
|
||||||
|
// ModAPI.hooks.methods.nmcr_EntityRenderer_renderHand($this, $float_partialTicks, $int_pass);
|
||||||
|
// ModAPI.hooks.methods.nmcr_EntityRenderer_renderWorldDirections($this, $float_partialTicks);
|
||||||
|
// }
|
||||||
|
// $this.$renderHand = shouldRenderHand;
|
||||||
|
// return out;
|
||||||
|
// }
|
||||||
|
|
||||||
const ScaledResolutionConstructor = ModAPI.reflect.getClassByName("ScaledResolution").constructors[0];
|
const ScaledResolutionConstructor = ModAPI.reflect.getClassByName("ScaledResolution").constructors[0];
|
||||||
ModAPI.events.newEvent("frame", "client");
|
ModAPI.events.newEvent("frame", "client");
|
||||||
const frameMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.client.Minecraft", "runTick");
|
const frameMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.client.Minecraft", "runTick");
|
||||||
|
@ -10,11 +10,12 @@
|
|||||||
<h1>EaglerForgeInjector Roadmap</h1>
|
<h1>EaglerForgeInjector Roadmap</h1>
|
||||||
|
|
||||||
<div id="todolist">
|
<div id="todolist">
|
||||||
Add makeItemStack to LCI [done]
|
Add custom itemstack meta to LCI [done]
|
||||||
Fix blocklook.js [todo]
|
Fix blocklook.js [todo]
|
||||||
Fix setblocktest.js [done]
|
Fix setblocktest.js [done]
|
||||||
`ModAPI.asyncMode(10)# and `ModAPI.exitAsync()# to allow using `await# on things. I will have to create a new `TeaVMThread#, and create a `ModAPI.util.async(fn)# method to promisify. [wip]
|
Async toolkit library [done]
|
||||||
Full backwards compatibility for mods [todo]
|
Object.keys() and `in` operator on proxy objects [todo]
|
||||||
|
Add textures to LCI. [todo]
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="roadmap.js"></script>
|
<script src="roadmap.js"></script>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user