From 58edd997854d21c100baf022f218e9c3a250e7b3 Mon Sep 17 00:00:00 2001 From: Waiting Idly <25394029+WaitingIdly@users.noreply.github.com> Date: Fri, 16 Dec 2022 11:06:08 -0800 Subject: [PATCH 01/30] add mods to build.gradle --- build.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build.gradle b/build.gradle index d590b69c0..9559f3e93 100644 --- a/build.gradle +++ b/build.gradle @@ -108,6 +108,10 @@ dependencies { deobfCompile 'curse.maven:redstone_flux-270789:2920436' deobfCompile 'curse.maven:thermal_expansion-69163:2926431' deobfCompile 'curse.maven:thermal_foundation-222880:2926428' + deobfCompile 'curse.maven:patchouli-306770:3162874' + deobfCompile 'curse.maven:mystical_lib-277064:3483816' + deobfCompile 'curse.maven:mystical_world-282940:3460961' + deobfCompile 'curse.maven:roots-246183:3905074' deobfCompile 'curse.maven:draconic_evolution-223565:3431261' deobfCompile 'curse.maven:brandons_core-231382:3408276' deobfCompile 'curse.maven:immersive_engineering-231951:2974106' @@ -125,6 +129,10 @@ dependencies { deobfProvided 'curse.maven:redstone_flux-270789:2920436' deobfProvided 'curse.maven:thermal_expansion-69163:2926431' deobfProvided 'curse.maven:thermal_foundation-222880:2926428' + deobfProvided 'curse.maven:patchouli-306770:3162874' + deobfProvided 'curse.maven:mystical_lib-277064:3483816' + deobfProvided 'curse.maven:mystical_world-282940:3460961' + deobfProvided 'curse.maven:roots-246183:3905074' deobfProvided 'curse.maven:draconic_evolution-223565:3431261' deobfProvided 'curse.maven:brandons_core-231382:3408276' deobfProvided 'curse.maven:immersive_engineering-231951:2974106' From fa6dc38e19d84bd0a2d5bc733c0cde577a3a2ef3 Mon Sep 17 00:00:00 2001 From: Waiting Idly <25394029+WaitingIdly@users.noreply.github.com> Date: Thu, 13 Apr 2023 16:04:06 -0700 Subject: [PATCH 02/30] add mods to build.gradle again --- build.gradle | 12 ++++++++++++ gradle.properties | 1 + 2 files changed, 13 insertions(+) diff --git a/build.gradle b/build.gradle index 67216cf33..8acdb6783 100644 --- a/build.gradle +++ b/build.gradle @@ -116,6 +116,18 @@ dependencies { deobfProvided 'curse.maven:blood-magic-224791:2822288' } + if (project.debug_roots.toBoolean()) { + deobfCompile 'curse.maven:patchouli-306770:3162874' + deobfCompile 'curse.maven:mystical_lib-277064:3483816' + deobfCompile 'curse.maven:mystical_world-282940:3460961' + deobfCompile 'curse.maven:roots-246183:3905074' + } else { + deobfProvided 'curse.maven:patchouli-306770:3162874' + deobfProvided 'curse.maven:mystical_lib-277064:3483816' + deobfProvided 'curse.maven:mystical_world-282940:3460961' + deobfProvided 'curse.maven:roots-246183:3905074' + } + if (project.debug_thermal.toBoolean()) { deobfCompile 'curse.maven:cofh_core-69162:2920433' deobfCompile 'curse.maven:cofh_world-271384:2920434' diff --git a/gradle.properties b/gradle.properties index 83206caa5..0862558a8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -31,5 +31,6 @@ debug_de = false debug_ie = false debug_enderio = false debug_astral = false +debug_roots = true debug_blood_magic = false debug_tinkers = false \ No newline at end of file From 90513ca73cb6c54ea65f575c65b88b6f624dc57e Mon Sep 17 00:00:00 2001 From: Waiting Idly <25394029+WaitingIdly@users.noreply.github.com> Date: Fri, 5 May 2023 12:48:38 -0700 Subject: [PATCH 03/30] add a ResourceLocation bracket handler --- examples/thaumcraft.groovy | 12 +++---- .../brackets/BracketHandlerManager.java | 1 + .../ResourceLocationBracketHandler.java | 36 +++++++++++++++++++ 3 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/cleanroommc/groovyscript/brackets/ResourceLocationBracketHandler.java diff --git a/examples/thaumcraft.groovy b/examples/thaumcraft.groovy index a1e171cfa..9fd24f9ea 100644 --- a/examples/thaumcraft.groovy +++ b/examples/thaumcraft.groovy @@ -1,5 +1,3 @@ -import net.minecraft.util.ResourceLocation - mods.thaumcraft.Crucible.removeByOutput(item('minecraft:gunpowder')) mods.thaumcraft.Crucible.recipeBuilder() @@ -52,7 +50,7 @@ mods.thaumcraft.ArcaneWorkbench.shapedBuilder() // .chatColor(14013676) // .component(aspect('cognito')) // .component(aspect('perditio')) -// .image(new ResourceLocation('thaumcraft', 'textures/aspects/humor.png')) +// .image(resource('thaumcraft:textures/aspects/humor.png')) // .register() mods.thaumcraft.AspectHelper.aspectBuilder() @@ -122,12 +120,12 @@ mods.thaumcraft.SmeltingBonus.removeByOutput(item('minecraft:gold_nugget')) // .formulaAspect(aspect('ignis') * 5) // .formulaAspect(aspect('terra') * 5) // .formulaAspect(aspect('aqua') * 5) -// .icon(new ResourceLocation('thaumcraft', 'textures/aspects/humor.png')) -// .background(new ResourceLocation('thaumcraft', 'textures/gui/gui_research_back_1.jpg')) -// .background2(new ResourceLocation('thaumcraft', 'textures/gui/gui_research_back_over.png')) +// .icon(resource('thaumcraft:textures/aspects/humor.png')) +// .background(resource('thaumcraft:textures/gui/gui_research_back_1.jpg')) +// .background2(resource('thaumcraft:textures/gui/gui_research_back_over.png')) // .register() // -//mods.thaumcraft.Research.addResearchLocation(new ResourceLocation('thaumcraft', 'research/new.json')) +//mods.thaumcraft.Research.addResearchLocation(resource('thaumcraft:research/new.json')) mods.thaumcraft.Research.addScannable('KNOWLEDGETYPEHUMOR', item('minecraft:pumpkin')) diff --git a/src/main/java/com/cleanroommc/groovyscript/brackets/BracketHandlerManager.java b/src/main/java/com/cleanroommc/groovyscript/brackets/BracketHandlerManager.java index c33861bef..e9b38d9a2 100644 --- a/src/main/java/com/cleanroommc/groovyscript/brackets/BracketHandlerManager.java +++ b/src/main/java/com/cleanroommc/groovyscript/brackets/BracketHandlerManager.java @@ -56,6 +56,7 @@ public static BracketHandler getBracketHandler(String key) { } public static void init() { + registerBracketHandler("resource", ResourceLocationBracketHandler.INSTANCE); registerBracketHandler("ore", s -> s.contains("*") ? OreDictWildcardIngredient.of(s) : new OreDictIngredient(s)); registerBracketHandler("item", ItemBracketHandler.INSTANCE, () -> ItemStack.EMPTY); registerBracketHandler("liquid", BracketHandlerManager::parseFluidStack); diff --git a/src/main/java/com/cleanroommc/groovyscript/brackets/ResourceLocationBracketHandler.java b/src/main/java/com/cleanroommc/groovyscript/brackets/ResourceLocationBracketHandler.java new file mode 100644 index 000000000..1a74eab34 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/brackets/ResourceLocationBracketHandler.java @@ -0,0 +1,36 @@ +package com.cleanroommc.groovyscript.brackets; + +import com.cleanroommc.groovyscript.api.IBracketHandler; +import net.minecraft.util.ResourceLocation; + +import static com.cleanroommc.groovyscript.brackets.BracketHandlerManager.SPLITTER; + +public class ResourceLocationBracketHandler implements IBracketHandler { + + public static final ResourceLocationBracketHandler INSTANCE = new ResourceLocationBracketHandler(); + + private ResourceLocationBracketHandler() { + } + + @Override + public ResourceLocation parse(String mainArg, Object[] args) { + String[] parts = mainArg.split(SPLITTER); + if (parts.length > 1) { + return new ResourceLocation(parts[0], parts[1]); + } + + if (args.length > 1 || (args.length == 1 && !(args[0] instanceof String))) { + throw new IllegalArgumentException("Arguments not valid for bracket handler. Use 'resource(String)' or 'resource(String mod, String path)'"); + } + return new ResourceLocation(mainArg, (String) args[0]); + } + + @Override + public ResourceLocation parse(String arg) { + String[] parts = arg.split(SPLITTER); + if (parts.length < 2) { + return null; + } + return new ResourceLocation(parts[0], parts[1]); + } +} From adbc862c2a08c850ee2513f125c719989cc22382 Mon Sep 17 00:00:00 2001 From: Waiting Idly <25394029+WaitingIdly@users.noreply.github.com> Date: Fri, 5 May 2023 12:49:16 -0700 Subject: [PATCH 04/30] implement compat --- .../groovyscript/compat/mods/ModSupport.java | 2 + .../compat/mods/roots/AnimalHarvest.java | 126 ++++++++ .../compat/mods/roots/AnimalHarvestFish.java | 135 ++++++++ .../compat/mods/roots/BarkCarving.java | 163 ++++++++++ .../compat/mods/roots/Chrysopoeia.java | 158 ++++++++++ .../compat/mods/roots/FeyCrafter.java | 132 ++++++++ .../compat/mods/roots/FlowerGeneration.java | 174 +++++++++++ .../compat/mods/roots/LifeEssence.java | 57 ++++ .../compat/mods/roots/Modifiers.java | 109 +++++++ .../compat/mods/roots/Mortar.java | 259 +++++++++++++++ .../groovyscript/compat/mods/roots/Moss.java | 124 ++++++++ .../compat/mods/roots/Pacifist.java | 123 ++++++++ .../compat/mods/roots/Predicates.java | 126 ++++++++ .../groovyscript/compat/mods/roots/Pyre.java | 149 +++++++++ .../compat/mods/roots/Rituals.java | 151 +++++++++ .../groovyscript/compat/mods/roots/Roots.java | 71 +++++ .../compat/mods/roots/RunicShearBlock.java | 159 ++++++++++ .../compat/mods/roots/RunicShearEntity.java | 159 ++++++++++ .../compat/mods/roots/Spells.java | 295 ++++++++++++++++++ .../compat/mods/roots/SummonCreature.java | 136 ++++++++ .../compat/mods/roots/Transmutation.java | 188 +++++++++++ .../groovyscript/core/LateMixin.java | 2 +- .../core/mixin/roots/ModRecipesAccessor.java | 43 +++ .../core/mixin/roots/ModifierAccessor.java | 16 + .../mixin/roots/ModifierRegistryAccessor.java | 17 + .../core/mixin/roots/MossConfigAccessor.java | 35 +++ .../core/mixin/roots/RitualBaseAccessor.java | 15 + .../resources/mixin.groovyscript.roots.json | 14 + 28 files changed, 3137 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/AnimalHarvest.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/AnimalHarvestFish.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/BarkCarving.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Chrysopoeia.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/FeyCrafter.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/FlowerGeneration.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/LifeEssence.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Modifiers.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Mortar.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Moss.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Pacifist.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Predicates.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Pyre.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Rituals.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Roots.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/RunicShearBlock.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/RunicShearEntity.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Spells.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/SummonCreature.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Transmutation.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModRecipesAccessor.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModifierAccessor.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModifierRegistryAccessor.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/MossConfigAccessor.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/RitualBaseAccessor.java create mode 100644 src/main/resources/mixin.groovyscript.roots.json 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 c071596af..dcc5aacd4 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java @@ -10,6 +10,7 @@ import com.cleanroommc.groovyscript.compat.mods.immersiveengineering.ImmersiveEngineering; import com.cleanroommc.groovyscript.compat.mods.jei.JustEnoughItems; import com.cleanroommc.groovyscript.compat.mods.mekanism.Mekanism; +import com.cleanroommc.groovyscript.compat.mods.roots.Roots; import com.cleanroommc.groovyscript.compat.mods.tcomplement.TinkersComplement; import com.cleanroommc.groovyscript.compat.mods.thaumcraft.Thaumcraft; import com.cleanroommc.groovyscript.compat.mods.thermalexpansion.ThermalExpansion; @@ -42,6 +43,7 @@ public class ModSupport implements IDynamicGroovyProperty { public static final Container TINKERS_CONSTRUCT = new Container<>("tconstruct", "Tinkers' Construct", TinkersConstruct::new, "ticon", "tinkersconstruct"); public static final Container TINKERS_COMPLEMENT = new Container<>("tcomplement", "Tinkers Complement", TinkersComplement::new, "tcomp", "tinkerscomplement"); public static final Container DRACONIC_EVO = new Container<>("draconicevolution", "Draconic Evolution", DraconicEvolution::new, "de"); + public static final Container ROOTS = new Container<>("roots", "Roots 3", Roots::new); public static final Container BLOOD_MAGIC = new Container<>("bloodmagic", "Blood Magic: Alchemical Wizardry", BloodMagic::new, "bm"); public static final Container IMMERSIVE_ENGINEERING = new Container<>("immersiveengineering", "Immersive Engineering", ImmersiveEngineering::new, "ie"); public static final Container INDUSTRIALCRAFT = new Container<>("ic2", "Industrial Craft 2", IC2::new, "industrialcraft"); diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/AnimalHarvest.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/AnimalHarvest.java new file mode 100644 index 000000000..0f01bd572 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/AnimalHarvest.java @@ -0,0 +1,126 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.helper.recipe.RecipeName; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.recipe.AnimalHarvestRecipe; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.common.registry.EntityEntry; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +import static epicsquid.roots.init.ModRecipes.getAnimalHarvestRecipes; +import static epicsquid.roots.init.ModRecipes.removeAnimalHarvestRecipe; + +public class AnimalHarvest extends VirtualizedRegistry> { + + public AnimalHarvest() { + super(); + } + + public static RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(pair -> removeAnimalHarvestRecipe(pair.getKey())); + restoreFromBackup().forEach(pair -> getAnimalHarvestRecipes().put(pair.getKey(), pair.getValue())); + } + + public void add(AnimalHarvestRecipe recipe) { + add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_animal_harvest_")), recipe); + } + + public void add(ResourceLocation name, AnimalHarvestRecipe recipe) { + getAnimalHarvestRecipes().put(name, recipe); + addScripted(Pair.of(name, recipe)); + } + + public ResourceLocation findRecipe(AnimalHarvestRecipe recipe) { + for (Map.Entry entry : getAnimalHarvestRecipes().entrySet()) { + if (entry.getValue().matches(recipe.getHarvestClass())) return entry.getKey(); + } + return null; + } + + public boolean removeByName(ResourceLocation name) { + AnimalHarvestRecipe recipe = getAnimalHarvestRecipes().get(name); + if (recipe == null) return false; + removeAnimalHarvestRecipe(name); + addBackup(Pair.of(name, recipe)); + return true; + } + + public boolean removeByEntity(EntityEntry entity) { + for (Map.Entry x : getAnimalHarvestRecipes().entrySet()) { + if (x.getValue().matches(entity.getEntityClass())) { + getAnimalHarvestRecipes().remove(x.getKey()); + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + } + return false; + } + + public void removeAll() { + getAnimalHarvestRecipes().forEach((key, value) -> addBackup(Pair.of(key, value))); + getAnimalHarvestRecipes().clear(); + } + + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(getAnimalHarvestRecipes().entrySet()) + .setRemover(r -> this.removeByName(r.getKey())); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder { + + private Class entity; + private ResourceLocation name; + + public RecipeBuilder entity(EntityEntry entity) { + this.entity = (Class) entity.getEntityClass(); + return this; + } + + public RecipeBuilder name(String name) { + this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); + return this; + } + + public RecipeBuilder name(ResourceLocation name) { + this.name = name; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Roots Animal Harvest recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg); + validateFluids(msg); + msg.add(entity == null, "entity must be defined and extended EntityLivingBase, instead it was {}", entity); + if (name == null) { + name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_animal_harvest_")); + } + } + + @Override + public @Nullable AnimalHarvestRecipe register() { + if (!validate()) return null; + AnimalHarvestRecipe recipe = new AnimalHarvestRecipe(name, entity); + ModSupport.ROOTS.get().animalHarvest.add(name, recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/AnimalHarvestFish.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/AnimalHarvestFish.java new file mode 100644 index 000000000..35cd38941 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/AnimalHarvestFish.java @@ -0,0 +1,135 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.helper.recipe.RecipeName; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.recipe.AnimalHarvestFishRecipe; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +import static epicsquid.roots.init.ModRecipes.getAnimalHarvestFishRecipes; +import static epicsquid.roots.init.ModRecipes.removeAnimalHarvestFishRecipe; + + +public class AnimalHarvestFish extends VirtualizedRegistry> { + + public AnimalHarvestFish() { + super(); + } + + public static RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(pair -> removeAnimalHarvestFishRecipe(pair.getKey())); + restoreFromBackup().forEach(pair -> getAnimalHarvestFishRecipes().put(pair.getKey(), pair.getValue())); + } + + public void add(String name, AnimalHarvestFishRecipe recipe) { + add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + } + + public void add(ResourceLocation name, AnimalHarvestFishRecipe recipe) { + getAnimalHarvestFishRecipes().put(name, recipe); + addScripted(Pair.of(name, recipe)); + } + + public ResourceLocation findRecipeByOutput(ItemStack output) { + for (Map.Entry entry : getAnimalHarvestFishRecipes().entrySet()) { + if (ItemStack.areItemsEqual(entry.getValue().getItemStack(), output)) return entry.getKey(); + } + return null; + } + + public boolean removeByName(ResourceLocation name) { + AnimalHarvestFishRecipe recipe = getAnimalHarvestFishRecipes().get(name); + if (recipe == null) return false; + removeAnimalHarvestFishRecipe(name); + addBackup(Pair.of(name, recipe)); + return true; + } + + public boolean removeByOutput(ItemStack output) { + for (Map.Entry x : getAnimalHarvestFishRecipes().entrySet()) { + if (ItemStack.areItemsEqual(x.getValue().getItemStack(), output)) { + getAnimalHarvestFishRecipes().remove(x.getKey()); + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + } + return false; + } + + public boolean removeByFish(ItemStack fish) { + return removeByOutput(fish); + } + + public void removeAll() { + getAnimalHarvestFishRecipes().forEach((key, value) -> addBackup(Pair.of(key, value))); + getAnimalHarvestFishRecipes().clear(); + } + + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(getAnimalHarvestFishRecipes().entrySet()) + .setRemover(r -> this.removeByName(r.getKey())); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder { + + private int weight; + private ResourceLocation name; + + public RecipeBuilder weight(int weight) { + this.weight = weight; + return this; + } + + public RecipeBuilder fish(ItemStack fish) { + this.output.add(fish); + return this; + } + + public RecipeBuilder name(String name) { + this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); + return this; + } + + public RecipeBuilder name(ResourceLocation name) { + this.name = name; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Roots Animal Harvest Fish recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 0, 0, 1, 1); + validateFluids(msg); + msg.add(weight <= 0, "weight must be a nonnegative integer greater than 0, instead it was {}", weight); + if (name == null) { + name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_animal_harvest_fish_")); + } + } + + @Override + public @Nullable AnimalHarvestFishRecipe register() { + if (!validate()) return null; + AnimalHarvestFishRecipe recipe = new AnimalHarvestFishRecipe(name, output.get(0), weight); + ModSupport.ROOTS.get().animalHarvestFish.add(name, recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/BarkCarving.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/BarkCarving.java new file mode 100644 index 000000000..a5a743e2c --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/BarkCarving.java @@ -0,0 +1,163 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyLog; +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.helper.recipe.RecipeName; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.recipe.BarkRecipe; +import net.minecraft.block.BlockPlanks; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +import static epicsquid.roots.init.ModRecipes.*; + +public class BarkCarving extends VirtualizedRegistry> { + + public BarkCarving() { + super(VirtualizedRegistry.generateAliases("Bark")); + } + + public static RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(pair -> getBarkRecipeMap().remove(pair.getKey())); + restoreFromBackup().forEach(pair -> getBarkRecipeMap().put(pair.getKey(), pair.getValue())); + } + + public void add(String name, BarkRecipe recipe) { + add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + } + + public void add(ResourceLocation name, BarkRecipe recipe) { + getBarkRecipeMap().put(name, recipe); + addScripted(Pair.of(name, recipe)); + } + + public ResourceLocation findRecipe(BarkRecipe recipe) { + return getBarkRecipeByName(recipe.getName()) == null ? null : recipe.getName(); + } + + public ResourceLocation findRecipeByInput(BlockPlanks.EnumType input) { + for (BarkRecipe entry : getBarkRecipes()) { + if (entry.getType().equals(input)) return entry.getName(); + } + return null; + } + + public ResourceLocation findRecipeByInput(ItemStack input) { + for (BarkRecipe entry : getBarkRecipes()) { + if (ItemStack.areItemsEqual(entry.getBlockStack(), input)) return entry.getName(); + } + return null; + } + + public ResourceLocation findRecipeByOutput(ItemStack output) { + for (BarkRecipe entry : getBarkRecipes()) { + if (ItemStack.areItemsEqual(entry.getItem(), output)) return entry.getName(); + } + return null; + } + + public boolean removeByName(ResourceLocation name) { + BarkRecipe recipe = getBarkRecipeByName(name); + if (recipe == null) return false; + removeBarkRecipe(recipe.getBlockStack()); + addBackup(Pair.of(name, recipe)); + return true; + } + + public boolean removeByInput(ItemStack input) { + for (Map.Entry x : getBarkRecipeMap().entrySet()) { + if (ItemStack.areItemsEqual(x.getValue().getBlockStack(), input)) { + getBarkRecipeMap().remove(x.getKey()); + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + } + return false; + } + + public boolean removeByBlock(ItemStack block) { + return removeByInput(block); + } + + public boolean removeByOutput(ItemStack output) { + for (Map.Entry x : getBarkRecipeMap().entrySet()) { + if (ItemStack.areItemsEqual(x.getValue().getItem(), output)) { + getBarkRecipeMap().remove(x.getKey()); + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + } + return false; + } + + public void removeAll() { + getBarkRecipeMap().forEach((key, value) -> addBackup(Pair.of(key, value))); + getBarkRecipeMap().clear(); + } + + public SimpleObjectStream streamRecipes() { + return new SimpleObjectStream<>(getBarkRecipes()) + .setRemover(r -> this.removeByName(r.getName())); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder { + + private ResourceLocation name; + + public RecipeBuilder blockstate(IBlockState blockstate) { + return this.input(blockstate); + } + + public RecipeBuilder input(IBlockState blockstate) { + this.input.add(IngredientHelper.toIIngredient(new ItemStack(blockstate.getBlock(), 1, blockstate.getBlock().damageDropped(blockstate)))); + return this; + } + + public RecipeBuilder name(String name) { + this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); + return this; + } + + public RecipeBuilder name(ResourceLocation name) { + this.name = name; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Roots Pyre recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 1, 1, 1, 1); + validateFluids(msg); + if (name == null) { + name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_bark_carving_")); + } + } + + @Override + public @Nullable BarkRecipe register() { + if (!validate()) return null; + BarkRecipe recipe; + recipe = new BarkRecipe(name, output.get(0), input.get(0).toMcIngredient().getMatchingStacks()[0]); + ModSupport.ROOTS.get().barkCarving.add(name, recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Chrysopoeia.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Chrysopoeia.java new file mode 100644 index 000000000..9756309db --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Chrysopoeia.java @@ -0,0 +1,158 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.core.mixin.roots.ModRecipesAccessor; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.helper.recipe.RecipeName; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.recipe.ChrysopoeiaRecipe; +import epicsquid.roots.util.IngredientWithStack; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +public class Chrysopoeia extends VirtualizedRegistry> { + + public Chrysopoeia() { + super(); + } + + public static RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(pair -> ModRecipesAccessor.getChrysopoeiaRecipes().remove(pair.getKey())); + restoreFromBackup().forEach(pair -> ModRecipesAccessor.getChrysopoeiaRecipes().put(pair.getKey(), pair.getValue())); + } + + public void add(String name, ChrysopoeiaRecipe recipe) { + add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + } + + public void add(ResourceLocation name, ChrysopoeiaRecipe recipe) { + ModRecipesAccessor.getChrysopoeiaRecipes().put(name, recipe); + addScripted(Pair.of(name, recipe)); + } + + public ResourceLocation findRecipe(ChrysopoeiaRecipe recipe) { + for (Map.Entry entry : ModRecipesAccessor.getChrysopoeiaRecipes().entrySet()) { + if (entry.getValue().matches(recipe.getOutput())) return entry.getKey(); + } + return null; + } + + public ResourceLocation findRecipeByOutput(ItemStack output) { + for (Map.Entry entry : ModRecipesAccessor.getChrysopoeiaRecipes().entrySet()) { + if (ItemStack.areItemsEqual(entry.getValue().getOutput(), output)) return entry.getKey(); + } + return null; + } + + public boolean removeByName(ResourceLocation name) { + ChrysopoeiaRecipe recipe = ModRecipesAccessor.getChrysopoeiaRecipes().get(name); + if (recipe == null) return false; + ModRecipesAccessor.getChrysopoeiaRecipes().remove(name); + addBackup(Pair.of(name, recipe)); + return true; + } + + public boolean removeByOutput(ItemStack output) { + for (Map.Entry entry : ModRecipesAccessor.getChrysopoeiaRecipes().entrySet()) { + if (ItemStack.areItemsEqual(entry.getValue().getOutput(), output)) { + ModRecipesAccessor.getChrysopoeiaRecipes().remove(entry.getKey()); + addBackup(Pair.of(entry.getKey(), entry.getValue())); + return true; + } + } + return false; + } + + public boolean removeByInput(ItemStack output) { + for (Map.Entry entry : ModRecipesAccessor.getChrysopoeiaRecipes().entrySet()) { + if (entry.getValue().getIngredient().getIngredient().test(output)) { + ModRecipesAccessor.getChrysopoeiaRecipes().remove(entry.getKey()); + addBackup(Pair.of(entry.getKey(), entry.getValue())); + return true; + } + } + return false; + } + + public void removeAll() { + ModRecipesAccessor.getChrysopoeiaRecipes().forEach((key, value) -> addBackup(Pair.of(key, value))); + ModRecipesAccessor.getChrysopoeiaRecipes().clear(); + } + + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(ModRecipesAccessor.getChrysopoeiaRecipes().entrySet()) + .setRemover(r -> this.removeByName(r.getKey())); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder { + + // overload, byproductChance, and byproduct are all unused +// private float overload = 0.0F; +// private float byproductChance = 0.0F; +// private ItemStack byproduct = ItemStack.EMPTY; + private ResourceLocation name; + +// public RecipeBuilder overload(float overload) { +// this.overload = overload; +// return this; +// } + +// public RecipeBuilder byproductChance(float byproductChance) { +// this.byproductChance = byproductChance; +// return this; +// } + +// public RecipeBuilder byproduct(IIngredient byproduct) { +// this.byproduct = IngredientHelper.toItemStack(byproduct); +// return this; +// } + + public RecipeBuilder name(String name) { + this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); + return this; + } + + public RecipeBuilder name(ResourceLocation name) { + this.name = name; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Roots Chrysopoeia conversion recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 1, 1, 1, 1); + validateFluids(msg); +// msg.add(overload < 0, "overload must be a nonnegative float, yet it was {}", overload); +// msg.add(byproductChance < 0, "byproductChance must be a nonnegative float, yet it was {}", byproductChance); + if (name == null) { + name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_chrysopoeia_")); + } + } + + @Override + public @Nullable ChrysopoeiaRecipe register() { + if (!validate()) return null; + ChrysopoeiaRecipe recipe = new ChrysopoeiaRecipe(new IngredientWithStack(IngredientHelper.toItemStack(input.get(0))), output.get(0)/*, byproduct, overload, byproductChance*/); + recipe.setRegistryName(name); + ModSupport.ROOTS.get().chrysopoeia.add(name, recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/FeyCrafter.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/FeyCrafter.java new file mode 100644 index 000000000..a96b7fd88 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/FeyCrafter.java @@ -0,0 +1,132 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.helper.recipe.RecipeName; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.recipe.FeyCraftingRecipe; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +import static epicsquid.roots.init.ModRecipes.*; + +public class FeyCrafter extends VirtualizedRegistry> { + + public FeyCrafter() { + super(); + } + + public static RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(pair -> removeFeyCraftingRecipe(pair.getKey())); + restoreFromBackup().forEach(pair -> addFeyCraftingRecipe(pair.getKey(), pair.getValue())); + } + + public void add(String name, FeyCraftingRecipe recipe) { + add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + } + + public void add(ResourceLocation name, FeyCraftingRecipe recipe) { + addFeyCraftingRecipe(name, recipe); + addScripted(Pair.of(name, recipe)); + } + + public ResourceLocation findRecipe(FeyCraftingRecipe recipe) { + for (Map.Entry entry : getFeyCraftingRecipes().entrySet()) { + if (entry.getValue().matches(recipe.getRecipe())) return entry.getKey(); + } + return null; + } + + public ResourceLocation findRecipeByOutput(ItemStack output) { + for (Map.Entry entry : getFeyCraftingRecipes().entrySet()) { + if (ItemStack.areItemsEqual(entry.getValue().getResult(), output)) return entry.getKey(); + } + return null; + } + + public boolean removeByName(ResourceLocation name) { + FeyCraftingRecipe recipe = getFeyCraftingRecipe(name); + if (recipe == null) return false; + removeFeyCraftingRecipe(name); + addBackup(Pair.of(name, recipe)); + return true; + } + + public boolean removeByOutput(ItemStack output) { + for (Map.Entry x : getFeyCraftingRecipes().entrySet()) { + if (ItemStack.areItemsEqual(x.getValue().getResult(), output)) { + getFeyCraftingRecipes().remove(x.getKey()); + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + } + return false; + } + + public void removeAll() { + getFeyCraftingRecipes().forEach((key, value) -> addBackup(Pair.of(key, value))); + getFeyCraftingRecipes().clear(); + } + + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(getFeyCraftingRecipes().entrySet()) + .setRemover(r -> this.removeByName(r.getKey())); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder { + + private int xp = 0; + private ResourceLocation name; + + public RecipeBuilder xp(int xp) { + this.xp = xp; + return this; + } + + public RecipeBuilder name(String name) { + this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); + return this; + } + + public RecipeBuilder name(ResourceLocation name) { + this.name = name; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Roots Fey Crafter recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 5, 5, 1, 1); + validateFluids(msg); + msg.add(xp < 0, "xp must be a nonnegative integer, yet it was {}", xp); + if (name == null) { + name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_fey_crafter_")); + } + } + + @Override + public @Nullable FeyCraftingRecipe register() { + if (!validate()) return null; + FeyCraftingRecipe recipe = new FeyCraftingRecipe(output.get(0), xp); + input.forEach(i -> recipe.addIngredient(i.toMcIngredient())); + ModSupport.ROOTS.get().feyCrafter.add(name, recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/FlowerGeneration.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/FlowerGeneration.java new file mode 100644 index 000000000..9b572282e --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/FlowerGeneration.java @@ -0,0 +1,174 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.helper.recipe.RecipeName; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.recipe.FlowerRecipe; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.ResourceLocation; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static epicsquid.roots.init.ModRecipes.getFlowerRecipes; + + +public class FlowerGeneration extends VirtualizedRegistry> { + + public FlowerGeneration() { + super(); + } + + public static RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(pair -> getFlowerRecipes().remove(pair.getKey())); + restoreFromBackup().forEach(pair -> getFlowerRecipes().put(pair.getKey(), pair.getValue())); + } + + public void add(String name, FlowerRecipe recipe) { + add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + } + + public void add(ResourceLocation name, FlowerRecipe recipe) { + getFlowerRecipes().put(name, recipe); + addScripted(Pair.of(name, recipe)); + } + + public ResourceLocation findRecipe(FlowerRecipe recipe) { + for (Map.Entry entry : getFlowerRecipes().entrySet()) { + if (entry.getValue().equals(recipe)) return entry.getKey(); + } + return null; + } + + public boolean removeByName(ResourceLocation name) { + FlowerRecipe recipe = getFlowerRecipes().get(name); + if (recipe == null) return false; + getFlowerRecipes().remove(name); + addBackup(Pair.of(name, recipe)); + return true; + } + + public boolean removeByFlower(IBlockState flower) { + for (Map.Entry x : getFlowerRecipes().entrySet()) { + if (x.getValue().getFlower() == flower) { + getFlowerRecipes().remove(x.getKey()); + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + } + return false; + } + + public boolean removeByFlower(Block flower, int meta) { + return removeByFlower(flower.getStateFromMeta(meta)); + } + + public boolean removeByFlower(Block flower) { + boolean found = false; + for (IBlockState state : flower.getBlockState().getValidStates()) { + if (removeByFlower(state)) found = true; + } + return found; + } + + public boolean removeByFlower(ItemStack output) { + return removeByFlower(((ItemBlock) output.getItem()).getBlock().getStateFromMeta(output.getMetadata())); + } + + public void removeAll() { + getFlowerRecipes().forEach((key, value) -> addBackup(Pair.of(key, value))); + getFlowerRecipes().clear(); + } + + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(getFlowerRecipes().entrySet()) + .setRemover(r -> this.removeByName(r.getKey())); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder { + + private IBlockState flower; + private final List allowedSoils = new ArrayList<>(); + private ResourceLocation name; + + public RecipeBuilder flower(IBlockState flower) { + this.flower = flower; + return this; + } + + public RecipeBuilder flower(Block flower, int meta) { + this.flower = flower.getStateFromMeta(meta); + return this; + } + + /* + public RecipeBuilder allowedSoils(IIngredient allowedSoils) { + this.allowedSoils.add(allowedSoils.toMcIngredient()); + return this; + } + + public RecipeBuilder allowedSoils(IIngredient... allowedSoilss) { + for (IIngredient allowedSoils : allowedSoilss) { + allowedSoils(allowedSoils); + } + return this; + } + + public RecipeBuilder allowedSoils(Collection allowedSoilss) { + for (IIngredient allowedSoils : allowedSoilss) { + allowedSoils(allowedSoils); + } + return this; + } + */ + + public RecipeBuilder name(String name) { + this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); + return this; + } + + public RecipeBuilder name(ResourceLocation name) { + this.name = name; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Roots Flower Generation recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg); + validateFluids(msg); + msg.add(flower == null, "flower must be defined"); + if (name == null) { + name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_flower_generation_recipe_")); + } + } + + @Override + public @Nullable FlowerRecipe register() { + if (!validate()) return null; + FlowerRecipe recipe = new FlowerRecipe(name, flower, allowedSoils); + ModSupport.ROOTS.get().flowerGeneration.add(name, recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/LifeEssence.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/LifeEssence.java new file mode 100644 index 000000000..a94bf7270 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/LifeEssence.java @@ -0,0 +1,57 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import net.minecraft.entity.EntityLivingBase; +import net.minecraftforge.fml.common.registry.EntityEntry; + +import static epicsquid.roots.init.ModRecipes.getLifeEssenceList; + +public class LifeEssence extends VirtualizedRegistry> { + + public LifeEssence() { + super(); + } + + @Override + public void onReload() { + removeScripted().forEach(getLifeEssenceList()::remove); + restoreFromBackup().forEach(getLifeEssenceList()::add); + } + + public void add(Class clazz) { + getLifeEssenceList().add(clazz); + addScripted(clazz); + } + + public void add(EntityLivingBase entity) { + add(entity.getClass()); + } + + public void add(EntityEntry entity) { + add((Class) entity.getEntityClass()); + } + + public boolean remove(Class clazz) { + if (!getLifeEssenceList().remove(clazz)) return false; + addBackup(clazz); + return true; + } + + public boolean remove(EntityLivingBase entity) { + return remove(entity.getClass()); + } + + public boolean remove(EntityEntry entity) { + return remove((Class) entity.getEntityClass()); + } + + public void removeAll() { + getLifeEssenceList().forEach(this::addBackup); + getLifeEssenceList().clear(); + } + + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(getLifeEssenceList()).setRemover(this::remove); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Modifiers.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Modifiers.java new file mode 100644 index 000000000..ba81cea0b --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Modifiers.java @@ -0,0 +1,109 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.core.mixin.roots.ModifierRegistryAccessor; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.modifiers.Modifier; +import epicsquid.roots.modifiers.ModifierRegistry; +import epicsquid.roots.spell.SpellBase; +import net.minecraft.util.ResourceLocation; + +public class Modifiers extends VirtualizedRegistry { + + public Modifiers() { + super(); + } + + @Override + public void onReload() { + removeScripted().forEach(ModifierRegistryAccessor.getDisabledModifiers()::remove); + restoreFromBackup().forEach(ModifierRegistryAccessor.getDisabledModifiers()::add); + } + + public boolean disable(String name) { + return disable(name.contains(":") ? new ResourceLocation(name) : new ResourceLocation("roots", name)); + } + + public boolean disable(ResourceLocation rl) { + Modifier modifier = ModifierRegistry.get(rl); + if (modifier == null) { + GroovyLog.msg("Error disabling modifier {}", rl).error().post(); + } else { + ModifierRegistry.disable(modifier); + addScripted(modifier.getRegistryName()); + return true; + } + return false; + } + + public boolean disable(Modifier modifier) { + if (ModifierRegistry.get(modifier) == null) { + GroovyLog.msg("Error disabling modifier {}", modifier).error().post(); + return false; + } + ModifierRegistry.disable(modifier); + addScripted(modifier.getRegistryName()); + return true; + } + + public boolean disable(SpellBase spell) { + for (Modifier mod : spell.getModifiers()) { + ModifierRegistry.disable(mod); + addScripted(mod.getRegistryName()); + } + return true; + } + + public boolean enable(String name) { + return enable(name.contains(":") ? new ResourceLocation(name) : new ResourceLocation("roots", name)); + } + + public boolean enable(ResourceLocation rl) { + Modifier modifier = ModifierRegistry.get(rl); + if (modifier == null) { + GroovyLog.msg("Error enabling modifier {}", rl).error().post(); + } else { + ModifierRegistryAccessor.getDisabledModifiers().remove(rl); + addBackup(rl); + return true; + } + return false; + } + + public boolean enable(Modifier modifier) { + if (ModifierRegistry.get(modifier) == null) { + GroovyLog.msg("Error enabling modifier {}", modifier).error().post(); + return false; + } + ModifierRegistryAccessor.getDisabledModifiers().remove(modifier.getRegistryName()); + addScripted(modifier.getRegistryName()); + return true; + } + + public boolean enable(SpellBase spell) { + for (Modifier mod : spell.getModifiers()) { + ModifierRegistryAccessor.getDisabledModifiers().remove(mod.getRegistryName()); + addBackup(mod.getRegistryName()); + } + return true; + } + + public void disableAll() { + for (Modifier mod : ModifierRegistry.getModifiers()) { + ModifierRegistry.disable(mod); + addScripted(mod.getRegistryName()); + } + } + + public void enableAll() { + for (Modifier mod : ModifierRegistry.getModifiers()) { + ModifierRegistryAccessor.getDisabledModifiers().remove(mod.getRegistryName()); + addBackup(mod.getRegistryName()); + } + } + + public SimpleObjectStream streamRecipes() { + return new SimpleObjectStream<>(ModifierRegistryAccessor.getDisabledModifiers()).setRemover(this::disable); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Mortar.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Mortar.java new file mode 100644 index 000000000..dc174e232 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Mortar.java @@ -0,0 +1,259 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.core.mixin.roots.ModRecipesAccessor; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.helper.recipe.RecipeName; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.recipe.MortarRecipe; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.ResourceLocation; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +import static epicsquid.roots.init.ModRecipes.addMortarRecipe; +import static epicsquid.roots.init.ModRecipes.getMortarRecipes; + +public class Mortar extends VirtualizedRegistry> { + + public Mortar() { + super(VirtualizedRegistry.generateAliases("MortarAndPestle")); + } + + public static RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(pair -> ModRecipesAccessor.getMortarRecipes().remove(pair.getKey())); + restoreFromBackup().forEach(pair -> addMortarRecipe(pair.getValue())); + } + + public void add(String name, MortarRecipe recipe) { + add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + } + + public void add(ResourceLocation name, MortarRecipe recipe) { + addMortarRecipe(recipe); + addScripted(Pair.of(name, recipe)); + } + + public ResourceLocation findRecipe(MortarRecipe recipe) { + for (MortarRecipe entry : getMortarRecipes()) { + if (entry.matches(recipe.getRecipe())) return entry.getRegistryName(); + } + return null; + } + + public ResourceLocation findRecipeByOutput(ItemStack output) { + for (MortarRecipe entry : getMortarRecipes()) { + if (ItemStack.areItemsEqual(entry.getResult(), output)) return entry.getRegistryName(); + } + return null; + } + + public boolean removeByName(ResourceLocation name) { + return ModRecipesAccessor.getMortarRecipes().entrySet().removeIf(x -> { + // Some Mortar recipe names are generated via [base]_x. If we are removing eg "wheat_flour" we should detect and remove all 5 variants + if (x.getKey().equals(name) || x.getKey().toString().startsWith(name.toString())) { + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + return false; + }); + } + + public boolean removeByOutput(ItemStack output) { + return ModRecipesAccessor.getMortarRecipes().entrySet().removeIf(x -> { + if (ItemStack.areItemsEqual(x.getValue().getResult(), output)) { + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + return false; + }); + } + + public void removeAll() { + ModRecipesAccessor.getMortarRecipes().forEach((key, value) -> addBackup(Pair.of(key, value))); + ModRecipesAccessor.getMortarRecipes().clear(); + } + + + public SimpleObjectStream streamRecipes() { + return new SimpleObjectStream<>(getMortarRecipes()) + .setRemover(r -> this.removeByName(r.getRegistryName())); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder { + + private float red1 = 1.0F; + private float green1 = 1.0F; + private float blue1 = 1.0F; + private float red2 = 1.0F; + private float green2 = 1.0F; + private float blue2 = 1.0F; + private boolean generate = true; + private ResourceLocation name; + + public RecipeBuilder red1(float red1) { + this.red1 = red1; + return this; + } + + public RecipeBuilder green1(float green1) { + this.green1 = green1; + return this; + } + + public RecipeBuilder blue1(float blue1) { + this.blue1 = blue1; + return this; + } + + public RecipeBuilder red2(float red2) { + this.red2 = red2; + return this; + } + + public RecipeBuilder green2(float green2) { + this.green2 = green2; + return this; + } + + public RecipeBuilder blue2(float blue2) { + this.blue2 = blue2; + return this; + } + + public RecipeBuilder red(float red1, float red2) { + this.red1 = red1; + this.red2 = red2; + return this; + } + + public RecipeBuilder red(float red) { + this.red1 = red; + this.red2 = red; + return this; + } + + public RecipeBuilder green(float green1, float green2) { + this.green1 = green1; + this.green2 = green2; + return this; + } + + public RecipeBuilder green(float green) { + this.green1 = green; + this.green2 = green; + return this; + } + + public RecipeBuilder blue(float blue1, float blue2) { + this.blue1 = blue1; + this.blue2 = blue2; + return this; + } + + public RecipeBuilder blue(float blue) { + this.blue1 = blue; + this.blue2 = blue; + return this; + } + + public RecipeBuilder color(float red1, float green1, float blue1, float red2, float green2, float blue2) { + this.red1 = red1; + this.red2 = red2; + this.green1 = green1; + this.green2 = green2; + this.blue1 = blue1; + this.blue2 = blue2; + return this; + } + + public RecipeBuilder color(float red, float green, float blue) { + this.red1 = red; + this.red2 = red; + this.green1 = green; + this.green2 = green; + this.blue1 = blue; + this.blue2 = blue; + return this; + } + + public RecipeBuilder generate(boolean generate) { + this.generate = generate; + return this; + } + + public RecipeBuilder generate() { + this.generate = !this.generate; + return this; + } + + public RecipeBuilder name(String name) { + this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); + return this; + } + + public RecipeBuilder name(ResourceLocation name) { + this.name = name; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Roots Pyre recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 1, 5, 1, 1); + validateFluids(msg); + msg.add(red1 < 0 || red1 > 1, "red1 must be a float between 0 and 1, yet it was {}", red1); + msg.add(green1 < 0 || green1 > 1, "green1 must be a float between 0 and 1, yet it was {}", green1); + msg.add(blue1 < 0 || blue1 > 1, "blue1 must be a float between 0 and 1, yet it was {}", blue1); + msg.add(red2 < 0 || red2 > 1, "red2 must be a float between 0 and 1, yet it was {}", red2); + msg.add(green2 < 0 || green2 > 1, "green2 must be a float between 0 and 1, yet it was {}", green2); + msg.add(blue2 < 0 || blue2 > 1, "blue2 must be a float between 0 and 1, yet it was {}", blue2); + if (name == null) { + name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_mortar_recipe_")); + } + } + + @Override + public @Nullable MortarRecipe register() { + if (!validate()) return null; + + if (input.size() == 1 && generate) { + List ingredients = new ArrayList<>(); + int count = output.get(0).getCount(); + + for (int i = 1; i <= 5; i++ ) { + ingredients.add(input.get(0).toMcIngredient()); + ItemStack copy = output.get(0).copy(); + copy.setCount(i * count); + MortarRecipe recipe = new MortarRecipe(copy, ingredients.toArray(new Ingredient[0]), red1, green1, blue1, red2, green2, blue2); + recipe.setRegistryName(new ResourceLocation(name.toString() + "_" + i)); + ModSupport.ROOTS.get().mortar.add(recipe.getRegistryName(), recipe); + } + return null; + } + + MortarRecipe recipe = new MortarRecipe(output.get(0), input.stream().map(IIngredient::toMcIngredient).toArray(Ingredient[]::new), red1, red2, green1, green2, blue1, blue2); + recipe.setRegistryName(name); + ModSupport.ROOTS.get().mortar.add(name, recipe); + return recipe; + + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Moss.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Moss.java new file mode 100644 index 000000000..c58feab79 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Moss.java @@ -0,0 +1,124 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.core.mixin.roots.MossConfigAccessor; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.mysticallib.util.ConfigUtil; +import net.minecraft.block.Block; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +import static epicsquid.roots.config.MossConfig.MossyCobblestones; + +public class Moss extends VirtualizedRegistry> { + + public Moss() { + super(); + // Roots adds the default ingredients after we have to, but only does so if mossyCobblestones is null. + // So we define it here to prevent NPEs and make sure we still respect the config. + // Probably a better way to do this, but it works. + if (MossConfigAccessor.getMossyCobblestones() == null) { + MossConfigAccessor.setMossyCobblestones(ConfigUtil.parseMap(new HashMap<>(), ConfigUtil::parseItemStack, ConfigUtil::parseItemStack, ",", MossyCobblestones)); + } + } + + public static RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(pair -> MossConfigAccessor.getMossyCobblestones().remove(pair.getKey(), pair.getValue())); + restoreFromBackup().forEach(pair -> MossConfigAccessor.getMossyCobblestones().put(pair.getKey(), pair.getValue())); + Moss.reload(); + } + + public static void reload() { + MossConfigAccessor.getMossyBlocks().clear(); + MossConfigAccessor.getMossyStates().clear(); + + for (Map.Entry entry : MossConfigAccessor.getMossyCobblestones().entrySet()) { + ItemStack in = entry.getKey(); + ItemStack out = entry.getValue(); + + if (!(in.getItem() instanceof ItemBlock) || !(out.getItem() instanceof ItemBlock)) continue; + + Block blockIn = ((ItemBlock) in.getItem()).getBlock(); + Block blockOut = ((ItemBlock) out.getItem()).getBlock(); + + if (in.getMetadata() == 0 && out.getMetadata() == 0) { + MossConfigAccessor.getMossyBlocks().put(blockIn, blockOut); + } else { + MossConfigAccessor.getMossyStates().put(blockIn.getStateFromMeta(in.getMetadata()), blockOut.getStateFromMeta(out.getMetadata())); + } + } + + } + + public void add(ItemStack in, ItemStack out) { + MossConfigAccessor.getMossyCobblestones().put(in, out); + addScripted(Pair.of(in, out)); + Moss.reload(); + } + + public boolean remove(ItemStack in, ItemStack out) { + if (MossConfigAccessor.getMossyCobblestones().remove(in, out)) { + addBackup(Pair.of(in, out)); + Moss.reload(); + return true; + } + return false; + } + + public boolean remove(ItemStack in) { + ItemStack out = MossConfigAccessor.getMossyCobblestones().remove(in); + if (out != null) { + addBackup(Pair.of(in, out)); + Moss.reload(); + return true; + } + return false; + } + + public void removeAll() { + MossConfigAccessor.getMossyCobblestones().forEach((in, out) -> addBackup(Pair.of(in, out))); + MossConfigAccessor.getMossyCobblestones().clear(); + Moss.reload(); + } + + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(MossConfigAccessor.getMossyCobblestones().entrySet()).setRemover(r -> this.remove(r.getKey())); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder> { + + @Override + public String getErrorMsg() { + return "Error adding Roots Moss conversion"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 1, 1, 1, 1); + validateFluids(msg); + msg.add(!(input.get(0).getMatchingStacks()[0].getItem() instanceof ItemBlock), "input must be an instance of ItemBlock"); + msg.add(!(output.get(0).getItem() instanceof ItemBlock), "output must be an instance of ItemBlock"); + } + + @Override + public @Nullable Pair register() { + if (!validate()) return null; + ModSupport.ROOTS.get().moss.add(input.get(0).getMatchingStacks()[0], output.get(0)); + Moss.reload(); + return Pair.of(input.get(0).getMatchingStacks()[0], output.get(0)); + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Pacifist.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Pacifist.java new file mode 100644 index 000000000..f706e2a40 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Pacifist.java @@ -0,0 +1,123 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.helper.recipe.RecipeName; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.recipe.PacifistEntry; +import net.minecraft.entity.Entity; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.common.registry.EntityEntry; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +import static epicsquid.roots.init.ModRecipes.getPacifistEntities; + +public class Pacifist extends VirtualizedRegistry> { + + public Pacifist() { + super(); + } + + public static RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(pair -> getPacifistEntities().remove(pair.getKey())); + restoreFromBackup().forEach(pair -> getPacifistEntities().put(pair.getKey(), pair.getValue())); + } + + public void add(String name, PacifistEntry recipe) { + add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + } + + public void add(ResourceLocation name, PacifistEntry recipe) { + getPacifistEntities().put(name, recipe); + addScripted(Pair.of(name, recipe)); + } + + public ResourceLocation findRecipe(PacifistEntry recipe) { + for (Map.Entry entry : getPacifistEntities().entrySet()) { + if (entry.getValue().equals(recipe)) return entry.getKey(); + } + return null; + } + + public boolean removeByName(ResourceLocation name) { + PacifistEntry recipe = getPacifistEntities().get(name); + if (recipe == null) return false; + getPacifistEntities().remove(name); + addBackup(Pair.of(name, recipe)); + return true; + } + + public boolean removeByEntity(EntityEntry entity) { + return removeByClass(entity.getEntityClass()); + } + + public boolean removeByClass(Class clazz) { + return getPacifistEntities().entrySet().removeIf(x -> { + if (x.getValue().getEntityClass().equals(clazz)) { + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + return false; + }); + } + + public void removeAll() { + getPacifistEntities().forEach((key, value) -> addBackup(Pair.of(key, value))); + getPacifistEntities().clear(); + } + + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(getPacifistEntities().entrySet()) + .setRemover(r -> this.removeByName(r.getKey())); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder { + + private Class entity; + private String name; + + public RecipeBuilder entity(EntityEntry entity) { + this.entity = entity.getEntityClass(); + return this; + } + + public RecipeBuilder name(String name) { + this.name = name; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Roots Runic Shear Entity recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg); + validateFluids(msg); + msg.add(entity == null, "entity must be defined"); + if (name == null) { + name = RecipeName.generate("groovyscript_pacifist_"); + } + } + + @Override + public @Nullable PacifistEntry register() { + if (!validate()) return null; + PacifistEntry recipe = new PacifistEntry(entity, name); + ModSupport.ROOTS.get().pacifist.add(recipe.getRegistryName(), recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Predicates.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Predicates.java new file mode 100644 index 000000000..3bec5c17c --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Predicates.java @@ -0,0 +1,126 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.recipe.transmutation.*; +import net.minecraft.block.Block; +import net.minecraft.block.state.BlockStateContainer; +import net.minecraft.block.state.IBlockState; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.stream.Collectors; + +public class Predicates extends VirtualizedRegistry { + + public WorldBlockStatePredicate ANY = WorldBlockStatePredicate.TRUE; + public WorldBlockStatePredicate TRUE = WorldBlockStatePredicate.TRUE; + public BlocksPredicate LAVA = new LavaPredicate(); + public BlocksPredicate WATER = new WaterPredicate(); + public LeavesPredicate LEAVES = new LeavesPredicate(); + + public Predicates() { + super(); + } + + @Override + public void onReload() { + } + + public StateBuilder stateBuilder() { + return new StateBuilder(); + } + + StatePredicate create(IBlockState blockState) { + return new StatePredicate(blockState); + } + + PropertyPredicate create(IBlockState blockState, String... properties) { + return new PropertyPredicate(blockState, Arrays.stream(properties).map(x -> blockState.getBlock().getBlockState().getProperty(x)).filter(Objects::nonNull).collect(Collectors.toList())); + } + + PropertyPredicate create(IBlockState blockState, Collection properties) { + return new PropertyPredicate(blockState, properties.stream().map(x -> blockState.getBlock().getBlockState().getProperty(x)).filter(Objects::nonNull).collect(Collectors.toList())); + } + + WorldBlockStatePredicate above(BlockStatePredicate blockState) { + return new BlockStateAbove(blockState); + } + + WorldBlockStatePredicate below(BlockStatePredicate blockState) { + return new BlockStateBelow(blockState); + } + + public static class StateBuilder extends AbstractRecipeBuilder { + + private final Collection properties = new ArrayList<>(); + private IBlockState blockstate; + private boolean above = false; + private boolean below = false; + + public StateBuilder blockstate(IBlockState blockstate) { + this.blockstate = blockstate; + return this; + } + + public StateBuilder block(Block block) { + this.blockstate = block.getDefaultState(); + return this; + } + + public StateBuilder properties(String... properties) { + Collections.addAll(this.properties, properties); + return this; + } + + public StateBuilder properties(Collection properties) { + this.properties.addAll(properties); + return this; + } + + public StateBuilder above() { + this.above = true; + return this; + } + + public StateBuilder below() { + this.below = true; + return this; + } + + @Override + public String getErrorMsg() { + return "Error creating Roots Predicate"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg); + validateFluids(msg); + msg.add(above && below, "both above and below cannot be true"); + msg.add(blockstate == null, "blockstate must be defined"); + + BlockStateContainer container = blockstate.getBlock().getBlockState(); + properties.forEach(prop -> { + if (container.getProperty(prop) == null) { + msg.add("property {} is not a property of the provided blockstate {}", prop, blockstate); + } + }); + } + + @Override + public @Nullable MatchingStates register() { + if (!validate()) return null; + BlockStateContainer container = blockstate.getBlock().getBlockState(); + + BlockStatePredicate predicate = properties.isEmpty() + ? new StatePredicate(blockstate) + : new PropertyPredicate(blockstate, properties.stream().map(container::getProperty).collect(Collectors.toList())); + + if (above) return new BlockStateAbove(predicate); + if (below) return new BlockStateBelow(predicate); + return predicate; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Pyre.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Pyre.java new file mode 100644 index 000000000..79ab64ba4 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Pyre.java @@ -0,0 +1,149 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.helper.recipe.RecipeName; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.recipe.PyreCraftingRecipe; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +import static epicsquid.roots.init.ModRecipes.*; + +public class Pyre extends VirtualizedRegistry> { + + public Pyre() { + super(); + } + + public static RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(pair -> removePyreCraftingRecipe(pair.getKey())); + restoreFromBackup().forEach(pair -> addPyreCraftingRecipe(pair.getKey(), pair.getValue())); + } + + public void add(String name, PyreCraftingRecipe recipe) { + add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + } + + public void add(ResourceLocation name, PyreCraftingRecipe recipe) { + addPyreCraftingRecipe(name, recipe); + addScripted(Pair.of(name, recipe)); + } + + public ResourceLocation findRecipe(PyreCraftingRecipe recipe) { + for (Map.Entry entry : getPyreCraftingRecipes().entrySet()) { + if (entry.getValue().matches(recipe.getRecipe())) return entry.getKey(); + } + return null; + } + + public ResourceLocation findRecipeByOutput(ItemStack output) { + for (Map.Entry entry : getPyreCraftingRecipes().entrySet()) { + if (ItemStack.areItemsEqual(entry.getValue().getResult(), output)) return entry.getKey(); + } + return null; + } + + public boolean removeByName(ResourceLocation name) { + PyreCraftingRecipe recipe = getCraftingRecipe(name); + if (recipe == null) return false; + removePyreCraftingRecipe(name); + addBackup(Pair.of(name, recipe)); + return true; + } + + public boolean removeByOutput(ItemStack output) { + for (Map.Entry x : getPyreCraftingRecipes().entrySet()) { + if (ItemStack.areItemsEqual(x.getValue().getResult(), output)) { + getPyreCraftingRecipes().remove(x.getKey()); + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + } + return false; + } + + public void removeAll() { + getPyreCraftingRecipes().forEach((key, value) -> addBackup(Pair.of(key, value))); + getPyreCraftingRecipes().clear(); + } + + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(getPyreCraftingRecipes().entrySet()) + .setRemover(r -> this.removeByName(r.getKey())); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder { + + private int xp = 0; + private int burnTime = 200; + private ResourceLocation name; + + public RecipeBuilder xp(int xp) { + this.xp = xp; + return this; + } + + public RecipeBuilder levels(int levels) { + this.xp = levels; + return this; + } + + public RecipeBuilder burnTime(int burnTime) { + this.burnTime = burnTime; + return this; + } + + public RecipeBuilder time(int time) { + return this.burnTime(time); + } + + public RecipeBuilder name(String name) { + this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); + return this; + } + + public RecipeBuilder name(ResourceLocation name) { + this.name = name; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Roots Pyre recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 5, 5, 1, 1); + validateFluids(msg); + msg.add(xp < 0, "xp must be a nonnegative integer, yet it was {}", xp); + if (name == null) { + name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_pyre_recipe_")); + } + } + + @Override + public @Nullable PyreCraftingRecipe register() { + if (!validate()) return null; + PyreCraftingRecipe recipe = new PyreCraftingRecipe(output.get(0), xp); + input.forEach(i -> recipe.addIngredient(i.toMcIngredient())); + recipe.setBurnTime(this.burnTime); + recipe.setRegistryName(name); + ModSupport.ROOTS.get().pyre.add(name, recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Rituals.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Rituals.java new file mode 100644 index 000000000..cf7ea12c9 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Rituals.java @@ -0,0 +1,151 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.core.mixin.roots.RitualBaseAccessor; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.properties.Property; +import epicsquid.roots.properties.PropertyTable; +import epicsquid.roots.ritual.RitualBase; +import epicsquid.roots.ritual.RitualRegistry; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +public class Rituals extends VirtualizedRegistry { + + public Rituals() { + super(); + } + + public static RitualWrapper ritual(String ritual) { + return ritual(RitualRegistry.getRitual(ritual)); + } + + public static RitualWrapper ritual(RitualBase ritual) { + return new RitualWrapper(ritual); + } + + public static RitualWrapper.RecipeBuilder recipeBuilder() { + return new RitualWrapper.RecipeBuilder(); + } + + @Override + public void onReload() { + // TODO Roots: I don't have a good idea for how to implement reloading here + } + + public void disableAll() { + RitualRegistry.getRituals().forEach(r -> { + ((RitualBaseAccessor) r).setDisabled(true); + r.setRecipe(RitualBase.RitualRecipe.EMPTY); + }); + } + + public static class RitualWrapper { + + private final RitualBase ritual; + + public RitualWrapper(String name) { + this.ritual = RitualRegistry.getRitual(name); + } + + public RitualWrapper(RitualBase ritual) { + this.ritual = ritual; + } + + public RitualWrapper recipe(IIngredient... input) { + if (ritual == null) { + GroovyLog.msg("Error modifying Roots Ritual recipe").add("No ritual specified when recipe change requested.").error().post(); + } else { + new RecipeBuilder(ritual).input(input).register(); + } + return this; + } + + public RitualWrapper recipe(Collection input) { + if (ritual == null) { + GroovyLog.msg("Error modifying Roots Ritual recipe").add("No ritual specified when recipe change requested.").error().post(); + } else { + new RecipeBuilder(ritual).input(input).register(); + } + return this; + } + + public RitualWrapper setDisabled() { + ((RitualBaseAccessor) this.ritual).setDisabled(true); + return this; + } + + public RitualWrapper setEnabled() { + ((RitualBaseAccessor) this.ritual).setDisabled(false); + return this; + } + + public RitualWrapper set(String propertyName, T value) { + PropertyTable table = this.ritual.getProperties(); + Property prop = table.get(propertyName); + if (prop == null) GroovyLog.msg("Property {} was undefined for ritual {}", propertyName, ritual).error().post(); + else table.set(prop, value); + return this; + } + + public RitualWrapper setProperty(String propertyName, double value) { + return this.set(propertyName, value); + } + + public RitualWrapper setProperty(String propertyName, float value) { + return this.set(propertyName, value); + } + + public RitualWrapper setProperty(String propertyName, int value) { + return this.set(propertyName, value); + } + + public RitualWrapper setProperty(String propertyName, String value) { + return this.set(propertyName, value); + } + + public RitualWrapper setDuration(int value) { + return this.set("duration", value); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder { + + private RitualBase ritual; + + public RecipeBuilder() { + } + + public RecipeBuilder(RitualBase ritual) { + this.ritual = ritual; + } + + public RecipeBuilder ritual(RitualBase ritual) { + this.ritual = ritual; + return this; + } + + @Override + public String getErrorMsg() { + return "Error creating Roots Ritual Recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 5, 5, 0, 0); + validateFluids(msg); + msg.add(ritual == null, "ritual must be defined"); + } + + @Override + public @Nullable RitualBase.RitualRecipe register() { + if (!validate()) return null; + RitualBase.RitualRecipe recipe = new RitualBase.RitualRecipe(ritual, input.stream().map(IIngredient::toMcIngredient).toArray()); + this.ritual.setRecipe(recipe); + return recipe; + } + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Roots.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Roots.java new file mode 100644 index 000000000..f746805cf --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Roots.java @@ -0,0 +1,71 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.brackets.BracketHandlerManager; +import com.cleanroommc.groovyscript.compat.mods.ModPropertyContainer; +import epicsquid.roots.init.HerbRegistry; +import epicsquid.roots.modifiers.CostType; +import epicsquid.roots.modifiers.ModifierRegistry; +import epicsquid.roots.ritual.RitualRegistry; +import epicsquid.roots.spell.SpellRegistry; +import net.minecraft.util.ResourceLocation; + +import java.util.Locale; + +public class Roots extends ModPropertyContainer { + + AnimalHarvest animalHarvest = new AnimalHarvest(); + AnimalHarvestFish animalHarvestFish = new AnimalHarvestFish(); + BarkCarving barkCarving = new BarkCarving(); + Chrysopoeia chrysopoeia = new Chrysopoeia(); + FeyCrafter feyCrafter = new FeyCrafter(); + FlowerGeneration flowerGeneration = new FlowerGeneration(); + LifeEssence lifeEssence = new LifeEssence(); + Modifiers modifiers = new Modifiers(); + Moss moss = new Moss(); + Mortar mortar = new Mortar(); + Pacifist pacifist = new Pacifist(); + Predicates predicates = new Predicates(); + Pyre pyre = new Pyre(); + Rituals rituals = new Rituals(); + RunicShearBlock runicShearBlock = new RunicShearBlock(); + RunicShearEntity runicShearEntity = new RunicShearEntity(); + Spells spells = new Spells(); + SummonCreature summonCreature = new SummonCreature(); + Transmutation transmutation = new Transmutation(); + + + public Roots() { + addRegistry(animalHarvest); + addRegistry(animalHarvestFish); + addRegistry(barkCarving); + addRegistry(chrysopoeia); + addRegistry(feyCrafter); + addRegistry(flowerGeneration); + addRegistry(lifeEssence); + addRegistry(modifiers); + addRegistry(moss); + addRegistry(mortar); + addRegistry(pacifist); + addRegistry(pyre); + addRegistry(predicates); + addRegistry(rituals); + addRegistry(runicShearBlock); + addRegistry(runicShearEntity); + addRegistry(spells); + addRegistry(summonCreature); + addRegistry(transmutation); + } + + @Override + public void initialize() { + BracketHandlerManager.registerBracketHandler("ritual", RitualRegistry::getRitual); + BracketHandlerManager.registerBracketHandler("herb", HerbRegistry::getHerbByName); + BracketHandlerManager.registerBracketHandler("cost", s -> CostType.valueOf(s.toUpperCase(Locale.ROOT))); + BracketHandlerManager.registerBracketHandler("spell", s -> { + if (s.contains(":")) return SpellRegistry.getSpell(new ResourceLocation(s)); + if (s.startsWith("spell_")) return SpellRegistry.getSpell(s); + return SpellRegistry.getSpell("spell_" + s); + }); + BracketHandlerManager.registerBracketHandler("modifier", s -> ModifierRegistry.get(new ResourceLocation(s))); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/RunicShearBlock.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/RunicShearBlock.java new file mode 100644 index 000000000..38fec7bad --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/RunicShearBlock.java @@ -0,0 +1,159 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.helper.recipe.RecipeName; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.recipe.RunicShearRecipe; +import epicsquid.roots.recipe.transmutation.BlockStatePredicate; +import epicsquid.roots.recipe.transmutation.StatePredicate; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +import static epicsquid.roots.init.ModRecipes.getRunicShearRecipes; + +public class RunicShearBlock extends VirtualizedRegistry> { + + public RunicShearBlock() { + super(); + } + + public static RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(pair -> getRunicShearRecipes().remove(pair.getKey())); + restoreFromBackup().forEach(pair -> getRunicShearRecipes().put(pair.getKey(), pair.getValue())); + } + + public void add(String name, RunicShearRecipe recipe) { + add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + } + + public void add(ResourceLocation name, RunicShearRecipe recipe) { + getRunicShearRecipes().put(name, recipe); + addScripted(Pair.of(name, recipe)); + } + + public ResourceLocation findRecipe(RunicShearRecipe recipe) { + for (Map.Entry entry : getRunicShearRecipes().entrySet()) { + if (entry.getValue().equals(recipe)) return entry.getKey(); + } + return null; + } + + public boolean removeByName(ResourceLocation name) { + RunicShearRecipe recipe = getRunicShearRecipes().get(name); + if (recipe == null) return false; + getRunicShearRecipes().remove(name); + addBackup(Pair.of(name, recipe)); + return true; + } + + public boolean removeByState(IBlockState state) { + for (Map.Entry x : getRunicShearRecipes().entrySet()) { + if (x.getValue().matches(state)) { + getRunicShearRecipes().remove(x.getKey()); + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + } + return false; + } + + public boolean removeByOutput(ItemStack output) { + for (Map.Entry x : getRunicShearRecipes().entrySet()) { + if (ItemStack.areItemsEqual(x.getValue().getDrop(), output)) { + getRunicShearRecipes().remove(x.getKey()); + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + } + return false; + } + + public void removeAll() { + getRunicShearRecipes().forEach((key, value) -> addBackup(Pair.of(key, value))); + getRunicShearRecipes().clear(); + } + + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(getRunicShearRecipes().entrySet()) + .setRemover(r -> this.removeByName(r.getKey())); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder { + + private ItemStack displayItem; + private BlockStatePredicate state; + private IBlockState replacementState; + private ResourceLocation name; + + public RecipeBuilder displayItem(ItemStack displayItem) { + this.displayItem = displayItem; + return this; + } + + public RecipeBuilder state(IBlockState state) { + this.state = new StatePredicate(state); + return this; + } + + public RecipeBuilder state(BlockStatePredicate state) { + this.state = state; + return this; + } + + public RecipeBuilder replacementState(IBlockState replacementState) { + this.replacementState = replacementState; + return this; + } + + public RecipeBuilder name(String name) { + this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); + return this; + } + + public RecipeBuilder name(ResourceLocation name) { + this.name = name; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Roots Runic Shear Block recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 0, 0, 1, 1); + validateFluids(msg); + msg.add(state == null, "state must be defined"); + msg.add(replacementState == null, "replacementState must be defined"); + if (displayItem == null) { + displayItem = state.matchingItems().get(0); + } + if (name == null) { + name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_runic_shear_block_")); + } + } + + @Override + public @Nullable RunicShearRecipe register() { + if (!validate()) return null; + RunicShearRecipe recipe = new RunicShearRecipe(name, state, replacementState, output.get(0), displayItem); + ModSupport.ROOTS.get().runicShearBlock.add(name, recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/RunicShearEntity.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/RunicShearEntity.java new file mode 100644 index 000000000..6130d2c0c --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/RunicShearEntity.java @@ -0,0 +1,159 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.helper.recipe.RecipeName; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.recipe.RunicShearConditionalEntityRecipe; +import epicsquid.roots.recipe.RunicShearEntityRecipe; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.common.registry.EntityEntry; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; + +import java.util.HashSet; +import java.util.Map; +import java.util.function.Function; + +import static epicsquid.roots.init.ModRecipes.getRunicShearEntityRecipes; + +public class RunicShearEntity extends VirtualizedRegistry> { + + public RunicShearEntity() { + super(); + } + + public static RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + // FIXME Not currently reloadable due to being controlled by the Capability RunicShearsCapabilityProvider + removeScripted().forEach(pair -> getRunicShearEntityRecipes().remove(pair.getKey())); + restoreFromBackup().forEach(pair -> getRunicShearEntityRecipes().put(pair.getKey(), pair.getValue())); + } + + public void add(String name, RunicShearEntityRecipe recipe) { + add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + } + + public void add(ResourceLocation name, RunicShearEntityRecipe recipe) { + getRunicShearEntityRecipes().put(name, recipe); + addScripted(Pair.of(name, recipe)); + } + + public ResourceLocation findRecipe(RunicShearEntityRecipe recipe) { + for (Map.Entry entry : getRunicShearEntityRecipes().entrySet()) { + if (entry.getValue().equals(recipe)) return entry.getKey(); + } + return null; + } + + public boolean removeByName(ResourceLocation name) { + RunicShearEntityRecipe recipe = getRunicShearEntityRecipes().get(name); + if (recipe == null) return false; + getRunicShearEntityRecipes().remove(name); + addBackup(Pair.of(name, recipe)); + return true; + } + + public boolean removeByOutput(ItemStack output) { + return getRunicShearEntityRecipes().entrySet().removeIf(x -> { + if (ItemStack.areItemsEqual(x.getValue().getDrop(), output)) { + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + return false; + }); + } + + public boolean removeByEntity(EntityEntry entity) { + return removeByEntity((Class) entity.getEntityClass()); + } + + public boolean removeByEntity(Class clazz) { + for (Map.Entry x : getRunicShearEntityRecipes().entrySet()) { + if (x.getValue().getClazz() == clazz) { + getRunicShearEntityRecipes().remove(x.getKey()); + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + } + return false; + } + + public void removeAll() { + getRunicShearEntityRecipes().forEach((key, value) -> addBackup(Pair.of(key, value))); + getRunicShearEntityRecipes().clear(); + } + + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(getRunicShearEntityRecipes().entrySet()) + .setRemover(r -> this.removeByName(r.getKey())); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder { + + private Class entity; + private int cooldown; + private Function functionMap; + private ResourceLocation name; + + public RecipeBuilder entity(EntityEntry entity) { + this.entity = (Class) entity.getEntityClass(); + return this; + } + + public RecipeBuilder cooldown(int cooldown) { + this.cooldown = cooldown; + return this; + } + + public RecipeBuilder functionMap(Function functionMap) { + this.functionMap = functionMap; + return this; + } + + public RecipeBuilder name(String name) { + this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); + return this; + } + + public RecipeBuilder name(ResourceLocation name) { + this.name = name; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Roots Runic Shear Entity recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + msg.add(!input.isEmpty(), () -> "No item inputs allowed, but found " + input.size()); + validateFluids(msg); + msg.add(output.size() > 1 && functionMap == null, "if output is greater than 1, functionMap must be defined"); + msg.add(entity == null , "entity must be defined and extended EntityLivingBase, instead it was {}", entity); + if (name == null) { + name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_runic_shear_entity_")); + } + } + + @Override + public @Nullable RunicShearEntityRecipe register() { + if (!validate()) return null; + RunicShearEntityRecipe recipe; + if (functionMap == null) recipe = new RunicShearEntityRecipe(name, output.get(0), entity, cooldown); + else recipe = new RunicShearConditionalEntityRecipe(name, functionMap, new HashSet<>(output), entity, cooldown); + ModSupport.ROOTS.get().runicShearEntity.add(name, recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Spells.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Spells.java new file mode 100644 index 000000000..4763444bc --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Spells.java @@ -0,0 +1,295 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.core.mixin.roots.ModifierAccessor; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.api.Herb; +import epicsquid.roots.config.SpellConfig; +import epicsquid.roots.modifiers.*; +import epicsquid.roots.properties.Property; +import epicsquid.roots.properties.PropertyTable; +import epicsquid.roots.spell.SpellBase; +import epicsquid.roots.spell.SpellRegistry; +import net.minecraft.util.ResourceLocation; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public class Spells extends VirtualizedRegistry { + + public Spells() { + super(); + } + + public static SpellWrapper spell(String spell) { + return new SpellWrapper(spell); + } + + public static SpellWrapper spell(ResourceLocation spell) { + return new SpellWrapper(spell); + } + + public static SpellWrapper spell(SpellBase spell) { + return new SpellWrapper(spell); + } + + public static SpellWrapper.RecipeBuilder recipeBuilder() { + return new SpellWrapper.RecipeBuilder(); + } + + public static CostBuilder costBuilder() { + return new CostBuilder(); + } + + @Override + public void onReload() { + // TODO Roots: I don't have a good idea for how to implement reloading here + } + + public void disableAll() { + SpellRegistry.getSpells().forEach(r -> r.setDisabled(true)); + } + + public static class SpellWrapper { + + private final SpellBase spell; + + public SpellWrapper(String name) { + ResourceLocation rl; + if (name.contains(":")) rl = new ResourceLocation(name); + else if (name.startsWith("spell_")) rl = new ResourceLocation("roots", name); + else rl = new ResourceLocation("roots", "spell_" + name); + this.spell = SpellRegistry.getSpell(rl); + } + + public SpellWrapper(ResourceLocation rl) { + this.spell = SpellRegistry.getSpell(rl); + } + + public SpellWrapper(SpellBase spell) { + this.spell = spell; + } + + public static RecipeBuilder recipe() { + return new RecipeBuilder(); + } + + public SpellWrapper recipe(IIngredient... input) { + if (spell == null) { + GroovyLog.msg("Error modifying Roots Spell recipe").add("No spell specified when recipe change requested.").error().post(); + } else { + new RecipeBuilder(spell).input(input).register(); + } + return this; + } + + public SpellWrapper recipe(Collection input) { + if (spell == null) { + GroovyLog.msg("Error modifying Roots Spell recipe").add("No spell specified when recipe change requested.").error().post(); + } else { + new RecipeBuilder(spell).input(input).register(); + } + return this; + } + + public SpellWrapper setDisabled() { + this.spell.setDisabled(true); + return this; + } + + public SpellWrapper setEnabled() { + this.spell.setDisabled(false); + return this; + } + + public SpellWrapper disableSound() { + SpellConfig.SpellSoundsCategory.SpellSound sound = new SpellConfig.SpellSoundsCategory.SpellSound(); + sound.enabled = false; + this.spell.setSound(sound); + return this; + } + + public SpellWrapper setSound(boolean enabled) { + SpellConfig.SpellSoundsCategory.SpellSound sound = new SpellConfig.SpellSoundsCategory.SpellSound(); + sound.enabled = enabled; + this.spell.setSound(sound); + return this; + } + + public SpellWrapper setSound(double volume) { + SpellConfig.SpellSoundsCategory.SpellSound sound = new SpellConfig.SpellSoundsCategory.SpellSound(); + sound.volume = volume; + this.spell.setSound(sound); + return this; + } + + public SpellWrapper setSound(boolean enabled, double volume) { + SpellConfig.SpellSoundsCategory.SpellSound sound = new SpellConfig.SpellSoundsCategory.SpellSound(); + sound.enabled = enabled; + sound.volume = volume; + this.spell.setSound(sound); + return this; + } + + public SpellWrapper set(String propertyName, T value) { + PropertyTable table = this.spell.getProperties(); + Property prop = table.get(propertyName); + if (prop == null) GroovyLog.msg("Property {} was undefined for spell {}", propertyName, spell.getName()).error().post(); + else table.set(prop, value); + return this; + } + + public SpellWrapper setProperty(String propertyName, double value) { + return this.set(propertyName, value); + } + + public SpellWrapper setProperty(String propertyName, float value) { + return this.set(propertyName, value); + } + + public SpellWrapper setProperty(String propertyName, int value) { + return this.set(propertyName, value); + } + + public SpellWrapper setProperty(String propertyName, String value) { + return this.set(propertyName, value); + } + + public SpellWrapper setCooldown(int value) { + return this.set("cooldown", value); + } + + public SpellWrapper setDamage(float value) { + return this.set("damage", value); + } + + public SpellWrapper setCost(Herb herb, double value) { + this.spell.getCosts().clear(); + this.spell.getCosts().put(herb, value); + return this; + } + + public SpellWrapper setSpellCost(Herb herb, double value) { + return this.setCost(herb, value); + } + + public SpellWrapper addCost(Herb herb, double value) { + this.spell.getCosts().put(herb, value); + return this; + } + + public SpellWrapper addSpellCost(Herb herb, double value) { + return this.addCost(herb, value); + } + + public SpellWrapper clearCost() { + this.spell.getCosts().clear(); + return this; + } + + public SpellWrapper clearSpellCost() { + return this.clearCost(); + } + + public SpellWrapper setModifierCost(Modifier mod, Map costs) { + ((ModifierAccessor) mod).getCosts().clear(); + ((ModifierAccessor) mod).getCosts().putAll(costs); + return this; + } + + public SpellWrapper addModifierCost(Modifier mod, Map costs) { + ((ModifierAccessor) mod).getCosts().putAll(costs); + return this; + } + + public SpellWrapper clearModifierCost(Modifier mod) { + ((ModifierAccessor) mod).getCosts().clear(); + return this; + } + + public static class RecipeBuilder extends AbstractRecipeBuilder { + + private SpellBase spell; + + public RecipeBuilder() { + } + + public RecipeBuilder(SpellBase spell) { + this.spell = spell; + } + + public RecipeBuilder spell(SpellBase spell) { + this.spell = spell; + return this; + } + + @Override + public String getErrorMsg() { + return "Error creating Roots Spell Recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 1, 5, 0, 0); + validateFluids(msg); + } + + @Override + public @Nullable SpellBase.SpellRecipe register() { + if (!validate()) return null; + SpellBase.SpellRecipe recipe = new SpellBase.SpellRecipe(input.stream().map(IIngredient::toMcIngredient).toArray()); + this.spell.setRecipe(recipe); + return recipe; + } + } + } + + public static class CostBuilder extends AbstractRecipeBuilder> { + + List list = new ArrayList<>(); + + public CostBuilder cost(CostType cost, double value, IModifierCore herb) { + list.add(new epicsquid.roots.modifiers.Cost(cost, value, herb)); + return this; + } + + public CostBuilder cost(CostType cost, IModifierCore herb, double value) { + return this.cost(cost, value, herb); + } + + public CostBuilder cost(CostType cost, Herb herb, double value) { + return this.cost(cost, value, ModifierCores.fromHerb(herb)); + } + + public CostBuilder cost(CostType cost, double value) { + return this.cost(cost, value, null); + } + + public CostBuilder cost(CostType cost) { + return this.cost(cost, 0.0, null); + } + + @Override + public String getErrorMsg() { + return "Error creating Roots Spell Cost"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg); + validateFluids(msg); + } + + @Override + public @Nullable Map register() { + if (!validate()) return null; + if (list.size() == 0) return epicsquid.roots.modifiers.Cost.noCost(); + return epicsquid.roots.modifiers.Cost.of(list.toArray(new IModifierCost[0])); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/SummonCreature.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/SummonCreature.java new file mode 100644 index 000000000..f932841de --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/SummonCreature.java @@ -0,0 +1,136 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.core.mixin.roots.ModRecipesAccessor; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.helper.recipe.RecipeName; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.recipe.SummonCreatureRecipe; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.common.registry.EntityEntry; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static epicsquid.roots.init.ModRecipes.*; + +public class SummonCreature extends VirtualizedRegistry> { + + public SummonCreature() { + super(); + } + + public static RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(pair -> removeSummonCreatureEntry(pair.getKey())); + restoreFromBackup().forEach(pair -> addSummonCreatureEntry(pair.getValue())); + } + + public void add(String name, SummonCreatureRecipe recipe) { + add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + } + + public void add(ResourceLocation name, SummonCreatureRecipe recipe) { + addSummonCreatureEntry(recipe); + addScripted(Pair.of(name, recipe)); + } + + public ResourceLocation findRecipe(SummonCreatureRecipe recipe) { + for (Map.Entry entry : ModRecipesAccessor.getSummonCreatureEntries().entrySet()) { + if (entry.getValue().equals(recipe)) return entry.getKey(); + } + return null; + } + + public boolean removeByName(ResourceLocation name) { + SummonCreatureRecipe recipe = getSummonCreatureEntry(name); + if (recipe == null) return false; + removeSummonCreatureEntry(name); + addBackup(Pair.of(name, recipe)); + return true; + } + + public boolean removeByEntity(EntityEntry entity) { + return removeByEntity((Class) entity.getEntityClass()); + } + + public boolean removeByEntity(Class clazz) { + for (Map.Entry x : ModRecipesAccessor.getSummonCreatureEntries().entrySet()) { + if (x.getValue().getClazz() == clazz) { + removeSummonCreatureEntry(x.getKey()); + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + } + return false; + } + + public void removeAll() { + ModRecipesAccessor.getSummonCreatureEntries().forEach((key, value) -> addBackup(Pair.of(key, value))); + ModRecipesAccessor.getSummonCreatureEntries().clear(); + ModRecipesAccessor.getSummonCreatureClasses().clear(); + } + + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(ModRecipesAccessor.getSummonCreatureEntries().entrySet()) + .setRemover(r -> this.removeByName(r.getKey())); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder { + + private Class entity; + private ResourceLocation name; + + public RecipeBuilder entity(EntityEntry entity) { + this.entity = (Class) entity.getEntityClass(); + return this; + } + + public RecipeBuilder name(String name) { + this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); + return this; + } + + public RecipeBuilder name(ResourceLocation name) { + this.name = name; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Roots Summon Creature recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 1, 10, 0, 0); + validateFluids(msg); + msg.add(entity == null, "entity must be defined"); + if (name == null) { + name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_summon_creature_")); + } + } + + @Override + public @Nullable SummonCreatureRecipe register() { + if (!validate()) return null; + List ingredients = input.stream().map(IIngredient::toMcIngredient).collect(Collectors.toList()); + SummonCreatureRecipe recipe = new SummonCreatureRecipe(name, entity, ingredients); + ModSupport.ROOTS.get().summonCreature.add(name, recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Transmutation.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Transmutation.java new file mode 100644 index 000000000..b6478755c --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Transmutation.java @@ -0,0 +1,188 @@ +package com.cleanroommc.groovyscript.compat.mods.roots; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.core.mixin.roots.ModRecipesAccessor; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.helper.recipe.RecipeName; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import epicsquid.roots.recipe.TransmutationRecipe; +import epicsquid.roots.recipe.transmutation.BlockStatePredicate; +import epicsquid.roots.recipe.transmutation.StatePredicate; +import epicsquid.roots.recipe.transmutation.WorldBlockStatePredicate; +import net.minecraft.block.properties.IProperty; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Map; +import java.util.Optional; + +import static epicsquid.roots.init.ModRecipes.removeTransmutationRecipe; + +public class Transmutation extends VirtualizedRegistry> { + + public Transmutation() { + super(); + } + + public static RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(pair -> removeTransmutationRecipe(pair.getKey())); + restoreFromBackup().forEach(pair -> ModRecipesAccessor.getTransmutationRecipes().put(pair.getKey(), pair.getValue())); + } + + public void add(String name, TransmutationRecipe recipe) { + add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + } + + public void add(ResourceLocation name, TransmutationRecipe recipe) { + ModRecipesAccessor.getTransmutationRecipes().put(name, recipe); + addScripted(Pair.of(name, recipe)); + } + + public ResourceLocation findRecipe(TransmutationRecipe recipe) { + for (Map.Entry entry : ModRecipesAccessor.getTransmutationRecipes().entrySet()) { + if (entry.getValue().equals(recipe)) return entry.getKey(); + } + return null; + } + + public boolean removeByName(ResourceLocation name) { + TransmutationRecipe recipe = ModRecipesAccessor.getTransmutationRecipes().get(name); + if (recipe == null) return false; + removeTransmutationRecipe(name); + addBackup(Pair.of(name, recipe)); + return true; + } + + public boolean removeByInput(IBlockState input) { + return ModRecipesAccessor.getTransmutationRecipes().entrySet().removeIf(x -> { + if (x.getValue().getStartPredicate().test(input)) { + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + return false; + }); + } + + public boolean removeByOutput(ItemStack output) { + return ModRecipesAccessor.getTransmutationRecipes().entrySet().removeIf(x -> { + if (ItemStack.areItemsEqual(x.getValue().getStack(), output)) { + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + return false; + }); + } + + public boolean removeByOutput(IBlockState output) { + return ModRecipesAccessor.getTransmutationRecipes().entrySet().removeIf(x -> { + Optional state = x.getValue().getState(); + if (!state.isPresent()) return false; + + Collection> incoming = output.getPropertyKeys(); + Collection> current = state.get().getPropertyKeys(); + + if (state.get().getBlock() == output.getBlock() && + output.getPropertyKeys().stream().allMatch(prop -> incoming.contains(prop) && + current.contains(prop) && + state.get().getValue(prop).equals(output.getValue(prop))) + ) { + addBackup(Pair.of(x.getKey(), x.getValue())); + return true; + } + return false; + }); + } + + public void removeAll() { + ModRecipesAccessor.getTransmutationRecipes().forEach((key, value) -> addBackup(Pair.of(key, value))); + ModRecipesAccessor.getTransmutationRecipes().clear(); + } + + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(ModRecipesAccessor.getTransmutationRecipes().entrySet()) + .setRemover(r -> this.removeByName(r.getKey())); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder { + + private BlockStatePredicate start; + private IBlockState state; + private WorldBlockStatePredicate condition = WorldBlockStatePredicate.TRUE; + private ResourceLocation name; + + public RecipeBuilder start(BlockStatePredicate start) { + this.start = start; + return this; + } + + public RecipeBuilder start(IBlockState start) { + this.start = new StatePredicate(start); + return this; + } + + public RecipeBuilder state(IBlockState state) { + this.state = state; + return this; + } + + public RecipeBuilder output(IBlockState state) { + this.state = state; + return this; + } + + public RecipeBuilder condition(WorldBlockStatePredicate condition) { + this.condition = condition; + return this; + } + + public RecipeBuilder name(String name) { + this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); + return this; + } + + public RecipeBuilder name(ResourceLocation name) { + this.name = name; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Roots Transmutation recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 0, 0, 0, 1); + validateFluids(msg); + msg.add(start == null, "start must be defined"); + msg.add(state == null && (output.size() != 1 || output.get(0).isEmpty()), "either state must be defined or recipe must have an output"); + if (name == null) { + name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_transmutation_")); + } + } + + @Override + public @Nullable TransmutationRecipe register() { + if (!validate()) return null; + TransmutationRecipe recipe = new TransmutationRecipe(start); + recipe.setRegistryName(name); + if (state == null) recipe.item(output.get(0)); + else recipe.state(state); + recipe.condition(condition); + ModSupport.ROOTS.get().transmutation.add(name, recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/core/LateMixin.java b/src/main/java/com/cleanroommc/groovyscript/core/LateMixin.java index 8d5517373..9058bcdb5 100644 --- a/src/main/java/com/cleanroommc/groovyscript/core/LateMixin.java +++ b/src/main/java/com/cleanroommc/groovyscript/core/LateMixin.java @@ -10,7 +10,7 @@ public class LateMixin implements ILateMixinLoader { - public static final List modMixins = ImmutableList.of("jei", "mekanism", "enderio", "thermalexpansion", "draconicevolution", "ic2_classic", "ic2_exp", "bloodmagic", "astralsorcery", "tconstruct", "tcomplement"); + public static final List modMixins = ImmutableList.of("jei", "roots", "mekanism", "enderio", "thermalexpansion", "draconicevolution", "ic2_classic", "ic2_exp", "bloodmagic", "astralsorcery", "tconstruct", "tcomplement"); @Override public List getMixinConfigs() { diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModRecipesAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModRecipesAccessor.java new file mode 100644 index 000000000..cb8c9f5ea --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModRecipesAccessor.java @@ -0,0 +1,43 @@ +package com.cleanroommc.groovyscript.core.mixin.roots; + + +import epicsquid.roots.init.ModRecipes; +import epicsquid.roots.recipe.ChrysopoeiaRecipe; +import epicsquid.roots.recipe.MortarRecipe; +import epicsquid.roots.recipe.SummonCreatureRecipe; +import epicsquid.roots.recipe.TransmutationRecipe; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.ResourceLocation; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Map; + +@Mixin(value = ModRecipes.class, remap = false) +public interface ModRecipesAccessor { + + @Accessor + static Map getChrysopoeiaRecipes() { + throw new AssertionError(); + } + + @Accessor + static Map getTransmutationRecipes() { + throw new AssertionError(); + } + + @Accessor("summonCreatureRecipes") + static Map getSummonCreatureEntries() { + throw new AssertionError(); + } + + @Accessor + static Map, SummonCreatureRecipe> getSummonCreatureClasses() { + throw new AssertionError(); + } + + @Accessor + static Map getMortarRecipes() { + throw new AssertionError(); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModifierAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModifierAccessor.java new file mode 100644 index 000000000..e3d164bc8 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModifierAccessor.java @@ -0,0 +1,16 @@ +package com.cleanroommc.groovyscript.core.mixin.roots; + +import epicsquid.roots.modifiers.CostType; +import epicsquid.roots.modifiers.IModifierCost; +import epicsquid.roots.modifiers.Modifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Map; + +@Mixin(Modifier.class) +public interface ModifierAccessor { + + @Accessor + Map getCosts(); +} diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModifierRegistryAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModifierRegistryAccessor.java new file mode 100644 index 000000000..9d7393a9e --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModifierRegistryAccessor.java @@ -0,0 +1,17 @@ +package com.cleanroommc.groovyscript.core.mixin.roots; + +import epicsquid.roots.modifiers.ModifierRegistry; +import net.minecraft.util.ResourceLocation; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Set; + +@Mixin(ModifierRegistry.class) +public interface ModifierRegistryAccessor { + + @Accessor + static Set getDisabledModifiers() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/MossConfigAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/MossConfigAccessor.java new file mode 100644 index 000000000..ca5000f7e --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/MossConfigAccessor.java @@ -0,0 +1,35 @@ +package com.cleanroommc.groovyscript.core.mixin.roots; + +import com.google.common.collect.BiMap; +import epicsquid.roots.config.MossConfig; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Map; + +@Mixin(MossConfig.class) +public interface MossConfigAccessor { + + @Accessor + static Map getMossyCobblestones() { + throw new UnsupportedOperationException(); + } + + @Accessor("mossyCobblestones") + static void setMossyCobblestones(Map map) { + throw new UnsupportedOperationException(); + } + + @Accessor + static BiMap getMossyBlocks() { + throw new UnsupportedOperationException(); + } + + @Accessor + static BiMap getMossyStates() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/RitualBaseAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/RitualBaseAccessor.java new file mode 100644 index 000000000..530a72fd4 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/RitualBaseAccessor.java @@ -0,0 +1,15 @@ +package com.cleanroommc.groovyscript.core.mixin.roots; + +import epicsquid.roots.ritual.RitualBase; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(RitualBase.class) +public interface RitualBaseAccessor { + + @Accessor("disabled") + boolean getDisabled(); + + @Accessor("disabled") + void setDisabled(boolean value); +} diff --git a/src/main/resources/mixin.groovyscript.roots.json b/src/main/resources/mixin.groovyscript.roots.json new file mode 100644 index 000000000..05e2f8cb5 --- /dev/null +++ b/src/main/resources/mixin.groovyscript.roots.json @@ -0,0 +1,14 @@ +{ + "package": "com.cleanroommc.groovyscript.core.mixin.roots", + "refmap": "mixins.groovyscript.refmap.json", + "target": "@env(DEFAULT)", + "minVersion": "0.8", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "ModifierAccessor", + "ModifierRegistryAccessor", + "ModRecipesAccessor", + "MossConfigAccessor", + "RitualBaseAccessor" + ] +} \ No newline at end of file From 87fc39ce22bb409358fc7d5c949ba47f908b42e0 Mon Sep 17 00:00:00 2001 From: Waiting Idly <25394029+WaitingIdly@users.noreply.github.com> Date: Fri, 5 May 2023 12:49:41 -0700 Subject: [PATCH 05/30] add compat examples --- examples/roots.groovy | 459 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 459 insertions(+) create mode 100644 examples/roots.groovy diff --git a/examples/roots.groovy b/examples/roots.groovy new file mode 100644 index 000000000..27fd5ba57 --- /dev/null +++ b/examples/roots.groovy @@ -0,0 +1,459 @@ + +// Bracket Handlers + +// Cost Bracket Handler +cost('no_cost') +cost('additional_cost') +cost('all_cost_multiplier') +cost('specific_cost_adjustment') +cost('specific_cost_multiplier') + +// Herb Bracket Handler +herb('spirit_herb') +herb('baffle_cap') +herb('moonglow_leaf') +herb('pereskia') +herb('terra_moss') +herb('wildroot') +herb('wildewheet') +herb('infernal_bulb') +herb('dewgonia') +herb('stalicripe') +herb('cloud_berry') + +// Spell Bracket Handler +spell('roots:spell_geas') +spell('spell_geas') // Automatically adds `roots:` +spell('geas') // Automatically adds `roots:spell_` + +// Modifier Bracket Handler +modifier('roots:extended_geas') + +// Ritual Bracket Handler +ritual('ritual_summon_creatures') +ritual('summon_creatures') // Automatically prefixes `ritual_` + + +// Animal Harvest: +// Animal Harvest is a ritual that drops items from nearby mobs based on that mob's loottable without harming the mob. Only applies to allowed mobs. +mods.roots.animalharvest.recipeBuilder() + .name('wither_skeleton_harvest') // Optional, either a ResourceLocation or a String + .entity(entity('minecraft:wither_skeleton')) // Target Entity must extend EntityLivingBase + .register() + +mods.roots.animalharvest.recipeBuilder() + .entity(entity('minecraft:enderman')) + .register() + +mods.roots.animalharvest.removeByName(resource('roots:chicken')) +mods.roots.animalharvest.removeByEntity(entity('minecraft:pig')) +//mods.roots.animalharvest.removeAll() + + +// Animal Harvest Fish: +// Animal Harvest Fish is another effect of the Animal Harvest ritual that applies if there are water source blocks within the ritual range. +mods.roots.animalharvestfish.recipeBuilder() + .name('clay_fish') // Optional, either a ResourceLocation or a String + .weight(50) + .output(item('minecraft:clay')) + .register() + +mods.roots.animalharvestfish.recipeBuilder() + .weight(13) + .fish(item('minecraft:gold_ingot')) // fish is an alternative to output + .register() + +mods.roots.animalharvestfish.removeByName(resource('roots:cod')) +mods.roots.animalharvestfish.removeByOutput(item('minecraft:fish:1')) +mods.roots.animalharvestfish.removeByFish(item('minecraft:fish:2')) +//mods.roots.animalharvestfish.removeAll() + + +// Bark Carving: +// Bark Carving is a special set of alternate drops for blocks when broken with an item containing the tool type 'knife'. Amount dropped is up to 2 + fortune/looting level higher than the set amount. +// bark or barkcarving +mods.roots.bark.recipeBuilder() // also accessible via BarkCarving + .name('gold_bark') // Optional, either a ResourceLocation or a String + .input(item('minecraft:clay')) // An item that would be dropped by a block when broken + .output(item('minecraft:gold_ingot')) + .register() + +mods.roots.bark.recipeBuilder() + .blockstate(blockstate('minecraft:gold_block')) + .output(item('minecraft:diamond')) + .register() + +mods.roots.bark.recipeBuilder() + .input(blockstate('minecraft:diamond_block')) + .output(item('minecraft:clay') * 10) + .register() + +mods.roots.bark.removeByName(resource('roots:wildwood')) +mods.roots.bark.removeByInput(item('minecraft:log')) +mods.roots.bark.removeByBlock(item('minecraft:log:1')) +mods.roots.bark.removeByOutput(item('roots:bark_dark_oak')) +//mods.roots.bark.removeAll() + + +// Chrysopoeia: +// Chrysopoeia is a spell that transmutes items held in the main hand. +mods.roots.chrysopoeia.recipeBuilder() + .name('clay_transmute') // Optional, either a ResourceLocation or a String + .input(item('minecraft:gold_ingot')) + .output(item('minecraft:clay')) + .register() + +mods.roots.chrysopoeia.recipeBuilder() + .input(item('minecraft:diamond') * 3) + .output(item('minecraft:gold_ingot') * 3) + .register() + +mods.roots.chrysopoeia.removeByName(resource('roots:gold_from_silver')) +mods.roots.chrysopoeia.removeByInput(item('minecraft:rotten_flesh')) +mods.roots.chrysopoeia.removeByOutput(item('minecraft:iron_nugget')) +//mods.roots.chrysopoeia.removeAll() + + +// Fey Crafter: +// The Fey Crafter is a crafting mechanism that requires an activated Grove Stone nearby to take 5 item inputs and return an item output. +mods.roots.feycrafter.recipeBuilder() + .name('clay_craft') // Optional, either a ResourceLocation or a String + .input(item('minecraft:stone'),item('minecraft:stone'),item('minecraft:stone'),item('minecraft:stone'),item('minecraft:stone')) // Must be exactly 5 + .output(item('minecraft:clay')) + .xp(100) // Optional, int + .register() + +mods.roots.feycrafter.removeByName(resource('roots:unending_bowl')) // WARNING: When reloading recipes with the Fey Crafter, you may encounter a ConcurrentModificationException! +mods.roots.feycrafter.removeByOutput(item('minecraft:gravel')) +//mods.roots.feycrafter.removeAll() + + +// Flower Generation: +// When running the Flower Growth Ritual, allowed flowers will generate in the area. Additionally, using the spell Growth Infusion's Floral Reproduction modifier will duplicate the flower. +mods.roots.flowergeneration.recipeBuilder() + .name('clay_flower') // Optional, either a ResourceLocation or a String + .flower(blockstate('minecraft:clay')) + .register() + +mods.roots.flowergeneration.removeByName(resource('roots:dandelion')) +//mods.roots.flowergeneration.removeByFlower(block('minecraft:red_flower')) // Removes by all blockstates of the block +mods.roots.flowergeneration.removeByFlower(block('minecraft:red_flower'), 1) +mods.roots.flowergeneration.removeByFlower(blockstate('minecraft:red_flower:2')) +mods.roots.flowergeneration.removeByFlower(item('minecraft:red_flower:3')) +//mods.roots.flowergeneration.removeAll() + + +// Life Essence: +// When shift right clicking a mob in the Life Essence Pool with Runic Shears, it will drop a Life-Essence, which allows that mob to be spawned via the Creature Summoning ritual. +mods.roots.lifeessence.add(entity('minecraft:wither_skeleton')) + +mods.roots.lifeessence.remove(entity('minecraft:sheep')) +//mods.roots.lifeessence.removeAll() + + +// Mortar And Pestle: +// When right clicking a mortar containing the input items with a pestle, it will display a few colored sparkles, consume the inputs, and drop the item output. +mods.roots.mortar.recipeBuilder() // also accessible via MortarAndPestle + .name('clay_mortar') // Optional, either a ResourceLocation or a String + .input(item('minecraft:stone'),item('minecraft:gold_ingot'),item('minecraft:stone'),item('minecraft:gold_ingot'),item('minecraft:stone')) // Between 1 and 5 + .generate(false) // Optional, when inputs = 3 and generate isnt disabled, creates a recipe for each amount of items + .output(item('minecraft:clay')) + .color(1, 0, 0.1, 1, 0, 0.1) // Optional, sets color as red1, green1, blue1, red2, green2, blue2. All values must be a float between 0 and 1 + .register() + +mods.roots.mortarandpestle.recipeBuilder() + .input(item('minecraft:clay')) // With generate being true and only 1 input, this will generate a recipe for each amount of inputs to 5. Without this, only 1 clay could be converted at a time + .output(item('minecraft:diamond')) + .color(0, 0, 0.1) // Optional, sets the color as red, green, blue. All values must be a float between 0 and 1 + .register() + +mods.roots.mortar.recipeBuilder() + .input(item('minecraft:diamond'), item('minecraft:diamond')) + .output(item('minecraft:gold_ingot') * 16) + .red(0) // Optional, sets red1 and red2. All values must be a float between 0 and 1 + .green1(0.5) // Optional. The value must be a float between 0 and 1 + .green2(1) // Optional. The value must be a float between 0 and 1 + .register() + +mods.roots.mortar.removeByName(resource('roots:wheat_flour')) // Many Mortar recipes are generated and have the resource location of [base]_x, where x is the output. They can all be removed by running removeByName(base) +mods.roots.mortar.removeByOutput(item('minecraft:string')) +//mods.roots.mortar.removeAll() + + +// Moss: +// Moss indicates a pair of items that can right click the input with a knife to turn it into the output and give a Terra Moss and right click the output with moss spores to turn it into the input. +mods.roots.moss.recipeBuilder() + .input(item('minecraft:gold_block')) + .output(item('minecraft:clay')) + .register() + +mods.roots.moss.add(item('minecraft:stained_glass:3'), item('minecraft:stained_glass:4')) + +mods.roots.moss.remove(item('minecraft:cobblestone')) +//mods.roots.moss.removeAll() + + +// Pacifist: +// Pacifist is a list of entities which killing will give the player the advancement 'Untrue Pacifist'. +mods.roots.pacifist.recipeBuilder() + .name('wither_skeleton_pacifist') // Optional, either a ResourceLocation or a String + .entity(entity('minecraft:wither_skeleton')) + .register() + +mods.roots.pacifist.removeByName(resource('minecraft:chicken')) +mods.roots.pacifist.removeByEntity(entity('minecraft:cow')) +//mods.roots.pacifist.removeAll() + + +// Pyre: +// Converts 5 input items into the ouput after a period of time when the Pyre is lit on fire. +mods.roots.pyre.recipeBuilder() + .name('clay_from_fire') // Optional, either a ResourceLocation or a String + .input(item('minecraft:stone'),item('minecraft:stone'),item('minecraft:stone'),item('minecraft:stone'),item('minecraft:stone')) + .output(item('minecraft:clay')) + .xp(5) // Optional, XP given when the recipe finishes in levels. Default 0 + .time(1) // Optional, time in ticks for the recipe to procress. Default 200 + .register() + +mods.roots.pyre.recipeBuilder() + .input(item('minecraft:gold_ingot'),item('minecraft:clay'),item('minecraft:clay'),item('minecraft:stone'),item('minecraft:stone')) + .output(item('minecraft:diamond') * 32) + .levels(5) // Optional, XP given when the recipe finishes in levels. Default 0 + .burnTime(1000) // Optional, time in ticks for the recipe to procress. Default 200 + .register() + +mods.roots.pyre.removeByName(resource('roots:infernal_bulb')) +mods.roots.pyre.removeByOutput(item('minecraft:gravel')) +//mods.roots.pyre.removeAll() + + +// Runic Shear Block: +// Right clicking a Runic Shear on a block to convert it into a replacement block and drop items +mods.roots.runicshearblock.recipeBuilder() + .name('clay_from_runic_diamond') // Optional, either a ResourceLocation or a String + .state(blockstate('minecraft:diamond_block')) // Either an IBlockState or BlockStatePredicate + .replacementState(blockstate('minecraft:air')) // NOTE: Not displayed in JEI + .output(item('minecraft:clay') * 64) + .displayItem(item('minecraft:diamond') * 9) // Optional, represents the state. Otherwise, is the first itemstack found from the given state + .register() + +mods.roots.runicshearblock.recipeBuilder() + .state(mods.roots.predicates.stateBuilder().blockstate(blockstate('minecraft:yellow_flower:type=dandelion')).properties('type').register()) + .replacementState(blockstate('minecraft:red_flower:type=poppy')) + .output(item('minecraft:gold_ingot')) + .register() + +mods.roots.runicshearblock.removeByName(resource('roots:wildewheet')) +mods.roots.runicshearblock.removeByOutput(item('roots:spirit_herb')) +mods.roots.runicshearblock.removeByState(blockstate('minecraft:beetroots:age=3')) +//mods.roots.runicshearblock.removeAll() + + +// Runic Shear Entity: +// Right clicking a Runic Shear on an entity. The entity will have a cooldown, preventing spamming. +// === WARNING: Not Reloadable === +mods.roots.runicshearentity.recipeBuilder() + .name('clay_from_wither_skeletons') // Optional, either a ResourceLocation or a String + .entity(entity('minecraft:wither_skeleton')) + .output(item('minecraft:clay')) + .cooldown(1000) // Optional, time in ticks between harvesting. Default of 0 + .register() + +mods.roots.runicshearentity.recipeBuilder() + .name('creeper_at_the_last_moment') // Optional, either a ResourceLocation or a String + .entity(entity('minecraft:creeper')) + .output(item('minecraft:diamond'), item('minecraft:nether_star')) // WARNING: JEI will not display this properly. Add a tooltip to the first item informing about all options. + .functionMap({ entityLivingBase -> + // If the creeper has ignited (been right clicked with Flint and Steel), it will drop a Nether Star. Otherwise, its just dirt. + if (entityLivingBase.hasIgnited()) return item('minecraft:nether_star') + return item('minecraft:dirt') + }) + .register() + +mods.roots.runicshearentity.recipeBuilder() + .entity(entity('minecraft:witch')) + .output(item('minecraft:clay')) + .register() + +mods.roots.runicshearentity.removeByName(resource('roots:slime_strange_ooze')) +mods.roots.runicshearentity.removeByOutput(item('roots:fey_leather')) +mods.roots.runicshearentity.removeByEntity(entity('minecraft:chicken')) +//mods.roots.runicshearentity.removeAll() + + +// Summon Creature: +// When running a Summon Creature Ritual, the input items placed on Catalyst Plate will summon the target entity +mods.roots.summoncreature.recipeBuilder() + .name('wither_skeleton_from_clay') // Optional, either a ResourceLocation or a String + .input(item('minecraft:clay'), item('minecraft:clay'), item('minecraft:clay'), item('minecraft:clay'), item('minecraft:clay')) // Between 1 and 10 + .entity(entity('minecraft:wither_skeleton')) + .register() + +mods.roots.summoncreature.removeByName(resource('roots:cow')) +mods.roots.summoncreature.removeByEntity(entity('minecraft:chicken')) +//mods.roots.summoncreature.removeAll() + + +// Transmutation: +// When running the Transmutation, convert nearby blocks that match a set of conditions into either a block or items. +mods.roots.transmutation.recipeBuilder() + .name('clay_duping') // Optional, either a ResourceLocation or a String + .start(blockstate('minecraft:clay')) // Either an IBlockState or BlockStatePredicate + .output(item('minecraft:clay_ball') * 30) // Either a state or output must be defined + .condition(mods.roots.predicates.stateBuilder().blockstate(blockstate('minecraft:gold_block')).below().register()) // Optional, must be a WorldBlockStatePredicate (BlockStateAbove, or BlockStateBelow) + .register() + +mods.roots.transmutation.recipeBuilder() + .start(mods.roots.predicates.stateBuilder().blockstate(blockstate('minecraft:yellow_flower:type=dandelion')).properties('type').register()) // Either an IBlockState or BlockStatePredicate + .state(blockstate('minecraft:gold_block')) + .condition(mods.roots.predicates.above(mods.roots.predicates.LEAVES)) + .register() + +mods.roots.transmutation.recipeBuilder() + .start(blockstate('minecraft:diamond_block')) + .state(blockstate('minecraft:gold_block')) + .register() + +mods.roots.transmutation.removeByName(resource('roots:redstone_block_to_glowstone')) +mods.roots.transmutation.removeByOutput(item('minecraft:dye:3')) +mods.roots.transmutation.removeByOutput(blockstate('minecraft:log:variant=jungle')) +//mods.roots.transmutation.removeAll() + + +// Predicates: +// Predicates are used in Transmution and RunicShearBlock. They either match all blockstates of a block, or all blockstates that have the given properties that match the input blockstate. +// When used in Transmutation, they may require a direction (above or below) to be set. +mods.roots.predicates.stateBuilder() + .blockstate(blockstate('minecraft:red_flower')) // Because this is has no 'properties' set, any blockstate of the base block will work. + .register() + +mods.roots.predicates.stateBuilder() + .block(block('minecraft:red_flower')) // This is identical to the prior predicate. + .register() + +mods.roots.predicates.stateBuilder() + .blockstate(blockstate('minecraft:red_flower:type=poppy')) + .properties('type') // Optional, contains a String..., String[], or List. Controls what properties are matched against with the provided blockstate + .register() + +mods.roots.predicates.stateBuilder() // Matches any log on the z-axis, as 'properties' only checks 'axis'. Matches above the target in Transmutation. + .blockstate(blockstate('minecraft:log:axis=z:variant=oak')) + .properties('axis') + .above() // Optional, used for Transmution to indicate the required direction relative to the primary block. + .register() + +mods.roots.predicates.stateBuilder() // Matches any log, regardless of axis or variant, below the target in Transmutation. + .blockstate(blockstate('minecraft:log')) + .below() // Optional, used for Transmution to indicate the required direction relative to the primary block. + .register() + +// A few constant values are provided: +mods.roots.predicates.ANY // Matches everything +mods.roots.predicates.TRUE // Matches everything +mods.roots.predicates.LAVA // Matches a Lava source block. Required to render properly in JEI +mods.roots.predicates.WATER // Matches a Water source block. Required to render properly in JEI +mods.roots.predicates.LEAVES // Matches any leaf block + +// Converts a BlockStatePredicate into a WorldBlockStatePredicate (BlockStateAbove, or BlockStateBelow) +mods.roots.predicates.above(mods.roots.predicates.LAVA) +mods.roots.predicates.below(mods.roots.predicates.LAVA) + +mods.roots.predicates.create(blockstate('minecraft:red_flower')) +mods.roots.predicates.create(blockstate('minecraft:log:axis=z:variant=oak'), 'axis', 'variant') + + + +// Rituals: +// Set the Pyre Ritual recipe and control all stats. Dump the modifiable stats into `roots.log` by running `/roots rituals`. +// WARNING: When reloading scripts, changes made are never undone. +mods.roots.rituals.recipeBuilder() + .ritual(ritual('ritual_healing_aura')) + .input(item('minecraft:clay'),item('minecraft:gold_ingot'),item('minecraft:gold_ingot'),item('minecraft:gold_ingot'),item('minecraft:gold_ingot')) // Exactly 5 input items + .register() + +mods.roots.rituals.ritual(ritual('ritual_summon_creatures')) + .recipe(item('minecraft:diamond'),item('minecraft:diamond'),item('minecraft:diamond'),item('minecraft:clay'),item('minecraft:clay')) + .setDuration(10) + .setProperty('tries', 10) + .setProperty('radius_z', 1) + .setProperty('radius_y', 10) + .setProperty('glow_duration', 100) + .setProperty('interval', 1) + .setProperty('radius_x', 1) + +mods.roots.rituals.ritual(ritual('ritual_spreading_forest')) + .setDisabled() + +//mods.roots.rituals.disableAll() + +// Cost: +// A helper method to generate modifier costs for spells. Output should be used in a setModifierCost of a spell. +def exampleCost = mods.roots.spells.costBuilder() + .cost(cost('additional_cost'), herb('spirit_herb'), 0.1) + .cost(cost('all_cost_multiplier'), null, -0.125) + .register() + +// Spells: +// Controls the recipe for the given spell, the sound, all properties, the base cost, and each modifier's cost. +// WARNING: When reloading scripts, changes made are never undone. +mods.roots.spells.recipeBuilder() + .spell(spell('spell_fey_light')) + .input(item('minecraft:clay'),item('minecraft:diamond'),item('minecraft:gold_ingot')) // Up to 5 input items, but < 5 generates an error in the Patchouli book + .register() + +mods.roots.spells.spell(spell('spell_acid_cloud')) + .recipe(item('minecraft:diamond'),item('minecraft:diamond'),item('minecraft:diamond'),item('minecraft:clay'),item('minecraft:clay')) + .setSound(5) // Change the volume of the sound played + .setCooldown(10) + .setDamage(10) + .setProperty('regeneration', 10) // An example list of the modifiable properties + .setProperty('radius_general', 10) + .setProperty('damage_count', 10) + .setProperty('poison_amplification', 10) + .setProperty('healing', 10) + .setProperty('slow_duration', 10) + .setProperty('weakness_duration', 10) + .setProperty('regeneration_amplifier', 10) + .setProperty('weakness_amplifier', 10) + .setProperty('radius_boost', 10) + .setProperty('healing_count', 10) + .setProperty('night_modifier_high', 0.6) + .setProperty('fire_duration', 10) + .setProperty('undead_damage', 10) + .setProperty('slow_amplifier', 10) + .setProperty('underwater_boost', 10) + .setProperty('night_modifier_low', 0.05) + .clearCost() // clearCost or clearSpellCost + .addCost(herb('baffle_cap'), 1.0) // addCost or addSpellCost + .addSpellCost(herb('dewgonia'), 0.25) + .setModifierCost(modifier('roots:moonfall'), exampleCost) + .setModifierCost(modifier('roots:radius_boost'), exampleCost) + .setModifierCost(modifier('roots:peaceful_cloud'), exampleCost) + .setModifierCost(modifier('roots:weakening_cloud'), exampleCost) + .setModifierCost(modifier('roots:moonfall'), exampleCost) + .setModifierCost(modifier('roots:unholy_vanquisher'), exampleCost) + .setModifierCost(modifier('roots:healing_cloud'), exampleCost) + .setModifierCost(modifier('roots:increased_speed'), exampleCost) + .setModifierCost(modifier('roots:fire_cloud'), exampleCost) + .setModifierCost(modifier('roots:slowing'), exampleCost) + .setModifierCost(modifier('roots:underwater_increase'), exampleCost) + +mods.roots.spells.spell(spell('spell_harvest')) + .disableSound() + .setSpellCost(herb('baffle_cap'), 0.01) // setCost or setSpellCost + +mods.roots.spells.spell(spell('spell_aqua_bubble')) + .addSpellCost(herb('baffle_cap'), 0.01) + .setSound(0.1) + +mods.roots.spells.spell(spell('spell_geas')) + .setDisabled() + +//mods.roots.spells.disableAll() + +// Modifiers +mods.roots.modifiers.disable(spell('spell_geas')) // Disable all Modifiers for the spell Geas +mods.roots.modifiers.enable(modifier('roots:extended_geas')) // Reenable these three modifiers +mods.roots.modifiers.enable(modifier('roots:animal_savior')) +mods.roots.modifiers.enable(modifier('roots:weakened_response')) +//mods.roots.modifiers.disableAll() From 3fd9ea829ea3f9d8aaf02410cc042edd92a75a17 Mon Sep 17 00:00:00 2001 From: Waiting Idly <25394029+WaitingIdly@users.noreply.github.com> Date: Fri, 5 May 2023 12:50:14 -0700 Subject: [PATCH 06/30] disable debug_roots --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 0862558a8..65b8aab95 100644 --- a/gradle.properties +++ b/gradle.properties @@ -31,6 +31,6 @@ debug_de = false debug_ie = false debug_enderio = false debug_astral = false -debug_roots = true +debug_roots = false debug_blood_magic = false debug_tinkers = false \ No newline at end of file From ad1cd829e32cbb553db6da8fa9f63db3137215cf Mon Sep 17 00:00:00 2001 From: Waiting Idly <25394029+WaitingIdly@users.noreply.github.com> Date: Fri, 5 May 2023 13:27:06 -0700 Subject: [PATCH 07/30] consolidate recipe name into AbstractRecipeBuilder --- .../compat/mods/roots/AnimalHarvest.java | 23 +++++----------- .../compat/mods/roots/AnimalHarvestFish.java | 25 +++++------------ .../compat/mods/roots/BarkCarving.java | 26 +++++------------- .../compat/mods/roots/Chrysopoeia.java | 27 ++++++------------- .../compat/mods/roots/FeyCrafter.java | 25 +++++------------ .../compat/mods/roots/FlowerGeneration.java | 25 +++++------------ .../compat/mods/roots/Mortar.java | 25 +++++------------ .../compat/mods/roots/Pacifist.java | 24 +++++++---------- .../groovyscript/compat/mods/roots/Pyre.java | 25 +++++------------ .../compat/mods/roots/RunicShearBlock.java | 25 +++++------------ .../compat/mods/roots/RunicShearEntity.java | 25 +++++------------ .../compat/mods/roots/SummonCreature.java | 25 +++++------------ .../compat/mods/roots/Transmutation.java | 25 +++++------------ .../mixin/roots/PacifistEntryAccessor.java | 13 +++++++++ .../helper/recipe/AbstractRecipeBuilder.java | 23 ++++++++++++++++ .../resources/mixin.groovyscript.roots.json | 1 + 16 files changed, 131 insertions(+), 231 deletions(-) create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/PacifistEntryAccessor.java diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/AnimalHarvest.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/AnimalHarvest.java index 0f01bd572..a8149c0ee 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/AnimalHarvest.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/AnimalHarvest.java @@ -1,11 +1,9 @@ package com.cleanroommc.groovyscript.compat.mods.roots; -import com.cleanroommc.groovyscript.GroovyScript; import com.cleanroommc.groovyscript.api.GroovyLog; import com.cleanroommc.groovyscript.compat.mods.ModSupport; import com.cleanroommc.groovyscript.helper.SimpleObjectStream; import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; -import com.cleanroommc.groovyscript.helper.recipe.RecipeName; import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; import epicsquid.roots.recipe.AnimalHarvestRecipe; import net.minecraft.entity.EntityLivingBase; @@ -36,7 +34,7 @@ public void onReload() { } public void add(AnimalHarvestRecipe recipe) { - add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_animal_harvest_")), recipe); + add(recipe.getRegistryName(), recipe); } public void add(ResourceLocation name, AnimalHarvestRecipe recipe) { @@ -83,36 +81,27 @@ public SimpleObjectStream> stre public static class RecipeBuilder extends AbstractRecipeBuilder { private Class entity; - private ResourceLocation name; public RecipeBuilder entity(EntityEntry entity) { this.entity = (Class) entity.getEntityClass(); return this; } - public RecipeBuilder name(String name) { - this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); - return this; - } - - public RecipeBuilder name(ResourceLocation name) { - this.name = name; - return this; - } - @Override public String getErrorMsg() { return "Error adding Roots Animal Harvest recipe"; } + public String getRecipeNamePrefix() { + return "groovyscript_animal_harvest_"; + } + @Override public void validate(GroovyLog.Msg msg) { + validateName(); validateItems(msg); validateFluids(msg); msg.add(entity == null, "entity must be defined and extended EntityLivingBase, instead it was {}", entity); - if (name == null) { - name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_animal_harvest_")); - } } @Override diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/AnimalHarvestFish.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/AnimalHarvestFish.java index 35cd38941..01ef5be9b 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/AnimalHarvestFish.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/AnimalHarvestFish.java @@ -1,11 +1,9 @@ package com.cleanroommc.groovyscript.compat.mods.roots; -import com.cleanroommc.groovyscript.GroovyScript; import com.cleanroommc.groovyscript.api.GroovyLog; import com.cleanroommc.groovyscript.compat.mods.ModSupport; import com.cleanroommc.groovyscript.helper.SimpleObjectStream; import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; -import com.cleanroommc.groovyscript.helper.recipe.RecipeName; import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; import epicsquid.roots.recipe.AnimalHarvestFishRecipe; import net.minecraft.item.ItemStack; @@ -35,8 +33,8 @@ public void onReload() { restoreFromBackup().forEach(pair -> getAnimalHarvestFishRecipes().put(pair.getKey(), pair.getValue())); } - public void add(String name, AnimalHarvestFishRecipe recipe) { - add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + public void add(AnimalHarvestFishRecipe recipe) { + add(recipe.getRegistryName(), recipe); } public void add(ResourceLocation name, AnimalHarvestFishRecipe recipe) { @@ -87,7 +85,6 @@ public SimpleObjectStream> public static class RecipeBuilder extends AbstractRecipeBuilder { private int weight; - private ResourceLocation name; public RecipeBuilder weight(int weight) { this.weight = weight; @@ -99,29 +96,21 @@ public RecipeBuilder fish(ItemStack fish) { return this; } - public RecipeBuilder name(String name) { - this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); - return this; - } - - public RecipeBuilder name(ResourceLocation name) { - this.name = name; - return this; - } - @Override public String getErrorMsg() { return "Error adding Roots Animal Harvest Fish recipe"; } + public String getRecipeNamePrefix() { + return "groovyscript_animal_harvest_fish_"; + } + @Override public void validate(GroovyLog.Msg msg) { + validateName(); validateItems(msg, 0, 0, 1, 1); validateFluids(msg); msg.add(weight <= 0, "weight must be a nonnegative integer greater than 0, instead it was {}", weight); - if (name == null) { - name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_animal_harvest_fish_")); - } } @Override diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/BarkCarving.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/BarkCarving.java index a5a743e2c..84fd1456b 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/BarkCarving.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/BarkCarving.java @@ -1,12 +1,10 @@ package com.cleanroommc.groovyscript.compat.mods.roots; -import com.cleanroommc.groovyscript.GroovyScript; import com.cleanroommc.groovyscript.api.GroovyLog; 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.helper.recipe.RecipeName; import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; import epicsquid.roots.recipe.BarkRecipe; import net.minecraft.block.BlockPlanks; @@ -36,8 +34,8 @@ public void onReload() { restoreFromBackup().forEach(pair -> getBarkRecipeMap().put(pair.getKey(), pair.getValue())); } - public void add(String name, BarkRecipe recipe) { - add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + public void add(BarkRecipe recipe) { + add(recipe.getName(), recipe); } public void add(ResourceLocation name, BarkRecipe recipe) { @@ -116,8 +114,6 @@ public SimpleObjectStream streamRecipes() { public static class RecipeBuilder extends AbstractRecipeBuilder { - private ResourceLocation name; - public RecipeBuilder blockstate(IBlockState blockstate) { return this.input(blockstate); } @@ -127,28 +123,20 @@ public RecipeBuilder input(IBlockState blockstate) { return this; } - public RecipeBuilder name(String name) { - this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); - return this; - } - - public RecipeBuilder name(ResourceLocation name) { - this.name = name; - return this; - } - @Override public String getErrorMsg() { return "Error adding Roots Pyre recipe"; } + public String getRecipeNamePrefix() { + return "groovyscript_bark_carving_"; + } + @Override public void validate(GroovyLog.Msg msg) { + validateName(); validateItems(msg, 1, 1, 1, 1); validateFluids(msg); - if (name == null) { - name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_bark_carving_")); - } } @Override diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Chrysopoeia.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Chrysopoeia.java index 9756309db..9764db89d 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Chrysopoeia.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Chrysopoeia.java @@ -1,13 +1,11 @@ package com.cleanroommc.groovyscript.compat.mods.roots; -import com.cleanroommc.groovyscript.GroovyScript; import com.cleanroommc.groovyscript.api.GroovyLog; import com.cleanroommc.groovyscript.compat.mods.ModSupport; import com.cleanroommc.groovyscript.core.mixin.roots.ModRecipesAccessor; import com.cleanroommc.groovyscript.helper.SimpleObjectStream; import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper; import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; -import com.cleanroommc.groovyscript.helper.recipe.RecipeName; import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; import epicsquid.roots.recipe.ChrysopoeiaRecipe; import epicsquid.roots.util.IngredientWithStack; @@ -34,8 +32,8 @@ public void onReload() { restoreFromBackup().forEach(pair -> ModRecipesAccessor.getChrysopoeiaRecipes().put(pair.getKey(), pair.getValue())); } - public void add(String name, ChrysopoeiaRecipe recipe) { - add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + public void add(ChrysopoeiaRecipe recipe) { + add(recipe.getRegistryName(), recipe); } public void add(ResourceLocation name, ChrysopoeiaRecipe recipe) { @@ -99,11 +97,10 @@ public SimpleObjectStream> stream public static class RecipeBuilder extends AbstractRecipeBuilder { - // overload, byproductChance, and byproduct are all unused +// overload, byproductChance, and byproduct are all unused // private float overload = 0.0F; // private float byproductChance = 0.0F; // private ItemStack byproduct = ItemStack.EMPTY; - private ResourceLocation name; // public RecipeBuilder overload(float overload) { // this.overload = overload; @@ -120,30 +117,22 @@ public static class RecipeBuilder extends AbstractRecipeBuilder addFeyCraftingRecipe(pair.getKey(), pair.getValue())); } - public void add(String name, FeyCraftingRecipe recipe) { - add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + public void add(FeyCraftingRecipe recipe) { + add(recipe.getName().contains(":") ? new ResourceLocation(recipe.getName()) : new ResourceLocation("roots", recipe.getName()), recipe); } public void add(ResourceLocation name, FeyCraftingRecipe recipe) { @@ -88,36 +86,27 @@ public SimpleObjectStream> stream public static class RecipeBuilder extends AbstractRecipeBuilder { private int xp = 0; - private ResourceLocation name; public RecipeBuilder xp(int xp) { this.xp = xp; return this; } - public RecipeBuilder name(String name) { - this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); - return this; - } - - public RecipeBuilder name(ResourceLocation name) { - this.name = name; - return this; - } - @Override public String getErrorMsg() { return "Error adding Roots Fey Crafter recipe"; } + public String getRecipeNamePrefix() { + return "groovyscript_fey_crafter_"; + } + @Override public void validate(GroovyLog.Msg msg) { + validateName(); validateItems(msg, 5, 5, 1, 1); validateFluids(msg); msg.add(xp < 0, "xp must be a nonnegative integer, yet it was {}", xp); - if (name == null) { - name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_fey_crafter_")); - } } @Override diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/FlowerGeneration.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/FlowerGeneration.java index 9b572282e..6b85317b6 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/FlowerGeneration.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/FlowerGeneration.java @@ -1,11 +1,9 @@ package com.cleanroommc.groovyscript.compat.mods.roots; -import com.cleanroommc.groovyscript.GroovyScript; import com.cleanroommc.groovyscript.api.GroovyLog; import com.cleanroommc.groovyscript.compat.mods.ModSupport; import com.cleanroommc.groovyscript.helper.SimpleObjectStream; import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; -import com.cleanroommc.groovyscript.helper.recipe.RecipeName; import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; import epicsquid.roots.recipe.FlowerRecipe; import net.minecraft.block.Block; @@ -40,8 +38,8 @@ public void onReload() { restoreFromBackup().forEach(pair -> getFlowerRecipes().put(pair.getKey(), pair.getValue())); } - public void add(String name, FlowerRecipe recipe) { - add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + public void add(FlowerRecipe recipe) { + add(recipe.getRegistryName(), recipe); } public void add(ResourceLocation name, FlowerRecipe recipe) { @@ -105,7 +103,6 @@ public static class RecipeBuilder extends AbstractRecipeBuilder { private IBlockState flower; private final List allowedSoils = new ArrayList<>(); - private ResourceLocation name; public RecipeBuilder flower(IBlockState flower) { this.flower = flower; @@ -138,29 +135,21 @@ public RecipeBuilder allowedSoils(Collection allowedSoilss) { } */ - public RecipeBuilder name(String name) { - this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); - return this; - } - - public RecipeBuilder name(ResourceLocation name) { - this.name = name; - return this; - } - @Override public String getErrorMsg() { return "Error adding Roots Flower Generation recipe"; } + public String getRecipeNamePrefix() { + return "groovyscript_flower_generation_recipe_"; + } + @Override public void validate(GroovyLog.Msg msg) { + validateName(); validateItems(msg); validateFluids(msg); msg.add(flower == null, "flower must be defined"); - if (name == null) { - name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_flower_generation_recipe_")); - } } @Override diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Mortar.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Mortar.java index dc174e232..fe77aecf0 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Mortar.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Mortar.java @@ -1,13 +1,11 @@ package com.cleanroommc.groovyscript.compat.mods.roots; -import com.cleanroommc.groovyscript.GroovyScript; import com.cleanroommc.groovyscript.api.GroovyLog; import com.cleanroommc.groovyscript.api.IIngredient; import com.cleanroommc.groovyscript.compat.mods.ModSupport; import com.cleanroommc.groovyscript.core.mixin.roots.ModRecipesAccessor; import com.cleanroommc.groovyscript.helper.SimpleObjectStream; import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; -import com.cleanroommc.groovyscript.helper.recipe.RecipeName; import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; import epicsquid.roots.recipe.MortarRecipe; import net.minecraft.item.ItemStack; @@ -38,8 +36,8 @@ public void onReload() { restoreFromBackup().forEach(pair -> addMortarRecipe(pair.getValue())); } - public void add(String name, MortarRecipe recipe) { - add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + public void add(MortarRecipe recipe) { + add(recipe.getRegistryName(), recipe); } public void add(ResourceLocation name, MortarRecipe recipe) { @@ -102,7 +100,6 @@ public static class RecipeBuilder extends AbstractRecipeBuilder { private float green2 = 1.0F; private float blue2 = 1.0F; private boolean generate = true; - private ResourceLocation name; public RecipeBuilder red1(float red1) { this.red1 = red1; @@ -200,23 +197,18 @@ public RecipeBuilder generate() { return this; } - public RecipeBuilder name(String name) { - this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); - return this; - } - - public RecipeBuilder name(ResourceLocation name) { - this.name = name; - return this; - } - @Override public String getErrorMsg() { return "Error adding Roots Pyre recipe"; } + public String getRecipeNamePrefix() { + return "groovyscript_mortar_recipe_"; + } + @Override public void validate(GroovyLog.Msg msg) { + validateName(); validateItems(msg, 1, 5, 1, 1); validateFluids(msg); msg.add(red1 < 0 || red1 > 1, "red1 must be a float between 0 and 1, yet it was {}", red1); @@ -225,9 +217,6 @@ public void validate(GroovyLog.Msg msg) { msg.add(red2 < 0 || red2 > 1, "red2 must be a float between 0 and 1, yet it was {}", red2); msg.add(green2 < 0 || green2 > 1, "green2 must be a float between 0 and 1, yet it was {}", green2); msg.add(blue2 < 0 || blue2 > 1, "blue2 must be a float between 0 and 1, yet it was {}", blue2); - if (name == null) { - name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_mortar_recipe_")); - } } @Override diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Pacifist.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Pacifist.java index f706e2a40..f6b9221b7 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Pacifist.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Pacifist.java @@ -1,11 +1,10 @@ package com.cleanroommc.groovyscript.compat.mods.roots; -import com.cleanroommc.groovyscript.GroovyScript; import com.cleanroommc.groovyscript.api.GroovyLog; import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.core.mixin.roots.PacifistEntryAccessor; import com.cleanroommc.groovyscript.helper.SimpleObjectStream; import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; -import com.cleanroommc.groovyscript.helper.recipe.RecipeName; import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; import epicsquid.roots.recipe.PacifistEntry; import net.minecraft.entity.Entity; @@ -34,8 +33,8 @@ public void onReload() { restoreFromBackup().forEach(pair -> getPacifistEntities().put(pair.getKey(), pair.getValue())); } - public void add(String name, PacifistEntry recipe) { - add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + public void add(PacifistEntry recipe) { + add(recipe.getRegistryName(), recipe); } public void add(ResourceLocation name, PacifistEntry recipe) { @@ -85,37 +84,34 @@ public SimpleObjectStream> streamReci public static class RecipeBuilder extends AbstractRecipeBuilder { private Class entity; - private String name; public RecipeBuilder entity(EntityEntry entity) { this.entity = entity.getEntityClass(); return this; } - public RecipeBuilder name(String name) { - this.name = name; - return this; - } - @Override public String getErrorMsg() { return "Error adding Roots Runic Shear Entity recipe"; } + public String getRecipeNamePrefix() { + return "groovyscript_pacifist_"; + } + @Override public void validate(GroovyLog.Msg msg) { + validateName(); validateItems(msg); validateFluids(msg); msg.add(entity == null, "entity must be defined"); - if (name == null) { - name = RecipeName.generate("groovyscript_pacifist_"); - } } @Override public @Nullable PacifistEntry register() { if (!validate()) return null; - PacifistEntry recipe = new PacifistEntry(entity, name); + PacifistEntry recipe = new PacifistEntry(entity, name.toString()); + ((PacifistEntryAccessor) recipe).setName(name); ModSupport.ROOTS.get().pacifist.add(recipe.getRegistryName(), recipe); return recipe; } diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Pyre.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Pyre.java index 79ab64ba4..c4e7edeee 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Pyre.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Pyre.java @@ -1,11 +1,9 @@ package com.cleanroommc.groovyscript.compat.mods.roots; -import com.cleanroommc.groovyscript.GroovyScript; import com.cleanroommc.groovyscript.api.GroovyLog; import com.cleanroommc.groovyscript.compat.mods.ModSupport; import com.cleanroommc.groovyscript.helper.SimpleObjectStream; import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; -import com.cleanroommc.groovyscript.helper.recipe.RecipeName; import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; import epicsquid.roots.recipe.PyreCraftingRecipe; import net.minecraft.item.ItemStack; @@ -33,8 +31,8 @@ public void onReload() { restoreFromBackup().forEach(pair -> addPyreCraftingRecipe(pair.getKey(), pair.getValue())); } - public void add(String name, PyreCraftingRecipe recipe) { - add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + public void add(PyreCraftingRecipe recipe) { + add(recipe.getRegistryName(), recipe); } public void add(ResourceLocation name, PyreCraftingRecipe recipe) { @@ -89,7 +87,6 @@ public static class RecipeBuilder extends AbstractRecipeBuilder getRunicShearRecipes().put(pair.getKey(), pair.getValue())); } - public void add(String name, RunicShearRecipe recipe) { - add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + public void add(RunicShearRecipe recipe) { + add(recipe.getRegistryName(), recipe); } public void add(ResourceLocation name, RunicShearRecipe recipe) { @@ -97,7 +95,6 @@ public static class RecipeBuilder extends AbstractRecipeBuilder getRunicShearEntityRecipes().put(pair.getKey(), pair.getValue())); } - public void add(String name, RunicShearEntityRecipe recipe) { - add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + public void add(RunicShearEntityRecipe recipe) { + add(recipe.getRegistryName(), recipe); } public void add(ResourceLocation name, RunicShearEntityRecipe recipe) { @@ -103,7 +101,6 @@ public static class RecipeBuilder extends AbstractRecipeBuilder entity; private int cooldown; private Function functionMap; - private ResourceLocation name; public RecipeBuilder entity(EntityEntry entity) { this.entity = (Class) entity.getEntityClass(); @@ -120,30 +117,22 @@ public RecipeBuilder functionMap(Function functionM return this; } - public RecipeBuilder name(String name) { - this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); - return this; - } - - public RecipeBuilder name(ResourceLocation name) { - this.name = name; - return this; - } - @Override public String getErrorMsg() { return "Error adding Roots Runic Shear Entity recipe"; } + public String getRecipeNamePrefix() { + return "groovyscript_runic_shear_entity_"; + } + @Override public void validate(GroovyLog.Msg msg) { + validateName(); msg.add(!input.isEmpty(), () -> "No item inputs allowed, but found " + input.size()); validateFluids(msg); msg.add(output.size() > 1 && functionMap == null, "if output is greater than 1, functionMap must be defined"); msg.add(entity == null , "entity must be defined and extended EntityLivingBase, instead it was {}", entity); - if (name == null) { - name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_runic_shear_entity_")); - } } @Override diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/SummonCreature.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/SummonCreature.java index f932841de..a817e4875 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/SummonCreature.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/SummonCreature.java @@ -1,13 +1,11 @@ package com.cleanroommc.groovyscript.compat.mods.roots; -import com.cleanroommc.groovyscript.GroovyScript; import com.cleanroommc.groovyscript.api.GroovyLog; import com.cleanroommc.groovyscript.api.IIngredient; import com.cleanroommc.groovyscript.compat.mods.ModSupport; import com.cleanroommc.groovyscript.core.mixin.roots.ModRecipesAccessor; import com.cleanroommc.groovyscript.helper.SimpleObjectStream; import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; -import com.cleanroommc.groovyscript.helper.recipe.RecipeName; import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; import epicsquid.roots.recipe.SummonCreatureRecipe; import net.minecraft.entity.EntityLivingBase; @@ -39,8 +37,8 @@ public void onReload() { restoreFromBackup().forEach(pair -> addSummonCreatureEntry(pair.getValue())); } - public void add(String name, SummonCreatureRecipe recipe) { - add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + public void add(SummonCreatureRecipe recipe) { + add(recipe.getRegistryName(), recipe); } public void add(ResourceLocation name, SummonCreatureRecipe recipe) { @@ -92,36 +90,27 @@ public SimpleObjectStream> str public static class RecipeBuilder extends AbstractRecipeBuilder { private Class entity; - private ResourceLocation name; public RecipeBuilder entity(EntityEntry entity) { this.entity = (Class) entity.getEntityClass(); return this; } - public RecipeBuilder name(String name) { - this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); - return this; - } - - public RecipeBuilder name(ResourceLocation name) { - this.name = name; - return this; - } - @Override public String getErrorMsg() { return "Error adding Roots Summon Creature recipe"; } + public String getRecipeNamePrefix() { + return "groovyscript_summon_creature_"; + } + @Override public void validate(GroovyLog.Msg msg) { + validateName(); validateItems(msg, 1, 10, 0, 0); validateFluids(msg); msg.add(entity == null, "entity must be defined"); - if (name == null) { - name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate("groovyscript_summon_creature_")); - } } @Override diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Transmutation.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Transmutation.java index b6478755c..37ecb14be 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Transmutation.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/roots/Transmutation.java @@ -1,12 +1,10 @@ package com.cleanroommc.groovyscript.compat.mods.roots; -import com.cleanroommc.groovyscript.GroovyScript; import com.cleanroommc.groovyscript.api.GroovyLog; import com.cleanroommc.groovyscript.compat.mods.ModSupport; import com.cleanroommc.groovyscript.core.mixin.roots.ModRecipesAccessor; import com.cleanroommc.groovyscript.helper.SimpleObjectStream; import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; -import com.cleanroommc.groovyscript.helper.recipe.RecipeName; import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; import epicsquid.roots.recipe.TransmutationRecipe; import epicsquid.roots.recipe.transmutation.BlockStatePredicate; @@ -41,8 +39,8 @@ public void onReload() { restoreFromBackup().forEach(pair -> ModRecipesAccessor.getTransmutationRecipes().put(pair.getKey(), pair.getValue())); } - public void add(String name, TransmutationRecipe recipe) { - add(new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name), recipe); + public void add(TransmutationRecipe recipe) { + add(recipe.getRegistryName(), recipe); } public void add(ResourceLocation name, TransmutationRecipe recipe) { @@ -120,7 +118,6 @@ public static class RecipeBuilder extends AbstractRecipeBuilder implements IRecipeBuilder { + protected ResourceLocation name; protected final IngredientList input = new IngredientList<>(); protected final ItemStackList output = new ItemStackList(); protected final FluidStackList fluidInput = new FluidStackList(); protected final FluidStackList fluidOutput = new FluidStackList(); + public String getRecipeNamePrefix() { + return "groovyscript_"; + } + + public AbstractRecipeBuilder name(String name) { + this.name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), name); + return this; + } + + public AbstractRecipeBuilder name(ResourceLocation name) { + this.name = name; + return this; + } + public AbstractRecipeBuilder input(IIngredient ingredient) { this.input.add(ingredient); return this; @@ -104,6 +121,12 @@ public boolean validate() { public abstract void validate(GroovyLog.Msg msg); + public void validateName() { + if (name == null) { + name = new ResourceLocation(GroovyScript.getRunConfig().getPackId(), RecipeName.generate(getRecipeNamePrefix())); + } + } + public void validateFluids(GroovyLog.Msg msg, int minFluidInput, int maxFluidInput, int minFluidOutput, int maxFluidOutput) { fluidInput.trim(); fluidOutput.trim(); diff --git a/src/main/resources/mixin.groovyscript.roots.json b/src/main/resources/mixin.groovyscript.roots.json index 05e2f8cb5..de197c73d 100644 --- a/src/main/resources/mixin.groovyscript.roots.json +++ b/src/main/resources/mixin.groovyscript.roots.json @@ -9,6 +9,7 @@ "ModifierRegistryAccessor", "ModRecipesAccessor", "MossConfigAccessor", + "PacifistEntryAccessor", "RitualBaseAccessor" ] } \ No newline at end of file From 11bddcd1ae1320ebfc6a480e3572bf1c1f0eda30 Mon Sep 17 00:00:00 2001 From: Rongmario Date: Sun, 14 May 2023 13:27:35 +0100 Subject: [PATCH 08/30] Migrate to RFG --- build.gradle | 355 ++++++++++++----------- gradle.properties | 7 - gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 24 ++ 4 files changed, 208 insertions(+), 180 deletions(-) create mode 100644 settings.gradle diff --git a/build.gradle b/build.gradle index 2bad2c688..009fa58a6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,211 +1,217 @@ -buildscript { - repositories { - maven { - name = "forge" - url = "https://maven.minecraftforge.net/" - } - maven { - url = 'https://maven.cleanroommc.com/' - } - maven { - url = 'https://repo.spongepowered.org/maven/' - } - } - dependencies { - classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT' - if (project.use_mixins.toBoolean()) { - classpath 'org.spongepowered:mixingradle:0.6-SNAPSHOT' - } - } -} +import com.gtnewhorizons.retrofuturagradle.mcp.ReobfuscatedJar +import org.jetbrains.gradle.ext.Gradle plugins { - id 'com.github.johnrengelman.shadow' version '4.0.4' -} - -apply plugin: 'net.minecraftforge.gradle.forge' -apply plugin: 'com.github.johnrengelman.shadow' - -if (project.use_mixins.toBoolean()) { - apply plugin: 'org.spongepowered.mixin' + id 'java' + id 'java-library' + id 'maven-publish' + id 'org.jetbrains.gradle.plugin.idea-ext' version '1.1.7' + id 'eclipse' + id 'com.gtnewhorizons.retrofuturagradle' version '1.3.9' + id 'com.matthewprenger.cursegradle' version '1.4.0' } version = project.mod_version group = project.maven_group archivesBaseName = project.archives_base_name -sourceCompatibility = targetCompatibility = '1.8' +// Set the toolchain version to decouple the Java we run Gradle with from the Java used to compile and run the mod +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(8)) + // Azul covers the most platforms for Java 8 toolchains, crucially including MacOS arm64 + vendor.set(org.gradle.jvm.toolchain.JvmVendorSpec.AZUL) + } + // Generate sources and javadocs jars when building and publishing + withSourcesJar() + withJavadocJar() +} -compileJava { - sourceCompatibility = targetCompatibility = '1.8' +tasks.withType(JavaCompile).configureEach { + options.encoding = "UTF-8" +} + +configurations { + embed + implementation.extendsFrom(embed) } minecraft { - version = '1.12.2-14.23.5.2847' - runDir = 'run' - mappings = 'stable_39' - def args = [] - if (project.use_coremod.toBoolean()) { - args << '-Dfml.coreMods.load=' + coremod_plugin_class_name - } - if (project.use_mixins.toBoolean()) { - args << '-Dmixin.hotSwap=true' - args << '-Dmixin.checks.interfaces=true' - args << '-Dmixin.debug.export=true' - } - clientJvmArgs.addAll(args) - serverJvmArgs.addAll(args) + mcVersion = '1.12.2' + def args = ["-ea:${project.group}"] + args << '-Dfml.coreMods.load=' + coremod_plugin_class_name + args << '-Dmixin.hotSwap=true' + args << '-Dmixin.checks.interfaces=true' + args << '-Dmixin.debug.export=true' + extraRunJvmArguments.addAll(args) + + useDependencyAccessTransformers = true + + injectedTags.put("VERSION", project.version) +} - replaceIn("src/main/java/${project.mod_ref_path.replace('.', '/')}.java") - replace("@VERSION@", project.mod_version) - replace("@MODID@", project.archivesBaseName) - replace("@GROOVY_VERSION@", project.groovy_version) +// Generate a my.project.Tags class with the version number as a field +tasks.injectTags.configure { + outputClassName.set("${project.group}.Tags") } repositories { maven { - url = 'https://maven.cleanroommc.com/' + url = 'https://maven.cleanroommc.com' } maven { - url = 'https://repo.spongepowered.org/maven/' + url = 'https://repo.spongepowered.org/maven' } maven { - url = "https://mvnrepository.com/artifact/org.apache.groovy/groovy" + url 'https://cursemaven.com' + content { + includeGroup "curse.maven" + } } maven { - url 'https://dvs1.progwml6.com/files/maven/' + url = 'https://mvnrepository.com/artifact/org.apache.groovy/groovy' } maven { - name = "CurseForge" - url = 'https://www.cursemaven.com/' + url 'https://dvs1.progwml6.com/files/maven/' } maven { - url "http://maven.tterrag.com/" + url 'http://maven.tterrag.com/' + allowInsecureProtocol = true } + mavenLocal() // Must be last for caching to work } dependencies { - if (project.use_mixins.toBoolean()) { - deobfCompile 'zone.rong:mixinbooter:4.2' + implementation 'zone.rong:mixinbooter:7.1' + + api ('org.spongepowered:mixin:0.8.3') { + transitive = false + } + annotationProcessor 'org.ow2.asm:asm-debug-all:5.2' + annotationProcessor 'com.google.guava:guava:24.1.1-jre' + annotationProcessor 'com.google.code.gson:gson:2.8.6' + annotationProcessor ('org.spongepowered:mixin:0.8.3') { + transitive = false } compileOnly 'org.jetbrains:annotations:23.0.0' - implementation "org.apache.groovy:groovy:${project.groovy_version}" - shadow "org.apache.groovy:groovy:${project.groovy_version}" + embed "org.apache.groovy:groovy:${project.groovy_version}" - compile 'mezz.jei:jei_1.12.2:4.16.1.302' + implementation 'mezz.jei:jei_1.12.2:4.16.1.302' + compileOnly rfg.deobf('curse.maven:mekanism-268560:2835175') if (project.debug_mekanism.toBoolean()) { - deobfCompile 'curse.maven:mekanism-268560:2835175' - } else { - deobfProvided 'curse.maven:mekanism-268560:2835175' + runtimeOnly rfg.deobf('curse.maven:mekanism-268560:2835175') } + compileOnly rfg.deobf('curse.maven:redstone_flux-270789:2920436') if (project.debug_thermal.toBoolean() || project.debug_de.toBoolean()) { - deobfCompile 'curse.maven:redstone_flux-270789:2920436' - } else { - deobfProvided 'curse.maven:redstone_flux-270789:2920436' + runtimeOnly rfg.deobf('curse.maven:redstone_flux-270789:2920436') } + compileOnly rfg.deobf('curse.maven:guide-api-228832:2645992') + compileOnly rfg.deobf('curse.maven:blood-magic-224791:2822288') if (project.debug_blood_magic.toBoolean()) { - deobfCompile 'curse.maven:guide-api-228832:2645992' - deobfCompile 'curse.maven:blood-magic-224791:2822288' - } else { - deobfProvided 'curse.maven:guide-api-228832:2645992' - deobfProvided 'curse.maven:blood-magic-224791:2822288' + runtimeOnly rfg.deobf('curse.maven:guide-api-228832:2645992') + runtimeOnly rfg.deobf('curse.maven:blood-magic-224791:2822288') } + compileOnly rfg.deobf('curse.maven:cucumber-272335:2645867') + compileOnly rfg.deobf('curse.maven:extended-crafting-nomifactory-edition-398267:3613140') if (project.debug_extended_crafting.toBoolean()) { - deobfCompile 'curse.maven:cucumber-272335:2645867' - deobfCompile 'curse.maven:extended-crafting-nomifactory-edition-398267:3613140' - } else { - deobfProvided 'curse.maven:cucumber-272335:2645867' - deobfProvided 'curse.maven:extended-crafting-nomifactory-edition-398267:3613140' + runtimeOnly rfg.deobf('curse.maven:cucumber-272335:2645867') + runtimeOnly rfg.deobf('curse.maven:extended-crafting-nomifactory-edition-398267:3613140') } + compileOnly rfg.deobf('curse.maven:cofh_core-69162:2920433') + compileOnly rfg.deobf('curse.maven:cofh_world-271384:2920434') + compileOnly rfg.deobf('curse.maven:thermal_expansion-69163:2926431') + compileOnly rfg.deobf('curse.maven:thermal_foundation-222880:2926428') if (project.debug_thermal.toBoolean()) { - deobfCompile 'curse.maven:cofh_core-69162:2920433' - deobfCompile 'curse.maven:cofh_world-271384:2920434' - deobfCompile 'curse.maven:thermal_expansion-69163:2926431' - deobfCompile 'curse.maven:thermal_foundation-222880:2926428' - } else { - deobfProvided 'curse.maven:cofh_core-69162:2920433' - deobfProvided 'curse.maven:cofh_world-271384:2920434' - deobfProvided 'curse.maven:thermal_expansion-69163:2926431' - deobfProvided 'curse.maven:thermal_foundation-222880:2926428' + runtimeOnly rfg.deobf('curse.maven:cofh_core-69162:2920433') + runtimeOnly rfg.deobf('curse.maven:cofh_world-271384:2920434') + runtimeOnly rfg.deobf('curse.maven:thermal_expansion-69163:2926431') + runtimeOnly rfg.deobf('curse.maven:thermal_foundation-222880:2926428') } + compileOnly rfg.deobf('curse.maven:codechicken_lib_1_8-242818:2779848') + compileOnly rfg.deobf('curse.maven:draconic_evolution-223565:3431261') + compileOnly rfg.deobf('curse.maven:brandons_core-231382:3408276') if (project.debug_de.toBoolean()) { - deobfCompile 'curse.maven:codechicken_lib_1_8-242818:2779848' - deobfCompile 'curse.maven:draconic_evolution-223565:3431261' - deobfCompile 'curse.maven:brandons_core-231382:3408276' - } else { - deobfProvided 'curse.maven:codechicken_lib_1_8-242818:2779848' - deobfProvided 'curse.maven:draconic_evolution-223565:3431261' - deobfProvided 'curse.maven:brandons_core-231382:3408276' - } - - if (project.debug_enderio.toBoolean()) { - deobfProvided "com.enderio.core:EnderCore:1.12.2-+" - deobfCompile("com.enderio:EnderIO:1.12.2-+") { - transitive = false - } - } else { - deobfProvided "com.enderio.core:EnderCore:1.12.2-+" - deobfProvided("com.enderio:EnderIO:1.12.2-+") { - transitive = false - } + runtimeOnly rfg.deobf('curse.maven:codechicken_lib_1_8-242818:2779848') + runtimeOnly rfg.deobf('curse.maven:draconic_evolution-223565:3431261') + runtimeOnly rfg.deobf('curse.maven:brandons_core-231382:3408276') } + compileOnly rfg.deobf('curse.maven:industrialcraft_experimental-242638:3838713') + compileOnly rfg.deobf('curse.maven:industrialcraft_classic-242942:3093607') if (project.debug_ic2.toBoolean()) { - deobfCompile 'curse.maven:industrialcraft_experimental-242638:3838713' - deobfProvided 'curse.maven:industrialcraft_classic-242942:3093607' - } else { - deobfProvided 'curse.maven:industrialcraft_experimental-242638:3838713' - deobfProvided 'curse.maven:industrialcraft_classic-242942:3093607' + runtimeOnly rfg.deobf('curse.maven:industrialcraft_experimental-242638:3838713') + runtimeOnly rfg.deobf('curse.maven:industrialcraft_classic-242942:3093607') } - if (project.debug_astral.toBoolean() || project.debug_thaum.toBoolean()) { - runtime 'curse.maven:baubles-227083:2518667' + compileOnly rfg.deobf('curse.maven:baubles-227083:2518667') + compileOnly rfg.deobf('curse.maven:thaumcraft-223628:2629023') + if (project.debug_thaum.toBoolean()) { + runtimeOnly rfg.deobf('curse.maven:baubles-227083:2518667') + runtimeOnly rfg.deobf('curse.maven:thaumcraft-223628:2629023') } + runtimeOnly 'curse.maven:thaumic_jei-285492:2705304' + compileOnly rfg.deobf('curse.maven:astralsorcery-sorcery-241721:3044416') if (project.debug_astral.toBoolean()) { - deobfCompile 'curse.maven:astralsorcery-sorcery-241721:3044416' - } else { - deobfProvided 'curse.maven:astralsorcery-sorcery-241721:3044416' - } - - if (project.debug_thaum.toBoolean()) { - deobfCompile 'curse.maven:thaumcraft-223628:2629023' - runtime 'curse.maven:thaumic_jei-285492:2705304' - } else { - deobfProvided 'curse.maven:thaumcraft-223628:2629023' + runtimeOnly rfg.deobf('curse.maven:astralsorcery-sorcery-241721:3044416') } + compileOnly rfg.deobf('curse.maven:immersive_engineering-231951:2974106') if (project.debug_ie.toBoolean()) { - deobfCompile 'curse.maven:immersive_engineering-231951:2974106' - } else { - deobfProvided 'curse.maven:immersive_engineering-231951:2974106' + runtimeOnly rfg.deobf('curse.maven:immersive_engineering-231951:2974106') } + compileOnly 'slimeknights.mantle:Mantle:1.12-1.3.3.55' + compileOnly 'slimeknights:TConstruct:1.12.2-2.13.0.190' + compileOnly rfg.deobf('curse.maven:constructs-armory-287683:3174535') + compileOnly rfg.deobf('curse.maven:tinkers-complement-272671:2843439') if (project.debug_tinkers.toBoolean()) { - deobfCompile 'slimeknights.mantle:Mantle:1.12-1.3.3.55' - deobfCompile 'slimeknights:TConstruct:1.12.2-2.13.0.190' - deobfCompile 'curse.maven:constructs-armory-287683:3174535' - deobfCompile 'curse.maven:tinkers-complement-272671:2843439' - } else { - deobfProvided 'slimeknights.mantle:Mantle:1.12-1.3.3.55' - deobfProvided 'slimeknights:TConstruct:1.12.2-2.13.0.190' - deobfProvided 'curse.maven:constructs-armory-287683:3174535' - deobfProvided 'curse.maven:tinkers-complement-272671:2843439' + runtimeOnly 'slimeknights.mantle:Mantle:1.12-1.3.3.55' + runtimeOnly 'slimeknights:TConstruct:1.12.2-2.13.0.190' + runtimeOnly rfg.deobf('curse.maven:constructs-armory-287683:3174535') + runtimeOnly rfg.deobf('curse.maven:tinkers-complement-272671:2843439') + } + + compileOnly 'com.enderio.core:EnderCore:1.12.2-+' + compileOnly ('com.enderio:EnderIO:1.12.2-+') { + transitive = false } + if (project.debug_enderio.toBoolean()) { + runtimeOnly 'com.enderio.core:EnderCore:1.12.2-+' + runtimeOnly ('com.enderio:EnderIO:1.12.2-+') { + transitive = false + } + } + + +} + +def mixinConfigRefMap = 'mixins.' + project.archives_base_name + '.refmap.json' +def mixinTmpDir = buildDir.path + File.separator + 'tmp' + File.separator + 'mixins' +def refMap = "${mixinTmpDir}" + File.separator + mixinConfigRefMap +def mixinSrg = "${mixinTmpDir}" + File.separator + "mixins.srg" + +tasks.named("reobfJar", ReobfuscatedJar).configure { + extraSrgFiles.from(mixinSrg) } -sourceSets { - main { - ext.refMap = 'mixins.' + archives_base_name + '.refmap.json' +tasks.named("compileJava", JavaCompile).configure { + doFirst { + new File(mixinTmpDir).mkdirs() } + options.compilerArgs += [ + "-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}", + "-AoutSrgFile=${mixinSrg}", + "-AoutRefMapFile=${refMap}", + ] } processResources { @@ -213,52 +219,57 @@ processResources { inputs.property 'version', project.version inputs.property 'mcversion', project.minecraft.version // replace stuff in mcmod.info, nothing else - from(sourceSets.main.resources.srcDirs) { - include 'mcmod.info' + filesMatching(['mcmod.info', 'pack.mcmeta']) { fcd -> // replace version and mcversion - expand 'version': project.version, 'mcversion': project.minecraft.version - } - // copy everything else except the mcmod.info - from(sourceSets.main.resources.srcDirs) { - exclude 'mcmod.info' + fcd.expand ( + 'version': project.version, + 'mcversion': project.minecraft.version + ) } - rename '(.+_at.cfg)', 'META-INF/$1' // Access Transformers + from refMap + dependsOn 'compileJava' } jar { manifest { def attribute_map = [:] - if (project.use_coremod.toBoolean()) { - attribute_map['FMLCorePlugin'] = project.coremod_plugin_class_name - if (project.include_mod.toBoolean()) { - attribute_map['FMLCorePluginContainsFMLMod'] = true - } - } - if (project.use_mixins.toBoolean()) { - attribute_map['TweakClass'] = 'org.spongepowered.asm.launch.MixinTweaker' - // false for dev and true for non dev - attribute_map['ForceLoadAsMod'] = project.gradle.startParameter.taskNames[0] == "build" - } + attribute_map['FMLCorePlugin'] = project.coremod_plugin_class_name + attribute_map['FMLCorePluginContainsFMLMod'] = true + attribute_map['ForceLoadAsMod'] = project.gradle.startParameter.taskNames[0] == "build" attributes(attribute_map) } + // Add all embedded dependencies into the jar + from(provider{ configurations.embed.collect {it.isDirectory() ? it : zipTree(it)} }) } -shadowJar { - classifier = '' - baseName = archivesBaseName - version = version - configurations = [project.configurations.shadow] - relocate 'lib.group', "${project.group}.shadow.lib.group" // ensure repackaged packages have unique names -} - -reobf { - shadowJar {} +idea { + module { inheritOutputDirs = true } + project { settings { + runConfigurations { + "1. Run Client"(Gradle) { + taskNames = ['runClient'] + } + "2. Run Server"(Gradle) { + taskNames = ['runServer'] + } + "3. Run Obfuscated Client"(Gradle) { + taskNames = ['runObfClient'] + } + "4. Run Obfuscated Server"(Gradle) { + taskNames = ['runObfServer'] + } + } + compiler.javac { + afterEvaluate { + javacAdditionalOptions = '-encoding utf8' + moduleJavacAdditionalOptions = [ + (project.name + ".main"): tasks.compileJava.options.compilerArgs.collect { '"' + it + '"' }.join(' ') + ] + } + } + }} } -// this replaces jar.finalizedBy('reobfJar') in the standard forge mod buildscript -tasks.build.dependsOn reobfShadowJar -jar.finalizedBy('reobfShadowJar') - -artifacts { - archives shadowJar +tasks.named("processIdeaSettings").configure { + dependsOn("injectTags") } diff --git a/gradle.properties b/gradle.properties index 965c01376..17826049e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,17 +9,10 @@ maven_group = com.cleanroommc archives_base_name = groovyscript groovy_version = 4.0.8 - mod_ref_path=com.cleanroommc.groovyscript.GroovyScript - -# Boilerplate Options -use_mixins = true -use_coremod = true - debug_load_all_mods = true # Coremod Arguments -include_mod = true coremod_plugin_class_name = com.cleanroommc.groovyscript.core.GroovyScriptCore # Debug mod compat diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6b071a780..d8d24753d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 000000000..4633bcf19 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,24 @@ +pluginManagement { + repositories { + maven { + // RetroFuturaGradle + name = 'GTNH Maven' + url = 'http://jenkins.usrv.eu:8081/nexus/content/groups/public/' + allowInsecureProtocol = true + mavenContent { + includeGroup 'com.gtnewhorizons' + includeGroup 'com.gtnewhorizons.retrofuturagradle' + } + } + gradlePluginPortal() + mavenCentral() + mavenLocal() + } +} + +plugins { + // Automatic toolchain provisioning + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.4.0' +} + +rootProject.name = archives_base_name \ No newline at end of file From fedac697cee87dd203a2aa290bb8b9b393104bd9 Mon Sep 17 00:00:00 2001 From: Rongmario Date: Sun, 14 May 2023 13:37:13 +0100 Subject: [PATCH 09/30] RFG tags, fix ThaumicJEI running without Thaumcraft --- build.gradle | 6 ++++-- .../java/com/cleanroommc/groovyscript/GroovyScript.java | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 009fa58a6..30fdadcdc 100644 --- a/build.gradle +++ b/build.gradle @@ -47,12 +47,14 @@ minecraft { useDependencyAccessTransformers = true + injectedTags.put("ID", project.archives_base_name) injectedTags.put("VERSION", project.version) + injectedTags.put("GROOVY_VERSION", project.groovy_version) } // Generate a my.project.Tags class with the version number as a field tasks.injectTags.configure { - outputClassName.set("${project.group}.Tags") + outputClassName.set("${project.group}.${project.archives_base_name}.Tags") } repositories { @@ -156,8 +158,8 @@ dependencies { if (project.debug_thaum.toBoolean()) { runtimeOnly rfg.deobf('curse.maven:baubles-227083:2518667') runtimeOnly rfg.deobf('curse.maven:thaumcraft-223628:2629023') + runtimeOnly 'curse.maven:thaumic_jei-285492:2705304' } - runtimeOnly 'curse.maven:thaumic_jei-285492:2705304' compileOnly rfg.deobf('curse.maven:astralsorcery-sorcery-241721:3044416') if (project.debug_astral.toBoolean()) { diff --git a/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java b/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java index efd07b8e6..b440f53b8 100644 --- a/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java +++ b/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java @@ -67,12 +67,12 @@ @Mod.EventBusSubscriber(modid = GroovyScript.ID) public class GroovyScript { - public static final String ID = "@MODID@"; + public static final String ID = Tags.ID; public static final String NAME = "GroovyScript"; - public static final String VERSION = "@VERSION@"; + public static final String VERSION = Tags.VERSION; public static final String MC_VERSION = "1.12.2"; - public static final String GROOVY_VERSION = "@GROOVY_VERSION@"; + public static final String GROOVY_VERSION = Tags.GROOVY_VERSION; public static final Logger LOGGER = LogManager.getLogger(ID); From 57e40fdd8d6b29e3fedafbe66d3f42591e09f621 Mon Sep 17 00:00:00 2001 From: Rongmario Date: Sun, 14 May 2023 13:47:18 +0100 Subject: [PATCH 10/30] Disable javadocs jar for now --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 30fdadcdc..17289e9bf 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,7 @@ java { } // Generate sources and javadocs jars when building and publishing withSourcesJar() - withJavadocJar() + // withJavadocJar() } tasks.withType(JavaCompile).configureEach { From ec5ddefd7ef24576cc6fca63314387392fdbb56c Mon Sep 17 00:00:00 2001 From: Turing6 <39919441+Testure@users.noreply.github.com> Date: Mon, 15 May 2023 10:14:59 -0500 Subject: [PATCH 11/30] initial support --- build.gradle | 8 +- gradle.properties | 1 + .../groovyscript/compat/mods/ModSupport.java | 2 + .../compat/mods/botania/Apothecary.java | 113 +++++++ .../compat/mods/botania/Botania.java | 56 ++++ .../compat/mods/botania/Brew.java | 205 ++++++++++++ .../compat/mods/botania/ElvenTrade.java | 117 +++++++ .../compat/mods/botania/Flowers.java | 30 ++ .../compat/mods/botania/Knowledge.java | 38 +++ .../compat/mods/botania/Lexicon.java | 294 ++++++++++++++++++ .../compat/mods/botania/Magnet.java | 74 +++++ .../compat/mods/botania/ManaInfusion.java | 128 ++++++++ .../compat/mods/botania/Orechid.java | 81 +++++ .../compat/mods/botania/OrechidIgnem.java | 66 ++++ .../compat/mods/botania/PureDaisy.java | 158 ++++++++++ .../compat/mods/botania/RuneAltar.java | 121 +++++++ .../mods/botania/recipe/MagnetSubject.java | 31 ++ .../mods/botania/recipe/OrechidRecipe.java | 14 + .../mods/botania/recipe/PageChange.java | 16 + .../groovyscript/core/LateMixin.java | 2 +- .../mixin/botania/BotaniaAPIAccessor.java | 21 ++ .../resources/mixin.groovyscript.botania.json | 10 + 22 files changed, 1584 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Apothecary.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Botania.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Brew.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/ElvenTrade.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Flowers.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Knowledge.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Lexicon.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Magnet.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/ManaInfusion.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Orechid.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/OrechidIgnem.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/PureDaisy.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/RuneAltar.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/recipe/MagnetSubject.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/recipe/OrechidRecipe.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/recipe/PageChange.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/botania/BotaniaAPIAccessor.java create mode 100644 src/main/resources/mixin.groovyscript.botania.json diff --git a/build.gradle b/build.gradle index 2bad2c688..e0693f8ac 100644 --- a/build.gradle +++ b/build.gradle @@ -166,7 +166,7 @@ dependencies { deobfProvided 'curse.maven:industrialcraft_classic-242942:3093607' } - if (project.debug_astral.toBoolean() || project.debug_thaum.toBoolean()) { + if (project.debug_astral.toBoolean() || project.debug_thaum.toBoolean() || project.debug_botania.toBoolean()) { runtime 'curse.maven:baubles-227083:2518667' } @@ -200,6 +200,12 @@ dependencies { deobfProvided 'curse.maven:constructs-armory-287683:3174535' deobfProvided 'curse.maven:tinkers-complement-272671:2843439' } + + if (project.debug_botania.toBoolean()) { + deobfCompile 'curse.maven:botania-225643:3330934' + } else { + deobfProvided 'curse.maven:botania-225643:3330934' + } } sourceSets { diff --git a/gradle.properties b/gradle.properties index 965c01376..8adfd8444 100644 --- a/gradle.properties +++ b/gradle.properties @@ -34,3 +34,4 @@ debug_astral = false debug_blood_magic = false debug_tinkers = false debug_extended_crafting = false +debug_botania = true 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 06c50069c..205d1abf6 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java @@ -4,6 +4,7 @@ import com.cleanroommc.groovyscript.api.IDynamicGroovyProperty; import com.cleanroommc.groovyscript.compat.mods.astralsorcery.AstralSorcery; import com.cleanroommc.groovyscript.compat.mods.bloodmagic.BloodMagic; +import com.cleanroommc.groovyscript.compat.mods.botania.Botania; import com.cleanroommc.groovyscript.compat.mods.draconicevolution.DraconicEvolution; import com.cleanroommc.groovyscript.compat.mods.enderio.EnderIO; import com.cleanroommc.groovyscript.compat.mods.extendedcrafting.ExtendedCrafting; @@ -38,6 +39,7 @@ public class ModSupport implements IDynamicGroovyProperty { public static final Container ENDER_IO = new Container<>("enderio", "Ender IO", EnderIO::new, "eio"); public static final Container JEI = new Container<>("jei", "Just Enough Items", JustEnoughItems::new, "hei"); public static final Container THAUMCRAFT = new Container<>("thaumcraft", "Thaumcraft", Thaumcraft::new, "tc", "thaum"); + public static final Container BOTANIA = new Container<>("botania", "Botania", Botania::new); public static final Container MEKANISM = new Container<>("mekanism", "Mekanism", Mekanism::new); public static final Container THERMAL_EXPANSION = new Container<>("thermalexpansion", "Thermal Expansion", ThermalExpansion::new, "te", "thermal"); public static final Container TINKERS_CONSTRUCT = new Container<>("tconstruct", "Tinkers' Construct", TinkersConstruct::new, "ticon", "tinkersconstruct"); diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Apothecary.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Apothecary.java new file mode 100644 index 000000000..d60440263 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Apothecary.java @@ -0,0 +1,113 @@ +package com.cleanroommc.groovyscript.compat.mods.botania; + +import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.IIngredient; +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 net.minecraft.item.ItemStack; +import org.jetbrains.annotations.Nullable; +import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.api.recipe.RecipePetals; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class Apothecary extends VirtualizedRegistry { + + public RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + @GroovyBlacklist + public void onReload() { + removeScripted().forEach(BotaniaAPI.petalRecipes::remove); + BotaniaAPI.petalRecipes.addAll(restoreFromBackup()); + } + + public RecipePetals add(ItemStack output, IIngredient... inputs) { + RecipePetals recipe = new RecipePetals(output, Arrays.stream(inputs).map(i -> i instanceof OreDictIngredient ? ((OreDictIngredient) i).getOreDict() : i.getMatchingStacks()[0]).toArray()); + add(recipe); + return recipe; + } + + public void add(RecipePetals recipe) { + if (recipe == null) return; + addScripted(recipe); + BotaniaAPI.petalRecipes.add(recipe); + } + + public boolean remove(RecipePetals recipe) { + if (recipe == null) return false; + addBackup(recipe); + return BotaniaAPI.petalRecipes.remove(recipe); + } + + public boolean removeByOutput(IIngredient output) { + if (BotaniaAPI.petalRecipes.removeIf(recipe -> { + boolean found = output.test(recipe.getOutput()); + if (found) addBackup(recipe); + return found; + })) return true; + + GroovyLog.msg("Error removing Botania Apothecary recipe") + .add("could not find recipe with output {}", output) + .error() + .post(); + return false; + } + + public boolean removeByInput(IIngredient... inputs) { + List converted = Arrays.stream(inputs).map(i -> i instanceof OreDictIngredient ? ((OreDictIngredient) i).getOreDict() : i.getMatchingStacks()[0]).collect(Collectors.toList()); + if (BotaniaAPI.petalRecipes.removeIf(recipe -> { + boolean found = converted.stream().allMatch(o -> recipe.getInputs().stream().anyMatch(i -> o instanceof String ? o.equals(i) : ItemStack.areItemStacksEqual((ItemStack) i, (ItemStack) o))); + if (found) addBackup(recipe); + return found; + })) return true; + + GroovyLog.msg("Error removing Botania Apothecary recipe") + .add("could not find recipe with inputs {}", converted) + .error() + .post(); + return false; + } + + public boolean removeByInputs(IIngredient... inputs) { + return removeByInput(inputs); + } + + public void removeAll() { + BotaniaAPI.petalRecipes.forEach(this::addBackup); + BotaniaAPI.petalRecipes.clear(); + } + + public SimpleObjectStream streamRecipes() { + return new SimpleObjectStream<>(BotaniaAPI.petalRecipes).setRemover(this::remove); + } + + public class RecipeBuilder extends AbstractRecipeBuilder { + + @Override + public String getErrorMsg() { + return "Error adding Botania Apothecary recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateFluids(msg, 0, 0, 0, 0); + validateItems(msg, 1, 20, 1, 1); + } + + @Override + public @Nullable RecipePetals register() { + if (!validate()) return null; + RecipePetals recipe = new RecipePetals(output.get(0), input.stream().map(i -> i instanceof OreDictIngredient ? ((OreDictIngredient) i).getOreDict() : i.getMatchingStacks()[0]).toArray()); + add(recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Botania.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Botania.java new file mode 100644 index 000000000..c591f526b --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Botania.java @@ -0,0 +1,56 @@ +package com.cleanroommc.groovyscript.compat.mods.botania; + +import com.cleanroommc.groovyscript.brackets.BracketHandlerManager; +import com.cleanroommc.groovyscript.compat.mods.ModPropertyContainer; +import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.api.lexicon.LexiconCategory; +import vazkii.botania.api.lexicon.LexiconEntry; + +public class Botania extends ModPropertyContainer { + + public final ElvenTrade elvenTrade = new ElvenTrade(); + public final ManaInfusion manaInfusion = new ManaInfusion(); + public final PureDaisy pureDaisy = new PureDaisy(); + public final Apothecary apothecary = new Apothecary(); + public final Orechid orechid = new Orechid(); + public final OrechidIgnem orechidIgnem = new OrechidIgnem(); + public final RuneAltar runeAltar = new RuneAltar(); + public final Brew brew = new Brew(); + public final Lexicon lexicon = new Lexicon(); + public final Knowledge knowledge = new Knowledge(); + public final Magnet magnet = new Magnet(); + public final Flowers flowers = new Flowers(); + + public Botania() { + addRegistry(elvenTrade); + addRegistry(manaInfusion); + addRegistry(pureDaisy); + addRegistry(apothecary); + addRegistry(orechid); + addRegistry(orechidIgnem); + addRegistry(runeAltar); + addRegistry(brew); + addRegistry(lexicon.category); + addRegistry(lexicon.entry); + addRegistry(lexicon.page); + addRegistry(knowledge); + addRegistry(magnet); + } + + public static LexiconCategory getCategory(String name) { + for (LexiconCategory category : BotaniaAPI.getAllCategories()) + if (category.getUnlocalizedName().equals(name)) return category; + return null; + } + + public static LexiconEntry getEntry(String name) { + for (LexiconEntry entry : BotaniaAPI.getAllEntries()) + if (entry.getUnlocalizedName().equals(name)) return entry; + return null; + } + + @Override + public void initialize() { + BracketHandlerManager.registerBracketHandler("brew", s -> BotaniaAPI.brewMap.getOrDefault(s, BotaniaAPI.fallbackBrew)); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Brew.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Brew.java new file mode 100644 index 000000000..4d8384d5c --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Brew.java @@ -0,0 +1,205 @@ +package com.cleanroommc.groovyscript.compat.mods.botania; + +import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.IIngredient; +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 net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; +import org.jetbrains.annotations.Nullable; +import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.api.recipe.RecipeBrew; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class Brew extends VirtualizedRegistry { + + public BrewBuilder brewBuilder() { + return new BrewBuilder(); + } + + public RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + @GroovyBlacklist + public void onReload() { + removeScripted().forEach(BotaniaAPI.brewRecipes::remove); + BotaniaAPI.brewRecipes.addAll(restoreFromBackup()); + } + + public void add(RecipeBrew recipe) { + if (recipe == null) return; + addScripted(recipe); + BotaniaAPI.brewRecipes.add(recipe); + } + + public boolean remove(RecipeBrew recipe) { + if (recipe == null) return false; + addBackup(recipe); + return BotaniaAPI.brewRecipes.remove(recipe); + } + + public boolean removeByOutput(String brew) { + if (BotaniaAPI.brewRecipes.removeIf(recipe -> { + boolean found = recipe.getBrew().getKey().equals(brew); + if (found) addBackup(recipe); + return found; + })) return true; + + GroovyLog.msg("Error removing Botania Brew recipe") + .add("could not find recipe with input {}", brew) + .error() + .post(); + return false; + } + + public boolean removeByOutput(vazkii.botania.api.brew.Brew brew) { + return removeByOutput(brew.getKey()); + } + + public boolean removeByInput(IIngredient... inputs) { + List converted = Arrays.stream(inputs).map(i -> i instanceof OreDictIngredient ? ((OreDictIngredient) i).getOreDict() : i.getMatchingStacks()[0]).collect(Collectors.toList()); + if (BotaniaAPI.brewRecipes.removeIf(recipe -> { + boolean found = converted.stream().allMatch(o -> recipe.getInputs().stream().anyMatch(i -> (i instanceof String || o instanceof String) ? i.equals(o) : ItemStack.areItemStacksEqual((ItemStack) i, (ItemStack) o))); + if (found) addBackup(recipe); + return found; + })) return true; + + GroovyLog.msg("Error removing Botania Brew recipe") + .add("could not find recipe with inputs {}", converted) + .error() + .post(); + return false; + } + + public boolean removeByInputs(IIngredient... inputs) { + return removeByInput(inputs); + } + + public void removeAll() { + BotaniaAPI.brewRecipes.forEach(this::addBackup); + BotaniaAPI.brewRecipes.clear(); + } + + public SimpleObjectStream streamRecipes() { + return new SimpleObjectStream<>(BotaniaAPI.brewRecipes).setRemover(this::remove); + } + + public class RecipeBuilder extends AbstractRecipeBuilder { + + protected vazkii.botania.api.brew.Brew brew; + + public RecipeBuilder output(vazkii.botania.api.brew.Brew brew) { + this.brew = brew; + return this; + } + + public RecipeBuilder brew(vazkii.botania.api.brew.Brew brew) { + return output(brew); + } + + @Override + public String getErrorMsg() { + return "Error adding Botania Brew recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateFluids(msg, 0, 0, 0, 0); + validateItems(msg, 1, 20, 0, 0); + msg.add(brew == null, "Expected a valid output brew, got " + brew); + } + + @Override + public @Nullable RecipeBrew register() { + if (!validate()) return null; + RecipeBrew recipe = new RecipeBrew(brew, input.stream().map(i -> i instanceof OreDictIngredient ? ((OreDictIngredient) i).getOreDict() : i.getMatchingStacks()[0]).toArray()); + add(recipe); + return recipe; + } + } + + public SimpleObjectStream streamBrews() { + return new SimpleObjectStream<>(BotaniaAPI.brewMap.values()); + } + + public static class BrewBuilder extends AbstractRecipeBuilder { + + protected String key; + protected String name; + protected int color = 0xFFFFFF; + protected int cost; + protected boolean canInfuseIncense = true; + protected boolean canInfuseBloodPendant = true; + protected List effects = new ArrayList<>(); + + public BrewBuilder key(String key) { + this.key = key; + return this; + } + + public BrewBuilder name(String name) { + this.name = name; + return this; + } + + public BrewBuilder color(int color) { + this.color = color; + return this; + } + + public BrewBuilder cost(int cost) { + this.cost = cost; + return this; + } + + public BrewBuilder noIncenseInfusion() { + this.canInfuseIncense = false; + return this; + } + + public BrewBuilder noBloodPendantInfusion() { + this.canInfuseBloodPendant = false; + return this; + } + + public BrewBuilder effect(PotionEffect effect) { + this.effects.add(effect); + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Botania Brew"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 0, 0, 0, 0); + validateFluids(msg, 0, 0, 0, 0); + msg.add(key == null, "must have a unique key for brew, got " + key); + msg.add(cost < 1, "cost must be at least 1, got " + cost); + msg.add(effects.size() < 1, "must have at least 1 potion effect, got " + effects.size()); + } + + @Nullable + @Override + public vazkii.botania.api.brew.Brew register() { + if (!validate()) return null; + if (name == null) name = key; + vazkii.botania.api.brew.Brew brew = new vazkii.botania.api.brew.Brew(key, name, color, cost, effects.toArray(new PotionEffect[0])); + if (!canInfuseBloodPendant) brew.setNotBloodPendantInfusable(); + if (!canInfuseIncense) brew.setNotIncenseInfusable(); + BotaniaAPI.registerBrew(brew); + return brew; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/ElvenTrade.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/ElvenTrade.java new file mode 100644 index 000000000..f8b53baff --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/ElvenTrade.java @@ -0,0 +1,117 @@ +package com.cleanroommc.groovyscript.compat.mods.botania; + +import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.IIngredient; +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 net.minecraft.item.ItemStack; +import org.jetbrains.annotations.Nullable; +import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.api.recipe.RecipeElvenTrade; + +import java.util.Arrays; +import java.util.List; + +public class ElvenTrade extends VirtualizedRegistry { + + public RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + @GroovyBlacklist + public void onReload() { + removeScripted().forEach(BotaniaAPI.elvenTradeRecipes::remove); + BotaniaAPI.elvenTradeRecipes.addAll(restoreFromBackup()); + } + + protected Object[] convertIngredients(IIngredient[] inputs) { + return Arrays.stream(inputs).map(input -> input instanceof OreDictIngredient ? ((OreDictIngredient) input).getOreDict() : input.getMatchingStacks()[0]).toArray(); + } + + public RecipeElvenTrade add(ItemStack[] outputs, IIngredient[] inputs) { + RecipeElvenTrade recipe = new RecipeElvenTrade(outputs, convertIngredients(inputs)); + add(recipe); + return recipe; + } + + public RecipeElvenTrade add(ItemStack output, IIngredient[] inputs) { + return add(new ItemStack[]{output}, inputs); + } + + public void add(RecipeElvenTrade recipe) { + if (recipe == null) return; + addScripted(recipe); + BotaniaAPI.elvenTradeRecipes.add(recipe); + } + + public boolean remove(RecipeElvenTrade recipe) { + if (recipe == null) return false; + addBackup(recipe); + return BotaniaAPI.elvenTradeRecipes.remove(recipe); + } + + public boolean removeByOutputs(ItemStack... outputs) { + if (BotaniaAPI.elvenTradeRecipes.removeIf(recipe -> { + boolean found = Arrays.stream(outputs).allMatch(output -> recipe.getOutputs().stream().anyMatch(o -> ItemStack.areItemStacksEqual(o, output))); + if (found) addBackup(recipe); + return found; + })) return true; + + GroovyLog.msg("Error removing Botania Elven Trade recipe") + .add("could not find recipe with outputs {}", outputs) + .error() + .post(); + return false; + } + + public boolean removeByInputs(IIngredient... inputs) { + List converted = Arrays.asList(convertIngredients(inputs)); + List list = Arrays.asList(inputs); + if (BotaniaAPI.elvenTradeRecipes.removeIf(recipe -> { + boolean found = recipe.getInputs().stream().allMatch(input -> input instanceof String ? converted.contains(input) : list.stream().anyMatch(i -> i.test((ItemStack) input))); + if (found) addBackup(recipe); + return found; + })) return true; + + GroovyLog.msg("Error removing Botania Elven Trade recipe") + .add("could not find recipe with inputs {}", converted) + .error() + .post(); + return false; + } + + public void removeAll() { + BotaniaAPI.elvenTradeRecipes.forEach(this::addBackup); + BotaniaAPI.elvenTradeRecipes.clear(); + } + + public SimpleObjectStream streamRecipes() { + return new SimpleObjectStream<>(BotaniaAPI.elvenTradeRecipes).setRemover(this::remove); + } + + public class RecipeBuilder extends AbstractRecipeBuilder { + + @Override + public String getErrorMsg() { + return "Error adding Botania Elven Trade recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateFluids(msg, 0, 0, 0, 0); + validateItems(msg, 1, 99, 1, 99); + } + + @Override + public @Nullable RecipeElvenTrade register() { + if (!validate()) return null; + RecipeElvenTrade recipe = new RecipeElvenTrade(output.toArray(new ItemStack[0]), convertIngredients(input.toArray(new IIngredient[0]))); + add(recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Flowers.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Flowers.java new file mode 100644 index 000000000..957af53bd --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Flowers.java @@ -0,0 +1,30 @@ +package com.cleanroommc.groovyscript.compat.mods.botania; + +import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.api.subtile.SubTileEntity; +import vazkii.botania.api.subtile.signature.BasicSignature; + +public class Flowers { + + public void registerFlower(String name, Class clazz) { + BotaniaAPI.registerSubTile(name, clazz); + BotaniaAPI.registerSubTileSignature(clazz, new BasicSignature(name)); + BotaniaAPI.addSubTileToCreativeMenu(name); + } + + public void registerFlowerWithMini(String name, Class clazz) { + registerFlower(name, clazz); + Class[] subClasses = clazz.getDeclaredClasses(); + int l = subClasses.length; + + for (int i = 0; i < l; i++) { + Class subClass = subClasses[i]; + if (subClass.getSimpleName().equals("Mini") && SubTileEntity.class.isAssignableFrom(subClass)) { + BotaniaAPI.registerMiniSubTile(name + "Chibi", (Class) subClass, name); + BotaniaAPI.registerSubTileSignature((Class) subClass, new BasicSignature(name + "Chibi")); + BotaniaAPI.addSubTileToCreativeMenu(name); + break; + } + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Knowledge.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Knowledge.java new file mode 100644 index 000000000..e623d90ba --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Knowledge.java @@ -0,0 +1,38 @@ +package com.cleanroommc.groovyscript.compat.mods.botania; + +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import net.minecraft.util.text.TextFormatting; +import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.api.lexicon.KnowledgeType; + +import javax.annotation.Nullable; + +public class Knowledge extends VirtualizedRegistry { + + @Override + public void onReload() { + removeScripted().forEach(type -> BotaniaAPI.knowledgeTypes.remove(type.id, type)); + restoreFromBackup().forEach(type -> BotaniaAPI.knowledgeTypes.put(type.id, type)); + } + + public KnowledgeType add(String id, @Nullable TextFormatting formatting, boolean autoUnlock) { + KnowledgeType type = new KnowledgeType(id, formatting != null ? formatting : TextFormatting.RESET, autoUnlock); + add(type); + return type; + } + + public KnowledgeType add(String id, @Nullable TextFormatting formatting) { + return add(id, formatting, false); + } + + public void add(KnowledgeType type) { + if (type == null) return; + addScripted(type); + BotaniaAPI.knowledgeTypes.put(type.id, type); + } + + public SimpleObjectStream streamKnowledgeTypes() { + return new SimpleObjectStream<>(BotaniaAPI.knowledgeTypes.values()); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Lexicon.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Lexicon.java new file mode 100644 index 000000000..5c01cf37a --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Lexicon.java @@ -0,0 +1,294 @@ +package com.cleanroommc.groovyscript.compat.mods.botania; + +import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.compat.mods.botania.recipe.PageChange; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.common.registry.EntityEntry; +import org.jetbrains.annotations.Nullable; +import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.api.lexicon.KnowledgeType; +import vazkii.botania.api.lexicon.LexiconCategory; +import vazkii.botania.api.lexicon.LexiconEntry; +import vazkii.botania.api.lexicon.LexiconPage; +import vazkii.botania.api.recipe.*; +import vazkii.botania.common.lexicon.page.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class Lexicon { + public final Category category = new Category(); + public final Entry entry = new Entry(); + public final Page page = new Page(); + + public static class Category extends VirtualizedRegistry { + + @Override + @GroovyBlacklist + public void onReload() { + removeScripted().forEach(BotaniaAPI.getAllCategories()::remove); + BotaniaAPI.getAllCategories().addAll(restoreFromBackup()); + } + + public LexiconCategory add(String name, ResourceLocation icon, int priority) { + LexiconCategory category = new LexiconCategory(name); + category.setIcon(icon); + category.setPriority(priority); + add(category); + return category; + } + + public LexiconCategory add(String name, ResourceLocation icon) { + return add(name, icon, 5); + } + + public void add(LexiconCategory category) { + if (category == null) return; + addScripted(category); + BotaniaAPI.addCategory(category); + } + + public boolean remove(LexiconCategory category) { + if (category == null) return false; + addBackup(category); + BotaniaAPI.getAllCategories().remove(category); + return true; + } + + public boolean removeCategory(String name) { + LexiconCategory category = Botania.getCategory(name); + if (category != null) return remove(category); + return false; + } + + public SimpleObjectStream streamCategories() { + return new SimpleObjectStream<>(BotaniaAPI.getAllCategories()).setRemover(this::remove); + } + } + + public static class Page extends VirtualizedRegistry { + + @Override + @GroovyBlacklist + public void onReload() { + removeScripted().forEach(change -> change.parent.pages.remove(change.index)); + restoreFromBackup().forEach(change -> change.parent.pages.add(change.index, change.page)); + } + + public void add(LexiconEntry entry, LexiconPage page, int index) { + if (page == null || entry == null) return; + if (entry.pages.contains(page)) return; + PageChange change = new PageChange(page, entry, index); + addScripted(change); + entry.pages.add(index, page); + } + + public boolean remove(LexiconEntry entry, LexiconPage page) { + if (page == null || entry == null) return false; + if (!entry.pages.contains(page)) return false; + int index = entry.pages.indexOf(page); + PageChange change = new PageChange(page, entry, index); + addBackup(change); + entry.pages.remove(index); + return true; + } + + public boolean remove(LexiconEntry entry, int index) { + if (entry == null) return false; + if (entry.pages.get(index) == null) return false; + LexiconPage page = entry.pages.get(index); + return remove(entry, page); + } + + public void removeAll(LexiconEntry entry) { + for (int i = 0; i < entry.pages.size(); i++) + addBackup(new PageChange(entry.pages.get(i), entry, i)); + entry.pages.clear(); + } + + public SimpleObjectStream streamPages(LexiconEntry entry) { + return new SimpleObjectStream<>(entry.pages).setRemover(page -> remove(entry, page)); + } + + public PageText createTextPage(String name) { + return new PageText(name); + } + + public PageLoreText createLoreTextPage(String name) { + return new PageLoreText(name); + } + + public PageImage createImagePage(String name, String image) { + return new PageImage(name, image); + } + + public PageEntity createEntityPage(String name, int size, String entity) { + return new PageEntity(name, entity, size); + } + + public PageEntity createEntityPage(String name, int size, EntityEntry entity) { + return createEntityPage(name, size, Objects.requireNonNull(entity.getRegistryName()).toString()); + } + + public PageCraftingRecipe createCraftingPage(String name, String... recipes) { + return new PageCraftingRecipe(name, Arrays.stream(recipes).map(ResourceLocation::new).collect(Collectors.toList())); + } + + public PageBrew createBrewingPage(String name, String bottomText, RecipeBrew recipe) { + return new PageBrew(recipe, name, bottomText); + } + + public PageManaInfusionRecipe createInfusionPage(String name, RecipeManaInfusion... recipes) { + return new PageManaInfusionRecipe(name, Arrays.asList(recipes)); + } + + public PageRuneRecipe createRunePage(String name, RecipeRuneAltar... recipes) { + return new PageRuneRecipe(name, Arrays.asList(recipes)); + } + + public PagePetalRecipe createPetalPage(String name, RecipePetals... recipes) { + return new PagePetalRecipe<>(name, Arrays.asList(recipes)); + } + + public PageElvenRecipe createElvenTradePage(String name, RecipeElvenTrade... recipes) { + return new PageElvenRecipe(name, Arrays.asList(recipes)); + } + } + + public static class Entry extends VirtualizedRegistry { + + public EntryBuilder entryBuilder() { + return new EntryBuilder(); + } + + @Override + @GroovyBlacklist + public void onReload() { + removeScripted().forEach(BotaniaAPI.getAllEntries()::remove); + restoreFromBackup().forEach(entry -> { + BotaniaAPI.getAllEntries().add(entry); + entry.category.entries.add(entry); + }); + } + + public LexiconEntry add(String name, LexiconCategory category) { + LexiconEntry entry = new LexiconEntry(name, category); + add(entry); + return entry; + } + + public LexiconEntry add(String name, String category) { + return add(name, Botania.getCategory(category)); + } + + public void add(LexiconEntry entry) { + if (entry == null) return; + addScripted(entry); + BotaniaAPI.addEntry(entry, entry.category); + } + + public boolean remove(LexiconEntry entry) { + if (entry == null) return false; + addBackup(entry); + BotaniaAPI.getAllEntries().remove(entry); + entry.category.entries.remove(entry); + return true; + } + + public boolean removeEntry(String name) { + LexiconEntry entry = Botania.getEntry(name); + if (entry != null) return remove(entry); + return false; + } + + public SimpleObjectStream streamEntries() { + return new SimpleObjectStream<>(BotaniaAPI.getAllEntries()).setRemover(this::remove); + } + + public class EntryBuilder extends AbstractRecipeBuilder { + + protected String name; + protected LexiconCategory category; + protected KnowledgeType type = BotaniaAPI.basicKnowledge; + protected ItemStack icon = ItemStack.EMPTY; + protected final List pages = new ArrayList<>(); + protected final List extraRecipes = new ArrayList<>(); + protected boolean priority = false; + + public EntryBuilder isPriority() { + this.priority = true; + return this; + } + + public EntryBuilder icon(IIngredient icon) { + this.icon = icon.getMatchingStacks()[0]; + return this; + } + + public EntryBuilder name(String name) { + this.name = name; + return this; + } + + public EntryBuilder category(LexiconCategory category) { + this.category = category; + return this; + } + + public EntryBuilder category(String categoryName) { + return category(Botania.getCategory(categoryName)); + } + + public EntryBuilder knowledgeType(KnowledgeType type) { + this.type = type; + return this; + } + + public EntryBuilder page(LexiconPage page) { + this.pages.add(page); + return this; + } + + public EntryBuilder extraRecipe(IIngredient stack) { + this.extraRecipes.add(stack.getMatchingStacks()[0]); + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Botania Lexicon Entry"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateFluids(msg, 0, 0, 0, 0); + validateItems(msg, 0, 0, 0, 0); + msg.add(name == null, "expected a valid name, got " + name); + msg.add(pages.size() < 1, "entry must have at least 1 page, got " + pages.size()); + msg.add(category == null, "expected a valid category, got " + category); + } + + @Override + public @Nullable LexiconEntry register() { + if (!validate()) return null; + LexiconEntry entry = new LexiconEntry(name, category); + if (priority) entry.setPriority(); + entry.setKnowledgeType(type); + entry.setIcon(icon); + pages.forEach(entry::addPage); + extraRecipes.forEach(entry::addExtraDisplayedRecipe); + add(entry); + return entry; + } + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Magnet.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Magnet.java new file mode 100644 index 000000000..4b98b3d97 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Magnet.java @@ -0,0 +1,74 @@ +package com.cleanroommc.groovyscript.compat.mods.botania; + +import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.compat.mods.botania.recipe.MagnetSubject; +import com.cleanroommc.groovyscript.core.mixin.botania.BotaniaAPIAccessor; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import vazkii.botania.api.BotaniaAPI; + +public class Magnet extends VirtualizedRegistry { + + @Override + @GroovyBlacklist + public void onReload() { + removeScripted().forEach(m -> BotaniaAPI.magnetBlacklist.remove(m.getMagnetKey())); + restoreFromBackup().forEach(m -> BotaniaAPI.magnetBlacklist.add(m.getMagnetKey())); + } + + public boolean isInBlacklist(IIngredient item) { + return BotaniaAPI.isItemBlacklistedFromMagnet(item.getMatchingStacks()[0]); + } + + public boolean isInBlacklist(Block block, int meta) { + return BotaniaAPI.isBlockBlacklistedFromMagnet(block, meta); + } + + public boolean isInBlacklist(IBlockState state) { + return BotaniaAPI.isBlockBlacklistedFromMagnet(state); + } + + public void addToBlacklist(IIngredient item) { + if (item == null) return; + MagnetSubject subject = new MagnetSubject(item); + addScripted(subject); + BotaniaAPI.blacklistItemFromMagnet(item.getMatchingStacks()[0]); + } + + public void addToBlacklist(Block block, int meta) { + if (block == null) return; + MagnetSubject subject = new MagnetSubject(block, meta); + addScripted(subject); + BotaniaAPI.blacklistBlockFromMagnet(block, meta); + } + + public void addToBlacklist(IBlockState state) { + addToBlacklist(state.getBlock(), state.getBlock().getMetaFromState(state)); + } + + public boolean removeFromBlacklist(IIngredient item) { + if (item == null) return false; + String key = BotaniaAPIAccessor.invokeGetMagnetKey(item.getMatchingStacks()[0]); + if (!BotaniaAPI.magnetBlacklist.contains(key)) return false; + MagnetSubject subject = new MagnetSubject(item); + addBackup(subject); + BotaniaAPI.magnetBlacklist.remove(key); + return true; + } + + public boolean removeFromBlacklist(Block block, int meta) { + if (block == null) return false; + String key = BotaniaAPIAccessor.invokeGetMagnetKey(block, meta); + if (!BotaniaAPI.magnetBlacklist.contains(key)) return false; + MagnetSubject subject = new MagnetSubject(block, meta); + addBackup(subject); + BotaniaAPI.magnetBlacklist.remove(key); + return true; + } + + public boolean removeFromBlacklist(IBlockState state) { + return removeFromBlacklist(state.getBlock(), state.getBlock().getMetaFromState(state)); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/ManaInfusion.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/ManaInfusion.java new file mode 100644 index 000000000..605db69f4 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/ManaInfusion.java @@ -0,0 +1,128 @@ +package com.cleanroommc.groovyscript.compat.mods.botania; + +import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.IIngredient; +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 net.minecraft.block.state.IBlockState; +import net.minecraft.item.ItemStack; +import org.jetbrains.annotations.Nullable; +import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.api.recipe.RecipeManaInfusion; + +public class ManaInfusion extends VirtualizedRegistry { + + public RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + @GroovyBlacklist + public void onReload() { + removeScripted().forEach(BotaniaAPI.manaInfusionRecipes::remove); + BotaniaAPI.manaInfusionRecipes.addAll(restoreFromBackup()); + } + + public RecipeManaInfusion add(ItemStack output, IIngredient input, int mana) { + RecipeManaInfusion recipe = new RecipeManaInfusion(output, input instanceof OreDictIngredient ? ((OreDictIngredient) input).getOreDict() : input.getMatchingStacks()[0], mana); + add(recipe); + return recipe; + } + + public void add(RecipeManaInfusion recipe) { + if (recipe == null) return; + addScripted(recipe); + BotaniaAPI.manaInfusionRecipes.add(recipe); + } + + public boolean remove(RecipeManaInfusion recipe) { + if (recipe == null) return false; + addBackup(recipe); + return BotaniaAPI.manaInfusionRecipes.remove(recipe); + } + + public boolean removeByOutput(ItemStack output) { + if (BotaniaAPI.manaInfusionRecipes.removeIf(recipe -> { + boolean found = ItemStack.areItemStacksEqual(recipe.getOutput(), output); + if (found) addBackup(recipe); + return found; + })) return true; + + GroovyLog.msg("Error removing Botania Mana Infusion recipe") + .add("could not find recipe with output {}", output) + .error() + .post(); + return false; + } + + public boolean removeByInput(IIngredient input) { + if (BotaniaAPI.manaInfusionRecipes.removeIf(recipe -> { + boolean found = recipe.getInput() instanceof ItemStack ? input.test((ItemStack) recipe.getInput()) : (input instanceof OreDictIngredient && ((OreDictIngredient) input).getOreDict().equals(recipe.getInput())); + if (found) addBackup(recipe); + return found; + })) return true; + + GroovyLog.msg("Error removing Botania Mana Infusion recipe") + .add("could not find recipe with input {}", input) + .error() + .post(); + return false; + } + + public void removeAll() { + BotaniaAPI.manaInfusionRecipes.forEach(this::addBackup); + BotaniaAPI.manaInfusionRecipes.clear(); + } + + public SimpleObjectStream streamRecipes() { + return new SimpleObjectStream<>(BotaniaAPI.manaInfusionRecipes).setRemover(this::remove); + } + + public class RecipeBuilder extends AbstractRecipeBuilder { + + protected int mana = 100; + protected IBlockState catalyst; + + public RecipeBuilder mana(int amount) { + this.mana = amount; + return this; + } + + public RecipeBuilder catalyst(IBlockState block) { + this.catalyst = block; + return this; + } + + public RecipeBuilder useAlchemy() { + return catalyst(RecipeManaInfusion.alchemyState); + } + + public RecipeBuilder useConjuration() { + return catalyst(RecipeManaInfusion.conjurationState); + } + + @Override + public String getErrorMsg() { + return "Error adding Botania Mana Infusion recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateFluids(msg, 0, 0, 0, 0); + validateItems(msg, 1, 1, 1, 1); + msg.add(mana < 1, "Mana amount must be at least 1, got " + mana); + } + + @Override + public @Nullable RecipeManaInfusion register() { + if (!validate()) return null; + RecipeManaInfusion recipe = new RecipeManaInfusion(output.get(0), input.get(0) instanceof OreDictIngredient ? ((OreDictIngredient) input.get(0)).getOreDict() : input.get(0).getMatchingStacks()[0], mana); + if (catalyst != null) recipe.setCatalyst(catalyst); + add(recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Orechid.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Orechid.java new file mode 100644 index 000000000..44e48c296 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Orechid.java @@ -0,0 +1,81 @@ +package com.cleanroommc.groovyscript.compat.mods.botania; + +import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.compat.mods.botania.recipe.OrechidRecipe; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import vazkii.botania.api.BotaniaAPI; + +import java.util.ArrayList; +import java.util.List; + +public class Orechid extends VirtualizedRegistry { + + @Override + @GroovyBlacklist + public void onReload() { + removeScripted().forEach(recipe -> BotaniaAPI.oreWeights.remove(recipe.output.getOreDict())); + restoreFromBackup().forEach(recipe -> BotaniaAPI.oreWeights.put(recipe.output.getOreDict(), recipe.weight)); + } + + protected List getAllRecipes() { + List recipes = new ArrayList<>(BotaniaAPI.oreWeights.size()); + BotaniaAPI.oreWeights.forEach((ore, weight) -> recipes.add(new OrechidRecipe(new OreDictIngredient(ore), weight))); + return recipes; + } + + public OrechidRecipe add(OreDictIngredient output, int weight) { + OrechidRecipe recipe = new OrechidRecipe(output, weight); + add(recipe); + return recipe; + } + + public OrechidRecipe add(String output, int weight) { + return add(new OreDictIngredient(output), weight); + } + + public void add(OrechidRecipe recipe) { + if (recipe == null) return; + addScripted(recipe); + BotaniaAPI.oreWeights.put(recipe.output.getOreDict(), recipe.weight); + } + + public boolean remove(OrechidRecipe recipe) { + if (recipe == null) return false; + if (BotaniaAPI.oreWeights.containsKey(recipe.output.getOreDict())) { + addBackup(recipe); + BotaniaAPI.oreWeights.remove(recipe.output.getOreDict()); + return true; + } + return false; + } + + public boolean removeByOutput(OreDictIngredient output) { + if (BotaniaAPI.oreWeights.containsKey(output.getOreDict())) { + addBackup(new OrechidRecipe(output, BotaniaAPI.getOreWeight(output.getOreDict()))); + BotaniaAPI.oreWeights.remove(output.getOreDict()); + return true; + } + + GroovyLog.msg("Error removing Botania Orechid recipe") + .add("could not find recipe for oredict {}", output) + .error() + .post(); + return false; + } + + public boolean removeByOutput(String output) { + return removeByOutput(new OreDictIngredient(output)); + } + + public void removeAll() { + getAllRecipes().forEach(this::addBackup); + BotaniaAPI.oreWeights.clear(); + } + + public SimpleObjectStream streamRecipes() { + return new SimpleObjectStream<>(getAllRecipes(), false).setRemover(this::remove); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/OrechidIgnem.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/OrechidIgnem.java new file mode 100644 index 000000000..478ececa2 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/OrechidIgnem.java @@ -0,0 +1,66 @@ +package com.cleanroommc.groovyscript.compat.mods.botania; + +import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.compat.mods.botania.recipe.OrechidRecipe; +import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; +import vazkii.botania.api.BotaniaAPI; + +import java.util.ArrayList; +import java.util.List; + +public class OrechidIgnem extends Orechid { + + @Override + @GroovyBlacklist + public void onReload() { + removeScripted().forEach(recipe -> BotaniaAPI.oreWeightsNether.remove(recipe.output.getOreDict())); + restoreFromBackup().forEach(recipe -> BotaniaAPI.oreWeightsNether.put(recipe.output.getOreDict(), recipe.weight)); + } + + @Override + protected List getAllRecipes() { + List list = new ArrayList<>(BotaniaAPI.oreWeightsNether.size()); + BotaniaAPI.oreWeightsNether.forEach((ore, weight) -> list.add(new OrechidRecipe(new OreDictIngredient(ore), weight))); + return list; + } + + @Override + public void add(OrechidRecipe recipe) { + if (recipe == null) return; + addScripted(recipe); + BotaniaAPI.oreWeightsNether.put(recipe.output.getOreDict(), recipe.weight); + } + + @Override + public boolean remove(OrechidRecipe recipe) { + if (recipe == null) return false; + if (BotaniaAPI.oreWeightsNether.containsKey(recipe.output.getOreDict())) { + addBackup(recipe); + BotaniaAPI.oreWeightsNether.remove(recipe.output.getOreDict()); + return true; + } + return false; + } + + @Override + public boolean removeByOutput(OreDictIngredient output) { + if (BotaniaAPI.oreWeightsNether.containsKey(output.getOreDict())) { + addBackup(new OrechidRecipe(output, BotaniaAPI.getOreWeight(output.getOreDict()))); + BotaniaAPI.oreWeightsNether.remove(output.getOreDict()); + return true; + } + + GroovyLog.msg("Error removing Botania OrechidIgnem recipe") + .add("could not find recipe for oredict {}", output) + .error() + .post(); + return false; + } + + @Override + public void removeAll() { + getAllRecipes().forEach(this::addBackup); + BotaniaAPI.oreWeightsNether.clear(); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/PureDaisy.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/PureDaisy.java new file mode 100644 index 000000000..3db5c93b4 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/PureDaisy.java @@ -0,0 +1,158 @@ +package com.cleanroommc.groovyscript.compat.mods.botania; + +import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.helper.SimpleObjectStream; +import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; +import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; +import org.jetbrains.annotations.Nullable; +import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.api.recipe.RecipePureDaisy; + +public class PureDaisy extends VirtualizedRegistry { + + public RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + @GroovyBlacklist + public void onReload() { + removeScripted().forEach(BotaniaAPI.pureDaisyRecipes::remove); + BotaniaAPI.pureDaisyRecipes.addAll(restoreFromBackup()); + } + + public RecipePureDaisy add(IBlockState output, IBlockState input, int time) { + RecipePureDaisy recipe = new RecipePureDaisy(input, output, time); + add(recipe); + return recipe; + } + + public RecipePureDaisy add(IBlockState output, IBlockState input) { + return add(output, input, RecipePureDaisy.DEFAULT_TIME); + } + + public void add(RecipePureDaisy recipe) { + if (recipe == null) return; + addScripted(recipe); + BotaniaAPI.pureDaisyRecipes.add(recipe); + } + + public boolean remove(RecipePureDaisy recipe) { + if (recipe == null) return false; + addBackup(recipe); + return BotaniaAPI.pureDaisyRecipes.remove(recipe); + } + + public boolean removeByOutput(IBlockState output) { + if (BotaniaAPI.pureDaisyRecipes.removeIf(recipe -> { + boolean found = recipe.getOutputState().equals(output); + if (found) addBackup(recipe); + return found; + })) return true; + + GroovyLog.msg("Error removing Botania Pure Daisy recipe") + .add("could not find recipe with output {}", output) + .error() + .post(); + return false; + } + + public boolean removeByInput(String input) { + if (BotaniaAPI.pureDaisyRecipes.removeIf(recipe -> { + boolean found = recipe.getInput() instanceof String && recipe.getInput().equals(input); + if (found) addBackup(recipe); + return found; + })) return true; + + GroovyLog.msg("Error removing Botania Pure Daisy recipe") + .add("could not find recipe with input {}", input) + .error() + .post(); + return false; + } + + public boolean removeByInput(IBlockState input) { + if (BotaniaAPI.pureDaisyRecipes.removeIf(recipe -> { + boolean found = (recipe.getInput() instanceof IBlockState && recipe.getInput().equals(input)) || (recipe.getInput() instanceof Block && recipe.getInput() == input.getBlock()); + if (found) addBackup(recipe); + return found; + })) return true; + + GroovyLog.msg("Error removing Botania Pure Daisy recipe") + .add("could not find recipe with input {}", input) + .error() + .post(); + return false; + } + + public boolean removeByInput(Block input) { + return removeByInput(input.getDefaultState()); + } + + public void removeAll() { + BotaniaAPI.pureDaisyRecipes.forEach(this::addBackup); + BotaniaAPI.pureDaisyRecipes.clear(); + } + + public SimpleObjectStream streamRecipes() { + return new SimpleObjectStream<>(BotaniaAPI.pureDaisyRecipes).setRemover(this::remove); + } + + public class RecipeBuilder extends AbstractRecipeBuilder { + + protected int time = RecipePureDaisy.DEFAULT_TIME; + protected IBlockState output; + protected Object input; + + public RecipeBuilder time(int amount) { + this.time = amount; + return this; + } + + public RecipeBuilder output(IBlockState output) { + this.output = output; + return this; + } + + public RecipeBuilder input(IBlockState input) { + this.input = input; + return this; + } + + public RecipeBuilder input(Block input) { + return input(input.getDefaultState()); + } + + public RecipeBuilder input(String input) { + this.input = input; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Botania Pure Daisy recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 0, 0, 0, 0); + validateFluids(msg, 0, 0, 0, 0); + msg.add(time < 0, "time must be at least 1, got " + time); + msg.add(output != null, "expected IBlockState output, got " + output); + msg.add(input != null, "expected IBlockState or String input, got " + input); + } + + @Override + public @Nullable RecipePureDaisy register() { + if (!validate()) return null; + RecipePureDaisy recipe = new RecipePureDaisy(input, output, time); + add(recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/RuneAltar.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/RuneAltar.java new file mode 100644 index 000000000..3c245dffd --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/RuneAltar.java @@ -0,0 +1,121 @@ +package com.cleanroommc.groovyscript.compat.mods.botania; + +import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.api.IIngredient; +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 net.minecraft.item.ItemStack; +import org.jetbrains.annotations.Nullable; +import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.api.recipe.RecipeRuneAltar; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class RuneAltar extends VirtualizedRegistry { + + public RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + @GroovyBlacklist + public void onReload() { + removeScripted().forEach(BotaniaAPI.runeAltarRecipes::remove); + BotaniaAPI.runeAltarRecipes.addAll(restoreFromBackup()); + } + + public RecipeRuneAltar add(ItemStack output, int mana, IIngredient... inputs) { + RecipeRuneAltar recipe = new RecipeRuneAltar(output, mana, Arrays.stream(inputs).map(i -> i instanceof OreDictIngredient ? ((OreDictIngredient) i).getOreDict() : i.getMatchingStacks()[0]).toArray()); + add(recipe); + return recipe; + } + + public void add(RecipeRuneAltar recipe) { + if (recipe == null) return; + addScripted(recipe); + BotaniaAPI.runeAltarRecipes.add(recipe); + } + + public boolean remove(RecipeRuneAltar recipe) { + if (recipe == null) return false; + addBackup(recipe); + return BotaniaAPI.runeAltarRecipes.remove(recipe); + } + + public boolean removeByOutput(IIngredient output) { + if (BotaniaAPI.runeAltarRecipes.removeIf(recipe -> { + boolean found = output.test(recipe.getOutput()); + if (found) addBackup(recipe); + return found; + })) return true; + + GroovyLog.msg("Error removing Botania Rune Altar recipe") + .add("could not find recipe with output {}", output) + .error() + .post(); + return false; + } + + public boolean removeByInput(IIngredient... inputs) { + List converted = Arrays.stream(inputs).map(i -> i instanceof OreDictIngredient ? ((OreDictIngredient) i).getOreDict() : i.getMatchingStacks()[0]).collect(Collectors.toList()); + if (BotaniaAPI.runeAltarRecipes.removeIf(recipe -> { + boolean found = converted.stream().allMatch(o -> recipe.getInputs().stream().anyMatch(i -> (i instanceof String || o instanceof String)? i.equals(o) : ItemStack.areItemStacksEqual((ItemStack) i, (ItemStack) o)));; + if (found) addBackup(recipe); + return found; + })) return true; + + GroovyLog.msg("Error removing Botania Rune Altar recipe") + .add("could not find recipe with inputs {}", converted) + .error() + .post(); + return false; + } + + public boolean removeByInputs(IIngredient... inputs) { + return removeByInput(inputs); + } + + public void removeAll() { + BotaniaAPI.runeAltarRecipes.forEach(this::addBackup); + BotaniaAPI.runeAltarRecipes.clear(); + } + + public SimpleObjectStream streamRecipes() { + return new SimpleObjectStream<>(BotaniaAPI.runeAltarRecipes).setRemover(this::remove); + } + + public class RecipeBuilder extends AbstractRecipeBuilder { + + protected int mana; + + public RecipeBuilder mana(int amount) { + this.mana = amount; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding Botania Rune Altar recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateFluids(msg, 0, 0, 0, 0); + validateItems(msg, 1, 20, 1, 1); + msg.add(mana < 1, "mana must be at least 1, got " + mana); + } + + @Override + public @Nullable RecipeRuneAltar register() { + if (!validate()) return null; + RecipeRuneAltar recipe = new RecipeRuneAltar(output.get(0), mana, input.stream().map(i -> i instanceof OreDictIngredient ? ((OreDictIngredient) i).getOreDict() : i.getMatchingStacks()[0]).toArray()); + add(recipe); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/recipe/MagnetSubject.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/recipe/MagnetSubject.java new file mode 100644 index 000000000..472294e8d --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/recipe/MagnetSubject.java @@ -0,0 +1,31 @@ +package com.cleanroommc.groovyscript.compat.mods.botania.recipe; + +import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.core.mixin.botania.BotaniaAPIAccessor; +import net.minecraft.block.Block; + +public class MagnetSubject { + public final IIngredient item; + public final Block block; + public final int meta; + + public MagnetSubject(IIngredient item) { + this.item = item; + this.meta = 0; + this.block = null; + } + + public MagnetSubject(Block block, int meta) { + this.meta = meta; + this.block = block; + this.item = null; + } + + public boolean isBlock() { + return block != null; + } + + public String getMagnetKey() { + return isBlock() ? BotaniaAPIAccessor.invokeGetMagnetKey(block, meta) : BotaniaAPIAccessor.invokeGetMagnetKey(item.getMatchingStacks()[0]); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/recipe/OrechidRecipe.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/recipe/OrechidRecipe.java new file mode 100644 index 000000000..0656bf712 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/recipe/OrechidRecipe.java @@ -0,0 +1,14 @@ +package com.cleanroommc.groovyscript.compat.mods.botania.recipe; + +import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; + +public class OrechidRecipe { + + public final int weight; + public final OreDictIngredient output; + + public OrechidRecipe(OreDictIngredient output, int weight) { + this.weight = weight; + this.output = output; + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/recipe/PageChange.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/recipe/PageChange.java new file mode 100644 index 000000000..990747176 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/recipe/PageChange.java @@ -0,0 +1,16 @@ +package com.cleanroommc.groovyscript.compat.mods.botania.recipe; + +import vazkii.botania.api.lexicon.LexiconEntry; +import vazkii.botania.api.lexicon.LexiconPage; + +public class PageChange { + public LexiconPage page; + public LexiconEntry parent; + public int index; + + public PageChange(LexiconPage page, LexiconEntry parent, int index) { + this.page = page; + this.parent = parent; + this.index = index; + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/core/LateMixin.java b/src/main/java/com/cleanroommc/groovyscript/core/LateMixin.java index 8bbd7d91f..8e98391a6 100644 --- a/src/main/java/com/cleanroommc/groovyscript/core/LateMixin.java +++ b/src/main/java/com/cleanroommc/groovyscript/core/LateMixin.java @@ -12,7 +12,7 @@ public class LateMixin implements ILateMixinLoader { public static final List modMixins = ImmutableList.of("jei", "mekanism", "enderio", "thermalexpansion", "draconicevolution", "ic2_classic", "ic2_exp", "bloodmagic", "astralsorcery", "tconstruct", - "tcomplement", "extendedcrafting"); + "tcomplement", "extendedcrafting", "botania"); @Override public List getMixinConfigs() { diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/botania/BotaniaAPIAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/botania/BotaniaAPIAccessor.java new file mode 100644 index 000000000..e78f7bc0c --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/botania/BotaniaAPIAccessor.java @@ -0,0 +1,21 @@ +package com.cleanroommc.groovyscript.core.mixin.botania; + +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; +import vazkii.botania.api.BotaniaAPI; + +@Mixin(value = BotaniaAPI.class, remap = false) +public interface BotaniaAPIAccessor { + + @Invoker + static String invokeGetMagnetKey(ItemStack stack) { + throw new AssertionError(); + } + + @Invoker + static String invokeGetMagnetKey(Block block, int meta) { + throw new AssertionError(); + } +} diff --git a/src/main/resources/mixin.groovyscript.botania.json b/src/main/resources/mixin.groovyscript.botania.json new file mode 100644 index 000000000..7bf574d73 --- /dev/null +++ b/src/main/resources/mixin.groovyscript.botania.json @@ -0,0 +1,10 @@ +{ + "package": "com.cleanroommc.groovyscript.core.mixin.botania", + "refmap": "mixins.groovyscript.refmap.json", + "target": "@env(DEFAULT)", + "minVersion": "0.8", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "BotaniaAPIAccessor" + ] +} \ No newline at end of file From 9e08b4d2dfbe8e2972aaa68293ed2537714f5341 Mon Sep 17 00:00:00 2001 From: Turing6 <39919441+Testure@users.noreply.github.com> Date: Mon, 15 May 2023 10:18:35 -0500 Subject: [PATCH 12/30] Update gradle.properties --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 8adfd8444..5f662f2b4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -34,4 +34,4 @@ debug_astral = false debug_blood_magic = false debug_tinkers = false debug_extended_crafting = false -debug_botania = true +debug_botania = false From c5ac25ee9c95d9cdbfc92f0aa9cc49640d02be1b Mon Sep 17 00:00:00 2001 From: Turing6 <39919441+Testure@users.noreply.github.com> Date: Mon, 15 May 2023 10:38:28 -0500 Subject: [PATCH 13/30] Allow changing entry knowledge type --- .../groovyscript/compat/mods/botania/Lexicon.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Lexicon.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Lexicon.java index 5c01cf37a..e46bed8c0 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Lexicon.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Lexicon.java @@ -210,6 +210,14 @@ public boolean removeEntry(String name) { return false; } + public void setKnowledgeType(String entry, KnowledgeType type) { + Objects.requireNonNull(Botania.getEntry(entry)).setKnowledgeType(type); + } + + public void setKnowledgeType(String entry, String type) { + setKnowledgeType(entry, BotaniaAPI.knowledgeTypes.get(type)); + } + public SimpleObjectStream streamEntries() { return new SimpleObjectStream<>(BotaniaAPI.getAllEntries()).setRemover(this::remove); } From 9627691df84333ead254d349d5a3c61b9b268178 Mon Sep 17 00:00:00 2001 From: Turing6 <39919441+Testure@users.noreply.github.com> Date: Mon, 15 May 2023 20:49:44 -0500 Subject: [PATCH 14/30] Vazkii pls --- .../botania/PageCraftingRecipeMixin.java | 86 +++++++++++++++++++ .../resources/mixin.groovyscript.botania.json | 3 +- 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/botania/PageCraftingRecipeMixin.java diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/botania/PageCraftingRecipeMixin.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/botania/PageCraftingRecipeMixin.java new file mode 100644 index 000000000..c51775e67 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/botania/PageCraftingRecipeMixin.java @@ -0,0 +1,86 @@ +package com.cleanroommc.groovyscript.core.mixin.botania; + +import com.cleanroommc.groovyscript.compat.vanilla.ShapedCraftingRecipe; +import com.cleanroommc.groovyscript.compat.vanilla.ShapelessCraftingRecipe; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.item.crafting.ShapedRecipes; +import net.minecraft.item.crafting.ShapelessRecipes; +import net.minecraftforge.common.crafting.IShapedRecipe; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import net.minecraftforge.oredict.ShapedOreRecipe; +import net.minecraftforge.oredict.ShapelessOreRecipe; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; +import vazkii.botania.api.internal.IGuiLexiconEntry; +import vazkii.botania.common.lexicon.page.PageCraftingRecipe; +import vazkii.botania.common.lexicon.page.PageRecipe; + +@Mixin(value = PageCraftingRecipe.class, remap = false) +public abstract class PageCraftingRecipeMixin extends PageRecipe { + @Shadow + boolean shapelessRecipe; + @Shadow + boolean oreDictRecipe; + @Shadow + int ticksElapsed; + + public PageCraftingRecipeMixin(String unlocalizedName) { + super(unlocalizedName); + } + + /** + * @author Turing6 + * @reason Groovyscript's recipe classes are ignored during ingredient render + */ + @SideOnly(Side.CLIENT) + @Overwrite + public void renderCraftingRecipe(IGuiLexiconEntry gui, IRecipe recipe) { + if (recipe != null) { + int x; + int y; + int index; + if (!(recipe instanceof ShapedRecipes) && !(recipe instanceof ShapedOreRecipe) && !(recipe instanceof ShapedCraftingRecipe)) { + if (recipe instanceof ShapelessRecipes || recipe instanceof ShapelessOreRecipe || recipe instanceof ShapelessCraftingRecipe) { + this.shapelessRecipe = true; + this.oreDictRecipe = recipe instanceof ShapelessOreRecipe; + + label56: + for(y = 0; y < 3; ++y) { + for(x = 0; x < 3; ++x) { + index = y * 3 + x; + if (index >= recipe.getIngredients().size()) { + break label56; + } + + Ingredient input = recipe.getIngredients().get(index); + if (input != Ingredient.EMPTY) { + ItemStack[] stacks = input.getMatchingStacks(); + this.renderItemAtGridPos(gui, 1 + x, 1 + y, stacks[this.ticksElapsed / 40 % stacks.length], true); + } + } + } + } + } else { + this.oreDictRecipe = recipe instanceof ShapedOreRecipe; + y = ((IShapedRecipe) recipe).getRecipeHeight(); + x = ((IShapedRecipe) recipe).getRecipeWidth(); + + for(index = 0; index < x; ++index) { + for(x = 0; x < y; ++x) { + Ingredient input = recipe.getIngredients().get(index * y + x); + ItemStack[] stacks = input.getMatchingStacks(); + if (stacks.length > 0) { + this.renderItemAtGridPos(gui, 1 + x, 1 + index, stacks[this.ticksElapsed / 40 % stacks.length], true); + } + } + } + } + + this.renderItemAtGridPos(gui, 2, 0, recipe.getRecipeOutput(), false); + } + } +} diff --git a/src/main/resources/mixin.groovyscript.botania.json b/src/main/resources/mixin.groovyscript.botania.json index 7bf574d73..26eca1b73 100644 --- a/src/main/resources/mixin.groovyscript.botania.json +++ b/src/main/resources/mixin.groovyscript.botania.json @@ -5,6 +5,7 @@ "minVersion": "0.8", "compatibilityLevel": "JAVA_8", "mixins": [ - "BotaniaAPIAccessor" + "BotaniaAPIAccessor", + "PageCraftingRecipeMixin" ] } \ No newline at end of file From 7c715a95da1992b2f9e4d082840393f20a5b8fc6 Mon Sep 17 00:00:00 2001 From: Turing6 <39919441+Testure@users.noreply.github.com> Date: Tue, 16 May 2023 07:12:25 -0500 Subject: [PATCH 15/30] Use string for orechid recipe --- .../compat/mods/botania/Orechid.java | 30 +++++++++---------- .../compat/mods/botania/OrechidIgnem.java | 20 ++++++------- .../mods/botania/recipe/OrechidRecipe.java | 6 ++-- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Orechid.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Orechid.java index 44e48c296..765e40359 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Orechid.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Orechid.java @@ -16,46 +16,46 @@ public class Orechid extends VirtualizedRegistry { @Override @GroovyBlacklist public void onReload() { - removeScripted().forEach(recipe -> BotaniaAPI.oreWeights.remove(recipe.output.getOreDict())); - restoreFromBackup().forEach(recipe -> BotaniaAPI.oreWeights.put(recipe.output.getOreDict(), recipe.weight)); + removeScripted().forEach(recipe -> BotaniaAPI.oreWeights.remove(recipe.output)); + restoreFromBackup().forEach(recipe -> BotaniaAPI.oreWeights.put(recipe.output, recipe.weight)); } protected List getAllRecipes() { List recipes = new ArrayList<>(BotaniaAPI.oreWeights.size()); - BotaniaAPI.oreWeights.forEach((ore, weight) -> recipes.add(new OrechidRecipe(new OreDictIngredient(ore), weight))); + BotaniaAPI.oreWeights.forEach((ore, weight) -> recipes.add(new OrechidRecipe(ore, weight))); return recipes; } - public OrechidRecipe add(OreDictIngredient output, int weight) { + public OrechidRecipe add(String output, int weight) { OrechidRecipe recipe = new OrechidRecipe(output, weight); add(recipe); return recipe; } - public OrechidRecipe add(String output, int weight) { - return add(new OreDictIngredient(output), weight); + public OrechidRecipe add(OreDictIngredient output, int weight) { + return add(output.getOreDict(), weight); } public void add(OrechidRecipe recipe) { if (recipe == null) return; addScripted(recipe); - BotaniaAPI.oreWeights.put(recipe.output.getOreDict(), recipe.weight); + BotaniaAPI.oreWeights.put(recipe.output, recipe.weight); } public boolean remove(OrechidRecipe recipe) { if (recipe == null) return false; - if (BotaniaAPI.oreWeights.containsKey(recipe.output.getOreDict())) { + if (BotaniaAPI.oreWeights.containsKey(recipe.output)) { addBackup(recipe); - BotaniaAPI.oreWeights.remove(recipe.output.getOreDict()); + BotaniaAPI.oreWeights.remove(recipe.output); return true; } return false; } - public boolean removeByOutput(OreDictIngredient output) { - if (BotaniaAPI.oreWeights.containsKey(output.getOreDict())) { - addBackup(new OrechidRecipe(output, BotaniaAPI.getOreWeight(output.getOreDict()))); - BotaniaAPI.oreWeights.remove(output.getOreDict()); + public boolean removeByOutput(String output) { + if (BotaniaAPI.oreWeights.containsKey(output)) { + addBackup(new OrechidRecipe(output, BotaniaAPI.getOreWeight(output))); + BotaniaAPI.oreWeights.remove(output); return true; } @@ -66,8 +66,8 @@ public boolean removeByOutput(OreDictIngredient output) { return false; } - public boolean removeByOutput(String output) { - return removeByOutput(new OreDictIngredient(output)); + public boolean removeByOutput(OreDictIngredient output) { + return removeByOutput(output.getOreDict()); } public void removeAll() { diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/OrechidIgnem.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/OrechidIgnem.java index 478ececa2..c5accd124 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/OrechidIgnem.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/OrechidIgnem.java @@ -14,14 +14,14 @@ public class OrechidIgnem extends Orechid { @Override @GroovyBlacklist public void onReload() { - removeScripted().forEach(recipe -> BotaniaAPI.oreWeightsNether.remove(recipe.output.getOreDict())); - restoreFromBackup().forEach(recipe -> BotaniaAPI.oreWeightsNether.put(recipe.output.getOreDict(), recipe.weight)); + removeScripted().forEach(recipe -> BotaniaAPI.oreWeightsNether.remove(recipe.output)); + restoreFromBackup().forEach(recipe -> BotaniaAPI.oreWeightsNether.put(recipe.output, recipe.weight)); } @Override protected List getAllRecipes() { List list = new ArrayList<>(BotaniaAPI.oreWeightsNether.size()); - BotaniaAPI.oreWeightsNether.forEach((ore, weight) -> list.add(new OrechidRecipe(new OreDictIngredient(ore), weight))); + BotaniaAPI.oreWeightsNether.forEach((ore, weight) -> list.add(new OrechidRecipe(ore, weight))); return list; } @@ -29,25 +29,25 @@ protected List getAllRecipes() { public void add(OrechidRecipe recipe) { if (recipe == null) return; addScripted(recipe); - BotaniaAPI.oreWeightsNether.put(recipe.output.getOreDict(), recipe.weight); + BotaniaAPI.oreWeightsNether.put(recipe.output, recipe.weight); } @Override public boolean remove(OrechidRecipe recipe) { if (recipe == null) return false; - if (BotaniaAPI.oreWeightsNether.containsKey(recipe.output.getOreDict())) { + if (BotaniaAPI.oreWeightsNether.containsKey(recipe.output)) { addBackup(recipe); - BotaniaAPI.oreWeightsNether.remove(recipe.output.getOreDict()); + BotaniaAPI.oreWeightsNether.remove(recipe.output); return true; } return false; } @Override - public boolean removeByOutput(OreDictIngredient output) { - if (BotaniaAPI.oreWeightsNether.containsKey(output.getOreDict())) { - addBackup(new OrechidRecipe(output, BotaniaAPI.getOreWeight(output.getOreDict()))); - BotaniaAPI.oreWeightsNether.remove(output.getOreDict()); + public boolean removeByOutput(String output) { + if (BotaniaAPI.oreWeightsNether.containsKey(output)) { + addBackup(new OrechidRecipe(output, BotaniaAPI.getOreWeight(output))); + BotaniaAPI.oreWeightsNether.remove(output); return true; } diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/recipe/OrechidRecipe.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/recipe/OrechidRecipe.java index 0656bf712..d3bf89482 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/recipe/OrechidRecipe.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/recipe/OrechidRecipe.java @@ -1,13 +1,11 @@ package com.cleanroommc.groovyscript.compat.mods.botania.recipe; -import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; - public class OrechidRecipe { public final int weight; - public final OreDictIngredient output; + public final String output; - public OrechidRecipe(OreDictIngredient output, int weight) { + public OrechidRecipe(String output, int weight) { this.weight = weight; this.output = output; } From 6c2d122058bd33f9db94cf486e9bb15bbc68d2be Mon Sep 17 00:00:00 2001 From: Turing6 <39919441+Testure@users.noreply.github.com> Date: Tue, 16 May 2023 07:15:29 -0500 Subject: [PATCH 16/30] Manually provide class for mini flower --- .../compat/mods/botania/Flowers.java | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Flowers.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Flowers.java index 957af53bd..5842e587d 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Flowers.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/Flowers.java @@ -12,19 +12,10 @@ public void registerFlower(String name, Class clazz) { BotaniaAPI.addSubTileToCreativeMenu(name); } - public void registerFlowerWithMini(String name, Class clazz) { + public void registerFlowerWithMini(String name, Class clazz, Class miniClazz) { registerFlower(name, clazz); - Class[] subClasses = clazz.getDeclaredClasses(); - int l = subClasses.length; - - for (int i = 0; i < l; i++) { - Class subClass = subClasses[i]; - if (subClass.getSimpleName().equals("Mini") && SubTileEntity.class.isAssignableFrom(subClass)) { - BotaniaAPI.registerMiniSubTile(name + "Chibi", (Class) subClass, name); - BotaniaAPI.registerSubTileSignature((Class) subClass, new BasicSignature(name + "Chibi")); - BotaniaAPI.addSubTileToCreativeMenu(name); - break; - } - } + BotaniaAPI.registerMiniSubTile(name + "Chibi", miniClazz, name); + BotaniaAPI.registerSubTileSignature(miniClazz, new BasicSignature(name + "Chibi")); + BotaniaAPI.addSubTileToCreativeMenu(name); } } From ac36f57b11678962d91b89d2484484714e2d722e Mon Sep 17 00:00:00 2001 From: Turing6 <39919441+Testure@users.noreply.github.com> Date: Tue, 16 May 2023 07:16:22 -0500 Subject: [PATCH 17/30] Fix crafting page crash --- .../botania/PageCraftingRecipeMixin.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/botania/PageCraftingRecipeMixin.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/botania/PageCraftingRecipeMixin.java index c51775e67..c38199264 100644 --- a/src/main/java/com/cleanroommc/groovyscript/core/mixin/botania/PageCraftingRecipeMixin.java +++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/botania/PageCraftingRecipeMixin.java @@ -7,7 +7,7 @@ import net.minecraft.item.crafting.Ingredient; import net.minecraft.item.crafting.ShapedRecipes; import net.minecraft.item.crafting.ShapelessRecipes; -import net.minecraftforge.common.crafting.IShapedRecipe; +import net.minecraftforge.fml.relauncher.ReflectionHelper; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.oredict.ShapedOreRecipe; @@ -48,12 +48,12 @@ public void renderCraftingRecipe(IGuiLexiconEntry gui, IRecipe recipe) { this.shapelessRecipe = true; this.oreDictRecipe = recipe instanceof ShapelessOreRecipe; - label56: + drawGrid: for(y = 0; y < 3; ++y) { for(x = 0; x < 3; ++x) { index = y * 3 + x; if (index >= recipe.getIngredients().size()) { - break label56; + break drawGrid; } Ingredient input = recipe.getIngredients().get(index); @@ -66,12 +66,16 @@ public void renderCraftingRecipe(IGuiLexiconEntry gui, IRecipe recipe) { } } else { this.oreDictRecipe = recipe instanceof ShapedOreRecipe; - y = ((IShapedRecipe) recipe).getRecipeHeight(); - x = ((IShapedRecipe) recipe).getRecipeWidth(); + int width = oreDictRecipe + ? ReflectionHelper.getPrivateValue(ShapedOreRecipe.class, (ShapedOreRecipe) recipe, "width") + : recipe instanceof ShapedCraftingRecipe ? ((ShapedCraftingRecipe) recipe).getRecipeWidth() : ((ShapedRecipes) recipe).getWidth(); + int height = oreDictRecipe + ? ReflectionHelper.getPrivateValue(ShapedOreRecipe.class, (ShapedOreRecipe) recipe, "height") + : recipe instanceof ShapedCraftingRecipe ? ((ShapedCraftingRecipe) recipe).getRecipeHeight() : ((ShapedRecipes) recipe).getHeight(); - for(index = 0; index < x; ++index) { - for(x = 0; x < y; ++x) { - Ingredient input = recipe.getIngredients().get(index * y + x); + for(index = 0; index < height; ++index) { + for(x = 0; x < width; ++x) { + Ingredient input = recipe.getIngredients().get(index * width + x); ItemStack[] stacks = input.getMatchingStacks(); if (stacks.length > 0) { this.renderItemAtGridPos(gui, 1 + x, 1 + index, stacks[this.ticksElapsed / 40 % stacks.length], true); From f457ced37ca631bf977bb5069352c5981f992dde Mon Sep 17 00:00:00 2001 From: Rongmario Date: Tue, 16 May 2023 15:32:52 +0100 Subject: [PATCH 18/30] getOreWeightNether for OrechidIgnem's removeByOutput --- .../groovyscript/compat/mods/botania/OrechidIgnem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/OrechidIgnem.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/OrechidIgnem.java index c5accd124..da8a4241c 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/OrechidIgnem.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/botania/OrechidIgnem.java @@ -46,7 +46,7 @@ public boolean remove(OrechidRecipe recipe) { @Override public boolean removeByOutput(String output) { if (BotaniaAPI.oreWeightsNether.containsKey(output)) { - addBackup(new OrechidRecipe(output, BotaniaAPI.getOreWeight(output))); + addBackup(new OrechidRecipe(output, BotaniaAPI.getOreWeightNether(output))); BotaniaAPI.oreWeightsNether.remove(output); return true; } From a1d52147b82dae2b1fa0460b1ae903032d462010 Mon Sep 17 00:00:00 2001 From: Rongmario Date: Wed, 17 May 2023 16:41:56 +0100 Subject: [PATCH 19/30] Stop firing AspectRegistryEvents --- .../mods/thaumcraft/aspect/AspectHelper.java | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thaumcraft/aspect/AspectHelper.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thaumcraft/aspect/AspectHelper.java index dfab7d070..663503a80 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thaumcraft/aspect/AspectHelper.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thaumcraft/aspect/AspectHelper.java @@ -14,9 +14,7 @@ import thaumcraft.api.ThaumcraftApi; import thaumcraft.api.ThaumcraftApiHelper; import thaumcraft.api.aspects.Aspect; -import thaumcraft.api.aspects.AspectEventProxy; import thaumcraft.api.aspects.AspectList; -import thaumcraft.api.aspects.AspectRegistryEvent; import thaumcraft.api.internal.CommonInternals; import java.util.ArrayList; @@ -146,9 +144,6 @@ public void add(EntityEntry entity, AspectStack aspect, boolean doBackup) { if (doBackup) addScripted(entity, aspect); - AspectRegistryEvent are = new AspectRegistryEvent(); - are.register = new AspectEventProxy(); - MinecraftForge.EVENT_BUS.post(are); return; } GroovyLog.msg("Error adding Thaumcraft Aspects from item/entity") @@ -186,9 +181,6 @@ public void add(ItemStack item, AspectStack aspect, boolean doBackup) { if (doBackup) addScripted(item, aspect); - AspectRegistryEvent are = new AspectRegistryEvent(); - are.register = new AspectEventProxy(); - MinecraftForge.EVENT_BUS.post(are); return; } GroovyLog.msg("Error adding Thaumcraft Aspects from item/entity") @@ -211,9 +203,6 @@ public void remove(EntityEntry entity, AspectStack aspect, boolean doBackup) { if (doBackup) addBackup(entity, aspect); - AspectRegistryEvent are = new AspectRegistryEvent(); - are.register = new AspectEventProxy(); - MinecraftForge.EVENT_BUS.post(are); return; } GroovyLog.msg("Error removing Thaumcraft Aspects from item/entity") @@ -251,9 +240,6 @@ public void remove(ItemStack item, AspectStack aspect, boolean doBackup) { CommonInternals.objectTags.get(CommonInternals.generateUniqueItemstackId(item)).remove(aspect.getAspect()); - AspectRegistryEvent are = new AspectRegistryEvent(); - are.register = new AspectEventProxy(); - MinecraftForge.EVENT_BUS.post(are); return; } GroovyLog.msg("Error adding Thaumcraft Aspects from item/entity") @@ -334,9 +320,6 @@ public AspectHelperBuilder stripAspects() { .error() .post(); } - AspectRegistryEvent are = new AspectRegistryEvent(); - are.register = new AspectEventProxy(); - MinecraftForge.EVENT_BUS.post(are); return this; } From 70df3bbdf828dbd9c12d300c39ad03da89acaf77 Mon Sep 17 00:00:00 2001 From: Rongmario Date: Wed, 17 May 2023 16:55:11 +0100 Subject: [PATCH 20/30] TextFormatting bracket handler --- .../groovyscript/brackets/BracketHandlerManager.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/cleanroommc/groovyscript/brackets/BracketHandlerManager.java b/src/main/java/com/cleanroommc/groovyscript/brackets/BracketHandlerManager.java index c33861bef..a18955b14 100644 --- a/src/main/java/com/cleanroommc/groovyscript/brackets/BracketHandlerManager.java +++ b/src/main/java/com/cleanroommc/groovyscript/brackets/BracketHandlerManager.java @@ -12,6 +12,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.potion.Potion; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.TextFormatting; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.common.registry.ForgeRegistries; @@ -77,6 +78,15 @@ public static void init() { } return null; }); + registerBracketHandler("textformat", s -> { + TextFormatting textformat = TextFormatting.getValueByName(s); + if (textformat == null) { + try { + textformat = TextFormatting.fromColorIndex(Integer.parseInt(s)); + } catch (NumberFormatException ignored) { } + } + return textformat; + }); } public static FluidStack parseFluidStack(String s) { From b318574f431d05b378c111c4ce4b5fc7f3bd6cc1 Mon Sep 17 00:00:00 2001 From: Rongmario Date: Wed, 17 May 2023 17:59:00 +0100 Subject: [PATCH 21/30] Item rarities --- .../groovyscript/compat/vanilla/Rarity.java | 93 +++++++++++++++++++ .../compat/vanilla/VanillaModule.java | 2 + .../groovyscript/core/mixin/ItemMixin.java | 21 +++++ src/main/resources/mixin.groovyscript.json | 1 + 4 files changed, 117 insertions(+) create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/vanilla/Rarity.java create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/ItemMixin.java diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/Rarity.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/Rarity.java new file mode 100644 index 000000000..01b651315 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/Rarity.java @@ -0,0 +1,93 @@ +package com.cleanroommc.groovyscript.compat.vanilla; + +import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.common.IRarity; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; + +public class Rarity { + + private final List> rarities = new ArrayList<>(); + + public Rarity() { + super(); + } + + public IRarity check(ItemStack testStack) { + for (Pair pair : this.rarities) { + if (((Predicate) (Object) pair.getKey()).test(testStack)) { + return pair.getValue(); + } + } + return testStack.getItem().getRarity(testStack); + } + + public void set(TextFormatting color, ItemStack stack) { + set(color, getAppropriateRarityName(color), stack); + } + + public void set(TextFormatting color, String rarityName, ItemStack stack) { + set(new RarityImpl(color, rarityName), stack); + } + + public void set(IRarity rarity, ItemStack stack) { + if (GroovyLog.msg("Error setting Item Rarity") + .add(rarity == null, () -> "Rarity must not be null") + .add(IngredientHelper.isEmpty(stack), () -> "Stack must not be null") + .error() + .postIfNotEmpty()) { + return; + } + rarities.add(Pair.of(stack, rarity)); + } + + @GroovyBlacklist + public void onReload() { + this.rarities.clear(); + } + + private String getAppropriateRarityName(TextFormatting formatting) { + switch (formatting) { + case WHITE: + return EnumRarity.COMMON.rarityName; + case YELLOW: + return EnumRarity.UNCOMMON.rarityName; + case AQUA: + return EnumRarity.RARE.rarityName; + case LIGHT_PURPLE: + return EnumRarity.EPIC.rarityName; + } + return StringUtils.capitalize(formatting.getFriendlyName()); + } + + private static class RarityImpl implements IRarity { + + private final TextFormatting color; + private final String name; + + private RarityImpl(TextFormatting color, String name) { + this.color = color; + this.name = name; + } + + @Override + public TextFormatting getColor() { + return color; + } + + @Override + public String getName() { + return name; + } + } + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/VanillaModule.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/VanillaModule.java index d802e75a6..cd5ab97a3 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/VanillaModule.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/VanillaModule.java @@ -10,6 +10,7 @@ public class VanillaModule { public static final OreDict oreDict = new OreDict(); public static final Player player = new Player(); public static final Content content = new Content(); + public static final Rarity rarity = new Rarity(); public static void initializeBinding() { GroovyScript.getSandbox().registerBinding("Crafting", crafting); @@ -18,5 +19,6 @@ public static void initializeBinding() { GroovyScript.getSandbox().registerBinding("OreDictionary", oreDict); GroovyScript.getSandbox().registerBinding("Player", player); GroovyScript.getSandbox().registerBinding("Content", content); + GroovyScript.getSandbox().registerBinding("Rarity", rarity); } } diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/ItemMixin.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/ItemMixin.java new file mode 100644 index 000000000..b6af180a1 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/ItemMixin.java @@ -0,0 +1,21 @@ +package com.cleanroommc.groovyscript.core.mixin; + +import com.cleanroommc.groovyscript.compat.vanilla.VanillaModule; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.IRarity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +// Forge is stupid (again) +@Mixin(Item.class) +public class ItemMixin { + + @Inject(method = "getForgeRarity", at = @At("HEAD"), cancellable = true, remap = false) + private void prioritzeGSRarities(ItemStack stack, CallbackInfoReturnable cir) { + cir.setReturnValue(VanillaModule.rarity.check(stack)); + } + +} diff --git a/src/main/resources/mixin.groovyscript.json b/src/main/resources/mixin.groovyscript.json index ab203beae..dfd1e8782 100644 --- a/src/main/resources/mixin.groovyscript.json +++ b/src/main/resources/mixin.groovyscript.json @@ -11,6 +11,7 @@ "ForgeRegistryMixin", "FurnaceRecipeMixin", "InventoryCraftingAccess", + "ItemMixin", "ItemStackMixin", "Java8Mixin", "LoaderControllerMixin", From 3a913192f8fb7cf485a56f75746b9edc554727f3 Mon Sep 17 00:00:00 2001 From: Waiting Idly <25394029+WaitingIdly@users.noreply.github.com> Date: Wed, 17 May 2023 11:15:30 -0700 Subject: [PATCH 22/30] remap false --- .../groovyscript/core/mixin/roots/ModifierAccessor.java | 2 +- .../groovyscript/core/mixin/roots/ModifierRegistryAccessor.java | 2 +- .../groovyscript/core/mixin/roots/MossConfigAccessor.java | 2 +- .../groovyscript/core/mixin/roots/PacifistEntryAccessor.java | 2 +- .../groovyscript/core/mixin/roots/RitualBaseAccessor.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModifierAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModifierAccessor.java index e3d164bc8..66c28ab49 100644 --- a/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModifierAccessor.java +++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModifierAccessor.java @@ -8,7 +8,7 @@ import java.util.Map; -@Mixin(Modifier.class) +@Mixin(value = Modifier.class, remap = false) public interface ModifierAccessor { @Accessor diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModifierRegistryAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModifierRegistryAccessor.java index 9d7393a9e..3506867ed 100644 --- a/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModifierRegistryAccessor.java +++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/ModifierRegistryAccessor.java @@ -7,7 +7,7 @@ import java.util.Set; -@Mixin(ModifierRegistry.class) +@Mixin(value = ModifierRegistry.class, remap = false) public interface ModifierRegistryAccessor { @Accessor diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/MossConfigAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/MossConfigAccessor.java index ca5000f7e..2cac3f1da 100644 --- a/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/MossConfigAccessor.java +++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/MossConfigAccessor.java @@ -10,7 +10,7 @@ import java.util.Map; -@Mixin(MossConfig.class) +@Mixin(value = MossConfig.class, remap = false) public interface MossConfigAccessor { @Accessor diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/PacifistEntryAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/PacifistEntryAccessor.java index 8d69bffe3..c9da5c4bf 100644 --- a/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/PacifistEntryAccessor.java +++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/PacifistEntryAccessor.java @@ -5,7 +5,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(PacifistEntry.class) +@Mixin(value = PacifistEntry.class, remap = false) public interface PacifistEntryAccessor { @Accessor diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/RitualBaseAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/RitualBaseAccessor.java index 530a72fd4..577628357 100644 --- a/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/RitualBaseAccessor.java +++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/roots/RitualBaseAccessor.java @@ -4,7 +4,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(RitualBase.class) +@Mixin(value = RitualBase.class, remap = false) public interface RitualBaseAccessor { @Accessor("disabled") From 88e2f45fcc375e503f5f8ce2d090e7577e537282 Mon Sep 17 00:00:00 2001 From: Rongmario Date: Thu, 18 May 2023 12:44:37 +0100 Subject: [PATCH 23/30] Allow closures for setting item rarities --- .../groovyscript/compat/vanilla/Rarity.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/Rarity.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/Rarity.java index 01b651315..2db1e3f19 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/Rarity.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/Rarity.java @@ -2,7 +2,9 @@ import com.cleanroommc.groovyscript.api.GroovyBlacklist; import com.cleanroommc.groovyscript.api.GroovyLog; -import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper; +import com.cleanroommc.groovyscript.sandbox.ClosureHelper; +import com.cleanroommc.groovyscript.sandbox.expand.LambdaClosure; +import groovy.lang.Closure; import net.minecraft.item.EnumRarity; import net.minecraft.item.ItemStack; import net.minecraft.util.text.TextFormatting; @@ -16,15 +18,15 @@ public class Rarity { - private final List> rarities = new ArrayList<>(); + private final List, IRarity>> rarities = new ArrayList<>(); public Rarity() { super(); } public IRarity check(ItemStack testStack) { - for (Pair pair : this.rarities) { - if (((Predicate) (Object) pair.getKey()).test(testStack)) { + for (Pair, IRarity> pair : this.rarities) { + if (ClosureHelper.call(false, pair.getKey(), testStack)) { return pair.getValue(); } } @@ -40,14 +42,26 @@ public void set(TextFormatting color, String rarityName, ItemStack stack) { } public void set(IRarity rarity, ItemStack stack) { + set(rarity, new LambdaClosure<>(this, arr -> ((Predicate) (Object) stack).test((ItemStack) arr[0]))); + } + + public void set(TextFormatting color, Closure predicate) { + set(color, getAppropriateRarityName(color), predicate); + } + + public void set(TextFormatting color, String rarityName, Closure predicate) { + set(new RarityImpl(color, rarityName), predicate); + } + + public void set(IRarity rarity, Closure predicate) { if (GroovyLog.msg("Error setting Item Rarity") .add(rarity == null, () -> "Rarity must not be null") - .add(IngredientHelper.isEmpty(stack), () -> "Stack must not be null") + .add(predicate == null, () -> "Predicate must not be null") .error() .postIfNotEmpty()) { return; } - rarities.add(Pair.of(stack, rarity)); + rarities.add(Pair.of(predicate, rarity)); } @GroovyBlacklist From 7a4d0966a3951dcb0bb3910c462a4b2c4ba90495 Mon Sep 17 00:00:00 2001 From: Rongmario Date: Thu, 18 May 2023 13:04:30 +0100 Subject: [PATCH 24/30] It ain't clean, but it still is cleaner than before --- .../groovyscript/api/IScriptReloadable.java | 15 +++++++++++++++ .../compat/vanilla/VanillaModule.java | 19 ++++++++++++++++++- .../registry/ReloadableRegistryManager.java | 5 ++--- .../registry/VirtualizedRegistry.java | 3 ++- 4 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/cleanroommc/groovyscript/api/IScriptReloadable.java diff --git a/src/main/java/com/cleanroommc/groovyscript/api/IScriptReloadable.java b/src/main/java/com/cleanroommc/groovyscript/api/IScriptReloadable.java new file mode 100644 index 000000000..8728b03e1 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/api/IScriptReloadable.java @@ -0,0 +1,15 @@ +package com.cleanroommc.groovyscript.api; + +import org.jetbrains.annotations.ApiStatus; + +public interface IScriptReloadable { + + @GroovyBlacklist + @ApiStatus.OverrideOnly + void onReload(); + + @GroovyBlacklist + @ApiStatus.OverrideOnly + void afterScriptLoad(); + +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/VanillaModule.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/VanillaModule.java index cd5ab97a3..660890139 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/VanillaModule.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/VanillaModule.java @@ -1,9 +1,11 @@ package com.cleanroommc.groovyscript.compat.vanilla; import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.cleanroommc.groovyscript.api.IScriptReloadable; import com.cleanroommc.groovyscript.compat.content.Content; -public class VanillaModule { +public class VanillaModule implements IScriptReloadable { public static final Crafting crafting = new Crafting(); public static final Furnace furnace = new Furnace(); @@ -21,4 +23,19 @@ public static void initializeBinding() { GroovyScript.getSandbox().registerBinding("Content", content); GroovyScript.getSandbox().registerBinding("Rarity", rarity); } + + @Override + @GroovyBlacklist + public void onReload() { + furnace.onReload(); + oreDict.onReload(); + rarity.onReload(); + } + + @Override + @GroovyBlacklist + public void afterScriptLoad() { + furnace.afterScriptLoad(); + } + } diff --git a/src/main/java/com/cleanroommc/groovyscript/registry/ReloadableRegistryManager.java b/src/main/java/com/cleanroommc/groovyscript/registry/ReloadableRegistryManager.java index 7a036d4bd..8ff1c7a94 100644 --- a/src/main/java/com/cleanroommc/groovyscript/registry/ReloadableRegistryManager.java +++ b/src/main/java/com/cleanroommc/groovyscript/registry/ReloadableRegistryManager.java @@ -74,8 +74,7 @@ public static void init() { public static void onReload() { GroovyScript.reloadRunConfig(); reloadForgeRegistries(); - VanillaModule.furnace.onReload(); - VanillaModule.oreDict.onReload(); + new VanillaModule().onReload(); ModSupport.getAllContainers().stream() .filter(Container::isLoaded) .map(Container::get) @@ -93,7 +92,7 @@ public static void afterScriptRun() { .map(ModPropertyContainer::getRegistries) .flatMap(Collection::stream) .forEach(VirtualizedRegistry::afterScriptLoad); - VanillaModule.furnace.afterScriptLoad(); + new VanillaModule().afterScriptLoad(); unfreezeForgeRegistries(); } diff --git a/src/main/java/com/cleanroommc/groovyscript/registry/VirtualizedRegistry.java b/src/main/java/com/cleanroommc/groovyscript/registry/VirtualizedRegistry.java index 8cffdbf03..a69b517f8 100644 --- a/src/main/java/com/cleanroommc/groovyscript/registry/VirtualizedRegistry.java +++ b/src/main/java/com/cleanroommc/groovyscript/registry/VirtualizedRegistry.java @@ -1,12 +1,13 @@ package com.cleanroommc.groovyscript.registry; import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.cleanroommc.groovyscript.api.IScriptReloadable; import com.google.common.base.CaseFormat; import org.jetbrains.annotations.ApiStatus; import java.util.*; -public abstract class VirtualizedRegistry { +public abstract class VirtualizedRegistry implements IScriptReloadable { protected final List aliases; From c649694aaca81f22b276b87a972e7d3e6661a9e9 Mon Sep 17 00:00:00 2001 From: Rongmario Date: Thu, 18 May 2023 13:41:14 +0100 Subject: [PATCH 25/30] Allow player starting items to be reloadable --- .../groovyscript/compat/vanilla/Player.java | 59 ++++++++++++++++--- .../compat/vanilla/VanillaModule.java | 1 + .../groovyscript/event/EventHandler.java | 5 +- 3 files changed, 54 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/Player.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/Player.java index ac1b6b987..fa0e4587c 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/Player.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/Player.java @@ -1,26 +1,67 @@ package com.cleanroommc.groovyscript.compat.vanilla; +import com.cleanroommc.groovyscript.api.GroovyBlacklist; import com.cleanroommc.groovyscript.api.GroovyLog; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import com.cleanroommc.groovyscript.api.IScriptReloadable; +import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.item.ItemStack; -import java.util.Map; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; -public class Player { +public class Player implements IScriptReloadable { public static final String GIVEN_ITEMS = "GroovyScript:GivenItems"; - public static final Map ITEM_MAP = new Object2IntOpenHashMap<>(); + + public boolean testingStartingItems = false; + + private final List givenItemsAnySlot = new ArrayList<>(); + + private ItemStack[] givenItemsSlots = new ItemStack[36]; + + @GroovyBlacklist + public void addToInventory(InventoryPlayer playerInv) { + for (int i = 0; i < givenItemsSlots.length; i++) { + ItemStack stack = givenItemsSlots[i]; + if (stack != null && !stack.isEmpty()) { + playerInv.add(i, stack); + } + } + givenItemsAnySlot.forEach(playerInv::addItemStackToInventory); + } public void addStartingItem(ItemStack item) { this.addStartingItem(item, -1); } public void addStartingItem(ItemStack item, int slot) { - if (ITEM_MAP.size() > 36) - GroovyLog.msg("Warning: adding more than 36 items to a player's inventory may cause some items to not be received by the player.").warn().post(); - if (slot > 36) - GroovyLog.msg("Warning: assigning items to a player's inventory slot greater than 36 may cause some items to not be received by the player.").warn().post(); - ITEM_MAP.put(item, slot); + if (slot >= 36) { + GroovyLog.msg("Warning: assigning items to a player's inventory slot greater than 36 may cause some items to not be received by the player.") + .warn().post(); + } + if (slot <= -1) { + this.givenItemsAnySlot.add(item); + } else { + if (slot >= givenItemsSlots.length) { + ItemStack[] oldGivenItemsSlots = givenItemsSlots; + givenItemsSlots = Arrays.copyOf(oldGivenItemsSlots, slot + 1); + } + if (givenItemsSlots[slot] != null) { + GroovyLog.msg("Error: slot {} has already been occupied by another item.", slot) + .error().post(); + } + } } + @Override + public void onReload() { + this.givenItemsAnySlot.clear(); + this.givenItemsSlots = new ItemStack[36]; + } + + @Override + public void afterScriptLoad() { + + } } diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/VanillaModule.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/VanillaModule.java index 660890139..5f04ab4a2 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/VanillaModule.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/VanillaModule.java @@ -30,6 +30,7 @@ public void onReload() { furnace.onReload(); oreDict.onReload(); rarity.onReload(); + player.onReload(); } @Override diff --git a/src/main/java/com/cleanroommc/groovyscript/event/EventHandler.java b/src/main/java/com/cleanroommc/groovyscript/event/EventHandler.java index 08f3c8a83..5724df35b 100644 --- a/src/main/java/com/cleanroommc/groovyscript/event/EventHandler.java +++ b/src/main/java/com/cleanroommc/groovyscript/event/EventHandler.java @@ -7,6 +7,7 @@ import com.cleanroommc.groovyscript.compat.vanilla.CraftingInfo; import com.cleanroommc.groovyscript.compat.vanilla.ICraftingRecipe; import com.cleanroommc.groovyscript.compat.vanilla.Player; +import com.cleanroommc.groovyscript.compat.vanilla.VanillaModule; import com.cleanroommc.groovyscript.core.mixin.InventoryCraftingAccess; import com.cleanroommc.groovyscript.core.mixin.SlotCraftingAccess; import com.cleanroommc.groovyscript.sandbox.ClosureHelper; @@ -55,8 +56,8 @@ public static void playerLogin(PlayerEvent.PlayerLoggedInEvent event) { if (tag.hasKey(EntityPlayer.PERSISTED_NBT_TAG)) { data = tag.getCompoundTag(EntityPlayer.PERSISTED_NBT_TAG); } - if (!data.getBoolean(Player.GIVEN_ITEMS)) { - Player.ITEM_MAP.forEach((stack, slot) -> event.player.inventory.add(slot, stack.copy())); + if (VanillaModule.player.testingStartingItems || !data.getBoolean(Player.GIVEN_ITEMS)) { + VanillaModule.player.addToInventory(event.player.inventory); data.setBoolean(Player.GIVEN_ITEMS, true); tag.setTag(EntityPlayer.PERSISTED_NBT_TAG, data); } From f9c5ac700364f41db7caab8dbcfac32e3415a4d0 Mon Sep 17 00:00:00 2001 From: Rongmario Date: Thu, 18 May 2023 13:43:03 +0100 Subject: [PATCH 26/30] Copy stacks --- .../com/cleanroommc/groovyscript/compat/vanilla/Player.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/Player.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/Player.java index fa0e4587c..18312ce9f 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/Player.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/Player.java @@ -25,10 +25,10 @@ public void addToInventory(InventoryPlayer playerInv) { for (int i = 0; i < givenItemsSlots.length; i++) { ItemStack stack = givenItemsSlots[i]; if (stack != null && !stack.isEmpty()) { - playerInv.add(i, stack); + playerInv.add(i, stack.copy()); } } - givenItemsAnySlot.forEach(playerInv::addItemStackToInventory); + givenItemsAnySlot.stream().map(ItemStack::copy).forEach(playerInv::addItemStackToInventory); } public void addStartingItem(ItemStack item) { From aff91831aa33cfbfa79b9ee2d75e8a7c3f47a6ff Mon Sep 17 00:00:00 2001 From: Rongmario Date: Sun, 14 May 2023 13:27:35 +0100 Subject: [PATCH 27/30] Migrate to RFG --- build.gradle | 369 +++++++++++------------ gradle.properties | 7 - gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 24 ++ 4 files changed, 206 insertions(+), 196 deletions(-) create mode 100644 settings.gradle diff --git a/build.gradle b/build.gradle index c200f7f8d..009fa58a6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,229 +1,217 @@ -buildscript { - repositories { - maven { - name = "forge" - url = "https://maven.minecraftforge.net/" - } - maven { - url = 'https://maven.cleanroommc.com/' - } - maven { - url = 'https://repo.spongepowered.org/maven/' - } - } - dependencies { - classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT' - if (project.use_mixins.toBoolean()) { - classpath 'org.spongepowered:mixingradle:0.6-SNAPSHOT' - } - } -} +import com.gtnewhorizons.retrofuturagradle.mcp.ReobfuscatedJar +import org.jetbrains.gradle.ext.Gradle plugins { - id 'com.github.johnrengelman.shadow' version '4.0.4' -} - -apply plugin: 'net.minecraftforge.gradle.forge' -apply plugin: 'com.github.johnrengelman.shadow' - -if (project.use_mixins.toBoolean()) { - apply plugin: 'org.spongepowered.mixin' + id 'java' + id 'java-library' + id 'maven-publish' + id 'org.jetbrains.gradle.plugin.idea-ext' version '1.1.7' + id 'eclipse' + id 'com.gtnewhorizons.retrofuturagradle' version '1.3.9' + id 'com.matthewprenger.cursegradle' version '1.4.0' } version = project.mod_version group = project.maven_group archivesBaseName = project.archives_base_name -sourceCompatibility = targetCompatibility = '1.8' +// Set the toolchain version to decouple the Java we run Gradle with from the Java used to compile and run the mod +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(8)) + // Azul covers the most platforms for Java 8 toolchains, crucially including MacOS arm64 + vendor.set(org.gradle.jvm.toolchain.JvmVendorSpec.AZUL) + } + // Generate sources and javadocs jars when building and publishing + withSourcesJar() + withJavadocJar() +} -compileJava { - sourceCompatibility = targetCompatibility = '1.8' +tasks.withType(JavaCompile).configureEach { + options.encoding = "UTF-8" +} + +configurations { + embed + implementation.extendsFrom(embed) } minecraft { - version = '1.12.2-14.23.5.2847' - runDir = 'run' - mappings = 'stable_39' - def args = [] - if (project.use_coremod.toBoolean()) { - args << '-Dfml.coreMods.load=' + coremod_plugin_class_name - } - if (project.use_mixins.toBoolean()) { - args << '-Dmixin.hotSwap=true' - args << '-Dmixin.checks.interfaces=true' - args << '-Dmixin.debug.export=true' - } - clientJvmArgs.addAll(args) - serverJvmArgs.addAll(args) + mcVersion = '1.12.2' + def args = ["-ea:${project.group}"] + args << '-Dfml.coreMods.load=' + coremod_plugin_class_name + args << '-Dmixin.hotSwap=true' + args << '-Dmixin.checks.interfaces=true' + args << '-Dmixin.debug.export=true' + extraRunJvmArguments.addAll(args) + + useDependencyAccessTransformers = true + + injectedTags.put("VERSION", project.version) +} - replaceIn("src/main/java/${project.mod_ref_path.replace('.', '/')}.java") - replace("@VERSION@", project.mod_version) - replace("@MODID@", project.archivesBaseName) - replace("@GROOVY_VERSION@", project.groovy_version) +// Generate a my.project.Tags class with the version number as a field +tasks.injectTags.configure { + outputClassName.set("${project.group}.Tags") } repositories { maven { - url = 'https://maven.cleanroommc.com/' + url = 'https://maven.cleanroommc.com' } maven { - url = 'https://repo.spongepowered.org/maven/' + url = 'https://repo.spongepowered.org/maven' } maven { - url = "https://mvnrepository.com/artifact/org.apache.groovy/groovy" + url 'https://cursemaven.com' + content { + includeGroup "curse.maven" + } } maven { - url 'https://dvs1.progwml6.com/files/maven/' + url = 'https://mvnrepository.com/artifact/org.apache.groovy/groovy' } maven { - name = "CurseForge" - url = 'https://www.cursemaven.com/' + url 'https://dvs1.progwml6.com/files/maven/' } maven { - url "http://maven.tterrag.com/" + url 'http://maven.tterrag.com/' + allowInsecureProtocol = true } + mavenLocal() // Must be last for caching to work } dependencies { - if (project.use_mixins.toBoolean()) { - deobfCompile 'zone.rong:mixinbooter:4.2' + implementation 'zone.rong:mixinbooter:7.1' + + api ('org.spongepowered:mixin:0.8.3') { + transitive = false + } + annotationProcessor 'org.ow2.asm:asm-debug-all:5.2' + annotationProcessor 'com.google.guava:guava:24.1.1-jre' + annotationProcessor 'com.google.code.gson:gson:2.8.6' + annotationProcessor ('org.spongepowered:mixin:0.8.3') { + transitive = false } compileOnly 'org.jetbrains:annotations:23.0.0' - implementation "org.apache.groovy:groovy:${project.groovy_version}" - shadow "org.apache.groovy:groovy:${project.groovy_version}" + embed "org.apache.groovy:groovy:${project.groovy_version}" - compile 'mezz.jei:jei_1.12.2:4.16.1.302' + implementation 'mezz.jei:jei_1.12.2:4.16.1.302' + compileOnly rfg.deobf('curse.maven:mekanism-268560:2835175') if (project.debug_mekanism.toBoolean()) { - deobfCompile 'curse.maven:mekanism-268560:2835175' - } else { - deobfProvided 'curse.maven:mekanism-268560:2835175' + runtimeOnly rfg.deobf('curse.maven:mekanism-268560:2835175') } + compileOnly rfg.deobf('curse.maven:redstone_flux-270789:2920436') if (project.debug_thermal.toBoolean() || project.debug_de.toBoolean()) { - deobfCompile 'curse.maven:redstone_flux-270789:2920436' - } else { - deobfProvided 'curse.maven:redstone_flux-270789:2920436' + runtimeOnly rfg.deobf('curse.maven:redstone_flux-270789:2920436') } + compileOnly rfg.deobf('curse.maven:guide-api-228832:2645992') + compileOnly rfg.deobf('curse.maven:blood-magic-224791:2822288') if (project.debug_blood_magic.toBoolean()) { - deobfCompile 'curse.maven:guide-api-228832:2645992' - deobfCompile 'curse.maven:blood-magic-224791:2822288' - } else { - deobfProvided 'curse.maven:guide-api-228832:2645992' - deobfProvided 'curse.maven:blood-magic-224791:2822288' - } - - if (project.debug_roots.toBoolean()) { - deobfCompile 'curse.maven:patchouli-306770:3162874' - deobfCompile 'curse.maven:mystical_lib-277064:3483816' - deobfCompile 'curse.maven:mystical_world-282940:3460961' - deobfCompile 'curse.maven:roots-246183:3905074' - } else { - deobfProvided 'curse.maven:patchouli-306770:3162874' - deobfProvided 'curse.maven:mystical_lib-277064:3483816' - deobfProvided 'curse.maven:mystical_world-282940:3460961' - deobfProvided 'curse.maven:roots-246183:3905074' + runtimeOnly rfg.deobf('curse.maven:guide-api-228832:2645992') + runtimeOnly rfg.deobf('curse.maven:blood-magic-224791:2822288') } + compileOnly rfg.deobf('curse.maven:cucumber-272335:2645867') + compileOnly rfg.deobf('curse.maven:extended-crafting-nomifactory-edition-398267:3613140') if (project.debug_extended_crafting.toBoolean()) { - deobfCompile 'curse.maven:cucumber-272335:2645867' - deobfCompile 'curse.maven:extended-crafting-nomifactory-edition-398267:3613140' - } else { - deobfProvided 'curse.maven:cucumber-272335:2645867' - deobfProvided 'curse.maven:extended-crafting-nomifactory-edition-398267:3613140' + runtimeOnly rfg.deobf('curse.maven:cucumber-272335:2645867') + runtimeOnly rfg.deobf('curse.maven:extended-crafting-nomifactory-edition-398267:3613140') } + compileOnly rfg.deobf('curse.maven:cofh_core-69162:2920433') + compileOnly rfg.deobf('curse.maven:cofh_world-271384:2920434') + compileOnly rfg.deobf('curse.maven:thermal_expansion-69163:2926431') + compileOnly rfg.deobf('curse.maven:thermal_foundation-222880:2926428') if (project.debug_thermal.toBoolean()) { - deobfCompile 'curse.maven:cofh_core-69162:2920433' - deobfCompile 'curse.maven:cofh_world-271384:2920434' - deobfCompile 'curse.maven:thermal_expansion-69163:2926431' - deobfCompile 'curse.maven:thermal_foundation-222880:2926428' - } else { - deobfProvided 'curse.maven:cofh_core-69162:2920433' - deobfProvided 'curse.maven:cofh_world-271384:2920434' - deobfProvided 'curse.maven:thermal_expansion-69163:2926431' - deobfProvided 'curse.maven:thermal_foundation-222880:2926428' + runtimeOnly rfg.deobf('curse.maven:cofh_core-69162:2920433') + runtimeOnly rfg.deobf('curse.maven:cofh_world-271384:2920434') + runtimeOnly rfg.deobf('curse.maven:thermal_expansion-69163:2926431') + runtimeOnly rfg.deobf('curse.maven:thermal_foundation-222880:2926428') } + compileOnly rfg.deobf('curse.maven:codechicken_lib_1_8-242818:2779848') + compileOnly rfg.deobf('curse.maven:draconic_evolution-223565:3431261') + compileOnly rfg.deobf('curse.maven:brandons_core-231382:3408276') if (project.debug_de.toBoolean()) { - deobfCompile 'curse.maven:codechicken_lib_1_8-242818:2779848' - deobfCompile 'curse.maven:draconic_evolution-223565:3431261' - deobfCompile 'curse.maven:brandons_core-231382:3408276' - } else { - deobfProvided 'curse.maven:codechicken_lib_1_8-242818:2779848' - deobfProvided 'curse.maven:draconic_evolution-223565:3431261' - deobfProvided 'curse.maven:brandons_core-231382:3408276' - } - - if (project.debug_enderio.toBoolean()) { - deobfProvided "com.enderio.core:EnderCore:1.12.2-+" - deobfCompile("com.enderio:EnderIO:1.12.2-+") { - transitive = false - } - } else { - deobfProvided "com.enderio.core:EnderCore:1.12.2-+" - deobfProvided("com.enderio:EnderIO:1.12.2-+") { - transitive = false - } + runtimeOnly rfg.deobf('curse.maven:codechicken_lib_1_8-242818:2779848') + runtimeOnly rfg.deobf('curse.maven:draconic_evolution-223565:3431261') + runtimeOnly rfg.deobf('curse.maven:brandons_core-231382:3408276') } + compileOnly rfg.deobf('curse.maven:industrialcraft_experimental-242638:3838713') + compileOnly rfg.deobf('curse.maven:industrialcraft_classic-242942:3093607') if (project.debug_ic2.toBoolean()) { - deobfCompile 'curse.maven:industrialcraft_experimental-242638:3838713' - deobfProvided 'curse.maven:industrialcraft_classic-242942:3093607' - } else { - deobfProvided 'curse.maven:industrialcraft_experimental-242638:3838713' - deobfProvided 'curse.maven:industrialcraft_classic-242942:3093607' + runtimeOnly rfg.deobf('curse.maven:industrialcraft_experimental-242638:3838713') + runtimeOnly rfg.deobf('curse.maven:industrialcraft_classic-242942:3093607') } - if (project.debug_astral.toBoolean() || project.debug_thaum.toBoolean() || project.debug_botania.toBoolean()) { - runtime 'curse.maven:baubles-227083:2518667' + compileOnly rfg.deobf('curse.maven:baubles-227083:2518667') + compileOnly rfg.deobf('curse.maven:thaumcraft-223628:2629023') + if (project.debug_thaum.toBoolean()) { + runtimeOnly rfg.deobf('curse.maven:baubles-227083:2518667') + runtimeOnly rfg.deobf('curse.maven:thaumcraft-223628:2629023') } + runtimeOnly 'curse.maven:thaumic_jei-285492:2705304' + compileOnly rfg.deobf('curse.maven:astralsorcery-sorcery-241721:3044416') if (project.debug_astral.toBoolean()) { - deobfCompile 'curse.maven:astralsorcery-sorcery-241721:3044416' - } else { - deobfProvided 'curse.maven:astralsorcery-sorcery-241721:3044416' - } - - if (project.debug_thaum.toBoolean()) { - deobfCompile 'curse.maven:thaumcraft-223628:2629023' - runtime 'curse.maven:thaumic_jei-285492:2705304' - } else { - deobfProvided 'curse.maven:thaumcraft-223628:2629023' + runtimeOnly rfg.deobf('curse.maven:astralsorcery-sorcery-241721:3044416') } + compileOnly rfg.deobf('curse.maven:immersive_engineering-231951:2974106') if (project.debug_ie.toBoolean()) { - deobfCompile 'curse.maven:immersive_engineering-231951:2974106' - } else { - deobfProvided 'curse.maven:immersive_engineering-231951:2974106' + runtimeOnly rfg.deobf('curse.maven:immersive_engineering-231951:2974106') } + compileOnly 'slimeknights.mantle:Mantle:1.12-1.3.3.55' + compileOnly 'slimeknights:TConstruct:1.12.2-2.13.0.190' + compileOnly rfg.deobf('curse.maven:constructs-armory-287683:3174535') + compileOnly rfg.deobf('curse.maven:tinkers-complement-272671:2843439') if (project.debug_tinkers.toBoolean()) { - deobfCompile 'slimeknights.mantle:Mantle:1.12-1.3.3.55' - deobfCompile 'slimeknights:TConstruct:1.12.2-2.13.0.190' - deobfCompile 'curse.maven:constructs-armory-287683:3174535' - deobfCompile 'curse.maven:tinkers-complement-272671:2843439' - } else { - deobfProvided 'slimeknights.mantle:Mantle:1.12-1.3.3.55' - deobfProvided 'slimeknights:TConstruct:1.12.2-2.13.0.190' - deobfProvided 'curse.maven:constructs-armory-287683:3174535' - deobfProvided 'curse.maven:tinkers-complement-272671:2843439' + runtimeOnly 'slimeknights.mantle:Mantle:1.12-1.3.3.55' + runtimeOnly 'slimeknights:TConstruct:1.12.2-2.13.0.190' + runtimeOnly rfg.deobf('curse.maven:constructs-armory-287683:3174535') + runtimeOnly rfg.deobf('curse.maven:tinkers-complement-272671:2843439') } - if (project.debug_botania.toBoolean()) { - deobfCompile 'curse.maven:botania-225643:3330934' - } else { - deobfProvided 'curse.maven:botania-225643:3330934' + compileOnly 'com.enderio.core:EnderCore:1.12.2-+' + compileOnly ('com.enderio:EnderIO:1.12.2-+') { + transitive = false } + if (project.debug_enderio.toBoolean()) { + runtimeOnly 'com.enderio.core:EnderCore:1.12.2-+' + runtimeOnly ('com.enderio:EnderIO:1.12.2-+') { + transitive = false + } + } + + +} + +def mixinConfigRefMap = 'mixins.' + project.archives_base_name + '.refmap.json' +def mixinTmpDir = buildDir.path + File.separator + 'tmp' + File.separator + 'mixins' +def refMap = "${mixinTmpDir}" + File.separator + mixinConfigRefMap +def mixinSrg = "${mixinTmpDir}" + File.separator + "mixins.srg" + +tasks.named("reobfJar", ReobfuscatedJar).configure { + extraSrgFiles.from(mixinSrg) } -sourceSets { - main { - ext.refMap = 'mixins.' + archives_base_name + '.refmap.json' +tasks.named("compileJava", JavaCompile).configure { + doFirst { + new File(mixinTmpDir).mkdirs() } + options.compilerArgs += [ + "-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}", + "-AoutSrgFile=${mixinSrg}", + "-AoutRefMapFile=${refMap}", + ] } processResources { @@ -231,52 +219,57 @@ processResources { inputs.property 'version', project.version inputs.property 'mcversion', project.minecraft.version // replace stuff in mcmod.info, nothing else - from(sourceSets.main.resources.srcDirs) { - include 'mcmod.info' + filesMatching(['mcmod.info', 'pack.mcmeta']) { fcd -> // replace version and mcversion - expand 'version': project.version, 'mcversion': project.minecraft.version - } - // copy everything else except the mcmod.info - from(sourceSets.main.resources.srcDirs) { - exclude 'mcmod.info' + fcd.expand ( + 'version': project.version, + 'mcversion': project.minecraft.version + ) } - rename '(.+_at.cfg)', 'META-INF/$1' // Access Transformers + from refMap + dependsOn 'compileJava' } jar { manifest { def attribute_map = [:] - if (project.use_coremod.toBoolean()) { - attribute_map['FMLCorePlugin'] = project.coremod_plugin_class_name - if (project.include_mod.toBoolean()) { - attribute_map['FMLCorePluginContainsFMLMod'] = true - } - } - if (project.use_mixins.toBoolean()) { - attribute_map['TweakClass'] = 'org.spongepowered.asm.launch.MixinTweaker' - // false for dev and true for non dev - attribute_map['ForceLoadAsMod'] = project.gradle.startParameter.taskNames[0] == "build" - } + attribute_map['FMLCorePlugin'] = project.coremod_plugin_class_name + attribute_map['FMLCorePluginContainsFMLMod'] = true + attribute_map['ForceLoadAsMod'] = project.gradle.startParameter.taskNames[0] == "build" attributes(attribute_map) } + // Add all embedded dependencies into the jar + from(provider{ configurations.embed.collect {it.isDirectory() ? it : zipTree(it)} }) } -shadowJar { - classifier = '' - baseName = archivesBaseName - version = version - configurations = [project.configurations.shadow] - relocate 'lib.group', "${project.group}.shadow.lib.group" // ensure repackaged packages have unique names -} - -reobf { - shadowJar {} +idea { + module { inheritOutputDirs = true } + project { settings { + runConfigurations { + "1. Run Client"(Gradle) { + taskNames = ['runClient'] + } + "2. Run Server"(Gradle) { + taskNames = ['runServer'] + } + "3. Run Obfuscated Client"(Gradle) { + taskNames = ['runObfClient'] + } + "4. Run Obfuscated Server"(Gradle) { + taskNames = ['runObfServer'] + } + } + compiler.javac { + afterEvaluate { + javacAdditionalOptions = '-encoding utf8' + moduleJavacAdditionalOptions = [ + (project.name + ".main"): tasks.compileJava.options.compilerArgs.collect { '"' + it + '"' }.join(' ') + ] + } + } + }} } -// this replaces jar.finalizedBy('reobfJar') in the standard forge mod buildscript -tasks.build.dependsOn reobfShadowJar -jar.finalizedBy('reobfShadowJar') - -artifacts { - archives shadowJar +tasks.named("processIdeaSettings").configure { + dependsOn("injectTags") } diff --git a/gradle.properties b/gradle.properties index dfca65ff3..927bd9a83 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,17 +9,10 @@ maven_group = com.cleanroommc archives_base_name = groovyscript groovy_version = 4.0.8 - mod_ref_path=com.cleanroommc.groovyscript.GroovyScript - -# Boilerplate Options -use_mixins = true -use_coremod = true - debug_load_all_mods = true # Coremod Arguments -include_mod = true coremod_plugin_class_name = com.cleanroommc.groovyscript.core.GroovyScriptCore # Debug mod compat diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6b071a780..d8d24753d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 000000000..4633bcf19 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,24 @@ +pluginManagement { + repositories { + maven { + // RetroFuturaGradle + name = 'GTNH Maven' + url = 'http://jenkins.usrv.eu:8081/nexus/content/groups/public/' + allowInsecureProtocol = true + mavenContent { + includeGroup 'com.gtnewhorizons' + includeGroup 'com.gtnewhorizons.retrofuturagradle' + } + } + gradlePluginPortal() + mavenCentral() + mavenLocal() + } +} + +plugins { + // Automatic toolchain provisioning + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.4.0' +} + +rootProject.name = archives_base_name \ No newline at end of file From 3de2ea0fb2bff0f100af1f5e1d2a62b5e6cae64e Mon Sep 17 00:00:00 2001 From: Rongmario Date: Sun, 14 May 2023 13:37:13 +0100 Subject: [PATCH 28/30] RFG tags, fix ThaumicJEI running without Thaumcraft --- build.gradle | 6 ++++-- .../java/com/cleanroommc/groovyscript/GroovyScript.java | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 009fa58a6..30fdadcdc 100644 --- a/build.gradle +++ b/build.gradle @@ -47,12 +47,14 @@ minecraft { useDependencyAccessTransformers = true + injectedTags.put("ID", project.archives_base_name) injectedTags.put("VERSION", project.version) + injectedTags.put("GROOVY_VERSION", project.groovy_version) } // Generate a my.project.Tags class with the version number as a field tasks.injectTags.configure { - outputClassName.set("${project.group}.Tags") + outputClassName.set("${project.group}.${project.archives_base_name}.Tags") } repositories { @@ -156,8 +158,8 @@ dependencies { if (project.debug_thaum.toBoolean()) { runtimeOnly rfg.deobf('curse.maven:baubles-227083:2518667') runtimeOnly rfg.deobf('curse.maven:thaumcraft-223628:2629023') + runtimeOnly 'curse.maven:thaumic_jei-285492:2705304' } - runtimeOnly 'curse.maven:thaumic_jei-285492:2705304' compileOnly rfg.deobf('curse.maven:astralsorcery-sorcery-241721:3044416') if (project.debug_astral.toBoolean()) { diff --git a/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java b/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java index efd07b8e6..b440f53b8 100644 --- a/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java +++ b/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java @@ -67,12 +67,12 @@ @Mod.EventBusSubscriber(modid = GroovyScript.ID) public class GroovyScript { - public static final String ID = "@MODID@"; + public static final String ID = Tags.ID; public static final String NAME = "GroovyScript"; - public static final String VERSION = "@VERSION@"; + public static final String VERSION = Tags.VERSION; public static final String MC_VERSION = "1.12.2"; - public static final String GROOVY_VERSION = "@GROOVY_VERSION@"; + public static final String GROOVY_VERSION = Tags.GROOVY_VERSION; public static final Logger LOGGER = LogManager.getLogger(ID); From 18c67232dc58804e1c228b6af491c9526092cd58 Mon Sep 17 00:00:00 2001 From: Rongmario Date: Sun, 14 May 2023 13:47:18 +0100 Subject: [PATCH 29/30] Disable javadocs jar for now --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 30fdadcdc..17289e9bf 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,7 @@ java { } // Generate sources and javadocs jars when building and publishing withSourcesJar() - withJavadocJar() + // withJavadocJar() } tasks.withType(JavaCompile).configureEach { From a9f1c484b65466ef8c1e014a47c5f93e75e90e79 Mon Sep 17 00:00:00 2001 From: Rongmario Date: Thu, 18 May 2023 17:30:30 +0100 Subject: [PATCH 30/30] Botania + Roots (and libs) --- build.gradle | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 17289e9bf..db3f235fa 100644 --- a/build.gradle +++ b/build.gradle @@ -154,9 +154,17 @@ dependencies { } compileOnly rfg.deobf('curse.maven:baubles-227083:2518667') + if (project.debug_astral.toBoolean() || project.debug_thaum.toBoolean() || project.debug_botania.toBoolean()) { + runtimeOnly rfg.deobf('curse.maven:baubles-227083:2518667') + } + + compileOnly rfg.deobf('curse.maven:botania-225643:3330934') + if (project.debug_botania.toBoolean()) { + runtimeOnly rfg.deobf('curse.maven:botania-225643:3330934') + } + compileOnly rfg.deobf('curse.maven:thaumcraft-223628:2629023') if (project.debug_thaum.toBoolean()) { - runtimeOnly rfg.deobf('curse.maven:baubles-227083:2518667') runtimeOnly rfg.deobf('curse.maven:thaumcraft-223628:2629023') runtimeOnly 'curse.maven:thaumic_jei-285492:2705304' } @@ -171,6 +179,17 @@ dependencies { runtimeOnly rfg.deobf('curse.maven:immersive_engineering-231951:2974106') } + compileOnly rfg.deobf('curse.maven:patchouli-306770:3162874') + compileOnly rfg.deobf('curse.maven:mystical_lib-277064:3483816') + 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_lib-277064:3483816') + runtimeOnly rfg.deobf('curse.maven:mystical_world-282940:3460961') + runtimeOnly rfg.deobf('curse.maven:roots-246183:3905074') + } + compileOnly 'slimeknights.mantle:Mantle:1.12-1.3.3.55' compileOnly 'slimeknights:TConstruct:1.12.2-2.13.0.190' compileOnly rfg.deobf('curse.maven:constructs-armory-287683:3174535')