From bb8b1d92df89b069ae043b5156c837a1737dc349 Mon Sep 17 00:00:00 2001 From: Waiting Idly <25394029+WaitingIdly@users.noreply.github.com> Date: Fri, 8 Nov 2024 12:35:20 -0800 Subject: [PATCH] add Ice And Fire compat (#258) * add ice and fire compat * extract complex compat dependencies from map * replace example block comments with line comments * update how isRotN is checked based on review --- dependencies.gradle | 23 +++++- examples/postInit/iceandfire.groovy | 66 +++++++++++++++++ examples/postInit/jei.groovy | 12 +-- gradle.properties | 2 + .../groovyscript/compat/mods/ModSupport.java | 2 + .../compat/mods/iceandfire/FireForge.java | 73 ++++++++++++++++++ .../compat/mods/iceandfire/IceAndFire.java | 22 ++++++ .../compat/mods/iceandfire/IceForge.java | 73 ++++++++++++++++++ .../mods/iceandfire/LightningForge.java | 74 +++++++++++++++++++ .../groovyscript/documentation/Builder.java | 10 +-- .../assets/groovyscript/lang/en_us.lang | 12 +++ 11 files changed, 355 insertions(+), 14 deletions(-) create mode 100644 examples/postInit/iceandfire.groovy create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/iceandfire/FireForge.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/iceandfire/IceAndFire.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/iceandfire/IceForge.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/iceandfire/LightningForge.java diff --git a/dependencies.gradle b/dependencies.gradle index 4cbea18e2..99b5616af 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -72,12 +72,10 @@ final def mod_dependencies = [ 'forestry-59751:2918418' : [project.debug_forestry], 'future-mc-310059:5626387' : [project.debug_future_mc], 'horse-power-270466:2705433' : [project.debug_horse_power], + 'llibrary-243298:2504999' : [project.debug_ice_and_fire_old, project.debug_ice_and_fire_rotn], 'immersive_engineering-231951:2974106' : [project.debug_immersive_engineering, project.debug_immersive_petroleum, project.debug_immersive_technology], 'immersive-petroleum-268250:3382321' : [project.debug_immersive_petroleum], 'mct-immersive-technology-359407:5108047' : [project.debug_immersive_technology], - // WARNING: experimental must be placed before classic, otherwise you will crash when debugging either. Check FluidGenerator compat to confirm - 'industrialcraft_experimental-242638:3838713' : [project.debug_industrial_craft_2_experimental], - 'industrialcraft_classic-242942:3093607' : [project.debug_industrial_craft_2_classic], 'tesla-core-lib-254602:3438487' : [project.debug_industrial_foregoing], 'industrialforegoing-266515:2745321' : [project.debug_industrial_foregoing], 'inspirations-284007:2843007' : [project.debug_inspirations], @@ -155,6 +153,25 @@ dependencies { runtimeOnly 'crazypants:enderio:5.3.72' } + // WARNING: rotn must be placed before normal, otherwise you will not be able to properly detect sources for the LightningForge + compileOnly rfg.deobf('curse.maven:ice-and-fire-rotn-edition-457668:5738729') + compileOnly rfg.deobf('curse.maven:iceandfire-264231:2939529') + if (project.debug_ice_and_fire_rotn.toBoolean()) { + runtimeOnly rfg.deobf('curse.maven:ice-and-fire-rotn-edition-457668:5738729') + } else if (project.debug_ice_and_fire_old.toBoolean()) { + runtimeOnly rfg.deobf('curse.maven:iceandfire-264231:2939529') + } + + // WARNING: experimental must be placed before classic, otherwise you will crash when debugging either. Check FluidGenerator compat to confirm + compileOnly rfg.deobf('curse.maven:industrialcraft_experimental-242638:3838713') + compileOnly rfg.deobf('curse.maven:industrialcraft_classic-242942:3093607') + if (project.debug_industrial_craft_2_experimental.toBoolean()) { + runtimeOnly rfg.deobf('curse.maven:industrialcraft_experimental-242638:3838713') + } else if (project.debug_industrial_craft_2_classic.toBoolean()) { + runtimeOnly rfg.deobf('curse.maven:industrialcraft_classic-242942:3093607') + } + + if (project.debug_forestry.toBoolean()) { runtimeOnly rfg.deobf('curse.maven:jei-bees-248370:2490058') } diff --git a/examples/postInit/iceandfire.groovy b/examples/postInit/iceandfire.groovy new file mode 100644 index 000000000..1870b1761 --- /dev/null +++ b/examples/postInit/iceandfire.groovy @@ -0,0 +1,66 @@ + +// Auto generated groovyscript example file +// MODS_LOADED: iceandfire + +log.info 'mod \'iceandfire\' detected, running script' + +// Fire Dragonforge: +// Converts two input itemstacks into an output itemstack in a multiblock Dragonforge Fire Multiblock while there is a +// stage 3+ Fire Dragon nearby. + +mods.iceandfire.fire_forge.removeByInput(item('minecraft:iron_ingot')) +// mods.iceandfire.fire_forge.removeByInput(item('iceandfire:fire_dragon_blood')) +// mods.iceandfire.fire_forge.removeByOutput(item('iceandfire:dragonsteel_fire_ingot')) +// mods.iceandfire.fire_forge.removeAll() + +mods.iceandfire.fire_forge.recipeBuilder() + .input(item('minecraft:gold_ingot'), item('minecraft:gold_ingot')) + .output(item('minecraft:clay')) + .register() + +mods.iceandfire.fire_forge.recipeBuilder() + .input(item('minecraft:diamond'), item('minecraft:clay')) + .output(item('minecraft:gold_ingot')) + .register() + + +// Ice Dragonforge: +// Converts two input itemstacks into an output itemstack in a multiblock Dragonforge Ice Multiblock while there is a stage +// 3+ Ice Dragon nearby. + +mods.iceandfire.ice_forge.removeByInput(item('minecraft:iron_ingot')) +// mods.iceandfire.ice_forge.removeByInput(item('iceandfire:ice_dragon_blood')) +// mods.iceandfire.ice_forge.removeByOutput(item('iceandfire:dragonsteel_ice_ingot')) +// mods.iceandfire.ice_forge.removeAll() + +mods.iceandfire.ice_forge.recipeBuilder() + .input(item('minecraft:gold_ingot'), item('minecraft:gold_ingot')) + .output(item('minecraft:clay')) + .register() + +mods.iceandfire.ice_forge.recipeBuilder() + .input(item('minecraft:diamond'), item('minecraft:gold_ingot')) + .output(item('minecraft:clay')) + .register() + + +// Lightning Dragonforge: +// Converts two input itemstacks into an output itemstack in a multiblock Dragonforge Lightning Multiblock while there is a +// stage 3+ Lightning Dragon nearby. + +// mods.iceandfire.lightning_forge.removeByInput(item('minecraft:iron_ingot')) +// mods.iceandfire.lightning_forge.removeByInput(item('iceandfire:lightning_dragon_blood')) +// mods.iceandfire.lightning_forge.removeByOutput(item('iceandfire:dragonsteel_lightning_ingot')) +// mods.iceandfire.lightning_forge.removeAll() + +//mods.iceandfire.lightning_forge.recipeBuilder() +// .input(item('minecraft:gold_ingot'), item('minecraft:gold_ingot')) +// .output(item('minecraft:clay')) +// .register() + +//mods.iceandfire.lightning_forge.recipeBuilder() +// .input(item('minecraft:diamond'), item('minecraft:gold_ingot')) +// .output(item('minecraft:clay')) +// .register() + + diff --git a/examples/postInit/jei.groovy b/examples/postInit/jei.groovy index bf4fa52a5..c17ae6c8b 100644 --- a/examples/postInit/jei.groovy +++ b/examples/postInit/jei.groovy @@ -21,12 +21,12 @@ mods.jei.catalyst.add('minecraft.smelting', item('minecraft:clay') * 8, item('mi mods.jei.category.hideCategory('minecraft.fuel') // mods.jei.category.hideAll() -/*mods.jei.category.categoryBuilder() - .id(classes.GenericRecipeCategory.UID) // Note that `classes.GenericRecipeCategory` must be defined elsewhere, and this example presumes certain fields and methods exist. - .category(guiHelper -> new classes.GenericRecipeCategory(guiHelper)) - .catalyst(item('minecraft:clay')) - .wrapper(classes.GenericRecipeCategory.getRecipeWrappers()) - .register()*/ +//mods.jei.category.categoryBuilder() +// .id(classes.GenericRecipeCategory.UID) // Note that `classes.GenericRecipeCategory` must be defined elsewhere, and this example presumes certain fields and methods exist. +// .category(guiHelper -> new classes.GenericRecipeCategory(guiHelper)) +// .catalyst(item('minecraft:clay')) +// .wrapper(classes.GenericRecipeCategory.getRecipeWrappers()) +// .register() mods.jei.category.setOrder('minecraft.crafting', 'jei.information', 'minecraft.smelting', 'groovyscript:burning', 'groovyscript:explosion', 'groovyscript:fluid_recipe', 'groovyscript:piston_push', 'minecraft.anvil') diff --git a/gradle.properties b/gradle.properties index 6728ffcbb..ac888afbf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -49,6 +49,8 @@ debug_future_mc = false debug_horse_power = false +debug_ice_and_fire_old = false +debug_ice_and_fire_rotn = false debug_immersive_engineering = false debug_immersive_petroleum = false debug_immersive_technology = false diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java index 8b5fe196d..a2e660f2c 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java @@ -33,6 +33,7 @@ import com.cleanroommc.groovyscript.compat.mods.futuremc.FutureMC; import com.cleanroommc.groovyscript.compat.mods.horsepower.HorsePower; import com.cleanroommc.groovyscript.compat.mods.ic2.IC2; +import com.cleanroommc.groovyscript.compat.mods.iceandfire.IceAndFire; import com.cleanroommc.groovyscript.compat.mods.immersiveengineering.ImmersiveEngineering; import com.cleanroommc.groovyscript.compat.mods.immersivepetroleum.ImmersivePetroleum; import com.cleanroommc.groovyscript.compat.mods.immersivetechnology.ImmersiveTechnology; @@ -109,6 +110,7 @@ public class ModSupport { public static final GroovyContainer FORESTRY = new InternalModContainer<>("forestry", "Forestry", Forestry::new); public static final GroovyContainer FUTURE_MC = new InternalModContainer<>("futuremc", "Future MC", FutureMC::new); public static final GroovyContainer HORSE_POWER = new InternalModContainer<>("horsepower", "Horse Power", HorsePower::new); + public static final GroovyContainer ICE_AND_FIRE = new InternalModContainer<>("iceandfire", "Ice And Fire", IceAndFire::new); public static final GroovyContainer IMMERSIVE_ENGINEERING = new InternalModContainer<>("immersiveengineering", "Immersive Engineering", ImmersiveEngineering::new, "ie"); public static final GroovyContainer IMMERSIVE_PETROLEUM = new InternalModContainer<>("immersivepetroleum", "Immersive Petroleum", ImmersivePetroleum::new); public static final GroovyContainer IMMERSIVE_TECHNOLOGY = new InternalModContainer<>("immersivetech", "Immersive Technology", ImmersiveTechnology::new); diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/iceandfire/FireForge.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/iceandfire/FireForge.java new file mode 100644 index 000000000..a99d33ea2 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/iceandfire/FireForge.java @@ -0,0 +1,73 @@ +package com.cleanroommc.groovyscript.compat.mods.iceandfire; + +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.api.documentation.annotations.*; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.registry.StandardListRegistry; +import com.github.alexthe666.iceandfire.recipe.DragonForgeRecipe; +import com.github.alexthe666.iceandfire.recipe.IafRecipeRegistry; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +@RegistryDescription +public class FireForge extends StandardListRegistry { + + @Override + public Collection getRecipes() { + return IafRecipeRegistry.FIRE_FORGE_RECIPES; + } + + @RecipeBuilderDescription(example = { + @Example(".input(item('minecraft:gold_ingot'), item('minecraft:gold_ingot')).output(item('minecraft:clay'))"), + @Example(".input(item('minecraft:diamond'), item('minecraft:clay')).output(item('minecraft:gold_ingot'))") + }) + public RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @MethodDescription(example = { + @Example("item('minecraft:iron_ingot')"), @Example(value = "item('iceandfire:fire_dragon_blood')", commented = true) + }) + public boolean removeByInput(IIngredient input) { + return getRecipes().removeIf(r -> (input.test(r.getInput()) || input.test(r.getBlood())) && doAddBackup(r)); + } + + @MethodDescription(example = @Example(value = "item('iceandfire:dragonsteel_fire_ingot')", commented = true)) + public boolean removeByOutput(IIngredient output) { + return getRecipes().removeIf(r -> output.test(r.getOutput()) && doAddBackup(r)); + } + + @Property(property = "input", comp = @Comp(eq = 2)) + @Property(property = "output", comp = @Comp(eq = 1)) + public static class RecipeBuilder extends AbstractRecipeBuilder { + + @Override + public String getErrorMsg() { + return "Error adding Ice And Fire Fire Forge recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 2, 2, 1, 1); + validateFluids(msg); + } + + @Nullable + @Override + @RecipeBuilderRegistrationMethod + public DragonForgeRecipe register() { + if (!validate()) return null; + DragonForgeRecipe recipe = null; + for (var inputStack : input.get(0).getMatchingStacks()) { + for (var blood : input.get(1).getMatchingStacks()) { + recipe = new DragonForgeRecipe(inputStack, blood, output.get(0)); + ModSupport.ICE_AND_FIRE.get().fireForge.add(recipe); + } + } + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/iceandfire/IceAndFire.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/iceandfire/IceAndFire.java new file mode 100644 index 000000000..37b47c0c3 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/iceandfire/IceAndFire.java @@ -0,0 +1,22 @@ +package com.cleanroommc.groovyscript.compat.mods.iceandfire; + +import com.cleanroommc.groovyscript.compat.mods.GroovyPropertyContainer; +import net.minecraftforge.fml.common.Loader; + +public class IceAndFire extends GroovyPropertyContainer { + + public final FireForge fireForge = new FireForge(); + public final IceForge iceForge = new IceForge(); + public final LightningForge lightningForge; + + public IceAndFire() { + lightningForge = isRotN() ? new LightningForge() : null; + } + + public static boolean isRotN() { + var entry = Loader.instance().getIndexedModList().get("iceandfire"); + if (entry == null) return false; + // Name should be "Ice And Fire: RotN Edition" + return entry.getName().contains("RotN"); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/iceandfire/IceForge.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/iceandfire/IceForge.java new file mode 100644 index 000000000..22790b7eb --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/iceandfire/IceForge.java @@ -0,0 +1,73 @@ +package com.cleanroommc.groovyscript.compat.mods.iceandfire; + +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.api.documentation.annotations.*; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.registry.StandardListRegistry; +import com.github.alexthe666.iceandfire.recipe.DragonForgeRecipe; +import com.github.alexthe666.iceandfire.recipe.IafRecipeRegistry; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +@RegistryDescription +public class IceForge extends StandardListRegistry { + + @Override + public Collection getRecipes() { + return IafRecipeRegistry.ICE_FORGE_RECIPES; + } + + @RecipeBuilderDescription(example = { + @Example(".input(item('minecraft:gold_ingot'), item('minecraft:gold_ingot')).output(item('minecraft:clay'))"), + @Example(".input(item('minecraft:diamond'), item('minecraft:gold_ingot')).output(item('minecraft:clay'))") + }) + public RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @MethodDescription(example = { + @Example("item('minecraft:iron_ingot')"), @Example(value = "item('iceandfire:ice_dragon_blood')", commented = true) + }) + public boolean removeByInput(IIngredient input) { + return getRecipes().removeIf(r -> (input.test(r.getInput()) || input.test(r.getBlood())) && doAddBackup(r)); + } + + @MethodDescription(example = @Example(value = "item('iceandfire:dragonsteel_ice_ingot')", commented = true)) + public boolean removeByOutput(IIngredient output) { + return getRecipes().removeIf(r -> output.test(r.getOutput()) && doAddBackup(r)); + } + + @Property(property = "input", comp = @Comp(eq = 2)) + @Property(property = "output", comp = @Comp(eq = 1)) + public static class RecipeBuilder extends AbstractRecipeBuilder { + + @Override + public String getErrorMsg() { + return "Error adding Ice And Fire Ice Forge recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 2, 2, 1, 1); + validateFluids(msg); + } + + @Nullable + @Override + @RecipeBuilderRegistrationMethod + public DragonForgeRecipe register() { + if (!validate()) return null; + DragonForgeRecipe recipe = null; + for (var inputStack : input.get(0).getMatchingStacks()) { + for (var blood : input.get(1).getMatchingStacks()) { + recipe = new DragonForgeRecipe(inputStack, blood, output.get(0)); + ModSupport.ICE_AND_FIRE.get().iceForge.add(recipe); + } + } + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/iceandfire/LightningForge.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/iceandfire/LightningForge.java new file mode 100644 index 000000000..7659ccdd0 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/iceandfire/LightningForge.java @@ -0,0 +1,74 @@ +package com.cleanroommc.groovyscript.compat.mods.iceandfire; + +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.api.documentation.annotations.*; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.registry.StandardListRegistry; +import com.github.alexthe666.iceandfire.recipe.DragonForgeRecipe; +import com.github.alexthe666.iceandfire.recipe.IafRecipeRegistry; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +// want all the examples to be commented +@RegistryDescription(admonition = @Admonition("groovyscript.wiki.iceandfire.lightning_forge.note")) +public class LightningForge extends StandardListRegistry { + + @Override + public Collection getRecipes() { + return IafRecipeRegistry.LIGHTNING_FORGE_RECIPES; + } + + @RecipeBuilderDescription(example = { + @Example(value = ".input(item('minecraft:gold_ingot'), item('minecraft:gold_ingot')).output(item('minecraft:clay'))", commented = true), + @Example(value = ".input(item('minecraft:diamond'), item('minecraft:gold_ingot')).output(item('minecraft:clay'))", commented = true) + }) + public RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @MethodDescription(example = { + @Example(value = "item('minecraft:iron_ingot')", commented = true), @Example(value = "item('iceandfire:lightning_dragon_blood')", commented = true) + }) + public boolean removeByInput(IIngredient input) { + return getRecipes().removeIf(r -> (input.test(r.getInput()) || input.test(r.getBlood())) && doAddBackup(r)); + } + + @MethodDescription(example = @Example(value = "item('iceandfire:dragonsteel_lightning_ingot')", commented = true)) + public boolean removeByOutput(IIngredient output) { + return getRecipes().removeIf(r -> output.test(r.getOutput()) && doAddBackup(r)); + } + + @Property(property = "input", comp = @Comp(eq = 2)) + @Property(property = "output", comp = @Comp(eq = 1)) + public static class RecipeBuilder extends AbstractRecipeBuilder { + + @Override + public String getErrorMsg() { + return "Error adding Ice And Fire Lightning Forge recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 2, 2, 1, 1); + validateFluids(msg); + } + + @Nullable + @Override + @RecipeBuilderRegistrationMethod + public DragonForgeRecipe register() { + if (!validate()) return null; + DragonForgeRecipe recipe = null; + for (var inputStack : input.get(0).getMatchingStacks()) { + for (var blood : input.get(1).getMatchingStacks()) { + recipe = new DragonForgeRecipe(inputStack, blood, output.get(0)); + ModSupport.ICE_AND_FIRE.get().lightningForge.add(recipe); + } + } + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/documentation/Builder.java b/src/main/java/com/cleanroommc/groovyscript/documentation/Builder.java index 8a2e8986c..862739bf4 100644 --- a/src/main/java/com/cleanroommc/groovyscript/documentation/Builder.java +++ b/src/main/java/com/cleanroommc/groovyscript/documentation/Builder.java @@ -330,7 +330,9 @@ public StringBuilder documentFields() { private String createBuilder(Example example, boolean canBeCommented) { StringBuilder out = new StringBuilder(); - if (canBeCommented && example.commented()) out.append("/*"); + var prependComment = canBeCommented && example.commented(); + + if (prependComment) out.append("//"); if (!example.def().isEmpty()) out.append("def ").append(example.def()).append(" = "); @@ -342,11 +344,9 @@ private String createBuilder(Example example, boolean canBeCommented) { if (!registrationMethods.isEmpty()) out.append(" .").append(String.format("%s()", registrationMethods.get(0).getName())); - if (canBeCommented && example.commented()) out.append("*/"); - - out.append("\n"); + var exampleMethod = prependComment ? out.toString().replace("\n", "\n//") : out.toString(); - return out.toString(); + return exampleMethod + "\n"; } private static class FieldDocumentation implements Comparable { diff --git a/src/main/resources/assets/groovyscript/lang/en_us.lang b/src/main/resources/assets/groovyscript/lang/en_us.lang index 84b9cd6ba..01882f94e 100644 --- a/src/main/resources/assets/groovyscript/lang/en_us.lang +++ b/src/main/resources/assets/groovyscript/lang/en_us.lang @@ -1132,6 +1132,18 @@ groovyscript.wiki.horsepower.press.description=Converts an itemstack into anothe groovyscript.wiki.horsepower.press.add=Adds recipes in the format `input`, `output` +# Ice And Fire +groovyscript.wiki.iceandfire.fire_forge.title=Fire Dragonforge +groovyscript.wiki.iceandfire.fire_forge.description=Converts two input itemstacks into an output itemstack in a multiblock Dragonforge Fire Multiblock while there is a stage 3+ Fire Dragon nearby. + +groovyscript.wiki.iceandfire.ice_forge.title=Ice Dragonforge +groovyscript.wiki.iceandfire.ice_forge.description=Converts two input itemstacks into an output itemstack in a multiblock Dragonforge Ice Multiblock while there is a stage 3+ Ice Dragon nearby. + +groovyscript.wiki.iceandfire.lightning_forge.title=Lightning Dragonforge +groovyscript.wiki.iceandfire.lightning_forge.description=Converts two input itemstacks into an output itemstack in a multiblock Dragonforge Lightning Multiblock while there is a stage 3+ Lightning Dragon nearby. +groovyscript.wiki.iceandfire.lightning_forge.note=Requires [Ice And Fire: RotN edition](https://www.curseforge.com/minecraft/mc-mods/ice-and-fire-rotn-edition) to be installed to be enabled + + # Immersive Engineering groovyscript.wiki.immersiveengineering.alloy_kiln.title=Alloy Kiln groovyscript.wiki.immersiveengineering.alloy_kiln.description=Converts two input itemstacks into an output itemstack, consuming fuel (based on burn time).