mirror of
https://github.com/eaglerforge/EaglerForgeInjector
synced 2025-07-26 23:39:25 -09:00
commit
a07c3207cf
@ -49,6 +49,10 @@ Can only be used in the context of the dedicated server. More: [DedicatedServerD
|
|||||||
- `serverstart`:
|
- `serverstart`:
|
||||||
- Called when the dedicated server starts.
|
- Called when the dedicated server starts.
|
||||||
- Event object is blank.
|
- Event object is blank.
|
||||||
|
- `bootstrap`:
|
||||||
|
- Called when the dedicated server registers blocks, items, materials, enchantments, etc.
|
||||||
|
- This is when you should register cstom blocks and items.
|
||||||
|
- Event object is blank.
|
||||||
- `serverstop`:
|
- `serverstop`:
|
||||||
- Called when the dedicated server stops.
|
- Called when the dedicated server stops.
|
||||||
- Event object is blank.
|
- Event object is blank.
|
||||||
|
@ -16,7 +16,12 @@ Methods:
|
|||||||
- This method is used to find a class by its id.
|
- This method is used to find a class by its id.
|
||||||
- For example, to get the `Minecraft` class, you can use `ModAPI.reflect.getClassById("Minecraft")`
|
- For example, to get the `Minecraft` class, you can use `ModAPI.reflect.getClassById("Minecraft")`
|
||||||
- This runs slower than `getClassById` because it has to filter through all classes. Make sure to cache the result rather than calling it over and over again.
|
- This runs slower than `getClassById` because it has to filter through all classes. Make sure to cache the result rather than calling it over and over again.
|
||||||
|
- `ModAPI.reflect.getSuper(rClass: ReflectClass, filter: Function) : Function`
|
||||||
|
- Gets a super function from a reflect class. This is used to extend built in classes, like `Block`.
|
||||||
|
- For an example, see lines [29](https://github.com/eaglerforge/EaglerForgeInjector/blob/6e8598c180f96a65c0c101be72e6d0fa53195404/examplemods/unlucky_blocks.js#L29) and [33](https://github.com/eaglerforge/EaglerForgeInjector/blob/6e8598c180f96a65c0c101be72e6d0fa53195404/examplemods/unlucky_blocks.js#L33) in unlucky_blocks.js
|
||||||
|
- `ModAPI.reflect.prototypeStack(rClass: ReflectClass, target: Class/ConstructorFunction) : void`
|
||||||
|
- Copies methods from a reflect class and it's parents onto a target native JavaScript class. This allows TeaVM to use these objects normally, without you having to manually reimplement every method. In other words, this is the equivalent of extending a class.
|
||||||
|
- [Example usage](https://github.com/eaglerforge/EaglerForgeInjector/blob/6e8598c180f96a65c0c101be72e6d0fa53195404/examplemods/unlucky_blocks.js#L37)
|
||||||
### ReflectClass Definition
|
### ReflectClass Definition
|
||||||
|
|
||||||
Each `ReflectClass` has the following properties:
|
Each `ReflectClass` has the following properties:
|
||||||
@ -44,7 +49,9 @@ Each `ReflectClass` has the following properties:
|
|||||||
- List of all the static variable names for the class.
|
- List of all the static variable names for the class.
|
||||||
- `staticVariables: Map<String, *>`
|
- `staticVariables: Map<String, *>`
|
||||||
- key-value dictionary of all the static variables in a class.
|
- key-value dictionary of all the static variables in a class.
|
||||||
- `superclass: String?`
|
- `superclass: Class?`
|
||||||
|
- The raw teavm class of the superclass.
|
||||||
|
- `superclassName: String?`
|
||||||
- The class id of the class's superclass. Eg: `net.minecraft.client.entity.AbstractClientPlayer`
|
- The class id of the class's superclass. Eg: `net.minecraft.client.entity.AbstractClientPlayer`
|
||||||
- Will be `null` if `hasMeta` is equal to `false`
|
- Will be `null` if `hasMeta` is equal to `false`
|
||||||
|
|
||||||
|
@ -37,6 +37,8 @@ Methods:
|
|||||||
- `ModAPI.util.isCritical() : boolean`
|
- `ModAPI.util.isCritical() : boolean`
|
||||||
- Checks wether the thread is in a critical state.
|
- Checks wether the thread is in a critical state.
|
||||||
- When patching methods, it is good practice to allow the method to resume as usual if this is `true`, to avoid stack implosions. (yes, those are real)
|
- When patching methods, it is good practice to allow the method to resume as usual if this is `true`, to avoid stack implosions. (yes, those are real)
|
||||||
|
- `ModAPI.util.bootstrap() : void`
|
||||||
|
- Regenerate proxies for ModAPI.items, .blocks, .materials, .enchantments
|
||||||
- `ModAPI.util.createArray(class, jsArray) : Object[]`
|
- `ModAPI.util.createArray(class, jsArray) : Object[]`
|
||||||
- Makes a java array from a class and a javascript array.
|
- Makes a java array from a class and a javascript array.
|
||||||
- The class parameter can be retrieved via reflect: `ModAPI.reflect.getClassById("net.minecraft.util.BlockPos").class`
|
- The class parameter can be retrieved via reflect: `ModAPI.reflect.getClassById("net.minecraft.util.BlockPos").class`
|
||||||
|
1
docs/tutorials/comingsoon.md
Normal file
1
docs/tutorials/comingsoon.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Coming Soon
|
@ -1,10 +1,11 @@
|
|||||||
ModAPI.meta.title("AsyncSink");
|
ModAPI.meta.title("AsyncSink");
|
||||||
ModAPI.meta.description("Library for patching and hooking into asynchronous filesystem requests for EaglercraftX.");
|
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");
|
const asyncSinkIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAL9JREFUOE9jZGBg+M9ABcAIMsgtPo3hzZ2zYONEVIxJZu9aOIsBbJCRtTHcEJAgLgBSh82ic0fPIgyCKQAJXrx4EcUsfX19sBiIRrYU5gu4Qchew2cQyHSQYehBgdNruFwEcybMZci+gIcRIa+hhxu6LzBiDZvX0A1BDyuivYbLIJK8pqevjze5GlsbMxAdayCT/PQwDRS2gaQror2m36KH4SqjZybwxEl0gsQWRkM01ogpVQh6jaJihBgXEFIDAAIQ9AFDJlrxAAAAAElFTkSuQmCC";
|
||||||
|
ModAPI.meta.icon(asyncSinkIcon);
|
||||||
ModAPI.meta.credits("By ZXMushroom63");
|
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() {
|
async function runtimeComponent() {
|
||||||
const booleanResult = (b) => ModAPI.hooks.methods.nlevit_BooleanResult__new(b * 1);
|
const booleanResult = (b) => ModAPI.hooks.methods.nlevit_BooleanResult__new(b * 1);
|
||||||
const wrap = ModAPI.hooks.methods.otji_JSWrapper_wrap;
|
const wrap = ModAPI.hooks.methods.otji_JSWrapper_wrap;
|
||||||
const unwrap = ModAPI.hooks.methods.otji_JSWrapper_unwrap;
|
const unwrap = ModAPI.hooks.methods.otji_JSWrapper_unwrap;
|
||||||
@ -39,6 +40,7 @@ ModAPI.meta.credits("By ZXMushroom63");
|
|||||||
|
|
||||||
// @type Map<string, ArrayBuffer>
|
// @type Map<string, ArrayBuffer>
|
||||||
AsyncSink.FS = new Map();
|
AsyncSink.FS = new Map();
|
||||||
|
AsyncSink.L10N = new Map();
|
||||||
AsyncSink.FSOverride = new Set();
|
AsyncSink.FSOverride = new Set();
|
||||||
AsyncSink.MIDDLEWARE = [];
|
AsyncSink.MIDDLEWARE = [];
|
||||||
AsyncSink.setFile = function setFile(path, data) {
|
AsyncSink.setFile = function setFile(path, data) {
|
||||||
@ -147,10 +149,107 @@ ModAPI.meta.credits("By ZXMushroom63");
|
|||||||
}
|
}
|
||||||
return originalFileExists.apply(this, args);
|
return originalFileExists.apply(this, args);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const L10NRead = ModAPI.util.getMethodFromPackage("net.minecraft.util.StatCollector", "translateToLocal");
|
||||||
|
const originalL10NRead = ModAPI.hooks.methods[L10NRead];
|
||||||
|
ModAPI.hooks.methods[L10NRead] = function (...args) {
|
||||||
|
var key = ModAPI.util.ustr(args[0]);
|
||||||
|
if (AsyncSink.L10N.has(key)) {
|
||||||
|
return ModAPI.util.str(AsyncSink.L10N.get(key));
|
||||||
|
}
|
||||||
|
return originalL10NRead.apply(this, args);
|
||||||
|
};
|
||||||
|
|
||||||
|
const L10NCheck = ModAPI.util.getMethodFromPackage("net.minecraft.util.StatCollector", "canTranslate");
|
||||||
|
const originalL10NCheck = ModAPI.hooks.methods[L10NRead];
|
||||||
|
ModAPI.hooks.methods[L10NCheck] = function (...args) {
|
||||||
|
if (AsyncSink.L10N.has(ModAPI.util.ustr(args[0]))) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return originalL10NCheck.apply(this, args);
|
||||||
|
};
|
||||||
|
|
||||||
globalThis.AsyncSink = AsyncSink;
|
globalThis.AsyncSink = AsyncSink;
|
||||||
|
ModAPI.events.newEvent("lib:asyncsink");
|
||||||
ModAPI.events.callEvent("lib:asyncsink", {});
|
ModAPI.events.callEvent("lib:asyncsink", {});
|
||||||
console.log("[AsyncSink] Loaded!");
|
console.log("[AsyncSink] Loaded!");
|
||||||
}
|
}
|
||||||
runtimeComponent();
|
runtimeComponent();
|
||||||
ModAPI.dedicatedServer.appendCode(runtimeComponent);
|
ModAPI.dedicatedServer.appendCode(runtimeComponent);
|
||||||
|
|
||||||
|
|
||||||
|
async function assureAsyncSinkResources() {
|
||||||
|
const dec = new TextDecoder("utf-8");
|
||||||
|
const enc = new TextEncoder("utf-8");
|
||||||
|
var resourcePackKey = (await indexedDB.databases()).find(x => x?.name?.endsWith("_resourcePacks")).name;
|
||||||
|
const dbRequest = indexedDB.open(resourcePackKey);
|
||||||
|
const db = await promisifyIDBRequest(dbRequest);
|
||||||
|
const transaction = db.transaction(["filesystem"], "readonly");
|
||||||
|
const objectStore = transaction.objectStore("filesystem");
|
||||||
|
var object = (await promisifyIDBRequest(objectStore.get(["resourcepacks/manifest.json"])))?.data;
|
||||||
|
var resourcePackList = object ? JSON.parse(dec.decode(object)) : { resourcePacks: [] };
|
||||||
|
if (!resourcePackList.resourcePacks.find(x => x.name === "AsyncSinkLib")) {
|
||||||
|
resourcePackList.resourcePacks.push({
|
||||||
|
domains: ["minecraft"],
|
||||||
|
folder: "AsyncSinkLib",
|
||||||
|
name: "AsyncSinkLib",
|
||||||
|
timestamp: Date.now()
|
||||||
|
});
|
||||||
|
const writeableTransaction = db.transaction(["filesystem"], "readwrite");
|
||||||
|
const writeableObjectStore = writeableTransaction.objectStore("filesystem");
|
||||||
|
await promisifyIDBRequest(writeableObjectStore.put({
|
||||||
|
path: "resourcepacks/manifest.json",
|
||||||
|
data: enc.encode(JSON.stringify(resourcePackList)).buffer
|
||||||
|
}));
|
||||||
|
await promisifyIDBRequest(writeableObjectStore.put({
|
||||||
|
path: "resourcepacks/AsyncSinkLib/pack.mcmeta",
|
||||||
|
data: enc.encode(JSON.stringify({
|
||||||
|
"pack": {
|
||||||
|
"pack_format": 1,
|
||||||
|
"description": "AsyncSink Library Resources"
|
||||||
|
}
|
||||||
|
})).buffer
|
||||||
|
}));
|
||||||
|
|
||||||
|
var icon = {
|
||||||
|
path: "resourcepacks/AsyncSinkLib/pack.png",
|
||||||
|
data: await (await fetch(asyncSinkIcon)).arrayBuffer()
|
||||||
|
};
|
||||||
|
|
||||||
|
const imageTransaction = db.transaction(["filesystem"], "readwrite");
|
||||||
|
const imageObjectStore = imageTransaction.objectStore("filesystem");
|
||||||
|
|
||||||
|
await promisifyIDBRequest(imageObjectStore.put(icon));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client side reminders to enable the AsyncSink Resource Pack
|
||||||
|
var asyncSinkInstallStatus = false;
|
||||||
|
var installMessage = document.createElement("span");
|
||||||
|
installMessage.innerText = "Please enable the AsyncSink resource pack\nIn game, use the .reload_tex command to load textures for modded blocks and items.";
|
||||||
|
installMessage.style = "background-color: rgba(0,0,0,0.7); color: red; position: fixed; top: 0; left: 0; font-family: sans-serif; pointer-events: none; user-select: none;";
|
||||||
|
document.body.appendChild(installMessage);
|
||||||
|
|
||||||
|
assureAsyncSinkResources();
|
||||||
|
setInterval(() => {
|
||||||
|
var resourcePackEntries = ModAPI.mc.mcResourcePackRepository.getRepositoryEntries().getCorrective();
|
||||||
|
var array = resourcePackEntries.array || [resourcePackEntries.element];
|
||||||
|
asyncSinkInstallStatus = array.find(x => ModAPI.util.ustr(x.reResourcePack.resourcePackFile.getRef()) === "AsyncSinkLib") ? true : false;
|
||||||
|
assureAsyncSinkResources();
|
||||||
|
if (asyncSinkInstallStatus) {
|
||||||
|
installMessage.style.display = "none";
|
||||||
|
} else {
|
||||||
|
installMessage.style.display = "initial";
|
||||||
|
}
|
||||||
|
}, 8000);
|
||||||
|
ModAPI.events.newEvent("custom:asyncsink_reloaded");
|
||||||
|
ModAPI.addEventListener("sendchatmessage", (e) => {
|
||||||
|
if (e.message.toLowerCase().startsWith(".reload_tex")) {
|
||||||
|
e.preventDefault = true;
|
||||||
|
ModAPI.mc.renderItem.itemModelMesher.simpleShapesCache.clear();
|
||||||
|
ModAPI.promisify(ModAPI.mc.refreshResources)().then(()=>{
|
||||||
|
ModAPI.events.callEvent("custom:asyncsink_reloaded", {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
})();
|
})();
|
127
examplemods/block_of_steve_advanced.js
Normal file
127
examplemods/block_of_steve_advanced.js
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
//THIS IS A DEMO MOD
|
||||||
|
|
||||||
|
|
||||||
|
//nice little utility function to fix the block identity map
|
||||||
|
function fixupBlockIds() {
|
||||||
|
var blockRegistry = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.blockRegistry).getCorrective();
|
||||||
|
var BLOCK_STATE_IDS = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.BLOCK_STATE_IDS).getCorrective();
|
||||||
|
blockRegistry.registryObjects.hashTableKToV.forEach(entry => {
|
||||||
|
if (entry) {
|
||||||
|
var block = entry.value;
|
||||||
|
var validStates = block.getBlockState().getValidStates();
|
||||||
|
var stateArray = validStates.array || [validStates.element];
|
||||||
|
stateArray.forEach(iblockstate => {
|
||||||
|
var i = blockRegistry.getIDForObject(block.getRef()) << 4 | block.getMetaFromState(iblockstate.getRef());
|
||||||
|
BLOCK_STATE_IDS.put(iblockstate.getRef(), i);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function makeSteveBlock() {
|
||||||
|
var blockClass = ModAPI.reflect.getClassById("net.minecraft.block.Block");
|
||||||
|
var iproperty = ModAPI.reflect.getClassById("net.minecraft.block.properties.IProperty").class;
|
||||||
|
var makeBlockState = ModAPI.reflect.getClassById("net.minecraft.block.state.BlockState").constructors.find(x => x.length === 2);
|
||||||
|
var blockSuper = ModAPI.reflect.getSuper(blockClass, (x) => x.length === 2);
|
||||||
|
var creativeBlockTab = ModAPI.reflect.getClassById("net.minecraft.creativetab.CreativeTabs").staticVariables.tabBlock;
|
||||||
|
var nmb_BlockSteve = function nmb_BlockSteve() {
|
||||||
|
blockSuper(this, ModAPI.materials.rock.getRef());
|
||||||
|
this.$defaultBlockState = this.$blockState.$getBaseState();
|
||||||
|
this.$setCreativeTab(creativeBlockTab);
|
||||||
|
}
|
||||||
|
ModAPI.reflect.prototypeStack(blockClass, nmb_BlockSteve);
|
||||||
|
nmb_BlockSteve.prototype.$isOpaqueCube = function () {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
nmb_BlockSteve.prototype.$createBlockState = function (t) {
|
||||||
|
return makeBlockState(this, ModAPI.array.object(iproperty, 0));
|
||||||
|
}
|
||||||
|
globalThis.nmb_BlockSteve = nmb_BlockSteve;
|
||||||
|
}
|
||||||
|
function registerSteveClientSide() {
|
||||||
|
var itemClass = ModAPI.reflect.getClassById("net.minecraft.item.Item");
|
||||||
|
var blockClass = ModAPI.reflect.getClassById("net.minecraft.block.Block");
|
||||||
|
var block_of_steve = (new nmb_BlockSteve()).$setHardness(-1.0).$setStepSound(blockClass.staticVariables.soundTypeGravel).$setUnlocalizedName(
|
||||||
|
ModAPI.util.str("steve")
|
||||||
|
);
|
||||||
|
blockClass.staticMethods.registerBlock0.method(
|
||||||
|
198, //use blockid 198
|
||||||
|
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"));
|
||||||
|
});
|
||||||
|
AsyncSink.L10N.set("tile.steve.name", "Block Of Steve");
|
||||||
|
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/models/block/steve.json", JSON.stringify(
|
||||||
|
{
|
||||||
|
"parent": "block/cube_all",
|
||||||
|
"textures": {
|
||||||
|
"all": "blocks/steve"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/models/item/steve.json", JSON.stringify(
|
||||||
|
{
|
||||||
|
"parent": "block/steve",
|
||||||
|
"display": {
|
||||||
|
"thirdperson": {
|
||||||
|
"rotation": [10, -45, 170],
|
||||||
|
"translation": [0, 1.5, -2.75],
|
||||||
|
"scale": [0.375, 0.375, 0.375]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/blockstates/steve.json", JSON.stringify(
|
||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"normal": [
|
||||||
|
{ "model": "steve" },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/textures/blocks/steve.png", await (await fetch(
|
||||||
|
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE0SURBVDhPpdO9S8NAHMbxy3sVfJmMg6h7FRXXkkUUX0addSjo4OAfIDqLIoiLi3+BRRx0EIQOnV0EcVAIWkR0KIFgrcEktX6vcXD0nuE+5Afhnhw5bWy4qylaidOfVQhT0zFKYozjBHVdzi3TwCZvteaS/0fLD8oGf5OzTeyxNUyE3Ln2HmGctpuxKuS3wd76CgPHsrEj142NeojCkHsFry+4c3aJ6g1OtlZp0Ok4DD4i+Y2GIZ+DMMAhtw+fHu8xi3IDM9t5YfMQF71dLHo+ZjsfXbh4WtnH0vYaqp/BcXGGM3D7BxiYTi+el8uYZWm2gM/VB/Tfaqje4GB5iga2Jv+sUuUa5/ITmOXq7gbnC+MY1r9QvcHG9AgN0lRex1u/ilr7ehqWvBNZvMlRbESfqNhAiG/Pb1bHXpMbFgAAAABJRU5ErkJggg=="
|
||||||
|
)).arrayBuffer());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function registerSteveServerSide() {
|
||||||
|
function fixupBlockIds() {
|
||||||
|
var blockRegistry = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.blockRegistry).getCorrective();
|
||||||
|
var BLOCK_STATE_IDS = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.BLOCK_STATE_IDS).getCorrective();
|
||||||
|
blockRegistry.registryObjects.hashTableKToV.forEach(entry => {
|
||||||
|
if (entry) {
|
||||||
|
var block = entry.value;
|
||||||
|
var validStates = block.getBlockState().getValidStates();
|
||||||
|
var stateArray = validStates.array || [validStates.element];
|
||||||
|
stateArray.forEach(iblockstate => {
|
||||||
|
var i = blockRegistry.getIDForObject(block.getRef()) << 4 | block.getMetaFromState(iblockstate.getRef());
|
||||||
|
BLOCK_STATE_IDS.put(iblockstate.getRef(), i);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var blockClass = ModAPI.reflect.getClassById("net.minecraft.block.Block");
|
||||||
|
var itemClass = ModAPI.reflect.getClassById("net.minecraft.item.Item");
|
||||||
|
ModAPI.addEventListener("bootstrap", () => {
|
||||||
|
var block_of_steve = (new nmb_BlockSteve()).$setHardness(-1.0).$setStepSound(blockClass.staticVariables.soundTypeGravel).$setUnlocalizedName(
|
||||||
|
ModAPI.util.str("steve")
|
||||||
|
);
|
||||||
|
blockClass.staticMethods.registerBlock0.method(
|
||||||
|
198,
|
||||||
|
ModAPI.util.str("steve"),
|
||||||
|
block_of_steve
|
||||||
|
);
|
||||||
|
itemClass.staticMethods.registerItemBlock0.method(block_of_steve);
|
||||||
|
fixupBlockIds();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ModAPI.dedicatedServer.appendCode(makeSteveBlock);
|
||||||
|
makeSteveBlock();
|
||||||
|
registerSteveClientSide();
|
||||||
|
fixupBlockIds();
|
||||||
|
ModAPI.dedicatedServer.appendCode(registerSteveServerSide);
|
111
examplemods/block_of_steve_simple.js
Normal file
111
examplemods/block_of_steve_simple.js
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
//THIS IS A DEMO MOD
|
||||||
|
|
||||||
|
|
||||||
|
//nice little utility function to fix the block identity map
|
||||||
|
function fixupBlockIds() {
|
||||||
|
var blockRegistry = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.blockRegistry).getCorrective();
|
||||||
|
var BLOCK_STATE_IDS = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.BLOCK_STATE_IDS).getCorrective();
|
||||||
|
blockRegistry.registryObjects.hashTableKToV.forEach(entry => {
|
||||||
|
if (entry) {
|
||||||
|
var block = entry.value;
|
||||||
|
var validStates = block.getBlockState().getValidStates();
|
||||||
|
var stateArray = validStates.array || [validStates.element];
|
||||||
|
stateArray.forEach(iblockstate => {
|
||||||
|
var i = blockRegistry.getIDForObject(block.getRef()) << 4 | block.getMetaFromState(iblockstate.getRef());
|
||||||
|
BLOCK_STATE_IDS.put(iblockstate.getRef(), i);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function registerSteveClientSide() {
|
||||||
|
var creativeBlockTab = ModAPI.reflect.getClassById("net.minecraft.creativetab.CreativeTabs").staticVariables.tabBlock;
|
||||||
|
var itemClass = ModAPI.reflect.getClassById("net.minecraft.item.Item");
|
||||||
|
var blockClass = ModAPI.reflect.getClassById("net.minecraft.block.Block");
|
||||||
|
var constructor = blockClass.constructors.find(x=>x.length === 1);
|
||||||
|
var block_of_steve = constructor(ModAPI.materials.rock.getRef()).$setHardness(-1.0).$setStepSound(blockClass.staticVariables.soundTypeGravel).$setUnlocalizedName(
|
||||||
|
ModAPI.util.str("steve")
|
||||||
|
).$setCreativeTab(creativeBlockTab);
|
||||||
|
blockClass.staticMethods.registerBlock0.method(
|
||||||
|
198, //use blockid 198
|
||||||
|
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"));
|
||||||
|
});
|
||||||
|
AsyncSink.L10N.set("tile.steve.name", "Block Of Steve");
|
||||||
|
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/models/block/steve.json", JSON.stringify(
|
||||||
|
{
|
||||||
|
"parent": "block/cube_all",
|
||||||
|
"textures": {
|
||||||
|
"all": "blocks/steve"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/models/item/steve.json", JSON.stringify(
|
||||||
|
{
|
||||||
|
"parent": "block/steve",
|
||||||
|
"display": {
|
||||||
|
"thirdperson": {
|
||||||
|
"rotation": [10, -45, 170],
|
||||||
|
"translation": [0, 1.5, -2.75],
|
||||||
|
"scale": [0.375, 0.375, 0.375]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/blockstates/steve.json", JSON.stringify(
|
||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"normal": [
|
||||||
|
{ "model": "steve" },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/textures/blocks/steve.png", await (await fetch(
|
||||||
|
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE0SURBVDhPpdO9S8NAHMbxy3sVfJmMg6h7FRXXkkUUX0addSjo4OAfIDqLIoiLi3+BRRx0EIQOnV0EcVAIWkR0KIFgrcEktX6vcXD0nuE+5Afhnhw5bWy4qylaidOfVQhT0zFKYozjBHVdzi3TwCZvteaS/0fLD8oGf5OzTeyxNUyE3Ln2HmGctpuxKuS3wd76CgPHsrEj142NeojCkHsFry+4c3aJ6g1OtlZp0Ok4DD4i+Y2GIZ+DMMAhtw+fHu8xi3IDM9t5YfMQF71dLHo+ZjsfXbh4WtnH0vYaqp/BcXGGM3D7BxiYTi+el8uYZWm2gM/VB/Tfaqje4GB5iga2Jv+sUuUa5/ITmOXq7gbnC+MY1r9QvcHG9AgN0lRex1u/ilr7ehqWvBNZvMlRbESfqNhAiG/Pb1bHXpMbFgAAAABJRU5ErkJggg=="
|
||||||
|
)).arrayBuffer());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function registerSteveServerSide() {
|
||||||
|
function fixupBlockIds() {
|
||||||
|
var blockRegistry = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.blockRegistry).getCorrective();
|
||||||
|
var BLOCK_STATE_IDS = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.BLOCK_STATE_IDS).getCorrective();
|
||||||
|
blockRegistry.registryObjects.hashTableKToV.forEach(entry => {
|
||||||
|
if (entry) {
|
||||||
|
var block = entry.value;
|
||||||
|
var validStates = block.getBlockState().getValidStates();
|
||||||
|
var stateArray = validStates.array || [validStates.element];
|
||||||
|
stateArray.forEach(iblockstate => {
|
||||||
|
var i = blockRegistry.getIDForObject(block.getRef()) << 4 | block.getMetaFromState(iblockstate.getRef());
|
||||||
|
BLOCK_STATE_IDS.put(iblockstate.getRef(), i);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var creativeBlockTab = ModAPI.reflect.getClassById("net.minecraft.creativetab.CreativeTabs").staticVariables.tabBlock;
|
||||||
|
var blockClass = ModAPI.reflect.getClassById("net.minecraft.block.Block");
|
||||||
|
var itemClass = ModAPI.reflect.getClassById("net.minecraft.item.Item");
|
||||||
|
var constructor = blockClass.constructors.find(x=>x.length === 1);
|
||||||
|
ModAPI.addEventListener("bootstrap", () => {
|
||||||
|
var block_of_steve = constructor(ModAPI.materials.rock.getRef()).$setHardness(-1.0).$setStepSound(blockClass.staticVariables.soundTypeGravel).$setUnlocalizedName(
|
||||||
|
ModAPI.util.str("steve")
|
||||||
|
).$setCreativeTab(creativeBlockTab);
|
||||||
|
blockClass.staticMethods.registerBlock0.method(
|
||||||
|
198,
|
||||||
|
ModAPI.util.str("steve"),
|
||||||
|
block_of_steve
|
||||||
|
);
|
||||||
|
itemClass.staticMethods.registerItemBlock0.method(block_of_steve);
|
||||||
|
fixupBlockIds();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
registerSteveClientSide();
|
||||||
|
fixupBlockIds();
|
||||||
|
ModAPI.dedicatedServer.appendCode(registerSteveServerSide);
|
@ -92,7 +92,7 @@ function button_utility_script(inputArr, bindingClass, actionBindMode) {
|
|||||||
{
|
{
|
||||||
text: "Server Close",
|
text: "Server Close",
|
||||||
click: () => {
|
click: () => {
|
||||||
var CloseWindow = ModAPI.reflect.getClassByName("C0DPacketCloseWindow").constructors.find(x => x.length === 1);
|
var CloseWindow = ModAPI.reflect.getClassByName("C0DPacketCloseWindow").constructors[0];
|
||||||
ModAPI.player.sendQueue.addToSendQueue(CloseWindow(ModAPI.player.openContainer.getCorrective().windowId));
|
ModAPI.player.sendQueue.addToSendQueue(CloseWindow(ModAPI.player.openContainer.getCorrective().windowId));
|
||||||
},
|
},
|
||||||
x: 0,
|
x: 0,
|
||||||
|
134
examplemods/unlucky_blocks.js
Normal file
134
examplemods/unlucky_blocks.js
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
(()=>{
|
||||||
|
const unluckyBlockTexture = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAOhJREFUOE9jnJn2/z8DGvj4koHh9UOIoKg8AwO/OLoKBJ8RZED6LEbcKvDIzEz7z8DY5f//f9lGTANCGTAcxrCaAVUd2IBSg///uy+gSqBr/sJwF+6O7QwqcHaXPxYXgDTDNCArtmXYBtZ4mMELbkCpwX8GjDDwZLjD8IXhFopCkA5s4mAXEBOIMC+BXIbsKnAYEDIAOTywBiI+A0DO5mFQBvsZXTNIjKALQAHHw6CG4mzkZIE3HYAUEjIAHIjY0gGxyRIcjfgMgIUBNv+DLAEbgCspgxTAYgCXAUSnA1xegscCPj8TytoAA5eEOx9BbCgAAAAASUVORK5CYII=";
|
||||||
|
ModAPI.meta.title("Unlucky Blocks");
|
||||||
|
ModAPI.meta.version("v1.0");
|
||||||
|
ModAPI.meta.description("These purple cubes ruined my life. Requires AsyncSink.");
|
||||||
|
ModAPI.meta.credits("By ZXMushroom63");
|
||||||
|
ModAPI.meta.icon(unluckyBlockTexture);
|
||||||
|
|
||||||
|
function UnluckyBlocks() {
|
||||||
|
function fixupBlockIds() {
|
||||||
|
var blockRegistry = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.blockRegistry).getCorrective();
|
||||||
|
var BLOCK_STATE_IDS = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.BLOCK_STATE_IDS).getCorrective();
|
||||||
|
blockRegistry.registryObjects.hashTableKToV.forEach(entry => {
|
||||||
|
if (entry) {
|
||||||
|
var block = entry.value;
|
||||||
|
var validStates = block.getBlockState().getValidStates();
|
||||||
|
var stateArray = validStates.array || [validStates.element];
|
||||||
|
stateArray.forEach(iblockstate => {
|
||||||
|
var i = blockRegistry.getIDForObject(block.getRef()) << 4 | block.getMetaFromState(iblockstate.getRef());
|
||||||
|
BLOCK_STATE_IDS.put(iblockstate.getRef(), i);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var itemClass = ModAPI.reflect.getClassById("net.minecraft.item.Item");
|
||||||
|
var blockClass = ModAPI.reflect.getClassById("net.minecraft.block.Block");
|
||||||
|
var iproperty = ModAPI.reflect.getClassById("net.minecraft.block.properties.IProperty").class;
|
||||||
|
var makeBlockState = ModAPI.reflect.getClassById("net.minecraft.block.state.BlockState").constructors.find(x => x.length === 2);
|
||||||
|
var blockSuper = ModAPI.reflect.getSuper(blockClass, (x) => x.length === 2); //Get super function from the block class with a target length of two. ($this (mandatory), material (optional))
|
||||||
|
var creativeBlockTab = ModAPI.reflect.getClassById("net.minecraft.creativetab.CreativeTabs").staticVariables.tabBlock;
|
||||||
|
var breakBlockMethod = blockClass.methods.breakBlock.method;
|
||||||
|
var nmb_BlockUnlucky = function nmb_BlockUnlucky() {
|
||||||
|
blockSuper(this, ModAPI.materials.rock.getRef()); //Use super function to get block properties on this class.
|
||||||
|
this.$defaultBlockState = this.$blockState.$getBaseState();
|
||||||
|
this.$setCreativeTab(creativeBlockTab);
|
||||||
|
}
|
||||||
|
ModAPI.reflect.prototypeStack(blockClass, nmb_BlockUnlucky);
|
||||||
|
nmb_BlockUnlucky.prototype.$isOpaqueCube = function () {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
nmb_BlockUnlucky.prototype.$createBlockState = function () {
|
||||||
|
return makeBlockState(this, ModAPI.array.object(iproperty, 0));
|
||||||
|
}
|
||||||
|
nmb_BlockUnlucky.prototype.$breakBlock = function ($world, $blockpos, $blockstate) {
|
||||||
|
var world = ModAPI.util.wrap($world);
|
||||||
|
var blockpos = ModAPI.util.wrap($blockpos);
|
||||||
|
if (Math.random() < 1) { //was gonna add random events but couldn't be bothered. Enjoy exploding!
|
||||||
|
world.newExplosion(null, blockpos.getX() + 0.5, blockpos.getY() + 0.5,
|
||||||
|
blockpos.getZ() + 0.5, 9, 1, 1);
|
||||||
|
}
|
||||||
|
return breakBlockMethod(this, $world, $blockpos, $blockstate);
|
||||||
|
}
|
||||||
|
|
||||||
|
function internal_reg() {
|
||||||
|
var block_of_unluckiness = (new nmb_BlockUnlucky()).$setHardness(0.0).$setStepSound(blockClass.staticVariables.soundTypePiston).$setUnlocalizedName(
|
||||||
|
ModAPI.util.str("unluckiness")
|
||||||
|
);
|
||||||
|
blockClass.staticMethods.registerBlock0.method(
|
||||||
|
544,
|
||||||
|
ModAPI.util.str("unluckiness"),
|
||||||
|
block_of_unluckiness
|
||||||
|
);
|
||||||
|
itemClass.staticMethods.registerItemBlock0.method(block_of_unluckiness);
|
||||||
|
fixupBlockIds();
|
||||||
|
ModAPI.blocks["unluckiness"] = block_of_unluckiness;
|
||||||
|
|
||||||
|
return block_of_unluckiness;
|
||||||
|
}
|
||||||
|
|
||||||
|
const WorldGenMineable = ModAPI.reflect.getClassById("net.minecraft.world.gen.feature.WorldGenMinable").constructors.find(x=>x.length===2);
|
||||||
|
|
||||||
|
const BiomeDecorator_decorate = ModAPI.util.getMethodFromPackage("net.minecraft.world.biome.BiomeDecorator", "decorate");
|
||||||
|
const oldDecorate = ModAPI.hooks.methods[BiomeDecorator_decorate];
|
||||||
|
ModAPI.hooks.methods[BiomeDecorator_decorate] = function ($this, $world, $random, $biomeGenBase, $blockpos) {
|
||||||
|
if (!$this.$currentWorld) {
|
||||||
|
$this.$unluckyBlockGen = WorldGenMineable(ModAPI.blocks.unluckiness.getDefaultState().getRef(), 4);
|
||||||
|
}
|
||||||
|
return oldDecorate.apply(this, [$this, $world, $random, $biomeGenBase, $blockpos]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const BiomeDecorator_generateOres = ModAPI.util.getMethodFromPackage("net.minecraft.world.biome.BiomeDecorator", "generateOres");
|
||||||
|
const oldGenerateOres = ModAPI.hooks.methods[BiomeDecorator_generateOres];
|
||||||
|
ModAPI.hooks.methods[BiomeDecorator_generateOres] = function ($this) {
|
||||||
|
$this.$genStandardOre1(105, $this.$unluckyBlockGen || null, 0, 256);
|
||||||
|
return oldGenerateOres.apply(this, [$this]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ModAPI.materials) {
|
||||||
|
return internal_reg();
|
||||||
|
} else {
|
||||||
|
ModAPI.addEventListener("bootstrap", internal_reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ModAPI.dedicatedServer.appendCode(UnluckyBlocks);
|
||||||
|
var block_of_unluckiness = UnluckyBlocks();
|
||||||
|
ModAPI.addEventListener("lib:asyncsink", async () => {
|
||||||
|
ModAPI.addEventListener("custom:asyncsink_reloaded", ()=>{
|
||||||
|
ModAPI.mc.renderItem.registerBlock(block_of_unluckiness, ModAPI.util.str("unluckiness"));
|
||||||
|
});
|
||||||
|
AsyncSink.L10N.set("tile.unluckiness.name", "Unlucky Block");
|
||||||
|
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/models/block/unluckiness.json", JSON.stringify(
|
||||||
|
{
|
||||||
|
"parent": "block/cube_all",
|
||||||
|
"textures": {
|
||||||
|
"all": "blocks/unluckiness"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/models/item/unluckiness.json", JSON.stringify(
|
||||||
|
{
|
||||||
|
"parent": "block/unluckiness",
|
||||||
|
"display": {
|
||||||
|
"thirdperson": {
|
||||||
|
"rotation": [10, -45, 170],
|
||||||
|
"translation": [0, 1.5, -2.75],
|
||||||
|
"scale": [0.375, 0.375, 0.375]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/blockstates/unluckiness.json", JSON.stringify(
|
||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"normal": [
|
||||||
|
{ "model": "unluckiness" },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/textures/blocks/unluckiness.png", await (await fetch(
|
||||||
|
unluckyBlockTexture
|
||||||
|
)).arrayBuffer());
|
||||||
|
});
|
||||||
|
})();
|
@ -167,6 +167,7 @@
|
|||||||
ModAPI.hooks._rippedData ||= [];
|
ModAPI.hooks._rippedData ||= [];
|
||||||
ModAPI.hooks._teavm ||= {};
|
ModAPI.hooks._teavm ||= {};
|
||||||
ModAPI.hooks._rippedConstructors ||= {};
|
ModAPI.hooks._rippedConstructors ||= {};
|
||||||
|
ModAPI.hooks._rippedInternalConstructors ||= {};
|
||||||
ModAPI.hooks.methods ||= {};
|
ModAPI.hooks.methods ||= {};
|
||||||
ModAPI.hooks._rippedMethodTypeMap ||= {};
|
ModAPI.hooks._rippedMethodTypeMap ||= {};
|
||||||
ModAPI.hooks._postInit ||= ()=>{};
|
ModAPI.hooks._postInit ||= ()=>{};
|
||||||
|
35
injector.js
35
injector.js
@ -9,6 +9,12 @@ function _status(x) {
|
|||||||
document.querySelector("#status").innerText = x;
|
document.querySelector("#status").innerText = x;
|
||||||
}
|
}
|
||||||
function entriesToStaticVariableProxy(entries, prefix) {
|
function entriesToStaticVariableProxy(entries, prefix) {
|
||||||
|
if (entries.length === 0) {
|
||||||
|
return `ModAPI.hooks._rippedStaticProperties[\`${prefix.replace(
|
||||||
|
"var ",
|
||||||
|
""
|
||||||
|
)}\`]={};`;
|
||||||
|
}
|
||||||
var getComponents = "";
|
var getComponents = "";
|
||||||
entries.forEach((entry) => {
|
entries.forEach((entry) => {
|
||||||
getComponents += `
|
getComponents += `
|
||||||
@ -16,6 +22,9 @@ function entriesToStaticVariableProxy(entries, prefix) {
|
|||||||
return ${entry.variable};
|
return ${entry.variable};
|
||||||
break;`;
|
break;`;
|
||||||
});
|
});
|
||||||
|
getComponents += `
|
||||||
|
default:
|
||||||
|
return Reflect.get(a,b,c);`
|
||||||
|
|
||||||
var setComponents = "";
|
var setComponents = "";
|
||||||
entries.forEach((entry) => {
|
entries.forEach((entry) => {
|
||||||
@ -24,7 +33,11 @@ function entriesToStaticVariableProxy(entries, prefix) {
|
|||||||
${entry.variable} = c;
|
${entry.variable} = c;
|
||||||
break;`;
|
break;`;
|
||||||
});
|
});
|
||||||
var proxy = `
|
setComponents += `
|
||||||
|
default:
|
||||||
|
a[b]=c;`
|
||||||
|
/*/
|
||||||
|
|
||||||
ModAPI.hooks._rippedStaticIndexer[\`${prefix.replace(
|
ModAPI.hooks._rippedStaticIndexer[\`${prefix.replace(
|
||||||
"var ",
|
"var ",
|
||||||
""
|
""
|
||||||
@ -33,7 +46,8 @@ function entriesToStaticVariableProxy(entries, prefix) {
|
|||||||
return '"' + x.name + '"';
|
return '"' + x.name + '"';
|
||||||
})
|
})
|
||||||
.join(",")}];
|
.join(",")}];
|
||||||
ModAPI.hooks._rippedStaticProperties[\`${prefix.replace(
|
/*/
|
||||||
|
var proxy = `ModAPI.hooks._rippedStaticProperties[\`${prefix.replace(
|
||||||
"var ",
|
"var ",
|
||||||
""
|
""
|
||||||
)}\`] = new Proxy({${entries
|
)}\`] = new Proxy({${entries
|
||||||
@ -51,6 +65,7 @@ function entriesToStaticVariableProxy(entries, prefix) {
|
|||||||
switch (b) {
|
switch (b) {
|
||||||
${setComponents}
|
${setComponents}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
});`;
|
});`;
|
||||||
return proxy;
|
return proxy;
|
||||||
@ -137,6 +152,20 @@ var main;(function(){`
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const extractInternalConstructorRegex =
|
||||||
|
/^\s*function (\S*?)__init_\d*?\(\$this/gm; //same as extract constructor regex, but only allow $this as first argument
|
||||||
|
patchedFile = patchedFile.replaceAll(
|
||||||
|
extractInternalConstructorRegex,
|
||||||
|
(match) => {
|
||||||
|
var fullName = match.match(extractConstructorFullNameRegex);
|
||||||
|
fullName = fullName[0].replace("function ", "");
|
||||||
|
return (
|
||||||
|
`ModAPI.hooks._rippedInternalConstructors[\`${fullName}\`] = ${fullName};
|
||||||
|
` + match
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if(globalThis.optimizePi){
|
if(globalThis.optimizePi){
|
||||||
patchedFile = patchedFile.replaceAll(
|
patchedFile = patchedFile.replaceAll(
|
||||||
"3.1415927410125732 / 180.0",
|
"3.1415927410125732 / 180.0",
|
||||||
@ -224,7 +253,7 @@ var main;(function(){`
|
|||||||
|
|
||||||
|
|
||||||
patchedFile = patchedFile.replaceAll(
|
patchedFile = patchedFile.replaceAll(
|
||||||
/function [a-z]+?_([a-zA-Z\$]+?)\(\) \{/gm,
|
/function [a-z]+?_([a-zA-Z0-9\$]+?)\(\) \{/gm,
|
||||||
(match) => {
|
(match) => {
|
||||||
var prefix = "var " + match.replace("function ", "").replace("() {", "");
|
var prefix = "var " + match.replace("function ", "").replace("() {", "");
|
||||||
var entries = [];
|
var entries = [];
|
||||||
|
@ -35,4 +35,4 @@ PatchesRegistry.addPatch(function (input) {
|
|||||||
if (!$this.$renderHand)`
|
if (!$this.$renderHand)`
|
||||||
);
|
);
|
||||||
return output;
|
return output;
|
||||||
})
|
});
|
60
postinit.js
60
postinit.js
@ -22,7 +22,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
ModAPI.meta._versionMap = {};
|
ModAPI.meta._versionMap = {};
|
||||||
ModAPI.array = {};
|
ModAPI.array = {};
|
||||||
|
|
||||||
ModAPI.version = "v2.1.2";
|
ModAPI.version = "v2.2";
|
||||||
ModAPI.flavour = "injector";
|
ModAPI.flavour = "injector";
|
||||||
ModAPI.GNU = "terry pratchett";
|
ModAPI.GNU = "terry pratchett";
|
||||||
ModAPI.credits = ["ZXMushroom63", "radmanplays", "Murturtle", "OtterCodes101", "TheIdiotPlays", "OeildeLynx31", "Stpv22"];
|
ModAPI.credits = ["ZXMushroom63", "radmanplays", "Murturtle", "OtterCodes101", "TheIdiotPlays", "OeildeLynx31", "Stpv22"];
|
||||||
@ -149,7 +149,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
}
|
}
|
||||||
if (xOut && typeof xOut === "object" && !Array.isArray(xOut)) {
|
if (xOut && typeof xOut === "object" && !Array.isArray(xOut)) {
|
||||||
if (corrective) {
|
if (corrective) {
|
||||||
return new Proxy(outputValue.data, CorrectiveRecursive);
|
return new Proxy(xOut, CorrectiveRecursive);
|
||||||
}
|
}
|
||||||
return new Proxy(xOut, ModAPI.util.TeaVM_to_Recursive_BaseData_ProxyConf);
|
return new Proxy(xOut, ModAPI.util.TeaVM_to_Recursive_BaseData_ProxyConf);
|
||||||
}
|
}
|
||||||
@ -209,6 +209,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
|
|
||||||
ModAPI.hooks.regenerateClassMap = function () {
|
ModAPI.hooks.regenerateClassMap = function () {
|
||||||
ModAPI.hooks._rippedConstructorKeys = Object.keys(ModAPI.hooks._rippedConstructors);
|
ModAPI.hooks._rippedConstructorKeys = Object.keys(ModAPI.hooks._rippedConstructors);
|
||||||
|
ModAPI.hooks._rippedInternalConstructorKeys = Object.keys(ModAPI.hooks._rippedInternalConstructors);
|
||||||
ModAPI.hooks._rippedMethodKeys = Object.keys(ModAPI.hooks._rippedMethodTypeMap);
|
ModAPI.hooks._rippedMethodKeys = Object.keys(ModAPI.hooks._rippedMethodTypeMap);
|
||||||
|
|
||||||
var compiledNames = new Set();
|
var compiledNames = new Set();
|
||||||
@ -255,6 +256,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
"id": classId,
|
"id": classId,
|
||||||
"binaryName": item?.$meta?.binaryName || null,
|
"binaryName": item?.$meta?.binaryName || null,
|
||||||
"constructors": [],
|
"constructors": [],
|
||||||
|
"internalConstructors": [],
|
||||||
"methods": {},
|
"methods": {},
|
||||||
"staticMethods": {},
|
"staticMethods": {},
|
||||||
"staticVariables": {},
|
"staticVariables": {},
|
||||||
@ -268,12 +270,16 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeof item?.$meta?.superclass === "function" && item?.$meta?.superclass?.$meta) {
|
if (typeof item?.$meta?.superclass === "function" && item?.$meta?.superclass?.$meta) {
|
||||||
ModAPI.hooks._classMap[compiledName].superclass = item.$meta.superclass.$meta.name;
|
ModAPI.hooks._classMap[compiledName].superclassName = item.$meta.superclass.$meta.name;
|
||||||
|
ModAPI.hooks._classMap[compiledName].superclass = item.$meta.superclass;
|
||||||
} else {
|
} else {
|
||||||
ModAPI.hooks._classMap[compiledName].superclass = null;
|
ModAPI.hooks._classMap[compiledName].superclass = null;
|
||||||
|
ModAPI.hooks._classMap[compiledName].superclassName = null;
|
||||||
}
|
}
|
||||||
ModAPI.hooks._classMap[compiledName].staticVariableNames = ModAPI.hooks._rippedStaticIndexer[compiledName];
|
|
||||||
ModAPI.hooks._classMap[compiledName].staticVariables = ModAPI.hooks._rippedStaticProperties[compiledName];
|
ModAPI.hooks._classMap[compiledName].staticVariables = ModAPI.hooks._rippedStaticProperties[compiledName];
|
||||||
|
ModAPI.hooks._classMap[compiledName].staticVariableNames = Object.keys(ModAPI.hooks._classMap[compiledName].staticVariables || {});
|
||||||
|
|
||||||
if (item?.["$$constructor$$"]) {
|
if (item?.["$$constructor$$"]) {
|
||||||
//Class does not have any hand written constructors
|
//Class does not have any hand written constructors
|
||||||
//Eg: class MyClass {}
|
//Eg: class MyClass {}
|
||||||
@ -286,6 +292,13 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModAPI.hooks._rippedInternalConstructorKeys.forEach(initialiser => { // Find internal constructors/initialisers. Used for calling super() on custom classes. (They are the different implementations of a classes constructor, that don't automatically create an object. Thus, it is identical to calling super)
|
||||||
|
if (initialiser.startsWith(compiledName + "__init_") && !initialiser.includes("$lambda$")) {
|
||||||
|
ModAPI.hooks._classMap[compiledName].internalConstructors.push(ModAPI.hooks._rippedInternalConstructors[initialiser]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ModAPI.hooks._rippedMethodKeys.forEach((method) => {
|
ModAPI.hooks._rippedMethodKeys.forEach((method) => {
|
||||||
if (method.startsWith(compiledName + "_") && !method.includes("$lambda$")) {
|
if (method.startsWith(compiledName + "_") && !method.includes("$lambda$")) {
|
||||||
var targetMethodMap = ModAPI.hooks._classMap[compiledName].methods;
|
var targetMethodMap = ModAPI.hooks._classMap[compiledName].methods;
|
||||||
@ -319,6 +332,31 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
var key = classKeys.filter(k => { return ModAPI.hooks._classMap[k].name === className })[0];
|
var key = classKeys.filter(k => { return ModAPI.hooks._classMap[k].name === className })[0];
|
||||||
return key ? ModAPI.hooks._classMap[key] : null;
|
return key ? ModAPI.hooks._classMap[key] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Magical function for making a subclass with a custom constructor that you can easily use super(...) on.
|
||||||
|
ModAPI.reflect.getSuper = function getSuper(reflectClass, filter) {
|
||||||
|
filter ||= ()=>true;
|
||||||
|
var initialiser = reflectClass.internalConstructors.find(filter);
|
||||||
|
return function superFunction(thisArg, ...extra_args) {
|
||||||
|
reflectClass.class.call(thisArg);
|
||||||
|
initialiser(thisArg, ...extra_args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Iteratively load the superclasses' prototype methods.
|
||||||
|
ModAPI.reflect.prototypeStack = function prototypeStack(reflectClass, classFn) {
|
||||||
|
var stack = [reflectClass.class.prototype];
|
||||||
|
var currentSuperclass = reflectClass.superclass;
|
||||||
|
while (currentSuperclass) {
|
||||||
|
stack.push(currentSuperclass.prototype);
|
||||||
|
currentSuperclass = currentSuperclass?.$meta?.superclass;
|
||||||
|
}
|
||||||
|
stack.reverse();
|
||||||
|
stack.forEach(proto => {
|
||||||
|
Object.assign(classFn.prototype, proto);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var reloadDeprecationWarnings = 0;
|
var reloadDeprecationWarnings = 0;
|
||||||
const TeaVMArray_To_Recursive_BaseData_ProxyConf = {
|
const TeaVMArray_To_Recursive_BaseData_ProxyConf = {
|
||||||
get(target, prop, receiver) {
|
get(target, prop, receiver) {
|
||||||
@ -556,7 +594,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
|
|
||||||
//Function used for running @Async / @Async-dependent TeaVM methods.
|
//Function used for running @Async / @Async-dependent TeaVM methods.
|
||||||
ModAPI.promisify = function promisify(fn) {
|
ModAPI.promisify = function promisify(fn) {
|
||||||
return function promisifiedJavaMethpd(...inArguments) {
|
return function promisifiedJavaMethod(...inArguments) {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
Promise.resolve().then( //queue microtask
|
Promise.resolve().then( //queue microtask
|
||||||
() => {
|
() => {
|
||||||
@ -843,13 +881,19 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
const originalBootstrap = ModAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.init.Bootstrap", "register")];
|
ModAPI.util.bootstrap = function () {
|
||||||
ModAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.init.Bootstrap", "register")] = function (...args) {
|
|
||||||
var x = originalBootstrap.apply(this, args);
|
|
||||||
ModAPI.items = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.init.Items")].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.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.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);
|
ModAPI.enchantments = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.enchantment.Enchantment")].staticVariables, StaticProps_ProxyConf);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModAPI.events.newEvent("bootstrap", "server");
|
||||||
|
const originalBootstrap = ModAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.init.Bootstrap", "register")];
|
||||||
|
ModAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.init.Bootstrap", "register")] = function (...args) {
|
||||||
|
var x = originalBootstrap.apply(this, args);
|
||||||
|
ModAPI.util.bootstrap();
|
||||||
|
ModAPI.events.callEvent("bootstrap", {});
|
||||||
console.log("[ModAPI] Hooked into bootstrap. .blocks, .items, .materials and .enchantments are now accessible.");
|
console.log("[ModAPI] Hooked into bootstrap. .blocks, .items, .materials and .enchantments are now accessible.");
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
*/*/ ZXMushroom63's rather large to do list */*/
|
|
||||||
|
|
||||||
Add makeItemStack to LCI [Todo]
|
|
||||||
Fix blocklook.js [In progress]
|
|
||||||
Fix setblocktest.js [In progress]
|
|
Loading…
x
Reference in New Issue
Block a user