diff --git a/build.gradle b/build.gradle index c6f71e732..0fc29a6ee 100644 --- a/build.gradle +++ b/build.gradle @@ -131,7 +131,17 @@ dependencies { runtimeOnly rfg.deobf('curse.maven:guide-api-228832:2645992') runtimeOnly rfg.deobf('curse.maven:blood-magic-224791:2822288') } + + compileOnly rfg.deobf('curse.maven:cyclops-core-232758:3159497') + if (project.debug_evilcraft.toBoolean()) { + runtimeOnly rfg.deobf('curse.maven:cyclops-core-232758:3159497') + } + compileOnly rfg.deobf('curse.maven:evilcraft-74610:2811267') + if (project.debug_evilcraft.toBoolean()) { + runtimeOnly rfg.deobf('curse.maven:evilcraft-74610:2811267') + } + compileOnly rfg.deobf('curse.maven:actually-additions-228404:3117927') if (project.debug_actually_additions.toBoolean()) { runtimeOnly rfg.deobf('curse.maven:actually-additions-228404:3117927') diff --git a/examples/evilcraft.groovy b/examples/evilcraft.groovy new file mode 100644 index 000000000..6d362c046 --- /dev/null +++ b/examples/evilcraft.groovy @@ -0,0 +1,70 @@ + +// Weather Bracket Handler +weather('clear') +weather('rain') +weather('lightning') + + +// Blood Infuser: +// Consumes an item, some fluid, and requires a given tier of Promise of Tenacity to produce the output and some experience after a duration. +mods.evilcraft.bloodinfuser.recipeBuilder() + .input(item('minecraft:clay')) + .output(item('minecraft:clay')) + .fluidInput(fluid('evilcraftblood') * 1000) + .tier(3) // Optional integer. Requires at least this tier of Promise of Tenacity to craft. Defaults to 0. + .duration(100) // Optional integer. Time in ticks for the recipe to complete. Defaults to 0. + .xp(10000) // Optional float. Experience gained when completing the recipe. Defaults to 0. + .register() + +mods.evilcraft.bloodinfuser.recipeBuilder() + .input(item('minecraft:gold_ingot')) + .output(item('minecraft:clay')) + .fluidInput(100000) // Calling `fluidInput` with just an integer will automatically consider the fluid as "evilcraftblood". + .register() + +mods.evilcraft.bloodinfuser.recipeBuilder() + .input(item('minecraft:diamond')) + .output(item('minecraft:clay') * 4) + .fluidInput(5000) // `blood` can also be used as an alias for `fluidInput` when only an integer is used. + .tier(1) + .register() + +mods.evilcraft.bloodinfuser.removeByInput(item('evilcraft:dark_gem')) +mods.evilcraft.bloodinfuser.removeByOutput(item('minecraft:leather')) +//mods.evilcraft.bloodinfuser.removeAll() + + +// Environmental Accumulator: +// Consumes an item to give an output, possibly changing the weather. Has a cooldown time or a blood cost. +mods.evilcraft.environmentalaccumulator.recipeBuilder() + .input(item('minecraft:clay')) + .output(item('minecraft:clay') * 2) + .inputWeather(weather('clear')) + .outputWeather(weather('rain')) + .processingspeed(1) // Optional doube. Controls the visual rotation of the item while crafting. Defaults to the amount set in the config. + .cooldowntime(1000) // Optional integer. Time it takes before another recipe can be run. Defaults to the time set in the config. + // cooldowntime also controls the amount of evilcraftblood consumed by the Sanguinary Environmental Accumulator + .duration(10) // Optional integer. Time it takes to complete the recipe. Defaults to the time set in the config. + .register() + +mods.evilcraft.environmentalaccumulator.recipeBuilder() + .input(item('minecraft:gold_ingot')) + .output(item('minecraft:diamond')) + .inputWeather(weather('rain')) + .outputWeather(weather('lightning')) + .speed(10) // Short for processingspeed. + .cooldown(1) // Short for cooldowntime. + .register() + +mods.evilcraft.environmentalaccumulator.recipeBuilder() + .input(item('minecraft:diamond')) + .output(item('minecraft:clay') * 16) + .inputWeather(weather('lightning')) + .outputWeather(weather('lightning')) + .register() + + +mods.evilcraft.environmentalaccumulator.removeByInput(item('evilcraft:exalted_crafter:1')) +mods.evilcraft.environmentalaccumulator.removeByOutput(item('evilcraft:exalted_crafter:2')) +//mods.evilcraft.environmentalaccumulator.removeAll() + diff --git a/gradle.properties b/gradle.properties index 9a0498abb..0f45288fb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,6 +19,7 @@ coremod_plugin_class_name = com.cleanroommc.groovyscript.core.GroovyScriptCore debug_actually_additions = false debug_chisel = false debug_mekanism = false +debug_evilcraft = false debug_thermal = false debug_thaum = false debug_ic2 = false diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java index e70675094..c22b71d2c 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java @@ -9,6 +9,7 @@ import com.cleanroommc.groovyscript.compat.mods.chisel.Chisel; import com.cleanroommc.groovyscript.compat.mods.draconicevolution.DraconicEvolution; import com.cleanroommc.groovyscript.compat.mods.enderio.EnderIO; +import com.cleanroommc.groovyscript.compat.mods.evilcraft.EvilCraft; import com.cleanroommc.groovyscript.compat.mods.extendedcrafting.ExtendedCrafting; import com.cleanroommc.groovyscript.compat.mods.forestry.Forestry; import com.cleanroommc.groovyscript.compat.mods.ic2.IC2; @@ -53,6 +54,7 @@ public class ModSupport implements IDynamicGroovyProperty { 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 EVILCRAFT = new Container<>("evilcraft", "EvilCraft", EvilCraft::new); 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"); public static final Container EXTENDED_CRAFTING = new Container<>("extendedcrafting", "Extended Crafting", ExtendedCrafting::new); diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/evilcraft/BloodInfuser.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/evilcraft/BloodInfuser.java new file mode 100644 index 000000000..e0cfa1cda --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/evilcraft/BloodInfuser.java @@ -0,0 +1,141 @@ +package com.cleanroommc.groovyscript.compat.mods.evilcraft; + +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.registry.VirtualizedRegistry; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; +import org.cyclops.cyclopscore.recipe.custom.api.IRecipe; +import org.cyclops.cyclopscore.recipe.custom.component.IngredientRecipeComponent; +import org.cyclops.evilcraft.core.recipe.custom.DurationXpRecipeProperties; +import org.cyclops.evilcraft.core.recipe.custom.IngredientFluidStackAndTierRecipeComponent; +import org.jetbrains.annotations.Nullable; + +public class BloodInfuser extends VirtualizedRegistry> { + + public BloodInfuser() { + super(); + } + + public RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(org.cyclops.evilcraft.block.BloodInfuser.getInstance().getRecipeRegistry().allRecipes()::remove); + restoreFromBackup().forEach(org.cyclops.evilcraft.block.BloodInfuser.getInstance().getRecipeRegistry().allRecipes()::add); + } + + public void add(IRecipe recipe) { + this.add(recipe, true); + } + + public void add(IRecipe recipe, boolean add) { + if (recipe == null) return; + addScripted(recipe); + if (add) org.cyclops.evilcraft.block.BloodInfuser.getInstance().getRecipeRegistry().allRecipes().add(recipe); + } + + public boolean remove(IRecipe recipe) { + if (recipe == null) return false; + addBackup(recipe); + org.cyclops.evilcraft.block.BloodInfuser.getInstance().getRecipeRegistry().allRecipes().remove(recipe); + return true; + } + + public boolean removeByInput(ItemStack input) { + return org.cyclops.evilcraft.block.BloodInfuser.getInstance().getRecipeRegistry().allRecipes().removeIf(r -> { + if (r.getInput().getIngredient().test(input)) { + addBackup(r); + return true; + } + return false; + }); + } + + public boolean removeByOutput(ItemStack input) { + return org.cyclops.evilcraft.block.BloodInfuser.getInstance().getRecipeRegistry().allRecipes().removeIf(r -> { + if (r.getOutput().getIngredient().test(input)) { + addBackup(r); + return true; + } + return false; + }); + } + + public void removeAll() { + org.cyclops.evilcraft.block.BloodInfuser.getInstance().getRecipeRegistry().allRecipes().forEach(this::addBackup); + org.cyclops.evilcraft.block.BloodInfuser.getInstance().getRecipeRegistry().allRecipes().clear(); + } + + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(org.cyclops.evilcraft.block.BloodInfuser.getInstance().getRecipeRegistry().allRecipes()) + .setRemover(this::remove); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder> { + + private static final Fluid bloodFluid = FluidRegistry.getFluid("evilcraftblood"); + + private int tier = 0; + private int duration = 0; + private float xp = 0; + + public RecipeBuilder tier(int tier) { + this.tier = tier; + return this; + } + + public RecipeBuilder duration(int duration) { + this.duration = duration; + return this; + } + + public RecipeBuilder xp(float xp) { + this.xp = xp; + return this; + } + + public RecipeBuilder blood(int amount) { + this.fluidInput.add(new FluidStack(bloodFluid, amount)); + return this; + } + + public RecipeBuilder fluidInput(int amount) { + this.fluidInput.add(new FluidStack(bloodFluid, amount)); + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding EvilCraft Blood Infuser Recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 1, 1, 1, 1); + validateFluids(msg, 1, 1, 0, 0); + msg.add(tier < 0 || tier > 3, "tier must be between 0 and 3, yet it was {}", tier); + msg.add(duration < 0, "duration must be a non negative integer, yet it was {}", duration); + msg.add(xp < 0, "xp must be a non negative integer, yet it was {}", xp); + } + + @Override + public @Nullable IRecipe register() { + if (!validate()) return null; + IRecipe recipe = + org.cyclops.evilcraft.block.BloodInfuser.getInstance().getRecipeRegistry().registerRecipe( + new IngredientFluidStackAndTierRecipeComponent(input.get(0).toMcIngredient(), fluidInput.get(0), tier), + new IngredientRecipeComponent(output.get(0)), + new DurationXpRecipeProperties(duration, xp) + ); + ModSupport.EVILCRAFT.get().bloodInfuser.add(recipe, false); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/evilcraft/EnvironmentalAccumulator.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/evilcraft/EnvironmentalAccumulator.java new file mode 100644 index 000000000..53691beec --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/evilcraft/EnvironmentalAccumulator.java @@ -0,0 +1,163 @@ +package com.cleanroommc.groovyscript.compat.mods.evilcraft; + +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.registry.VirtualizedRegistry; +import net.minecraft.item.ItemStack; +import org.cyclops.cyclopscore.recipe.custom.api.IRecipe; +import org.cyclops.evilcraft.block.EnvironmentalAccumulatorConfig; +import org.cyclops.evilcraft.core.recipe.custom.EnvironmentalAccumulatorRecipeComponent; +import org.cyclops.evilcraft.core.recipe.custom.EnvironmentalAccumulatorRecipeProperties; +import org.cyclops.evilcraft.core.weather.WeatherType; +import org.jetbrains.annotations.Nullable; + +import java.util.Locale; + +public class EnvironmentalAccumulator extends VirtualizedRegistry> { + + public EnvironmentalAccumulator() { + super(); + } + + public RecipeBuilder recipeBuilder() { + return new RecipeBuilder(); + } + + @Override + public void onReload() { + removeScripted().forEach(org.cyclops.evilcraft.block.EnvironmentalAccumulator.getInstance().getRecipeRegistry().allRecipes()::remove); + restoreFromBackup().forEach(org.cyclops.evilcraft.block.EnvironmentalAccumulator.getInstance().getRecipeRegistry().allRecipes()::add); + } + + public void add(IRecipe recipe) { + this.add(recipe, true); + } + + public void add(IRecipe recipe, boolean add) { + if (recipe == null) return; + addScripted(recipe); + if (add) org.cyclops.evilcraft.block.EnvironmentalAccumulator.getInstance().getRecipeRegistry().allRecipes().add(recipe); + } + + public boolean remove(IRecipe recipe) { + if (recipe == null) return false; + addBackup(recipe); + org.cyclops.evilcraft.block.EnvironmentalAccumulator.getInstance().getRecipeRegistry().allRecipes().remove(recipe); + return true; + } + + public boolean removeByInput(ItemStack input) { + return org.cyclops.evilcraft.block.EnvironmentalAccumulator.getInstance().getRecipeRegistry().allRecipes().removeIf(r -> { + if (r.getInput().getIngredient().test(input)) { + addBackup(r); + return true; + } + return false; + }); + } + + public boolean removeByOutput(ItemStack input) { + return org.cyclops.evilcraft.block.EnvironmentalAccumulator.getInstance().getRecipeRegistry().allRecipes().removeIf(r -> { + if (r.getOutput().getIngredient().test(input)) { + addBackup(r); + return true; + } + return false; + }); + } + + public void removeAll() { + org.cyclops.evilcraft.block.EnvironmentalAccumulator.getInstance().getRecipeRegistry().allRecipes().forEach(this::addBackup); + org.cyclops.evilcraft.block.EnvironmentalAccumulator.getInstance().getRecipeRegistry().allRecipes().clear(); + } + + public SimpleObjectStream> streamRecipes() { + return new SimpleObjectStream<>(org.cyclops.evilcraft.block.EnvironmentalAccumulator.getInstance().getRecipeRegistry().allRecipes()) + .setRemover(this::remove); + } + + public static class RecipeBuilder extends AbstractRecipeBuilder> { + + private double processingspeed = EnvironmentalAccumulatorConfig.defaultProcessItemSpeed; + private int cooldowntime = EnvironmentalAccumulatorConfig.defaultTickCooldown; + private int duration = EnvironmentalAccumulatorConfig.defaultProcessItemTickCount; + private WeatherType inputWeather; + private WeatherType outputWeather; + + public RecipeBuilder cooldowntime(int cooldowntime) { + this.cooldowntime = cooldowntime; + return this; + } + + public RecipeBuilder cooldown(int cooldowntime) { + this.cooldowntime = cooldowntime; + return this; + } + + public RecipeBuilder duration(int duration) { + this.duration = duration; + return this; + } + + public RecipeBuilder processingspeed(double processingspeed) { + this.processingspeed = processingspeed; + return this; + } + + public RecipeBuilder speed(double processingspeed) { + this.processingspeed = processingspeed; + return this; + } + + public RecipeBuilder inputWeather(String inputWeather) { + this.inputWeather = WeatherType.valueOf(inputWeather.toUpperCase(Locale.ROOT)); + return this; + } + + public RecipeBuilder inputWeather(WeatherType inputWeather) { + this.inputWeather = inputWeather; + return this; + } + + public RecipeBuilder outputWeather(String outputWeather) { + this.outputWeather = WeatherType.valueOf(outputWeather.toUpperCase(Locale.ROOT)); + return this; + } + + public RecipeBuilder outputWeather(WeatherType outputWeather) { + this.outputWeather = outputWeather; + return this; + } + + @Override + public String getErrorMsg() { + return "Error adding EvilCraft Environmental Accumulator Recipe"; + } + + @Override + public void validate(GroovyLog.Msg msg) { + validateItems(msg, 1, 1, 1, 1); + validateFluids(msg); + msg.add(inputWeather == null, "inputWeather must be defined"); + msg.add(outputWeather == null, "outputWeather must be defined"); + msg.add(cooldowntime < 0, "cooldowntime must be a non negative integer, yet it was {}", cooldowntime); + msg.add(duration < 0, "duration must be a non negative integer, yet it was {}", duration); + msg.add(processingspeed < 0, "processingspeed must be a non negative integer, yet it was {}", processingspeed); + } + + @Override + public @Nullable IRecipe register() { + if (!validate()) return null; + IRecipe recipe = + org.cyclops.evilcraft.block.EnvironmentalAccumulator.getInstance().getRecipeRegistry().registerRecipe( + new EnvironmentalAccumulatorRecipeComponent(input.get(0).toMcIngredient(), inputWeather), + new EnvironmentalAccumulatorRecipeComponent(output.get(0), outputWeather), + new EnvironmentalAccumulatorRecipeProperties(duration, cooldowntime, processingspeed) + ); + ModSupport.EVILCRAFT.get().environmentalAccumulator.add(recipe, false); + return recipe; + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/evilcraft/EvilCraft.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/evilcraft/EvilCraft.java new file mode 100644 index 000000000..eb0b3f1b0 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/evilcraft/EvilCraft.java @@ -0,0 +1,23 @@ +package com.cleanroommc.groovyscript.compat.mods.evilcraft; + +import com.cleanroommc.groovyscript.brackets.BracketHandlerManager; +import com.cleanroommc.groovyscript.compat.mods.ModPropertyContainer; +import org.cyclops.evilcraft.core.weather.WeatherType; + +import java.util.Locale; + +public class EvilCraft extends ModPropertyContainer { + + public final BloodInfuser bloodInfuser = new BloodInfuser(); + public final EnvironmentalAccumulator environmentalAccumulator = new EnvironmentalAccumulator(); + + public EvilCraft() { + addRegistry(bloodInfuser); + addRegistry(environmentalAccumulator); + } + + @Override + public void initialize() { + BracketHandlerManager.registerBracketHandler("weather", s -> WeatherType.valueOf(s.toUpperCase(Locale.ROOT))); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/helper/recipe/AbstractRecipeBuilder.java b/src/main/java/com/cleanroommc/groovyscript/helper/recipe/AbstractRecipeBuilder.java index 1158c32c6..84b5a158a 100644 --- a/src/main/java/com/cleanroommc/groovyscript/helper/recipe/AbstractRecipeBuilder.java +++ b/src/main/java/com/cleanroommc/groovyscript/helper/recipe/AbstractRecipeBuilder.java @@ -137,7 +137,7 @@ public void validateFluids(GroovyLog.Msg msg, int minFluidInput, int maxFluidInp public void validateItems(GroovyLog.Msg msg, int minInput, int maxInput, int minOutput, int maxOutput) { input.trim(); output.trim(); - msg.add(input.size() < minInput || input.size() > maxInput, () -> getRequiredString(minInput, maxInput, " item input") + ", but found " + input.size()); + msg.add(input.size() < minInput || input.size() > maxInput, () -> getRequiredString(minInput, maxInput, "item input") + ", but found " + input.size()); msg.add(output.size() < minOutput || output.size() > maxOutput, () -> getRequiredString(minOutput, maxOutput, "item output") + ", but found " + output.size()); }