From 8ea4da7bebb3f0db420aa8af794cdddd0d00fba8 Mon Sep 17 00:00:00 2001 From: Waiting Idly <25394029+WaitingIdly@users.noreply.github.com> Date: Sat, 6 Apr 2024 05:14:51 -0700 Subject: [PATCH] add Nature's Aura compat (#147) * add natures aura * dont need to store the ResourceLocation --- dependencies.gradle | 11 +- examples/postInit/naturesaura.groovy | 140 +++++++++++++++ gradle.properties | 1 + .../groovyscript/compat/mods/ModSupport.java | 2 + .../compat/mods/naturesaura/Altar.java | 166 +++++++++++++++++ .../compat/mods/naturesaura/NaturesAura.java | 19 ++ .../compat/mods/naturesaura/Offering.java | 144 +++++++++++++++ .../compat/mods/naturesaura/Ritual.java | 156 ++++++++++++++++ .../compat/mods/naturesaura/Spawning.java | 167 ++++++++++++++++++ .../assets/groovyscript/lang/en_us.lang | 33 ++++ 10 files changed, 837 insertions(+), 2 deletions(-) create mode 100644 examples/postInit/naturesaura.groovy create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/Altar.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/NaturesAura.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/Offering.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/Ritual.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/Spawning.java diff --git a/dependencies.gradle b/dependencies.gradle index 3fa1c9a6c..0cfbeb110 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -210,21 +210,28 @@ dependencies { if (project.debug_immersive_engineering.toBoolean()) { runtimeOnly rfg.deobf('curse.maven:immersive_engineering-231951:2974106') } + compileOnly rfg.deobf('curse.maven:patchouli-306770:3162874') + if (project.debug_roots.toBoolean() || project.debug_natures_aura.toBoolean()) { + runtimeOnly rfg.deobf('curse.maven:patchouli-306770:3162874') + } compileOnly rfg.deobf('curse.maven:mystical_lib-277064:3483816') if (project.debug_roots.toBoolean() || project.debug_arcane_archives.toBoolean()) { runtimeOnly rfg.deobf('curse.maven:mystical_lib-277064:3483816') } - compileOnly rfg.deobf('curse.maven:patchouli-306770:3162874') compileOnly rfg.deobf('curse.maven:mystical_world-282940:3460961') compileOnly rfg.deobf('curse.maven:roots-246183:3905074') if (project.debug_roots.toBoolean()) { - runtimeOnly rfg.deobf('curse.maven:patchouli-306770:3162874') runtimeOnly rfg.deobf('curse.maven:mystical_world-282940:3460961') runtimeOnly rfg.deobf('curse.maven:roots-246183:3905074') } + compileOnly rfg.deobf('curse.maven:natures-aura-306626:2882138') + if (project.debug_natures_aura.toBoolean()) { + runtimeOnly rfg.deobf('curse.maven:natures-aura-306626:2882138') + } + // gigaherz.lirelent.guidebook:Guidebook-1.12.2:2.9.1.s5 compileOnly rfg.deobf('curse.maven:guidebook-253874:2989594') compileOnly rfg.deobf('curse.maven:arcane-archives-311357:3057332') diff --git a/examples/postInit/naturesaura.groovy b/examples/postInit/naturesaura.groovy new file mode 100644 index 000000000..0a180abe9 --- /dev/null +++ b/examples/postInit/naturesaura.groovy @@ -0,0 +1,140 @@ + +// Auto generated groovyscript example file +// MODS_LOADED: naturesaura + +println 'mod \'naturesaura\' detected, running script' + +// Natural Altar Infusion: +// Converts an input itemstack into an itemstack in a multiblock structure, with an optional catalyst block, costing aura +// and taking a configurable duration. + +mods.naturesaura.altar.removeByCatalyst(item('naturesaura:crushing_catalyst')) +mods.naturesaura.altar.removeByInput(item('minecraft:rotten_flesh')) +mods.naturesaura.altar.removeByName(resource('naturesaura:infused_iron')) +mods.naturesaura.altar.removeByOutput(item('minecraft:soul_sand')) +// mods.naturesaura.altar.removeAll() + +mods.naturesaura.altar.recipeBuilder() + .name('demo') + .input(item('minecraft:clay')) + .catalyst(item('minecraft:clay')) + .output(item('minecraft:diamond')) + .aura(100) + .time(100) + .register() + +mods.naturesaura.altar.recipeBuilder() + .name(resource('example:demo')) + .input(item('minecraft:clay')) + .output(item('minecraft:gold_ingot') * 8) + .aura(30) + .time(5) + .register() + +mods.naturesaura.altar.recipeBuilder() + .input(item('minecraft:gold_ingot')) + .output(item('minecraft:diamond')) + .catalyst(item('minecraft:clay')) + .aura(50) + .time(100) + .register() + + +// Offering to the Gods: +// Converts up to 16 times the input itemstack into output itemstacks by consuming a catalyst item from the ground in a +// multiblock structure. + +// mods.naturesaura.offering.removeByCatalyst(item('naturesaura:calling_spirit')) +mods.naturesaura.offering.removeByInput(item('minecraft:nether_star')) +mods.naturesaura.offering.removeByName(resource('naturesaura:token_euphoria')) +mods.naturesaura.offering.removeByOutput(item('naturesaura:sky_ingot')) +// mods.naturesaura.offering.removeAll() + +mods.naturesaura.offering.recipeBuilder() + .name('demo') + .input(item('minecraft:diamond')) + .catalyst(item('minecraft:clay')) + .output(item('minecraft:gold_ingot') * 8) + .register() + +mods.naturesaura.offering.recipeBuilder() + .name(resource('example:demo')) + .input(item('minecraft:clay')) + .catalyst(item('minecraft:gold_ingot')) + .output(item('minecraft:diamond') * 8) + .register() + +mods.naturesaura.offering.recipeBuilder() + .input(item('minecraft:gold_ingot') * 10) + .catalyst(item('minecraft:diamond')) + .output(item('minecraft:clay')) + .register() + + +// Ritual of the Forest: +// Converts multiple input items into an output itemstack after a duration when a sapling grows in the middle of a +// multiblock structure. + +mods.naturesaura.ritual.removeByInput(item('naturesaura:infused_stone')) +mods.naturesaura.ritual.removeByName(resource('naturesaura:eye_improved')) +mods.naturesaura.ritual.removeByOutput(item('naturesaura:eye')) +mods.naturesaura.ritual.removeBySapling(item('minecraft:sapling:3')) +// mods.naturesaura.ritual.removeAll() + +mods.naturesaura.ritual.recipeBuilder() + .name('demo') + .input(item('minecraft:clay')) + .output(item('minecraft:diamond')) + .time(100) + .sapling(item('minecraft:sapling:1')) + .register() + +mods.naturesaura.ritual.recipeBuilder() + .name(resource('example:demo')) + .input(item('minecraft:clay'), item('minecraft:clay'), item('minecraft:clay'), item('minecraft:clay')) + .output(item('minecraft:gold_ingot')) + .time(15) + .sapling(item('minecraft:sapling:1')) + .register() + +mods.naturesaura.ritual.recipeBuilder() + .input(item('minecraft:gold_ingot'), item('minecraft:clay'), item('minecraft:gold_ingot'), item('minecraft:clay'), item('minecraft:gold_ingot'), item('minecraft:clay'), item('minecraft:gold_ingot'), item('minecraft:clay')) + .output(item('minecraft:diamond') * 16) + .time(20) + .sapling(item('minecraft:sapling:3')) + .register() + + +// Altar of Birthing: +// Converts multiple input itemstacks into a summoned entity, costing aura and taking time. + +mods.naturesaura.spawning.removeByEntity(entity('minecraft:polar_bear')) +mods.naturesaura.spawning.removeByEntity(resource('minecraft:cave_spider')) +mods.naturesaura.spawning.removeByInput(item('minecraft:bone')) +mods.naturesaura.spawning.removeByName(resource('naturesaura:cow')) +// mods.naturesaura.spawning.removeAll() + +mods.naturesaura.spawning.recipeBuilder() + .name('demo') + .input(item('minecraft:clay')) + .entity(entity('minecraft:bat')) + .aura(100) + .time(100) + .register() + +mods.naturesaura.spawning.recipeBuilder() + .name(resource('example:demo')) + .input(item('minecraft:mutton')) + .entity(entity('minecraft:wolf')) + .aura(30) + .time(5) + .register() + +mods.naturesaura.spawning.recipeBuilder() + .input(item('minecraft:bone'), item('minecraft:dye:15') * 4) + .entity(resource('minecraft:skeleton')) + .aura(10) + .time(10) + .register() + + diff --git a/gradle.properties b/gradle.properties index d8650027a..4fd396ddf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -25,6 +25,7 @@ debug_industrial_craft_2_experimental = false debug_inspirations = false debug_integrated_dynamics = false debug_mekanism = false +debug_natures_aura = false debug_packmode = false debug_pyrotech = false debug_roots = 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 94a4be96e..89fb07ed4 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java @@ -30,6 +30,7 @@ import com.cleanroommc.groovyscript.compat.mods.integrateddynamics.IntegratedDynamics; import com.cleanroommc.groovyscript.compat.mods.jei.JustEnoughItems; import com.cleanroommc.groovyscript.compat.mods.mekanism.Mekanism; +import com.cleanroommc.groovyscript.compat.mods.naturesaura.NaturesAura; import com.cleanroommc.groovyscript.compat.mods.pyrotech.PyroTech; import com.cleanroommc.groovyscript.compat.mods.roots.Roots; import com.cleanroommc.groovyscript.compat.mods.rustic.Rustic; @@ -84,6 +85,7 @@ public class ModSupport implements IDynamicGroovyProperty { public static final GroovyContainer INTEGRATED_DYNAMICS = new InternalModContainer<>("integrateddynamics", "Integrated Dynamics", IntegratedDynamics::new, "id"); public static final GroovyContainer JEI = new InternalModContainer<>("jei", "Just Enough Items", JustEnoughItems::new, "hei"); public static final GroovyContainer MEKANISM = new InternalModContainer<>("mekanism", "Mekanism", Mekanism::new); + public static final GroovyContainer NATURES_AURA = new InternalModContainer<>("naturesaura", "Nature's Aura", NaturesAura::new); public static final GroovyContainer PYROTECH = new InternalModContainer<>("pyrotech", "Pyrotech", PyroTech::new); public static final GroovyContainer ROOTS = new InternalModContainer<>("roots", "Roots 3", Roots::new); public static final GroovyContainer RUSTIC = new InternalModContainer<>("rustic", "Rustic", Rustic::new); diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/Altar.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/Altar.java new file mode 100644 index 000000000..07bb1cc7e --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/Altar.java @@ -0,0 +1,166 @@ +package com.cleanroommc.groovyscript.compat.mods.naturesaura; + +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.Alias; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import de.ellpeck.naturesaura.api.NaturesAuraAPI; +import de.ellpeck.naturesaura.api.recipes.AltarRecipe; +import net.minecraft.util.ResourceLocation; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +@RegistryDescription +public class Altar extends VirtualizedRegistry { + + public Altar() { + super(Alias.generateOfClass(Altar.class).andGenerate("Infusion")); + } + + @RecipeBuilderDescription(example = { + @Example(".name('demo').input(item('minecraft:clay')).catalyst(item('minecraft:clay')).output(item('minecraft:diamond')).aura(100).time(100)"), + @Example(".name(resource('example:demo')).input(item('minecraft:clay')).output(item('minecraft:gold_ingot') * 8).aura(30).time(5)"), + @Example(".input(item('minecraft:gold_ingot')).output(item('minecraft:diamond')).catalyst(item('minecraft:clay')).aura(50).time(100)") + }) + public RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(x -> NaturesAuraAPI.ALTAR_RECIPES.remove(x.name)); + restoreFromBackup().forEach(x -> NaturesAuraAPI.ALTAR_RECIPES.put(x.name, x)); + } + + public void add(AltarRecipe recipe) { + if (recipe == null) return; + addScripted(recipe); + NaturesAuraAPI.ALTAR_RECIPES.put(recipe.name, recipe); + } + + public boolean remove(AltarRecipe recipe) { + if (recipe == null) return false; + addBackup(recipe); + return NaturesAuraAPI.ALTAR_RECIPES.remove(recipe.name) != null; + } + + @MethodDescription(example = @Example("resource('naturesaura:infused_iron')")) + public boolean removeByName(ResourceLocation name) { + if (name == null) return false; + var recipe = NaturesAuraAPI.ALTAR_RECIPES.remove(name); + if (recipe == null) return false; + addBackup(recipe); + return true; + } + + @MethodDescription(description = "groovyscript.wiki.removeByInput", example = @Example("item('minecraft:rotten_flesh')")) + public boolean removeByInput(IIngredient input) { + return NaturesAuraAPI.ALTAR_RECIPES.entrySet().removeIf(r -> { + for (var item : r.getValue().input.getMatchingStacks()) { + if (input.test(item)) { + addBackup(r.getValue()); + return true; + } + } + return false; + }); + } + + @MethodDescription(description = "groovyscript.wiki.removeByCatalyst", example = @Example("item('naturesaura:crushing_catalyst')")) + public boolean removeByCatalyst(IIngredient catalyst) { + return NaturesAuraAPI.ALTAR_RECIPES.entrySet().removeIf(r -> { + for (var item : r.getValue().catalyst.getMatchingStacks()) { + if (catalyst.test(item)) { + addBackup(r.getValue()); + return true; + } + } + return false; + }); + } + + @MethodDescription(description = "groovyscript.wiki.removeByOutput", example = @Example("item('minecraft:soul_sand')")) + public boolean removeByOutput(IIngredient output) { + return NaturesAuraAPI.ALTAR_RECIPES.entrySet().removeIf(r -> { + if (output.test(r.getValue().output)) { + addBackup(r.getValue()); + return true; + } + return false; + }); + } + + @MethodDescription(description = "groovyscript.wiki.removeAll", priority = 2000, example = @Example(commented = true)) + public void removeAll() { + NaturesAuraAPI.ALTAR_RECIPES.values().forEach(this::addBackup); + NaturesAuraAPI.ALTAR_RECIPES.entrySet().clear(); + } + + @MethodDescription(description = "groovyscript.wiki.streamRecipes", type = MethodDescription.Type.QUERY) + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(NaturesAuraAPI.ALTAR_RECIPES.entrySet()).setRemover(x -> remove(x.getValue())); + } + + @Property(property = "input", valid = @Comp("1")) + @Property(property = "output", valid = @Comp("1")) + public static class RecipeBuilder extends AbstractRecipeBuilder { + + @Property(valid = @Comp(value = "null", type = Comp.Type.NOT), defaultValue = "IIngredient.EMPTY") + private IIngredient catalyst = IIngredient.EMPTY; + @Property(valid = @Comp(value = "1", type = Comp.Type.GTE)) + private int aura; + @Property(valid = @Comp(value = "1", type = Comp.Type.GTE)) + private int time; + + @RecipeBuilderMethodDescription + public RecipeBuilder catalyst(IIngredient catalyst) { + this.catalyst = catalyst; + return this; + } + + @RecipeBuilderMethodDescription + public RecipeBuilder aura(int aura) { + this.aura = aura; + return this; + } + + @RecipeBuilderMethodDescription + public RecipeBuilder time(int time) { + this.time = time; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Nature's Aura Altar Recipe"; + } + + public String getRecipeNamePrefix() { + return "groovyscript_altar_"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateName(); + validateItems(msg, 1, 1, 1, 1); + validateFluids(msg); + msg.add(catalyst == null, "catalyst must not be null"); + msg.add(aura <= 0, "aura must be greater than or equal to 1, yet it was {}", aura); + msg.add(time <= 0, "time must be greater than or equal to 1, yet it was {}", time); + } + + @Override + @RecipeBuilderRegistrationMethod + public @Nullable AltarRecipe register() { + if (!validate()) return null; + AltarRecipe recipe = new AltarRecipe(name, input.get(0).toMcIngredient(), output.get(0), catalyst.toMcIngredient(), aura, time); + ModSupport.NATURES_AURA.get().altar.add(recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/NaturesAura.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/NaturesAura.java new file mode 100644 index 000000000..a9aa65699 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/NaturesAura.java @@ -0,0 +1,19 @@ +package com.cleanroommc.groovyscript.compat.mods.naturesaura; + +import com.cleanroommc.groovyscript.compat.mods.ModPropertyContainer; + +public class NaturesAura extends ModPropertyContainer { + + public final Altar altar = new Altar(); + public final Ritual ritual = new Ritual(); + public final Offering offering = new Offering(); + public final Spawning spawning = new Spawning(); + + public NaturesAura() { + addRegistry(altar); + addRegistry(ritual); + addRegistry(offering); + addRegistry(spawning); + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/Offering.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/Offering.java new file mode 100644 index 000000000..14f66ea72 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/Offering.java @@ -0,0 +1,144 @@ +package com.cleanroommc.groovyscript.compat.mods.naturesaura; + +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 de.ellpeck.naturesaura.api.NaturesAuraAPI; +import de.ellpeck.naturesaura.api.recipes.OfferingRecipe; +import net.minecraft.util.ResourceLocation; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +@RegistryDescription(admonition = @Admonition("groovyscript.wiki.naturesaura.offering.note0")) +public class Offering extends VirtualizedRegistry { + + @RecipeBuilderDescription(example = { + @Example(".name('demo').input(item('minecraft:diamond')).catalyst(item('minecraft:clay')).output(item('minecraft:gold_ingot') * 8)"), + @Example(".name(resource('example:demo')).input(item('minecraft:clay')).catalyst(item('minecraft:gold_ingot')).output(item('minecraft:diamond') * 8)"), + @Example(".input(item('minecraft:gold_ingot') * 10).catalyst(item('minecraft:diamond')).output(item('minecraft:clay'))") + }) + public RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(x -> NaturesAuraAPI.OFFERING_RECIPES.remove(x.name)); + restoreFromBackup().forEach(x -> NaturesAuraAPI.OFFERING_RECIPES.put(x.name, x)); + } + + public void add(OfferingRecipe recipe) { + if (recipe == null) return; + addScripted(recipe); + NaturesAuraAPI.OFFERING_RECIPES.put(recipe.name, recipe); + } + + public boolean remove(OfferingRecipe recipe) { + if (recipe == null) return false; + addBackup(recipe); + return NaturesAuraAPI.OFFERING_RECIPES.remove(recipe.name) != null; + } + + @MethodDescription(example = @Example("resource('naturesaura:token_euphoria')")) + public boolean removeByName(ResourceLocation name) { + if (name == null) return false; + var recipe = NaturesAuraAPI.OFFERING_RECIPES.remove(name); + if (recipe == null) return false; + addBackup(recipe); + return true; + } + + @MethodDescription(description = "groovyscript.wiki.removeByInput", example = @Example("item('minecraft:nether_star')")) + public boolean removeByInput(IIngredient input) { + return NaturesAuraAPI.OFFERING_RECIPES.entrySet().removeIf(r -> { + for (var item : r.getValue().input.getMatchingStacks()) { + if (input.test(item)) { + addBackup(r.getValue()); + return true; + } + } + return false; + }); + } + + @MethodDescription(description = "groovyscript.wiki.removeByCatalyst", example = @Example(value = "item('naturesaura:calling_spirit')", commented = true)) + public boolean removeByCatalyst(IIngredient catalyst) { + return NaturesAuraAPI.OFFERING_RECIPES.entrySet().removeIf(r -> { + for (var x : r.getValue().startItem.getMatchingStacks()) { + if (catalyst.test(x)) { + addBackup(r.getValue()); + return true; + } + } + return false; + }); + } + + @MethodDescription(description = "groovyscript.wiki.removeByOutput", example = @Example("item('naturesaura:sky_ingot')")) + public boolean removeByOutput(IIngredient output) { + return NaturesAuraAPI.OFFERING_RECIPES.entrySet().removeIf(r -> { + if (output.test(r.getValue().output)) { + addBackup(r.getValue()); + return true; + } + return false; + }); + } + + @MethodDescription(description = "groovyscript.wiki.removeAll", priority = 2000, example = @Example(commented = true)) + public void removeAll() { + NaturesAuraAPI.OFFERING_RECIPES.values().forEach(this::addBackup); + NaturesAuraAPI.OFFERING_RECIPES.entrySet().clear(); + } + + @MethodDescription(description = "groovyscript.wiki.streamRecipes", type = MethodDescription.Type.QUERY) + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(NaturesAuraAPI.OFFERING_RECIPES.entrySet()).setRemover(x -> remove(x.getValue())); + } + + @Property(property = "input", valid = @Comp("1")) + @Property(property = "output", valid = @Comp("1")) + public static class RecipeBuilder extends AbstractRecipeBuilder { + + @Property(valid = @Comp(value = "null", type = Comp.Type.NOT)) + private IIngredient catalyst; + + @RecipeBuilderMethodDescription + public RecipeBuilder catalyst(IIngredient catalyst) { + this.catalyst = catalyst; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Nature's Aura Offering Recipe"; + } + + public String getRecipeNamePrefix() { + return "groovyscript_offering_"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateName(); + validateItems(msg, 1, 1, 1, 1); + validateFluids(msg); + msg.add(IngredientHelper.isEmpty(catalyst), "catalyst must not be empty"); + } + + @Override + @RecipeBuilderRegistrationMethod + public @Nullable OfferingRecipe register() { + if (!validate()) return null; + OfferingRecipe recipe = new OfferingRecipe(name, input.get(0).toMcIngredient(), catalyst.toMcIngredient(), output.get(0)); + ModSupport.NATURES_AURA.get().offering.add(recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/Ritual.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/Ritual.java new file mode 100644 index 000000000..c609a6bfb --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/Ritual.java @@ -0,0 +1,156 @@ +package com.cleanroommc.groovyscript.compat.mods.naturesaura; + +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 de.ellpeck.naturesaura.api.NaturesAuraAPI; +import de.ellpeck.naturesaura.api.recipes.TreeRitualRecipe; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.ResourceLocation; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +@RegistryDescription(admonition = @Admonition(value = "groovyscript.wiki.naturesaura.ritual.note0", type = Admonition.Type.WARNING)) +public class Ritual extends VirtualizedRegistry { + + @RecipeBuilderDescription(example = { + @Example(".name('demo').input(item('minecraft:clay')).output(item('minecraft:diamond')).time(100).sapling(item('minecraft:sapling:1'))"), + @Example(".name(resource('example:demo')).input(item('minecraft:clay'), item('minecraft:clay'), item('minecraft:clay'), item('minecraft:clay')).output(item('minecraft:gold_ingot')).time(15).sapling(item('minecraft:sapling:1'))"), + @Example(".input(item('minecraft:gold_ingot'), item('minecraft:clay'), item('minecraft:gold_ingot'), item('minecraft:clay'), item('minecraft:gold_ingot'), item('minecraft:clay'), item('minecraft:gold_ingot'), item('minecraft:clay')).output(item('minecraft:diamond') * 16).time(20).sapling(item('minecraft:sapling:3'))") + }) + public RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(x -> NaturesAuraAPI.TREE_RITUAL_RECIPES.remove(x.name)); + restoreFromBackup().forEach(x -> NaturesAuraAPI.TREE_RITUAL_RECIPES.put(x.name, x)); + } + + public void add(TreeRitualRecipe recipe) { + if (recipe == null) return; + addScripted(recipe); + NaturesAuraAPI.TREE_RITUAL_RECIPES.put(recipe.name, recipe); + } + + public boolean remove(TreeRitualRecipe recipe) { + if (recipe == null) return false; + addBackup(recipe); + return NaturesAuraAPI.TREE_RITUAL_RECIPES.remove(recipe.name) != null; + } + + @MethodDescription(example = @Example("resource('naturesaura:eye_improved')")) + public boolean removeByName(ResourceLocation name) { + if (name == null) return false; + var recipe = NaturesAuraAPI.TREE_RITUAL_RECIPES.remove(name); + if (recipe == null) return false; + addBackup(recipe); + return true; + } + + @MethodDescription(description = "groovyscript.wiki.removeByInput", example = @Example("item('naturesaura:infused_stone')")) + public boolean removeByInput(IIngredient input) { + return NaturesAuraAPI.TREE_RITUAL_RECIPES.entrySet().removeIf(r -> { + for (var ingredient : r.getValue().ingredients) { + for (var item : ingredient.getMatchingStacks()) { + if (input.test(item)) { + addBackup(r.getValue()); + return true; + } + } + } + return false; + }); + } + + @MethodDescription(example = @Example("item('minecraft:sapling:3')")) + public boolean removeBySapling(IIngredient catalyst) { + return NaturesAuraAPI.TREE_RITUAL_RECIPES.entrySet().removeIf(r -> { + for (var x : r.getValue().saplingType.getMatchingStacks()) { + if (catalyst.test(x)) { + addBackup(r.getValue()); + return true; + } + } + return false; + }); + } + + @MethodDescription(description = "groovyscript.wiki.removeByOutput", example = @Example("item('naturesaura:eye')")) + public boolean removeByOutput(IIngredient output) { + return NaturesAuraAPI.TREE_RITUAL_RECIPES.entrySet().removeIf(r -> { + if (output.test(r.getValue().result)) { + addBackup(r.getValue()); + return true; + } + return false; + }); + } + + @MethodDescription(description = "groovyscript.wiki.removeAll", priority = 2000, example = @Example(commented = true)) + public void removeAll() { + NaturesAuraAPI.TREE_RITUAL_RECIPES.values().forEach(this::addBackup); + NaturesAuraAPI.TREE_RITUAL_RECIPES.entrySet().clear(); + } + + @MethodDescription(description = "groovyscript.wiki.streamRecipes", type = MethodDescription.Type.QUERY) + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(NaturesAuraAPI.TREE_RITUAL_RECIPES.entrySet()).setRemover(x -> remove(x.getValue())); + } + + @Property(property = "input", valid = {@Comp(type = Comp.Type.GTE, value = "1"), @Comp(type = Comp.Type.LTE, value = "8")}) + @Property(property = "output", valid = @Comp("1")) + public static class RecipeBuilder extends AbstractRecipeBuilder { + + @Property(valid = @Comp(value = "null", type = Comp.Type.NOT)) + private IIngredient sapling; + @Property(valid = @Comp(value = "1", type = Comp.Type.GTE)) + private int time; + + @RecipeBuilderMethodDescription + public RecipeBuilder sapling(IIngredient sapling) { + this.sapling = sapling; + return this; + } + + @RecipeBuilderMethodDescription + public RecipeBuilder time(int time) { + this.time = time; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Nature's Aura Ritual Recipe"; + } + + public String getRecipeNamePrefix() { + return "groovyscript_ritual_"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateName(); + validateItems(msg, 1, 8, 1, 1); + validateFluids(msg); + msg.add(IngredientHelper.isEmpty(sapling), "sapling must not be empty"); + msg.add(time <= 0, "time must be greater than or equal to 1, yet it was {}", time); + } + + @Override + @RecipeBuilderRegistrationMethod + public @Nullable TreeRitualRecipe register() { + if (!validate()) return null; + TreeRitualRecipe recipe = new TreeRitualRecipe(name, sapling.toMcIngredient(), output.get(0), time, input.stream().map(IIngredient::toMcIngredient).toArray(Ingredient[]::new)); + ModSupport.NATURES_AURA.get().ritual.add(recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/Spawning.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/Spawning.java new file mode 100644 index 000000000..4008ff520 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/naturesaura/Spawning.java @@ -0,0 +1,167 @@ +package com.cleanroommc.groovyscript.compat.mods.naturesaura; + +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 de.ellpeck.naturesaura.api.NaturesAuraAPI; +import de.ellpeck.naturesaura.api.recipes.AnimalSpawnerRecipe; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.common.registry.EntityEntry; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +@RegistryDescription(admonition = @Admonition(value = "groovyscript.wiki.naturesaura.spawning.note0", type = Admonition.Type.WARNING)) +public class Spawning extends VirtualizedRegistry { + + @RecipeBuilderDescription(example = { + @Example(".name('demo').input(item('minecraft:clay')).entity(entity('minecraft:bat')).aura(100).time(100)"), + @Example(".name(resource('example:demo')).input(item('minecraft:mutton')).entity(entity('minecraft:wolf')).aura(30).time(5)"), + @Example(".input(item('minecraft:bone'), item('minecraft:dye:15') * 4).entity(resource('minecraft:skeleton')).aura(10).time(10)") + }) + public RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(x -> NaturesAuraAPI.ANIMAL_SPAWNER_RECIPES.remove(x.name)); + restoreFromBackup().forEach(x -> NaturesAuraAPI.ANIMAL_SPAWNER_RECIPES.put(x.name, x)); + } + + public void add(AnimalSpawnerRecipe recipe) { + if (recipe == null) return; + addScripted(recipe); + NaturesAuraAPI.ANIMAL_SPAWNER_RECIPES.put(recipe.name, recipe); + } + + public boolean remove(AnimalSpawnerRecipe recipe) { + if (recipe == null) return false; + addBackup(recipe); + return NaturesAuraAPI.ANIMAL_SPAWNER_RECIPES.remove(recipe.name) != null; + } + + @MethodDescription(example = @Example("resource('naturesaura:cow')")) + public boolean removeByName(ResourceLocation name) { + if (name == null) return false; + var recipe = NaturesAuraAPI.ANIMAL_SPAWNER_RECIPES.remove(name); + if (recipe == null) return false; + addBackup(recipe); + return true; + } + + @MethodDescription(description = "groovyscript.wiki.removeByInput", example = @Example("item('minecraft:bone')")) + public boolean removeByInput(IIngredient input) { + return NaturesAuraAPI.ANIMAL_SPAWNER_RECIPES.entrySet().removeIf(r -> { + for (var ingredient : r.getValue().ingredients) { + for (var item : ingredient.getMatchingStacks()) { + if (input.test(item)) { + addBackup(r.getValue()); + return true; + } + } + } + return false; + }); + } + + @MethodDescription(example = @Example("resource('minecraft:cave_spider')")) + public boolean removeByEntity(ResourceLocation resourceLocation) { + return NaturesAuraAPI.ANIMAL_SPAWNER_RECIPES.entrySet().removeIf(r -> { + if (r.getValue().entity.equals(resourceLocation)) { + addBackup(r.getValue()); + return true; + } + return false; + }); + } + + @MethodDescription(example = @Example("entity('minecraft:polar_bear')")) + public boolean removeByEntity(EntityEntry entity) { + return NaturesAuraAPI.ANIMAL_SPAWNER_RECIPES.entrySet().removeIf(r -> { + if (r.getValue().entity.equals(entity.getRegistryName())) { + addBackup(r.getValue()); + return true; + } + return false; + }); + } + + @MethodDescription(description = "groovyscript.wiki.removeAll", priority = 2000, example = @Example(commented = true)) + public void removeAll() { + NaturesAuraAPI.ANIMAL_SPAWNER_RECIPES.values().forEach(this::addBackup); + NaturesAuraAPI.ANIMAL_SPAWNER_RECIPES.entrySet().clear(); + } + + @MethodDescription(description = "groovyscript.wiki.streamRecipes", type = MethodDescription.Type.QUERY) + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(NaturesAuraAPI.ANIMAL_SPAWNER_RECIPES.entrySet()).setRemover(x -> remove(x.getValue())); + } + + @Property(property = "input", valid = {@Comp(type = Comp.Type.GTE, value = "1"), @Comp(type = Comp.Type.LTE, value = "Integer.MAX_VALUE")}) + @Property(property = "output", valid = @Comp("1")) + public static class RecipeBuilder extends AbstractRecipeBuilder { + + @Property(valid = @Comp(value = "null", type = Comp.Type.NOT)) + private ResourceLocation entity; + @Property(valid = @Comp(value = "1", type = Comp.Type.GTE)) + private int aura; + @Property(valid = @Comp(value = "1", type = Comp.Type.GTE)) + private int time; + + @RecipeBuilderMethodDescription + public RecipeBuilder entity(EntityEntry entity) { + this.entity = entity.getRegistryName(); + return this; + } + + @RecipeBuilderMethodDescription + public RecipeBuilder entity(ResourceLocation entity) { + this.entity = entity; + return this; + } + + @RecipeBuilderMethodDescription + public RecipeBuilder aura(int aura) { + this.aura = aura; + return this; + } + + @RecipeBuilderMethodDescription + public RecipeBuilder time(int time) { + this.time = time; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Nature's Aura Spawning Recipe"; + } + + public String getRecipeNamePrefix() { + return "groovyscript_spawning_"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateName(); + validateItems(msg, 1, Integer.MAX_VALUE, 0, 0); + validateFluids(msg); + msg.add(entity == null, "entity must not be null"); + } + + @Override + @RecipeBuilderRegistrationMethod + public @Nullable AnimalSpawnerRecipe register() { + if (!validate()) return null; + AnimalSpawnerRecipe recipe = new AnimalSpawnerRecipe(name, entity, aura, time, input.stream().map(IIngredient::toMcIngredient).toArray(Ingredient[]::new)); + ModSupport.NATURES_AURA.get().spawning.add(recipe); + return recipe; + } + } +} diff --git a/src/main/resources/assets/groovyscript/lang/en_us.lang b/src/main/resources/assets/groovyscript/lang/en_us.lang index 46b000f55..473ef1dea 100644 --- a/src/main/resources/assets/groovyscript/lang/en_us.lang +++ b/src/main/resources/assets/groovyscript/lang/en_us.lang @@ -1156,6 +1156,39 @@ groovyscript.wiki.mekanism.washer.title=Washer groovyscript.wiki.mekanism.washer.description=Converts an input gasstack into an output gasstack at the cost of 5mb of water. groovyscript.wiki.mekanism.washer.add=Adds recipes in the format `input`, `output` + +# Nature's Aura +groovyscript.wiki.naturesaura.altar.title=Natural Altar Infusion +groovyscript.wiki.naturesaura.altar.description=Converts an input itemstack into an itemstack in a multiblock structure, with an optional catalyst block, costing aura and taking a configurable duration. +groovyscript.wiki.naturesaura.altar.aura.value=Sets how much aura the recipe drains from the environment +groovyscript.wiki.naturesaura.altar.time.value=Sets the time the recipe takes to complete +groovyscript.wiki.naturesaura.altar.catalyst.value=Sets the catalyst item +groovyscript.wiki.naturesaura.altar.removeByName=Removes the Natural Altar Infusion recipe with the given name + +groovyscript.wiki.naturesaura.offering.title=Offering to the Gods +groovyscript.wiki.naturesaura.offering.description=Converts up to 16 times the input itemstack into output itemstacks by consuming a catalyst item from the ground in a multiblock structure. +groovyscript.wiki.naturesaura.offering.note0=The Offering Table can hold up to 16 items, and will try to run the recipe as many times as possible for a single catalyst item. +groovyscript.wiki.naturesaura.offering.catalyst.value=Sets the catalyst item +groovyscript.wiki.naturesaura.offering.removeByName=Removes the Offering to the Gods recipe with the given name + +groovyscript.wiki.naturesaura.ritual.title=Ritual of the Forest +groovyscript.wiki.naturesaura.ritual.description=Converts multiple input items into an output itemstack after a duration when a sapling grows in the middle of a multiblock structure. +groovyscript.wiki.naturesaura.ritual.note0=The sapling used must extended `BlockSapling` for the recipe to function properly. +groovyscript.wiki.naturesaura.ritual.time.value=Sets the time the recipe takes to complete +groovyscript.wiki.naturesaura.ritual.sapling.value=Sets the sapling used +groovyscript.wiki.naturesaura.ritual.removeByName=Removes the Ritual of the Forest recipe with the given name +groovyscript.wiki.naturesaura.ritual.removeBySapling=Removes all Rituals of the Forest using the given sapling + +groovyscript.wiki.naturesaura.spawning.title=Altar of Birthing +groovyscript.wiki.naturesaura.spawning.description=Converts multiple input itemstacks into a summoned entity, costing aura and taking time. +groovyscript.wiki.naturesaura.spawning.note0=While more than 4 items can function as the input of a Altar of Birthing recipe, only the first 4 are shown in JEI. +groovyscript.wiki.naturesaura.spawning.aura.value=Sets how much aura the recipe drains from the environment +groovyscript.wiki.naturesaura.spawning.time.value=Sets the time the recipe takes to complete +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 + + # Roots groovyscript.wiki.roots.animal_harvest.title=Animal Harvest groovyscript.wiki.roots.animal_harvest.description=Animal Harvest is a ritual that drops items from nearby mob's based on that mobs loottable without harming the mob. Only applies to allowed mobs.