diff --git a/dependencies.gradle b/dependencies.gradle index 7496ed163..ae1e1495b 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -78,7 +78,8 @@ final def mod_dependencies = [ 'athenaeum-284350:4633750' : [project.debug_pyrotech], 'pyrotech-306676:4956838' : [project.debug_pyrotech], 'mystical_world-282940:3460961' : [project.debug_roots], - 'patchouli-306770:3162874' : [project.debug_roots, project.debug_natures_aura], + 'patchouli-306770:3162874' : [project.debug_roots, project.debug_natures_aura, project.debug_prodigytech], + 'prodigytech-297414:2769520' : [project.debug_prodigytech], 'roots-246183:3905074' : [project.debug_roots], 'rustic-256141:3107974' : [project.debug_rustic], 'thaumcraft-223628:2629023' : [project.debug_thaum], diff --git a/examples/assets/placeholdername/lang/en_us.lang b/examples/assets/placeholdername/lang/en_us.lang index 7b214ff34..31d5ca7ab 100644 --- a/examples/assets/placeholdername/lang/en_us.lang +++ b/examples/assets/placeholdername/lang/en_us.lang @@ -2,8 +2,21 @@ itemGroup.groovyscript.example_creative_tab=GroovyScript Creative Tab item.placeholdername.heartofauniverse.name=Heart of the Universe item.placeholdername.clay_2.name=If clay is so good... item.placeholdername.clay_3.name=Enchanted Clay +item.placeholdername.prodigy_stick.name=Prodigy Stick item.placeholdername.snack.name=Snack tile.placeholdername.generic_block.name=Generic Block tile.placeholdername.dragon_egg_lamp.name=Dragon Egg Lamp fluid.placeholdername.amongium=Amongium + +# For the prodigy tech example +enchantment.level.11=XI +enchantment.level.12=XII +enchantment.level.13=XIII +enchantment.level.14=XIV +enchantment.level.15=XV +enchantment.level.16=XVI +enchantment.level.17=XVII +enchantment.level.18=XVIII +enchantment.level.19=XIX +enchantment.level.20=XX diff --git a/examples/assets/placeholdername/models/item/prodigy_stick.json b/examples/assets/placeholdername/models/item/prodigy_stick.json new file mode 100644 index 000000000..10bfc9abb --- /dev/null +++ b/examples/assets/placeholdername/models/item/prodigy_stick.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "placeholdername:items/prodigy_stick" + } +} \ No newline at end of file diff --git a/examples/assets/placeholdername/textures/items/prodigy_stick.png b/examples/assets/placeholdername/textures/items/prodigy_stick.png new file mode 100644 index 000000000..a6971ed33 Binary files /dev/null and b/examples/assets/placeholdername/textures/items/prodigy_stick.png differ diff --git a/examples/postInit/prodigytech.groovy b/examples/postInit/prodigytech.groovy new file mode 100644 index 000000000..3120c162f --- /dev/null +++ b/examples/postInit/prodigytech.groovy @@ -0,0 +1,195 @@ + +// Auto generated groovyscript example file +// MODS_LOADED: prodigytech + +println 'mod \'prodigytech\' detected, running script' + +// Atomic Reshaper: +// Uses Hot Air and Primordium to convert items. Can have a weighted random based output. + +mods.prodigytech.atomic_reshaper.removeByInput(ore('paper')) +// mods.prodigytech.atomic_reshaper.removeAll() + +mods.prodigytech.atomic_reshaper.recipeBuilder() + .input(item('minecraft:gold_ingot')) + .output(item('minecraft:emerald_block')) + .primordium(10) + .time(50) + .register() + +mods.prodigytech.atomic_reshaper.recipeBuilder() + .input(item('minecraft:gold_block')) + .output(item('minecraft:diamond_block'), 10) + .output(item('minecraft:carrot'), 3) + .primordium(7) + .register() + + +// Explosion Furnace: +// Uses an explosive, a dampener, and an optional reagent to convert items. The power value of all recipes, all explosives, +// and all dampeners should be close to avoid an efficiency loss. + +// mods.prodigytech.explosion_furnace.removeAll() +mods.prodigytech.explosion_furnace.removeByOutput(item('prodigytech:ferramic_ingot')) + +mods.prodigytech.explosion_furnace.recipeBuilder() + .input(ore('ingotGold'), item('minecraft:diamond')) + .craftPerReagent(8) + .power(160) + .output(item('minecraft:emerald_block')) + .register() + +mods.prodigytech.explosion_furnace.recipeBuilder() + .input(item('minecraft:stone')) + .power(160) + .output(item('minecraft:glowstone')) + .register() + + +// Explosion Furnace Additives: +// Turn an item into an explosive or into a dampener when inserted into the Explosion Furnace. + +// mods.prodigytech.explosion_furnace_additives.removeAllDampeners() +// mods.prodigytech.explosion_furnace_additives.removeAllExplosives() +mods.prodigytech.explosion_furnace_additives.removeDampener(ore('dustAsh')) +mods.prodigytech.explosion_furnace_additives.removeExplosive(ore('gunpowder')) + +mods.prodigytech.explosion_furnace_additives.addDampener(item('minecraft:stone'), 50) +mods.prodigytech.explosion_furnace_additives.addExplosive(item('minecraft:cobblestone'), 50) + +// Heat Sawmill: +// Wood processing machine with 1 input, 2 outputs and an optional chance for the 2nd output. + +mods.prodigytech.heat_sawmill.removeByInput(ore('plankWood')) +// mods.prodigytech.heat_sawmill.removeAll() + +mods.prodigytech.heat_sawmill.recipeBuilder() + .input(item('minecraft:gold_ingot')) + .output(item('minecraft:diamond')) + .time(50) + .register() + +mods.prodigytech.heat_sawmill.recipeBuilder() + .input(item('minecraft:iron_ingot')) + .output(item('minecraft:coal')) + .register() + +mods.prodigytech.heat_sawmill.recipeBuilder() + .input(item('minecraft:iron_block')) + .output(item('minecraft:emerald'), item('minecraft:clay')) + .register() + +mods.prodigytech.heat_sawmill.recipeBuilder() + .input(item('minecraft:gold_block')) + .output(item('minecraft:emerald'), item('minecraft:nether_star')) + .secondaryChance(0.25) + .time(50) + .register() + + +// Magnetic Reassembler: +// A simple 1 to 1 processing machine for dusts. + +mods.prodigytech.magnetic_reassembler.removeByInput(item('minecraft:gravel')) +// mods.prodigytech.magnetic_reassembler.removeAll() + +mods.prodigytech.magnetic_reassembler.recipeBuilder() + .input(item('minecraft:gold_ingot')) + .output(item('minecraft:diamond')) + .time(50) + .register() + +mods.prodigytech.magnetic_reassembler.recipeBuilder() + .input(item('minecraft:iron_ingot')) + .output(item('minecraft:coal')) + .register() + + +// Ore Refinery: +// Ore processing machine with 1 input, 2 outputs and an optional chance for the 2nd output. + +mods.prodigytech.ore_refinery.removeByInput(ore('oreLapis')) +// mods.prodigytech.ore_refinery.removeAll() + +mods.prodigytech.ore_refinery.recipeBuilder() + .input(item('minecraft:gold_ingot')) + .output(item('minecraft:diamond')) + .time(50) + .register() + +mods.prodigytech.ore_refinery.recipeBuilder() + .input(item('minecraft:iron_ingot')) + .output(item('minecraft:coal')) + .register() + +mods.prodigytech.ore_refinery.recipeBuilder() + .input(item('minecraft:iron_block')) + .output(item('minecraft:emerald'), item('minecraft:clay')) + .register() + +mods.prodigytech.ore_refinery.recipeBuilder() + .input(item('minecraft:gold_block')) + .output(item('minecraft:emerald'), item('minecraft:nether_star')) + .secondaryChance(0.25) + .time(50) + .register() + + +// Primordialis Reactor: +// Turns organic matter into Primordium. + +mods.prodigytech.primordialis_reactor.remove(ore('sugarcane')) +// mods.prodigytech.primordialis_reactor.removeAll() + +mods.prodigytech.primordialis_reactor.add(item('minecraft:diamond')) + +// Rotary Grinder: +// A simple 1 to 1 processing machine making dusts. + +mods.prodigytech.rotary_grinder.removeByInput(item('minecraft:gravel')) +// mods.prodigytech.rotary_grinder.removeAll() + +mods.prodigytech.rotary_grinder.recipeBuilder() + .input(item('minecraft:gold_ingot')) + .output(item('minecraft:diamond')) + .time(50) + .register() + +mods.prodigytech.rotary_grinder.recipeBuilder() + .input(item('minecraft:iron_ingot')) + .output(item('minecraft:coal')) + .register() + + +// Solderer: +// Performs recipes using Gold Dust, has a recipe catalyst, and uses up Circuit Boards and an optional extra input for each +// recipe. + +mods.prodigytech.solderer.removeByAdditive(item('minecraft:iron_ingot')) +mods.prodigytech.solderer.removeByOutput(item('prodigytech:circuit_refined')) +mods.prodigytech.solderer.removeByPattern(item('prodigytech:pattern_circuit_refined')) +// mods.prodigytech.solderer.removeAll() +// mods.prodigytech.solderer.removeWithoutAdditive() + +mods.prodigytech.solderer.recipeBuilder() + .pattern(item('minecraft:clay')) + .input(item('minecraft:gold_ingot')) + .output(item('minecraft:diamond')) + .gold(5) + .time(100) + .register() + +mods.prodigytech.solderer.recipeBuilder() + .pattern(item('minecraft:coal_block')) + .output(item('minecraft:nether_star')) + .gold(75) + .register() + + +// Zorra Altar: +// Allows over-enchanting Zorrasteel equipment. + +mods.prodigytech.zorra_altar.addEnchantment('sword', enchantment('minecraft:power'), 10) +mods.prodigytech.zorra_altar.addEnchantment('stick', enchantment('minecraft:knockback'), 20) +mods.prodigytech.zorra_altar.removeEnchantment('sword', enchantment('minecraft:sharpness')) + diff --git a/examples/preInit/prodigytech.groovy b/examples/preInit/prodigytech.groovy new file mode 100644 index 000000000..c0dddae21 --- /dev/null +++ b/examples/preInit/prodigytech.groovy @@ -0,0 +1,21 @@ +// MODS_LOADED: prodigytech + +import lykrast.prodigytech.common.item.IZorrasteelEquipment +import lykrast.prodigytech.common.recipe.ZorraAltarManager + +if (!isLoaded('prodigytech')) return +println 'mod \'prodigytech\' detected, running script' + +// Create an item at the location 'placeholdername:prodigy_stick' enchantable in the Zorra Altar +// Note: due to the PT's implementation it is difficult to make other mod's items enchantable +// This merely registers the item, the post-init script adds the specific enchantments +class ProdigyStick extends Item implements IZorrasteelEquipment { + static registry = mods.prodigytech.zorra_altar.createRegistry('stick') + + ZorraAltarManager getManager() { + return registry + } +} + +content.registerItem('prodigy_stick', new ProdigyStick()) + diff --git a/gradle.properties b/gradle.properties index 88a5d2b50..9b833e877 100644 --- a/gradle.properties +++ b/gradle.properties @@ -42,6 +42,7 @@ debug_lazy_ae2 = false debug_mekanism = false debug_natures_aura = false debug_packmode = false +debug_prodigytech = false debug_projecte = false debug_pyrotech = false debug_roots = false diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 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 56caf140d..e589a4f99 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java @@ -32,6 +32,7 @@ import com.cleanroommc.groovyscript.compat.mods.lazyae2.LazyAE2; import com.cleanroommc.groovyscript.compat.mods.mekanism.Mekanism; import com.cleanroommc.groovyscript.compat.mods.naturesaura.NaturesAura; +import com.cleanroommc.groovyscript.compat.mods.prodigytech.ProdigyTech; import com.cleanroommc.groovyscript.compat.mods.projecte.ProjectE; import com.cleanroommc.groovyscript.compat.mods.pyrotech.PyroTech; import com.cleanroommc.groovyscript.compat.mods.roots.Roots; @@ -92,6 +93,7 @@ public class ModSupport { public static final GroovyContainer MEKANISM = new InternalModContainer<>("mekanism", "Mekanism", Mekanism::new); public static final GroovyContainer LAZYAE2 = new InternalModContainer<>("threng", "LazyAE2", LazyAE2::new, "lazyae2"); public static final GroovyContainer NATURES_AURA = new InternalModContainer<>("naturesaura", "Nature's Aura", NaturesAura::new); + public static final GroovyContainer PRODIGY_TECH = new InternalModContainer<>("prodigytech", "Prodigy Tech", ProdigyTech::new); public static final GroovyContainer PROJECT_E = new InternalModContainer<>("projecte", "ProjectE", ProjectE::new); public static final GroovyContainer PYROTECH = new InternalModContainer<>("pyrotech", "Pyrotech", PyroTech::new); public static final GroovyContainer ROOTS = new InternalModContainer<>("roots", "Roots 3", Roots::new); diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/AtomicReshaper.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/AtomicReshaper.java new file mode 100644 index 000000000..2c439c792 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/AtomicReshaper.java @@ -0,0 +1,193 @@ +package com.cleanroommc.groovyscript.compat.mods.prodigytech; + +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.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import lykrast.prodigytech.common.recipe.AtomicReshaperManager; +import lykrast.prodigytech.common.util.Config; +import net.minecraft.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@RegistryDescription +public class AtomicReshaper extends VirtualizedRegistry { + @RecipeBuilderDescription(example = { + @Example(".input(item('minecraft:gold_ingot')).output(item('minecraft:emerald_block')).primordium(10).time(50)"), + @Example(".input(item('minecraft:gold_block')).output(item('minecraft:diamond_block'), 10).output(item('minecraft:carrot'), 3).primordium(7)") + }) + public AtomicReshaper.RecipeBuilder recipeBuilder() { + return new AtomicReshaper.RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(recipe -> { + if (recipe.isOreRecipe()) { + AtomicReshaperManager.INSTANCE.removeOreRecipe(recipe.getOreInput()); + } else { + AtomicReshaperManager.INSTANCE.removeRecipe(recipe.getInput()); + } + }); + restoreFromBackup().forEach(AtomicReshaperManager.INSTANCE::addRecipe); + } + + @MethodDescription(example = @Example("ore('paper')")) + public boolean removeByInput(IIngredient input) { + if (input instanceof OreDictIngredient) { + AtomicReshaperManager.AtomicReshaperRecipe recipe = AtomicReshaperManager.INSTANCE.removeOreRecipe(((OreDictIngredient) input).getOreDict()); + if (recipe == null) return false; + addBackup(recipe); + return true; + } else { + boolean success = false; + for (ItemStack it : input.getMatchingStacks()) { + AtomicReshaperManager.AtomicReshaperRecipe recipe = AtomicReshaperManager.INSTANCE.removeRecipe(it); + if (recipe != null) { + success = true; + addBackup(recipe); + } + } + return success; + } + } + + private boolean backupAndRemove(AtomicReshaperManager.AtomicReshaperRecipe recipe) { + AtomicReshaperManager.AtomicReshaperRecipe removed; + if (recipe.isOreRecipe()) { + removed = AtomicReshaperManager.INSTANCE.removeOreRecipe(recipe.getOreInput()); + } else { + removed = AtomicReshaperManager.INSTANCE.removeRecipe(recipe.getInput()); + } + if (removed == null) { + return false; + } + addBackup(removed); + return true; + } + + public void add(AtomicReshaperManager.AtomicReshaperRecipe recipe) { + AtomicReshaperManager.INSTANCE.addRecipe(recipe); + addScripted(recipe); + } + + @MethodDescription(priority = 2000, example = @Example(commented = true)) + public void removeAll() { + AtomicReshaperManager.INSTANCE.getAllRecipes().forEach(this::addBackup); + AtomicReshaperManager.INSTANCE.removeAll(); + } + + @MethodDescription(type = MethodDescription.Type.QUERY) + public SimpleObjectStream streamRecipes() { + return new SimpleObjectStream<>(AtomicReshaperManager.INSTANCE.getAllRecipes()) + .setRemover(this::backupAndRemove); + } + + @Property(property = "input", valid = @Comp("1")) + @Property(property = "output", valid = @Comp(value = "1", type = Comp.Type.GTE)) + public static class RecipeBuilder extends AbstractRecipeBuilder { + + @Property(valid = @Comp(value = "1", type = Comp.Type.GTE), defaultValue = "Config.atomicReshaperProcessTime") + private int time = Config.atomicReshaperProcessTime; + + @Property(valid = @Comp(value = "1", type = Comp.Type.GTE)) + private int primordium; + + private final List outputWeights = new ArrayList<>(); + + @RecipeBuilderMethodDescription + public AtomicReshaper.RecipeBuilder time(int time) { + this.time = time; + return this; + } + + @RecipeBuilderMethodDescription + public AtomicReshaper.RecipeBuilder primordium(int primordium) { + this.primordium = primordium; + return this; + } + + public AtomicReshaper.RecipeBuilder output(ItemStack output) { + output(output, 1); + return this; + } + + public AtomicReshaper.RecipeBuilder output(ItemStack... outputs) { + for (ItemStack output : outputs) { + output(output, 1); + } + return this; + } + + public AtomicReshaper.RecipeBuilder output(Collection outputs) { + for (ItemStack output : outputs) { + output(output, 1); + } + return this; + } + + @RecipeBuilderMethodDescription + public AtomicReshaper.RecipeBuilder output(ItemStack output, int weight) { + this.output.add(output); + outputWeights.add(weight); + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding ProdigyTech Atomic Reshaper Recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 1, 1, 1, Integer.MAX_VALUE); + validateFluids(msg); + + // I think this check is not possible to fail at all but still, adding it for consistency + msg.add(output.size() != outputWeights.size(), "Outputs and output weights must be the same size!"); + + msg.add(outputWeights.stream().anyMatch(x -> x <= 0), "all weighted outputs must be greater than 0, yet they were {}", outputWeights); + msg.add(primordium <= 0, "primordium must be greater than or equal to 1, yet it was {}", primordium); + // 100 is hardcoded in the source + int capacity = Config.atomicReshaperMaxPrimordium * 100; + msg.add(primordium > capacity, "primordium must be less than or equal to the Reshaper's capacity {}, yet it was {}", capacity, primordium); + msg.add(time <= 0, "time must be greater than 0, got {}", time); + } + + private Object[] getRecipeOutput() { + List target = new ArrayList<>(); + for (int i = 0; i < output.size(); i++) { + target.add(output.get(i)); + target.add(outputWeights.get(i)); + } + return target.toArray(); + } + + @Override + @RecipeBuilderRegistrationMethod + public @Nullable AtomicReshaperManager.AtomicReshaperRecipe register() { + if (!validate()) return null; + AtomicReshaperManager.AtomicReshaperRecipe recipe = null; + IIngredient inputItem = input.get(0); + if (inputItem instanceof OreDictIngredient) { + String oredict = ((OreDictIngredient) inputItem).getOreDict(); + recipe = new AtomicReshaperManager.AtomicReshaperRecipe(oredict, time, primordium, getRecipeOutput()); + ModSupport.PRODIGY_TECH.get().atomicReshaper.add(recipe); + } else { + for (ItemStack it : inputItem.getMatchingStacks()) { + recipe = new AtomicReshaperManager.AtomicReshaperRecipe(it, time, primordium, getRecipeOutput()); + ModSupport.PRODIGY_TECH.get().atomicReshaper.add(recipe); + } + } + + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/ExplosionFurnace.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/ExplosionFurnace.java new file mode 100644 index 000000000..92a8136b2 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/ExplosionFurnace.java @@ -0,0 +1,127 @@ +package com.cleanroommc.groovyscript.compat.mods.prodigytech; + +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.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import lykrast.prodigytech.common.recipe.ExplosionFurnaceManager; +import net.minecraft.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +@RegistryDescription +public class ExplosionFurnace extends VirtualizedRegistry { + @RecipeBuilderDescription(example = { + @Example(".input(ore('ingotGold'), item('minecraft:diamond')).craftPerReagent(8).power(160).output(item('minecraft:emerald_block'))"), + @Example(".input(item('minecraft:stone')).power(160).output(item('minecraft:glowstone'))") + }) + public ExplosionFurnace.RecipeBuilder recipeBuilder() { + return new ExplosionFurnace.RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(this::remove); + restoreFromBackup().forEach(ExplosionFurnaceManager::addRecipe); + } + + private boolean remove(ExplosionFurnaceManager.ExplosionFurnaceRecipe recipe) { + return ExplosionFurnaceManager.RECIPES.removeIf(recipe::equals); + } + + private boolean backupAndRemove(ExplosionFurnaceManager.ExplosionFurnaceRecipe recipe) { + if (remove(recipe)) { + addBackup(recipe); + return true; + } + return false; + } + + public void addRecipe(ExplosionFurnaceManager.ExplosionFurnaceRecipe x) { + addScripted(x); + ExplosionFurnaceManager.addRecipe(x); + } + + @MethodDescription(example = @Example("item('prodigytech:ferramic_ingot')")) + public void removeByOutput(ItemStack output) { + ExplosionFurnaceManager.RECIPES.removeIf(r -> { + if (!r.getOutput().isItemEqual(output)) return false; + addBackup(r); + return true; + }); + } + + @MethodDescription(example = @Example(priority = 2000, commented = true)) + public void removeAll() { + ExplosionFurnaceManager.RECIPES.forEach(this::addBackup); + ExplosionFurnaceManager.removeAllRecipes(); + } + + @MethodDescription(type = MethodDescription.Type.QUERY) + public SimpleObjectStream streamRecipes() { + return new SimpleObjectStream<>(ExplosionFurnaceManager.RECIPES) + .setRemover(this::backupAndRemove); + } + + @Property(property = "input", valid = {@Comp(type = Comp.Type.GTE, value = "1"), @Comp(type = Comp.Type.LTE, value = "2")}) + @Property(property = "output", valid = @Comp("1")) + public static class RecipeBuilder extends AbstractRecipeBuilder { + + @Property(valid = @Comp(value = "1", type = Comp.Type.GTE)) + private int craftPerReagent = 1; + + @Property(valid = @Comp(value = "1", type = Comp.Type.GTE)) + private int power; + + @RecipeBuilderMethodDescription + public ExplosionFurnace.RecipeBuilder craftPerReagent(int craftPerReagent) { + this.craftPerReagent = craftPerReagent; + return this; + } + + @RecipeBuilderMethodDescription + public ExplosionFurnace.RecipeBuilder power(int power) { + this.power = power; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding ProdigyTech Explosion Furnace Recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 1, 2, 1, 1); + validateFluids(msg); + msg.add(craftPerReagent <= 0, "craftPerReagent should be greater than 0!"); + msg.add(power <= 0, "power should be greater than 0!"); + } + + @Override + @RecipeBuilderRegistrationMethod + public @Nullable ExplosionFurnaceManager.ExplosionFurnaceRecipe register() { + if (!validate()) return null; + ExplosionFurnaceManager.ExplosionFurnaceRecipe recipe = null; + IIngredient inputItem = input.get(0); + // We do not do the OreDict check like in other places as it adds far too much code bloat + if (input.size() == 1) { + for (ItemStack it : inputItem.getMatchingStacks()) { + recipe = new ExplosionFurnaceManager.ExplosionFurnaceRecipe(it, output.get(0), power); + ModSupport.PRODIGY_TECH.get().explosionFurnace.addRecipe(recipe); + } + } else { + for (ItemStack inp : inputItem.getMatchingStacks()) { + for (ItemStack rea : input.get(1).getMatchingStacks()) { + recipe = new ExplosionFurnaceManager.ExplosionFurnaceRecipe(inp, output.get(0), power, rea, craftPerReagent); + ModSupport.PRODIGY_TECH.get().explosionFurnace.addRecipe(recipe); + } + } + } + + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/ExplosionFurnaceAdditives.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/ExplosionFurnaceAdditives.java new file mode 100644 index 000000000..e07c5c34f --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/ExplosionFurnaceAdditives.java @@ -0,0 +1,136 @@ +package com.cleanroommc.groovyscript.compat.mods.prodigytech; + +import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.api.documentation.annotations.Example; +import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription; +import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription; +import com.cleanroommc.groovyscript.helper.ingredient.ItemsIngredient; +import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import com.github.bsideup.jabel.Desugar; +import lykrast.prodigytech.common.recipe.ExplosionFurnaceManager; +import net.minecraft.item.ItemStack; + +@RegistryDescription(category = RegistryDescription.Category.ENTRIES) +public class ExplosionFurnaceAdditives extends VirtualizedRegistry { + @Override + public void onReload() { + removeScripted().forEach(EFAdditiveRecipe::unregister); + restoreFromBackup().forEach(EFAdditiveRecipe::register); + } + + private void add(EFAdditiveRecipe recipe) { + recipe.register(); + addScripted(recipe); + } + + private void remove(EFAdditiveRecipe recipe) { + recipe.unregister(); + addBackup(recipe); + } + + @MethodDescription(example = @Example("item('minecraft:cobblestone'), 50"), type = MethodDescription.Type.ADDITION) + public void addExplosive(IIngredient explosive, int power) { + EFAdditiveRecipe recipe = new EFAdditiveExplosive(explosive, power); + add(recipe); + } + + @MethodDescription(example = @Example("ore('gunpowder')")) + public boolean removeExplosive(IIngredient explosive) { + for (ItemStack it : explosive.getMatchingStacks()) { + ExplosionFurnaceManager.Explosive externalExplosive = ExplosionFurnaceManager.findExplosive(it); + if (externalExplosive == null) continue; + EFAdditiveRecipe recipe = new EFAdditiveExplosive(explosive, externalExplosive.getPower()); + remove(recipe); + return true; + } + return false; + } + + @MethodDescription(example = @Example(priority = 2000, commented = true)) + public void removeAllExplosives() { + ExplosionFurnaceManager.EXPLOSIVES.getAllContent().forEach(r -> + addBackup(new EFAdditiveExplosive(new ItemsIngredient(r.getMatchingStacks()), r.getPower()))); + ExplosionFurnaceManager.removeAllExplosives(); + } + + @MethodDescription(example = @Example("item('minecraft:stone'), 50"), type = MethodDescription.Type.ADDITION) + public void addDampener(IIngredient dampener, int power) { + EFAdditiveRecipe recipe = new EFAdditiveDampener(dampener, power); + add(recipe); + } + + @MethodDescription(example = @Example("ore('dustAsh')")) + public boolean removeDampener(IIngredient dampener) { + for (ItemStack it : dampener.getMatchingStacks()) { + ExplosionFurnaceManager.Dampener externalDampener = ExplosionFurnaceManager.findDampener(it); + if (externalDampener == null) continue; + EFAdditiveRecipe recipe = new EFAdditiveDampener(dampener, externalDampener.getDampening()); + remove(recipe); + return true; + } + return false; + } + + @MethodDescription(example = @Example(priority = 2000, commented = true)) + public void removeAllDampeners() { + ExplosionFurnaceManager.DAMPENERS.getAllContent().forEach(r -> + addBackup(new EFAdditiveDampener(new ItemsIngredient(r.getMatchingStacks()), r.getDampening()))); + ExplosionFurnaceManager.removeAllDampeners(); + } + + public interface EFAdditiveRecipe { + void register(); + void unregister(); + } + + @Desugar + public record EFAdditiveExplosive(IIngredient input, int value) implements EFAdditiveRecipe { + @Override + public void register() { + if (this.input instanceof OreDictIngredient) { + ExplosionFurnaceManager.addExplosive(((OreDictIngredient) this.input).getOreDict(), this.value); + } else { + for (ItemStack it : this.input.getMatchingStacks()) { + ExplosionFurnaceManager.addExplosive(it, this.value); + } + } + } + + @Override + public void unregister() { + if (this.input instanceof OreDictIngredient) { + ExplosionFurnaceManager.removeExplosive(((OreDictIngredient) this.input).getOreDict()); + } else { + for (ItemStack it : this.input.getMatchingStacks()) { + ExplosionFurnaceManager.removeExplosive(it); + } + } + } + } + + @Desugar + public record EFAdditiveDampener(IIngredient input, int value) implements EFAdditiveRecipe { + @Override + public void register() { + if (this.input instanceof OreDictIngredient) { + ExplosionFurnaceManager.addDampener(((OreDictIngredient) this.input).getOreDict(), this.value); + } else { + for (ItemStack it : this.input.getMatchingStacks()) { + ExplosionFurnaceManager.addDampener(it, this.value); + } + } + } + + @Override + public void unregister() { + if (this.input instanceof OreDictIngredient) { + ExplosionFurnaceManager.removeDampener(((OreDictIngredient) this.input).getOreDict()); + } else { + for (ItemStack it : this.input.getMatchingStacks()) { + ExplosionFurnaceManager.removeDampener(it); + } + } + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/PrimordialisReactor.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/PrimordialisReactor.java new file mode 100644 index 000000000..db61d4005 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/PrimordialisReactor.java @@ -0,0 +1,76 @@ +package com.cleanroommc.groovyscript.compat.mods.prodigytech; + +import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.api.documentation.annotations.Example; +import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription; +import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.ingredient.ItemsIngredient; +import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import lykrast.prodigytech.common.recipe.PrimordialisReactorManager; +import net.minecraft.item.ItemStack; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@RegistryDescription(category = RegistryDescription.Category.ENTRIES) +public class PrimordialisReactor extends VirtualizedRegistry { + @Override + public void onReload() { + removeScripted().forEach(this::removeRecipeBase); + restoreFromBackup().forEach(this::addRecipeBase); + } + + private void addRecipeBase(IIngredient x) { + if (x instanceof OreDictIngredient) { + PrimordialisReactorManager.addInput(((OreDictIngredient) x).getOreDict()); + } else { + for (ItemStack it : x.getMatchingStacks()) { + PrimordialisReactorManager.addInput(it); + } + } + } + + private boolean removeRecipeBase(IIngredient x) { + if (x instanceof OreDictIngredient) { + PrimordialisReactorManager.removeInput(((OreDictIngredient) x).getOreDict()); + } else { + for (ItemStack it : x.getMatchingStacks()) { + PrimordialisReactorManager.removeInput(it); + } + } + // the mod's API does not expose a boolean there + return true; + } + + @MethodDescription(example = @Example("item('minecraft:diamond')"), type = MethodDescription.Type.ADDITION) + public void add(IIngredient x) { + addScripted(x); + addRecipeBase(x); + } + + @MethodDescription(example = @Example("ore('sugarcane')")) + public boolean remove(IIngredient x) { + addBackup(x); + return removeRecipeBase(x); + } + + @MethodDescription(example = @Example(priority = 2000, commented = true)) + public void removeAll() { + PrimordialisReactorManager.getAllEntries().forEach(r -> addBackup(new ItemsIngredient(r))); + PrimordialisReactorManager.getAllOreEntries().forEach(r -> addBackup(new OreDictIngredient(r))); + PrimordialisReactorManager.removeAll(); + } + + @MethodDescription(type = MethodDescription.Type.QUERY) + public SimpleObjectStream streamRecipes() { + Stream normalRecipes = PrimordialisReactorManager.getAllEntries().stream() + .map(ItemsIngredient::new); + Stream oreDictRecipes = PrimordialisReactorManager.getAllOreEntries().stream() + .map(OreDictIngredient::new); + List items = Stream.concat(normalRecipes, oreDictRecipes).collect(Collectors.toList()); + return new SimpleObjectStream<>(items).setRemover(this::remove); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/ProdigyTech.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/ProdigyTech.java new file mode 100644 index 000000000..306f891b6 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/ProdigyTech.java @@ -0,0 +1,30 @@ +package com.cleanroommc.groovyscript.compat.mods.prodigytech; + +import com.cleanroommc.groovyscript.compat.mods.ModPropertyContainer; + +public class ProdigyTech extends ModPropertyContainer { + public final AtomicReshaper atomicReshaper = new AtomicReshaper(); + public final ExplosionFurnace explosionFurnace = new ExplosionFurnace(); + public final ExplosionFurnaceAdditives explosionAdditives = new ExplosionFurnaceAdditives(); + public final SimpleRecipeHandler magneticReassembler = new SimpleRecipeHandler.MagneticReassembler(); + public final SimpleRecipeHandlerSecondaryOutput oreRefinery = new SimpleRecipeHandlerSecondaryOutput.OreRefinery(); + public final SimpleRecipeHandler grinder = new SimpleRecipeHandler.RotaryGrinder(); + public final PrimordialisReactor primordialisReactor = new PrimordialisReactor(); + public final SimpleRecipeHandlerSecondaryOutput sawmill = new SimpleRecipeHandlerSecondaryOutput.HeatSawmill(); + public final Solderer solderer = new Solderer(); + public final ZorraAltar zorraAltar = new ZorraAltar(); + + public ProdigyTech() { + addRegistry(atomicReshaper); + addRegistry(explosionFurnace); + addRegistry(explosionAdditives); + addRegistry(magneticReassembler); + addRegistry(oreRefinery); + addRegistry(grinder); + addRegistry(primordialisReactor); + addRegistry(sawmill); + addRegistry(solderer); + addRegistry(zorraAltar); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandler.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandler.java new file mode 100644 index 000000000..afc195e55 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandler.java @@ -0,0 +1,107 @@ +package com.cleanroommc.groovyscript.compat.mods.prodigytech; + +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.api.documentation.annotations.*; +import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import lykrast.prodigytech.common.recipe.MagneticReassemblerManager; +import lykrast.prodigytech.common.recipe.RotaryGrinderManager; +import lykrast.prodigytech.common.recipe.SimpleRecipe; +import lykrast.prodigytech.common.recipe.SimpleRecipeManager; +import lykrast.prodigytech.common.util.Config; +import net.minecraft.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +public abstract class SimpleRecipeHandler extends SimpleRecipeHandlerAbstract { + @RecipeBuilderDescription(example = { + @Example(".input(item('minecraft:gold_ingot')).output(item('minecraft:diamond')).time(50)"), + @Example(".input(item('minecraft:iron_ingot')).output(item('minecraft:coal'))") + }) + public SimpleRecipeHandler.RecipeBuilder recipeBuilder() { + return new SimpleRecipeHandler.RecipeBuilder(); + } + + SimpleRecipeHandler(String name, SimpleRecipeManager instance) { + super(name, instance); + } + + @Property(property = "input", valid = @Comp("1")) + @Property(property = "output", valid = @Comp("1")) + public class RecipeBuilder extends AbstractRecipeBuilder { + @Property(valid = @Comp(value = "1", type = Comp.Type.GTE), defaultValue = "(default time for this machine in the mod's config)") + private int time = getDefaultTime(); + + @RecipeBuilderMethodDescription + public RecipeBuilder time(int time) { + this.time = time; + return this; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 1, 1, 1, 1); + validateFluids(msg); + msg.add(time <= 0, "time must be greater than 0, got {}", time); + } + + @Override + public String getErrorMsg() { + return String.format("Error adding ProdigyTech %s Recipe", SimpleRecipeHandler.this.name); + } + + @Override + @RecipeBuilderRegistrationMethod + public @Nullable SimpleRecipe register() { + if (!validate()) return null; + SimpleRecipe recipe = null; + IIngredient input1 = input.get(0); + if (input1 instanceof OreDictIngredient) { + recipe = new SimpleRecipe(((OreDictIngredient) input1).getOreDict(), output.get(0), time); + addRecipe(recipe); + } else { + for (ItemStack input : input1.getMatchingStacks()) { + recipe = new SimpleRecipe(input, output.get(0), time); + addRecipe(recipe); + } + } + return recipe; + } + } + + @RegistryDescription + public static class RotaryGrinder extends SimpleRecipeHandler { + RotaryGrinder() { + super("Rotary Grinder", RotaryGrinderManager.INSTANCE); + } + + @Override + protected int getDefaultTime() { + return Config.rotaryGrinderProcessTime; + } + + @Override + @MethodDescription(example = @Example("item('minecraft:gravel')")) + public boolean removeByInput(IIngredient input) { + return super.removeByInput(input); + } + } + + @RegistryDescription + public static class MagneticReassembler extends SimpleRecipeHandler { + MagneticReassembler() { + super("Magnetic Reassembler", MagneticReassemblerManager.INSTANCE); + } + + @Override + protected int getDefaultTime() { + return Config.magneticReassemblerProcessTime; + } + + @Override + @MethodDescription(example = @Example("item('minecraft:gravel')")) + public boolean removeByInput(IIngredient input) { + return super.removeByInput(input); + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandlerAbstract.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandlerAbstract.java new file mode 100644 index 000000000..21a77982d --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandlerAbstract.java @@ -0,0 +1,98 @@ +package com.cleanroommc.groovyscript.compat.mods.prodigytech; + +import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.api.documentation.annotations.Example; +import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import lykrast.prodigytech.common.recipe.SimpleRecipe; +import lykrast.prodigytech.common.recipe.SimpleRecipeManagerAbstract; +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.OreDictionary; + +public abstract class SimpleRecipeHandlerAbstract extends VirtualizedRegistry { + private final SimpleRecipeManagerAbstract instance; + protected final String name; + + SimpleRecipeHandlerAbstract(String name, SimpleRecipeManagerAbstract instance) { + this.instance = instance; + this.name = name; + } + + protected abstract int getDefaultTime(); + + @Override + public void onReload() { + removeScripted().forEach(x -> instance.removeRecipe(x.getInput())); + restoreFromBackup().forEach(instance::addRecipe); + } + + public void addRecipe(T recipe) { + addScripted(recipe); + instance.addRecipe(recipe); + } + + public boolean removeStackRecipe(ItemStack input) { + T removed = instance.removeRecipe(input); + if (removed != null) { + addBackup(removed); + return true; + } + // Try to remove the recipe through its OreDict + for (int oreDictId : OreDictionary.getOreIDs(input)) { + String oreDict = OreDictionary.getOreName(oreDictId); + removed = instance.removeOreRecipe(oreDict); + if (removed != null) { + addBackup(removed); + return true; + } + } + return false; + } + + public boolean removeOreRecipe(String input) { + T removed = instance.removeOreRecipe(input); + if (removed == null) return false; + addBackup(removed); + return true; + } + + public boolean removeByInput(IIngredient input) { + if (input instanceof OreDictIngredient) { + return removeOreRecipe(((OreDictIngredient) input).getOreDict()); + } else { + boolean removed = false; + for (ItemStack it : input.getMatchingStacks()) { + removed |= removeStackRecipe(it); + } + return removed; + } + } + + @MethodDescription(priority = 2000, example = @Example(commented = true)) + public void removeAll() { + instance.getAllRecipes().forEach(this::addBackup); + instance.removeAll(); + } + + private boolean backupAndRemove(T recipe) { + T removed; + if (recipe.isOreRecipe()) { + removed = instance.removeOreRecipe(recipe.getOreInput()); + } else { + removed = instance.removeRecipe(recipe.getInput()); + } + if (removed == null) { + return false; + } + addBackup(removed); + return true; + } + + @MethodDescription(type = MethodDescription.Type.QUERY) + public SimpleObjectStream streamRecipes() { + return new SimpleObjectStream<>(instance.getAllRecipes()) + .setRemover(this::backupAndRemove); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandlerSecondaryOutput.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandlerSecondaryOutput.java new file mode 100644 index 000000000..bf86f63e3 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandlerSecondaryOutput.java @@ -0,0 +1,117 @@ +package com.cleanroommc.groovyscript.compat.mods.prodigytech; + +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.api.documentation.annotations.*; +import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import lykrast.prodigytech.common.recipe.*; +import lykrast.prodigytech.common.util.Config; +import net.minecraft.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +public abstract class SimpleRecipeHandlerSecondaryOutput extends SimpleRecipeHandlerAbstract { + @RecipeBuilderDescription(example = { + @Example(".input(item('minecraft:gold_ingot')).output(item('minecraft:diamond')).time(50)"), + @Example(".input(item('minecraft:iron_ingot')).output(item('minecraft:coal'))"), + @Example(".input(item('minecraft:iron_block')).output(item('minecraft:emerald'), item('minecraft:clay'))"), + @Example(".input(item('minecraft:gold_block')).output(item('minecraft:emerald'), item('minecraft:nether_star')).secondaryChance(0.25).time(50)") + }) + public SimpleRecipeHandlerSecondaryOutput.RecipeBuilder recipeBuilder() { + return new SimpleRecipeHandlerSecondaryOutput.RecipeBuilder(); + } + + SimpleRecipeHandlerSecondaryOutput(String name, SimpleRecipeManagerSecondaryOutput instance) { + super(name, instance); + } + + @Property(property = "input", valid = @Comp("1")) + @Property(property = "output", valid = {@Comp(value = "1", type = Comp.Type.GTE), @Comp(value = "2", type = Comp.Type.LTE)}) + public class RecipeBuilder extends AbstractRecipeBuilder { + @Property(valid = @Comp(value = "1", type = Comp.Type.GTE)) + private int time = getDefaultTime(); + + @Property(valid = @Comp(value = "1", type = Comp.Type.LTE), defaultValue = "1.0f") + private float secondaryChance = 1.0f; + + @RecipeBuilderMethodDescription + public SimpleRecipeHandlerSecondaryOutput.RecipeBuilder time(int time) { + this.time = time; + return this; + } + + @RecipeBuilderMethodDescription + public SimpleRecipeHandlerSecondaryOutput.RecipeBuilder secondaryChance(float secondaryOutput) { + this.secondaryChance = secondaryOutput; + return this; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 1, 1, 1, 2); + validateFluids(msg); + msg.add(time <= 0, "time must be greater than 0, got {}", time); + msg.add(secondaryChance > 1.0f || secondaryChance < 0.0f, "secondary output has to be between 0 and 1, got {}", secondaryChance); + } + + @Override + public String getErrorMsg() { + return String.format("Error adding ProdigyTech %s Recipe", SimpleRecipeHandlerSecondaryOutput.this.name); + } + + @Override + @RecipeBuilderRegistrationMethod + public @Nullable SimpleRecipeSecondaryOutput register() { + if (!validate()) return null; + SimpleRecipeSecondaryOutput recipe = null; + IIngredient input1 = input.get(0); + ItemStack secondaryOutput = output.size() == 1 ? ItemStack.EMPTY : output.get(1); + if (input1 instanceof OreDictIngredient) { + recipe = new SimpleRecipeSecondaryOutput(((OreDictIngredient) input1).getOreDict(), output.get(0), secondaryOutput, time, secondaryChance); + addRecipe(recipe); + } else { + for (ItemStack input : input1.getMatchingStacks()) { + recipe = new SimpleRecipeSecondaryOutput(input, output.get(0), secondaryOutput, time, secondaryChance); + addRecipe(recipe); + } + } + return recipe; + } + } + + @RegistryDescription + public static class HeatSawmill extends SimpleRecipeHandlerSecondaryOutput { + HeatSawmill() { + super("Heat Sawmill", HeatSawmillManager.INSTANCE); + } + + @Override + protected int getDefaultTime() { + return Config.heatSawmillProcessTime; + } + + @Override + @MethodDescription(example = @Example("ore('plankWood')")) + public boolean removeByInput(IIngredient input) { + return super.removeByInput(input); + } + } + + @RegistryDescription + public static class OreRefinery extends SimpleRecipeHandlerSecondaryOutput { + OreRefinery() { + super("Ore Refinery", OreRefineryManager.INSTANCE); + } + + @Override + protected int getDefaultTime() { + return Config.oreRefineryProcessTime; + } + + @Override + @MethodDescription(example = @Example("ore('oreLapis')")) + public boolean removeByInput(IIngredient input) { + return super.removeByInput(input); + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/Solderer.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/Solderer.java new file mode 100644 index 000000000..031b3e79b --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/Solderer.java @@ -0,0 +1,168 @@ +package com.cleanroommc.groovyscript.compat.mods.prodigytech; + +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.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import lykrast.prodigytech.common.recipe.SoldererManager; +import lykrast.prodigytech.common.util.Config; +import net.minecraft.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +@RegistryDescription +public class Solderer extends VirtualizedRegistry { + + @RecipeBuilderDescription(example = { + @Example(".pattern(item('minecraft:clay')).input(item('minecraft:gold_ingot')).output(item('minecraft:diamond')).gold(5).time(100)"), + @Example(".pattern(item('minecraft:coal_block')).output(item('minecraft:nether_star')).gold(75)"), + }) + public Solderer.RecipeBuilder recipeBuilder() { + return new Solderer.RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(x -> SoldererManager.removeRecipe(x.getPattern(), x.getAdditive(), 9999)); + restoreFromBackup().forEach(SoldererManager::addRecipe); + } + + public void add(SoldererManager.SoldererRecipe recipe) { + if (recipe == null) return; + addScripted(recipe); + SoldererManager.addRecipe(recipe); + } + + public boolean remove(SoldererManager.SoldererRecipe recipe) { + if (recipe == null) return false; + addBackup(recipe); + return SoldererManager.removeRecipe(recipe.getPattern(), recipe.getAdditive(), 9999) != null; + } + + @MethodDescription(example = @Example("item('prodigytech:pattern_circuit_refined')")) + public boolean removeByPattern(IIngredient pattern) { + return SoldererManager.RECIPES.removeIf(r -> { + if (pattern.test(r.getPattern())) { + addBackup(r); + return true; + } + return false; + }); + } + + @MethodDescription(example = @Example("item('minecraft:iron_ingot')")) + public boolean removeByAdditive(IIngredient additive) { + return SoldererManager.RECIPES.removeIf(r -> { + if (r.requiresAdditive() && additive.test(r.getPattern())) { + addBackup(r); + return true; + } + return false; + }); + } + + @MethodDescription(example = @Example("item('prodigytech:circuit_refined')")) + public boolean removeByOutput(IIngredient output) { + return SoldererManager.RECIPES.removeIf(r -> { + if (output.test(r.getPattern())) { + addBackup(r); + return true; + } + return false; + }); + } + + @MethodDescription(priority = 2000, example = @Example(commented = true)) + public void removeAll() { + SoldererManager.RECIPES.forEach(this::addBackup); + SoldererManager.removeAll(); + } + + @MethodDescription(priority = 2000, example = @Example(commented = true)) + public void removeWithoutAdditive() { + SoldererManager.RECIPES.removeIf(r -> { + if (r.requiresAdditive()) return false; + addBackup(r); + return true; + }); + } + + @MethodDescription(type = MethodDescription.Type.QUERY) + public SimpleObjectStream streamRecipes() { + return new SimpleObjectStream<>(SoldererManager.RECIPES) + .setRemover(this::remove); + } + + @Property(property = "input", valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "1")}) + @Property(property = "output", valid = @Comp("1")) + public static class RecipeBuilder extends AbstractRecipeBuilder { + + @Property(valid = @Comp(value = "1", type = Comp.Type.GTE)) + private int time = Config.soldererProcessTime; + + @Property(valid = @Comp(value = "1", type = Comp.Type.GTE)) + private int gold; + + @Property(valid = @Comp("1")) + private IIngredient pattern; + + @RecipeBuilderMethodDescription + public Solderer.RecipeBuilder time(int time) { + this.time = time; + return this; + } + + @RecipeBuilderMethodDescription + public Solderer.RecipeBuilder gold(int gold) { + this.gold = gold; + return this; + } + + @RecipeBuilderMethodDescription + public Solderer.RecipeBuilder pattern(IIngredient pattern) { + this.pattern = pattern; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding ProdigyTech Solderer Recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 0, 1, 1, 1); + validateFluids(msg); + msg.add(gold <= 0, "gold must be greater than or equal to 1, yet it was {}", gold); + msg.add(IngredientHelper.isEmpty(pattern), "pattern cannot be empty"); + int capacity = Config.soldererMaxGold; + msg.add(gold > capacity, "gold must be less than or equal to the Solderer's capacity {}, yet it was {}", capacity, gold); + msg.add(time <= 0, "time must be greater than 0, got {}", time); + } + + @Override + @RecipeBuilderRegistrationMethod + public @Nullable SoldererManager.SoldererRecipe register() { + if (!validate()) return null; + SoldererManager.SoldererRecipe recipe = null; + for (ItemStack pat : pattern.getMatchingStacks()) { + if (input.isEmpty()) { + SoldererManager.SoldererRecipe theRecipe = new SoldererManager.SoldererRecipe(pat, ItemStack.EMPTY, output.get(0), gold, time); + ModSupport.PRODIGY_TECH.get().solderer.add(theRecipe); + if (recipe == null) recipe = theRecipe; + } else { + for (ItemStack additive : input.get(0).getMatchingStacks()) { + SoldererManager.SoldererRecipe theRecipe = new SoldererManager.SoldererRecipe(pat, additive, output.get(0), gold, time); + ModSupport.PRODIGY_TECH.get().solderer.add(theRecipe); + if (recipe == null) recipe = theRecipe; + } + } + } + + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/ZorraAltar.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/ZorraAltar.java new file mode 100644 index 000000000..4b48d52ba --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/ZorraAltar.java @@ -0,0 +1,76 @@ +package com.cleanroommc.groovyscript.compat.mods.prodigytech; + +import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.cleanroommc.groovyscript.api.documentation.annotations.Example; +import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription; +import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import com.github.bsideup.jabel.Desugar; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import lykrast.prodigytech.common.recipe.ZorraAltarManager; +import lykrast.prodigytech.common.util.Config; +import net.minecraft.enchantment.Enchantment; + +import java.util.Map; + + +@RegistryDescription +public class ZorraAltar extends VirtualizedRegistry { + @GroovyBlacklist + private static final Map managers = new Object2ObjectOpenHashMap<>(); + + ZorraAltar() { + managers.put("sword", ZorraAltarManager.SWORD); + managers.put("bow", ZorraAltarManager.BOW); + } + + public ZorraAltarManager createRegistry(String key) { + ZorraAltarManager manager = new ZorraAltarManager(); + managers.put(key, manager); + return manager; + } + + public ZorraAltarManager getRegistry(String key) { + return managers.get(key); + } + + @GroovyBlacklist + public void onReload() { + removeScripted().forEach(this::removeEnchantment); + restoreFromBackup().forEach(this::addEnchantment); + } + + private void addEnchantment(ZorraRecipeData recipe) { + if (!managers.containsKey(recipe.registry)) return; + managers.get(recipe.registry).addEnchant(recipe.enchantment, recipe.maxLevel); + } + + private void removeEnchantment(ZorraRecipeData recipe) { + if (!managers.containsKey(recipe.registry)) return; + managers.get(recipe.registry).removeEnchant(recipe.enchantment); + } + + @MethodDescription(example = { + @Example("'sword', enchantment('minecraft:power'), 10"), + @Example("'stick', enchantment('minecraft:knockback'), 20") + }) + public void addEnchantment(String registry, Enchantment enchantment, int maxLevel) { + if (!managers.containsKey(registry)) return; + managers.get(registry).addEnchant(enchantment, maxLevel); + addScripted(new ZorraRecipeData(registry, enchantment, maxLevel)); + } + + @MethodDescription(example = @Example("'sword', enchantment('minecraft:sharpness')")) + public boolean removeEnchantment(String registry, Enchantment enchantment) { + if (!managers.containsKey(registry)) return false; + int maxLevel = enchantment.getMaxLevel(); + if (maxLevel > 1) + maxLevel += Config.altarBonusLvl; + addBackup(new ZorraRecipeData(registry, enchantment, maxLevel)); + return managers.get(registry).removeEnchant(enchantment); + } + + @Desugar + public record ZorraRecipeData(String registry, Enchantment enchantment, int maxLevel) {} +} diff --git a/src/main/resources/assets/groovyscript/lang/en_us.lang b/src/main/resources/assets/groovyscript/lang/en_us.lang index e7eb00d5a..d3a5ab9ec 100644 --- a/src/main/resources/assets/groovyscript/lang/en_us.lang +++ b/src/main/resources/assets/groovyscript/lang/en_us.lang @@ -1265,6 +1265,126 @@ groovyscript.wiki.naturesaura.spawning.entity.value=Sets the entity spawned groovyscript.wiki.naturesaura.spawning.removeByEntity=Removes all Altar of Birthing recipes that summon the given entity groovyscript.wiki.naturesaura.spawning.removeByName=Removes the Altar of Birthing recipe with the given name +# ProdigyTech +groovyscript.wiki.prodigytech.atomic_reshaper.title=Atomic Reshaper +groovyscript.wiki.prodigytech.atomic_reshaper.description=Uses Hot Air and Primordium to convert items. Can have a weighted random based output. +groovyscript.wiki.prodigytech.atomic_reshaper.time.value=The time needed to perform the recipe, in ticks. Will run faster than this number when heated over 250 C. +groovyscript.wiki.prodigytech.atomic_reshaper.primordium.value=The amount of Primordium units consumed by this recipe. 1 Primordium equals 100 Primordium units. + +groovyscript.wiki.prodigytech.explosion_furnace.title=Explosion Furnace +groovyscript.wiki.prodigytech.explosion_furnace.description=Uses an explosive, a dampener, and an optional reagent to convert items. The power value of all recipes, all explosives, and all dampeners should be close to avoid an efficiency loss. +groovyscript.wiki.prodigytech.explosion_furnace.power.value=Sets the power used by this recipe. +groovyscript.wiki.prodigytech.explosion_furnace.craftPerReagent.value=Sets the number of input items that can be converted with 1 reagent. + +groovyscript.wiki.prodigytech.explosion_furnace_additives.title=Explosion Furnace Additives +groovyscript.wiki.prodigytech.explosion_furnace_additives.description=Turn an item into an explosive or into a dampener when inserted into the Explosion Furnace. +groovyscript.wiki.prodigytech.explosion_furnace_additives.addDampener=Adds a dampener. +groovyscript.wiki.prodigytech.explosion_furnace_additives.addExplosive=Adds an explosive. +groovyscript.wiki.prodigytech.explosion_furnace_additives.removeAllDampeners=Removes all registered dampeners. +groovyscript.wiki.prodigytech.explosion_furnace_additives.removeAllExplosives=Removes all registered explosives. +groovyscript.wiki.prodigytech.explosion_furnace_additives.removeDampener=Removes a dampener by the input item. +groovyscript.wiki.prodigytech.explosion_furnace_additives.removeExplosive=Removes an explosive by the input item. + +groovyscript.wiki.prodigytech.heat_sawmill.title=Heat Sawmill +groovyscript.wiki.prodigytech.heat_sawmill.description=Wood processing machine with 1 input, 2 outputs and an optional chance for the 2nd output. +groovyscript.wiki.prodigytech.heat_sawmill.time.value=The time needed to perform the recipe, in ticks. Will run faster than this number when heated over 80 C. +groovyscript.wiki.prodigytech.heat_sawmill.secondaryChance.value=Sets the chance to get the 2nd output. + +groovyscript.wiki.prodigytech.magnetic_reassembler.title=Magnetic Reassembler +groovyscript.wiki.prodigytech.magnetic_reassembler.description=A simple 1 to 1 processing machine for dusts. +groovyscript.wiki.prodigytech.magnetic_reassembler.time.value=The time needed to perform the recipe, in ticks. Will run faster than this number when heated over 125 C. + +groovyscript.wiki.prodigytech.ore_refinery.title=Ore Refinery +groovyscript.wiki.prodigytech.ore_refinery.description=Ore processing machine with 1 input, 2 outputs and an optional chance for the 2nd output. +groovyscript.wiki.prodigytech.ore_refinery.time.value=The time needed to perform the recipe, in ticks. Will run faster than this number when heated over 125 C. +groovyscript.wiki.prodigytech.ore_refinery.secondaryChance.value=Sets the chance to get the 2nd output. + +groovyscript.wiki.prodigytech.primordialis_reactor.title=Primordialis Reactor +groovyscript.wiki.prodigytech.primordialis_reactor.description=Turns organic matter into Primordium. +groovyscript.wiki.prodigytech.primordialis_reactor.add=Adds an item that can be converted. +groovyscript.wiki.prodigytech.primordialis_reactor.remove=Removes an item that can be converted. + +groovyscript.wiki.prodigytech.rotary_grinder.title=Rotary Grinder +groovyscript.wiki.prodigytech.rotary_grinder.description=A simple 1 to 1 processing machine making dusts. +groovyscript.wiki.prodigytech.rotary_grinder.time.value=The time needed to perform the recipe, in ticks. Will run faster than this number when heated over 80 C. + +groovyscript.wiki.prodigytech.solderer.title=Solderer +groovyscript.wiki.prodigytech.solderer.description=Performs recipes using Gold Dust, has a recipe catalyst, and uses up Circuit Boards and an optional extra input for each recipe. +groovyscript.wiki.prodigytech.solderer.gold.value=Sets the number of Tiny Gold Dusts needed for the recipe (9 equals 1 ingot). +groovyscript.wiki.prodigytech.solderer.time.value=Sets the time needed to perform the recipe, in ticks. Will run faster than this number when heated over 125 C. +groovyscript.wiki.prodigytech.solderer.pattern.value=The pattern used by the recipe, will not be consumed. +groovyscript.wiki.prodigytech.solderer.removeByAdditive=Removes the recipes using the given additive. +groovyscript.wiki.prodigytech.solderer.removeByPattern=Removes the recipes using the given pattern. +groovyscript.wiki.prodigytech.solderer.removeWithoutAdditive=Removes all recipes not using additives. + +groovyscript.wiki.prodigytech.zorra_altar.title=Zorra Altar +groovyscript.wiki.prodigytech.zorra_altar.description=Allows over-enchanting Zorrasteel equipment. +groovyscript.wiki.prodigytech.zorra_altar.addEnchantment=Adds an enchantment that can be applied in the Altar. +groovyscript.wiki.prodigytech.zorra_altar.removeEnchantment=Removes an enchantment that can be applied in the Altar. + +# Pyrotech +groovyscript.wiki.pyrotech.anvil.title=Anvil +groovyscript.wiki.pyrotech.anvil.description=When using hammer or pickaxe it can convert items +groovyscript.wiki.pyrotech.anvil.hits.value=Sets how often the item needs to be hit +groovyscript.wiki.pyrotech.anvil.tier.value=Sets the tier of the required anvil (Granite, Ironclad, Obsidian) +groovyscript.wiki.pyrotech.anvil.type.value=Sets the type of tool required (Hammer, Pickaxe) +groovyscript.wiki.pyrotech.anvil.add=Adds recipes in the format `name`, `input`, `output`, `hits`, `tier`, `type` + +groovyscript.wiki.pyrotech.barrel.title=Barrel +groovyscript.wiki.pyrotech.barrel.description=Over time converts a fluid with four items into a new fluid +groovyscript.wiki.pyrotech.barrel.duration.value=Sets the time required for the recipe to complete +groovyscript.wiki.pyrotech.barrel.add=Adds recipes in the format `name`, `input1`, `input2`, `input3`, `input4`, `fluidInput`, `fluidOutput`, `duration` + +groovyscript.wiki.pyrotech.campfire.title=Campfire +groovyscript.wiki.pyrotech.campfire.description=Can cook food +groovyscript.wiki.pyrotech.campfire.duration.value=Sets the time required for the recipe to complete +groovyscript.wiki.pyrotech.campfire.add=Adds recipes in the format `name`, `input`, `output`, `duration` + +groovyscript.wiki.pyrotech.chopping_block.title=Chopping Block +groovyscript.wiki.pyrotech.chopping_block.description=When using a axe it can convert items +groovyscript.wiki.pyrotech.chopping_block.chops.value=Sets how often the item needs to be hit with output amount. Call it 4 times for 4 different tiers (Crude, Stone, Iron, Diamond) +groovyscript.wiki.pyrotech.chopping_block.quantities.value=Sets the amount of items output for a given tier. Call it 4 times for 4 different tiers (Crude, Stone, Iron, Diamond) + +groovyscript.wiki.pyrotech.compacting_bin.title=Compacting Bin +groovyscript.wiki.pyrotech.compacting_bin.description=When using a shovel it can convert items +groovyscript.wiki.pyrotech.compacting_bin.toolUses.value=Sets how often the item needs to be hit +groovyscript.wiki.pyrotech.compacting_bin.add=Adds recipes in the format `name`, `input`, `output`, `hits` + +groovyscript.wiki.pyrotech.compost_bin.title=Compost Bin +groovyscript.wiki.pyrotech.compost_bin.description=Can convert multiple items into a new one when its full +groovyscript.wiki.pyrotech.compost_bin.compostValue.value=Sets how much the items fills the bin +groovyscript.wiki.pyrotech.compost_bin.add=Adds recipes in the format `name`, `input`, `output`, `compostValue` + +groovyscript.wiki.pyrotech.crude_drying_rack.title=Crude Drying Rack +groovyscript.wiki.pyrotech.crude_drying_rack.description=Converts an item over time into a new one +groovyscript.wiki.pyrotech.crude_drying_rack.dryTime.value=Sets the time required for the recipe to complete +groovyscript.wiki.pyrotech.crude_drying_rack.add=Adds recipes in the format `name`, `input`, `output`, `dryTime` + +groovyscript.wiki.pyrotech.drying_rack.title=Drying Rack +groovyscript.wiki.pyrotech.drying_rack.description=Converts an item over time into a new one +groovyscript.wiki.pyrotech.drying_rack.dryTime.value=Sets the time required for the recipe to complete +groovyscript.wiki.pyrotech.drying_rack.add=Adds recipes in the format `name`, `input`, `output`, `dryTime` + +groovyscript.wiki.pyrotech.kiln.title=Kiln +groovyscript.wiki.pyrotech.kiln.description=Converts an item into a new one by burning it. Has a chance to fail +groovyscript.wiki.pyrotech.kiln.burnTime.value=Sets the time required for the recipe to complete +groovyscript.wiki.pyrotech.kiln.failureChance.value=Sets the chance to fail the recipe +groovyscript.wiki.pyrotech.kiln.failureOutputs.value=Sets the output when the recipe failed +groovyscript.wiki.pyrotech.kiln.failureOutput.value= +groovyscript.wiki.pyrotech.kiln.add=Adds recipes in the format `name`, `input`, `output`, `burnTime`, `failureChance`, `failureOutput` + +groovyscript.wiki.pyrotech.soaking_pot.title=Soaking Pot +groovyscript.wiki.pyrotech.soaking_pot.description=Converts an item into a new one by soaking it in a liquid. Can require a campfire +groovyscript.wiki.pyrotech.soaking_pot.time.value=Sets the time required for the recipe to complete +groovyscript.wiki.pyrotech.soaking_pot.campfireRequired.value=Sets if a campfire is required underneath +groovyscript.wiki.pyrotech.soaking_pot.add=Adds recipes in the format `name`, `input`, `output`, `time` + +groovyscript.wiki.pyrotech.tanning_rack.title=Tanning Rack +groovyscript.wiki.pyrotech.tanning_rack.description=Converts an item over time into a new one +groovyscript.wiki.pyrotech.tanning_rack.dryTime.value=Sets the time required for the recipe to complete +groovyscript.wiki.pyrotech.tanning_rack.failureItem.value=Sets the output when the recipe failed +groovyscript.wiki.pyrotech.tanning_rack.add=Adds recipes in the format `name`, `input`, `output`, `dryTime`, `failureItem` + # Project E groovyscript.wiki.projecte.entity_randomizer.title=Entity Randomizer @@ -1874,67 +1994,3 @@ groovyscript.wiki.woot.stygian_iron_anvil.note1=While more than 6 items can func groovyscript.wiki.woot.stygian_iron_anvil.base.value=Sets the itemstack used for the base groovyscript.wiki.woot.stygian_iron_anvil.preserveBase.value=Sets if the base is used as a catalyst and not consumed groovyscript.wiki.woot.stygian_iron_anvil.removeByBase=Removes all recipes that match the given base item - - -# Pyrotech -groovyscript.wiki.pyrotech.anvil.title=Anvil -groovyscript.wiki.pyrotech.anvil.description=When using hammer or pickaxe it can convert items -groovyscript.wiki.pyrotech.anvil.hits.value=Sets how often the item needs to be hit -groovyscript.wiki.pyrotech.anvil.tier.value=Sets the tier of the required anvil (Granite, Ironclad, Obsidian) -groovyscript.wiki.pyrotech.anvil.type.value=Sets the type of tool required (Hammer, Pickaxe) -groovyscript.wiki.pyrotech.anvil.add=Adds recipes in the format `name`, `input`, `output`, `hits`, `tier`, `type` - -groovyscript.wiki.pyrotech.barrel.title=Barrel -groovyscript.wiki.pyrotech.barrel.description=Over time converts a fluid with four items into a new fluid -groovyscript.wiki.pyrotech.barrel.duration.value=Sets the time required for the recipe to complete -groovyscript.wiki.pyrotech.barrel.add=Adds recipes in the format `name`, `input1`, `input2`, `input3`, `input4`, `fluidInput`, `fluidOutput`, `duration` - -groovyscript.wiki.pyrotech.campfire.title=Campfire -groovyscript.wiki.pyrotech.campfire.description=Can cook food -groovyscript.wiki.pyrotech.campfire.duration.value=Sets the time required for the recipe to complete -groovyscript.wiki.pyrotech.campfire.add=Adds recipes in the format `name`, `input`, `output`, `duration` - -groovyscript.wiki.pyrotech.chopping_block.title=Chopping Block -groovyscript.wiki.pyrotech.chopping_block.description=When using a axe it can convert items -groovyscript.wiki.pyrotech.chopping_block.chops.value=Sets how often the item needs to be hit with output amount. Call it 4 times for 4 different tiers (Crude, Stone, Iron, Diamond) -groovyscript.wiki.pyrotech.chopping_block.quantities.value=Sets the amount of items output for a given tier. Call it 4 times for 4 different tiers (Crude, Stone, Iron, Diamond) - -groovyscript.wiki.pyrotech.compacting_bin.title=Compacting Bin -groovyscript.wiki.pyrotech.compacting_bin.description=When using a shovel it can convert items -groovyscript.wiki.pyrotech.compacting_bin.toolUses.value=Sets how often the item needs to be hit -groovyscript.wiki.pyrotech.compacting_bin.add=Adds recipes in the format `name`, `input`, `output`, `hits` - -groovyscript.wiki.pyrotech.compost_bin.title=Compost Bin -groovyscript.wiki.pyrotech.compost_bin.description=Can convert multiple items into a new one when its full -groovyscript.wiki.pyrotech.compost_bin.compostValue.value=Sets how much the items fills the bin -groovyscript.wiki.pyrotech.compost_bin.add=Adds recipes in the format `name`, `input`, `output`, `compostValue` - -groovyscript.wiki.pyrotech.crude_drying_rack.title=Crude Drying Rack -groovyscript.wiki.pyrotech.crude_drying_rack.description=Converts an item over time into a new one -groovyscript.wiki.pyrotech.crude_drying_rack.dryTime.value=Sets the time required for the recipe to complete -groovyscript.wiki.pyrotech.crude_drying_rack.add=Adds recipes in the format `name`, `input`, `output`, `dryTime` - -groovyscript.wiki.pyrotech.drying_rack.title=Drying Rack -groovyscript.wiki.pyrotech.drying_rack.description=Converts an item over time into a new one -groovyscript.wiki.pyrotech.drying_rack.dryTime.value=Sets the time required for the recipe to complete -groovyscript.wiki.pyrotech.drying_rack.add=Adds recipes in the format `name`, `input`, `output`, `dryTime` - -groovyscript.wiki.pyrotech.kiln.title=Kiln -groovyscript.wiki.pyrotech.kiln.description=Converts an item into a new one by burning it. Has a chance to fail -groovyscript.wiki.pyrotech.kiln.burnTime.value=Sets the time required for the recipe to complete -groovyscript.wiki.pyrotech.kiln.failureChance.value=Sets the chance to fail the recipe -groovyscript.wiki.pyrotech.kiln.failureOutputs.value=Sets the output when the recipe failed -groovyscript.wiki.pyrotech.kiln.failureOutput.value= -groovyscript.wiki.pyrotech.kiln.add=Adds recipes in the format `name`, `input`, `output`, `burnTime`, `failureChance`, `failureOutput` - -groovyscript.wiki.pyrotech.soaking_pot.title=Soaking Pot -groovyscript.wiki.pyrotech.soaking_pot.description=Converts an item into a new one by soaking it in a liquid. Can require a campfire -groovyscript.wiki.pyrotech.soaking_pot.time.value=Sets the time required for the recipe to complete -groovyscript.wiki.pyrotech.soaking_pot.campfireRequired.value=Sets if a campfire is required underneath -groovyscript.wiki.pyrotech.soaking_pot.add=Adds recipes in the format `name`, `input`, `output`, `time` - -groovyscript.wiki.pyrotech.tanning_rack.title=Tanning Rack -groovyscript.wiki.pyrotech.tanning_rack.description=Converts an item over time into a new one -groovyscript.wiki.pyrotech.tanning_rack.dryTime.value=Sets the time required for the recipe to complete -groovyscript.wiki.pyrotech.tanning_rack.failureItem.value=Sets the output when the recipe failed -groovyscript.wiki.pyrotech.tanning_rack.add=Adds recipes in the format `name`, `input`, `output`, `dryTime`, `failureItem`