diff --git a/examplemods/AsyncSink.js b/examplemods/AsyncSink.js index 101b3b7..b5f6fd4 100644 --- a/examplemods/AsyncSink.js +++ b/examplemods/AsyncSink.js @@ -247,8 +247,9 @@ ModAPI.meta.credits("By ZXMushroom63"); if (e.message.toLowerCase().startsWith(".reload_tex")) { e.preventDefault = true; ModAPI.mc.renderItem.itemModelMesher.simpleShapesCache.clear(); - ModAPI.promisify(ModAPI.mc.refreshResources)(); - ModAPI.events.callEvent("custom:asyncsink_reloaded", {}); + ModAPI.promisify(ModAPI.mc.refreshResources)().then(()=>{ + ModAPI.events.callEvent("custom:asyncsink_reloaded", {}); + }); } }); })(); \ No newline at end of file diff --git a/examplemods/unlucky_blocks.js b/examplemods/unlucky_blocks.js new file mode 100644 index 0000000..0967a99 --- /dev/null +++ b/examplemods/unlucky_blocks.js @@ -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); + 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()); + 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(), 5); + } + 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(145, $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()); + }); +})(); \ No newline at end of file diff --git a/injector.js b/injector.js index 96bfd39..919ae40 100644 --- a/injector.js +++ b/injector.js @@ -9,13 +9,22 @@ function _status(x) { document.querySelector("#status").innerText = x; } function entriesToStaticVariableProxy(entries, prefix) { + if (entries.length === 0) { + return `ModAPI.hooks._rippedStaticProperties[\`${prefix.replace( + "var ", + "" + )}\`]={};`; + } var getComponents = ""; entries.forEach((entry) => { getComponents += ` - case \`${entry.name}\`: - return ${entry.variable}; - break;`; + case \`${entry.name}\`: + return ${entry.variable}; + break;`; }); + getComponents += ` + default: + return Reflect.get(a,b,c);` var setComponents = ""; entries.forEach((entry) => { @@ -24,7 +33,11 @@ function entriesToStaticVariableProxy(entries, prefix) { ${entry.variable} = c; break;`; }); - var proxy = ` + setComponents += ` + default: + a[b]=c;` + /*/ + ModAPI.hooks._rippedStaticIndexer[\`${prefix.replace( "var ", "" @@ -33,7 +46,8 @@ function entriesToStaticVariableProxy(entries, prefix) { return '"' + x.name + '"'; }) .join(",")}]; - ModAPI.hooks._rippedStaticProperties[\`${prefix.replace( + /*/ + var proxy = `ModAPI.hooks._rippedStaticProperties[\`${prefix.replace( "var ", "" )}\`] = new Proxy({${entries @@ -51,6 +65,7 @@ function entriesToStaticVariableProxy(entries, prefix) { switch (b) { ${setComponents} } + return true; } });`; return proxy; @@ -238,7 +253,7 @@ var main;(function(){` patchedFile = patchedFile.replaceAll( - /function [a-z]+?_([a-zA-Z\$]+?)\(\) \{/gm, + /function [a-z]+?_([a-zA-Z0-9\$]+?)\(\) \{/gm, (match) => { var prefix = "var " + match.replace("function ", "").replace("() {", ""); var entries = []; diff --git a/postinit.js b/postinit.js index 064550a..5f52286 100644 --- a/postinit.js +++ b/postinit.js @@ -276,8 +276,10 @@ globalThis.modapi_postinit = "(" + (() => { 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].staticVariableNames = Object.keys(ModAPI.hooks._classMap[compiledName].staticVariables || {}); + if (item?.["$$constructor$$"]) { //Class does not have any hand written constructors //Eg: class MyClass {}