Skip to content

Commit

Permalink
Merge pull request #33 from eaglerforge/main
Browse files Browse the repository at this point in the history
add self-compile instructions to documentation
  • Loading branch information
ZXMushroom63 authored Nov 17, 2024
2 parents a07c320 + 0af8737 commit acc4df7
Show file tree
Hide file tree
Showing 10 changed files with 246 additions and 25 deletions.
53 changes: 53 additions & 0 deletions docs/compiling_client.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Compiling Eaglercraft with support for EFI
In recent updates of eaglercraft, compiling for EaglerForgeInjector has become a great deal more complicated. To enable reflection and disable obfuscation, follow these steps once you have an EaglercraftX workspace set up:


1. In any files named `build.gradle`, set the `obfuscate` property to `false`.
2. In any files named `build.gradle`, find any code that looks like this:
```javascript
tasks.named("generateJavaScript") {
doLast {

// NOTE: This step may break at any time, and is not required for 99% of browsers

def phile = file(folder + "/" + name)
def dest = phile.getText("UTF-8")
def i = dest.substring(0, dest.indexOf("=\$rt_globals.Symbol('jsoClass');")).lastIndexOf("let ")
dest = dest.substring(0, i) + "var" + dest.substring(i + 3)
def j = dest.indexOf("function(\$rt_globals,\$rt_exports){")
dest = dest.substring(0, j + 34) + "\n" + file(folder + "/ES6ShimScript.txt").getText("UTF-8") + "\n" + dest.substring(j + 34)
phile.write(dest, "UTF-8")
}
}
```
and delete it.
3. Inside of the `src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/` folder, create a new file called `ForceReflection.java`, with these contents:
```java
package net.lax1dude.eaglercraft.v1_8.internal.teavm;
public class ForceReflection {
public static Object myObject;
public static Object forceInit(Class iClass) {
myObject = new ReflectiveClass();
try {
myObject = iClass.newInstance();
} catch (Exception e) {
// TODO: handle exception
}
return myObject;
}
public static class ReflectiveClass {
}
}
```
4. In the same folder, edit `MainClass.java` edit the start of the `main(String[] args)` method to look like this:
```java
public static void main(String[] args) {
ForceReflection.forceInit(ForceReflection.class);
if(args.length == 1) {
//... rest of method
```
5. Finally, build an offline download by using `CompileJS.bat`/`CompileJS.sh` and then `MakeOfflineDownload.bat`/`MakeOfflineDownload.sh`.
6. You can then upload the `EaglercraftX_1.8_Offline_en_US.html` into EaglerForgeInjector.
52 changes: 52 additions & 0 deletions examplemods/Worldedit.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,58 @@ ModAPI.addEventListener("lib:libcustomitems:loaded", () => {
}
event.preventDefault = true;
}
// "this command was made by EymenWSMC. comments included" - radmanplays
if (event.command.toLowerCase().startsWith("//replacenear")) {
const args = event.command.split(" ").slice(1);
if (args.length < 3) {
event.sender.addChatMessage(ModAPI.reflect.getClassById("net.minecraft.util.ChatComponentText").constructors[0](ModAPI.util.str(prefix + "Usage: //replacenear <radius> <targetBlock> <replacementBlock>")));
event.preventDefault = true;
return;
}

const radius = parseInt(args[0]);
const targetBlockName = args[1];
const replacementBlockName = args[2];

const targetBlock = ModAPI.blocks[targetBlockName];
const replacementBlock = ModAPI.blocks[replacementBlockName];
if (!targetBlock || !replacementBlock) {
event.sender.addChatMessage(ModAPI.reflect.getClassById("net.minecraft.util.ChatComponentText").constructors[0](ModAPI.util.str(prefix + "Invalid block names!")));
event.preventDefault = true;
return;
}


//Replacing logic
const targetBlockState = targetBlock.getDefaultState().getRef();
const replacementBlockState = replacementBlock.getDefaultState().getRef();

const playerPos = event.sender.getPosition();
const xStart = Math.floor(playerPos.x - radius);
const xEnd = Math.floor(playerPos.x + radius);
const yStart = Math.floor(playerPos.y - radius);
const yEnd = Math.floor(playerPos.y + radius);
const zStart = Math.floor(playerPos.z - radius);
const zEnd = Math.floor(playerPos.z + radius);

//Replace ity with radoius
for (let x = xStart; x <= xEnd; x++) {
for (let y = yStart; y <= yEnd; y++) {
for (let z = zStart; z <= zEnd; z++) {
const blockPos = blockPosConstructor(x, y, z);
const currentBlock = event.sender.getServerForPlayer().getBlockState(blockPos);

if (currentBlock.equals(targetBlockState)) {
event.sender.getServerForPlayer().setBlockState(blockPos, replacementBlockState, 3);
}
}
}
}

//Send messages shit
event.sender.addChatMessage(ModAPI.reflect.getClassById("net.minecraft.util.ChatComponentText").constructors[0](ModAPI.util.str(prefix + `Replaced ${targetBlockName} with ${replacementBlockName} within radius ${radius}`)));
event.preventDefault = true;
}
});
});
})();
8 changes: 5 additions & 3 deletions examplemods/block_of_steve_advanced.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,11 @@ function registerSteveClientSide() {
ModAPI.util.str("steve")
);
blockClass.staticMethods.registerBlock0.method(
198, //use blockid 198
198, //use blockid 198. MAKE SURE TO CHANGE IF YOU ARE MAKING A MOD USING THIS, MAXIMUM BLOCK ID IS 4095.
ModAPI.util.str("steve"),
block_of_steve
);
itemClass.staticMethods.registerItemBlock0.method(block_of_steve);
ModAPI.mc.renderItem.registerBlock(block_of_steve, ModAPI.util.str("steve"));
ModAPI.addEventListener("lib:asyncsink", async () => {
ModAPI.addEventListener("custom:asyncsink_reloaded", ()=>{
ModAPI.mc.renderItem.registerBlock(block_of_steve, ModAPI.util.str("steve"));
Expand Down Expand Up @@ -88,6 +87,7 @@ function registerSteveClientSide() {
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE0SURBVDhPpdO9S8NAHMbxy3sVfJmMg6h7FRXXkkUUX0addSjo4OAfIDqLIoiLi3+BRRx0EIQOnV0EcVAIWkR0KIFgrcEktX6vcXD0nuE+5Afhnhw5bWy4qylaidOfVQhT0zFKYozjBHVdzi3TwCZvteaS/0fLD8oGf5OzTeyxNUyE3Ln2HmGctpuxKuS3wd76CgPHsrEj142NeojCkHsFry+4c3aJ6g1OtlZp0Ok4DD4i+Y2GIZ+DMMAhtw+fHu8xi3IDM9t5YfMQF71dLHo+ZjsfXbh4WtnH0vYaqp/BcXGGM3D7BxiYTi+el8uYZWm2gM/VB/Tfaqje4GB5iga2Jv+sUuUa5/ITmOXq7gbnC+MY1r9QvcHG9AgN0lRex1u/ilr7ehqWvBNZvMlRbESfqNhAiG/Pb1bHXpMbFgAAAABJRU5ErkJggg=="
)).arrayBuffer());
});
ModAPI.blocks["steve"] = block_of_steve;
}
function registerSteveServerSide() {
function fixupBlockIds() {
Expand All @@ -112,16 +112,18 @@ function registerSteveServerSide() {
ModAPI.util.str("steve")
);
blockClass.staticMethods.registerBlock0.method(
198,
198, //use blockid 198. MAKE SURE TO CHANGE IF YOU ARE MAKING A MOD USING THIS, MAXIMUM BLOCK ID IS 4095.
ModAPI.util.str("steve"),
block_of_steve
);
itemClass.staticMethods.registerItemBlock0.method(block_of_steve);
fixupBlockIds();
ModAPI.blocks["steve"] = block_of_steve;
});
}
ModAPI.dedicatedServer.appendCode(makeSteveBlock);
makeSteveBlock();
registerSteveClientSide();
fixupBlockIds();

ModAPI.dedicatedServer.appendCode(registerSteveServerSide);
8 changes: 4 additions & 4 deletions examplemods/block_of_steve_simple.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,11 @@ function registerSteveClientSide() {
ModAPI.util.str("steve")
).$setCreativeTab(creativeBlockTab);
blockClass.staticMethods.registerBlock0.method(
198, //use blockid 198
198, //use blockid 198. MAKE SURE TO CHANGE IF YOU ARE MAKING A MOD USING THIS, MAXIMUM BLOCK ID IS 4095.
ModAPI.util.str("steve"),
block_of_steve
);
itemClass.staticMethods.registerItemBlock0.method(block_of_steve);
ModAPI.mc.renderItem.registerBlock(block_of_steve, ModAPI.util.str("steve"));


ModAPI.addEventListener("lib:asyncsink", async () => {
ModAPI.addEventListener("custom:asyncsink_reloaded", ()=>{
Expand Down Expand Up @@ -72,6 +70,7 @@ function registerSteveClientSide() {
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE0SURBVDhPpdO9S8NAHMbxy3sVfJmMg6h7FRXXkkUUX0addSjo4OAfIDqLIoiLi3+BRRx0EIQOnV0EcVAIWkR0KIFgrcEktX6vcXD0nuE+5Afhnhw5bWy4qylaidOfVQhT0zFKYozjBHVdzi3TwCZvteaS/0fLD8oGf5OzTeyxNUyE3Ln2HmGctpuxKuS3wd76CgPHsrEj142NeojCkHsFry+4c3aJ6g1OtlZp0Ok4DD4i+Y2GIZ+DMMAhtw+fHu8xi3IDM9t5YfMQF71dLHo+ZjsfXbh4WtnH0vYaqp/BcXGGM3D7BxiYTi+el8uYZWm2gM/VB/Tfaqje4GB5iga2Jv+sUuUa5/ITmOXq7gbnC+MY1r9QvcHG9AgN0lRex1u/ilr7ehqWvBNZvMlRbESfqNhAiG/Pb1bHXpMbFgAAAABJRU5ErkJggg=="
)).arrayBuffer());
});
ModAPI.blocks["steve"] = block_of_steve;
}
function registerSteveServerSide() {
function fixupBlockIds() {
Expand All @@ -98,12 +97,13 @@ function registerSteveServerSide() {
ModAPI.util.str("steve")
).$setCreativeTab(creativeBlockTab);
blockClass.staticMethods.registerBlock0.method(
198,
198, //use blockid 198. MAKE SURE TO CHANGE IF YOU ARE MAKING A MOD USING THIS, MAXIMUM BLOCK ID IS 4095.
ModAPI.util.str("steve"),
block_of_steve
);
itemClass.staticMethods.registerItemBlock0.method(block_of_steve);
fixupBlockIds();
ModAPI.blocks["steve"] = block_of_steve;
});
}
registerSteveClientSide();
Expand Down
51 changes: 51 additions & 0 deletions examplemods/diamondBlockCustomCraft.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
(function AddDiamondRecipe() {
ModAPI.meta.title("DiamondCraftingRecipeMod");
ModAPI.meta.description("Adds a crafting recipe to create diamond blocks from dirt.");

async function addDiamondRecipe() {
await new Promise((res,rej)=>{var x = setInterval(()=>{if(ModAPI.blocks){clearInterval(x);res();}}, 100);})
var ObjectClass = ModAPI.reflect.getClassById("java.lang.Object").class;
function ToChar(char) {
return ModAPI.reflect.getClassById("java.lang.Character").staticMethods.valueOf.method(char[0].charCodeAt(0));
}

// Define the recipe legend to map characters to items
var recipeLegend = {
"D": {
type: "block",
id: "dirt" // Using dirt blocks
}
};

// Define the crafting grid pattern for the recipe
var recipePattern = [
"DDD",
"DDD",
"DDD"
];

// Convert the recipe pattern and legend into the required format
var recipeInternal = [];
Object.keys(recipeLegend).forEach((key) => {
recipeInternal.push(ToChar(key));
var ingredient = ModAPI.blocks[recipeLegend[key].id].getRef();
recipeInternal.push(ingredient);
});

var recipeContents = recipePattern.flatMap(row => ModAPI.util.str(row));
var recipe = ModAPI.util.makeArray(ObjectClass, recipeContents.concat(recipeInternal));

// Define the output item as diamond_block
var resultItem = ModAPI.reflect.getClassById("net.minecraft.item.ItemStack").constructors[1](ModAPI.blocks["diamond_block"].getRef(), 1);



// Register the recipe with CraftingManager
var craftingManager = ModAPI.reflect.getClassById("net.minecraft.item.crafting.CraftingManager").staticMethods.getInstance.method();
ModAPI.hooks.methods.nmic_CraftingManager_addRecipe(craftingManager, resultItem, recipe);
}

ModAPI.dedicatedServer.appendCode(addDiamondRecipe);

addDiamondRecipe();
})();
6 changes: 3 additions & 3 deletions examplemods/lib.customitems.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
globalThis.LCI_ITEMDB ||= {};
globalThis.LibCustomItems = {
makeItemStack: function makeItemStack(tag) {
return globalThis.LCI_ITEMBD[tag] || null;
return globalThis.LCI_ITEMDB[tag] || null;
}
};
var useName = ModAPI.util.getMethodFromPackage("net.minecraft.network.NetHandlerPlayServer", "processPlayerBlockPlacement");
Expand Down Expand Up @@ -148,7 +148,7 @@
if (globalThis.LCI_RECIPEEVENTS[data.tag]) {
globalThis.LCI_RECIPEEVENTS[data.tag](new Proxy(testItem, ModAPI.util.TeaVM_to_Recursive_BaseData_ProxyConf));
}
globalThis.LCI_ITEMBD[data.tag] = new Proxy(testItem, ModAPI.util.TeaVM_to_Recursive_BaseData_ProxyConf);
globalThis.LCI_ITEMDB[data.tag] = new Proxy(testItem, ModAPI.util.TeaVM_to_Recursive_BaseData_ProxyConf);

var craftingManager = ModAPI.reflect.getClassById("net.minecraft.item.crafting.CraftingManager").staticMethods.getInstance.method();
if((data.useRecipe !== false) || (data.useRecipe !== "false")) {
Expand All @@ -162,7 +162,7 @@
LCI_registerItem(data);
}
LibCustomItems.makeItemStack = function makeItemStack(tag) {
return globalThis.LCI_ITEMBD[tag] || null;
return globalThis.LCI_ITEMDB[tag] || null;
}
ModAPI.events.callEvent("lib:libcustomitems:loaded", {});
})();
4 changes: 4 additions & 0 deletions examplemods/no_particles.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examplemods/unlucky_blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
ModAPI.util.str("unluckiness")
);
blockClass.staticMethods.registerBlock0.method(
544,
544, //use blockid 544. MAKE SURE TO CHANGE IF YOU ARE MAKING A MOD USING THIS, MAXIMUM BLOCK ID IS 4095.
ModAPI.util.str("unluckiness"),
block_of_unluckiness
);
Expand Down
72 changes: 72 additions & 0 deletions examplemods/useless_item_example_mod.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// This is an example mod on how to register an item.
(()=>{
const itemTexture = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAKZJREFUOE9j/P//PxMDBIBoEP6HREOl4PLIciA2AyPIgMcM//7KgvWSDJjBBpx9/+YvJzc3Sbq12DhB6sEGsJ19/+YnmQawYhigzc7FcPXnN4KugbqAHWQAy9n3b34T4wJkw6EGYLqAoNVQBWS5ANlwZBfAvUCs/0EGkW0AzBKqGoCSDgh5A80F2KMRpAgfAKUT6kcjsfEPUycmKMQgy8AETkgUZWcAS3CPIf4oSPsAAAAASUVORK5CYII=";
//this texture is really baad, so the item appears 2d in game.
ModAPI.meta.title("Adding items demo.");
ModAPI.meta.version("v1.0");
ModAPI.meta.icon(itemTexture);
ModAPI.meta.description("Requires AsyncSink.");

function ExampleItem() {
var creativeMiscTab = ModAPI.reflect.getClassById("net.minecraft.creativetab.CreativeTabs").staticVariables.tabMisc;
var itemClass = ModAPI.reflect.getClassById("net.minecraft.item.Item");
var itemSuper = ModAPI.reflect.getSuper(itemClass, (x) => x.length === 1);
var nmi_ItemExample = function nmi_ItemExample() {
itemSuper(this); //Use super function to get block properties on this class.
this.$setCreativeTab(creativeMiscTab);
}
ModAPI.reflect.prototypeStack(itemClass, nmi_ItemExample);
nmi_ItemExample.prototype.$onItemRightClick = function ($itemstack, $world, $player) { //example of how to override a method
return $itemstack;
}

function internal_reg() {
var example_item = (new nmi_ItemExample()).$setUnlocalizedName(
ModAPI.util.str("exampleitem")
);
itemClass.staticMethods.registerItem0.method(432, ModAPI.util.str("exampleitem"), example_item);
ModAPI.items["exampleitem"] = example_item;

return example_item;
}

if (ModAPI.items) {
return internal_reg();
} else {
ModAPI.addEventListener("bootstrap", internal_reg);
}
}

ModAPI.dedicatedServer.appendCode(ExampleItem);
var example_item = ExampleItem();

ModAPI.addEventListener("lib:asyncsink", async () => {
ModAPI.addEventListener("custom:asyncsink_reloaded", ()=>{
ModAPI.mc.renderItem.registerItem(example_item, ModAPI.util.str("exampleitem"));
});
AsyncSink.L10N.set("item.exampleitem.name", "Example Item");
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/models/item/exampleitem.json", JSON.stringify(
{
"parent": "builtin/generated",
"textures": {
"layer0": "items/exampleitem"
},
"display": {
"thirdperson": {
"rotation": [ -90, 0, 0 ],
"translation": [ 0, 1, -3 ],
"scale": [ 0.55, 0.55, 0.55 ]
},
"firstperson": {
"rotation": [ 0, -135, 25 ],
"translation": [ 0, 4, 2 ],
"scale": [ 1.7, 1.7, 1.7 ]
}
}
}
));
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/textures/items/exampleitem.png", await (await fetch(
itemTexture
)).arrayBuffer());
});
})();
15 changes: 1 addition & 14 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -117,20 +117,7 @@ <h6>
<summary>
How do I compile my own unobfuscated unsigned Eaglercraft build?
</summary>
Once you have a local EaglercraftX workspace setup, in
<code>build.gradle</code>, set the <code>obfuscate</code> property to
<code>false</code>. Then, run <code>CompileJS.bat</code> (or .sh if on
a unix-based os), and then run <code>MakeOfflineDownload.bat</code>.
The outputted offline download will have a much larger file size than
other offline builds. This is the file you should select. (it should
have a naming convention similar to
<code>EaglercraftX_1.8_Offline_en_US.html</code>)
</details>
<details>
<summary>Roadmap?</summary>
<a href="https://eaglerforge.github.io/EaglerForgeInjector/roadmap/"
>roadmap.</a
>
<a href="docs/compiling_client.md">tutorial here</a>
</details>
<details>
<summary>How does this tool work?</summary>
Expand Down

0 comments on commit acc4df7

Please sign in to comment.