From 147afd61571d576a8ba41127a32bbf96f22664c4 Mon Sep 17 00:00:00 2001 From: ZHAY10086 Date: Mon, 16 Jun 2025 20:19:53 +0800 Subject: [PATCH] update with upstream --- config/ZenUtils.cfg | 19 ++ .../patches/thaumic_energistics.json | 36 +++ config/unidict/UniDict.cfg | 2 +- oresources/contenttweaker/lang/en_us.lang | 14 +- oresources/contenttweaker/lang/zh_cn.lang | 6 +- resources/contenttweaker/lang/en_us.lang | 12 +- scripts/ModularXPAssimilator.zs | 283 ------------------ scripts/ThaumcraftGating.zs | 63 +--- scripts/TheGreatOreCleanse.zs | 27 +- scripts/ToolTips.zs | 4 - scripts/ToolTips2.zs | 1 - .../experience/ModularXPAssimilator.zs | 92 ++++++ .../experience/XPConfigurator.zs | 69 +++++ .../portals/BeeStargatePortalBlocks.zs | 32 +- .../portals/ModularBeeStargate.zs | 42 +-- .../portals/ModularWormholeField.zs | 29 +- scripts/mixin/thaumcraft/UnifyBoreDrop.zs | 28 ++ scripts/mixin/thaumcraft/UnifyTurretDrops.zs | 55 ++++ scripts/thaumcraft/UnifyGolemMaterials.zs | 60 ++++ .../infusion/LateInfusionRecipes.zs | 123 ++++++++ scripts/thaumcraft/research/LateResearch.zs | 82 +++++ scripts/util/ModularEventUtils.zs | 47 +++ 22 files changed, 686 insertions(+), 440 deletions(-) create mode 100644 config/thaumcraftfix/patches/thaumic_energistics.json delete mode 100644 scripts/ModularXPAssimilator.zs create mode 100644 scripts/advancedModulars/experience/ModularXPAssimilator.zs create mode 100644 scripts/advancedModulars/experience/XPConfigurator.zs rename scripts/{ => advancedModulars}/portals/BeeStargatePortalBlocks.zs (99%) rename scripts/{ => advancedModulars}/portals/ModularBeeStargate.zs (90%) rename scripts/{ => advancedModulars}/portals/ModularWormholeField.zs (85%) create mode 100644 scripts/mixin/thaumcraft/UnifyBoreDrop.zs create mode 100644 scripts/mixin/thaumcraft/UnifyTurretDrops.zs create mode 100644 scripts/thaumcraft/UnifyGolemMaterials.zs create mode 100644 scripts/thaumcraft/infusion/LateInfusionRecipes.zs create mode 100644 scripts/thaumcraft/research/LateResearch.zs create mode 100644 scripts/util/ModularEventUtils.zs diff --git a/config/ZenUtils.cfg b/config/ZenUtils.cfg index 71b469ea..413d1409 100644 --- a/config/ZenUtils.cfg +++ b/config/ZenUtils.cfg @@ -1,7 +1,26 @@ # Configuration file general { + # Allow insertion of zs execution during mod loading stage + # Format: scriptLoaderName;modid;stageMarker;before|after + # Valid stage marker: C (Construction) H (Preinit) I (Init) J (Postinit) A (Available) + # Example: custom;mekanism;J;before -> runs `#loader custom` scripts before mekanism runs its code on post-initialization stage + # Note: + # 1. On construction stage and preinit stage before crafttweaker, only native methods are available + # 2. Many recipe modifications are staged. For example, scripts are loaded on init, but recipe modifications for crafting table and furnace are staged on postinit + # It means recipe modifications MAY NOT be executed after their loading stage + # ZenUtils will re-execute crafttweaker recipe modifications after all custom script load entrypoint on POSTINIT, but other crafttweaker addons not + S:customScriptEntrypoint < + lateAddTC;modtweaker;A;after + > + + # Enable mixinzs. Default: false B:enableMixin=true + + # Enable RandomTickEvent. It patches hotspot random tick code, which may produce performance loss. Do not enable it if you don't need it. Default: false B:enableRandomTickEvent=false + + # Enable fast script loading. Note: If enabled, ONLY PREPROCESSORS AT SCRIPT HEADER ARE EFFECTIVE. (except mixin scripts) Default: false + B:fastScriptLoading=false } diff --git a/config/thaumcraftfix/patches/thaumic_energistics.json b/config/thaumcraftfix/patches/thaumic_energistics.json new file mode 100644 index 00000000..243efcd2 --- /dev/null +++ b/config/thaumcraftfix/patches/thaumic_energistics.json @@ -0,0 +1,36 @@ +[ + { + "key": "ARCANEASSEMBLER", + "ops": [ + { + "op": "move", + "from": "stages/0/required_craft", + "path": "stages/0/required_item" + } + ] + }, + { + "key": "ARCANEINSCRIBER", + "ops": [ + { + "op": "move", + "from": "stages/0/required_craft", + "path": "stages/0/required_item" + } + ] + } + { + "key": "KNOWLEDGECORE", + "ops": [ + { + "op": "remove", + "path": "stages/0/required_craft" + }, + { + "op": "replace", + "path": "stages/0/required_item/0", + "value": "contenttweaker:complex_gearbox" + } + ] + } +] \ No newline at end of file diff --git a/config/unidict/UniDict.cfg b/config/unidict/UniDict.cfg index ff22e445..62c139c3 100644 --- a/config/unidict/UniDict.cfg +++ b/config/unidict/UniDict.cfg @@ -245,6 +245,7 @@ resources { minecraft:gold_ingot_from_block minecraft:gold_ingot_from_nuggets minecraft:gold_block + immersiveengineering:compat/plate_thaumium_brass > # Recipe names that you want to be removed. @@ -267,4 +268,3 @@ resources { B:treatRecipeToRemoveAsRegex=false } - diff --git a/oresources/contenttweaker/lang/en_us.lang b/oresources/contenttweaker/lang/en_us.lang index f90fa723..fb2f4e81 100644 --- a/oresources/contenttweaker/lang/en_us.lang +++ b/oresources/contenttweaker/lang/en_us.lang @@ -3183,7 +3183,7 @@ item.contenttweaker.stone_of_dimensional_ascension.name=Stone of Dimensional Asc item.contenttweaker.astral_mastery_tome.name=Tome of Astral Mastery item.contenttweaker.master_spell_infernum.name=Master Spell: Infernum item.contenttweaker.master_spell_sonus.name=Master Spell: Sonus -item.contenttweaker.master_spell_gognitio.name=Master Spell: Cognitio +item.contenttweaker.master_spell_cognitio.name=Master Spell: Cognitio item.contenttweaker.white_hole_core.name=White Hole Core item.contenttweaker.quasar_core.name=Quasar Core item.contenttweaker.call_to_mission.name=Call to Mission @@ -3262,11 +3262,7 @@ tile.contenttweaker.quasar_charged_core_of_definition.name=Quasar-Charged Core o tile.contenttweaker.directed_miniature_quasar.name=Directed Miniature Quasar tile.contenttweaker.quasar_burst_director.name=Quasar Burst Director fluid.inquiring_abyssite=Inquiring Abyssite - - - - - - - - +# XP Bath +item.contenttweaker.xp_configurator.desc=Right-click to cycle mode +tile.modularmachinery.xp_assimilator.failure=No nearby player +tile.modularmachinery.xp_assimilator.desc=%d xp: Stand right on top of the controller inside the pool \ No newline at end of file diff --git a/oresources/contenttweaker/lang/zh_cn.lang b/oresources/contenttweaker/lang/zh_cn.lang index ae9fb25a..689cd16a 100644 --- a/oresources/contenttweaker/lang/zh_cn.lang +++ b/oresources/contenttweaker/lang/zh_cn.lang @@ -1596,7 +1596,7 @@ item.contenttweaker.faultless_ichor.name=无瑕灵液 item.contenttweaker.gem_of_the_sleeping_city.name=长眠之城宝石 item.contenttweaker.cat_ears.name=猫耳 item.contenttweaker.blue_hair.name=蓝发 -item.contenttweaker.time_crystal.name=时间水晶 +item.contenttweaker.time_crystal.name=时间晶体 item.contenttweaker.stone_of_the_sleeping_city.name=长眠之城石头 item.contenttweaker.imstuck_getmehome.name=我卡住了,让我回家! item.contenttweaker.elder_spooder_string.name=古老四百大线 @@ -3262,6 +3262,10 @@ tile.contenttweaker.quasar_charged_core_of_definition.name=类星体充能定义 tile.contenttweaker.directed_miniature_quasar.name=定向微型类星体 tile.contenttweaker.quasar_burst_director.name=类星体爆发导向器 fluid.inquiring_abyssite=推演深渊金属 +# XP Bath +item.contenttweaker.xp_configurator.desc=右击以循环模式 +tile.modularmachinery.xp_assimilator.failure=附近没有玩家 +tile.modularmachinery.xp_assimilator.desc=%d xp:站在池子中控制器正上方的位置 # Custom Materials base.material.demonic_steel=恶魔钢 diff --git a/resources/contenttweaker/lang/en_us.lang b/resources/contenttweaker/lang/en_us.lang index 87e6f9d4..fb2f4e81 100644 --- a/resources/contenttweaker/lang/en_us.lang +++ b/resources/contenttweaker/lang/en_us.lang @@ -3262,11 +3262,7 @@ tile.contenttweaker.quasar_charged_core_of_definition.name=Quasar-Charged Core o tile.contenttweaker.directed_miniature_quasar.name=Directed Miniature Quasar tile.contenttweaker.quasar_burst_director.name=Quasar Burst Director fluid.inquiring_abyssite=Inquiring Abyssite - - - - - - - - +# XP Bath +item.contenttweaker.xp_configurator.desc=Right-click to cycle mode +tile.modularmachinery.xp_assimilator.failure=No nearby player +tile.modularmachinery.xp_assimilator.desc=%d xp: Stand right on top of the controller inside the pool \ No newline at end of file diff --git a/scripts/ModularXPAssimilator.zs b/scripts/ModularXPAssimilator.zs deleted file mode 100644 index c47ea97a..00000000 --- a/scripts/ModularXPAssimilator.zs +++ /dev/null @@ -1,283 +0,0 @@ -import mods.modularmachinery.RecipeBuilder; -import mods.modularmachinery.RecipeEvent; -import mods.modularmachinery.MachineEvent; -import mods.modularmachinery.RecipeCheckEvent; -import mods.modularmachinery.RecipeFinishEvent; -import mods.modularmachinery.IMachineController; -import mods.contenttweaker.Commands; -import crafttweaker.server.IServer; -import crafttweaker.command.ICommandManager; -import crafttweaker.command.ICommandSender; - - -recipes.addShaped(.withTag({FluidName: "bewitched_essence_salts", Amount: 1000}), -[[, , ], -[, .withTag({FluidName: "mana", Amount: 1000}), ], -[, , ]]); - -recipes.addShaped(.withTag({display: {Lore: ["§d§o1X§r"]}}), -[[, , ], -[, , ], -[, , ]]); - -mods.chisel.Carving.addGroup("experienceconfig"); -mods.chisel.Carving.addVariation("experienceconfig", .withTag({display: {Lore: ["§d§o1X§r"]}})); -mods.chisel.Carving.addVariation("experienceconfig", .withTag({display: {Lore: ["§d§o64X§r"]}})); -mods.chisel.Carving.addVariation("experienceconfig", .withTag({display: {Lore: ["§d§o256X§r"]}})); -mods.chisel.Carving.addVariation("experienceconfig", .withTag({display: {Lore: ["§d§o1024X§r"]}})); - - - -var addxpsolidified1 = RecipeBuilder.newBuilder("addxpsolidified1","xp_assimilator",5); -addxpsolidified1.addItemInput(); -addxpsolidified1.addItemInput(.withTag({display: {Lore: ["§d§o1X§r"]}})); -addxpsolidified1.setChance(0.0); -addxpsolidified1.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxpsolidified1.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 8 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxpsolidified1.addRecipeTooltip("8 xp:站在池子中控制器正上方的位置"); -addxpsolidified1.build(); - -var addxpsolidified2 = RecipeBuilder.newBuilder("addxpsolidified2","xp_assimilator",5); -addxpsolidified2.addItemInput(*64); -addxpsolidified2.addItemInput(.withTag({display: {Lore: ["§d§o64X§r"]}})); -addxpsolidified2.setChance(0.0); -addxpsolidified2.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxpsolidified2.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 512 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxpsolidified2.addRecipeTooltip("512 xp:站在池子中控制器正上方的位置"); -addxpsolidified2.build(); - -var addxpsolidified3 = RecipeBuilder.newBuilder("addxpsolidified3","xp_assimilator",5); -addxpsolidified3.addItemInput(*256); -addxpsolidified3.addItemInput(.withTag({display: {Lore: ["§d§o256X§r"]}})); -addxpsolidified3.setChance(0.0); -addxpsolidified3.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxpsolidified3.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 2048 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxpsolidified3.addRecipeTooltip("2048 xp:站在池子中控制器正上方的位置"); -addxpsolidified3.build(); - -var addxpsolidified4 = RecipeBuilder.newBuilder("addxpsolidified4","xp_assimilator",5); -addxpsolidified4.addItemInput(*1024); -addxpsolidified4.addItemInput(.withTag({display: {Lore: ["§d§o1024X§r"]}})); -addxpsolidified4.setChance(0.0); -addxpsolidified4.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxpsolidified4.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 8196 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxpsolidified4.addRecipeTooltip("8192 xp:站在池子中控制器正上方的位置"); -addxpsolidified4.build(); - - - -var addxpoverworldian1 = RecipeBuilder.newBuilder("addxpoverworldian1","xp_assimilator",5); -addxpoverworldian1.addItemInput(); -addxpoverworldian1.addItemInput(.withTag({display: {Lore: ["§d§o1X§r"]}})); -addxpoverworldian1.setChance(0.0); -addxpoverworldian1.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxpoverworldian1.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 10 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxpoverworldian1.addRecipeTooltip("10 xp:站在池子中控制器正上方的位置"); -addxpoverworldian1.build(); - -var addxpoverworldian2 = RecipeBuilder.newBuilder("addxpoverworldian2","xp_assimilator",5); -addxpoverworldian2.addItemInput(*64); -addxpoverworldian2.addItemInput(.withTag({display: {Lore: ["§d§o64X§r"]}})); -addxpoverworldian2.setChance(0.0); -addxpoverworldian2.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxpoverworldian2.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 640 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxpoverworldian2.addRecipeTooltip("640 xp:站在池子中控制器正上方的位置"); -addxpoverworldian2.build(); - -var addxpoverworldian3 = RecipeBuilder.newBuilder("addxpoverworldian3","xp_assimilator",5); -addxpoverworldian3.addItemInput(*256); -addxpoverworldian3.addItemInput(.withTag({display: {Lore: ["§d§o256X§r"]}})); -addxpoverworldian3.setChance(0.0); -addxpoverworldian3.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxpoverworldian3.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 2560 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxpoverworldian3.addRecipeTooltip("2560 xp:站在池子中控制器正上方的位置"); -addxpoverworldian3.build(); - -var addxpoverworldian4 = RecipeBuilder.newBuilder("addxpoverworldian4","xp_assimilator",5); -addxpoverworldian4.addItemInput(*1024); -addxpoverworldian4.addItemInput(.withTag({display: {Lore: ["§d§o1024X§r"]}})); -addxpoverworldian4.setChance(0.0); -addxpoverworldian4.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxpoverworldian4.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 10240 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxpoverworldian4.addRecipeTooltip("10240 xp:站在池子中控制器正上方的位置"); -addxpoverworldian4.build(); - - - - -var addxphellish1 = RecipeBuilder.newBuilder("addxphellish1","xp_assimilator",5); -addxphellish1.addItemInput(); -addxphellish1.addItemInput(.withTag({display: {Lore: ["§d§o1X§r"]}})); -addxphellish1.setChance(0.0); -addxphellish1.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxphellish1.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 14 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxphellish1.addRecipeTooltip("14 xp:站在池子中控制器正上方的位置"); -addxphellish1.build(); - -var addxphellish2 = RecipeBuilder.newBuilder("addxphellish2","xp_assimilator",5); -addxphellish2.addItemInput(*64); -addxphellish2.addItemInput(.withTag({display: {Lore: ["§d§o64X§r"]}})); -addxphellish2.setChance(0.0); -addxphellish2.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxphellish2.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 896 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxphellish2.addRecipeTooltip("896 xp:站在池子中控制器正上方的位置"); -addxphellish2.build(); - -var addxphellish3 = RecipeBuilder.newBuilder("addxphellish3","xp_assimilator",5); -addxphellish3.addItemInput(*256); -addxphellish3.addItemInput(.withTag({display: {Lore: ["§d§o256X§r"]}})); -addxphellish3.setChance(0.0); -addxphellish3.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxphellish3.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 3584 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxphellish3.addRecipeTooltip("3584 xp:站在池子中控制器正上方的位置"); -addxphellish3.build(); - -var addxphellish4 = RecipeBuilder.newBuilder("addxphellish4","xp_assimilator",5); -addxphellish4.addItemInput(*1024); -addxphellish4.addItemInput(.withTag({display: {Lore: ["§d§o1024X§r"]}})); -addxphellish4.setChance(0.0); -addxphellish4.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxphellish4.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 14336 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxphellish4.addRecipeTooltip("14336 xp:站在池子中控制器正上方的位置"); -addxphellish4.build(); - - - - - -var addxpextraterr1 = RecipeBuilder.newBuilder("addxpextraterr1","xp_assimilator",5); -addxpextraterr1.addItemInput(); -addxpextraterr1.addItemInput(.withTag({display: {Lore: ["§d§o1X§r"]}})); -addxpextraterr1.setChance(0.0); -addxpextraterr1.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxpextraterr1.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 20 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxpextraterr1.addRecipeTooltip("20 xp:站在池子中控制器正上方的位置"); -addxpextraterr1.build(); - -var addxpextraterr2 = RecipeBuilder.newBuilder("addxpextraterr2","xp_assimilator",5); -addxpextraterr2.addItemInput(*64); -addxpextraterr2.addItemInput(.withTag({display: {Lore: ["§d§o64X§r"]}})); -addxpextraterr2.setChance(0.0); -addxpextraterr2.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxpextraterr2.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 1280 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxpextraterr2.addRecipeTooltip("1280 xp:站在池子中控制器正上方的位置"); -addxpextraterr2.build(); - -var addxpextraterr3 = RecipeBuilder.newBuilder("addxpextraterr3","xp_assimilator",5); -addxpextraterr3.addItemInput(*256); -addxpextraterr3.addItemInput(.withTag({display: {Lore: ["§d§o256X§r"]}})); -addxpextraterr3.setChance(0.0); -addxpextraterr3.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxpextraterr3.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 5120 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxpextraterr3.addRecipeTooltip("5120 xp:站在池子中控制器正上方的位置"); -addxpextraterr3.build(); - -var addxpextraterr4 = RecipeBuilder.newBuilder("addxpextraterr4","xp_assimilator",5); -addxpextraterr4.addItemInput(*1024); -addxpextraterr4.addItemInput(.withTag({display: {Lore: ["§d§o1024X§r"]}})); -addxpextraterr4.setChance(0.0); -addxpextraterr4.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxpextraterr4.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 20480 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxpextraterr4.addRecipeTooltip("20480 xp:站在池子中控制器正上方的位置"); -addxpextraterr4.build(); - - - -var addxptwilight1 = RecipeBuilder.newBuilder("addxptwilight1","xp_assimilator",5); -addxptwilight1.addItemInput(); -addxptwilight1.addItemInput(.withTag({display: {Lore: ["§d§o1X§r"]}})); -addxptwilight1.setChance(0.0); -addxptwilight1.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxptwilight1.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 30 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxptwilight1.addRecipeTooltip("30 xp:站在池子中控制器正上方的位置"); -addxptwilight1.build(); - -var addxptwilight2 = RecipeBuilder.newBuilder("addxptwilight2","xp_assimilator",5); -addxptwilight2.addItemInput(*64); -addxptwilight2.addItemInput(.withTag({display: {Lore: ["§d§o64X§r"]}})); -addxptwilight2.setChance(0.0); -addxptwilight2.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxptwilight2.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 1920 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxptwilight2.addRecipeTooltip("1920 xp:站在池子中控制器正上方的位置"); -addxptwilight2.build(); - -var addxptwilight3 = RecipeBuilder.newBuilder("addxptwilight3","xp_assimilator",5); -addxptwilight3.addItemInput(*256); -addxptwilight3.addItemInput(.withTag({display: {Lore: ["§d§o256X§r"]}})); -addxptwilight3.setChance(0.0); -addxptwilight3.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxptwilight3.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 7680 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxptwilight3.addRecipeTooltip("7680 xp:站在池子中控制器正上方的位置"); -addxptwilight3.build(); - -var addxptwilight4 = RecipeBuilder.newBuilder("addxptwilight4","xp_assimilator",5); -addxptwilight4.addItemInput(*1024); -addxptwilight4.addItemInput(.withTag({display: {Lore: ["§d§o1024X§r"]}})); -addxptwilight4.setChance(0.0); -addxptwilight4.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxptwilight4.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 30720 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxptwilight4.addRecipeTooltip("30720 xp:站在池子中控制器正上方的位置"); -addxptwilight4.build(); - - - - - -var addxpbeessence1 = RecipeBuilder.newBuilder("addxpbeessence1","xp_assimilator",5); -addxpbeessence1.addItemInput(); -addxpbeessence1.addItemInput(.withTag({display: {Lore: ["§d§o1X§r"]}})); -addxpbeessence1.setChance(0.0); -addxpbeessence1.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxpbeessence1.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 1000 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxpbeessence1.addRecipeTooltip("1000 xp:站在池子中控制器正上方的位置"); -addxpbeessence1.build(); - -var addxpbeessence2 = RecipeBuilder.newBuilder("addxpbeessence2","xp_assimilator",5); -addxpbeessence2.addItemInput(*64); -addxpbeessence2.addItemInput(.withTag({display: {Lore: ["§d§o64X§r"]}})); -addxpbeessence2.setChance(0.0); -addxpbeessence2.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxpbeessence2.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 64000 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxpbeessence2.addRecipeTooltip("64000 xp:站在池子中控制器正上方的位置"); -addxpbeessence2.build(); - -var addxpbeessence3 = RecipeBuilder.newBuilder("addxpbeessence3","xp_assimilator",5); -addxpbeessence3.addItemInput(*256); -addxpbeessence3.addItemInput(.withTag({display: {Lore: ["§d§o256X§r"]}})); -addxpbeessence3.setChance(0.0); -addxpbeessence3.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxpbeessence3.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 256000 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxpbeessence3.addRecipeTooltip("256000 xp:站在池子中控制器正上方的位置"); -addxpbeessence3.build(); - -var addxpbeessence4 = RecipeBuilder.newBuilder("addxpbeessence4","xp_assimilator",5); -addxpbeessence4.addItemInput(*1024); -addxpbeessence4.addItemInput(.withTag({display: {Lore: ["§d§o1024X§r"]}})); -addxpbeessence4.setChance(0.0); -addxpbeessence4.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -addxpbeessence4.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 1024000 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -addxpbeessence4.addRecipeTooltip("1024000 xp:站在池子中控制器正上方的位置"); -addxpbeessence4.build(); - - - -var cyfluid = RecipeBuilder.newBuilder("xpa_cyclic_experience","xp_assimilator",5); -cyfluid.addFluidInput( * 1000); -cyfluid.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -cyfluid.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 50 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -cyfluid.addRecipeTooltip("50 xp:站在池子中控制器正上方的位置"); -cyfluid.build(); - -var iffluid = RecipeBuilder.newBuilder("xpa_industrial_foregoing_essence","xp_assimilator",5); -iffluid.addFluidInput( * 1000); -iffluid.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -iffluid.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 50 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -iffluid.addRecipeTooltip("50 xp:站在池子中控制器正上方的位置"); -iffluid.build(); - -var tffluid = RecipeBuilder.newBuilder("xpa_thermal_foundation_essence_of_knowledge","xp_assimilator",5); -tffluid.addFluidInput( * 1000); -tffluid.addPostCheckHandler(function(event as RecipeCheckEvent) { if (server.commandManager.executeCommand(server,"testfor @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + ",r=2]") == 0) {event.setFailed("附近无玩家");} } ); -tffluid.addFinishHandler(function(event as RecipeFinishEvent) { server.commandManager.executeCommand(server,"xp 50 @p[x=" + event.controller.pos.x + ",y=" + event.controller.pos.y + ",z=" + event.controller.pos.z + "]"); } ); -tffluid.addRecipeTooltip("50 xp:站在池子中控制器正上方的位置"); -tffluid.build(); \ No newline at end of file diff --git a/scripts/ThaumcraftGating.zs b/scripts/ThaumcraftGating.zs index 7f627614..08f492d4 100644 --- a/scripts/ThaumcraftGating.zs +++ b/scripts/ThaumcraftGating.zs @@ -66,14 +66,15 @@ recipes.addShaped(*4, [, .reuse(), ], [, , ]]); -// mods.thaumcraft.ArcaneWorkbench.removeRecipe(); - recipes.removeShaped(); recipes.removeShaped(); -// recipes.removeShaped(); -// recipes.removeShaped(); -// recipes.removeShaped(); - +# See scripts/thaumcraft/research/LateResearch.zs for related research adjustments +recipes.removeShaped(); +recipes.removeShaped(); +recipes.removeShaped(); +# See config/thaumcraftfix/patches/thaumic_energistics.json for related research adjustments +mods.thaumcraft.ArcaneWorkbench.removeRecipe(); +mods.thaumcraft.ArcaneWorkbench.removeRecipe(); mods.thaumcraft.Infusion.removeRecipe(); val arcaneassembler = RecipeBuilder.newBuilder("arcaneassemblerinf","arcane_autoinfuser",120); @@ -92,8 +93,6 @@ arcaneassembler.addItemInput(); arcaneassembler.addItemOutput(); arcaneassembler.build(); -mods.thaumcraft.ArcaneWorkbench.removeRecipe(); - mods.thaumcraft.Crucible.registerRecipe("easierseal1", "", , , [*20,*10]); mods.thaumcraft.Crucible.registerRecipe("easierseal2", "", , , [*20,*10]); mods.thaumcraft.Crucible.registerRecipe("easierseal3", "", , , [*20,*10]); @@ -108,53 +107,6 @@ mods.thaumcraft.Infusion.registerRecipe("infuseshimmerleaf", "", , [, , , ]); - -mods.thaumcraft.Infusion.removeRecipe(); - -mods.thaumcraft.Infusion.registerRecipe("infkamichest", "", -, 10, -[*250,*150,*125,*125,*125,*60], -, -[, , - , , - , , - , , - , , - , ]); - -mods.thaumcraft.Infusion.registerRecipe("infkamiboots", "", -, 10, -[*250,*150,*125,*125,*125,*60], -, -[, , - , , - , , - , , - , , - , ]); - - mods.thaumcraft.Infusion.registerRecipe("infkamilegs", "", -, 10, -[*250,*150,*125,*125,*125,*60], -, -[, , - , , - , , - .withTag({Potion: "minecraft:fire_resistance"}), , - , , - , ]); - - mods.thaumcraft.Infusion.registerRecipe("infkamihelm", "", -, 10, -[*250,*150,*125,*125,*125,*60], -, -[, , - , , - , , - .withTag({Potion: "minecraft:night_vision"}), , - , , - , ]); - recipes.addShaped(, [[null, , null], [, , ], @@ -179,4 +131,3 @@ recipes.addShaped(, [[, , ], [, , ], [, , ]]); - diff --git a/scripts/TheGreatOreCleanse.zs b/scripts/TheGreatOreCleanse.zs index 7b409c3c..6735e795 100644 --- a/scripts/TheGreatOreCleanse.zs +++ b/scripts/TheGreatOreCleanse.zs @@ -45,12 +45,15 @@ recipes.addShapeless(*9, []); val brassplate = ; brassplate.remove(); +brassplate.remove(); + +recipes.removeByRecipeName("thaumcraft:brassplate"); mods.immersiveengineering.MetalPress.removeRecipe(); mods.immersiveengineering.MetalPress.addRecipe(, , , 2000); -recipes.removeShapeless(, [], true); -recipes.addShapeless(, +recipes.removeShapeless(, [], true); +recipes.addShapeless("plate_brass_ie", , [, ]); @@ -68,8 +71,6 @@ recipes.addShaped(, mods.immersiveengineering.ArcFurnace.removeRecipe(); mods.immersiveengineering.ArcFurnace.addRecipe(, , null, 100, 512, [*3]); mods.immersiveengineering.ArcFurnace.addRecipe(, , null, 100, 512, [*3]); -mods.immersiveengineering.ArcFurnace.addRecipe(, , null, 100, 512, [*3]); -mods.immersiveengineering.ArcFurnace.addRecipe(, , null, 100, 512, [*3]); //================================================================== @@ -286,11 +287,13 @@ silverplate.remove(); silverplate.remove(); silverplate.remove(); +recipes.removeByRecipeName("bewitchment:compat/silver_plate"); + mods.immersiveengineering.MetalPress.removeRecipe(); mods.immersiveengineering.MetalPress.addRecipe(, , , 2000); recipes.removeShapeless(, [], true); -recipes.addShapeless(, +recipes.addShapeless("plate_silver_ie", , [, ]); @@ -691,26 +694,20 @@ irondust.remove(); val ironplate = ; ironplate.remove(); ironplate.remove(); +// ironplate.remove(); ironplate.remove(); ironplate.remove(); -recipes.remove(); -recipes.addShaped(*3, -[[,,]]); +recipes.removeByRecipeName("thaumcraft:ironplate"); mods.immersiveengineering.MetalPress.removeRecipe(); mods.immersiveengineering.MetalPress.addRecipe(, , , 2000); recipes.removeShapeless(, [], true); -recipes.addShapeless(, +recipes.addShapeless("plate_iron_ie", , [, ]); -recipes.addShapeless(*3, -[, -, -]); - mods.immersiveengineering.Crusher.removeRecipe(); mods.immersiveengineering.Crusher.addRecipe(*2, , 2048, , 0.1); mods.immersiveengineering.Crusher.addRecipe(, , 2048); @@ -906,4 +903,4 @@ mods.nuclearcraft.manufactory.removeRecipeWithInput([]); mods.nuclearcraft.melter.removeRecipeWithInput([]); -mods.nuclearcraft.pressurizer.removeRecipeWithInput([]); +mods.nuclearcraft.pressurizer.removeRecipeWithInput([]); \ No newline at end of file diff --git a/scripts/ToolTips.zs b/scripts/ToolTips.zs index 4be1b596..de0a5b0b 100644 --- a/scripts/ToolTips.zs +++ b/scripts/ToolTips.zs @@ -1192,10 +1192,6 @@ .addTooltip(format.red("在递归监狱钥匙生成的地牢内使用")); .addTooltip(format.red("在递归监狱钥匙生成的地牢内使用")); -.addTooltip(format.red("若想完成魔导手册中需要对应金属板的条目,一定要手动合成,使用压缩机合成无法完成条目")); -.addTooltip(format.red("若想完成魔导手册中需要对应金属板的条目,一定要手动合成,使用压缩机合成无法完成条目")); -.addTooltip(format.red("若想完成魔导手册中需要对应金属板的条目,一定要手动合成,使用压缩机合成无法完成条目")); - .addTooltip(format.red("由于卡顿,真正的注射器物品已在JEI中隐藏,无视结构空位即可")); diff --git a/scripts/ToolTips2.zs b/scripts/ToolTips2.zs index 0068ce69..7ea5d593 100644 --- a/scripts/ToolTips2.zs +++ b/scripts/ToolTips2.zs @@ -2612,7 +2612,6 @@ import crafttweaker.item.IItemCondition; .addTooltip(format.red("警告:不要与星芒宝典、魔导手册、植物魔法辞典、死灵之书以及万能溶剂之经合成")); .addTooltip(format.red("警告:可能引起崩溃,应避免过多使用")); -.addTooltip(format.red("虚空预言者的珍珠的魔力减免不起作用")); .addTooltip(format.red("HiaggTM得升级他的IO仓了")); diff --git a/scripts/advancedModulars/experience/ModularXPAssimilator.zs b/scripts/advancedModulars/experience/ModularXPAssimilator.zs new file mode 100644 index 00000000..0a85f56d --- /dev/null +++ b/scripts/advancedModulars/experience/ModularXPAssimilator.zs @@ -0,0 +1,92 @@ +import crafttweaker.liquid.ILiquidStack; +import crafttweaker.item.IItemStack; +import crafttweaker.player.IPlayer; +import crafttweaker.text.ITextComponent; +import mods.modularmachinery.IMachineController; +import mods.modularmachinery.RecipeBuilder; +import mods.modularmachinery.RecipeCheckEvent; +import mods.modularmachinery.RecipeFinishEvent; + +import scripts.advancedModulars.experience.XPConfigurator as Configurator; +import scripts.util.ModularEventUtils as Util; + +// Crafting recipes +recipes.addShaped(.withTag({FluidName: "bewitched_essence_salts", Amount: 1000}), +[[, , ], +[, .withTag({FluidName: "mana", Amount: 1000}), ], +[, , ]]); + +recipes.addShaped(Configurator.withMode(1), +[[, , ], +[, , ], +[, , ]]); + +// Item machine recipes +var xpSolidified = buildItemRecipes(, "xp_solidified", 8); +var xpOverworldian = buildItemRecipes(, "xp_overworldian", 10); +var xpHellish = buildItemRecipes(, "xp_hellish", 14); +var xpExtraterrestrial = buildItemRecipes(, "xp_extraterrestrial", 20); +var xpTwilight = buildItemRecipes(, "xp_twilight", 30); +var xpBeeEssence = buildItemRecipes(, "xp_bee_essence", 1000); + +// Fluid machine recipes +var xpCyclic = buildFluidRecipes(, "xp_cyclic", 50); +var xpIndustrialForegoing = buildFluidRecipes(, "xp_industrial_foregoing", 50); +var xpThermal = buildFluidRecipes(, "xp_thermal", 50); + +// Recipe builders +function buildItemRecipes(stack as IItemStack, baseName as string, baseXP as int) { + for mode in Configurator.modes { + var xp = baseXP * mode; + var itemXPRecipe = RecipeBuilder.newBuilder(`${baseName}_${mode}x`, "xp_assimilator", 5); + itemXPRecipe.addItemInput(stack * mode) + .addItemInput(Configurator.withMode(mode)) + .setChance(0.0) + .addPostCheckHandler(function(event as RecipeCheckEvent) { + checkForPlayer(event); + } + ) + .addFinishHandler(function(event as RecipeFinishEvent) { + giveXPToNearest(event.controller, xp); + } + ) + .addRecipeTooltip(ITextComponent.fromTranslation("tile.modularmachinery.xp_assimilator.desc", [xp]).formattedText) + .build(); + } +} + +function buildFluidRecipes(stack as ILiquidStack, baseName as string, baseXP as int) { + var xp = baseXP; + var fluidXPRecipe = RecipeBuilder.newBuilder(`${baseName}`, "xp_assimilator", 5); + fluidXPRecipe.addFluidInput(stack * 1000) + .addPostCheckHandler(function(event as RecipeCheckEvent) { + checkForPlayer(event); + } + ) + .addFinishHandler(function(event as RecipeFinishEvent) { + giveXPToNearest(event.controller, xp); + } + ) + .addRecipeTooltip(ITextComponent.fromTranslation("tile.modularmachinery.xp_assimilator.desc", [xp]).formattedText) + .build(); +} + +// Recipe logic +function checkForPlayer(event as RecipeCheckEvent) as void { + var pos = event.controller.pos; + // I think this is thread safe: doesn't modify world state and MMCE's task executor spins the main thread (?) during execution + var player = event.controller.world.getClosestPlayer(pos.x, pos.y, pos.z, 2, false) as IPlayer; + if (isNull(player)) { + var failureText = ITextComponent.fromTranslation("tile.modularmachinery.xp_assimilator.failure").formattedText; + event.setFailed(failureText); + } +} + +function giveXPToNearest(controller as IMachineController, xp as int) { + var sender = Util.getControllerSender(controller); + var pos = controller.pos; + var command = `xp ${xp} @p[x=${pos.x},y=${pos.y},z=${pos.z}]`; + Util.scheduleTask(controller, function() as void { + server.commandManager.executeCommand(sender, command); + }); +} \ No newline at end of file diff --git a/scripts/advancedModulars/experience/XPConfigurator.zs b/scripts/advancedModulars/experience/XPConfigurator.zs new file mode 100644 index 00000000..fc3df644 --- /dev/null +++ b/scripts/advancedModulars/experience/XPConfigurator.zs @@ -0,0 +1,69 @@ +#priority 10 + +import crafttweaker.data.IData; +import crafttweaker.item.IItemStack; +import crafttweaker.text.ITextComponent; + +static modes as int[] = [1, 64, 256, 1024]; + +.itemRightClick = function(itemStack, world, player, hand) { + if (world.remote) { + return "PASS"; + } + if (hand == "MAIN_HAND") { + var nbt as IData = itemStack.tag; + var newNBT as IData = {}; + if (isNull(nbt) || isNull(nbt.mode)) { + // Set the default mode + newNBT = { + mode: modes[0] as int + } as IData; + } else if (!isNull(nbt.mode)) { + // Cycle the mode + newNBT = { + mode: cycle(nbt.mode) + } as IData; + } + // Update the mode + (itemStack as IItemStack).mutable().withTag(newNBT); + + var text = ITextComponent.fromTranslation("chat.contenttweaker.xp_configurator.mode", newNBT.mode); + text.style.color = "LIGHT_PURPLE"; + player.sendRichTextStatusMessage(text, true); + return "SUCCESS"; + } + return "PASS"; +}; +.addTooltip(ITextComponent.fromTranslation("item.contenttweaker.xp_configurator.desc").formattedText); +.addAdvancedTooltip(function(item) { + var nbt = item.tag; + if (!(isNull(nbt) || isNull(nbt.mode))) { + var text = ITextComponent.fromTranslation("chat.contenttweaker.xp_configurator.mode", nbt.mode); + text.style.color = "LIGHT_PURPLE"; + return text.formattedText; + } + return null; +}); + +function cycle(currentMode as int) as int { + for i in 0 to modes.length { + if (modes[i] == currentMode) { + return modes[(i + 1) % modes.length]; + } + } +} + +function withMode(modeIn as int) as IItemStack { + var nbt = { + mode: "无效模式,请反馈该bug!" + } as IData; + for mode in modes { + if (modeIn == mode) { + nbt = { + mode: modeIn + } as IData; + break; + } + } + return .withTag(nbt); +} \ No newline at end of file diff --git a/scripts/portals/BeeStargatePortalBlocks.zs b/scripts/advancedModulars/portals/BeeStargatePortalBlocks.zs similarity index 99% rename from scripts/portals/BeeStargatePortalBlocks.zs rename to scripts/advancedModulars/portals/BeeStargatePortalBlocks.zs index 55aa59ec..2c00a466 100644 --- a/scripts/portals/BeeStargatePortalBlocks.zs +++ b/scripts/advancedModulars/portals/BeeStargatePortalBlocks.zs @@ -9,6 +9,7 @@ import mods.contenttweaker.Commands; import mods.contenttweaker.VanillaFactory; import mods.zenutils.cotx.Block; +# Bee stargate portals var sednaportal = VanillaFactory.createExpandBlock("sedna_portal_block", ); setPortalProps(sednaportal); setPortalLogic(sednaportal, 147, true); @@ -29,25 +30,21 @@ setPortalProps(lunaportal); setPortalLogic(lunaportal, 145, true); lunaportal.register(); - var osirisportal = VanillaFactory.createExpandBlock("osiris_portal_block", ); setPortalProps(osirisportal); setPortalLogic(osirisportal, 148, true); osirisportal.register(); - var ptahportal = VanillaFactory.createExpandBlock("ptah_portal_block", ); setPortalProps(ptahportal); setPortalLogic(ptahportal, 149, true); ptahportal.register(); - var hatorportal = VanillaFactory.createExpandBlock("hator_portal_block", ); setPortalProps(hatorportal); setPortalLogic(hatorportal, 150, true); hatorportal.register(); - var europaportal = VanillaFactory.createExpandBlock("europa_portal_block", ); setPortalProps(europaportal); setPortalLogic(europaportal, 151, true); @@ -58,25 +55,21 @@ setPortalProps(oiportal); setPortalLogic(oiportal, 152, true); oiportal.register(); - var falacerportal = VanillaFactory.createExpandBlock("falacer_portal_block", ); setPortalProps(falacerportal); setPortalLogic(falacerportal, 160, true); falacerportal.register(); - var orcusportal = VanillaFactory.createExpandBlock("orcus_portal_block", ); setPortalProps(orcusportal); setPortalLogic(orcusportal, 161, true); orcusportal.register(); - var myrmexportal = VanillaFactory.createExpandBlock("myrmex_portal_block", ); setPortalProps(myrmexportal); setPortalLogic(myrmexportal, 164, true); myrmexportal.register(); - var pixoniaportal = VanillaFactory.createExpandBlock("pixonia_portal_block", ); setPortalProps(pixoniaportal); setPortalLogic(pixoniaportal, 165, true); @@ -87,17 +80,15 @@ setPortalProps(proximaportal); setPortalLogic(proximaportal, 166, true); proximaportal.register(); - -var zoiportal = VanillaFactory.createExpandBlock("zoi_portal_block", ); -setPortalProps(zoiportal); -setPortalLogic(zoiportal, 171, true); -zoiportal.register(); - var neroportal = VanillaFactory.createExpandBlock("nero_portal_block", ); setPortalProps(neroportal); setPortalLogic(neroportal, 170, true); neroportal.register(); +var zoiportal = VanillaFactory.createExpandBlock("zoi_portal_block", ); +setPortalProps(zoiportal); +setPortalLogic(zoiportal, 171, true); +zoiportal.register(); var akathartosportal = VanillaFactory.createExpandBlock("akathartos_portal_block", ); setPortalProps(akathartosportal); @@ -109,19 +100,13 @@ setPortalProps(pauramportal); setPortalLogic(pauramportal, 173, true); pauramportal.register(); - var alkemiaportal = VanillaFactory.createExpandBlock("alkemia_portal_block", ); setPortalProps(alkemiaportal); setPortalLogic(alkemiaportal, 174, true); alkemiaportal.register(); -var apichisiportal = VanillaFactory.createExpandBlock("apichisi_portal_block", ); -setPortalProps(apichisiportal); -setPortalLogic(apichisiportal, 184, false); -apichisiportal.register(); - - +# Wormhole generator portals var taerrapiattaportal = VanillaFactory.createExpandBlock("taerrapiatta_portal_block", ); setPortalProps(taerrapiattaportal); setPortalLogic(taerrapiattaportal, 180, false); @@ -142,6 +127,11 @@ setPortalProps(finemportal); setPortalLogic(finemportal, 185, false); finemportal.register(); +var apichisiportal = VanillaFactory.createExpandBlock("apichisi_portal_block", ); +setPortalProps(apichisiportal); +setPortalLogic(apichisiportal, 184, false); +apichisiportal.register(); + var lyndenwyrmportal = VanillaFactory.createExpandBlock("lyndenwyrm_portal_block", ); setPortalProps(lyndenwyrmportal); setPortalLogic(lyndenwyrmportal, 162, false); diff --git a/scripts/portals/ModularBeeStargate.zs b/scripts/advancedModulars/portals/ModularBeeStargate.zs similarity index 90% rename from scripts/portals/ModularBeeStargate.zs rename to scripts/advancedModulars/portals/ModularBeeStargate.zs index a500a1f1..16d73c3f 100644 --- a/scripts/portals/ModularBeeStargate.zs +++ b/scripts/advancedModulars/portals/ModularBeeStargate.zs @@ -1,5 +1,3 @@ -import native.hellfirepvp.modularmachinery.common.crafting.command.ControllerCommandSender; -import native.hellfirepvp.modularmachinery.common.tiles.base.TileMultiblockMachineController; import native.net.minecraft.item.Item; import native.net.minecraft.item.ItemStack; @@ -9,16 +7,18 @@ import crafttweaker.world.IBlockPos; import mods.modularmachinery.RecipeBuilder; import mods.modularmachinery.MachineTickEvent; import mods.modularmachinery.RecipeStartEvent; -import mods.modularmachinery.RecipeFailureEvent; import mods.modularmachinery.MMEvents; import mods.modularmachinery.IMachineController; -// Ideally some code here should be shared with ModularWormholeField, but for some reason cross-script reference doesn't work. +// Shared code +import scripts.util.ModularEventUtils as Util; +static offset as Util.Offset = Util.Offset(5, -4); var portal = ; portal.addItems([ , , + , , , , @@ -38,7 +38,7 @@ portal.addItems([ ]); var tooltip = [ "该配方在激活时会生成一个传送门。", - "多方块结构必须位于太空站。", + "多方块结构必须位于空间站。", "站在传送门中以进行传送。" ] as string[]; @@ -62,6 +62,16 @@ stargaterhenia.addItemInput().setChance(0) .addRecipeTooltip(tooltip) .build(); +var stargatehaumea = RecipeBuilder.newBuilder("stargate_haumea", "bee_stargate", 100); +stargatehaumea.addItemInput().setChance(0) + .addFluidInput( * 100) + .addStartHandler(function(event as RecipeStartEvent) { + beeStargateRecipeStart(event.controller, "contenttweaker:haumea_portal_block", "Haumea"); + } + ) + .addRecipeTooltip(tooltip) + .build(); + var stargateluna = RecipeBuilder.newBuilder("stargate_luna", "bee_stargate", 100); stargateluna.addItemInput().setChance(0) .addFluidInput( * 100) @@ -224,9 +234,9 @@ stargatealkemia.addItemInput().setChance(0) // Do start up sound and message if no current portal, spawn portal if different recipe, or nothing if same portal: function beeStargateRecipeStart(controller as IMachineController, portalBlock as string, destination as string) { - var pos = getCenter(controller, 5, -4); - var sender = getControllerSender(controller); - controller.world.native.getMinecraftServer().addScheduledTask(function() { + var pos = offset.getCenter(controller); + var sender = Util.getControllerSender(controller); + Util.scheduleTask(controller, function() as void { var currentPortalBlock = controller.world.getBlockState(pos); if (currentPortalBlock != IBlockState.getBlockState(portalBlock,"")) { @@ -250,8 +260,8 @@ MMEvents.onMachinePostTick("bee_stargate", function(event as MachineTickEvent) { if (ctrl.world.time % 20 != 0 || ctrl.isWorking) { return; } - var pos = getCenter(ctrl, 5, -4); - ctrl.world.native.getMinecraftServer().addScheduledTask(function() { + var pos = offset.getCenter(ctrl); + Util.scheduleTask(ctrl, function() as void { var centerState = ctrl.world.getBlockState(pos); var itemBlock = ItemStack(Item.getItemFromBlock(centerState.block.native)); // Only clear blocks that aren't unbreakable or are known portal blocks. @@ -264,7 +274,7 @@ MMEvents.onMachinePostTick("bee_stargate", function(event as MachineTickEvent) { // Clear portal blocks. function beeStargateClear(controller as IMachineController, pos as IBlockPos) { - var sender = getControllerSender(controller); + var sender = Util.getControllerSender(controller); beeStargatePlacePortal(controller, "minecraft:air", pos, sender); var offlineText = '{"translate":"chat.contenttweaker.stargate.offline"}'; server.commandManager.executeCommand(sender, "playsound minecraft:entity.evocation_illager.cast_spell ambient @a " + pos.x + " " + pos.y + " " + pos.z + " 1 0.5"); @@ -281,14 +291,4 @@ function beeStargatePlacePortal(controller as IMachineController, portalBlock as if (facing == crafttweaker.world.IFacing.north() || facing == crafttweaker.world.IFacing.south()) { dx = 1; } else { dz = 1; } server.commandManager.executeCommand(sender, "fill " + (pos.x - dx) + " " + (pos.y - 1) + " " + (pos.z - dz) + " " + (pos.x + dx) + " " + (pos.y + 1) + " " + (pos.z + dz) + " " + portalBlock); -} - -function getCenter(ctrl as IMachineController, offsetUp as int, offsetFacing as int) as IBlockPos { - return ctrl.pos.getOffset(up, offsetUp).getOffset(ctrl.facing, offsetFacing); -} - -// The ICommandSender must have the correct associated world, so we're using ControllerCommandSender. -function getControllerSender(controller as IMachineController) as ICommandSender { - var sender = ControllerCommandSender(controller as TileMultiblockMachineController) as native.net.minecraft.command.ICommandSender; - return sender.wrapper; } \ No newline at end of file diff --git a/scripts/portals/ModularWormholeField.zs b/scripts/advancedModulars/portals/ModularWormholeField.zs similarity index 85% rename from scripts/portals/ModularWormholeField.zs rename to scripts/advancedModulars/portals/ModularWormholeField.zs index 19e8984e..7c9ba5d3 100644 --- a/scripts/portals/ModularWormholeField.zs +++ b/scripts/advancedModulars/portals/ModularWormholeField.zs @@ -1,5 +1,3 @@ -import native.hellfirepvp.modularmachinery.common.crafting.command.ControllerCommandSender; -import native.hellfirepvp.modularmachinery.common.tiles.base.TileMultiblockMachineController; import native.net.minecraft.item.Item; import native.net.minecraft.item.ItemStack; @@ -9,12 +7,13 @@ import crafttweaker.world.IBlockPos; import mods.modularmachinery.RecipeBuilder; import mods.modularmachinery.MachineTickEvent; import mods.modularmachinery.RecipeStartEvent; -import mods.modularmachinery.RecipeFailureEvent; import mods.modularmachinery.MMEvents; import mods.modularmachinery.IMachineController; -// Ideally some code here should be shared with ModularBeeStargate, but for some reason cross-script reference doesn't work. +// Shared code +import scripts.util.ModularEventUtils as Util; +static offset as Util.Offset = Util.Offset(4, -3); var portal = ; portal.addItems([ , @@ -102,9 +101,9 @@ wormholegallifrey.addItemInput().setChance(0) // Do start up sound and message if no current portal, spawn portal if different recipe, or nothing if same portal: function wormholeGeneratorRecipeStart(controller as IMachineController, portalBlock as string, destination as string) { - var pos = getCenter(controller, 4, -3); - var sender = getControllerSender(controller); - controller.world.native.getMinecraftServer().addScheduledTask(function() { + var pos = offset.getCenter(controller); + var sender = Util.getControllerSender(controller); + Util.scheduleTask(controller, function() as void { var currentPortalBlock = controller.world.getBlockState(pos); if (currentPortalBlock != IBlockState.getBlockState(portalBlock,"")) { @@ -128,8 +127,8 @@ MMEvents.onMachinePostTick("wormhole_field_generator", function(event as Machine if (ctrl.world.time % 20 != 0 || ctrl.isWorking) { return; } - var pos = getCenter(ctrl, 4, -3); - ctrl.world.native.getMinecraftServer().addScheduledTask(function() { + var pos = offset.getCenter(ctrl); + Util.scheduleTask(ctrl, function() as void { var centerState = ctrl.world.getBlockState(pos); var itemBlock = ItemStack(Item.getItemFromBlock(centerState.block.native)); // Only clear blocks that aren't unbreakable or are known portal blocks. @@ -142,7 +141,7 @@ MMEvents.onMachinePostTick("wormhole_field_generator", function(event as Machine // Clear portal blocks. function wormholeGeneratorClear(controller as IMachineController, pos as IBlockPos) { - var sender = getControllerSender(controller); + var sender = Util.getControllerSender(controller); wormholeGeneratorPlacePortal(controller, "minecraft:air", pos, sender); var offlineText = '{"translate":"chat.contenttweaker.wormhole_generator.offline"}'; server.commandManager.executeCommand(sender, "playsound minecraft:entity.evocation_illager.cast_spell ambient @a " + pos.x + " " + pos.y + " " + pos.z + " 1 0.5"); @@ -155,14 +154,4 @@ function wormholeGeneratorClear(controller as IMachineController, pos as IBlockP function wormholeGeneratorPlacePortal(controller as IMachineController, portalBlock as string, pos as IBlockPos, sender as ICommandSender) { var facing = controller.facing; server.commandManager.executeCommand(sender, "fill " + (pos.x - 1) + " " + (pos.y - 1) + " " + (pos.z - 1) + " " + (pos.x + 1) + " " + (pos.y + 1) + " " + (pos.z + 1) + " " + portalBlock); -} - -function getCenter(ctrl as IMachineController, offsetUp as int, offsetFacing as int) as IBlockPos { - return ctrl.pos.getOffset(up, offsetUp).getOffset(ctrl.facing, offsetFacing); -} - -// The ICommandSender must have the correct associated world, so we're using ControllerCommandSender. -function getControllerSender(controller as IMachineController) as ICommandSender { - var sender = ControllerCommandSender(controller as TileMultiblockMachineController) as native.net.minecraft.command.ICommandSender; - return sender.wrapper; } \ No newline at end of file diff --git a/scripts/mixin/thaumcraft/UnifyBoreDrop.zs b/scripts/mixin/thaumcraft/UnifyBoreDrop.zs new file mode 100644 index 00000000..bfd04f57 --- /dev/null +++ b/scripts/mixin/thaumcraft/UnifyBoreDrop.zs @@ -0,0 +1,28 @@ +#modloaded thaumcraft techreborn +#loader mixin + +import native.net.minecraft.item.Item; +import native.net.minecraft.item.ItemStack; + +import native.techreborn.items.ingredients.ItemPlates as TRPlates; + +/* +Unify plate drops for arcane bore. + +Created by ChaosStrikez for Thaumcraft v6.1.BETA-26. +*/ +#mixin {targets: "thaumcraft.common.entities.construct.EntityArcaneBore"} +zenClass mixinEntityArcaneBore { + #mixin Redirect + #{ + # method: "func_70628_a", + # at: { + # value: "NEW", + # target: "(Lnet/minecraft/item/Item;)Lnet/minecraft/item/ItemStack;", + # ordinal: 5 + # } + #} + function mbc_unifyBrassPlate(original as Item) as ItemStack { + return TRPlates.getPlateByName("brass"); + } +} \ No newline at end of file diff --git a/scripts/mixin/thaumcraft/UnifyTurretDrops.zs b/scripts/mixin/thaumcraft/UnifyTurretDrops.zs new file mode 100644 index 00000000..a5ffa83a --- /dev/null +++ b/scripts/mixin/thaumcraft/UnifyTurretDrops.zs @@ -0,0 +1,55 @@ +#modloaded thaumcraft techreborn thermalfoundation +#loader mixin + +import native.net.minecraft.item.Item; +import native.net.minecraft.item.ItemStack; + +import native.cofh.thermalfoundation.item.ItemMaterial as ThermalPlates; +import native.techreborn.items.ingredients.ItemPlates as TRPlates; + +/* +Unify plate drops for advanced crossbow turret. + +Created by ChaosStrikez for Thaumcraft v6.1.BETA-26. +*/ +#mixin {targets: "thaumcraft.common.entities.construct.EntityTurretCrossbowAdvanced"} +zenClass MixinEntityTurretCrossbowAdvanced { + #mixin Redirect + #{ + # method: "func_70628_a", + # at: { + # value: "NEW", + # target: "(Lnet/minecraft/item/Item;II)Lnet/minecraft/item/ItemStack;", + # ordinal: 4 + # } + #} + function mbc_unifyBrassPlate(original as Item, amount as int, meta as int) as ItemStack { + return TRPlates.getPlateByName("brass"); + } + + #mixin Redirect + #{ + # method: "func_70628_a", + # at: { + # value: "NEW", + # target: "(Lnet/minecraft/item/Item;II)Lnet/minecraft/item/ItemStack;", + # ordinal: 5 + # } + #} + function mbc_unifyIronPlate1(original as Item, amount as int, meta as int) as ItemStack { + return ThermalPlates.plateIron.copy(); + } + + #mixin Redirect + #{ + # method: "func_70628_a", + # at: { + # value: "NEW", + # target: "(Lnet/minecraft/item/Item;II)Lnet/minecraft/item/ItemStack;", + # ordinal: 6 + # } + #} + function mbc_unifyIronPlate2(original as Item, amount as int, meta as int) as ItemStack { + return ThermalPlates.plateIron.copy(); + } +} \ No newline at end of file diff --git a/scripts/thaumcraft/UnifyGolemMaterials.zs b/scripts/thaumcraft/UnifyGolemMaterials.zs new file mode 100644 index 00000000..2ca503d8 --- /dev/null +++ b/scripts/thaumcraft/UnifyGolemMaterials.zs @@ -0,0 +1,60 @@ +#modloaded thaumcraft +#loader lateAddTC +import native.net.minecraft.item.ItemStack; +import native.thaumcraft.api.golems.parts.GolemMaterial; +import native.thaumcraft.api.golems.parts.GolemHead; +import native.thaumcraft.api.golems.parts.GolemLeg; + +import crafttweaker.item.IItemStack; +/* +Unify plates visually shown in the golem press. +*/ +var unifiedPlates = { + : , // brass + : , // iron + : , // silver +} as IItemStack[IItemStack]; + +# Materials +for material in GolemMaterial.getMaterials() { + if (isStackValid(material.componentBase)) { + var baseComponent as IItemStack = material.componentBase.wrapper; + material.componentBase = unifyStack(baseComponent, unifiedPlates); + } +} +# Head +for head in GolemHead.getHeads() { + var components = head.components; + for i in 0 to components.length { + var component = components[i]; + if (component instanceof ItemStack && isStackValid(component as ItemStack)) { + var stack as IItemStack = (component as ItemStack).wrapper; + components[i] = unifyStack(stack, unifiedPlates); + } + } +} +# Leg +for leg in GolemLeg.getLegs() { + var components = leg.components; + for i in 0 to components.length { + var component = components[i]; + if (component instanceof ItemStack && isStackValid(component as ItemStack)) { + var stack as IItemStack = (component as ItemStack).wrapper; + components[i] = unifyStack(stack, unifiedPlates); + } + } +} + +function isStackValid(stack as ItemStack) as bool { + return !(isNull(stack) || stack.isEmpty()); +} + +function unifyStack(stackIn as ItemStack, unifiedDict as IItemStack[IItemStack]) as ItemStack { + var stack as IItemStack = stackIn.wrapper; + for original, unified in unifiedDict { + if (stack.anyAmount().matches(original)) { + return (unified * stack.amount).native; + } + } + return stackIn; +} \ No newline at end of file diff --git a/scripts/thaumcraft/infusion/LateInfusionRecipes.zs b/scripts/thaumcraft/infusion/LateInfusionRecipes.zs new file mode 100644 index 00000000..65d5196b --- /dev/null +++ b/scripts/thaumcraft/infusion/LateInfusionRecipes.zs @@ -0,0 +1,123 @@ +#modloaded thaumcraft modtweaker +#loader lateAddTC +import native.com.blamejared.compat.thaumcraft.handlers.ThaumCraft; +import native.com.blamejared.mtlib.helpers.InputHelper; +import native.net.minecraft.util.ResourceLocation; +import native.thaumcraft.api.ThaumcraftApi; +import native.thaumcraft.api.ThaumcraftApiHelper; +import native.thaumcraft.api.crafting.InfusionRecipe; + +import crafttweaker.item.IIngredient; +import crafttweaker.item.IItemStack; +import thaumcraft.aspect.CTAspectStack; + +/* +Infusion recipes that REPLACE existing recipes tied to research. Removal is unnecssary, the recipes will be overwritten. +This is to keep the recipe available in the research page. +*/ +var tcAdditions = "thaumadditions"; +var tcTinkerer = "thaumictinkerer"; +# KAMI armor +registerInfusionRecipeFromAddon(`${tcTinkerer}:kami_helm`, "TT_KAMIHELM", + , 32, + [ + * 150, * 125, * 125, + * 60, * 250, * 125 + ], + , + [ + , , , + , , , + .withTag({Potion: "minecraft:night_vision"}), , , + , , + ] +); +registerInfusionRecipeFromAddon(`${tcTinkerer}:kami_chest`, "TT_KAMICHEST", + , 32, + [ + * 150, * 125, * 125, + * 125, * 250, * 60 + ], + , + [ + , , , + , , , + , , , + , , + ] +); +registerInfusionRecipeFromAddon(`${tcTinkerer}:kami_legs`, "TT_KAMILEGS", + , 32, + [ + * 150, * 125, * 125, + * 125, * 250, * 60 + ], + , + [ + , , , + , , , + .withTag({Potion: "minecraft:fire_resistance"}), , , + , , + ] +); +registerInfusionRecipeFromAddon(`${tcTinkerer}:kami_boots`, "TT_KAMIBOOTS", + , 32, + [ + * 150, * 125, * 125, + * 125, * 250, * 60, + * 60 + ], + , + [ + , , , + , , , + , , , + , , + ] +); + +# Fix crystal crusher in JEI +registerInfusionRecipeFromAddon(`${tcAdditions}:crystal_crusher`, "TAR_CRYSTAL_CRUSHER", + , 3, + [ + * 20, * 20, * 20 + ], + , + [ + makeCrystal(), makeCrystal(), makeCrystal(), + makeCrystal(), makeCrystal(), makeCrystal(), + , , , + , , , + .withTag({Aspects: [{amount: 1, key: "praemunio"}]}), .withTag({Aspects: [{amount: 1, key: "praemunio"}]}) + ] +); + +# Unify brass plates +registerInfusionRecipeFromAddon(`${tcAdditions}:crystal_bore`, "TAR_CRYSTAL_BORE", + , 5, + [ + * 20, * 10, * 30 + ], + , + [ + , , , + , , + ] +); + +/* + The same as Infusion.registerRecipe(), but allows a namespace in the resource location. + ModTweaker only allows infusion recipes with the "thaumcraft" namespace, this allows any namespace. +*/ +function registerInfusionRecipeFromAddon(resourceLocation as string, research as string, output as IItemStack, instability as int, + aspects as CTAspectStack[], centralItem as IIngredient, recipe as IIngredient[]) { + var infusionRecipe = InfusionRecipe( + research, output.native, instability, + ThaumCraft.getAspects(aspects), centralItem.native, InputHelper.toObjects(recipe) + ); + ThaumcraftApi.addInfusionCraftingRecipe(ResourceLocation(resourceLocation), infusionRecipe); +} + +function makeCrystal(aspect as CTAspectStack) as IItemStack { + return ThaumcraftApiHelper.makeCrystal(ThaumCraft.getAspect(aspect)).wrapper; +} \ No newline at end of file diff --git a/scripts/thaumcraft/research/LateResearch.zs b/scripts/thaumcraft/research/LateResearch.zs new file mode 100644 index 00000000..1d831f67 --- /dev/null +++ b/scripts/thaumcraft/research/LateResearch.zs @@ -0,0 +1,82 @@ +#modloaded thaumcraft +#loader lateAddTC +import native.net.minecraft.item.ItemStack; +import native.thaumcraft.api.research.ResearchCategories; +import native.thaumcraft.api.research.ResearchStage; + +import crafttweaker.item.IItemStack; + +/* +Hard-coded, non-JSON, research pages to replace crafting requirements for consume requirements. +This is so we can make these ingredients obtainable through non-crafting recipes, +but still make associated research completable. + +See config/thaumcraftfix/patches for research page changes that are JSON-based. +*/ + +# Mithrillium plates +var mithrilliumPlate = ; +var t1JarStage = findCraftingStage("TAR_MITHRILLIUM_JAR", mithrilliumPlate); +convertCraftToConsume(t1JarStage, mithrilliumPlate); + +var t1SmelterStage = findCraftingStage("TAR_MITHRILLIUM_SMELTER", mithrilliumPlate); +convertCraftToConsume(t1SmelterStage, mithrilliumPlate); + +# Adaminite plates +var adaminitePlate = ; +var t2JarStage = findCraftingStage("TAR_ADAMINITE_JAR", adaminitePlate); +convertCraftToConsume(t2JarStage, adaminitePlate); + +var t2SmelterStage = findCraftingStage("TAR_ADAMINITE_SMELTER", adaminitePlate); +convertCraftToConsume(t2SmelterStage, adaminitePlate); + +# Mithminite plates +var mithminitePlate = ; +var t3JarStage = findCraftingStage("TAR_MITHMINITE_JAR", mithminitePlate); +convertCraftToConsume(t3JarStage, mithminitePlate); + +var t3SmelterStage = findCraftingStage("TAR_MITHMINITE_SMELTER", mithminitePlate); +convertCraftToConsume(t3SmelterStage, mithminitePlate); + +var scytheStage = findCraftingStage("TAR_MITHMINITE_SCYTHE", mithminitePlate); +convertCraftToConsume(scytheStage, mithminitePlate); + +function findCraftingStage(researchName as string, targetItem as IItemStack) as ResearchStage { + var stages = ResearchCategories.getResearch(researchName).getStages(); + for stage in stages { + var crafts = stage.getCraft(); + // Check this stage has the target crafting requirement + if (!isNull(crafts)) { + var craftsAsItems = crafts as ItemStack[]; + for stack in craftsAsItems { + if (ItemStack.areItemStacksEqual(stack, targetItem.native)) { + return stage; + } + } + } + } + return null; +} + +function convertCraftToConsume(stage as ResearchStage, itemToConvert as IItemStack) { + var newCrafts = [] as [ItemStack]; + var oldCrafts = stage.getCraft() as ItemStack[]; + for stack in oldCrafts { + if (!ItemStack.areItemStacksEqual(stack, itemToConvert.native)) { + newCrafts += stack; + } + } + // Remove item from crafting requirement + if (newCrafts.length == 0) { + stage.setCraft(null); + } else { + stage.setCraft(newCrafts); + } + // Add item to consume requirement + var consumed = stage.getObtain(); + if (isNull(consumed) || consumed.length == 0) { + stage.setObtain([itemToConvert.native] as ItemStack[]); + } else { + stage.setObtain((consumed as ItemStack[]) + itemToConvert.native); + } +} diff --git a/scripts/util/ModularEventUtils.zs b/scripts/util/ModularEventUtils.zs new file mode 100644 index 00000000..daefaa7f --- /dev/null +++ b/scripts/util/ModularEventUtils.zs @@ -0,0 +1,47 @@ +#priority 10 + +import native.hellfirepvp.modularmachinery.common.crafting.command.ControllerCommandSender; +import native.hellfirepvp.modularmachinery.common.tiles.base.TileMultiblockMachineController; + +import crafttweaker.command.ICommandSender; +import crafttweaker.world.IBlockPos; +import mods.modularmachinery.IMachineController; + +/* +Utility functions for properly executing commands from a MMCE event. +*/ + +zenClass Offset { + val yOffset as int; + val facingOffset as int; + + zenConstructor(y as int, facing as int) { + yOffset = y; + facingOffset = facing; + } + + /* + Return the position of the center to use. + */ + function getCenter(ctrl as IMachineController) as IBlockPos { + return ctrl.pos.getOffset(up, yOffset).getOffset(ctrl.facing, facingOffset); + } +} + +/* +Return a command sender based on the MMCE controller. +Required in order to provide dimension context to commands. +*/ +function getControllerSender(controller as IMachineController) as ICommandSender { + var sender = ControllerCommandSender(controller as TileMultiblockMachineController) as native.net.minecraft.command.ICommandSender; + return sender.wrapper; +} + +/* +Schedule a task to run on the main thread. +You should use this for anything that modifies in-world objects. +The passed task must be `function() as void {...}`. +*/ +function scheduleTask(controller as IMachineController, task as function()void) { + controller.world.native.getMinecraftServer().addScheduledTask(task); +} \ No newline at end of file