From ab64a4b26791f0848ae6100a001a72a1334c975f Mon Sep 17 00:00:00 2001
From: Waiting Idly <25394029+WaitingIdly@users.noreply.github.com>
Date: Tue, 30 Apr 2024 21:44:54 -0700
Subject: [PATCH] add Thermal Expansion compat (#152)
* allow recipe builder methods to be documented as commented
* add debug log to missing spot some likely annotations
* tweak internal documentation method using singleton list
* fix minor whitespace error in generating unfinished docs
* update gs hand text
* add nbt matcher to fluidstack mixin
* fix minor javadoc comment
* add a bunch of accessors
* add and implement AbstractReloadableStorage
* make editorconfig only indent groovy builders by 4
* add the machines
* gootbye old commented out example file
* dynamo
* remove duplicate colon when printing missing keys
* devices
* add recipebuilder examples for CentrifugeMobs
* note sawmill resin funnel augment better
* implement add
* add missing add lang keys
* \"tree\"
* allow overriding #recipeStorage, javadocs for ARS
* apply MethodDescription fallback to thermal
---
.editorconfig | 3 +-
examples/postInit/thermal.groovy | 63 --
examples/postInit/thermalexpansion.groovy | 653 ++++++++++++++++++
.../annotations/RegistryDescription.java | 2 +-
.../groovyscript/command/GSCommand.java | 4 +-
.../groovyscript/command/GSHandCommand.java | 38 +-
.../groovyscript/compat/mods/ModSupport.java | 2 +-
.../compat/mods/chisel/Carving.java | 32 +-
.../mods/inspirations/AnvilSmashing.java | 48 +-
.../compat/mods/mekanism/Infusion.java | 30 +-
.../compat/mods/tcomplement/Melter.java | 50 +-
.../compat/mods/thaumcraft/Research.java | 18 +-
.../compat/mods/thermalexpansion/Brewer.java | 119 ----
.../mods/thermalexpansion/Crucible.java | 110 ---
.../mods/thermalexpansion/Pulverizer.java | 143 ----
.../thermalexpansion/ThermalExpansion.java | 87 ++-
.../mods/thermalexpansion/device/Coolant.java | 93 +++
.../thermalexpansion/device/Diffuser.java | 99 +++
.../thermalexpansion/device/Factorizer.java | 206 ++++++
.../mods/thermalexpansion/device/Fisher.java | 98 +++
.../thermalexpansion/device/FisherBait.java | 75 ++
.../mods/thermalexpansion/device/Tapper.java | 168 +++++
.../device/TapperFertilizer.java | 75 ++
.../thermalexpansion/device/TapperTree.java | 101 +++
.../thermalexpansion/device/XpCollector.java | 94 +++
.../thermalexpansion/dynamo/Compression.java | 87 +++
.../thermalexpansion/dynamo/Enervation.java | 84 +++
.../thermalexpansion/dynamo/Lapidary.java | 84 +++
.../thermalexpansion/dynamo/Magmatic.java | 89 +++
.../thermalexpansion/dynamo/Numismatic.java | 84 +++
.../thermalexpansion/dynamo/Reactant.java | 189 +++++
.../mods/thermalexpansion/dynamo/Steam.java | 84 +++
.../mods/thermalexpansion/machine/Brewer.java | 172 +++++
.../thermalexpansion/machine/Centrifuge.java | 163 +++++
.../machine/CentrifugeMobs.java | 165 +++++
.../thermalexpansion/machine/Charger.java | 135 ++++
.../thermalexpansion/machine/Compactor.java | 195 ++++++
.../thermalexpansion/machine/Crucible.java | 151 ++++
.../thermalexpansion/machine/Enchanter.java | 199 ++++++
.../thermalexpansion/machine/Extruder.java | 220 ++++++
.../thermalexpansion/machine/Furnace.java | 155 +++++
.../machine/FurnacePyrolysis.java | 144 ++++
.../thermalexpansion/machine/Insolator.java | 223 ++++++
.../machine/Precipitator.java | 152 ++++
.../thermalexpansion/machine/Pulverizer.java | 146 ++++
.../thermalexpansion/machine/Refinery.java | 228 ++++++
.../machine/RefineryPotion.java | 143 ++++
.../thermalexpansion/machine/Sawmill.java | 148 ++++
.../thermalexpansion/machine/Smelter.java | 174 +++++
.../machine/TransposerExtract.java | 164 +++++
.../machine/TransposerFill.java | 175 +++++
.../compat/mods/tinkersconstruct/Melting.java | 18 +-
.../mods/tinkersconstruct/SmelteryFuel.java | 17 +-
.../core/mixin/FluidStackMixin.java | 63 +-
.../BrewerManagerAccessor.java | 1 +
.../BrewerRecipeAccessor.java | 17 +
.../CentrifugeManagerAccessor.java | 23 +
.../CentrifugeRecipeAccessor.java | 22 +
.../ChargerManagerAccessor.java | 18 +
.../CompactorManagerAccessor.java | 33 +
.../CompactorRecipeAccessor.java | 16 +
.../CompressionManagerAccessor.java | 16 +
.../CoolantManagerAccessor.java | 21 +
.../CrucibleManagerAccessor.java | 1 +
.../CrucibleRecipeAccessor.java | 17 +
.../DiffuserManagerAccessor.java | 22 +
.../EnchanterManagerAccessor.java | 30 +
.../EnchanterRecipeAccessor.java | 16 +
.../EnervationManagerAccessor.java | 17 +
.../ExtruderManagerAccessor.java | 35 +
.../ExtruderRecipeAccessor.java | 17 +
.../FactorizerManagerAccessor.java | 23 +
.../FactorizerRecipeAccessor.java | 16 +
.../FisherManagerAccessor.java | 40 ++
.../FurnaceManagerAccessor.java | 29 +
.../FurnaceRecipeAccessor.java | 21 +
.../InsolatorManagerAccessor.java | 30 +
.../InsolatorRecipeAccessor.java | 16 +
.../MagmaticManagerAccessor.java | 16 +
.../NumismaticManagerAccessor.java | 22 +
.../PrecipitatorManagerAccessor.java | 25 +
.../PrecipitatorRecipeAccessor.java | 17 +
.../PulverizerRecipeAccessor.java | 16 +
.../ReactantManagerAccessor.java | 40 ++
.../thermalexpansion/ReactionAccessor.java | 17 +
.../RefineryManagerAccessor.java | 33 +
.../RefineryRecipeAccessor.java | 17 +
.../SawmillManagerAccessor.java | 18 +
.../SawmillRecipeAccessor.java | 16 +
.../SmelterManagerAccessor.java | 30 +
.../SmelterRecipeAccessor.java | 16 +
.../SteamManagerAccessor.java | 17 +
.../TapperManagerAccessor.java | 38 +
.../TransposerManagerAccessor.java | 36 +
.../XpCollectorManagerAccessor.java | 22 +
.../groovyscript/documentation/Builder.java | 35 +-
.../documentation/Documentation.java | 2 +-
.../groovyscript/documentation/Registry.java | 9 +-
.../helper/ingredient/IngredientHelper.java | 11 +
.../helper/ingredient/NbtHelper.java | 97 ++-
.../registry/AbstractReloadableStorage.java | 112 +++
.../registry/VirtualizedRegistry.java | 45 +-
.../assets/groovyscript/lang/en_us.lang | 221 ++++++
.../mixin.groovyscript.thermalexpansion.json | 41 +-
104 files changed, 7261 insertions(+), 667 deletions(-)
delete mode 100644 examples/postInit/thermal.groovy
create mode 100644 examples/postInit/thermalexpansion.groovy
delete mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/Brewer.java
delete mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/Crucible.java
delete mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/Pulverizer.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Coolant.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Diffuser.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Factorizer.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Fisher.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/FisherBait.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Tapper.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/TapperFertilizer.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/TapperTree.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/XpCollector.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Compression.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Enervation.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Lapidary.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Magmatic.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Numismatic.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Reactant.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Steam.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Brewer.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Centrifuge.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/CentrifugeMobs.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Charger.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Compactor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Crucible.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Enchanter.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Extruder.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Furnace.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/FurnacePyrolysis.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Insolator.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Precipitator.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Pulverizer.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Refinery.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/RefineryPotion.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Sawmill.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Smelter.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/TransposerExtract.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/TransposerFill.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/BrewerRecipeAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CentrifugeManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CentrifugeRecipeAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/ChargerManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CompactorManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CompactorRecipeAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CompressionManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CoolantManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CrucibleRecipeAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/DiffuserManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/EnchanterManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/EnchanterRecipeAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/EnervationManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/ExtruderManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/ExtruderRecipeAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FactorizerManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FactorizerRecipeAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FisherManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FurnaceManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FurnaceRecipeAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/InsolatorManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/InsolatorRecipeAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/MagmaticManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/NumismaticManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/PrecipitatorManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/PrecipitatorRecipeAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/PulverizerRecipeAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/ReactantManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/ReactionAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/RefineryManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/RefineryRecipeAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/SawmillManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/SawmillRecipeAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/SmelterManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/SmelterRecipeAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/SteamManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/TapperManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/TransposerManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/XpCollectorManagerAccessor.java
create mode 100644 src/main/java/com/cleanroommc/groovyscript/registry/AbstractReloadableStorage.java
diff --git a/.editorconfig b/.editorconfig
index 4279c2d1f..63e24665b 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -319,6 +319,7 @@ ij_shell_switch_cases_indented = false
ij_shell_use_unix_line_separator = true
[{*.gant,*.groovy,*.gy}]
+ij_continuation_indent_size = 4
ij_groovy_align_group_field_declarations = false
ij_groovy_align_multiline_array_initializer_expression = false
ij_groovy_align_multiline_assignment = false
@@ -593,7 +594,7 @@ ij_kotlin_wrap_elvis_expressions = 1
ij_kotlin_wrap_expression_body_functions = 0
ij_kotlin_wrap_first_method_in_call_chain = false
-[{*.har,*.json,c:ingot_aluminium,mcmod.info,pack.mcmeta}]
+[{*.har,*.json,mcmod.info,pack.mcmeta}]
indent_size = 2
ij_json_array_wrapping = split_into_lines
ij_json_keep_blank_lines_in_code = 0
diff --git a/examples/postInit/thermal.groovy b/examples/postInit/thermal.groovy
deleted file mode 100644
index 14f8372c2..000000000
--- a/examples/postInit/thermal.groovy
+++ /dev/null
@@ -1,63 +0,0 @@
-
-// MODS_LOADED: thermalexpansion
-println 'mod \'thermalexpansion\' detected, running script'
-
-mods.te.Pulverizer.recipeBuilder()
- .input(item('minecraft:bookshelf'))
- .output(item('minecraft:diamond'))
- .secondaryOutput(item('minecraft:diamond'), 1)
- .energy(2000)
- .register()
-
-mods.te.Pulverizer.streamRecipes()
- .filter{ recipe -> recipe.getSecondaryOutputChance() <= 0 }
- .removeAll()
-
-mods.thermalexpansion.Brewer.recipeBuilder()
- .fluidInput(fluid('lava') * 1500)
- .input(item('minecraft:gold_ingot'))
- .fluidOutput(fluid('water') * 500)
- .register()
-
-mods.thermalexpansion.Crucible.recipeBuilder()
- .input(item('minecraft:diamond'))
- .fluidOutput(fluid('lava'))
- .register()
-
-//mods.thermalexpansion.Crucible.removeByInput(item('thermalfoundation:material:1027'))
-
-/*
-mods.thermalexpansion.Centrifuge.recipeBuilder()
- .input(item('minecraft:diamond'))
- .output(item('minecraft:wool:5'), 0.3)
- .output(item('minecraft:wool:6'), 0.2)
- .output(item('minecraft:wool:7'), 0.1)
- .output(item('minecraft:wool:8'), 0.05)
- .fluidOutput(fluid('water') * 420)
- .energy(3333)
- .register()
-
-mods.thermalexpansion.Centrifuge.removeByInput(item('minecraft:concrete_powder:6'))
-
-
-mods.thermalexpansion.Charger.recipeBuilder()
- .input(item('minecraft:iron_ingot'))
- .output(item('minecraft:diamond'))
- .energy(500000)
- .register()
-
-mods.thermalexpansion.Charger.removeByInput(item('thermalfoundation:fertilizer:1'))
-
-mods.thermalexpansion.Compactor.recipeBuilder()
- .input(item('minecraft:coal') * 64)
- .output(item('minecraft:diamond'))
- .energy(70000)
- .register()
-
-mods.thermalexpansion.Compactor.Coin.recipeBuilder()
- .input(item('minecraft:clay_ball'))
- .output(item('minecraft:diamond'))
- .register()
-
-mods.thermalexpansion.Compactor.Gear.removeByInput(ore('ingotEnderium'))
- */
\ No newline at end of file
diff --git a/examples/postInit/thermalexpansion.groovy b/examples/postInit/thermalexpansion.groovy
new file mode 100644
index 000000000..c37308f81
--- /dev/null
+++ b/examples/postInit/thermalexpansion.groovy
@@ -0,0 +1,653 @@
+
+// Auto generated groovyscript example file
+// MODS_LOADED: thermalexpansion
+
+import cofh.thermalexpansion.util.managers.machine.InsolatorManager
+
+println 'mod \'thermalexpansion\' detected, running script'
+
+// Alchemical Imbuer:
+// Converts an input fluidstack and input itemstack into an output fluidstack, costing power and taking time based on the
+// power cost.
+
+mods.thermalexpansion.brewer.removeByInput(item('minecraft:glowstone_dust'))
+mods.thermalexpansion.brewer.removeByInput(fluid('potion').withNbt(['Potion': 'minecraft:leaping']))
+mods.thermalexpansion.brewer.removeByOutput(fluid('potion_splash').withNbt(['Potion': 'cofhcore:luck2']))
+// mods.thermalexpansion.brewer.removeAll()
+
+mods.thermalexpansion.brewer.recipeBuilder()
+ .input(item('minecraft:clay'))
+ .fluidInput(fluid('water') * 100)
+ .fluidOutput(fluid('lava') * 100)
+ .register()
+
+mods.thermalexpansion.brewer.recipeBuilder()
+ .input(item('minecraft:diamond') * 2)
+ .fluidInput(fluid('water') * 1000)
+ .fluidOutput(fluid('steam') * 100)
+ .energy(1000)
+ .register()
+
+
+// mods.thermalexpansion.brewer.add(1000, item('minecraft:obsidian') * 2, fluid('water') * 1000, fluid('steam') * 100)
+
+// Centrifugal Separator:
+// Converts an input itemstack into an optional output fluidstack and up to four output itemstacks with chance, costing
+// power and taking time based on the power cost.
+
+mods.thermalexpansion.centrifuge.removeByInput(item('minecraft:reeds'))
+mods.thermalexpansion.centrifuge.removeByOutput(fluid('redstone'))
+mods.thermalexpansion.centrifuge.removeByOutput(item('minecraft:redstone'))
+// mods.thermalexpansion.centrifuge.removeAll()
+
+mods.thermalexpansion.centrifuge.recipeBuilder()
+ .input(item('minecraft:clay'))
+ .fluidOutput(fluid('water') * 100)
+ .output(item('minecraft:diamond') * 2, item('minecraft:gold_ingot'), item('minecraft:gold_ingot'))
+ .chance(50, 100, 1)
+ .register()
+
+mods.thermalexpansion.centrifuge.recipeBuilder()
+ .input(item('minecraft:diamond') * 3)
+ .output(item('minecraft:clay'))
+ .chance(100)
+ .energy(1000)
+ .register()
+
+
+// mods.thermalexpansion.centrifuge.add(1000, item('minecraft:obsidian') * 3, [item('minecraft:clay')], [100], null)
+
+// Centrifugal Separator - Enstabulation Apparatus:
+// Converts an input itemstack into an optional output fluidstack and up to four output itemstacks with chance, costing
+// power and taking time based on the power cost.
+
+mods.thermalexpansion.centrifuge_mobs.removeByInput(item('thermalexpansion:morb').withNbt(['id': 'minecraft:slime']))
+mods.thermalexpansion.centrifuge_mobs.removeByOutput(item('minecraft:fish'))
+// mods.thermalexpansion.centrifuge_mobs.removeByOutput(fluid('experience'))
+// mods.thermalexpansion.centrifuge_mobs.removeAll()
+
+mods.thermalexpansion.centrifuge_mobs.recipeBuilder()
+ .input(item('thermalexpansion:morb').withNbt(['id': 'minecraft:slime']))
+ .fluidOutput(fluid('water') * 100)
+ .output(item('minecraft:diamond') * 2, item('minecraft:gold_ingot'), item('minecraft:gold_ingot'))
+ .chance(50, 100, 1)
+ .register()
+
+mods.thermalexpansion.centrifuge_mobs.recipeBuilder()
+ .input(item('minecraft:diamond') * 3)
+ .output(item('minecraft:clay'))
+ .chance(100)
+ .energy(1000)
+ .register()
+
+
+// mods.thermalexpansion.centrifuge_mobs.add(1000, item('minecraft:obsidian') * 3, item('minecraft:clay'), 100)
+
+// Energetic Infuser:
+// Converts an input itemstack into an output itemstack, costing power and taking time based on the power cost.
+
+mods.thermalexpansion.charger.removeByInput(item('thermalfoundation:bait:1'))
+mods.thermalexpansion.charger.removeByOutput(item('thermalfoundation:fertilizer:2'))
+// mods.thermalexpansion.charger.removeAll()
+
+mods.thermalexpansion.charger.recipeBuilder()
+ .input(item('minecraft:diamond') * 5)
+ .output(item('minecraft:clay'))
+ .register()
+
+mods.thermalexpansion.charger.recipeBuilder()
+ .input(item('minecraft:clay'))
+ .output(item('minecraft:diamond') * 2)
+ .energy(1000)
+ .register()
+
+
+// mods.thermalexpansion.charger.add(1000, item('minecraft:obsidian'), item('minecraft:diamond') * 2)
+
+// Compactor:
+// Converts an input itemstack into an output itemstack, with different modes each requiring a different augment to be
+// installed, costing power and taking time based on the power cost.
+
+mods.thermalexpansion.compactor.removeByInput(mode('coin'), item('thermalfoundation:material:130'))
+mods.thermalexpansion.compactor.removeByInput(item('minecraft:iron_ingot'))
+// mods.thermalexpansion.compactor.removeByMode(mode('plate'))
+mods.thermalexpansion.compactor.removeByOutput(mode('coin'), item('thermalfoundation:coin:102'))
+mods.thermalexpansion.compactor.removeByOutput(item('minecraft:blaze_rod'))
+mods.thermalexpansion.compactor.removeByOutput(item('thermalfoundation:material:24'))
+// mods.thermalexpansion.compactor.removeAll()
+
+mods.thermalexpansion.compactor.recipeBuilder()
+ .input(item('minecraft:clay'))
+ .output(item('minecraft:diamond') * 2)
+ .mode(mode('coin'))
+ .register()
+
+mods.thermalexpansion.compactor.recipeBuilder()
+ .input(item('minecraft:clay'))
+ .output(item('minecraft:diamond'))
+ .mode(mode('all'))
+ .register()
+
+mods.thermalexpansion.compactor.recipeBuilder()
+ .input(item('minecraft:diamond') * 2)
+ .output(item('minecraft:gold_ingot'))
+ .mode(mode('plate'))
+ .energy(1000)
+ .register()
+
+
+// mods.thermalexpansion.compactor.add(1000, mode('plate'), item('minecraft:obsidian') * 2, item('minecraft:gold_ingot'))
+
+// Compression Dynamo:
+// Converts an input fluidstack into power, taking time based on the power.
+
+mods.thermalexpansion.compression.removeByInput(fluid('seed_oil'))
+// mods.thermalexpansion.compression.removeAll()
+
+mods.thermalexpansion.compression.add(fluid('steam'), 100)
+
+// Thermal Mediator:
+// Consumes fluid to speed up the tick rate of adjacent machines and devices and generate power in the Compression Dynamo.
+
+mods.thermalexpansion.coolant.remove(fluid('cryotheum'))
+// mods.thermalexpansion.coolant.removeAll()
+
+mods.thermalexpansion.coolant.add(fluid('lava'), 4000, 30)
+
+// Magma Crucible:
+// Converts an input itemstack into an output itemstack, costing power and taking time based on the power cost.
+
+mods.thermalexpansion.crucible.removeByInput(item('minecraft:glowstone_dust'))
+mods.thermalexpansion.crucible.removeByOutput(fluid('lava'))
+// mods.thermalexpansion.crucible.removeAll()
+
+mods.thermalexpansion.crucible.recipeBuilder()
+ .input(item('minecraft:clay'))
+ .fluidOutput(fluid('lava') * 25)
+ .register()
+
+mods.thermalexpansion.crucible.recipeBuilder()
+ .input(item('minecraft:diamond'))
+ .fluidOutput(fluid('water') * 1000)
+ .energy(1000)
+ .register()
+
+
+mods.thermalexpansion.crucible.add(1000, item('minecraft:obsidian'), fluid('water') * 1000)
+
+// Decorative Diffuser:
+// Controls what items can be used in to boost the potion time and level in the Decorative Diffuser.
+
+mods.thermalexpansion.diffuser.remove(item('minecraft:redstone'))
+// mods.thermalexpansion.diffuser.removeAll()
+
+mods.thermalexpansion.diffuser.add(item('minecraft:clay'), 2, 30)
+
+// Arcane Ensorcellator:
+// Converts two input itemstacks and liquid experience into an output itemstack, costing power and taking time based on the
+// power cost.
+
+mods.thermalexpansion.enchanter.removeByInput(item('minecraft:blaze_rod'))
+// mods.thermalexpansion.enchanter.removeByInput(item('minecraft:book'))
+mods.thermalexpansion.enchanter.removeByOutput(item('minecraft:enchanted_book').withNbt(['StoredEnchantments': [['lvl': 1, 'id': 34]]]))
+// mods.thermalexpansion.enchanter.removeAll()
+
+mods.thermalexpansion.enchanter.recipeBuilder()
+ .input(item('minecraft:clay'), item('minecraft:gold_ingot') * 4)
+ .output(item('minecraft:diamond'))
+ .register()
+
+mods.thermalexpansion.enchanter.recipeBuilder()
+ .input(item('minecraft:clay'), item('minecraft:gold_ingot'))
+ .output(item('minecraft:diamond'))
+ .experience(1000)
+ .energy(1000)
+ .register()
+
+
+mods.thermalexpansion.enchanter.add(1000, item('minecraft:obsidian'), item('minecraft:gold_ingot'), item('minecraft:diamond'), 1000)
+mods.thermalexpansion.enchanter.addArcana(item('minecraft:clay'))
+
+// Enervation Dynamo:
+// Converts an input itemstack into power, taking time based on the power.
+
+mods.thermalexpansion.enervation.removeByInput(item('minecraft:redstone'))
+// mods.thermalexpansion.enervation.removeAll()
+
+mods.thermalexpansion.enervation.add(item('minecraft:clay'), 100)
+
+// Igneous Extruder:
+// Converts a variable amount of lava and water into a specific output itemstack.
+
+// mods.thermalexpansion.extruder.removeByInput(false, fluid('lava'))
+// mods.thermalexpansion.extruder.removeByInput(fluid('water'))
+mods.thermalexpansion.extruder.removeByOutput(true, item('minecraft:gravel'))
+mods.thermalexpansion.extruder.removeByOutput(item('minecraft:obsidian'))
+// mods.thermalexpansion.extruder.removeByType(true)
+// mods.thermalexpansion.extruder.removeAll()
+
+mods.thermalexpansion.extruder.recipeBuilder()
+ .fluidHot(100)
+ .fluidCold(1000)
+ .output(item('minecraft:clay'))
+ .register()
+
+mods.thermalexpansion.extruder.recipeBuilder()
+ .fluidHot(100)
+ .fluidCold(1000)
+ .output(item('minecraft:gold_ingot'))
+ .sedimentary()
+ .energy(1000)
+ .register()
+
+
+mods.thermalexpansion.extruder.add(1000, item('minecraft:gold_block'), 100, 1000, false)
+
+// Factorizer:
+// Converts an input itemstack into an output itemstack, with the ability to undo the the recipe. Mainly used for
+// compressing ingots into blocks and splitting blocks into ingots.
+
+mods.thermalexpansion.factorizer.removeByInput(false, item('minecraft:diamond'))
+mods.thermalexpansion.factorizer.removeByInput(item('minecraft:coal:1'))
+// mods.thermalexpansion.factorizer.removeByOutput(false, item('minecraft:coal:1'))
+mods.thermalexpansion.factorizer.removeByOutput(item('minecraft:emerald_block'))
+// mods.thermalexpansion.factorizer.removeByType(true)
+// mods.thermalexpansion.factorizer.removeAll()
+
+mods.thermalexpansion.factorizer.recipeBuilder()
+ .input(item('minecraft:clay') * 7)
+ .output(item('minecraft:book') * 2)
+ .combine()
+ .split()
+ .register()
+
+mods.thermalexpansion.factorizer.recipeBuilder()
+ .input(item('minecraft:planks:*') * 4)
+ .output(item('minecraft:crafting_table'))
+ .combine()
+ .register()
+
+
+
+// Aquatic Entangler:
+// Controls what itemstacks can be gained and how likely each is to be obtained.
+
+mods.thermalexpansion.fisher.remove(item('minecraft:fish:0'))
+// mods.thermalexpansion.fisher.removeAll()
+
+mods.thermalexpansion.fisher.add(item('minecraft:clay'), 100)
+
+// Aquatic Entangler Bait:
+// Controls what items can be used in the bait slot of the Aquatic Entangler and how effective they are.
+
+mods.thermalexpansion.fisher_bait.remove(item('thermalfoundation:bait:2'))
+// mods.thermalexpansion.fisher_bait.removeAll()
+
+mods.thermalexpansion.fisher_bait.add(item('minecraft:clay'), 100)
+
+// Redstone Furnace:
+// Converts an input itemstack into an output itemstack, costing power and taking time based on the power cost.
+
+mods.thermalexpansion.furnace.removeByInput(item('minecraft:cactus:*'))
+mods.thermalexpansion.furnace.removeByOutput(item('minecraft:cooked_porkchop'))
+mods.thermalexpansion.furnace.removeFood(item('minecraft:rabbit:*'))
+// mods.thermalexpansion.furnace.removeAll()
+// mods.thermalexpansion.furnace.removeAllFood()
+
+mods.thermalexpansion.furnace.recipeBuilder()
+ .input(item('minecraft:diamond'))
+ .output(item('minecraft:clay') * 2)
+ .register()
+
+mods.thermalexpansion.furnace.recipeBuilder()
+ .input(item('minecraft:gold_ingot') * 2)
+ .output(item('minecraft:clay'))
+ .energy(1000)
+ .register()
+
+
+mods.thermalexpansion.furnace.add(1000, item('minecraft:obsidian') * 2, item('minecraft:clay'))
+mods.thermalexpansion.furnace.addFood(item('minecraft:emerald_ore'))
+
+// Redstone Furnace - Pyrolytic Conversion:
+// Converts an input itemstack into an output itemstack and creosote amount, costing power and taking time based on the
+// power cost.
+
+mods.thermalexpansion.furnace_pyrolysis.removeByInput(item('minecraft:cactus:*'))
+mods.thermalexpansion.furnace_pyrolysis.removeByOutput(item('thermalfoundation:storage_resource:1'))
+// mods.thermalexpansion.furnace_pyrolysis.removeAll()
+
+mods.thermalexpansion.furnace_pyrolysis.recipeBuilder()
+ .input(item('minecraft:clay'))
+ .output(item('minecraft:diamond') * 2)
+ .creosote(100)
+ .register()
+
+mods.thermalexpansion.furnace_pyrolysis.recipeBuilder()
+ .input(item('minecraft:gold_ingot') * 2)
+ .output(item('minecraft:clay'))
+ .creosote(1000)
+ .energy(1000)
+ .register()
+
+
+mods.thermalexpansion.furnace_pyrolysis.add(1000, item('minecraft:obsidian') * 2, item('minecraft:clay'), 1000)
+
+// Phytogenic Insolator:
+// Converts two input itemstacks into an output itemstack and optional output itemstack with a chance, costing power and
+// taking time based on the power cost.
+
+mods.thermalexpansion.insolator.removeByInput(item('minecraft:double_plant:4'))
+mods.thermalexpansion.insolator.removeByInput(item('thermalfoundation:fertilizer'))
+mods.thermalexpansion.insolator.removeByOutput(item('minecraft:melon_seeds'))
+mods.thermalexpansion.insolator.removeByOutput(item('minecraft:red_flower:6'))
+// mods.thermalexpansion.insolator.removeAll()
+
+mods.thermalexpansion.insolator.recipeBuilder()
+ .input(item('minecraft:clay'), item('minecraft:diamond'))
+ .output(item('minecraft:diamond') * 4)
+ .register()
+
+mods.thermalexpansion.insolator.recipeBuilder()
+ .input(item('minecraft:clay'), item('minecraft:gold_ingot') * 2)
+ .output(item('minecraft:clay'), item('minecraft:diamond'))
+ .chance(5)
+ .water(100)
+ .tree()
+ .energy(1000)
+ .register()
+
+
+mods.thermalexpansion.insolator.add(1000, 100, item('minecraft:obsidian'), item('minecraft:gold_ingot') * 2, item('minecraft:clay'), item('minecraft:diamond'), 5, InsolatorManager.Type.TREE)
+
+// Numismatic Dynamo - Lapidary Calibration:
+// Converts an input itemstack into power, taking time based on the power.
+
+mods.thermalexpansion.lapidary.removeByInput(item('minecraft:diamond'))
+// mods.thermalexpansion.lapidary.removeAll()
+
+mods.thermalexpansion.lapidary.add(item('minecraft:clay'), 1000)
+
+// Magmatic Dynamo:
+// Converts an input fluidstack into power, taking time based on the power.
+
+mods.thermalexpansion.magmatic.removeByInput(fluid('lava'))
+// mods.thermalexpansion.magmatic.removeAll()
+
+mods.thermalexpansion.magmatic.add(fluid('steam'), 100)
+
+// Numismatic Dynamo:
+// Converts an input itemstack into power, taking time based on the power.
+
+mods.thermalexpansion.numismatic.removeByInput(item('thermalfoundation:coin:69'))
+// mods.thermalexpansion.numismatic.removeAll()
+
+mods.thermalexpansion.numismatic.add(item('minecraft:clay'), 100)
+
+// Glacial Precipitator:
+// Converts an amount of water into a specific output itemstack, costing power and taking time based on the power cost.
+
+// mods.thermalexpansion.precipitator.removeByInput(fluid('water'))
+mods.thermalexpansion.precipitator.removeByOutput(item('minecraft:snowball'))
+// mods.thermalexpansion.precipitator.removeAll()
+
+mods.thermalexpansion.precipitator.recipeBuilder()
+ .output(item('minecraft:clay'))
+ .register()
+
+mods.thermalexpansion.precipitator.recipeBuilder()
+ .water(100)
+ .output(item('minecraft:clay'))
+ .energy(1000)
+ .register()
+
+
+mods.thermalexpansion.precipitator.add(1000, item('minecraft:obsidian'), 100)
+
+// Pulverizer:
+// Converts an input itemstack into an output itemstack and optional output itemstack with a chance, costing power and
+// taking time based on the power cost.
+
+mods.thermalexpansion.pulverizer.removeByInput(item('minecraft:emerald_ore'))
+mods.thermalexpansion.pulverizer.removeByOutput(item('minecraft:diamond'))
+mods.thermalexpansion.pulverizer.removeByOutput(item('thermalfoundation:material:772'))
+// mods.thermalexpansion.pulverizer.removeAll()
+
+mods.thermalexpansion.pulverizer.recipeBuilder()
+ .input(item('minecraft:diamond'))
+ .output(item('minecraft:clay'), item('minecraft:diamond'))
+ .chance(1)
+ .register()
+
+mods.thermalexpansion.pulverizer.recipeBuilder()
+ .input(item('minecraft:clay'))
+ .output(item('minecraft:gold_ingot'), item('minecraft:gold_ingot'))
+ .energy(1000)
+ .register()
+
+
+mods.thermalexpansion.pulverizer.add(1000, item('minecraft:obsidian'), item('minecraft:gold_ingot'), item('minecraft:gold_ingot'), 100)
+
+// Reactant Dynamo:
+// Converts an input itemstack and input fluidstack into power, taking time based on the power.
+
+mods.thermalexpansion.reactant.removeByInput(fluid('redstone'))
+mods.thermalexpansion.reactant.removeByInput(item('minecraft:blaze_powder'))
+mods.thermalexpansion.reactant.removeElementalFluid(fluid('cryotheum'))
+mods.thermalexpansion.reactant.removeElementalReactant(item('thermalfoundation:material:1024'))
+// mods.thermalexpansion.reactant.removeAll()
+
+mods.thermalexpansion.reactant.recipeBuilder()
+ .input(item('minecraft:diamond'))
+ .fluidInput(fluid('steam'))
+ .register()
+
+mods.thermalexpansion.reactant.recipeBuilder()
+ .input(item('minecraft:clay'))
+ .fluidInput(fluid('glowstone'))
+ .energy(100)
+ .register()
+
+
+mods.thermalexpansion.reactant.add(item('minecraft:clay'), fluid('steam'), 100)
+mods.thermalexpansion.reactant.addElementalFluid(fluid('glowstone'))
+mods.thermalexpansion.reactant.addElementalReactant(item('minecraft:clay'))
+mods.thermalexpansion.reactant.addElementalReactant(item('minecraft:gunpowder'))
+
+// Fractionating Still:
+// Converts an input fluidstack into an output fluidstack and optional output itemstack with chance, costing power and
+// taking time based on the power cost.
+
+mods.thermalexpansion.refinery.removeBioFuel(fluid('resin'))
+mods.thermalexpansion.refinery.removeByInput(fluid('resin'))
+mods.thermalexpansion.refinery.removeByOutput(fluid('refined_biofuel'))
+// mods.thermalexpansion.refinery.removeByOutput(item('thermalfoundation:material:771'))
+mods.thermalexpansion.refinery.removeFossilFuel(fluid('coal'))
+// mods.thermalexpansion.refinery.removeAll()
+// mods.thermalexpansion.refinery.removeAllBioFuels()
+// mods.thermalexpansion.refinery.removeAllFossilFuels()
+
+mods.thermalexpansion.refinery.recipeBuilder()
+ .fluidInput(fluid('water') * 100)
+ .fluidOutput(fluid('steam') * 80)
+ .register()
+
+mods.thermalexpansion.refinery.recipeBuilder()
+ .fluidInput(fluid('lava') * 100)
+ .fluidOutput(fluid('steam') * 150)
+ .output(item('minecraft:clay'))
+ .chance(25)
+ .energy(1000)
+ .register()
+
+
+mods.thermalexpansion.refinery.add(1000, fluid('ender') * 100, fluid('steam') * 150, item('minecraft:clay'), 25)
+mods.thermalexpansion.refinery.addBioFuel(fluid('coal'))
+mods.thermalexpansion.refinery.addFossilFuel(fluid('crude_oil'))
+
+// Fractionating Still - Alchemical Retort:
+// Converts an input fluidstack into an output fluidstack and optional output itemstack with chance, costing power and
+// taking time based on the power cost.
+
+mods.thermalexpansion.refinery_potion.removeByInput(fluid('potion_lingering').withNbt(['Potion': 'cofhcore:healing3']))
+mods.thermalexpansion.refinery_potion.removeByOutput(fluid('potion_splash').withNbt(['Potion': 'cofhcore:leaping4']))
+// mods.thermalexpansion.refinery_potion.removeAll()
+
+mods.thermalexpansion.refinery_potion.recipeBuilder()
+ .fluidInput(fluid('water') * 100)
+ .fluidOutput(fluid('steam') * 200)
+ .register()
+
+mods.thermalexpansion.refinery_potion.recipeBuilder()
+ .fluidInput(fluid('lava') * 100)
+ .fluidOutput(fluid('steam') * 30)
+ .output(item('minecraft:clay'))
+ .chance(75)
+ .energy(1000)
+ .register()
+
+
+mods.thermalexpansion.refinery_potion.add(1000, fluid('ender') * 100, fluid('steam') * 30, item('minecraft:clay'), 75)
+
+// Sawmill:
+// Converts an input itemstack into an output itemstack and optional output itemstack with a chance, costing power and
+// taking time based on the power cost.
+
+mods.thermalexpansion.sawmill.removeByInput(item('minecraft:pumpkin'))
+mods.thermalexpansion.sawmill.removeByOutput(item('minecraft:leather'))
+mods.thermalexpansion.sawmill.removeByOutput(item('thermalfoundation:material:800'))
+// mods.thermalexpansion.sawmill.removeAll()
+
+mods.thermalexpansion.sawmill.recipeBuilder()
+ .input(item('minecraft:diamond'))
+ .output(item('minecraft:gold_ingot') * 2)
+ .register()
+
+mods.thermalexpansion.sawmill.recipeBuilder()
+ .input(item('minecraft:clay') * 4)
+ .output(item('minecraft:gold_ingot'), item('minecraft:diamond'))
+ .chance(25)
+ .energy(1000)
+ .register()
+
+
+mods.thermalexpansion.sawmill.add(1000, item('minecraft:obsidian') * 4, item('minecraft:gold_ingot'), item('minecraft:diamond'), 25)
+
+// Induction Smelter:
+// Converts two input itemstacks into an output itemstack and optional output itemstack with a chance, costing power and
+// taking time based on the power cost.
+
+mods.thermalexpansion.smelter.removeByInput(ore('sand'))
+mods.thermalexpansion.smelter.removeByInput(item('minecraft:iron_ingot'))
+mods.thermalexpansion.smelter.removeByOutput(item('thermalfoundation:material:166'))
+// mods.thermalexpansion.smelter.removeAll()
+
+mods.thermalexpansion.smelter.recipeBuilder()
+ .input(item('minecraft:clay'), item('minecraft:diamond'))
+ .output(item('minecraft:diamond') * 4)
+ .register()
+
+mods.thermalexpansion.smelter.recipeBuilder()
+ .input(item('minecraft:clay'), item('minecraft:gold_ingot') * 2)
+ .output(item('minecraft:clay'), item('minecraft:diamond'))
+ .chance(5)
+ .energy(1000)
+ .register()
+
+
+// mods.thermalexpansion.smelter.add(1000, item('minecraft:obsidian'), item('minecraft:gold_ingot') * 2, item('minecraft:clay'), item('minecraft:diamond'), 5)
+
+// Steam Dynamo:
+// Converts an input itemstack into power, taking time based on the power.
+
+mods.thermalexpansion.steam.removeByInput(item('minecraft:coal:1'))
+// mods.thermalexpansion.steam.removeAll()
+
+mods.thermalexpansion.steam.add(item('minecraft:clay'), 100)
+
+// Arboreal Extractor:
+// Controls what items and blocks can be turned into what fluids. Output can be boosted via Fertilizer items.
+
+mods.thermalexpansion.tapper.removeBlockByInput(item('minecraft:log'))
+mods.thermalexpansion.tapper.removeItemByInput(item('minecraft:log:1'))
+// mods.thermalexpansion.tapper.removeAll()
+// mods.thermalexpansion.tapper.removeAllBlocks()
+// mods.thermalexpansion.tapper.removeAllItems()
+
+mods.thermalexpansion.tapper.addBlock(item('minecraft:clay'), fluid('lava') * 150)
+mods.thermalexpansion.tapper.addItem(item('minecraft:clay'), fluid('lava') * 300)
+
+// Arboreal Extractor Fertilizer:
+// Controls what items can be used in the fertilizer slot of the Arboreal Extractor Fertilizer and how effective they are.
+
+mods.thermalexpansion.tapper_fertilizer.remove(item('thermalfoundation:fertilizer:2'))
+// mods.thermalexpansion.tapper_fertilizer.removeAll()
+
+mods.thermalexpansion.tapper_fertilizer.add(item('minecraft:clay'), 1000)
+
+// Arboreal Extractor Tree Structures:
+// Controls what valid log blocks and leaf blocks are to define a tree structure which the Arboreal Extractor can function
+// on. The \"tree\" must contain some number of leaves adjacent to the log blocks to be valid.
+
+mods.thermalexpansion.tapper_tree.removeByLeaf(blockstate('minecraft:leaves', 'variant=birch'))
+mods.thermalexpansion.tapper_tree.removeByLog(blockstate('minecraft:log', 'variant=spruce'))
+// mods.thermalexpansion.tapper_tree.removeAll()
+
+mods.thermalexpansion.tapper_tree.add(blockstate('minecraft:clay'), blockstate('minecraft:gold_block'))
+
+// Fluid Transposer - Empty:
+// Converts an input itemstack into an output fluidstack and optional output itemstack with chance, costing power and
+// taking time based on the power cost.
+
+mods.thermalexpansion.transposer_extract.removeByInput(item('minecraft:sponge:1'))
+mods.thermalexpansion.transposer_extract.removeByOutput(fluid('seed_oil'))
+mods.thermalexpansion.transposer_extract.removeByOutput(item('minecraft:bowl'))
+// mods.thermalexpansion.transposer_extract.removeAll()
+
+mods.thermalexpansion.transposer_extract.recipeBuilder()
+ .input(item('minecraft:diamond') * 2)
+ .fluidOutput(fluid('water') * 100)
+ .register()
+
+mods.thermalexpansion.transposer_extract.recipeBuilder()
+ .input(item('minecraft:clay'))
+ .output(item('minecraft:diamond') * 2)
+ .fluidOutput(fluid('water') * 50)
+ .energy(1000)
+ .register()
+
+
+mods.thermalexpansion.transposer_extract.add(1000, item('minecraft:obsidian'), fluid('water') * 50, item('minecraft:diamond') * 2, 100)
+
+// Fluid Transposer - Fill:
+// Converts an input itemstack and input fluidstack into an output itemstack with chance, costing power and taking time
+// based on the power cost.
+
+mods.thermalexpansion.transposer_fill.removeByInput(fluid('glowstone'))
+mods.thermalexpansion.transposer_fill.removeByInput(item('minecraft:concrete_powder:3'))
+mods.thermalexpansion.transposer_fill.removeByOutput(item('minecraft:ice'))
+// mods.thermalexpansion.transposer_fill.removeAll()
+
+mods.thermalexpansion.transposer_fill.recipeBuilder()
+ .input(item('minecraft:diamond') * 2)
+ .fluidInput(fluid('water') * 100)
+ .register()
+
+mods.thermalexpansion.transposer_fill.recipeBuilder()
+ .input(item('minecraft:clay'))
+ .output(item('minecraft:diamond') * 2)
+ .fluidInput(fluid('water') * 50)
+ .energy(1000)
+ .register()
+
+
+mods.thermalexpansion.transposer_fill.add(1000, item('minecraft:obsidian'), fluid('water') * 50, item('minecraft:diamond') * 2, 100)
+
+// Insightful Condenser:
+// Collects experience orbs nearby, with the ability to increase the XP gained via catalyst itemstacks.
+
+mods.thermalexpansion.xp_collector.remove(item('minecraft:soul_sand'))
+// mods.thermalexpansion.xp_collector.removeAll()
+
+mods.thermalexpansion.xp_collector.add(item('minecraft:clay'), 100, 30)
+
diff --git a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RegistryDescription.java b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RegistryDescription.java
index 95482e8a6..d5926458f 100644
--- a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RegistryDescription.java
+++ b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RegistryDescription.java
@@ -22,7 +22,7 @@
* This will generate a link from the wiki to the source code of the specific file the class {@link RegistryDescription} annotates is in.
*
{@link #location()} is the name of a {@link com.cleanroommc.groovyscript.sandbox.LoadStage} and controls where all methods
* inside the {@link RegistryDescription} are generated.
- * {@link #reloadability()} ()} determines the status of the compat, defaulting to fully reloadable ({@link Reloadability#FULLY}).
+ * {@link #reloadability()} determines the status of the compat, defaulting to fully reloadable ({@link Reloadability#FULLY}).
* {@link #isFullyDocumented()} informs whether the {@link RegistryDescription} documents all relevant functionality.
* {@link #admonition()} is an array of admonition blocks to be generated at the top of the wiki page for additional information,
* commonly of the type {@link Admonition.Type#DANGER} to indicate important information.
diff --git a/src/main/java/com/cleanroommc/groovyscript/command/GSCommand.java b/src/main/java/com/cleanroommc/groovyscript/command/GSCommand.java
index c7d905054..df698edf5 100644
--- a/src/main/java/com/cleanroommc/groovyscript/command/GSCommand.java
+++ b/src/main/java/com/cleanroommc/groovyscript/command/GSCommand.java
@@ -124,7 +124,7 @@ public GSCommand() {
GSHandCommand.fluidInformation(messages, Arrays.stream(handler.getTankProperties())
.map(IFluidTankProperties::getContents)
.filter(Objects::nonNull)
- .collect(Collectors.toList()));
+ .collect(Collectors.toList()), prettyNbt);
}
}
@@ -132,7 +132,7 @@ public GSCommand() {
// if the block is a fluid, add the fluid's info
Fluid fluid = FluidRegistry.lookupFluidForBlock(block);
if (fluid != null) {
- GSHandCommand.fluidInformation(messages, new FluidStack(fluid, 1000));
+ GSHandCommand.fluidInformation(messages, new FluidStack(fluid, 1000), prettyNbt);
}
GSHandCommand.blockStateInformation(messages, blockState);
diff --git a/src/main/java/com/cleanroommc/groovyscript/command/GSHandCommand.java b/src/main/java/com/cleanroommc/groovyscript/command/GSHandCommand.java
index 45d88df6a..5f4a8595e 100644
--- a/src/main/java/com/cleanroommc/groovyscript/command/GSHandCommand.java
+++ b/src/main/java/com/cleanroommc/groovyscript/command/GSHandCommand.java
@@ -13,6 +13,7 @@
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.oredict.OreDictionary;
+import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
@@ -28,31 +29,37 @@ public static void itemInformation(List messages, @NotNull ItemS
String itemPretty = IngredientHelper.asGroovyCode(stack, true, prettyNbt);
String item = IngredientHelper.asGroovyCode(stack, false, prettyNbt);
- messages.add(new TextComponentString("Item:"));
- messages.add(TextCopyable.string(item, itemPretty).build());
+ messages.add(new TextComponentString("Item:")
+ .setStyle(new Style().setColor(TextFormatting.LIGHT_PURPLE).setBold(true)));
+ messages.add(TextCopyable.string(item, " - " + itemPretty).build());
GuiScreen.setClipboardString(item);
String copy = stack.getItem().getTranslationKey(stack);
- messages.add(TextCopyable.string(copy, "Translation key: " + TextFormatting.YELLOW + copy).build());
+
+ messages.add(new TextComponentString("Translation key:")
+ .setStyle(new Style().setColor(TextFormatting.LIGHT_PURPLE).setBold(true)));
+
+ messages.add(TextCopyable.string(copy, " - " + TextFormatting.YELLOW + copy).build());
}
public static void blockStateInformation(List messages, @NotNull IBlockState state) {
String copyText = IngredientHelper.asGroovyCode(state, false);
- messages.add(new TextComponentString("Block state:"));
- messages.add(TextCopyable.string(copyText, IngredientHelper.asGroovyCode(state, true)).build());
+ messages.add(new TextComponentString("Block state:")
+ .setStyle(new Style().setColor(TextFormatting.LIGHT_PURPLE).setBold(true)));
+ messages.add(TextCopyable.string(copyText, " - " + IngredientHelper.asGroovyCode(state, true)).build());
}
- public static void fluidInformation(List messages, @NotNull FluidStack stack) {
- fluidInformation(messages, Collections.singletonList(stack));
+ public static void fluidInformation(List messages, @NotNull FluidStack stack, boolean prettyNbt) {
+ fluidInformation(messages, Collections.singletonList(stack), prettyNbt);
}
- public static void fluidInformation(List messages, @NotNull List fluidStacks) {
+ public static void fluidInformation(List messages, @NotNull List fluidStacks, boolean prettyNbt) {
if (fluidStacks.isEmpty()) return;
messages.add(new TextComponentString("Fluids:")
- .setStyle(new Style().setColor(TextFormatting.GREEN)));
+ .setStyle(new Style().setColor(TextFormatting.LIGHT_PURPLE).setBold(true)));
for (FluidStack stack : fluidStacks) {
- String s = IngredientHelper.asGroovyCode(stack, true);
- messages.add(TextCopyable.string(s, " - " + stack.getFluid().getName()).build());
+ String copyText = IngredientHelper.asGroovyCode(stack, false, prettyNbt);
+ messages.add(TextCopyable.string(copyText, " - " + IngredientHelper.asGroovyCode(stack, true, false)).build());
}
}
@@ -61,7 +68,7 @@ public static void oredictInformation(List messages, ItemStack s
int[] ids = OreDictionary.getOreIDs(stack);
if (ids.length > 0) {
messages.add(new TextComponentString("Ore Dictionaries:")
- .setStyle(new Style().setColor(TextFormatting.GREEN)));
+ .setStyle(new Style().setColor(TextFormatting.LIGHT_PURPLE).setBold(true)));
for (int id : ids) {
String oreName = OreDictionary.getOreName(id);
s = IngredientHelper.asGroovyCode(oreName, true);
@@ -74,8 +81,11 @@ public static void oredictInformation(List messages, ItemStack s
public static void tileInformation(List messages, TileEntity tile) {
NBTTagCompound nbt = tile.serializeNBT();
String copyText = NbtHelper.toGroovyCode(nbt, false, false);
+ String msg = NbtHelper.toGroovyCode(nbt, true, true);
+ int trimLocation = StringUtils.ordinalIndexOf(msg, "\n", 8);
- messages.add(new TextComponentString("Tile NBT:"));
- messages.add(TextCopyable.string(copyText, NbtHelper.toGroovyCode(nbt, true, true)).build());
+ messages.add(new TextComponentString("Tile NBT:")
+ .setStyle(new Style().setColor(TextFormatting.LIGHT_PURPLE).setBold(true)));
+ messages.add(TextCopyable.string(copyText, trimLocation == -1 ? msg : msg.substring(0, trimLocation) + "\n\u00A7c(trimmed)").build());
}
}
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 89fb07ed4..599c14da7 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java
@@ -90,7 +90,7 @@ public class ModSupport implements IDynamicGroovyProperty {
public static final GroovyContainer ROOTS = new InternalModContainer<>("roots", "Roots 3", Roots::new);
public static final GroovyContainer RUSTIC = new InternalModContainer<>("rustic", "Rustic", Rustic::new);
public static final GroovyContainer THAUMCRAFT = new InternalModContainer<>("thaumcraft", "Thaumcraft", Thaumcraft::new, "tc", "thaum");
- public static final GroovyContainer THERMAL_EXPANSION = new InternalModContainer<>("thermalexpansion", "Thermal Expansion", ThermalExpansion::new, "te", "thermal");
+ public static final GroovyContainer THERMAL_EXPANSION = new InternalModContainer<>("thermalexpansion", "Thermal Expansion", ThermalExpansion::new, "thermal");
public static final GroovyContainer TINKERS_COMPLEMENT = new InternalModContainer<>("tcomplement", "Tinkers Complement", TinkersComplement::new, "tcomp", "tinkerscomplement");
public static final GroovyContainer TINKERS_CONSTRUCT = new InternalModContainer<>("tconstruct", "Tinkers' Construct", TinkersConstruct::new, "ticon", "tinkersconstruct");
public static final GroovyContainer WOOT = new InternalModContainer<>("woot", "Woot", Woot::new);
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/chisel/Carving.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/chisel/Carving.java
index 0a6e08784..808de8951 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/chisel/Carving.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/chisel/Carving.java
@@ -7,6 +7,7 @@
import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper;
+import com.cleanroommc.groovyscript.registry.AbstractReloadableStorage;
import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
import net.minecraft.item.ItemStack;
import net.minecraft.util.SoundEvent;
@@ -15,9 +16,7 @@
import team.chisel.api.carving.ICarvingGroup;
import team.chisel.api.carving.ICarvingRegistry;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
@RegistryDescription(
category = RegistryDescription.Category.ENTRIES,
@@ -26,16 +25,8 @@
)
public class Carving extends VirtualizedRegistry> {
- private List> sounds;
- private List groupBackup;
- private List groupScripted;
-
- public Carving() {
- super();
- this.sounds = new ArrayList<>();
- this.groupBackup = new ArrayList<>();
- this.groupScripted = new ArrayList<>();
- }
+ private final AbstractReloadableStorage groupStorage = new AbstractReloadableStorage<>();
+ private final AbstractReloadableStorage> soundStorage = new AbstractReloadableStorage<>();
private static ICarvingRegistry getRegistry() {
if (CarvingUtils.getChiselRegistry() == null) {
@@ -53,13 +44,10 @@ public void onReload() {
removeScripted().forEach(pair -> getRegistry().removeVariation(pair.getValue(), pair.getKey()));
restoreFromBackup().forEach(pair -> getRegistry().addVariation(pair.getKey(), CarvingUtils.variationFor(pair.getValue(), 0)));
- this.sounds.forEach(pair -> getRegistry().setVariationSound(pair.getKey(), pair.getValue()));
- this.groupBackup.forEach(group -> getRegistry().addGroup(CarvingUtils.getDefaultGroupFor(group)));
- this.groupScripted.forEach(getRegistry()::removeGroup);
+ groupStorage.restoreFromBackup().forEach(group -> getRegistry().addGroup(CarvingUtils.getDefaultGroupFor(group)));
+ groupStorage.removeScripted().forEach(getRegistry()::removeGroup);
- this.sounds = new ArrayList<>();
- this.groupBackup = new ArrayList<>();
- this.groupScripted = new ArrayList<>();
+ soundStorage.restoreFromBackup().forEach(pair -> getRegistry().setVariationSound(pair.getKey(), pair.getValue()));
}
@MethodDescription(example = {@Example("'demo', item('minecraft:diamond_block')"),
@@ -108,7 +96,7 @@ public void setSound(String group, SoundEvent sound) {
@MethodDescription(type = MethodDescription.Type.VALUE)
public void setSound(ICarvingGroup group, SoundEvent sound) {
getRegistry().setVariationSound(group.getName(), sound);
- this.sounds.add(Pair.of(group.getName(), group.getSound()));
+ soundStorage.addBackup(Pair.of(group.getName(), group.getSound()));
}
@MethodDescription(example = @Example("'demo'"), type = MethodDescription.Type.ADDITION)
@@ -121,7 +109,7 @@ public void addGroup(String groupName) {
return;
}
getRegistry().addGroup(CarvingUtils.getDefaultGroupFor(groupName));
- this.groupScripted.add(groupName);
+ groupStorage.addScripted(groupName);
}
@MethodDescription(example = @Example("'blockDiamond'"))
@@ -134,14 +122,14 @@ public void removeGroup(String groupName) {
return;
}
getRegistry().removeGroup(groupName);
- this.groupBackup.add(groupName);
+ groupStorage.addBackup(groupName);
}
@MethodDescription(example = @Example(commented = true))
public void removeAll() {
getRegistry().getSortedGroupNames().forEach(name -> {
getRegistry().removeGroup(name);
- this.groupBackup.add(name);
+ groupStorage.addBackup(name);
});
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/inspirations/AnvilSmashing.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/inspirations/AnvilSmashing.java
index ca601f554..d2eeaf6cd 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/inspirations/AnvilSmashing.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/inspirations/AnvilSmashing.java
@@ -6,6 +6,7 @@
import com.cleanroommc.groovyscript.core.mixin.inspirations.InspirationsRegistryAccessor;
import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
+import com.cleanroommc.groovyscript.registry.AbstractReloadableStorage;
import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
import knightminer.inspirations.library.InspirationsRegistry;
import net.minecraft.block.Block;
@@ -14,34 +15,14 @@
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Map;
import java.util.stream.Collectors;
@RegistryDescription
public class AnvilSmashing extends VirtualizedRegistry> {
- private Collection> blockBackup;
- private Collection> blockScripted;
- private Collection materialBackup;
-
- private void addBlockBackup(Pair recipe) {
- if (blockScripted.stream().anyMatch(r -> r == recipe)) return;
- blockBackup.add(recipe);
- }
-
- public void addBlockScripted(Pair recipe) {
- blockScripted.add(recipe);
- }
-
- public AnvilSmashing() {
- super();
- blockBackup = new ArrayList<>();
- blockScripted = new ArrayList<>();
- materialBackup = new ArrayList<>();
- }
-
+ private final AbstractReloadableStorage> blockStorage = new AbstractReloadableStorage<>();
+ private final AbstractReloadableStorage materialStorage = new AbstractReloadableStorage<>();
@RecipeBuilderDescription(example = {
@Example(".input(blockstate('minecraft:diamond_block')).output(blockstate('minecraft:clay'))"),
@@ -55,12 +36,9 @@ public RecipeBuilder recipeBuilder() {
public void onReload() {
removeScripted().forEach(pair -> InspirationsRegistryAccessor.getAnvilSmashing().remove(pair.getKey(), pair.getValue()));
restoreFromBackup().forEach(pair -> InspirationsRegistryAccessor.getAnvilSmashing().put(pair.getKey(), pair.getValue()));
- blockBackup.forEach(pair -> InspirationsRegistryAccessor.getAnvilSmashingBlocks().remove(pair.getKey(), pair.getValue()));
- blockScripted.forEach(pair -> InspirationsRegistryAccessor.getAnvilSmashingBlocks().put(pair.getKey(), pair.getValue()));
- materialBackup.forEach(mat -> InspirationsRegistryAccessor.getAnvilBreaking().add(mat));
- blockBackup = new ArrayList<>();
- blockScripted = new ArrayList<>();
- materialBackup = new ArrayList<>();
+ blockStorage.removeScripted().forEach(pair -> InspirationsRegistryAccessor.getAnvilSmashingBlocks().remove(pair.getKey(), pair.getValue()));
+ blockStorage.restoreFromBackup().forEach(pair -> InspirationsRegistryAccessor.getAnvilSmashingBlocks().put(pair.getKey(), pair.getValue()));
+ materialStorage.restoreFromBackup().forEach(mat -> InspirationsRegistryAccessor.getAnvilBreaking().add(mat));
}
@MethodDescription(type = MethodDescription.Type.ADDITION)
@@ -71,7 +49,7 @@ public void add(IBlockState input, IBlockState output) {
@MethodDescription(type = MethodDescription.Type.ADDITION)
public void add(Block input, IBlockState output) {
- addBlockScripted(Pair.of(input, output));
+ blockStorage.addScripted(Pair.of(input, output));
InspirationsRegistry.registerAnvilSmashing(input, output);
}
@@ -86,7 +64,7 @@ public boolean remove(IBlockState input, IBlockState output) {
@MethodDescription
public boolean remove(Block input, IBlockState output) {
if (!InspirationsRegistryAccessor.getAnvilSmashingBlocks().get(input).equals(output)) return false;
- addBlockBackup(Pair.of(input, output));
+ blockStorage.addBackup(Pair.of(input, output));
InspirationsRegistryAccessor.getAnvilSmashingBlocks().remove(input, output);
return true;
}
@@ -94,7 +72,7 @@ public boolean remove(Block input, IBlockState output) {
@MethodDescription(description = "groovyscript.wiki.inspirations.anvil_smashing.remove_material")
public boolean remove(Material material) {
if (!InspirationsRegistryAccessor.getAnvilBreaking().contains(material)) return false;
- materialBackup.add(material);
+ materialStorage.addBackup(material);
InspirationsRegistryAccessor.getAnvilBreaking().remove(material);
return true;
}
@@ -114,7 +92,7 @@ public void removeByInput(Block input) {
for (Map.Entry recipe : InspirationsRegistryAccessor.getAnvilSmashingBlocks().entrySet().stream()
.filter(r -> r.getKey().equals(input))
.collect(Collectors.toList())) {
- addBlockBackup(Pair.of(recipe.getKey(), recipe.getValue()));
+ blockStorage.addBackup(Pair.of(recipe.getKey(), recipe.getValue()));
InspirationsRegistryAccessor.getAnvilSmashingBlocks().remove(recipe.getKey(), recipe.getValue());
}
}
@@ -130,7 +108,7 @@ public void removeByOutput(IBlockState output) {
for (Map.Entry recipe : InspirationsRegistryAccessor.getAnvilSmashingBlocks().entrySet().stream()
.filter(r -> r.getValue().equals(output))
.collect(Collectors.toList())) {
- addBlockBackup(Pair.of(recipe.getKey(), recipe.getValue()));
+ blockStorage.addBackup(Pair.of(recipe.getKey(), recipe.getValue()));
InspirationsRegistryAccessor.getAnvilSmashingBlocks().remove(recipe.getKey(), recipe.getValue());
}
}
@@ -139,9 +117,9 @@ public void removeByOutput(IBlockState output) {
public void removeAll() {
InspirationsRegistryAccessor.getAnvilSmashing().forEach((a, b) -> addBackup(Pair.of(a, b)));
InspirationsRegistryAccessor.getAnvilSmashing().clear();
- InspirationsRegistryAccessor.getAnvilSmashingBlocks().forEach((a, b) -> addBlockBackup(Pair.of(a, b)));
+ InspirationsRegistryAccessor.getAnvilSmashingBlocks().forEach((a, b) -> blockStorage.addBackup(Pair.of(a, b)));
InspirationsRegistryAccessor.getAnvilSmashingBlocks().clear();
- materialBackup.addAll(InspirationsRegistryAccessor.getAnvilBreaking());
+ InspirationsRegistryAccessor.getAnvilBreaking().forEach(materialStorage::addBackup);
InspirationsRegistryAccessor.getAnvilBreaking().clear();
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/mekanism/Infusion.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/mekanism/Infusion.java
index 7df52354d..d2d261094 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/mekanism/Infusion.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/mekanism/Infusion.java
@@ -7,6 +7,7 @@
import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.registry.AbstractReloadableStorage;
import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
import mekanism.api.infuse.InfuseObject;
import mekanism.api.infuse.InfuseRegistry;
@@ -16,7 +17,10 @@
import net.minecraft.util.ResourceLocation;
import org.apache.commons.lang3.tuple.Pair;
-import java.util.*;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Locale;
+import java.util.Map;
import java.util.stream.Collectors;
@RegistryDescription(
@@ -30,14 +34,7 @@
)
public class Infusion extends VirtualizedRegistry> {
- private List> objectBackup;
- private List> objectScripted;
-
- public Infusion() {
- super();
- this.objectBackup = new ArrayList<>();
- this.objectScripted = new ArrayList<>();
- }
+ private AbstractReloadableStorage> objectStorage = new AbstractReloadableStorage<>();
public static InfusionItems infusion(InfuseType type) {
return new InfusionItems(type);
@@ -61,11 +58,8 @@ public void onReload() {
removeScripted().forEach(pair -> InfuseRegistry.getInfuseMap().put(pair.getKey(), pair.getValue()));
restoreFromBackup().forEach(pair -> InfuseRegistry.getInfuseMap().remove(pair.getKey()));
- this.objectBackup.forEach(pair -> InfuseRegistry.getObjectMap().put(pair.getKey(), pair.getValue()));
- this.objectScripted.forEach(pair -> InfuseRegistry.getObjectMap().remove(pair.getKey()));
-
- this.objectBackup = new ArrayList<>();
- this.objectScripted = new ArrayList<>();
+ objectStorage.restoreFromBackup().forEach(pair -> InfuseRegistry.getObjectMap().put(pair.getKey(), pair.getValue()));
+ objectStorage.removeScripted().forEach(pair -> InfuseRegistry.getObjectMap().remove(pair.getKey()));
}
@MethodDescription(example = @Example("'groovy_example', resource('placeholdername:blocks/example')"), type = MethodDescription.Type.ADDITION, priority = 500)
@@ -95,7 +89,7 @@ public boolean removeType(String name) {
}, type = MethodDescription.Type.ADDITION)
public void add(InfuseType type, int amount, ItemStack item) {
InfuseObject object = new InfuseObject(type, amount);
- this.objectScripted.add(Pair.of(item, object));
+ objectStorage.addScripted(Pair.of(item, object));
InfuseRegistry.registerInfuseObject(item, object);
}
@@ -129,7 +123,7 @@ public void add(String type, int amount, Collection ingredients) {
@MethodDescription(example = @Example("ore('dustDiamond')"))
public void remove(IIngredient item) {
for (Map.Entry entry : InfuseRegistry.getObjectMap().entrySet().stream().filter(x -> item.test(x.getKey())).collect(Collectors.toList())) {
- objectBackup.add(Pair.of(entry.getKey(), entry.getValue()));
+ objectStorage.addBackup(Pair.of(entry.getKey(), entry.getValue()));
InfuseRegistry.getObjectMap().remove(entry.getKey());
}
}
@@ -154,7 +148,7 @@ public void remove(Collection ingredients) {
})
public void removeByType(InfuseType type) {
for (Map.Entry entry : InfuseRegistry.getObjectMap().entrySet().stream().filter(x -> x.getValue().type == type).collect(Collectors.toList())) {
- objectBackup.add(Pair.of(entry.getKey(), entry.getValue()));
+ objectStorage.addBackup(Pair.of(entry.getKey(), entry.getValue()));
InfuseRegistry.getObjectMap().remove(entry.getKey());
}
}
@@ -168,7 +162,7 @@ public void removeByType(String type) {
public void removeAll() {
InfuseRegistry.getInfuseMap().forEach((l, r) -> addBackup(Pair.of(l, r)));
InfuseRegistry.getInfuseMap().clear();
- InfuseRegistry.getObjectMap().forEach((l, r) -> objectBackup.add(Pair.of(l, r)));
+ InfuseRegistry.getObjectMap().forEach((l, r) -> objectStorage.addBackup(Pair.of(l, r)));
InfuseRegistry.getObjectMap().clear();
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/tcomplement/Melter.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/tcomplement/Melter.java
index 6fd28aab9..1ca4f9bc7 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/tcomplement/Melter.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/tcomplement/Melter.java
@@ -8,63 +8,29 @@
import com.cleanroommc.groovyscript.compat.mods.tinkersconstruct.recipe.MeltingRecipeRegistry;
import com.cleanroommc.groovyscript.core.mixin.tcomplement.TCompRegistryAccessor;
import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.registry.AbstractReloadableStorage;
import knightminer.tcomplement.library.IBlacklist;
import net.minecraft.item.ItemStack;
import net.minecraft.util.NonNullList;
import net.minecraftforge.fluids.FluidStack;
import slimeknights.tconstruct.library.smeltery.MeltingRecipe;
-import java.util.ArrayList;
-import java.util.Collection;
-
public class Melter extends MeltingRecipeRegistry {
@GroovyBlacklist
- protected Collection backupBlacklist = new ArrayList<>();
- @GroovyBlacklist
- protected Collection scriptedBlacklist = new ArrayList<>();
+ protected AbstractReloadableStorage backupStorage = new AbstractReloadableStorage<>();
public MeltingRecipeBuilder recipeBuilder() {
return new MeltingRecipeBuilder(this, "Tinkers Complement Melter override");
}
- @GroovyBlacklist
- public void addBackupBlacklist(IBlacklist blacklist) {
- if (this.scriptedBlacklist.stream().anyMatch(r -> compareBlacklist(r, blacklist))) return;
- this.backupBlacklist.add(blacklist);
- }
-
- @GroovyBlacklist
- public void addScriptedBlacklist(IBlacklist blacklist) {
- this.scriptedBlacklist.add(blacklist);
- }
-
- @GroovyBlacklist
- public boolean compareBlacklist(IBlacklist list, IBlacklist list1) {
- return list == list1;
- }
-
- @GroovyBlacklist
- protected Collection restoreFromBackupBlacklist() {
- Collection backup = this.backupBlacklist;
- this.backupBlacklist = new ArrayList<>();
- return backupBlacklist;
- }
-
- @GroovyBlacklist
- protected Collection removeScriptedBlacklist() {
- Collection scripted = this.scriptedBlacklist;
- this.scriptedBlacklist = new ArrayList<>();
- return scripted;
- }
-
@Override
@GroovyBlacklist
public void onReload() {
removeScripted().forEach(TCompRegistryAccessor.getMeltingOverrides()::remove);
- removeScriptedBlacklist().forEach(TCompRegistryAccessor.getMeltingBlacklist()::remove);
+ backupStorage.removeScripted().forEach(TCompRegistryAccessor.getMeltingBlacklist()::remove);
restoreFromBackup().forEach(TCompRegistryAccessor.getMeltingOverrides()::add);
- restoreFromBackupBlacklist().forEach(TCompRegistryAccessor.getMeltingBlacklist()::add);
+ backupStorage.restoreFromBackup().forEach(TCompRegistryAccessor.getMeltingBlacklist()::add);
}
public IBlacklist addBlacklist(IIngredient ingredient) {
@@ -87,7 +53,7 @@ public void add(MeltingRecipe recipe) {
public void addBlacklist(IBlacklist blacklist) {
if (blacklist == null) return;
- addScriptedBlacklist(blacklist);
+ backupStorage.addScripted(blacklist);
TCompRegistryAccessor.getMeltingBlacklist().add(blacklist);
}
@@ -100,7 +66,7 @@ public boolean remove(MeltingRecipe recipe) {
public boolean removeBlacklist(IBlacklist blacklist) {
if (blacklist == null) return false;
- addBackupBlacklist(blacklist);
+ backupStorage.addBackup(blacklist);
TCompRegistryAccessor.getMeltingBlacklist().remove(blacklist);
return true;
}
@@ -108,7 +74,7 @@ public boolean removeBlacklist(IBlacklist blacklist) {
public boolean removeFromBlacklist(ItemStack item) {
if (TCompRegistryAccessor.getMeltingBlacklist().removeIf(b -> {
boolean found = b.matches(item);
- if (found) addBackupBlacklist(b);
+ if (found) backupStorage.addBackup(b);
return found;
})) return true;
@@ -173,7 +139,7 @@ public void removeAll() {
}
public void removeAllBlacklists() {
- TCompRegistryAccessor.getMeltingBlacklist().forEach(this::addBackupBlacklist);
+ TCompRegistryAccessor.getMeltingBlacklist().forEach(backupStorage::addBackup);
TCompRegistryAccessor.getMeltingBlacklist().forEach(TCompRegistryAccessor.getMeltingBlacklist()::remove);
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thaumcraft/Research.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thaumcraft/Research.java
index 5702767ee..609ad7d05 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thaumcraft/Research.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thaumcraft/Research.java
@@ -3,6 +3,7 @@
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.compat.mods.thaumcraft.aspect.AspectStack;
+import com.cleanroommc.groovyscript.registry.AbstractReloadableStorage;
import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
@@ -18,27 +19,18 @@
import thaumcraft.common.lib.research.ScanEnchantment;
import thaumcraft.common.lib.research.ScanPotion;
-import java.util.ArrayList;
-import java.util.Collection;
-
@RegistryDescription
public class Research extends VirtualizedRegistry {
- protected Collection scanBackup;
- protected Collection scanScripted;
-
- public Research() {
- scanBackup = new ArrayList<>();
- scanScripted = new ArrayList<>();
- }
+ protected AbstractReloadableStorage scanStorage = new AbstractReloadableStorage<>();
@Override
public void onReload() {
removeScripted().forEach(x -> ResearchCategories.researchCategories.remove(x.key));
restoreFromBackup().forEach(x -> ResearchCategories.researchCategories.put(x.key, x));
- scanBackup.clear();
- scanScripted.clear();
+ scanStorage.removeScripted();
+ scanStorage.restoreFromBackup();
}
private void addCategory(ResearchCategory category) {
@@ -62,7 +54,7 @@ public void addCategory(String key, String researchkey, AspectList formula, Stri
}
private void addScannable(IScanThing scanThing) {
- scanScripted.add(scanThing);
+ scanStorage.addScripted(scanThing);
ScanningManager.addScannableThing(scanThing);
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/Brewer.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/Brewer.java
deleted file mode 100644
index 860f74943..000000000
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/Brewer.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package com.cleanroommc.groovyscript.compat.mods.thermalexpansion;
-
-import cofh.core.inventory.ComparableItemStackValidatedNBT;
-import cofh.core.util.helpers.FluidHelper;
-import cofh.thermalexpansion.util.managers.machine.BrewerManager;
-import com.cleanroommc.groovyscript.api.GroovyBlacklist;
-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.thermalexpansion.BrewerManagerAccessor;
-import com.cleanroommc.groovyscript.helper.Alias;
-import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper;
-import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
-import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
-import net.minecraft.item.ItemStack;
-import net.minecraftforge.fluids.FluidStack;
-import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-public class Brewer extends VirtualizedRegistry {
-
- private final List validationSetScripted = new ArrayList<>();
- private final List validationSetBackup = new ArrayList<>();
- private final List validationFluidsScripted = new ArrayList<>();
- private final List validationFluidsBackup = new ArrayList<>();
-
- public Brewer() {
- super(Alias.generateOf("Imbuer").andGenerateOfClass(Brewer.class));
- }
-
- public RecipeBuilder recipeBuilder() {
- return new RecipeBuilder();
- }
-
- public void removeByInput(IIngredient ingredient, FluidStack input) {
- if (GroovyLog.msg("Error removing Thermal Expansion Brewer recipe").error()
- .add(IngredientHelper.isEmpty(ingredient), () -> "item input must not be empty")
- .add(IngredientHelper.isEmpty(input), () -> "fluid input must not be empty")
- .postIfNotEmpty()) {
- boolean found = false;
- for (ItemStack itemStack : ingredient.getMatchingStacks()) {
- BrewerManager.BrewerRecipe recipe = BrewerManager.removeRecipe(itemStack, input);
- if (recipe != null) {
- addBackup(recipe);
- validationSetBackup.add(BrewerManager.convertInput(itemStack));
- validationFluidsBackup.add(input.getFluid().getName());
- found = true;
- }
- }
- if (!found) {
- GroovyLog.msg("Error removing Thermal Expansion Brewer recipe")
- .add("could not find recipe for {} and {}", ingredient, input)
- .error()
- .post();
- }
- }
- }
-
- @Override
- @GroovyBlacklist
- @ApiStatus.Internal
- public void onReload() {
- Map, BrewerManager.BrewerRecipe> map = BrewerManagerAccessor.getRecipeMap();
- removeScripted().forEach(recipe -> map.values().removeIf(r -> r == recipe));
- restoreFromBackup().forEach(r -> map.put(Arrays.asList(BrewerManager.convertInput(r.getInput()).hashCode(), FluidHelper.getFluidHash(r.getInputFluid())), r));
- validationSetScripted.forEach(input -> BrewerManagerAccessor.getValidationSet().remove(input));
- validationFluidsScripted.forEach(input -> BrewerManagerAccessor.getValidationFluids().remove(input));
- validationSetBackup.forEach(input -> BrewerManagerAccessor.getValidationSet().add(input));
- validationFluidsBackup.forEach(input -> BrewerManagerAccessor.getValidationFluids().add(input));
- validationSetScripted.clear();
- validationFluidsScripted.clear();
- validationSetBackup.clear();
- validationFluidsBackup.clear();
- }
-
- public static class RecipeBuilder extends AbstractRecipeBuilder {
-
- private int energy;
-
- public RecipeBuilder energy(int energy) {
- this.energy = energy;
- return this;
- }
-
- @Override
- public String getErrorMsg() {
- return "Error adding Thermal Expansion Brewer recipe";
- }
-
- @Override
- public void validate(GroovyLog.Msg msg) {
- validateItems(msg, 1, 1, 0, 0);
- validateFluids(msg, 1, 1, 1, 1);
- if (energy <= 0) energy = 4800;
- }
-
- @Override
- public @Nullable BrewerManager.BrewerRecipe register() {
- if (!validate()) return null;
- BrewerManager.BrewerRecipe recipe = null;
- for (ItemStack itemStack : input.get(0).getMatchingStacks()) {
- BrewerManager.BrewerRecipe recipe1 = BrewerManager.addRecipe(energy, itemStack, fluidInput.get(0), fluidOutput.get(0));
- Brewer brewer = ModSupport.THERMAL_EXPANSION.get().brewer;
- brewer.addScripted(recipe1);
- brewer.validationSetScripted.add(BrewerManager.convertInput(itemStack));
- brewer.validationFluidsScripted.add(fluidInput.get(0).getFluid().getName());
- if (recipe == null) {
- recipe = recipe1;
- }
- }
- return recipe;
- }
- }
-}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/Crucible.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/Crucible.java
deleted file mode 100644
index 4876d71c7..000000000
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/Crucible.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package com.cleanroommc.groovyscript.compat.mods.thermalexpansion;
-
-import cofh.core.inventory.ComparableItemStackValidatedNBT;
-import cofh.thermalexpansion.util.managers.machine.CrucibleManager;
-import com.cleanroommc.groovyscript.api.GroovyBlacklist;
-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.thermalexpansion.CrucibleManagerAccessor;
-import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper;
-import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
-import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
-import net.minecraft.item.ItemStack;
-import net.minecraftforge.fluids.FluidRegistry;
-import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-public class Crucible extends VirtualizedRegistry {
-
- private final List lavaSetScripted = new ArrayList<>();
- private final List lavaSetBackup = new ArrayList<>();
-
- @Override
- @GroovyBlacklist
- @ApiStatus.Internal
- public void onReload() {
- Map map = CrucibleManagerAccessor.getRecipeMap();
- removeScripted().forEach(recipe -> map.values().removeIf(r -> r == recipe));
- restoreFromBackup().forEach(r -> map.put(CrucibleManager.convertInput(r.getInput()), r));
- lavaSetScripted.forEach(input -> CrucibleManagerAccessor.getLavaSet().remove(input));
- lavaSetBackup.forEach(input -> CrucibleManagerAccessor.getLavaSet().add(input));
- lavaSetScripted.clear();
- lavaSetBackup.clear();
- }
-
- public RecipeBuilder recipeBuilder() {
- return new RecipeBuilder();
- }
-
- public void removeByInput(IIngredient input) {
- if (IngredientHelper.isEmpty(input)) {
- GroovyLog.msg("Error removing Thermal Expansion Brewer recipe")
- .add("input must not be empty")
- .error()
- .post();
- return;
- }
-
- boolean found = false;
- for (ItemStack itemStack : input.getMatchingStacks()) {
- CrucibleManager.CrucibleRecipe recipe = CrucibleManager.removeRecipe(itemStack);
- if (recipe != null) {
- addBackup(recipe);
- if (recipe.getOutput().getFluid() == FluidRegistry.LAVA) {
- lavaSetBackup.add(CrucibleManager.convertInput(recipe.getInput()));
- }
- found = true;
- }
- }
- if (!found) {
- GroovyLog.msg("Error removing Thermal Expansion Brewer recipe")
- .add("could not find recipe for {}", input)
- .error()
- .post();
- }
-
- }
-
- public static class RecipeBuilder extends AbstractRecipeBuilder {
-
- private int energy;
-
- public RecipeBuilder energy(int energy) {
- this.energy = energy;
- return this;
- }
-
- @Override
- public String getErrorMsg() {
- return "Error adding Thermal Expansion Crucible recipe";
- }
-
- @Override
- public void validate(GroovyLog.Msg msg) {
- validateItems(msg, 1, 1, 0, 0);
- validateFluids(msg, 0, 0, 1, 1);
- if (energy <= 0) energy = 10000;
- }
-
- @Override
- public @Nullable CrucibleManager.CrucibleRecipe register() {
- if (!validate()) return null;
- CrucibleManager.CrucibleRecipe recipe = null;
- for (ItemStack itemStack : input.get(0).getMatchingStacks()) {
- CrucibleManager.CrucibleRecipe recipe1 = CrucibleManager.addRecipe(energy, itemStack, fluidOutput.get(0));
- Crucible crucible = ModSupport.THERMAL_EXPANSION.get().crucible;
- crucible.addScripted(recipe1);
- if (recipe1.getOutput().getFluid() == FluidRegistry.LAVA) {
- crucible.lavaSetScripted.add(CrucibleManager.convertInput(itemStack));
- }
- if (recipe == null) recipe = recipe1;
- }
- return recipe;
- }
- }
-}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/Pulverizer.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/Pulverizer.java
deleted file mode 100644
index 5554c24ef..000000000
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/Pulverizer.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package com.cleanroommc.groovyscript.compat.mods.thermalexpansion;
-
-import cofh.core.inventory.ComparableItemStackValidated;
-import cofh.thermalexpansion.util.managers.machine.PulverizerManager;
-import cofh.thermalexpansion.util.managers.machine.PulverizerManager.PulverizerRecipe;
-import com.cleanroommc.groovyscript.api.GroovyBlacklist;
-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.thermalexpansion.PulverizerManagerAccessor;
-import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
-import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper;
-import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
-import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
-import net.minecraft.item.ItemStack;
-import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Map;
-
-public class Pulverizer extends VirtualizedRegistry {
-
- public RecipeBuilder recipeBuilder() {
- return new RecipeBuilder();
- }
-
- @Override
- @GroovyBlacklist
- @ApiStatus.Internal
- public void onReload() {
- Map map = PulverizerManagerAccessor.getRecipeMap();
- removeScripted().forEach(recipe -> map.values().removeIf(r -> r == recipe));
- restoreFromBackup().forEach(r -> map.put(PulverizerManager.convertInput(r.getInput()), r));
- }
-
- public void add(PulverizerRecipe recipe) {
- if (!PulverizerManager.recipeExists(recipe.getInput())) {
- PulverizerManagerAccessor.getRecipeMap().put(PulverizerManager.convertInput(recipe.getInput()), recipe);
- addScripted(recipe);
- }
- }
-
- public PulverizerRecipe add(int energy, ItemStack input, ItemStack primaryOutput, ItemStack secondaryOutput, int secondaryChance) {
- PulverizerRecipe recipe = PulverizerManager.addRecipe(energy, input, primaryOutput, secondaryOutput, secondaryChance);
- if (recipe != null) {
- addScripted(recipe);
- }
- return recipe;
- }
-
- public boolean remove(PulverizerRecipe recipe) {
- if (PulverizerManagerAccessor.getRecipeMap().values().removeIf(r -> r == recipe)) {
- addBackup(recipe);
- return true;
- }
- return false;
- }
-
- public void removeByInput(IIngredient input) {
- if (IngredientHelper.isEmpty(input)) {
- GroovyLog.msg("Error removing Thermal Expansion Pulverizer recipe")
- .add("input must not be empty")
- .error()
- .post();
- return;
- }
- boolean found = false;
- for (ItemStack stack : input.getMatchingStacks()) {
- PulverizerRecipe recipe = PulverizerManager.removeRecipe(stack);
- if (recipe != null) {
- found = true;
- addBackup(recipe);
- }
- }
- if (!found) {
- GroovyLog.msg("Error removing Thermal Expansion Pulverizer recipe")
- .add("could not find recipe for {}", input)
- .error()
- .post();
- }
- }
-
- public SimpleObjectStream streamRecipes() {
- return new SimpleObjectStream<>(PulverizerManagerAccessor.getRecipeMap().values()).setRemover(this::remove);
- }
-
- public void removeAll() {
- for (PulverizerManager.PulverizerRecipe recipe : PulverizerManager.getRecipeList()) {
- addBackup(PulverizerManager.removeRecipe(recipe.getInput()));
- }
- }
-
- public static class RecipeBuilder extends AbstractRecipeBuilder {
-
- private int energy;
- private ItemStack secOutput;
- private int chance;
-
- public RecipeBuilder energy(int energy) {
- this.energy = energy;
- return this;
- }
-
- public RecipeBuilder secondaryOutput(ItemStack itemStack, int chance) {
- this.secOutput = itemStack;
- this.chance = chance;
- return this;
- }
-
- public RecipeBuilder secondaryOutput(ItemStack itemStack) {
- return secondaryOutput(itemStack, 100);
- }
-
- @Override
- public String getErrorMsg() {
- return "Error adding Thermal Pulverizer recipe";
- }
-
- @Override
- public void validate(GroovyLog.Msg msg) {
- validateItems(msg, 1, 1, 1, 1);
- validateFluids(msg);
- if (secOutput == null) secOutput = ItemStack.EMPTY;
- if (secOutput.isEmpty()) {
- chance = 0;
- } else if (chance <= 0) {
- chance = 100;
- }
- if (energy <= 0) energy = 3000;
- }
-
- @Override
- public @Nullable PulverizerManager.PulverizerRecipe register() {
- if (!validate()) return null;
- PulverizerManager.PulverizerRecipe recipe = null;
- for (ItemStack itemStack : input.get(0).getMatchingStacks()) {
- PulverizerRecipe recipe1 = ModSupport.THERMAL_EXPANSION.get().pulverizer.add(energy, itemStack, output.get(0), secOutput, chance);
- if (recipe == null) recipe = recipe1;
- }
- return recipe;
- }
- }
-}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/ThermalExpansion.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/ThermalExpansion.java
index 7f6300426..f1f26d0b3 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/ThermalExpansion.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/ThermalExpansion.java
@@ -1,17 +1,100 @@
package com.cleanroommc.groovyscript.compat.mods.thermalexpansion;
+import cofh.thermalexpansion.util.managers.machine.CompactorManager;
+import com.cleanroommc.groovyscript.api.IGameObjectParser;
import com.cleanroommc.groovyscript.compat.mods.ModPropertyContainer;
+import com.cleanroommc.groovyscript.compat.mods.thermalexpansion.device.*;
+import com.cleanroommc.groovyscript.compat.mods.thermalexpansion.dynamo.*;
+import com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine.*;
+import com.cleanroommc.groovyscript.gameobjects.GameObjectHandler;
+
+import java.util.Arrays;
+import java.util.Locale;
public class ThermalExpansion extends ModPropertyContainer {
- public final Pulverizer pulverizer = new Pulverizer();
public final Brewer brewer = new Brewer();
+ public final Centrifuge centrifuge = new Centrifuge();
+ public final CentrifugeMobs centrifugeMob = new CentrifugeMobs();
+ public final Charger charger = new Charger();
+ public final Compactor compactor = new Compactor();
+ public final Compression compression = new Compression();
+ public final Coolant coolant = new Coolant();
public final Crucible crucible = new Crucible();
+ public final Diffuser diffuser = new Diffuser();
+ public final Enchanter enchanter = new Enchanter();
+ public final Enervation enervation = new Enervation();
+ public final Extruder extruder = new Extruder();
+ public final Factorizer factorizer = new Factorizer();
+ public final Fisher fisher = new Fisher();
+ public final FisherBait fisherBait = new FisherBait();
+ public final Furnace furnace = new Furnace();
+ public final FurnacePyrolysis furnacePyrolysis = new FurnacePyrolysis();
+ public final Insolator insolator = new Insolator();
+ public final Lapidary lapidary = new Lapidary();
+ public final Magmatic magmatic = new Magmatic();
+ public final Numismatic numismatic = new Numismatic();
+ public final Precipitator precipitator = new Precipitator();
+ public final Pulverizer pulverizer = new Pulverizer();
+ public final Reactant reactant = new Reactant();
+ public final Refinery refinery = new Refinery();
+ public final RefineryPotion refineryPotion = new RefineryPotion();
+ public final Sawmill sawmill = new Sawmill();
+ public final Smelter smelter = new Smelter();
+ public final Steam steam = new Steam();
+ public final Tapper tapper = new Tapper();
+ public final TapperFertilizer tapperFertilizer = new TapperFertilizer();
+ public final TapperTree tapperTree = new TapperTree();
+ public final TransposerExtract transposerExtract = new TransposerExtract();
+ public final TransposerFill transposerFill = new TransposerFill();
+ public final XpCollector xpCollector = new XpCollector();
+
public ThermalExpansion() {
- addRegistry(pulverizer);
addRegistry(brewer);
+ addRegistry(centrifuge);
+ addRegistry(centrifugeMob);
+ addRegistry(charger);
+ addRegistry(compactor);
+ addRegistry(compression);
+ addRegistry(coolant);
addRegistry(crucible);
+ addRegistry(diffuser);
+ addRegistry(enchanter);
+ addRegistry(enervation);
+ addRegistry(extruder);
+ addRegistry(factorizer);
+ addRegistry(fisher);
+ addRegistry(fisherBait);
+ addRegistry(furnace);
+ addRegistry(furnacePyrolysis);
+ addRegistry(insolator);
+ addRegistry(lapidary);
+ addRegistry(magmatic);
+ addRegistry(numismatic);
+ addRegistry(precipitator);
+ addRegistry(pulverizer);
+ addRegistry(reactant);
+ addRegistry(refinery);
+ addRegistry(refineryPotion);
+ addRegistry(sawmill);
+ addRegistry(smelter);
+ addRegistry(steam);
+ addRegistry(tapper);
+ addRegistry(tapperFertilizer);
+ addRegistry(tapperTree);
+ addRegistry(transposerExtract);
+ addRegistry(transposerFill);
+ addRegistry(xpCollector);
+ }
+
+ @Override
+ public void initialize() {
+ GameObjectHandler.builder("mode", CompactorManager.Mode.class)
+ .mod("thermalexpansion")
+ .parser(IGameObjectParser.wrapEnum(CompactorManager.Mode.class, false))
+ .completerOfNamed(() -> Arrays.asList(CompactorManager.Mode.values()), v -> v.name().toUpperCase(Locale.ROOT))
+ .register();
}
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Coolant.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Coolant.java
new file mode 100644
index 000000000..33afd6014
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Coolant.java
@@ -0,0 +1,93 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.device;
+
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.documentation.annotations.Admonition;
+import com.cleanroommc.groovyscript.api.documentation.annotations.Example;
+import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
+import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.CoolantManagerAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import com.github.bsideup.jabel.Desugar;
+import mezz.jei.api.IGuiHelper;
+import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.ApiStatus;
+
+@RegistryDescription(category = RegistryDescription.Category.ENTRIES,
+ admonition = @Admonition(value = "groovyscript.wiki.thermalexpansion.coolant.note0", type = Admonition.Type.WARNING))
+public class Coolant extends VirtualizedRegistry {
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> {
+ CoolantManagerAccessor.getCoolantMap().keySet().removeIf(r -> r.equals(recipe.fluid()));
+ CoolantManagerAccessor.getCoolantFactorMap().keySet().removeIf(r -> r.equals(recipe.fluid()));
+ });
+ restoreFromBackup().forEach(r -> {
+ CoolantManagerAccessor.getCoolantMap().put(r.fluid(), r.rf());
+ CoolantManagerAccessor.getCoolantFactorMap().put(r.fluid(), r.factor());
+ });
+ }
+
+ /**
+ * This validation of rf is required because of {@link cofh.thermalexpansion.plugins.jei.device.coolant.CoolantWrapper#CoolantWrapper(IGuiHelper, FluidStack, int, int) CoolantWrapper}
+ * specifically, if the code {@code energy / (TileDynamoCompression.basePower * 10)} returns 0, JEI cannot display it.
+ */
+ public void add(CoolantRecipe recipe) {
+ if (recipe.rf < 4000) {
+ GroovyLog.get().error("cannot create a coolant entry with less than 4000 rf, yet tried to create an entry for fluid {} producing {}", recipe.fluid, recipe.rf);
+ return;
+ }
+ CoolantManagerAccessor.getCoolantMap().put(recipe.fluid(), recipe.rf());
+ CoolantManagerAccessor.getCoolantFactorMap().put(recipe.fluid(), recipe.factor());
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("fluid('lava'), 4000, 30"))
+ public void add(FluidStack fluid, int rf, int factor) {
+ add(new CoolantRecipe(fluid.getFluid().getName(), rf, factor));
+ }
+
+ public boolean remove(String fluid) {
+ if (CoolantManagerAccessor.getCoolantMap().containsKey(fluid) && CoolantManagerAccessor.getCoolantFactorMap().containsKey(fluid)) {
+ addBackup(new CoolantRecipe(fluid, CoolantManagerAccessor.getCoolantMap().removeInt(fluid), CoolantManagerAccessor.getCoolantFactorMap().removeInt(fluid)));
+ return true;
+ }
+ return false;
+ }
+
+ public boolean remove(CoolantRecipe recipe) {
+ if (CoolantManagerAccessor.getCoolantMap().containsKey(recipe.fluid()) && CoolantManagerAccessor.getCoolantFactorMap().containsKey(recipe.fluid())) {
+ addBackup(new CoolantRecipe(recipe.fluid(), CoolantManagerAccessor.getCoolantMap().removeInt(recipe.fluid()), CoolantManagerAccessor.getCoolantFactorMap().removeInt(recipe.fluid())));
+ return true;
+ }
+ return false;
+ }
+
+ @MethodDescription(example = @Example("fluid('cryotheum')"))
+ public boolean remove(FluidStack input) {
+ return remove(input.getFluid().getName());
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(CoolantManagerAccessor.getCoolantMap().keySet()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ CoolantManagerAccessor.getCoolantMap().keySet().stream().filter(CoolantManagerAccessor.getCoolantFactorMap()::containsKey)
+ .forEach(x -> addBackup(new CoolantRecipe(x, CoolantManagerAccessor.getCoolantMap().getInt(x), CoolantManagerAccessor.getCoolantFactorMap().getInt(x))));
+ CoolantManagerAccessor.getCoolantMap().clear();
+ CoolantManagerAccessor.getCoolantFactorMap().clear();
+ }
+
+ @Desugar
+ public record CoolantRecipe(String fluid, int rf, int factor) {
+
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Diffuser.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Diffuser.java
new file mode 100644
index 000000000..9c7b9f828
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Diffuser.java
@@ -0,0 +1,99 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.device;
+
+import cofh.core.inventory.ComparableItemStack;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.documentation.annotations.Example;
+import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
+import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.DiffuserManagerAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import com.github.bsideup.jabel.Desugar;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RegistryDescription(category = RegistryDescription.Category.ENTRIES)
+public class Diffuser extends VirtualizedRegistry {
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> {
+ DiffuserManagerAccessor.getReagentAmpMap().keySet().removeIf(r -> r.equals(recipe.stack()));
+ DiffuserManagerAccessor.getReagentDurMap().keySet().removeIf(r -> r.equals(recipe.stack()));
+ });
+ restoreFromBackup().forEach(r -> {
+ DiffuserManagerAccessor.getReagentAmpMap().put(r.stack(), r.amplifier());
+ DiffuserManagerAccessor.getReagentDurMap().put(r.stack(), r.duration());
+ });
+ }
+
+ public void add(DiffuserRecipe recipe) {
+ DiffuserManagerAccessor.getReagentAmpMap().put(recipe.stack(), recipe.amplifier());
+ DiffuserManagerAccessor.getReagentDurMap().put(recipe.stack(), recipe.duration());
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("item('minecraft:clay'), 2, 30"))
+ public void add(ItemStack stack, int amplifier, int duration) {
+ add(new DiffuserRecipe(new ComparableItemStack(stack), amplifier, duration));
+ }
+
+ public boolean remove(ComparableItemStack stack) {
+ if (DiffuserManagerAccessor.getReagentAmpMap().containsKey(stack) && DiffuserManagerAccessor.getReagentDurMap().containsKey(stack)) {
+ addBackup(new DiffuserRecipe(stack));
+ DiffuserManagerAccessor.getReagentAmpMap().remove(stack);
+ DiffuserManagerAccessor.getReagentDurMap().remove(stack);
+ return true;
+ }
+ return false;
+ }
+
+ public boolean remove(DiffuserRecipe recipe) {
+ if (DiffuserManagerAccessor.getReagentAmpMap().containsKey(recipe.stack()) && DiffuserManagerAccessor.getReagentDurMap().containsKey(recipe.stack())) {
+ addBackup(new DiffuserRecipe(recipe.stack()));
+ DiffuserManagerAccessor.getReagentAmpMap().remove(recipe.stack());
+ DiffuserManagerAccessor.getReagentDurMap().remove(recipe.stack());
+ return true;
+ }
+ return false;
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:redstone')"))
+ public boolean remove(ItemStack input) {
+ return remove(new ComparableItemStack(input));
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ List list = DiffuserManagerAccessor.getReagentAmpMap().keySet().stream()
+ .filter(DiffuserManagerAccessor.getReagentDurMap()::containsKey)
+ .map(DiffuserRecipe::new)
+ .collect(Collectors.toList());
+ return new SimpleObjectStream<>(list).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ DiffuserManagerAccessor.getReagentAmpMap().keySet().stream()
+ .filter(DiffuserManagerAccessor.getReagentDurMap()::containsKey)
+ .map(DiffuserRecipe::new)
+ .forEach(this::addBackup);
+ DiffuserManagerAccessor.getReagentAmpMap().clear();
+ DiffuserManagerAccessor.getReagentDurMap().clear();
+ }
+
+ @Desugar
+ public record DiffuserRecipe(ComparableItemStack stack, int amplifier, int duration) {
+
+ public DiffuserRecipe(ComparableItemStack stack) {
+ this(stack, DiffuserManagerAccessor.getReagentAmpMap().get(stack), DiffuserManagerAccessor.getReagentDurMap().get(stack));
+ }
+
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Factorizer.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Factorizer.java
new file mode 100644
index 000000000..cdb0dbce3
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Factorizer.java
@@ -0,0 +1,206 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.device;
+
+import cofh.core.inventory.ComparableItemStackValidated;
+import cofh.thermalexpansion.util.managers.device.FactorizerManager;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.FactorizerManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.FactorizerRecipeAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import com.google.common.primitives.Booleans;
+import net.minecraft.item.ItemStack;
+import org.apache.commons.lang3.tuple.Pair;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@RegistryDescription
+public class Factorizer extends VirtualizedRegistry> {
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('minecraft:clay') * 7).output(item('minecraft:book') * 2).combine().split()"),
+ @Example(".input(item('minecraft:planks:*') * 4).output(item('minecraft:crafting_table')).combine()")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> map(recipe.getKey()).values().removeIf(r -> r.equals(recipe.getValue())));
+ restoreFromBackup().forEach(r -> map(r.getKey()).put(new ComparableItemStackValidated(r.getValue().getInput()), r.getValue()));
+ }
+
+ private Map map(boolean isSplit) {
+ return isSplit ? FactorizerManagerAccessor.getRecipeMapReverse() : FactorizerManagerAccessor.getRecipeMap();
+ }
+
+ public void add(boolean isSplit, FactorizerManager.FactorizerRecipe recipe) {
+ map(isSplit).put(new ComparableItemStackValidated(recipe.getInput()), recipe);
+ addScripted(Pair.of(isSplit, recipe));
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION)
+ public FactorizerManager.FactorizerRecipe add(boolean combine, boolean split, IIngredient input, ItemStack output) {
+ return recipeBuilder()
+ .combine(combine)
+ .split(split)
+ .input(input)
+ .output(output)
+ .register();
+ }
+
+ public void add(FactorizerManager.FactorizerRecipe recipe) {
+ add(true, recipe);
+ add(false, recipe);
+ }
+
+ public boolean remove(boolean isSplit, FactorizerManager.FactorizerRecipe recipe) {
+ return map(isSplit).values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(Pair.of(isSplit, recipe));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ public boolean remove(FactorizerManager.FactorizerRecipe recipe) {
+ boolean hasRemoved = remove(false, recipe);
+ hasRemoved = remove(true, recipe) || hasRemoved;
+ return hasRemoved;
+ }
+
+ @MethodDescription(example = @Example("false, item('minecraft:diamond')"))
+ public boolean removeByInput(boolean isSplit, IIngredient input) {
+ return map(isSplit).values().removeIf(r -> {
+ if (input.test(r.getInput())) {
+ addBackup(Pair.of(isSplit, r));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:coal:1')"))
+ public boolean removeByInput(IIngredient input) {
+ // done this way so both remove operations are called
+ boolean hasRemoved = removeByInput(false, input);
+ hasRemoved = removeByInput(true, input) || hasRemoved;
+ return hasRemoved;
+ }
+
+ @MethodDescription(example = @Example(value = "false, item('minecraft:coal:1')", commented = true))
+ public boolean removeByOutput(boolean isSplit, IIngredient output) {
+ return map(isSplit).values().removeIf(r -> {
+ if (output.test(r.getOutput())) {
+ addBackup(Pair.of(isSplit, r));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(description = "groovyscript.wiki.removeByOutput", example = @Example("item('minecraft:emerald_block')"))
+ public boolean removeByOutput(IIngredient output) {
+ // done this way so both remove operations are called
+ boolean hasRemoved = removeByOutput(false, output);
+ hasRemoved = removeByOutput(true, output) || hasRemoved;
+ return hasRemoved;
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(Booleans.asList(true, false).stream().map(this::map).map(Map::values).flatMap(Collection::stream).collect(Collectors.toList()))
+ .setRemover(this::remove);
+ }
+
+ @MethodDescription(example = @Example(value = "true", commented = true))
+ public void removeByType(boolean isSplit) {
+ map(isSplit).values().forEach(x -> addBackup(Pair.of(isSplit, x)));
+ map(isSplit).clear();
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ removeByType(true);
+ removeByType(false);
+ }
+
+ @Property(property = "input", valid = @Comp("1"))
+ @Property(property = "output", valid = @Comp("1"))
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property
+ private boolean combine;
+ @Property
+ private boolean split;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder combine(boolean combine) {
+ this.combine = combine;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder combine() {
+ this.combine = !combine;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder split(boolean split) {
+ this.split = split;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder split() {
+ this.split = !split;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Factorizer recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 1, 1, 1, 1);
+ validateFluids(msg);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable FactorizerManager.FactorizerRecipe register() {
+ if (!validate()) return null;
+ FactorizerManager.FactorizerRecipe recipe = null;
+
+ for (ItemStack itemStack : input.get(0).getMatchingStacks()) {
+ if (combine) {
+ FactorizerManager.FactorizerRecipe recipe1 = FactorizerRecipeAccessor.createFactorizerRecipe(itemStack, output.get(0));
+ ModSupport.THERMAL_EXPANSION.get().factorizer.add(false, recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ if (split) {
+ FactorizerManager.FactorizerRecipe recipe1 = FactorizerRecipeAccessor.createFactorizerRecipe(output.get(0), itemStack);
+ ModSupport.THERMAL_EXPANSION.get().factorizer.add(true, recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ }
+ return recipe;
+ }
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Fisher.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Fisher.java
new file mode 100644
index 000000000..d1f3e8517
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Fisher.java
@@ -0,0 +1,98 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.device;
+
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.Example;
+import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
+import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.FisherManagerAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import com.github.bsideup.jabel.Desugar;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+
+@RegistryDescription(category = RegistryDescription.Category.ENTRIES)
+public class Fisher extends VirtualizedRegistry {
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ // not sure why this isn't stored as a Map, having to manage two lists is rather annoying.
+ removeScripted().forEach(recipe -> {
+ int index = FisherManagerAccessor.getFishList().indexOf(recipe.fish());
+ FisherManagerAccessor.getFishList().remove(index);
+ FisherManagerAccessor.setTotalWeight(FisherManagerAccessor.getTotalWeight() - FisherManagerAccessor.getWeightList().remove(index));
+ });
+ restoreFromBackup().forEach(r -> {
+ FisherManagerAccessor.getFishList().add(r.fish());
+ FisherManagerAccessor.getWeightList().add(r.weight());
+ FisherManagerAccessor.setTotalWeight(FisherManagerAccessor.getTotalWeight() + r.weight());
+ });
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void afterScriptLoad() {
+ // if the total weight is 0, then when `FisherManager.getFish()` calls `nextInt` we would implode
+ FisherManagerAccessor.setTotalWeight(1);
+ }
+
+ public void add(FisherRecipe recipe) {
+ FisherManagerAccessor.getFishList().add(recipe.fish());
+ FisherManagerAccessor.getWeightList().add(recipe.weight());
+ FisherManagerAccessor.setTotalWeight(FisherManagerAccessor.getTotalWeight() + recipe.weight());
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("item('minecraft:clay'), 100"))
+ public void add(ItemStack fish, int weight) {
+ add(new FisherRecipe(fish, weight));
+ }
+
+ public boolean remove(ItemStack itemStack) {
+ return FisherManagerAccessor.getFishList().removeIf(r -> {
+ if (itemStack.isItemEqual(r)) {
+ int weight = FisherManagerAccessor.getWeightList().remove(FisherManagerAccessor.getFishList().indexOf(r));
+ addBackup(new FisherRecipe(r, weight));
+ FisherManagerAccessor.setTotalWeight(FisherManagerAccessor.getTotalWeight() + weight);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:fish:0')"))
+ public boolean remove(IIngredient input) {
+ return FisherManagerAccessor.getFishList().removeIf(r -> {
+ if (input.test(r)) {
+ int weight = FisherManagerAccessor.getWeightList().remove(FisherManagerAccessor.getFishList().indexOf(r));
+ addBackup(new FisherRecipe(r, weight));
+ FisherManagerAccessor.setTotalWeight(FisherManagerAccessor.getTotalWeight() + weight);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(FisherManagerAccessor.getFishList())
+ .setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ FisherManagerAccessor.getFishList().forEach(x -> addBackup(new FisherRecipe(x, FisherManagerAccessor.getWeightList().remove(FisherManagerAccessor.getFishList().indexOf(x)))));
+ FisherManagerAccessor.getFishList().clear();
+ FisherManagerAccessor.setTotalWeight(0);
+ }
+
+ @Desugar
+ public record FisherRecipe(ItemStack fish, int weight) {
+
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/FisherBait.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/FisherBait.java
new file mode 100644
index 000000000..ce731a1ab
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/FisherBait.java
@@ -0,0 +1,75 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.device;
+
+import cofh.core.inventory.ComparableItemStack;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.Example;
+import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
+import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.FisherManagerAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import com.github.bsideup.jabel.Desugar;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+
+@RegistryDescription(category = RegistryDescription.Category.ENTRIES)
+public class FisherBait extends VirtualizedRegistry {
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> FisherManagerAccessor.getBaitMap().keySet().removeIf(r -> r.isItemEqual(recipe.bait())));
+ restoreFromBackup().forEach(r -> FisherManagerAccessor.getBaitMap().put(r.bait(), r.multiplier()));
+ }
+
+ public void add(FisherRecipe recipe) {
+ FisherManagerAccessor.getBaitMap().put(recipe.bait(), recipe.multiplier());
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("item('minecraft:clay'), 100"))
+ public void add(ItemStack stack, int multiplier) {
+ add(new FisherRecipe(new ComparableItemStack(stack), multiplier));
+ }
+
+ public boolean remove(ComparableItemStack stack) {
+ return FisherManagerAccessor.getBaitMap().keySet().removeIf(r -> {
+ if (stack.isItemEqual(r)) {
+ addBackup(new FisherRecipe(r, FisherManagerAccessor.getBaitMap().get(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('thermalfoundation:bait:2')"))
+ public boolean remove(IIngredient input) {
+ return FisherManagerAccessor.getBaitMap().keySet().removeIf(r -> {
+ if (input.test(r.toItemStack())) {
+ addBackup(new FisherRecipe(r, FisherManagerAccessor.getBaitMap().get(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(FisherManagerAccessor.getBaitMap().keySet())
+ .setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ FisherManagerAccessor.getBaitMap().keySet().forEach(x -> addBackup(new FisherRecipe(x, FisherManagerAccessor.getBaitMap().get(x))));
+ FisherManagerAccessor.getBaitMap().clear();
+ }
+
+ @Desugar
+ public record FisherRecipe(ComparableItemStack bait, int multiplier) {
+
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Tapper.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Tapper.java
new file mode 100644
index 000000000..6ceb308b4
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/Tapper.java
@@ -0,0 +1,168 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.device;
+
+import cofh.core.util.BlockWrapper;
+import cofh.core.util.ItemWrapper;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.Admonition;
+import com.cleanroommc.groovyscript.api.documentation.annotations.Example;
+import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
+import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.TapperManagerAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.registry.AbstractReloadableStorage;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import com.github.bsideup.jabel.Desugar;
+import net.minecraft.block.state.IBlockState;
+import net.minecraft.item.ItemBlock;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.ApiStatus;
+
+import java.util.stream.Collectors;
+
+@RegistryDescription(
+ admonition = @Admonition("groovyscript.wiki.thermalexpansion.tapper.note0")
+)
+public class Tapper extends VirtualizedRegistry {
+
+ private final AbstractReloadableStorage blockStorage = new AbstractReloadableStorage<>();
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> TapperManagerAccessor.getItemMap().entrySet().removeIf(r -> r.getKey().equals(recipe.itemWrapper()) && r.getValue().equals(recipe.fluidStack())));
+ restoreFromBackup().forEach(r -> TapperManagerAccessor.getItemMap().put(r.itemWrapper(), r.fluidStack()));
+ blockStorage.removeScripted().forEach(r -> TapperManagerAccessor.getBlockMap().put(r.blockWrapper(), r.fluidStack()));
+ blockStorage.restoreFromBackup().forEach(r -> TapperManagerAccessor.getBlockMap().remove(r.blockWrapper()));
+ }
+
+ public void addItem(TapperItemRecipe recipe) {
+ TapperManagerAccessor.getItemMap().put(recipe.itemWrapper(), recipe.fluidStack());
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("item('minecraft:clay'), fluid('lava') * 300"))
+ public void addItem(ItemStack itemStack, FluidStack fluidStack) {
+ addItem(new TapperItemRecipe(new ItemWrapper(itemStack), fluidStack));
+ }
+
+ public void addBlock(TapperBlockRecipe recipe) {
+ TapperManagerAccessor.getBlockMap().put(recipe.blockWrapper(), recipe.fluidStack());
+ blockStorage.addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("item('minecraft:clay'), fluid('lava') * 150"))
+ public void addBlock(ItemStack itemStack, FluidStack fluidStack) {
+ if (itemStack.getItem() instanceof ItemBlock itemBlock) {
+ addBlock(new TapperBlockRecipe(new BlockWrapper(itemBlock.getBlock(), itemStack.getMetadata()), fluidStack));
+ } else {
+ GroovyLog.get().debug("couldnt add a block recipe for {} because it was not an ItemBlock", itemStack);
+ }
+ }
+
+ public boolean remove(ItemWrapper recipe) {
+ return TapperManagerAccessor.getItemMap().keySet().removeIf(r -> {
+ if (r.equals(recipe)) {
+ addBackup(new TapperItemRecipe(r, TapperManagerAccessor.getItemMap().get(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ public boolean removeItem(TapperItemRecipe recipe) {
+ return TapperManagerAccessor.getItemMap().keySet().removeIf(r -> {
+ if (r.equals(recipe.itemWrapper())) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:log:1')"))
+ public boolean removeItemByInput(IIngredient input) {
+ return TapperManagerAccessor.getItemMap().entrySet().removeIf(r -> {
+ if (input.test(r.getValue()) || input.test(new ItemStack(r.getKey().item, r.getKey().metadata))) {
+ addBackup(new TapperItemRecipe(r.getKey(), r.getValue()));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ public boolean removeBlock(BlockWrapper wrapper) {
+ return TapperManagerAccessor.getBlockMap().entrySet().removeIf(r -> {
+ if (r.getKey().equals(wrapper)) {
+ blockStorage.addBackup(new TapperBlockRecipe(r.getKey(), r.getValue()));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ public boolean removeBlock(IBlockState state) {
+ return removeBlock(new BlockWrapper(state));
+ }
+
+ public boolean removeBlock(TapperBlockRecipe recipe) {
+ return removeBlock(recipe.blockWrapper());
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:log')"))
+ public boolean removeBlockByInput(IIngredient input) {
+ return TapperManagerAccessor.getBlockMap().entrySet().removeIf(r -> {
+ if (input.test(r.getValue())) {
+ blockStorage.addBackup(new TapperBlockRecipe(r.getKey(), r.getValue()));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(TapperManagerAccessor.getItemMap().entrySet().stream().map(x -> new TapperItemRecipe(x.getKey(), x.getValue())).collect(Collectors.toList()))
+ .setRemover(this::removeItem);
+ }
+
+ @MethodDescription(description = "groovyscript.wiki.streamRecipes", type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamBlockRecipes() {
+ return new SimpleObjectStream<>(TapperManagerAccessor.getBlockMap().entrySet().stream().map(x -> new TapperBlockRecipe(x.getKey(), x.getValue())).collect(Collectors.toList()))
+ .setRemover(this::removeBlock);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAllItems() {
+ TapperManagerAccessor.getItemMap().forEach((key, value) -> addBackup(new TapperItemRecipe(key, value)));
+ TapperManagerAccessor.getItemMap().clear();
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAllBlocks() {
+ TapperManagerAccessor.getBlockMap().forEach((key, value) -> blockStorage.addBackup(new TapperBlockRecipe(key, value)));
+ TapperManagerAccessor.getBlockMap().clear();
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ TapperManagerAccessor.getItemMap().forEach((key, value) -> addBackup(new TapperItemRecipe(key, value)));
+ TapperManagerAccessor.getItemMap().clear();
+ TapperManagerAccessor.getBlockMap().forEach((key, value) -> blockStorage.addBackup(new TapperBlockRecipe(key, value)));
+ TapperManagerAccessor.getBlockMap().clear();
+ }
+
+ @Desugar
+ public record TapperItemRecipe(ItemWrapper itemWrapper, FluidStack fluidStack) {
+
+ }
+
+ @Desugar
+ public record TapperBlockRecipe(BlockWrapper blockWrapper, FluidStack fluidStack) {
+
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/TapperFertilizer.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/TapperFertilizer.java
new file mode 100644
index 000000000..55a765baa
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/TapperFertilizer.java
@@ -0,0 +1,75 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.device;
+
+import cofh.core.inventory.ComparableItemStack;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.Example;
+import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
+import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.TapperManagerAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import com.github.bsideup.jabel.Desugar;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+
+@RegistryDescription(category = RegistryDescription.Category.ENTRIES)
+public class TapperFertilizer extends VirtualizedRegistry {
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> TapperManagerAccessor.getFertilizerMap().keySet().removeIf(r -> r.isItemEqual(recipe.bait())));
+ restoreFromBackup().forEach(r -> TapperManagerAccessor.getFertilizerMap().put(r.bait(), r.multiplier()));
+ }
+
+ public void add(TapperRecipe recipe) {
+ TapperManagerAccessor.getFertilizerMap().put(recipe.bait(), recipe.multiplier());
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("item('minecraft:clay'), 1000"))
+ public void add(ItemStack stack, int multiplier) {
+ add(new TapperRecipe(new ComparableItemStack(stack), multiplier));
+ }
+
+ public boolean remove(ComparableItemStack stack) {
+ return TapperManagerAccessor.getFertilizerMap().keySet().removeIf(r -> {
+ if (stack.isItemEqual(r)) {
+ addBackup(new TapperRecipe(r, TapperManagerAccessor.getFertilizerMap().get(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('thermalfoundation:fertilizer:2')"))
+ public boolean remove(IIngredient input) {
+ return TapperManagerAccessor.getFertilizerMap().keySet().removeIf(r -> {
+ if (input.test(r.toItemStack())) {
+ addBackup(new TapperRecipe(r, TapperManagerAccessor.getFertilizerMap().get(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(TapperManagerAccessor.getFertilizerMap().keySet())
+ .setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ TapperManagerAccessor.getFertilizerMap().keySet().forEach(x -> addBackup(new TapperRecipe(x, TapperManagerAccessor.getFertilizerMap().get(x))));
+ TapperManagerAccessor.getFertilizerMap().clear();
+ }
+
+ @Desugar
+ public record TapperRecipe(ComparableItemStack bait, int multiplier) {
+
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/TapperTree.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/TapperTree.java
new file mode 100644
index 000000000..36f2ff43f
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/TapperTree.java
@@ -0,0 +1,101 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.device;
+
+import cofh.core.util.BlockWrapper;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.documentation.annotations.Example;
+import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
+import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.TapperManagerAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import com.github.bsideup.jabel.Desugar;
+import net.minecraft.block.state.IBlockState;
+import org.jetbrains.annotations.ApiStatus;
+
+import java.util.Map;
+
+@RegistryDescription(category = RegistryDescription.Category.ENTRIES)
+public class TapperTree extends VirtualizedRegistry {
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> TapperManagerAccessor.getLeafMap().entries().removeIf(r -> r.getKey().equals(recipe.log()) && r.getValue().equals(recipe.leaf())));
+ restoreFromBackup().forEach(r -> TapperManagerAccessor.getLeafMap().put(r.log(), r.leaf()));
+ }
+
+ public void add(TapperTreeEntry recipe) {
+ TapperManagerAccessor.getLeafMap().put(recipe.log(), recipe.leaf());
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("blockstate('minecraft:clay'), blockstate('minecraft:gold_block')"))
+ public void add(IBlockState log, IBlockState leaf) {
+ add(new TapperTreeEntry(new BlockWrapper(log), new BlockWrapper(leaf)));
+ }
+
+ public boolean remove(TapperTreeEntry entry) {
+ return TapperManagerAccessor.getLeafMap().entries().removeIf(r -> {
+ if (entry.log().equals(r.getKey()) && entry.leaf().equals(r.getValue())) {
+ addBackup(entry);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ public boolean remove(BlockWrapper input, BlockWrapper output) {
+ return remove(new TapperTreeEntry(input, output));
+ }
+
+ @MethodDescription
+ public boolean removeByLog(BlockWrapper input) {
+ return TapperManagerAccessor.getLeafMap().entries().removeIf(r -> {
+ if (input.equals(r.getKey())) {
+ addBackup(new TapperTreeEntry(r.getKey(), r.getValue()));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("blockstate('minecraft:log', 'variant=spruce')"))
+ public boolean removeByLog(IBlockState input) {
+ return removeByLog(new BlockWrapper(input));
+ }
+
+ @MethodDescription
+ public boolean removeByLeaf(BlockWrapper output) {
+ return TapperManagerAccessor.getLeafMap().entries().removeIf(r -> {
+ if (output.equals(r.getValue())) {
+ addBackup(new TapperTreeEntry(r.getKey(), r.getValue()));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("blockstate('minecraft:leaves', 'variant=birch')"))
+ public boolean removeByLeaf(IBlockState output) {
+ return removeByLeaf(new BlockWrapper(output));
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream> streamRecipes() {
+ return new SimpleObjectStream<>(TapperManagerAccessor.getLeafMap().entries())
+ .setRemover(x -> remove(x.getKey(), x.getValue()));
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ TapperManagerAccessor.getLeafMap().entries().forEach(x -> addBackup(new TapperTreeEntry(x.getKey(), x.getValue())));
+ TapperManagerAccessor.getLeafMap().clear();
+ }
+
+ @Desugar
+ public record TapperTreeEntry(BlockWrapper log, BlockWrapper leaf) {
+
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/XpCollector.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/XpCollector.java
new file mode 100644
index 000000000..41e2447ba
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/device/XpCollector.java
@@ -0,0 +1,94 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.device;
+
+import cofh.core.inventory.ComparableItemStack;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.documentation.annotations.Example;
+import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
+import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.XpCollectorManagerAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import com.github.bsideup.jabel.Desugar;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+
+@RegistryDescription(category = RegistryDescription.Category.ENTRIES)
+public class XpCollector extends VirtualizedRegistry {
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> {
+ XpCollectorManagerAccessor.getCatalystMap().keySet().removeIf(r -> r.equals(recipe.getComparableStack()));
+ XpCollectorManagerAccessor.getCatalystFactorMap().keySet().removeIf(r -> r.equals(recipe.getComparableStack()));
+ });
+ restoreFromBackup().forEach(r -> {
+ XpCollectorManagerAccessor.getCatalystMap().put(r.getComparableStack(), r.xp());
+ XpCollectorManagerAccessor.getCatalystFactorMap().put(r.getComparableStack(), r.factor());
+ });
+ }
+
+ public void add(XpCollectorRecipe recipe) {
+ XpCollectorManagerAccessor.getCatalystMap().put(recipe.getComparableStack(), recipe.xp());
+ XpCollectorManagerAccessor.getCatalystFactorMap().put(recipe.getComparableStack(), recipe.factor());
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("item('minecraft:clay'), 100, 30"))
+ public void add(ItemStack catalyst, int xp, int factor) {
+ add(new XpCollectorRecipe(catalyst, xp, factor));
+ }
+
+ public boolean remove(ComparableItemStack comparableItemStack) {
+ if (XpCollectorManagerAccessor.getCatalystMap().containsKey(comparableItemStack) && XpCollectorManagerAccessor.getCatalystFactorMap().containsKey(comparableItemStack)) {
+ addBackup(new XpCollectorRecipe(new ItemStack(comparableItemStack.item, comparableItemStack.metadata),
+ XpCollectorManagerAccessor.getCatalystMap().remove(comparableItemStack),
+ XpCollectorManagerAccessor.getCatalystFactorMap().remove(comparableItemStack)));
+ return true;
+ }
+ return false;
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:soul_sand')"))
+ public boolean remove(ItemStack itemStack) {
+ ComparableItemStack help = new ComparableItemStack(itemStack);
+ if (XpCollectorManagerAccessor.getCatalystMap().containsKey(help) && XpCollectorManagerAccessor.getCatalystFactorMap().containsKey(help)) {
+ addBackup(new XpCollectorRecipe(itemStack, XpCollectorManagerAccessor.getCatalystMap().remove(help), XpCollectorManagerAccessor.getCatalystFactorMap().remove(help)));
+ return true;
+ }
+ return false;
+ }
+
+ public boolean remove(XpCollectorRecipe recipe) {
+ if (XpCollectorManagerAccessor.getCatalystMap().containsKey(recipe.getComparableStack()) && XpCollectorManagerAccessor.getCatalystFactorMap().containsKey(recipe.getComparableStack())) {
+ addBackup(new XpCollectorRecipe(recipe.catalyst(), XpCollectorManagerAccessor.getCatalystMap().remove(recipe.getComparableStack()), XpCollectorManagerAccessor.getCatalystFactorMap().remove(recipe.getComparableStack())));
+ return true;
+ }
+ return false;
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(XpCollectorManagerAccessor.getCatalystMap().keySet())
+ .setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ XpCollectorManagerAccessor.getCatalystMap().keySet().stream().filter(XpCollectorManagerAccessor.getCatalystFactorMap()::containsKey)
+ .forEach(x -> addBackup(new XpCollectorRecipe(new ItemStack(x.item, x.metadata), XpCollectorManagerAccessor.getCatalystMap().get(x), XpCollectorManagerAccessor.getCatalystFactorMap().get(x))));
+ XpCollectorManagerAccessor.getCatalystMap().clear();
+ XpCollectorManagerAccessor.getCatalystFactorMap().clear();
+ }
+
+ @Desugar
+ public record XpCollectorRecipe(ItemStack catalyst, int xp, int factor) {
+
+ public ComparableItemStack getComparableStack() {
+ return new ComparableItemStack(catalyst());
+ }
+
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Compression.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Compression.java
new file mode 100644
index 000000000..13e4caa44
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Compression.java
@@ -0,0 +1,87 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.dynamo;
+
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.documentation.annotations.Example;
+import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
+import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.CompressionManagerAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import com.github.bsideup.jabel.Desugar;
+import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.ApiStatus;
+
+@RegistryDescription
+public class Compression extends VirtualizedRegistry {
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> CompressionManagerAccessor.getFuelMap().keySet().removeIf(r -> r.equals(recipe.fluid())));
+ restoreFromBackup().forEach(r -> CompressionManagerAccessor.getFuelMap().put(r.fluid(), r.energy()));
+ }
+
+ public void add(CompressionRecipe recipe) {
+ CompressionManagerAccessor.getFuelMap().put(recipe.fluid(), recipe.energy());
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("fluid('steam'), 100"))
+ public void add(FluidStack fluidStack, int energy) {
+ add(new CompressionRecipe(fluidStack.getFluid().getName(), energy));
+ }
+
+ public boolean remove(String fluid) {
+ return CompressionManagerAccessor.getFuelMap().keySet().removeIf(r -> {
+ if (r.equals(fluid)) {
+ addBackup(new CompressionRecipe(r, CompressionManagerAccessor.getFuelMap().getInt(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ public boolean remove(CompressionRecipe recipe) {
+ return CompressionManagerAccessor.getFuelMap().keySet().removeIf(r -> {
+ if (r.equals(recipe.fluid())) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription
+ public boolean removeByInput(String input) {
+ return CompressionManagerAccessor.getFuelMap().keySet().removeIf(r -> {
+ if (input.equals(r)) {
+ addBackup(new CompressionRecipe(r, CompressionManagerAccessor.getFuelMap().getInt(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("fluid('seed_oil')"))
+ public boolean removeByInput(FluidStack input) {
+ return removeByInput(input.getFluid().getName());
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(CompressionManagerAccessor.getFuelMap().keySet()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ CompressionManagerAccessor.getFuelMap().keySet().forEach(x -> addBackup(new CompressionRecipe(x, CompressionManagerAccessor.getFuelMap().getInt(x))));
+ CompressionManagerAccessor.getFuelMap().clear();
+ }
+
+ @Desugar
+ public record CompressionRecipe(String fluid, int energy) {
+
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Enervation.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Enervation.java
new file mode 100644
index 000000000..90d961a72
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Enervation.java
@@ -0,0 +1,84 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.dynamo;
+
+import cofh.core.inventory.ComparableItemStack;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.Example;
+import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
+import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.EnervationManagerAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import com.github.bsideup.jabel.Desugar;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+
+@RegistryDescription
+public class Enervation extends VirtualizedRegistry {
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> EnervationManagerAccessor.getFuelMap().keySet().removeIf(r -> r.equals(recipe.comparableItemStack())));
+ restoreFromBackup().forEach(r -> EnervationManagerAccessor.getFuelMap().put(r.comparableItemStack(), r.energy()));
+ }
+
+ public void add(EnervationRecipe recipe) {
+ EnervationManagerAccessor.getFuelMap().put(recipe.comparableItemStack(), recipe.energy());
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("item('minecraft:clay'), 100"))
+ public void add(ItemStack itemStack, int energy) {
+ add(new EnervationRecipe(new ComparableItemStack(itemStack), energy));
+ }
+
+ public boolean remove(ComparableItemStack recipe) {
+ return EnervationManagerAccessor.getFuelMap().keySet().removeIf(r -> {
+ if (r.equals(recipe)) {
+ addBackup(new EnervationRecipe(r, EnervationManagerAccessor.getFuelMap().get(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ public boolean remove(EnervationRecipe recipe) {
+ return EnervationManagerAccessor.getFuelMap().keySet().removeIf(r -> {
+ if (r.equals(recipe.comparableItemStack())) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:redstone')"))
+ public boolean removeByInput(IIngredient input) {
+ return EnervationManagerAccessor.getFuelMap().keySet().removeIf(r -> {
+ if (input.test(r.toItemStack())) {
+ addBackup(new EnervationRecipe(r, EnervationManagerAccessor.getFuelMap().get(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(EnervationManagerAccessor.getFuelMap().keySet()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ EnervationManagerAccessor.getFuelMap().keySet().forEach(x -> addBackup(new EnervationRecipe(x, EnervationManagerAccessor.getFuelMap().get(x))));
+ EnervationManagerAccessor.getFuelMap().clear();
+ }
+
+ @Desugar
+ public record EnervationRecipe(ComparableItemStack comparableItemStack, int energy) {
+
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Lapidary.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Lapidary.java
new file mode 100644
index 000000000..e45d3408e
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Lapidary.java
@@ -0,0 +1,84 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.dynamo;
+
+import cofh.core.inventory.ComparableItemStack;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.Example;
+import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
+import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.NumismaticManagerAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import com.github.bsideup.jabel.Desugar;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+
+@RegistryDescription
+public class Lapidary extends VirtualizedRegistry {
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> NumismaticManagerAccessor.getGemFuelMap().keySet().removeIf(r -> r.equals(recipe.comparableItemStack())));
+ restoreFromBackup().forEach(r -> NumismaticManagerAccessor.getGemFuelMap().put(r.comparableItemStack(), r.energy()));
+ }
+
+ public void add(LapidaryRecipe recipe) {
+ NumismaticManagerAccessor.getGemFuelMap().put(recipe.comparableItemStack(), recipe.energy());
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("item('minecraft:clay'), 1000"))
+ public void add(ItemStack itemStack, int energy) {
+ add(new LapidaryRecipe(new ComparableItemStack(itemStack), energy));
+ }
+
+ public boolean remove(ComparableItemStack recipe) {
+ return NumismaticManagerAccessor.getGemFuelMap().keySet().removeIf(r -> {
+ if (r.equals(recipe)) {
+ addBackup(new LapidaryRecipe(r, NumismaticManagerAccessor.getGemFuelMap().get(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ public boolean remove(LapidaryRecipe recipe) {
+ return NumismaticManagerAccessor.getGemFuelMap().keySet().removeIf(r -> {
+ if (r.equals(recipe.comparableItemStack())) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:diamond')"))
+ public boolean removeByInput(IIngredient input) {
+ return NumismaticManagerAccessor.getGemFuelMap().keySet().removeIf(r -> {
+ if (input.test(r.toItemStack())) {
+ addBackup(new LapidaryRecipe(r, NumismaticManagerAccessor.getGemFuelMap().get(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(NumismaticManagerAccessor.getGemFuelMap().keySet()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ NumismaticManagerAccessor.getGemFuelMap().keySet().forEach(x -> addBackup(new LapidaryRecipe(x, NumismaticManagerAccessor.getGemFuelMap().get(x))));
+ NumismaticManagerAccessor.getGemFuelMap().clear();
+ }
+
+ @Desugar
+ public record LapidaryRecipe(ComparableItemStack comparableItemStack, int energy) {
+
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Magmatic.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Magmatic.java
new file mode 100644
index 000000000..de71bdb5e
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Magmatic.java
@@ -0,0 +1,89 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.dynamo;
+
+import cofh.core.inventory.ComparableItemStack;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.documentation.annotations.Example;
+import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
+import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.MagmaticManagerAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import com.github.bsideup.jabel.Desugar;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.ApiStatus;
+
+@RegistryDescription
+public class Magmatic extends VirtualizedRegistry {
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> MagmaticManagerAccessor.getFuelMap().keySet().removeIf(r -> r.equals(recipe.fluid())));
+ restoreFromBackup().forEach(r -> MagmaticManagerAccessor.getFuelMap().put(r.fluid(), r.energy()));
+ }
+
+ public void add(MagmaticRecipe recipe) {
+ MagmaticManagerAccessor.getFuelMap().put(recipe.fluid(), recipe.energy());
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("fluid('steam'), 100"))
+ public void add(FluidStack fluidStack, int energy) {
+ add(new MagmaticRecipe(fluidStack.getFluid().getName(), energy));
+ }
+
+ public boolean remove(String fluid) {
+ return MagmaticManagerAccessor.getFuelMap().keySet().removeIf(r -> {
+ if (r.equals(fluid)) {
+ addBackup(new MagmaticRecipe(r, MagmaticManagerAccessor.getFuelMap().getInt(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ public boolean remove(MagmaticRecipe recipe) {
+ return MagmaticManagerAccessor.getFuelMap().keySet().removeIf(r -> {
+ if (r.equals(recipe.fluid())) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription
+ public boolean removeByInput(String input) {
+ return MagmaticManagerAccessor.getFuelMap().keySet().removeIf(r -> {
+ if (input.equals(r)) {
+ addBackup(new MagmaticRecipe(r, MagmaticManagerAccessor.getFuelMap().getInt(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("fluid('lava')"))
+ public boolean removeByInput(FluidStack input) {
+ return removeByInput(input.getFluid().getName());
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(MagmaticManagerAccessor.getFuelMap().keySet()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ MagmaticManagerAccessor.getFuelMap().keySet().forEach(x -> addBackup(new MagmaticRecipe(x, MagmaticManagerAccessor.getFuelMap().getInt(x))));
+ MagmaticManagerAccessor.getFuelMap().clear();
+ }
+
+ @Desugar
+ public record MagmaticRecipe(String fluid, int energy) {
+
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Numismatic.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Numismatic.java
new file mode 100644
index 000000000..0849bd46a
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Numismatic.java
@@ -0,0 +1,84 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.dynamo;
+
+import cofh.core.inventory.ComparableItemStack;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.Example;
+import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
+import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.NumismaticManagerAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import com.github.bsideup.jabel.Desugar;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+
+@RegistryDescription
+public class Numismatic extends VirtualizedRegistry {
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> NumismaticManagerAccessor.getFuelMap().keySet().removeIf(r -> r.equals(recipe.comparableItemStack())));
+ restoreFromBackup().forEach(r -> NumismaticManagerAccessor.getFuelMap().put(r.comparableItemStack(), r.energy()));
+ }
+
+ public void add(NumismaticRecipe recipe) {
+ NumismaticManagerAccessor.getFuelMap().put(recipe.comparableItemStack(), recipe.energy());
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("item('minecraft:clay'), 100"))
+ public void add(ItemStack itemStack, int energy) {
+ add(new NumismaticRecipe(new ComparableItemStack(itemStack), energy));
+ }
+
+ public boolean remove(ComparableItemStack recipe) {
+ return NumismaticManagerAccessor.getFuelMap().keySet().removeIf(r -> {
+ if (r.equals(recipe)) {
+ addBackup(new NumismaticRecipe(r, NumismaticManagerAccessor.getFuelMap().get(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ public boolean remove(NumismaticRecipe recipe) {
+ return NumismaticManagerAccessor.getFuelMap().keySet().removeIf(r -> {
+ if (r.equals(recipe.comparableItemStack())) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('thermalfoundation:coin:69')"))
+ public boolean removeByInput(IIngredient input) {
+ return NumismaticManagerAccessor.getFuelMap().keySet().removeIf(r -> {
+ if (input.test(r.toItemStack())) {
+ addBackup(new NumismaticRecipe(r, NumismaticManagerAccessor.getFuelMap().get(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(NumismaticManagerAccessor.getFuelMap().keySet()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ NumismaticManagerAccessor.getFuelMap().keySet().forEach(x -> addBackup(new NumismaticRecipe(x, NumismaticManagerAccessor.getFuelMap().get(x))));
+ NumismaticManagerAccessor.getFuelMap().clear();
+ }
+
+ @Desugar
+ public record NumismaticRecipe(ComparableItemStack comparableItemStack, int energy) {
+
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Reactant.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Reactant.java
new file mode 100644
index 000000000..0a872f6eb
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Reactant.java
@@ -0,0 +1,189 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.dynamo;
+
+import cofh.core.inventory.ComparableItemStack;
+import cofh.thermalexpansion.util.managers.dynamo.ReactantManager;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.ReactantManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.ReactionAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper;
+import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
+import com.cleanroommc.groovyscript.registry.AbstractReloadableStorage;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RegistryDescription
+public class Reactant extends VirtualizedRegistry {
+
+ private final AbstractReloadableStorage elementalReactantStorage = new AbstractReloadableStorage<>();
+ private final AbstractReloadableStorage elementalFluidStorage = new AbstractReloadableStorage<>();
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('minecraft:diamond')).fluidInput(fluid('steam'))"),
+ @Example(".input(item('minecraft:clay')).fluidInput(fluid('glowstone')).energy(100)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> ReactantManagerAccessor.getReactionMap().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> ReactantManagerAccessor.getReactionMap().put(hash(r), r));
+ elementalReactantStorage.removeScripted().forEach(recipe -> ReactantManagerAccessor.getValidReactantsElemental().removeIf(r -> r.equals(new ComparableItemStack(recipe))));
+ elementalReactantStorage.restoreFromBackup().forEach(r -> ReactantManagerAccessor.getValidReactantsElemental().add(new ComparableItemStack(r)));
+ elementalFluidStorage.removeScripted().forEach(recipe -> ReactantManagerAccessor.getValidFluidsElemental().removeIf(r -> r.equals(recipe)));
+ elementalFluidStorage.restoreFromBackup().forEach(r -> ReactantManagerAccessor.getValidFluidsElemental().add(r));
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void afterScriptLoad() {
+ ReactantManagerAccessor.getValidReactants().clear();
+ ReactantManagerAccessor.getValidReactants().addAll(ReactantManagerAccessor.getReactionMap().values().stream().map(ReactantManager.Reaction::getReactant).map(ComparableItemStack::new).collect(Collectors.toList()));
+ ReactantManagerAccessor.getValidFluids().clear();
+ ReactantManagerAccessor.getValidFluids().addAll(ReactantManagerAccessor.getReactionMap().values().stream().map(ReactantManager.Reaction::getFluidName).collect(Collectors.toList()));
+ }
+
+ private List hash(ReactantManager.Reaction recipe) {
+ return hash(recipe.getReactant(), recipe.getFluid());
+ }
+
+ private List hash(ItemStack reactant, Fluid fluid) {
+ return Arrays.asList((new ComparableItemStack(reactant)).hashCode(), fluid.getName().hashCode());
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = {@Example("item('minecraft:gunpowder')"), @Example("item('minecraft:clay')")})
+ public boolean addElementalReactant(ItemStack itemStack) {
+ return ReactantManagerAccessor.getValidReactantsElemental().add(new ComparableItemStack(itemStack)) && elementalReactantStorage.addScripted(itemStack);
+ }
+
+ @MethodDescription(example = @Example("item('thermalfoundation:material:1024')"))
+ public boolean removeElementalReactant(ItemStack itemStack) {
+ return ReactantManagerAccessor.getValidReactantsElemental().removeIf(r -> r.equals(new ComparableItemStack(itemStack))) && elementalReactantStorage.addBackup(itemStack);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION)
+ public boolean addElementalFluid(String fluid) {
+ return ReactantManagerAccessor.getValidFluidsElemental().add(fluid) && elementalFluidStorage.addScripted(fluid);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("fluid('glowstone')"))
+ public boolean addElementalFluid(FluidStack fluid) {
+ return addElementalFluid(fluid.getFluid().getName());
+ }
+
+ @MethodDescription
+ public boolean removeElementalFluid(String fluid) {
+ return ReactantManagerAccessor.getValidFluidsElemental().removeIf(r -> r.equals(fluid)) && elementalFluidStorage.addBackup(fluid);
+ }
+
+ @MethodDescription(example = @Example("fluid('cryotheum')"))
+ public boolean removeElementalFluid(FluidStack fluid) {
+ return removeElementalFluid(fluid.getFluid().getName());
+ }
+
+ public void add(ReactantManager.Reaction recipe) {
+ ReactantManagerAccessor.getReactionMap().put(hash(recipe), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("item('minecraft:clay'), fluid('steam'), 100"))
+ public void add(IIngredient ingredient, FluidStack fluidStack, int energy) {
+ recipeBuilder()
+ .energy(energy)
+ .input(ingredient)
+ .fluidInput(fluidStack)
+ .register();
+ }
+
+ public boolean remove(ReactantManager.Reaction recipe) {
+ return ReactantManagerAccessor.getReactionMap().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = {
+ @Example("item('minecraft:blaze_powder')"), @Example("fluid('redstone')")
+ })
+ public boolean removeByInput(IIngredient input) {
+ return ReactantManagerAccessor.getReactionMap().values().removeIf(r -> {
+ if (input.test(r.getReactant()) || (input instanceof FluidStack && IngredientHelper.toFluidStack(input).getFluid().getName().equals(r.getFluidName()))) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(ReactantManagerAccessor.getReactionMap().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ ReactantManagerAccessor.getReactionMap().values().forEach(this::addBackup);
+ ReactantManagerAccessor.getReactionMap().clear();
+ }
+
+ @Property(property = "input", valid = @Comp("1"))
+ @Property(property = "fluidInput", valid = @Comp("1"))
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "ReactantManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT))
+ private int energy = ReactantManager.DEFAULT_ENERGY;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Reactant Dynamo recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 1, 1, 0, 0);
+ validateFluids(msg, 1, 1, 0, 0);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable ReactantManager.Reaction register() {
+ if (!validate()) return null;
+ ReactantManager.Reaction recipe = null;
+
+ for (ItemStack itemStack : input.get(0).getMatchingStacks()) {
+ ReactantManager.Reaction recipe1 = ReactionAccessor.createReaction(itemStack, fluidInput.get(0).getFluid(), energy);
+ ModSupport.THERMAL_EXPANSION.get().reactant.add(recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ return recipe;
+ }
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Steam.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Steam.java
new file mode 100644
index 000000000..816361eac
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/dynamo/Steam.java
@@ -0,0 +1,84 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.dynamo;
+
+import cofh.core.inventory.ComparableItemStack;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.Example;
+import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
+import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.SteamManagerAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import com.github.bsideup.jabel.Desugar;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+
+@RegistryDescription
+public class Steam extends VirtualizedRegistry {
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> SteamManagerAccessor.getFuelMap().keySet().removeIf(r -> r.equals(recipe.comparableItemStack())));
+ restoreFromBackup().forEach(r -> SteamManagerAccessor.getFuelMap().put(r.comparableItemStack(), r.energy()));
+ }
+
+ public void add(SteamRecipe recipe) {
+ SteamManagerAccessor.getFuelMap().put(recipe.comparableItemStack(), recipe.energy());
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("item('minecraft:clay'), 100"))
+ public void add(ItemStack itemStack, int energy) {
+ add(new SteamRecipe(new ComparableItemStack(itemStack), energy));
+ }
+
+ public boolean remove(ComparableItemStack recipe) {
+ return SteamManagerAccessor.getFuelMap().keySet().removeIf(r -> {
+ if (r.equals(recipe)) {
+ addBackup(new SteamRecipe(r, SteamManagerAccessor.getFuelMap().get(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ public boolean remove(SteamRecipe recipe) {
+ return SteamManagerAccessor.getFuelMap().keySet().removeIf(r -> {
+ if (r.equals(recipe.comparableItemStack())) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:coal:1')"))
+ public boolean removeByInput(IIngredient input) {
+ return SteamManagerAccessor.getFuelMap().keySet().removeIf(r -> {
+ if (input.test(r.toItemStack())) {
+ addBackup(new SteamRecipe(r, SteamManagerAccessor.getFuelMap().get(r)));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(SteamManagerAccessor.getFuelMap().keySet()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ SteamManagerAccessor.getFuelMap().keySet().forEach(x -> addBackup(new SteamRecipe(x, SteamManagerAccessor.getFuelMap().get(x))));
+ SteamManagerAccessor.getFuelMap().clear();
+ }
+
+ @Desugar
+ public record SteamRecipe(ComparableItemStack comparableItemStack, int energy) {
+
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Brewer.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Brewer.java
new file mode 100644
index 000000000..32b2da74f
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Brewer.java
@@ -0,0 +1,172 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.core.util.helpers.FluidHelper;
+import cofh.thermalexpansion.util.managers.machine.BrewerManager;
+import cofh.thermalexpansion.util.managers.machine.BrewerManager.BrewerRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.BrewerManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.BrewerRecipeAccessor;
+import com.cleanroommc.groovyscript.helper.Alias;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RegistryDescription
+public class Brewer extends VirtualizedRegistry {
+
+ public Brewer() {
+ super(Alias.generateOfClass(Brewer.class).andGenerate("Imbuer"));
+ }
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('minecraft:clay')).fluidInput(fluid('water') * 100).fluidOutput(fluid('lava') * 100)"),
+ @Example(".input(item('minecraft:diamond') * 2).fluidInput(fluid('water') * 1000).fluidOutput(fluid('steam') * 100).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> BrewerManagerAccessor.getRecipeMap().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> BrewerManagerAccessor.getRecipeMap().put(hash(r), r));
+ }
+
+ @Override
+ @GroovyBlacklist
+ public void afterScriptLoad() {
+ BrewerManagerAccessor.getValidationSet().clear();
+ BrewerManagerAccessor.getValidationSet().addAll(
+ BrewerManagerAccessor.getRecipeMap().values().stream().map(BrewerRecipe::getInput).map(BrewerManager::convertInput).collect(Collectors.toList())
+ );
+ BrewerManagerAccessor.getValidationFluids().clear();
+ BrewerManagerAccessor.getValidationFluids().addAll(
+ BrewerManagerAccessor.getRecipeMap().values().stream().map(BrewerRecipe::getInputFluid).map(FluidStack::getFluid).map(Fluid::getName).collect(Collectors.toList())
+ );
+ }
+
+ private List hash(BrewerRecipe recipe) {
+ return hash(recipe.getInput(), recipe.getInputFluid());
+ }
+
+ private List hash(ItemStack input, FluidStack fluid) {
+ return Arrays.asList(BrewerManager.convertInput(input).hashCode(), FluidHelper.getFluidHash(fluid));
+ }
+
+ public void add(BrewerRecipe recipe) {
+ BrewerManagerAccessor.getRecipeMap().put(hash(recipe), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example(value = "1000, item('minecraft:obsidian') * 2, fluid('water') * 1000, fluid('steam') * 100", commented = true))
+ public BrewerRecipe add(int energy, IIngredient input, FluidStack fluidInput, FluidStack fluidOutput) {
+ return recipeBuilder()
+ .energy(energy)
+ .input(input)
+ .fluidInput(fluidInput)
+ .fluidOutput(fluidOutput)
+ .register();
+ }
+
+ public boolean remove(BrewerRecipe recipe) {
+ return BrewerManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = {
+ @Example("fluid('potion').withNbt(['Potion': 'minecraft:leaping'])"),
+ @Example("item('minecraft:glowstone_dust')")
+ })
+ public boolean removeByInput(IIngredient input) {
+ return BrewerManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (input.test(r.getInput()) || input.test(r.getInputFluid())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("fluid('potion_splash').withNbt(['Potion': 'cofhcore:luck2'])"))
+ public boolean removeByOutput(IIngredient output) {
+ return BrewerManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (output.test(r.getOutputFluid())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(BrewerManagerAccessor.getRecipeMap().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ BrewerManagerAccessor.getRecipeMap().values().forEach(this::addBackup);
+ BrewerManagerAccessor.getRecipeMap().clear();
+ }
+
+ @Property(property = "input", valid = @Comp("1"))
+ @Property(property = "fluidInput", valid = @Comp("1"))
+ @Property(property = "fluidOutput", valid = @Comp("1"))
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "BrewerManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = BrewerManager.DEFAULT_ENERGY;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Brewer recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 1, 1, 0, 0);
+ validateFluids(msg, 1, 1, 1, 1);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable BrewerRecipe register() {
+ if (!validate()) return null;
+ BrewerRecipe recipe = null;
+
+ for (ItemStack itemStack : input.get(0).getMatchingStacks()) {
+ BrewerRecipe recipe1 = BrewerRecipeAccessor.createBrewerRecipe(itemStack, fluidInput.get(0), fluidOutput.get(0), energy);
+ ModSupport.THERMAL_EXPANSION.get().brewer.add(recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Centrifuge.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Centrifuge.java
new file mode 100644
index 000000000..f9c12df36
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Centrifuge.java
@@ -0,0 +1,163 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.thermalexpansion.util.managers.machine.CentrifugeManager;
+import cofh.thermalexpansion.util.managers.machine.CentrifugeManager.CentrifugeRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.CentrifugeManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.CentrifugeRecipeAccessor;
+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.FluidStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@RegistryDescription
+public class Centrifuge extends VirtualizedRegistry {
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('minecraft:clay')).fluidOutput(fluid('water') * 100).output(item('minecraft:diamond') * 2, item('minecraft:gold_ingot'), item('minecraft:gold_ingot')).chance(50, 100, 1)"),
+ @Example(".input(item('minecraft:diamond') * 3).output(item('minecraft:clay')).chance(100).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> CentrifugeManagerAccessor.getRecipeMap().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> CentrifugeManagerAccessor.getRecipeMap().put(CentrifugeManager.convertInput(r.getInput()), r));
+ }
+
+ public void add(CentrifugeRecipe recipe) {
+ CentrifugeManagerAccessor.getRecipeMap().put(CentrifugeManager.convertInput(recipe.getInput()), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example(value = "1000, item('minecraft:obsidian') * 3, [item('minecraft:clay')], [100], null", commented = true))
+ public CentrifugeRecipe add(int energy, IIngredient input, List output, List chance, FluidStack fluidOutput) {
+ return recipeBuilder()
+ .energy(energy)
+ .chance(chance)
+ .input(input)
+ .output(output)
+ .fluidOutput(fluidOutput)
+ .register();
+ }
+
+ public boolean remove(CentrifugeRecipe recipe) {
+ return CentrifugeManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:reeds')"))
+ public boolean removeByInput(IIngredient input) {
+ return CentrifugeManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (input.test(r.getInput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = {@Example("fluid('redstone')"), @Example("item('minecraft:redstone')")})
+ public boolean removeByOutput(IIngredient output) {
+ return CentrifugeManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (output.test(r.getFluid()) || r.getOutput().stream().anyMatch(output)) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(CentrifugeManagerAccessor.getRecipeMap().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ CentrifugeManagerAccessor.getRecipeMap().values().forEach(this::addBackup);
+ CentrifugeManagerAccessor.getRecipeMap().clear();
+ }
+
+ @Property(property = "input", valid = @Comp("1"))
+ @Property(property = "output", valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "4")})
+ @Property(property = "fluidOutput", valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "1")})
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "100")})
+ private final List chance = new ArrayList<>();
+ @Property(defaultValue = "CentrifugeManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = CentrifugeManager.DEFAULT_ENERGY;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder chance(int chance) {
+ this.chance.add(chance);
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder chance(Integer... chance) {
+ this.chance.addAll(Arrays.asList(chance));
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder chance(List chance) {
+ this.chance.addAll(chance);
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Centrifuge recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 1, 1, 0, 4);
+ validateFluids(msg, 0, 0, 0, 1);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ chance.forEach(x -> msg.add(x < 0 || x > 100, "all chance values must be non negative integers less than 100, yet one was {}", x));
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable CentrifugeRecipe register() {
+ if (!validate()) return null;
+ CentrifugeRecipe recipe = null;
+
+ for (ItemStack itemStack : input.get(0).getMatchingStacks()) {
+ CentrifugeRecipe recipe1 = CentrifugeRecipeAccessor.createCentrifugeRecipe(itemStack, output, chance, fluidOutput.getOrEmpty(0), energy);
+ ModSupport.THERMAL_EXPANSION.get().centrifuge.add(recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/CentrifugeMobs.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/CentrifugeMobs.java
new file mode 100644
index 000000000..8322fdb33
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/CentrifugeMobs.java
@@ -0,0 +1,165 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.thermalexpansion.util.managers.machine.CentrifugeManager;
+import cofh.thermalexpansion.util.managers.machine.CentrifugeManager.CentrifugeRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.CentrifugeManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.CentrifugeRecipeAccessor;
+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.FluidStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@RegistryDescription
+public class CentrifugeMobs extends VirtualizedRegistry {
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('thermalexpansion:morb').withNbt(['id': 'minecraft:slime'])).fluidOutput(fluid('water') * 100).output(item('minecraft:diamond') * 2, item('minecraft:gold_ingot'), item('minecraft:gold_ingot')).chance(50, 100, 1)"),
+ @Example(".input(item('minecraft:diamond') * 3).output(item('minecraft:clay')).chance(100).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> CentrifugeManagerAccessor.getRecipeMapMobs().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> CentrifugeManagerAccessor.getRecipeMapMobs().put(CentrifugeManager.convertInput(r.getInput()), r));
+ }
+
+ public void add(CentrifugeRecipe recipe) {
+ CentrifugeManagerAccessor.getRecipeMapMobs().put(CentrifugeManager.convertInput(recipe.getInput()), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example(value = "1000, item('minecraft:obsidian') * 3, item('minecraft:clay'), 100", commented = true))
+ public CentrifugeRecipe add(int energy, IIngredient input, List output, List chance, FluidStack fluidOutput) {
+ return recipeBuilder()
+ .energy(energy)
+ .chance(chance)
+ .input(input)
+ .output(output)
+ .fluidOutput(fluidOutput)
+ .register();
+ }
+
+ public boolean remove(CentrifugeRecipe recipe) {
+ return CentrifugeManagerAccessor.getRecipeMapMobs().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('thermalexpansion:morb').withNbt(['id': 'minecraft:slime'])"))
+ public boolean removeByInput(IIngredient input) {
+ return CentrifugeManagerAccessor.getRecipeMapMobs().values().removeIf(r -> {
+ if (input.test(r.getInput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = {
+ @Example("item('minecraft:fish')"), @Example(value = "fluid('experience')", commented = true)
+ })
+ public boolean removeByOutput(IIngredient output) {
+ return CentrifugeManagerAccessor.getRecipeMapMobs().values().removeIf(r -> {
+ if (output.test(r.getFluid()) || r.getOutput().stream().anyMatch(output)) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(CentrifugeManagerAccessor.getRecipeMapMobs().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ CentrifugeManagerAccessor.getRecipeMapMobs().values().forEach(this::addBackup);
+ CentrifugeManagerAccessor.getRecipeMapMobs().clear();
+ }
+
+ @Property(property = "input", valid = @Comp("1"))
+ @Property(property = "output", valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "4")})
+ @Property(property = "fluidOutput", valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "1")})
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "100")})
+ private final List chance = new ArrayList<>();
+ @Property(defaultValue = "CentrifugeManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = CentrifugeManager.DEFAULT_ENERGY;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder chance(int chance) {
+ this.chance.add(chance);
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder chance(Integer... chance) {
+ this.chance.addAll(Arrays.asList(chance));
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder chance(List chance) {
+ this.chance.addAll(chance);
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Centrifuge recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 1, 1, 0, 4);
+ validateFluids(msg, 0, 0, 0, 1);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ chance.forEach(x -> msg.add(x < 0 || x > 100, "all chance values must be greater than or equal to 0 and less than or equal to 100, yet a chance value was {}", x));
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable CentrifugeRecipe register() {
+ if (!validate()) return null;
+ CentrifugeRecipe recipe = null;
+
+ for (ItemStack itemStack : input.get(0).getMatchingStacks()) {
+ CentrifugeRecipe recipe1 = CentrifugeRecipeAccessor.createCentrifugeRecipe(itemStack, output, chance, fluidOutput.getOrEmpty(0), energy);
+ ModSupport.THERMAL_EXPANSION.get().centrifugeMob.add(recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Charger.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Charger.java
new file mode 100644
index 000000000..beea4f37c
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Charger.java
@@ -0,0 +1,135 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.core.inventory.ComparableItemStackValidated;
+import cofh.thermalexpansion.util.managers.machine.ChargerManager;
+import cofh.thermalexpansion.util.managers.machine.ChargerManager.ChargerRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.ChargerManagerAccessor;
+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.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+@RegistryDescription
+public class Charger extends VirtualizedRegistry {
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('minecraft:diamond') * 5).output(item('minecraft:clay'))"),
+ @Example(".input(item('minecraft:clay')).output(item('minecraft:diamond') * 2).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> ChargerManagerAccessor.getRecipeMap().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> ChargerManagerAccessor.getRecipeMap().put(new ComparableItemStackValidated(r.getInput()), r));
+ }
+
+ public void add(ChargerRecipe recipe) {
+ ChargerManagerAccessor.getRecipeMap().put(new ComparableItemStackValidated(recipe.getInput()), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example(value = "1000, item('minecraft:obsidian'), item('minecraft:diamond') * 2", commented = true))
+ public ChargerRecipe add(int energy, IIngredient input, ItemStack output) {
+ return recipeBuilder()
+ .energy(energy)
+ .input(input)
+ .output(output)
+ .register();
+ }
+
+ public boolean remove(ChargerRecipe recipe) {
+ return ChargerManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('thermalfoundation:bait:1')"))
+ public boolean removeByInput(IIngredient input) {
+ return ChargerManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (input.test(r.getInput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('thermalfoundation:fertilizer:2')"))
+ public boolean removeByOutput(IIngredient output) {
+ return ChargerManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (output.test(r.getOutput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(ChargerManagerAccessor.getRecipeMap().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ ChargerManagerAccessor.getRecipeMap().values().forEach(this::addBackup);
+ ChargerManagerAccessor.getRecipeMap().clear();
+ }
+
+ @Property(property = "input", valid = @Comp("1"))
+ @Property(property = "output", valid = @Comp("1"))
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "ChargerManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = ChargerManager.DEFAULT_ENERGY;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Charger recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 1, 1, 1, 1);
+ validateFluids(msg);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable ChargerRecipe register() {
+ if (!validate()) return null;
+ ChargerRecipe recipe = null;
+
+ for (ItemStack itemStack : input.get(0).getMatchingStacks()) {
+ // For some reason this specific Recipe is public. The rest aren't.
+ ChargerRecipe recipe1 = new ChargerRecipe(itemStack, output.get(0), energy);
+ ModSupport.THERMAL_EXPANSION.get().charger.add(recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Compactor.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Compactor.java
new file mode 100644
index 000000000..0f1a4c87b
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Compactor.java
@@ -0,0 +1,195 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.core.inventory.ComparableItemStackValidatedNBT;
+import cofh.thermalexpansion.util.managers.machine.CompactorManager;
+import cofh.thermalexpansion.util.managers.machine.CompactorManager.CompactorRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.CompactorManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.CompactorRecipeAccessor;
+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.apache.commons.lang3.tuple.Pair;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@RegistryDescription
+public class Compactor extends VirtualizedRegistry> {
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('minecraft:clay')).output(item('minecraft:diamond') * 2).mode(mode('coin'))"),
+ @Example(".input(item('minecraft:clay')).output(item('minecraft:diamond')).mode(mode('all'))"),
+ @Example(".input(item('minecraft:diamond') * 2).output(item('minecraft:gold_ingot')).mode(mode('plate')).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> map(recipe.getKey()).values().removeIf(r -> r == recipe.getValue()));
+ restoreFromBackup().forEach(r -> map(r.getKey()).put(new ComparableItemStackValidatedNBT(r.getValue().getInput()), r.getValue()));
+ }
+
+ private Map map(CompactorManager.Mode mode) {
+ return switch (mode) {
+ case ALL -> CompactorManagerAccessor.getRecipeMapAll();
+ case PLATE -> CompactorManagerAccessor.getRecipeMapPlate();
+ case COIN -> CompactorManagerAccessor.getRecipeMapCoin();
+ case GEAR -> CompactorManagerAccessor.getRecipeMapGear();
+ };
+ }
+
+ public void add(CompactorManager.Mode mode, CompactorRecipe recipe) {
+ map(mode).put(new ComparableItemStackValidatedNBT(recipe.getInput()), recipe);
+ addScripted(Pair.of(mode, recipe));
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example(value = "1000, mode('plate'), item('minecraft:obsidian') * 2, item('minecraft:gold_ingot')", commented = true))
+ public CompactorRecipe add(int energy, CompactorManager.Mode mode, IIngredient input, ItemStack output) {
+ return recipeBuilder()
+ .energy(energy)
+ .mode(mode)
+ .input(input)
+ .output(output)
+ .register();
+ }
+
+ public boolean remove(CompactorManager.Mode mode, CompactorRecipe recipe) {
+ return map(mode).values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(Pair.of(mode, recipe));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ public boolean remove(CompactorRecipe recipe) {
+ boolean hasRemoved = false;
+ for (CompactorManager.Mode mode : CompactorManager.Mode.values()) {
+ hasRemoved = remove(mode, recipe) || hasRemoved;
+ }
+ return hasRemoved;
+ }
+
+ @MethodDescription(example = @Example("mode('coin'), item('thermalfoundation:material:130')"))
+ public boolean removeByInput(CompactorManager.Mode mode, IIngredient input) {
+ return map(mode).values().removeIf(r -> {
+ if (input.test(r.getInput())) {
+ addBackup(Pair.of(mode, r));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:iron_ingot')"))
+ public boolean removeByInput(IIngredient input) {
+ boolean hasRemoved = false;
+ for (CompactorManager.Mode mode : CompactorManager.Mode.values()) {
+ hasRemoved = removeByInput(mode, input) || hasRemoved;
+ }
+ return hasRemoved;
+ }
+
+ @MethodDescription(example = @Example("mode('coin'), item('thermalfoundation:coin:102')"))
+ public boolean removeByOutput(CompactorManager.Mode mode, IIngredient output) {
+ return map(mode).values().removeIf(r -> {
+ if (output.test(r.getOutput())) {
+ addBackup(Pair.of(mode, r));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = {
+ @Example("item('thermalfoundation:material:24')"), @Example("item('minecraft:blaze_rod')")
+ })
+ public boolean removeByOutput(IIngredient output) {
+ boolean hasRemoved = false;
+ for (CompactorManager.Mode mode : CompactorManager.Mode.values()) {
+ hasRemoved = removeByOutput(mode, output) || hasRemoved;
+ }
+ return hasRemoved;
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(Arrays.stream(CompactorManager.Mode.values()).map(this::map).map(Map::values).flatMap(Collection::stream).collect(Collectors.toList()))
+ .setRemover(this::remove);
+ }
+
+ @MethodDescription(example = @Example(value = "mode('plate')", commented = true))
+ public void removeByMode(CompactorManager.Mode mode) {
+ map(mode).values().forEach(x -> addBackup(Pair.of(mode, x)));
+ map(mode).clear();
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ Arrays.stream(CompactorManager.Mode.values()).forEach(this::removeByMode);
+ }
+
+ @Property(property = "input", valid = @Comp("1"))
+ @Property(property = "output", valid = @Comp("1"))
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "CompactorManager.Mode.ALL")
+ CompactorManager.Mode mode = CompactorManager.Mode.ALL;
+ @Property(defaultValue = "CompactorManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = CompactorManager.DEFAULT_ENERGY;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder mode(CompactorManager.Mode mode) {
+ this.mode = mode;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Compactor recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 1, 1, 1, 1);
+ validateFluids(msg);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ msg.add(mode == null, "mode must be defined");
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable CompactorRecipe register() {
+ if (!validate()) return null;
+ CompactorRecipe recipe = null;
+
+ for (ItemStack itemStack : input.get(0).getMatchingStacks()) {
+ CompactorRecipe recipe1 = CompactorRecipeAccessor.createCompactorRecipe(itemStack, output.get(0), energy);
+ ModSupport.THERMAL_EXPANSION.get().compactor.add(mode, recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Crucible.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Crucible.java
new file mode 100644
index 000000000..e90219ff3
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Crucible.java
@@ -0,0 +1,151 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.core.inventory.ComparableItemStackValidatedNBT;
+import cofh.thermalexpansion.util.managers.machine.CrucibleManager;
+import cofh.thermalexpansion.util.managers.machine.CrucibleManager.CrucibleRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.CrucibleManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.CrucibleRecipeAccessor;
+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.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.stream.Collectors;
+
+@RegistryDescription
+public class Crucible extends VirtualizedRegistry {
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('minecraft:clay')).fluidOutput(fluid('lava') * 25)"),
+ @Example(".input(item('minecraft:diamond')).fluidOutput(fluid('water') * 1000).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> CrucibleManagerAccessor.getRecipeMap().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> CrucibleManagerAccessor.getRecipeMap().put(new ComparableItemStackValidatedNBT(r.getInput()), r));
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void afterScriptLoad() {
+ CrucibleManagerAccessor.getLavaSet().clear();
+ CrucibleManagerAccessor.getLavaSet().addAll(CrucibleManagerAccessor.getRecipeMap().values().stream()
+ .filter(x -> x.getOutput().getFluid() == FluidRegistry.LAVA)
+ .map(CrucibleRecipe::getInput)
+ .map(CrucibleManager::convertInput)
+ .collect(Collectors.toList()));
+ }
+
+ public void add(CrucibleRecipe recipe) {
+ CrucibleManagerAccessor.getRecipeMap().put(new ComparableItemStackValidatedNBT(recipe.getInput()), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("1000, item('minecraft:obsidian'), fluid('water') * 1000"))
+ public CrucibleRecipe add(int energy, IIngredient input, FluidStack fluidOutput) {
+ return recipeBuilder()
+ .energy(energy)
+ .input(input)
+ .fluidOutput(fluidOutput)
+ .register();
+ }
+
+ public boolean remove(CrucibleRecipe recipe) {
+ return CrucibleManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:glowstone_dust')"))
+ public boolean removeByInput(IIngredient input) {
+ return CrucibleManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (input.test(r.getInput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("fluid('lava')"))
+ public boolean removeByOutput(IIngredient output) {
+ return CrucibleManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (output.test(r.getOutput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(CrucibleManagerAccessor.getRecipeMap().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ CrucibleManagerAccessor.getRecipeMap().values().forEach(this::addBackup);
+ CrucibleManagerAccessor.getRecipeMap().clear();
+ }
+
+ @Property(property = "input", valid = @Comp("1"))
+ @Property(property = "fluidOutput", valid = @Comp("1"))
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "CrucibleManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = CrucibleManager.DEFAULT_ENERGY;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Crucible recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 1, 1, 0, 0);
+ validateFluids(msg, 0, 0, 1, 1);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable CrucibleRecipe register() {
+ if (!validate()) return null;
+ CrucibleRecipe recipe = null;
+
+ for (ItemStack itemStack : input.get(0).getMatchingStacks()) {
+ CrucibleRecipe recipe1 = CrucibleRecipeAccessor.createCrucibleRecipe(itemStack, fluidOutput.get(0), energy);
+ ModSupport.THERMAL_EXPANSION.get().crucible.add(recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Enchanter.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Enchanter.java
new file mode 100644
index 000000000..c5e52e7dc
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Enchanter.java
@@ -0,0 +1,199 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.core.inventory.ComparableItemStackValidatedNBT;
+import cofh.thermalexpansion.util.managers.machine.EnchanterManager;
+import cofh.thermalexpansion.util.managers.machine.EnchanterManager.EnchanterRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.EnchanterManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.EnchanterRecipeAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
+import com.cleanroommc.groovyscript.registry.AbstractReloadableStorage;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RegistryDescription
+public class Enchanter extends VirtualizedRegistry {
+
+ private final AbstractReloadableStorage arcanaStorage = new AbstractReloadableStorage<>();
+
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('minecraft:clay'), item('minecraft:gold_ingot') * 4).output(item('minecraft:diamond'))"),
+ @Example(".input(item('minecraft:clay'), item('minecraft:gold_ingot')).output(item('minecraft:diamond')).experience(1000).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> EnchanterManagerAccessor.getRecipeMap().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> EnchanterManagerAccessor.getRecipeMap().put(hash(r), r));
+ arcanaStorage.removeScripted().forEach(recipe -> EnchanterManagerAccessor.getLockSet().removeIf(r -> r.equals(EnchanterManager.convertInput(recipe))));
+ arcanaStorage.restoreFromBackup().forEach(r -> EnchanterManagerAccessor.getLockSet().add(EnchanterManager.convertInput(r)));
+ }
+
+ private List hash(EnchanterRecipe recipe) {
+ return hash(recipe.getPrimaryInput(), recipe.getSecondaryInput());
+ }
+
+ private List hash(ItemStack primaryInput, ItemStack secondaryInput) {
+ return Arrays.asList(EnchanterManager.convertInput(primaryInput), EnchanterManager.convertInput(secondaryInput));
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void afterScriptLoad() {
+ EnchanterManagerAccessor.getValidationSet().clear();
+ EnchanterManagerAccessor.getValidationSet().addAll(
+ EnchanterManagerAccessor.getRecipeMap().values().stream().map(EnchanterRecipe::getPrimaryInput).map(EnchanterManager::convertInput).collect(Collectors.toList())
+ );
+ EnchanterManagerAccessor.getValidationSet().addAll(
+ EnchanterManagerAccessor.getRecipeMap().values().stream().map(EnchanterRecipe::getSecondaryInput).map(EnchanterManager::convertInput).collect(Collectors.toList())
+ );
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("item('minecraft:clay')"))
+ public boolean addArcana(ItemStack itemStack) {
+ return EnchanterManagerAccessor.getLockSet().add(EnchanterManager.convertInput(itemStack)) && arcanaStorage.addScripted(itemStack);
+ }
+
+ @MethodDescription
+ public boolean removeArcana(ItemStack itemStack) {
+ return EnchanterManagerAccessor.getLockSet().removeIf(r -> r.equals(EnchanterManager.convertInput(itemStack))) && arcanaStorage.addBackup(itemStack);
+ }
+
+ public void add(EnchanterRecipe recipe) {
+ EnchanterManagerAccessor.getRecipeMap().put(hash(recipe), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("1000, item('minecraft:obsidian'), item('minecraft:gold_ingot'), item('minecraft:diamond'), 1000"))
+ public EnchanterRecipe add(int energy, IIngredient primaryInput, IIngredient secondaryInput, ItemStack output, int experience) {
+ return recipeBuilder()
+ .energy(energy)
+ .experience(experience)
+ .input(primaryInput, secondaryInput)
+ .output(output)
+ .register();
+ }
+
+ public boolean remove(EnchanterRecipe recipe) {
+ return EnchanterManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = {
+ @Example("item('minecraft:blaze_rod')"),
+ @Example(value = "item('minecraft:book')", commented = true)
+ })
+ public boolean removeByInput(IIngredient input) {
+ return EnchanterManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (input.test(r.getPrimaryInput()) || input.test(r.getSecondaryInput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:enchanted_book').withNbt(['StoredEnchantments': [['lvl': 1, 'id': 34]]])"))
+ public boolean removeByOutput(IIngredient output) {
+ return EnchanterManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (output.test(r.getOutput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(EnchanterManagerAccessor.getRecipeMap().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ EnchanterManagerAccessor.getRecipeMap().values().forEach(this::addBackup);
+ EnchanterManagerAccessor.getRecipeMap().clear();
+ }
+
+ @Property(property = "input", valid = @Comp("2"))
+ @Property(property = "output", valid = @Comp("1"))
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "EnchanterManager.DEFAULT_ENERGY[0]", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = EnchanterManager.DEFAULT_ENERGY[0];
+ @Property(defaultValue = "EnchanterManager.DEFAULT_EXPERIENCE[0]", valid = @Comp(value = "0", type = Comp.Type.GTE))
+ private int experience = EnchanterManager.DEFAULT_EXPERIENCE[0];
+ @Property(defaultValue = "EnchanterManager.Type.STANDARD")
+ private EnchanterManager.Type type = EnchanterManager.Type.STANDARD;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder experience(int experience) {
+ this.experience = experience;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder type(EnchanterManager.Type type) {
+ this.type = type;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Enchanter recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 2, 2, 1, 1);
+ validateFluids(msg);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ msg.add(experience < 0, "experience must be greater than or equal to 0, yet it was {}", experience);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable EnchanterRecipe register() {
+ if (!validate()) return null;
+ EnchanterRecipe recipe = null;
+
+ for (ItemStack input0 : input.get(0).getMatchingStacks()) {
+ for (ItemStack input1 : input.get(1).getMatchingStacks()) {
+ EnchanterRecipe recipe1 = EnchanterRecipeAccessor.createEnchanterRecipe(input0, input1, output.get(0), experience, energy, type);
+ ModSupport.THERMAL_EXPANSION.get().enchanter.add(recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ }
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Extruder.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Extruder.java
new file mode 100644
index 000000000..ea0e172ab
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Extruder.java
@@ -0,0 +1,220 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.core.util.ItemWrapper;
+import cofh.thermalexpansion.util.managers.machine.ExtruderManager;
+import cofh.thermalexpansion.util.managers.machine.ExtruderManager.ExtruderRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.ExtruderManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.ExtruderRecipeAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import com.google.common.primitives.Booleans;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+import org.apache.commons.lang3.tuple.Pair;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@RegistryDescription
+public class Extruder extends VirtualizedRegistry> {
+
+ @RecipeBuilderDescription(example = {
+ @Example(".fluidHot(100).fluidCold(1000).output(item('minecraft:clay'))"),
+ @Example(".fluidHot(100).fluidCold(1000).output(item('minecraft:gold_ingot')).sedimentary().energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> map(recipe.getKey()).values().removeIf(r -> r == recipe.getValue()));
+ restoreFromBackup().forEach(r -> map(r.getKey()).put(new ItemWrapper(r.getValue().getOutput()), r.getValue()));
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void afterScriptLoad() {
+ ExtruderManagerAccessor.getOutputListIgneous().clear();
+ ExtruderManagerAccessor.getOutputListIgneous().addAll(
+ ExtruderManagerAccessor.getRecipeMapIgneous().values().stream().map(ExtruderRecipe::getOutput).collect(Collectors.toList())
+ );
+ ExtruderManagerAccessor.getOutputListSedimentary().clear();
+ ExtruderManagerAccessor.getOutputListSedimentary().addAll(
+ ExtruderManagerAccessor.getRecipeMapSedimentary().values().stream().map(ExtruderRecipe::getOutput).collect(Collectors.toList())
+ );
+ }
+
+ private Map map(boolean isSedimentary) {
+ return isSedimentary ? ExtruderManagerAccessor.getRecipeMapSedimentary() : ExtruderManagerAccessor.getRecipeMapIgneous();
+ }
+
+ public void add(boolean sedimentary, ExtruderRecipe recipe) {
+ map(sedimentary).put(new ItemWrapper(recipe.getOutput()), recipe);
+ addScripted(Pair.of(sedimentary, recipe));
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("1000, item('minecraft:gold_block'), 100, 1000, false"))
+ public ExtruderRecipe add(int energy, ItemStack output, int fluidHot, int fluidCold, boolean sedimentary) {
+ return recipeBuilder()
+ .energy(energy)
+ .fluidCold(fluidCold)
+ .fluidHot(fluidHot)
+ .sedimentary(sedimentary)
+ .output(output)
+ .register();
+ }
+
+ public boolean remove(boolean isSedimentary, ExtruderRecipe recipe) {
+ return map(isSedimentary).values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(Pair.of(isSedimentary, recipe));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ public boolean remove(ExtruderRecipe recipe) {
+ // done this way so both remove operations are called
+ boolean hasRemoved = remove(false, recipe);
+ hasRemoved = remove(true, recipe) || hasRemoved;
+ return hasRemoved;
+ }
+
+ @MethodDescription(example = @Example(value = "false, fluid('lava')", commented = true))
+ public boolean removeByInput(boolean isSedimentary, IIngredient input) {
+ return map(isSedimentary).values().removeIf(r -> {
+ if (input.test(r.getInputHot()) || input.test(r.getInputCold())) {
+ addBackup(Pair.of(isSedimentary, r));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example(value = "fluid('water')", commented = true))
+ public boolean removeByInput(IIngredient input) {
+ // done this way so both remove operations are called
+ boolean hasRemoved = removeByInput(false, input);
+ hasRemoved = removeByInput(true, input) || hasRemoved;
+ return hasRemoved;
+ }
+
+ @MethodDescription(example = @Example("true, item('minecraft:gravel')"))
+ public boolean removeByOutput(boolean isSedimentary, IIngredient output) {
+ return map(isSedimentary).values().removeIf(r -> {
+ if (output.test(r.getOutput())) {
+ addBackup(Pair.of(isSedimentary, r));
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:obsidian')"))
+ public boolean removeByOutput(IIngredient output) {
+ // done this way so both remove operations are called
+ boolean hasRemoved = removeByOutput(false, output);
+ hasRemoved = removeByOutput(true, output) || hasRemoved;
+ return hasRemoved;
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(Booleans.asList(true, false).stream().map(this::map).map(Map::values).flatMap(Collection::stream).collect(Collectors.toList()))
+ .setRemover(this::remove);
+ }
+
+ @MethodDescription(example = @Example(value = "true", commented = true))
+ public void removeByType(boolean sedimentary) {
+ map(sedimentary).values().forEach(x -> addBackup(Pair.of(sedimentary, x)));
+ map(sedimentary).clear();
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ removeByType(true);
+ removeByType(false);
+ }
+
+ @Property(property = "output", valid = @Comp("1"))
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "ExtruderManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = ExtruderManager.DEFAULT_ENERGY;
+ @Property(valid = @Comp(value = "0", type = Comp.Type.GTE))
+ private int fluidHot;
+ @Property(valid = @Comp(value = "0", type = Comp.Type.GTE))
+ private int fluidCold;
+ @Property
+ private boolean sedimentary;
+
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder fluidHot(int fluidHot) {
+ this.fluidHot = fluidHot;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder fluidCold(int fluidCold) {
+ this.fluidCold = fluidCold;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder sedimentary() {
+ this.sedimentary = !sedimentary;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder sedimentary(boolean sedimentary) {
+ this.sedimentary = sedimentary;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Extruder recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 0, 0, 1, 1);
+ validateFluids(msg);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ msg.add(fluidHot < 0, "fluidHot must be greater than or equal to 0, yet it was {}", fluidHot);
+ msg.add(fluidCold < 0, "fluidCold must be greater than or equal to 0, yet it was {}", fluidCold);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable ExtruderRecipe register() {
+ if (!validate()) return null;
+ ExtruderRecipe recipe = ExtruderRecipeAccessor.createExtruderRecipe(output.get(0), new FluidStack(FluidRegistry.LAVA, fluidHot), new FluidStack(FluidRegistry.WATER, fluidCold), energy);
+ ModSupport.THERMAL_EXPANSION.get().extruder.add(sedimentary, recipe);
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Furnace.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Furnace.java
new file mode 100644
index 000000000..a52a84aa8
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Furnace.java
@@ -0,0 +1,155 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.thermalexpansion.util.managers.machine.FurnaceManager;
+import cofh.thermalexpansion.util.managers.machine.FurnaceManager.FurnaceRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.FurnaceManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.FurnaceRecipeAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
+import com.cleanroommc.groovyscript.registry.AbstractReloadableStorage;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+@RegistryDescription
+public class Furnace extends VirtualizedRegistry {
+
+ private final AbstractReloadableStorage foodStorage = new AbstractReloadableStorage<>();
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('minecraft:diamond')).output(item('minecraft:clay') * 2)"),
+ @Example(".input(item('minecraft:gold_ingot') * 2).output(item('minecraft:clay')).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> FurnaceManagerAccessor.getRecipeMap().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> FurnaceManagerAccessor.getRecipeMap().put(FurnaceManager.convertInput(r.getInput()), r));
+ foodStorage.removeScripted().forEach(r -> FurnaceManagerAccessor.getFoodSet().add(FurnaceManager.convertInput(r)));
+ foodStorage.restoreFromBackup().forEach(r -> FurnaceManagerAccessor.getFoodSet().remove(FurnaceManager.convertInput(r)));
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("item('minecraft:emerald_ore')"))
+ public boolean addFood(ItemStack item) {
+ return FurnaceManagerAccessor.getFoodSet().add(FurnaceManager.convertInput(item)) && foodStorage.addScripted(item);
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:rabbit:*')"))
+ public boolean removeFood(ItemStack item) {
+ return FurnaceManagerAccessor.getFoodSet().remove(FurnaceManager.convertInput(item)) && foodStorage.addBackup(item);
+ }
+
+ public void add(FurnaceRecipe recipe) {
+ FurnaceManagerAccessor.getRecipeMap().put(FurnaceManager.convertInput(recipe.getInput()), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("1000, item('minecraft:obsidian') * 2, item('minecraft:clay')"))
+ public FurnaceRecipe add(int energy, IIngredient input, ItemStack output) {
+ return recipeBuilder()
+ .energy(energy)
+ .input(input)
+ .output(output)
+ .register();
+ }
+
+ public boolean remove(FurnaceRecipe recipe) {
+ return FurnaceManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:cactus:*')"))
+ public boolean removeByInput(IIngredient input) {
+ return FurnaceManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (input.test(r.getInput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:cooked_porkchop')"))
+ public boolean removeByOutput(IIngredient output) {
+ return FurnaceManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (output.test(r.getOutput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(FurnaceManagerAccessor.getRecipeMap().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAllFood() {
+ FurnaceManagerAccessor.getFoodSet().forEach(x -> foodStorage.addBackup(x.toItemStack()));
+ FurnaceManagerAccessor.getFoodSet().clear();
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ FurnaceManagerAccessor.getRecipeMap().values().forEach(this::addBackup);
+ FurnaceManagerAccessor.getRecipeMap().clear();
+ }
+
+ @Property(property = "input", valid = @Comp("1"))
+ @Property(property = "output", valid = @Comp("1"))
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "FurnaceManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = FurnaceManager.DEFAULT_ENERGY;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Furnace recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 1, 1, 1, 1);
+ validateFluids(msg);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable FurnaceRecipe register() {
+ if (!validate()) return null;
+ FurnaceRecipe recipe = null;
+
+ for (ItemStack itemStack : input.get(0).getMatchingStacks()) {
+ FurnaceRecipe recipe1 = FurnaceRecipeAccessor.createFurnaceRecipe(itemStack, output.get(0), energy);
+ ModSupport.THERMAL_EXPANSION.get().furnace.add(recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/FurnacePyrolysis.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/FurnacePyrolysis.java
new file mode 100644
index 000000000..8a351b38e
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/FurnacePyrolysis.java
@@ -0,0 +1,144 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.thermalexpansion.util.managers.machine.FurnaceManager;
+import cofh.thermalexpansion.util.managers.machine.FurnaceManager.FurnaceRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.FurnaceManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.FurnaceRecipeAccessor;
+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.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+@RegistryDescription
+public class FurnacePyrolysis extends VirtualizedRegistry {
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('minecraft:clay')).output(item('minecraft:diamond') * 2).creosote(100)"),
+ @Example(".input(item('minecraft:gold_ingot') * 2).output(item('minecraft:clay')).creosote(1000).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> FurnaceManagerAccessor.getRecipeMapPyrolysis().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> FurnaceManagerAccessor.getRecipeMapPyrolysis().put(FurnaceManager.convertInput(r.getInput()), r));
+ }
+
+ public void add(FurnaceRecipe recipe) {
+ FurnaceManagerAccessor.getRecipeMapPyrolysis().put(FurnaceManager.convertInput(recipe.getInput()), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("1000, item('minecraft:obsidian') * 2, item('minecraft:clay'), 1000"))
+ public FurnaceRecipe add(int energy, IIngredient input, ItemStack output, int creosote) {
+ return recipeBuilder()
+ .energy(energy)
+ .creosote(creosote)
+ .input(input)
+ .output(output)
+ .register();
+ }
+
+ public boolean remove(FurnaceRecipe recipe) {
+ return FurnaceManagerAccessor.getRecipeMapPyrolysis().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:cactus:*')"))
+ public boolean removeByInput(IIngredient input) {
+ return FurnaceManagerAccessor.getRecipeMapPyrolysis().values().removeIf(r -> {
+ if (input.test(r.getInput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('thermalfoundation:storage_resource:1')"))
+ public boolean removeByOutput(IIngredient output) {
+ return FurnaceManagerAccessor.getRecipeMapPyrolysis().values().removeIf(r -> {
+ if (output.test(r.getOutput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(FurnaceManagerAccessor.getRecipeMapPyrolysis().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ FurnaceManagerAccessor.getRecipeMapPyrolysis().values().forEach(this::addBackup);
+ FurnaceManagerAccessor.getRecipeMapPyrolysis().clear();
+ }
+
+ @Property(property = "input", valid = @Comp("1"))
+ @Property(property = "output", valid = @Comp("1"))
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "FurnaceManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = FurnaceManager.DEFAULT_ENERGY;
+ @Property(valid = @Comp(value = "0", type = Comp.Type.GTE))
+ private int creosote;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder creosote(int creosote) {
+ this.creosote = creosote;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Furnace Pyrolysis recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 1, 1, 1, 1);
+ validateFluids(msg);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ msg.add(creosote < 0, "creosote must be greater than or equal to 0, yet it was {}", creosote);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable FurnaceRecipe register() {
+ if (!validate()) return null;
+ FurnaceRecipe recipe = null;
+
+ for (ItemStack itemStack : input.get(0).getMatchingStacks()) {
+ FurnaceRecipe recipe1 = FurnaceRecipeAccessor.createFurnaceRecipe(itemStack, output.get(0), energy, creosote);
+ ModSupport.THERMAL_EXPANSION.get().furnacePyrolysis.add(recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Insolator.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Insolator.java
new file mode 100644
index 000000000..e666ffdf2
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Insolator.java
@@ -0,0 +1,223 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.core.inventory.ComparableItemStackValidatedNBT;
+import cofh.thermalexpansion.util.managers.machine.InsolatorManager;
+import cofh.thermalexpansion.util.managers.machine.InsolatorManager.InsolatorRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.InsolatorManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.InsolatorRecipeAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
+import com.cleanroommc.groovyscript.registry.AbstractReloadableStorage;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RegistryDescription
+public class Insolator extends VirtualizedRegistry {
+
+ private final AbstractReloadableStorage fertilizerStorage = new AbstractReloadableStorage<>();
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('minecraft:clay'), item('minecraft:diamond')).output(item('minecraft:diamond') * 4)"),
+ @Example(".input(item('minecraft:clay'), item('minecraft:gold_ingot') * 2).output(item('minecraft:clay'), item('minecraft:diamond')).chance(5).water(100).tree().energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> InsolatorManagerAccessor.getRecipeMap().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> InsolatorManagerAccessor.getRecipeMap().put(hash(r), r));
+ fertilizerStorage.removeScripted().forEach(recipe -> InsolatorManagerAccessor.getLockSet().removeIf(r -> r.equals(InsolatorManager.convertInput(recipe))));
+ fertilizerStorage.restoreFromBackup().forEach(r -> InsolatorManagerAccessor.getLockSet().add(InsolatorManager.convertInput(r)));
+ }
+
+ private List hash(InsolatorRecipe recipe) {
+ return hash(recipe.getPrimaryInput(), recipe.getSecondaryInput());
+ }
+
+ private List hash(ItemStack primaryInput, ItemStack secondaryInput) {
+ return Arrays.asList(InsolatorManager.convertInput(primaryInput), InsolatorManager.convertInput(secondaryInput));
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void afterScriptLoad() {
+ InsolatorManagerAccessor.getValidationSet().clear();
+ InsolatorManagerAccessor.getValidationSet().addAll(
+ InsolatorManagerAccessor.getRecipeMap().values().stream().map(InsolatorRecipe::getPrimaryInput).map(InsolatorManager::convertInput).collect(Collectors.toList())
+ );
+ InsolatorManagerAccessor.getValidationSet().addAll(
+ InsolatorManagerAccessor.getRecipeMap().values().stream().map(InsolatorRecipe::getSecondaryInput).map(InsolatorManager::convertInput).collect(Collectors.toList())
+ );
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION)
+ public boolean addFertilizer(ItemStack itemStack) {
+ return InsolatorManagerAccessor.getLockSet().add(InsolatorManager.convertInput(itemStack)) && fertilizerStorage.addScripted(itemStack);
+ }
+
+ @MethodDescription
+ public boolean removeFertilizer(ItemStack itemStack) {
+ return InsolatorManagerAccessor.getLockSet().removeIf(r -> r.equals(InsolatorManager.convertInput(itemStack))) && fertilizerStorage.addBackup(itemStack);
+ }
+
+ public void add(InsolatorRecipe recipe) {
+ InsolatorManagerAccessor.getRecipeMap().put(hash(recipe), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example(value = "1000, 100, item('minecraft:obsidian'), item('minecraft:gold_ingot') * 2, item('minecraft:clay'), item('minecraft:diamond'), 5, InsolatorManager.Type.TREE", imports = "cofh.thermalexpansion.util.managers.machine.InsolatorManager"))
+ public InsolatorRecipe add(int energy, int water, IIngredient primaryInput, IIngredient secondaryInput, ItemStack primaryOutput, ItemStack secondaryOutput, int secondaryChance, InsolatorManager.Type type) {
+ return recipeBuilder()
+ .energy(energy)
+ .water(water)
+ .chance(secondaryChance)
+ .type(type)
+ .input(primaryInput, secondaryInput)
+ .output(primaryOutput, secondaryOutput)
+ .register();
+ }
+
+ public boolean remove(InsolatorRecipe recipe) {
+ return InsolatorManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = {
+ @Example("item('thermalfoundation:fertilizer')"), @Example("item('minecraft:double_plant:4')")
+ })
+ public boolean removeByInput(IIngredient input) {
+ return InsolatorManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (input.test(r.getPrimaryInput()) || input.test(r.getSecondaryInput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = {
+ @Example("item('minecraft:red_flower:6')"), @Example("item('minecraft:melon_seeds')")
+ })
+ public boolean removeByOutput(IIngredient output) {
+ return InsolatorManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (output.test(r.getPrimaryOutput()) || output.test(r.getSecondaryOutput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(InsolatorManagerAccessor.getRecipeMap().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ InsolatorManagerAccessor.getRecipeMap().values().forEach(this::addBackup);
+ InsolatorManagerAccessor.getRecipeMap().clear();
+ }
+
+ @Property(property = "input", valid = @Comp("2"))
+ @Property(property = "output", valid = {@Comp(type = Comp.Type.GTE, value = "1"), @Comp(type = Comp.Type.LTE, value = "2")})
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "InsolatorManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = InsolatorManager.DEFAULT_ENERGY;
+ @Property(valid = @Comp(value = "0", type = Comp.Type.GTE))
+ private int water;
+ @Property(valid = @Comp(value = "0", type = Comp.Type.GTE))
+ private int chance;
+ @Property(defaultValue = "InsolatorManager.Type.STANDARD")
+ private InsolatorManager.Type type = InsolatorManager.Type.STANDARD;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder water(int water) {
+ this.water = water;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder chance(int chance) {
+ this.chance = chance;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder type(InsolatorManager.Type type) {
+ this.type = type;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription(field = "type")
+ public RecipeBuilder tree() {
+ this.type = InsolatorManager.Type.TREE;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription(field = "type")
+ public RecipeBuilder standard() {
+ this.type = InsolatorManager.Type.STANDARD;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Insolator recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 2, 2, 1, 2);
+ validateFluids(msg);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ msg.add(water < 0, "water must be greater than or equal to 0, yet it was {}", water);
+ msg.add(chance < 0, "chance must be greater than or equal to 0, yet it was {}", chance);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable InsolatorRecipe register() {
+ if (!validate()) return null;
+ InsolatorRecipe recipe = null;
+
+ for (ItemStack input0 : input.get(0).getMatchingStacks()) {
+ for (ItemStack input1 : input.get(1).getMatchingStacks()) {
+ InsolatorRecipe recipe1 = InsolatorRecipeAccessor.createInsolatorRecipe(input1, input0, output.get(0), output.getOrEmpty(1), chance, energy, water, type);
+ ModSupport.THERMAL_EXPANSION.get().insolator.add(recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+
+ }
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Precipitator.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Precipitator.java
new file mode 100644
index 000000000..58152144e
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Precipitator.java
@@ -0,0 +1,152 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.core.util.ItemWrapper;
+import cofh.thermalexpansion.util.managers.machine.PrecipitatorManager;
+import cofh.thermalexpansion.util.managers.machine.PrecipitatorManager.PrecipitatorRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.PrecipitatorManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.PrecipitatorRecipeAccessor;
+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.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.stream.Collectors;
+
+@RegistryDescription
+public class Precipitator extends VirtualizedRegistry {
+
+ @RecipeBuilderDescription(example = {
+ @Example(".output(item('minecraft:clay'))"),
+ @Example(".water(100).output(item('minecraft:clay')).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> PrecipitatorManagerAccessor.getRecipeMap().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> PrecipitatorManagerAccessor.getRecipeMap().put(new ItemWrapper(r.getOutput()), r));
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void afterScriptLoad() {
+ PrecipitatorManagerAccessor.getOutputList().clear();
+ PrecipitatorManagerAccessor.getOutputList().addAll(
+ PrecipitatorManagerAccessor.getRecipeMap().values().stream().map(PrecipitatorManager.PrecipitatorRecipe::getOutput).collect(Collectors.toList())
+ );
+ }
+
+ public void add(PrecipitatorRecipe recipe) {
+ PrecipitatorManagerAccessor.getRecipeMap().put(new ItemWrapper(recipe.getOutput()), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("1000, item('minecraft:obsidian'), 100"))
+ public PrecipitatorRecipe add(int energy, ItemStack output, int water) {
+ return recipeBuilder()
+ .energy(energy)
+ .water(water)
+ .output(output)
+ .register();
+ }
+
+ public boolean remove(PrecipitatorRecipe recipe) {
+ return PrecipitatorManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example(value = "fluid('water')", commented = true))
+ public boolean removeByInput(IIngredient input) {
+ return PrecipitatorManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (input.test(r.getInput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:snowball')"))
+ public boolean removeByOutput(IIngredient output) {
+ return PrecipitatorManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (output.test(r.getOutput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(PrecipitatorManagerAccessor.getRecipeMap().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ PrecipitatorManagerAccessor.getRecipeMap().values().forEach(this::addBackup);
+ PrecipitatorManagerAccessor.getRecipeMap().clear();
+ }
+
+ @Property(property = "output", valid = @Comp("1"))
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "PrecipitatorManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = PrecipitatorManager.DEFAULT_ENERGY;
+ @Property(valid = @Comp(value = "0", type = Comp.Type.GTE))
+ private int water;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder water(int water) {
+ this.water = water;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Precipitator recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 0, 0, 1, 1);
+ validateFluids(msg);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ msg.add(water < 0, "water must be greater than or equal to 0, yet it was {}", water);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable PrecipitatorRecipe register() {
+ if (!validate()) return null;
+ PrecipitatorRecipe recipe = PrecipitatorRecipeAccessor.createPrecipitatorRecipe(output.get(0), new FluidStack(FluidRegistry.WATER, water), energy);
+ ModSupport.THERMAL_EXPANSION.get().precipitator.add(recipe);
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Pulverizer.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Pulverizer.java
new file mode 100644
index 000000000..0c6686fad
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Pulverizer.java
@@ -0,0 +1,146 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.thermalexpansion.util.managers.machine.PulverizerManager;
+import cofh.thermalexpansion.util.managers.machine.PulverizerManager.PulverizerRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.PulverizerManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.PulverizerRecipeAccessor;
+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.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+@RegistryDescription
+public class Pulverizer extends VirtualizedRegistry {
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('minecraft:diamond')).output(item('minecraft:clay'), item('minecraft:diamond')).chance(1)"),
+ @Example(".input(item('minecraft:clay')).output(item('minecraft:gold_ingot'), item('minecraft:gold_ingot')).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> PulverizerManagerAccessor.getRecipeMap().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> PulverizerManagerAccessor.getRecipeMap().put(PulverizerManager.convertInput(r.getInput()), r));
+ }
+
+ public void add(PulverizerRecipe recipe) {
+ PulverizerManagerAccessor.getRecipeMap().put(PulverizerManager.convertInput(recipe.getInput()), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("1000, item('minecraft:obsidian'), item('minecraft:gold_ingot'), item('minecraft:gold_ingot'), 100"))
+ public PulverizerRecipe add(int energy, IIngredient input, ItemStack primaryOutput, ItemStack secondaryOutput, int chance) {
+ return recipeBuilder()
+ .energy(energy)
+ .chance(chance)
+ .output(primaryOutput, secondaryOutput)
+ .input(input)
+ .register();
+ }
+
+ public boolean remove(PulverizerRecipe recipe) {
+ return PulverizerManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:emerald_ore')"))
+ public boolean removeByInput(IIngredient input) {
+ return PulverizerManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (input.test(r.getInput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = {
+ @Example("item('thermalfoundation:material:772')"), @Example("item('minecraft:diamond')")
+ })
+ public boolean removeByOutput(IIngredient output) {
+ return PulverizerManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (output.test(r.getPrimaryOutput()) || output.test(r.getSecondaryOutput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(PulverizerManagerAccessor.getRecipeMap().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ PulverizerManagerAccessor.getRecipeMap().values().forEach(this::addBackup);
+ PulverizerManagerAccessor.getRecipeMap().clear();
+ }
+
+ @Property(property = "input", valid = {@Comp(type = Comp.Type.GTE, value = "1"), @Comp(type = Comp.Type.LTE, value = "2")})
+ @Property(property = "output", valid = {@Comp(type = Comp.Type.GTE, value = "1"), @Comp(type = Comp.Type.LTE, value = "2")})
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "PulverizerManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = PulverizerManager.DEFAULT_ENERGY;
+ @Property(valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "100")})
+ private int chance;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder chance(int chance) {
+ this.chance = chance;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Pulverizer recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 1, 2, 1, 2);
+ validateFluids(msg);
+ msg.add(chance < 0 || chance > 100, "chance must be a non negative integer less than 100, yet it was {}", chance);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable PulverizerRecipe register() {
+ if (!validate()) return null;
+ PulverizerRecipe recipe = null;
+
+ for (ItemStack itemStack : input.get(0).getMatchingStacks()) {
+ PulverizerRecipe recipe1 = PulverizerRecipeAccessor.createPulverizerRecipe(itemStack, output.get(0), output.getOrEmpty(1), chance, energy);
+ ModSupport.THERMAL_EXPANSION.get().pulverizer.add(recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Refinery.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Refinery.java
new file mode 100644
index 000000000..2168446ee
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Refinery.java
@@ -0,0 +1,228 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.core.util.helpers.FluidHelper;
+import cofh.thermalexpansion.util.managers.machine.RefineryManager;
+import cofh.thermalexpansion.util.managers.machine.RefineryManager.RefineryRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.RefineryManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.RefineryRecipeAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
+import com.cleanroommc.groovyscript.registry.AbstractReloadableStorage;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+@RegistryDescription(
+ admonition = @Admonition("groovyscript.wiki.thermalexpansion.refinery.note0")
+)
+public class Refinery extends VirtualizedRegistry {
+
+ private final AbstractReloadableStorage fossilFuelStorage = new AbstractReloadableStorage<>();
+ private final AbstractReloadableStorage bioFuelStorage = new AbstractReloadableStorage<>();
+
+ @RecipeBuilderDescription(example = {
+ @Example(".fluidInput(fluid('water') * 100).fluidOutput(fluid('steam') * 80)"),
+ @Example(".fluidInput(fluid('lava') * 100).fluidOutput(fluid('steam') * 150).output(item('minecraft:clay')).chance(25).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> RefineryManagerAccessor.getRecipeMap().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> RefineryManagerAccessor.getRecipeMap().put(FluidHelper.getFluidHash(r.getInput()), r));
+ fossilFuelStorage.removeScripted().forEach(RefineryManagerAccessor.getFossilFluids()::add);
+ fossilFuelStorage.restoreFromBackup().forEach(RefineryManagerAccessor.getFossilFluids()::remove);
+ bioFuelStorage.removeScripted().forEach(RefineryManagerAccessor.getBioFluids()::add);
+ bioFuelStorage.restoreFromBackup().forEach(RefineryManagerAccessor.getBioFluids()::remove);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION)
+ public boolean addFossilFuel(String name) {
+ return RefineryManagerAccessor.getFossilFluids().add(name) && fossilFuelStorage.addScripted(name);
+ }
+
+ @MethodDescription
+ public boolean removeFossilFuel(String name) {
+ return RefineryManagerAccessor.getFossilFluids().remove(name) && fossilFuelStorage.addBackup(name);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION)
+ public boolean addFossilFuel(Fluid fluid) {
+ return addFossilFuel(fluid.getName());
+ }
+
+ @MethodDescription
+ public boolean removeFossilFuel(Fluid fluid) {
+ return removeFossilFuel(fluid.getName());
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("fluid('crude_oil')"))
+ public boolean addFossilFuel(FluidStack fluid) {
+ return addFossilFuel(fluid.getFluid());
+ }
+
+ @MethodDescription(example = @Example("fluid('coal')"))
+ public boolean removeFossilFuel(FluidStack fluid) {
+ return removeFossilFuel(fluid.getFluid());
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION)
+ public boolean addBioFuel(String name) {
+ return RefineryManagerAccessor.getBioFluids().add(name) && bioFuelStorage.addScripted(name);
+ }
+
+ @MethodDescription
+ public boolean removeBioFuel(String name) {
+ return RefineryManagerAccessor.getBioFluids().remove(name) && bioFuelStorage.addBackup(name);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION)
+ public boolean addBioFuel(Fluid fluid) {
+ return addBioFuel(fluid.getName());
+ }
+
+ @MethodDescription
+ public boolean removeBioFuel(Fluid fluid) {
+ return removeBioFuel(fluid.getName());
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("fluid('coal')"))
+ public boolean addBioFuel(FluidStack fluid) {
+ return addBioFuel(fluid.getFluid());
+ }
+
+ @MethodDescription(example = @Example("fluid('resin')"))
+ public boolean removeBioFuel(FluidStack fluid) {
+ return removeBioFuel(fluid.getFluid());
+ }
+
+ public void add(RefineryRecipe recipe) {
+ RefineryManagerAccessor.getRecipeMap().put(FluidHelper.getFluidHash(recipe.getInput()), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("1000, fluid('ender') * 100, fluid('steam') * 150, item('minecraft:clay'), 25"))
+ public RefineryRecipe add(int energy, FluidStack fluidInput, FluidStack outputFluid, ItemStack outputItem, int chance) {
+ return recipeBuilder()
+ .energy(energy)
+ .chance(chance)
+ .fluidInput(fluidInput)
+ .fluidOutput(outputFluid)
+ .output(outputItem)
+ .register();
+ }
+
+ public boolean remove(RefineryRecipe recipe) {
+ return RefineryManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("fluid('resin')"))
+ public boolean removeByInput(IIngredient input) {
+ return RefineryManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (input.test(r.getInput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = {
+ @Example(value = "item('thermalfoundation:material:771')", commented = true), @Example("fluid('refined_biofuel')")
+ })
+ public boolean removeByOutput(IIngredient output) {
+ return RefineryManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (output.test(r.getOutputFluid()) || output.test(r.getOutputItem())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(RefineryManagerAccessor.getRecipeMap().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAllFossilFuels() {
+ RefineryManagerAccessor.getFossilFluids().forEach(fossilFuelStorage::addBackup);
+ RefineryManagerAccessor.getFossilFluids().clear();
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAllBioFuels() {
+ RefineryManagerAccessor.getBioFluids().forEach(bioFuelStorage::addBackup);
+ RefineryManagerAccessor.getBioFluids().clear();
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ RefineryManagerAccessor.getRecipeMap().values().forEach(this::addBackup);
+ RefineryManagerAccessor.getRecipeMap().clear();
+ }
+
+ @Property(property = "fluidInput", valid = @Comp("1"))
+ @Property(property = "output", valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "1")})
+ @Property(property = "fluidOutput", valid = @Comp("1"))
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "RefineryManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = RefineryManager.DEFAULT_ENERGY;
+ @Property(valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "100")})
+ private int chance;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder chance(int chance) {
+ this.chance = chance;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Refinery recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 0, 0, 0, 1);
+ validateFluids(msg, 1, 1, 1, 1);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ msg.add(chance < 0 || chance > 100, "chance must be a non negative integer less than 100, yet it was {}", chance);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable RefineryRecipe register() {
+ if (!validate()) return null;
+ RefineryRecipe recipe = RefineryRecipeAccessor.createRefineryRecipe(fluidInput.get(0), fluidOutput.get(0), output.getOrEmpty(0), energy, chance);
+ ModSupport.THERMAL_EXPANSION.get().refinery.add(recipe);
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/RefineryPotion.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/RefineryPotion.java
new file mode 100644
index 000000000..10f6c3a83
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/RefineryPotion.java
@@ -0,0 +1,143 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.core.util.helpers.FluidHelper;
+import cofh.thermalexpansion.util.managers.machine.RefineryManager;
+import cofh.thermalexpansion.util.managers.machine.RefineryManager.RefineryRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.RefineryManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.RefineryRecipeAccessor;
+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.FluidStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+@RegistryDescription
+public class RefineryPotion extends VirtualizedRegistry {
+
+ @RecipeBuilderDescription(example = {
+ @Example(".fluidInput(fluid('water') * 100).fluidOutput(fluid('steam') * 200)"),
+ @Example(".fluidInput(fluid('lava') * 100).fluidOutput(fluid('steam') * 30).output(item('minecraft:clay')).chance(75).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> RefineryManagerAccessor.getRecipeMapPotion().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> RefineryManagerAccessor.getRecipeMapPotion().put(FluidHelper.getFluidHash(r.getInput()), r));
+ }
+
+ public void add(RefineryRecipe recipe) {
+ RefineryManagerAccessor.getRecipeMapPotion().put(FluidHelper.getFluidHash(recipe.getInput()), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("1000, fluid('ender') * 100, fluid('steam') * 30, item('minecraft:clay'), 75"))
+ public RefineryRecipe add(int energy, FluidStack fluidInput, FluidStack outputFluid, ItemStack outputItem, int chance) {
+ return recipeBuilder()
+ .energy(energy)
+ .chance(chance)
+ .fluidInput(fluidInput)
+ .fluidOutput(outputFluid)
+ .output(outputItem)
+ .register();
+ }
+
+ public boolean remove(RefineryRecipe recipe) {
+ return RefineryManagerAccessor.getRecipeMapPotion().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("fluid('potion_lingering').withNbt(['Potion': 'cofhcore:healing3'])"))
+ public boolean removeByInput(IIngredient input) {
+ return RefineryManagerAccessor.getRecipeMapPotion().values().removeIf(r -> {
+ if (input.test(r.getInput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("fluid('potion_splash').withNbt(['Potion': 'cofhcore:leaping4'])"))
+ public boolean removeByOutput(IIngredient output) {
+ return RefineryManagerAccessor.getRecipeMapPotion().values().removeIf(r -> {
+ if (output.test(r.getOutputFluid()) || output.test(r.getOutputItem())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(RefineryManagerAccessor.getRecipeMapPotion().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ RefineryManagerAccessor.getRecipeMapPotion().values().forEach(this::addBackup);
+ RefineryManagerAccessor.getRecipeMapPotion().clear();
+ }
+
+ @Property(property = "fluidInput", valid = @Comp("1"))
+ @Property(property = "output", valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "1")})
+ @Property(property = "fluidOutput", valid = @Comp("1"))
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "RefineryManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = RefineryManager.DEFAULT_ENERGY;
+ @Property(valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "100")})
+ private int chance;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder chance(int chance) {
+ this.chance = chance;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Refinery recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 0, 0, 0, 1);
+ validateFluids(msg, 1, 1, 1, 1);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ msg.add(chance < 0 || chance > 100, "chance must be a non negative integer less than 100, yet it was {}", chance);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable RefineryRecipe register() {
+ if (!validate()) return null;
+ RefineryRecipe recipe = RefineryRecipeAccessor.createRefineryRecipe(fluidInput.get(0), fluidOutput.get(0), output.getOrEmpty(0), energy, chance);
+ ModSupport.THERMAL_EXPANSION.get().refineryPotion.add(recipe);
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Sawmill.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Sawmill.java
new file mode 100644
index 000000000..66e2da7c3
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Sawmill.java
@@ -0,0 +1,148 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.thermalexpansion.util.managers.machine.SawmillManager;
+import cofh.thermalexpansion.util.managers.machine.SawmillManager.SawmillRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.SawmillManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.SawmillRecipeAccessor;
+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.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+@RegistryDescription(
+ admonition = @Admonition("groovyscript.wiki.thermalexpansion.sawmill.note0")
+)
+public class Sawmill extends VirtualizedRegistry {
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('minecraft:diamond')).output(item('minecraft:gold_ingot') * 2)"),
+ @Example(".input(item('minecraft:clay') * 4).output(item('minecraft:gold_ingot'), item('minecraft:diamond')).chance(25).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> SawmillManagerAccessor.getRecipeMap().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> SawmillManagerAccessor.getRecipeMap().put(SawmillManager.convertInput(r.getInput()), r));
+ }
+
+ public void add(SawmillRecipe recipe) {
+ SawmillManagerAccessor.getRecipeMap().put(SawmillManager.convertInput(recipe.getInput()), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("1000, item('minecraft:obsidian') * 4, item('minecraft:gold_ingot'), item('minecraft:diamond'), 25"))
+ public SawmillRecipe add(int energy, IIngredient input, ItemStack outputItem, ItemStack secondayOutput, int chance) {
+ return recipeBuilder()
+ .energy(energy)
+ .chance(chance)
+ .input(input)
+ .output(outputItem, secondayOutput)
+ .register();
+ }
+
+ public boolean remove(SawmillRecipe recipe) {
+ return SawmillManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:pumpkin')"))
+ public boolean removeByInput(IIngredient input) {
+ return SawmillManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (input.test(r.getInput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = {
+ @Example("item('thermalfoundation:material:800')"), @Example("item('minecraft:leather')")
+ })
+ public boolean removeByOutput(IIngredient output) {
+ return SawmillManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (output.test(r.getPrimaryOutput()) || output.test(r.getSecondaryOutput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(SawmillManagerAccessor.getRecipeMap().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ SawmillManagerAccessor.getRecipeMap().values().forEach(this::addBackup);
+ SawmillManagerAccessor.getRecipeMap().clear();
+ }
+
+ @Property(property = "input", valid = @Comp("1"))
+ @Property(property = "output", valid = {@Comp(type = Comp.Type.GTE, value = "1"), @Comp(type = Comp.Type.LTE, value = "2")})
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "SawmillManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = SawmillManager.DEFAULT_ENERGY;
+ @Property(valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "100")})
+ private int chance;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder chance(int chance) {
+ this.chance = chance;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Sawmill recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 1, 1, 1, 2);
+ validateFluids(msg);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ msg.add(chance < 0 || chance > 100, "chance must be a non negative integer less than 100, yet it was {}", chance);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable SawmillRecipe register() {
+ if (!validate()) return null;
+ SawmillRecipe recipe = null;
+
+ for (ItemStack itemStack : input.get(0).getMatchingStacks()) {
+ SawmillRecipe recipe1 = SawmillRecipeAccessor.createSawmillRecipe(itemStack, output.get(0), output.getOrEmpty(1), chance, energy);
+ ModSupport.THERMAL_EXPANSION.get().sawmill.add(recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Smelter.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Smelter.java
new file mode 100644
index 000000000..df664c4ca
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/Smelter.java
@@ -0,0 +1,174 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.core.inventory.ComparableItemStackValidatedNBT;
+import cofh.thermalexpansion.util.managers.machine.SmelterManager;
+import cofh.thermalexpansion.util.managers.machine.SmelterManager.SmelterRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.SmelterManagerAccessor;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.SmelterRecipeAccessor;
+import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
+import com.cleanroommc.groovyscript.registry.AbstractReloadableStorage;
+import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.List;
+
+@RegistryDescription
+public class Smelter extends VirtualizedRegistry {
+
+ private final AbstractReloadableStorage fluxStorage = new AbstractReloadableStorage<>();
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('minecraft:clay'), item('minecraft:diamond')).output(item('minecraft:diamond') * 4)"),
+ @Example(".input(item('minecraft:clay'), item('minecraft:gold_ingot') * 2).output(item('minecraft:clay'), item('minecraft:diamond')).chance(5).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> SmelterManagerAccessor.getRecipeMap().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> SmelterManagerAccessor.getRecipeMap().put(hash(r), r));
+ fluxStorage.removeScripted().forEach(recipe -> SmelterManagerAccessor.getLockSet().removeIf(r -> r.equals(SmelterManager.convertInput(recipe))));
+ fluxStorage.restoreFromBackup().forEach(r -> SmelterManagerAccessor.getLockSet().add(SmelterManager.convertInput(r)));
+ }
+
+ private List hash(SmelterRecipe recipe) {
+ return hash(recipe.getPrimaryInput(), recipe.getSecondaryInput());
+ }
+
+ private List hash(ItemStack primaryInput, ItemStack secondaryInput) {
+ return Arrays.asList(SmelterManager.convertInput(primaryInput), SmelterManager.convertInput(secondaryInput));
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION)
+ public boolean addFlux(ItemStack itemStack) {
+ return SmelterManagerAccessor.getLockSet().add(SmelterManager.convertInput(itemStack)) && fluxStorage.addScripted(itemStack);
+ }
+
+ @MethodDescription
+ public boolean removeFlux(ItemStack itemStack) {
+ return SmelterManagerAccessor.getLockSet().removeIf(r -> r.equals(SmelterManager.convertInput(itemStack))) && fluxStorage.addBackup(itemStack);
+ }
+
+ public void add(SmelterRecipe recipe) {
+ SmelterManagerAccessor.getRecipeMap().put(hash(recipe), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example(value = "1000, item('minecraft:obsidian'), item('minecraft:gold_ingot') * 2, item('minecraft:clay'), item('minecraft:diamond'), 5", commented = true))
+ public SmelterRecipe add(int energy, IIngredient input0, IIngredient input1, ItemStack output0, ItemStack output1, int chance) {
+ return recipeBuilder()
+ .energy(energy)
+ .chance(chance)
+ .input(input0, input1)
+ .output(output0, output1)
+ .register();
+ }
+
+ public boolean remove(SmelterRecipe recipe) {
+ return SmelterManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = {
+ @Example("ore('sand')"), @Example("item('minecraft:iron_ingot')")
+ })
+ public boolean removeByInput(IIngredient input) {
+ return SmelterManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (input.test(r.getPrimaryInput()) || input.test(r.getSecondaryInput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('thermalfoundation:material:166')"))
+ public boolean removeByOutput(IIngredient output) {
+ return SmelterManagerAccessor.getRecipeMap().values().removeIf(r -> {
+ if (output.test(r.getPrimaryOutput()) || output.test(r.getSecondaryOutput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(SmelterManagerAccessor.getRecipeMap().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ SmelterManagerAccessor.getRecipeMap().values().forEach(this::addBackup);
+ SmelterManagerAccessor.getRecipeMap().clear();
+ }
+
+ @Property(property = "input", valid = @Comp("2"))
+ @Property(property = "output", valid = {@Comp(type = Comp.Type.GTE, value = "1"), @Comp(type = Comp.Type.LTE, value = "2")})
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "SmelterManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = SmelterManager.DEFAULT_ENERGY;
+ @Property(valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "100")})
+ private int chance;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder chance(int chance) {
+ this.chance = chance;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Smelter recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 2, 2, 1, 2);
+ validateFluids(msg);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ msg.add(chance < 0 || chance > 100, "chance must be a non negative integer less than 100, yet it was {}", chance);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable SmelterRecipe register() {
+ if (!validate()) return null;
+ SmelterRecipe recipe = null;
+ for (ItemStack input0 : input.get(0).getMatchingStacks()) {
+ for (ItemStack input1 : input.get(1).getMatchingStacks()) {
+ SmelterRecipe recipe1 = SmelterRecipeAccessor.createSmelterRecipe(input0, input1, output.get(0), output.getOrEmpty(1), chance, energy);
+ ModSupport.THERMAL_EXPANSION.get().smelter.add(recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ }
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/TransposerExtract.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/TransposerExtract.java
new file mode 100644
index 000000000..8495db7ee
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/TransposerExtract.java
@@ -0,0 +1,164 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.thermalexpansion.util.managers.machine.TransposerManager;
+import cofh.thermalexpansion.util.managers.machine.TransposerManager.TransposerRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.TransposerManagerAccessor;
+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.FluidStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.stream.Collectors;
+
+@RegistryDescription(
+ admonition = @Admonition("groovyscript.wiki.thermalexpansion.transposer.note0")
+)
+public class TransposerExtract extends VirtualizedRegistry {
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('minecraft:diamond') * 2).fluidOutput(fluid('water') * 100)"),
+ @Example(".input(item('minecraft:clay')).output(item('minecraft:diamond') * 2).fluidOutput(fluid('water') * 50).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> TransposerManagerAccessor.getRecipeMapExtract().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> TransposerManagerAccessor.getRecipeMapExtract().put(TransposerManager.convertInput(r.getInput()), r));
+ }
+
+ @Override
+ @GroovyBlacklist
+ public void afterScriptLoad() {
+ TransposerManagerAccessor.getValidationSet().clear();
+ TransposerManagerAccessor.getValidationSet().addAll(
+ TransposerManagerAccessor.getRecipeMapExtract().values().stream().map(TransposerManager.TransposerRecipe::getInput).map(TransposerManager::convertInput).collect(Collectors.toList())
+ );
+ TransposerManagerAccessor.getValidationSet().clear();
+ TransposerManagerAccessor.getValidationSet().addAll(
+ TransposerManagerAccessor.getRecipeMapFill().values().stream().map(TransposerManager.TransposerRecipe::getInput).map(TransposerManager::convertInput).collect(Collectors.toList())
+ );
+ }
+
+ public void add(TransposerRecipe recipe) {
+ TransposerManagerAccessor.getRecipeMapExtract().put(TransposerManager.convertInput(recipe.getInput()), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("1000, item('minecraft:obsidian'), fluid('water') * 50, item('minecraft:diamond') * 2, 100"))
+ public TransposerRecipe add(int energy, IIngredient input, FluidStack outputFluid, ItemStack outputItem, int chance) {
+ return recipeBuilder()
+ .energy(energy)
+ .chance(chance)
+ .input(input)
+ .fluidOutput(outputFluid)
+ .output(outputItem)
+ .register();
+ }
+
+ public boolean remove(TransposerRecipe recipe) {
+ return TransposerManagerAccessor.getRecipeMapExtract().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:sponge:1')"))
+ public boolean removeByInput(IIngredient input) {
+ return TransposerManagerAccessor.getRecipeMapExtract().values().removeIf(r -> {
+ if (input.test(r.getInput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = {
+ @Example("fluid('seed_oil')"), @Example("item('minecraft:bowl')")
+ })
+ public boolean removeByOutput(IIngredient output) {
+ return TransposerManagerAccessor.getRecipeMapExtract().values().removeIf(r -> {
+ if (output.test(r.getOutput()) || output.test(r.getFluid())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(TransposerManagerAccessor.getRecipeMapExtract().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ TransposerManagerAccessor.getRecipeMapExtract().values().forEach(this::addBackup);
+ TransposerManagerAccessor.getRecipeMapExtract().clear();
+ }
+
+ @Property(property = "input", valid = @Comp("1"))
+ @Property(property = "output", valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "1")})
+ @Property(property = "fluidOutput", valid = @Comp("1"))
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "TransposerManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = TransposerManager.DEFAULT_ENERGY;
+ @Property(valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "100")})
+ private int chance;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder chance(int chance) {
+ this.chance = chance;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Transposer Extract recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 1, 1, 0, 1);
+ validateFluids(msg, 0, 0, 1, 1);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ msg.add(chance < 0 || chance > 100, "chance must be a non negative integer less than 100, yet it was {}", chance);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable TransposerRecipe register() {
+ if (!validate()) return null;
+ TransposerRecipe recipe = null;
+ for (ItemStack input0 : input.get(0).getMatchingStacks()) {
+ TransposerRecipe recipe1 = new TransposerRecipe(input0, output.getOrEmpty(0), fluidOutput.get(0), energy, chance);
+ ModSupport.THERMAL_EXPANSION.get().transposerExtract.add(recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/TransposerFill.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/TransposerFill.java
new file mode 100644
index 000000000..2e8f9fa0c
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/thermalexpansion/machine/TransposerFill.java
@@ -0,0 +1,175 @@
+package com.cleanroommc.groovyscript.compat.mods.thermalexpansion.machine;
+
+import cofh.core.util.helpers.FluidHelper;
+import cofh.thermalexpansion.util.managers.machine.TransposerManager;
+import cofh.thermalexpansion.util.managers.machine.TransposerManager.TransposerRecipe;
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import com.cleanroommc.groovyscript.api.IIngredient;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.compat.mods.ModSupport;
+import com.cleanroommc.groovyscript.core.mixin.thermalexpansion.TransposerManagerAccessor;
+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.FluidStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RegistryDescription(
+ admonition = @Admonition("groovyscript.wiki.thermalexpansion.transposer.note0")
+)
+public class TransposerFill extends VirtualizedRegistry {
+
+ @RecipeBuilderDescription(example = {
+ @Example(".input(item('minecraft:diamond') * 2).fluidInput(fluid('water') * 100)"),
+ @Example(".input(item('minecraft:clay')).output(item('minecraft:diamond') * 2).fluidInput(fluid('water') * 50).energy(1000)")
+ })
+ public RecipeBuilder recipeBuilder() {
+ return new RecipeBuilder();
+ }
+
+ @Override
+ @GroovyBlacklist
+ @ApiStatus.Internal
+ public void onReload() {
+ removeScripted().forEach(recipe -> TransposerManagerAccessor.getRecipeMapFill().values().removeIf(r -> r == recipe));
+ restoreFromBackup().forEach(r -> TransposerManagerAccessor.getRecipeMapFill().put(hash(r), r));
+ }
+
+ @Override
+ @GroovyBlacklist
+ public void afterScriptLoad() {
+ TransposerManagerAccessor.getValidationSet().clear();
+ TransposerManagerAccessor.getValidationSet().addAll(
+ TransposerManagerAccessor.getRecipeMapExtract().values().stream().map(TransposerManager.TransposerRecipe::getInput).map(TransposerManager::convertInput).collect(Collectors.toList())
+ );
+ TransposerManagerAccessor.getValidationSet().clear();
+ TransposerManagerAccessor.getValidationSet().addAll(
+ TransposerManagerAccessor.getRecipeMapFill().values().stream().map(TransposerManager.TransposerRecipe::getInput).map(TransposerManager::convertInput).collect(Collectors.toList())
+ );
+ }
+
+ private List hash(TransposerRecipe recipe) {
+ return hash(recipe.getInput(), recipe.getFluid());
+ }
+
+ private List hash(ItemStack primaryInput, FluidStack fluid) {
+ return Arrays.asList(TransposerManager.convertInput(primaryInput).hashCode(), FluidHelper.getFluidHash(fluid));
+ }
+
+ public void add(TransposerRecipe recipe) {
+ TransposerManagerAccessor.getRecipeMapFill().put(hash(recipe), recipe);
+ addScripted(recipe);
+ }
+
+ @MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("1000, item('minecraft:obsidian'), fluid('water') * 50, item('minecraft:diamond') * 2, 100"))
+ public TransposerRecipe add(int energy, IIngredient input, FluidStack fluidInput, ItemStack outputItem, int chance) {
+ return recipeBuilder()
+ .energy(energy)
+ .chance(chance)
+ .input(input)
+ .fluidInput(fluidInput)
+ .output(outputItem)
+ .register();
+ }
+
+ public boolean remove(TransposerRecipe recipe) {
+ return TransposerManagerAccessor.getRecipeMapFill().values().removeIf(r -> {
+ if (r == recipe) {
+ addBackup(recipe);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = {
+ @Example("fluid('glowstone')"), @Example("item('minecraft:concrete_powder:3')")
+ })
+ public boolean removeByInput(IIngredient input) {
+ return TransposerManagerAccessor.getRecipeMapFill().values().removeIf(r -> {
+ if (input.test(r.getInput()) || input.test(r.getFluid())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(example = @Example("item('minecraft:ice')"))
+ public boolean removeByOutput(IIngredient output) {
+ return TransposerManagerAccessor.getRecipeMapFill().values().removeIf(r -> {
+ if (output.test(r.getOutput())) {
+ addBackup(r);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @MethodDescription(type = MethodDescription.Type.QUERY)
+ public SimpleObjectStream streamRecipes() {
+ return new SimpleObjectStream<>(TransposerManagerAccessor.getRecipeMapFill().values()).setRemover(this::remove);
+ }
+
+ @MethodDescription(priority = 2000, example = @Example(commented = true))
+ public void removeAll() {
+ TransposerManagerAccessor.getRecipeMapFill().values().forEach(this::addBackup);
+ TransposerManagerAccessor.getRecipeMapFill().clear();
+ }
+
+ @Property(property = "input", valid = @Comp("1"))
+ @Property(property = "fluidInput", valid = @Comp("1"))
+ @Property(property = "output", valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "1")})
+ public static class RecipeBuilder extends AbstractRecipeBuilder {
+
+ @Property(defaultValue = "TransposerManager.DEFAULT_ENERGY", valid = @Comp(value = "0", type = Comp.Type.GT), value = "groovyscript.wiki.thermalexpansion.energy.value")
+ private int energy = TransposerManager.DEFAULT_ENERGY;
+ @Property(valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "100")})
+ private int chance;
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder energy(int energy) {
+ this.energy = energy;
+ return this;
+ }
+
+ @RecipeBuilderMethodDescription
+ public RecipeBuilder chance(int chance) {
+ this.chance = chance;
+ return this;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return "Error adding Thermal Expansion Transposer Fill recipe";
+ }
+
+ @Override
+ public void validate(GroovyLog.Msg msg) {
+ validateItems(msg, 1, 1, 0, 1);
+ validateFluids(msg, 1, 1, 0, 0);
+ msg.add(energy <= 0, "energy must be greater than 0, yet it was {}", energy);
+ msg.add(chance < 0 || chance > 100, "chance must be a non negative integer less than 100, yet it was {}", chance);
+ }
+
+ @Override
+ @RecipeBuilderRegistrationMethod
+ public @Nullable TransposerRecipe register() {
+ if (!validate()) return null;
+ TransposerRecipe recipe = null;
+ for (ItemStack input0 : input.get(0).getMatchingStacks()) {
+ TransposerRecipe recipe1 = new TransposerRecipe(input0, output.getOrEmpty(0), fluidInput.get(0), energy, chance);
+ ModSupport.THERMAL_EXPANSION.get().transposerFill.add(recipe1);
+ if (recipe == null) recipe = recipe1;
+ }
+ return recipe;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/tinkersconstruct/Melting.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/tinkersconstruct/Melting.java
index 826d3ba14..c74dd1d5b 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/tinkersconstruct/Melting.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/tinkersconstruct/Melting.java
@@ -9,6 +9,7 @@
import com.cleanroommc.groovyscript.core.mixin.tconstruct.TinkerRegistryAccessor;
import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
import com.cleanroommc.groovyscript.helper.recipe.IRecipeBuilder;
+import com.cleanroommc.groovyscript.registry.AbstractReloadableStorage;
import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
import net.minecraft.entity.EntityList;
import net.minecraft.item.ItemStack;
@@ -119,6 +120,18 @@ public RecipeBuilder(Melting melting) {
public static class EntityMelting extends VirtualizedRegistry {
+ @Override
+ @GroovyBlacklist
+ protected AbstractReloadableStorage createRecipeStorage() {
+ return new AbstractReloadableStorage<>() {
+ @Override
+ @GroovyBlacklist
+ protected boolean compareRecipe(EntityMeltingRecipe recipe, EntityMeltingRecipe recipe2) {
+ return recipe.equals(recipe2);
+ }
+ };
+ }
+
public RecipeBuilder recipeBuilder() {
return new RecipeBuilder();
}
@@ -191,11 +204,6 @@ public SimpleObjectStream streamRecipes() {
return new SimpleObjectStream<>(getAllRecipes()).setRemover(this::remove);
}
- @Override
- protected boolean compareRecipe(EntityMeltingRecipe recipe, EntityMeltingRecipe recipe2) {
- return recipe.equals(recipe2);
- }
-
public class RecipeBuilder implements IRecipeBuilder {
private FluidStack output;
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/tinkersconstruct/SmelteryFuel.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/tinkersconstruct/SmelteryFuel.java
index e203bc841..223aa6f98 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/tinkersconstruct/SmelteryFuel.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/tinkersconstruct/SmelteryFuel.java
@@ -5,6 +5,7 @@
import com.cleanroommc.groovyscript.compat.mods.tinkersconstruct.recipe.SmelteryFuelRecipe;
import com.cleanroommc.groovyscript.core.mixin.tconstruct.TinkerRegistryAccessor;
import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
+import com.cleanroommc.groovyscript.registry.AbstractReloadableStorage;
import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
import net.minecraftforge.fluids.FluidStack;
@@ -13,6 +14,18 @@
public class SmelteryFuel extends VirtualizedRegistry {
+ @Override
+ @GroovyBlacklist
+ protected AbstractReloadableStorage createRecipeStorage() {
+ return new AbstractReloadableStorage<>() {
+ @Override
+ @GroovyBlacklist
+ protected boolean compareRecipe(SmelteryFuelRecipe recipe, SmelteryFuelRecipe recipe2) {
+ return recipe.equals(recipe2);
+ }
+ };
+ }
+
@Override
@GroovyBlacklist
public void onReload() {
@@ -66,8 +79,4 @@ public SimpleObjectStream streamRecipes() {
return new SimpleObjectStream<>(getAllRecipes()).setRemover(this::remove);
}
- @Override
- protected boolean compareRecipe(SmelteryFuelRecipe recipe, SmelteryFuelRecipe recipe2) {
- return recipe.equals(recipe2);
- }
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/FluidStackMixin.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/FluidStackMixin.java
index 02c79898b..16451087b 100644
--- a/src/main/java/com/cleanroommc/groovyscript/core/mixin/FluidStackMixin.java
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/FluidStackMixin.java
@@ -2,7 +2,11 @@
import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.INBTResourceStack;
+import com.cleanroommc.groovyscript.api.INbtIngredient;
+import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper;
+import com.cleanroommc.groovyscript.helper.ingredient.NbtHelper;
import com.cleanroommc.groovyscript.sandbox.ClosureHelper;
+import com.cleanroommc.groovyscript.sandbox.expand.LambdaClosure;
import groovy.lang.Closure;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient;
@@ -19,7 +23,7 @@
import org.spongepowered.asm.mixin.Unique;
@Mixin(value = FluidStack.class, remap = false)
-public abstract class FluidStackMixin implements IIngredient, INBTResourceStack {
+public abstract class FluidStackMixin implements IIngredient, INbtIngredient, INBTResourceStack {
@Shadow
public int amount;
@@ -41,12 +45,15 @@ public abstract class FluidStackMixin implements IIngredient, INBTResourceStack
protected Closure matchCondition;
@Unique
protected Closure transformer;
+ @Unique
+ protected Closure nbtMatcher = null;
@Override
public IIngredient exactCopy() {
FluidStackMixin fluidStackMixin = (FluidStackMixin) (Object) copy();
fluidStackMixin.matchCondition = matchCondition;
fluidStackMixin.transformer = transformer;
+ fluidStackMixin.nbtMatcher = nbtMatcher;
return fluidStackMixin;
}
@@ -73,12 +80,23 @@ public boolean test(ItemStack stack) {
net.minecraftforge.fluids.FluidStack result = fluidHandler.drain(copy(), false);
return result != null && result.amount == getAmount();
}
+ if (nbtMatcher != null) {
+ NBTTagCompound nbt = stack.getTagCompound();
+ return nbt != null && ClosureHelper.call(true, nbtMatcher, nbt);
+ }
return false;
}
@Override
public boolean test(FluidStack fluidStack) {
- return isFluidEqual(fluidStack);
+ if (fluidStack == null) {
+ return false;
+ }
+ if (nbtMatcher != null) {
+ NBTTagCompound nbt = fluidStack.tag;
+ return nbt != null && ClosureHelper.call(true, nbtMatcher, nbt);
+ }
+ return getFluid() == fluidStack.getFluid();
}
@Override
@@ -101,6 +119,47 @@ public FluidStack transform(Closure transformer) {
return (FluidStack) (Object) fresh;
}
+ @Override
+ public INBTResourceStack withNbt(NBTTagCompound nbt) {
+ FluidStackMixin fluidStackMixin = (FluidStackMixin) INbtIngredient.super.withNbt(nbt);
+ fluidStackMixin.nbtMatcher = NbtHelper.makeNbtPredicate(nbt1 -> nbt.isEmpty() || NbtHelper.containsNbt(nbt1, nbt));
+ return fluidStackMixin;
+ }
+
+ @Override
+ public INbtIngredient withNbtExact(NBTTagCompound nbt) {
+ FluidStackMixin fluidStackMixin = (FluidStackMixin) INbtIngredient.super.withNbt(nbt);
+ if (nbt == null) {
+ fluidStackMixin.nbtMatcher = null;
+ } else {
+ fluidStackMixin.nbtMatcher = NbtHelper.makeNbtPredicate(nbt1 -> nbt.isEmpty() || nbt1.equals(nbt));
+ }
+ return fluidStackMixin;
+ }
+
+ public INbtIngredient withNbtFilter(Closure nbtFilter) {
+ this.nbtMatcher = nbtFilter == null ? IngredientHelper.MATCH_ANY : nbtFilter;
+ return this;
+ }
+
+ public INbtIngredient whenNoNbt() {
+ setNbt(null);
+ this.matchCondition = new LambdaClosure<>(args -> {
+ NBTTagCompound nbt = ((FluidStack) args[0]).tag;
+ return nbt == null || nbt.isEmpty();
+ });
+ return this;
+ }
+
+ public INbtIngredient whenAnyNbt() {
+ setNbt(new NBTTagCompound());
+ this.matchCondition = new LambdaClosure<>(args -> {
+ NBTTagCompound nbt = ((FluidStack) args[0]).tag;
+ return nbt != null && !nbt.isEmpty();
+ });
+ return this;
+ }
+
@Override
public @Nullable NBTTagCompound getNbt() {
return tag;
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/BrewerManagerAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/BrewerManagerAccessor.java
index fd1cd25da..38254bb70 100644
--- a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/BrewerManagerAccessor.java
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/BrewerManagerAccessor.java
@@ -26,4 +26,5 @@ static Set getValidationSet() {
static Set getValidationFluids() {
throw new AssertionError();
}
+
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/BrewerRecipeAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/BrewerRecipeAccessor.java
new file mode 100644
index 000000000..6ead0c54a
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/BrewerRecipeAccessor.java
@@ -0,0 +1,17 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.thermalexpansion.util.managers.machine.BrewerManager;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.FluidStack;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Invoker;
+
+@Mixin(value = BrewerManager.BrewerRecipe.class, remap = false)
+public interface BrewerRecipeAccessor {
+
+ @Invoker("")
+ static BrewerManager.BrewerRecipe createBrewerRecipe(ItemStack input, FluidStack inputFluid, FluidStack outputFluid, int energy) {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CentrifugeManagerAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CentrifugeManagerAccessor.java
new file mode 100644
index 000000000..346c8bc43
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CentrifugeManagerAccessor.java
@@ -0,0 +1,23 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.core.inventory.ComparableItemStackValidatedNBT;
+import cofh.thermalexpansion.util.managers.machine.CentrifugeManager;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+import java.util.Map;
+
+@Mixin(value = CentrifugeManager.class, remap = false)
+public interface CentrifugeManagerAccessor {
+
+ @Accessor
+ static Map getRecipeMap() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static Map getRecipeMapMobs() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CentrifugeRecipeAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CentrifugeRecipeAccessor.java
new file mode 100644
index 000000000..2b15cb768
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CentrifugeRecipeAccessor.java
@@ -0,0 +1,22 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.thermalexpansion.util.managers.machine.CentrifugeManager;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.FluidStack;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Invoker;
+
+import javax.annotation.Nullable;
+import java.util.List;
+
+@Mixin(value = CentrifugeManager.CentrifugeRecipe.class, remap = false)
+public interface CentrifugeRecipeAccessor {
+
+ @Invoker("")
+ static CentrifugeManager.CentrifugeRecipe createCentrifugeRecipe(ItemStack input,
+ @Nullable List output,
+ @Nullable List chance, @Nullable FluidStack fluid, int energy) {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/ChargerManagerAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/ChargerManagerAccessor.java
new file mode 100644
index 000000000..52d5c1e77
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/ChargerManagerAccessor.java
@@ -0,0 +1,18 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.core.inventory.ComparableItemStackValidated;
+import cofh.thermalexpansion.util.managers.machine.ChargerManager;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+import java.util.Map;
+
+@Mixin(value = ChargerManager.class, remap = false)
+public interface ChargerManagerAccessor {
+
+ @Accessor
+ static Map getRecipeMap() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CompactorManagerAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CompactorManagerAccessor.java
new file mode 100644
index 000000000..a7fc024bf
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CompactorManagerAccessor.java
@@ -0,0 +1,33 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.core.inventory.ComparableItemStackValidatedNBT;
+import cofh.thermalexpansion.util.managers.machine.CompactorManager;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+import java.util.Map;
+
+@Mixin(value = CompactorManager.class, remap = false)
+public interface CompactorManagerAccessor {
+
+ @Accessor
+ static Map getRecipeMapAll() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static Map getRecipeMapPlate() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static Map getRecipeMapCoin() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static Map getRecipeMapGear() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CompactorRecipeAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CompactorRecipeAccessor.java
new file mode 100644
index 000000000..b234bffef
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CompactorRecipeAccessor.java
@@ -0,0 +1,16 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.thermalexpansion.util.managers.machine.CompactorManager;
+import net.minecraft.item.ItemStack;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Invoker;
+
+@Mixin(value = CompactorManager.CompactorRecipe.class, remap = false)
+public interface CompactorRecipeAccessor {
+
+ @Invoker("")
+ static CompactorManager.CompactorRecipe createCompactorRecipe(ItemStack input, ItemStack output, int energy) {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CompressionManagerAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CompressionManagerAccessor.java
new file mode 100644
index 000000000..43e344bbd
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CompressionManagerAccessor.java
@@ -0,0 +1,16 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.thermalexpansion.util.managers.dynamo.CompressionManager;
+import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(value = CompressionManager.class, remap = false)
+public interface CompressionManagerAccessor {
+
+ @Accessor
+ static Object2IntOpenHashMap getFuelMap() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CoolantManagerAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CoolantManagerAccessor.java
new file mode 100644
index 000000000..d6b2162f5
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CoolantManagerAccessor.java
@@ -0,0 +1,21 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.thermalexpansion.util.managers.device.CoolantManager;
+import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(value = CoolantManager.class, remap = false)
+public interface CoolantManagerAccessor {
+
+ @Accessor
+ static Object2IntOpenHashMap getCoolantMap() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static Object2IntOpenHashMap getCoolantFactorMap() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CrucibleManagerAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CrucibleManagerAccessor.java
index cc536c32c..6aa4826d0 100644
--- a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CrucibleManagerAccessor.java
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CrucibleManagerAccessor.java
@@ -20,4 +20,5 @@ static Map getR
static Set getLavaSet() {
throw new AssertionError();
}
+
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CrucibleRecipeAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CrucibleRecipeAccessor.java
new file mode 100644
index 000000000..c38a29622
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/CrucibleRecipeAccessor.java
@@ -0,0 +1,17 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.thermalexpansion.util.managers.machine.CrucibleManager;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.FluidStack;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Invoker;
+
+@Mixin(value = CrucibleManager.CrucibleRecipe.class, remap = false)
+public interface CrucibleRecipeAccessor {
+
+ @Invoker("")
+ static CrucibleManager.CrucibleRecipe createCrucibleRecipe(ItemStack input, FluidStack output, int energy) {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/DiffuserManagerAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/DiffuserManagerAccessor.java
new file mode 100644
index 000000000..dc7739f83
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/DiffuserManagerAccessor.java
@@ -0,0 +1,22 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.core.inventory.ComparableItemStack;
+import cofh.thermalexpansion.util.managers.device.DiffuserManager;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(value = DiffuserManager.class, remap = false)
+public interface DiffuserManagerAccessor {
+
+ @Accessor
+ static TObjectIntHashMap getReagentAmpMap() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static TObjectIntHashMap getReagentDurMap() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/EnchanterManagerAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/EnchanterManagerAccessor.java
new file mode 100644
index 000000000..7dc6227ed
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/EnchanterManagerAccessor.java
@@ -0,0 +1,30 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.core.inventory.ComparableItemStackValidatedNBT;
+import cofh.thermalexpansion.util.managers.machine.EnchanterManager;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@Mixin(value = EnchanterManager.class, remap = false)
+public interface EnchanterManagerAccessor {
+
+ @Accessor
+ static Map, EnchanterManager.EnchanterRecipe> getRecipeMap() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static Set getValidationSet() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static Set getLockSet() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/EnchanterRecipeAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/EnchanterRecipeAccessor.java
new file mode 100644
index 000000000..af70bf54c
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/EnchanterRecipeAccessor.java
@@ -0,0 +1,16 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.thermalexpansion.util.managers.machine.EnchanterManager;
+import net.minecraft.item.ItemStack;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Invoker;
+
+@Mixin(value = EnchanterManager.EnchanterRecipe.class, remap = false)
+public interface EnchanterRecipeAccessor {
+
+ @Invoker("")
+ static EnchanterManager.EnchanterRecipe createEnchanterRecipe(ItemStack primaryInput, ItemStack secondaryInput, ItemStack output, int experience, int energy, EnchanterManager.Type type) {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/EnervationManagerAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/EnervationManagerAccessor.java
new file mode 100644
index 000000000..090207415
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/EnervationManagerAccessor.java
@@ -0,0 +1,17 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.core.inventory.ComparableItemStack;
+import cofh.thermalexpansion.util.managers.dynamo.EnervationManager;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(value = EnervationManager.class, remap = false)
+public interface EnervationManagerAccessor {
+
+ @Accessor
+ static TObjectIntHashMap getFuelMap() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/ExtruderManagerAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/ExtruderManagerAccessor.java
new file mode 100644
index 000000000..cafb68e30
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/ExtruderManagerAccessor.java
@@ -0,0 +1,35 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.core.util.ItemWrapper;
+import cofh.thermalexpansion.util.managers.machine.ExtruderManager;
+import net.minecraft.item.ItemStack;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+import java.util.List;
+import java.util.Map;
+
+@Mixin(value = ExtruderManager.class, remap = false)
+public interface ExtruderManagerAccessor {
+
+ @Accessor
+ static Map getRecipeMapIgneous() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static Map getRecipeMapSedimentary() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static List getOutputListIgneous() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static List getOutputListSedimentary() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/ExtruderRecipeAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/ExtruderRecipeAccessor.java
new file mode 100644
index 000000000..cb36d1d0f
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/ExtruderRecipeAccessor.java
@@ -0,0 +1,17 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.thermalexpansion.util.managers.machine.ExtruderManager;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.FluidStack;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Invoker;
+
+@Mixin(value = ExtruderManager.ExtruderRecipe.class, remap = false)
+public interface ExtruderRecipeAccessor {
+
+ @Invoker("")
+ static ExtruderManager.ExtruderRecipe createExtruderRecipe(ItemStack output, FluidStack inputHot, FluidStack inputCold, int energy) {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FactorizerManagerAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FactorizerManagerAccessor.java
new file mode 100644
index 000000000..133d640a1
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FactorizerManagerAccessor.java
@@ -0,0 +1,23 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.core.inventory.ComparableItemStackValidated;
+import cofh.thermalexpansion.util.managers.device.FactorizerManager;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+import java.util.Map;
+
+@Mixin(value = FactorizerManager.class, remap = false)
+public interface FactorizerManagerAccessor {
+
+ @Accessor
+ static Map getRecipeMap() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static Map getRecipeMapReverse() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FactorizerRecipeAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FactorizerRecipeAccessor.java
new file mode 100644
index 000000000..5c36f1844
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FactorizerRecipeAccessor.java
@@ -0,0 +1,16 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.thermalexpansion.util.managers.device.FactorizerManager;
+import net.minecraft.item.ItemStack;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Invoker;
+
+@Mixin(value = FactorizerManager.FactorizerRecipe.class, remap = false)
+public interface FactorizerRecipeAccessor {
+
+ @Invoker("")
+ static FactorizerManager.FactorizerRecipe createFactorizerRecipe(ItemStack input, ItemStack output) {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FisherManagerAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FisherManagerAccessor.java
new file mode 100644
index 000000000..1ff2631bf
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FisherManagerAccessor.java
@@ -0,0 +1,40 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.core.inventory.ComparableItemStack;
+import cofh.thermalexpansion.util.managers.device.FisherManager;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import net.minecraft.item.ItemStack;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+import java.util.List;
+
+@Mixin(value = FisherManager.class, remap = false)
+public interface FisherManagerAccessor {
+
+ @Accessor
+ static List getFishList() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static List getWeightList() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static int getTotalWeight() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static void setTotalWeight(int totalWeight) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static TObjectIntHashMap getBaitMap() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FurnaceManagerAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FurnaceManagerAccessor.java
new file mode 100644
index 000000000..884cda3a0
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FurnaceManagerAccessor.java
@@ -0,0 +1,29 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.core.inventory.ComparableItemStackValidated;
+import cofh.thermalexpansion.util.managers.machine.FurnaceManager;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+import java.util.Map;
+import java.util.Set;
+
+@Mixin(value = FurnaceManager.class, remap = false)
+public interface FurnaceManagerAccessor {
+
+ @Accessor
+ static Map getRecipeMap() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static Map getRecipeMapPyrolysis() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static Set getFoodSet() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FurnaceRecipeAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FurnaceRecipeAccessor.java
new file mode 100644
index 000000000..63d2f04f5
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/FurnaceRecipeAccessor.java
@@ -0,0 +1,21 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.thermalexpansion.util.managers.machine.FurnaceManager;
+import net.minecraft.item.ItemStack;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Invoker;
+
+@Mixin(value = FurnaceManager.FurnaceRecipe.class, remap = false)
+public interface FurnaceRecipeAccessor {
+
+ @Invoker("")
+ static FurnaceManager.FurnaceRecipe createFurnaceRecipe(ItemStack input, ItemStack output, int energy) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Invoker("")
+ static FurnaceManager.FurnaceRecipe createFurnaceRecipe(ItemStack input, ItemStack output, int energy, int creosote) {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/InsolatorManagerAccessor.java b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/InsolatorManagerAccessor.java
new file mode 100644
index 000000000..1d4e0f2b3
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/core/mixin/thermalexpansion/InsolatorManagerAccessor.java
@@ -0,0 +1,30 @@
+package com.cleanroommc.groovyscript.core.mixin.thermalexpansion;
+
+import cofh.core.inventory.ComparableItemStackValidatedNBT;
+import cofh.thermalexpansion.util.managers.machine.InsolatorManager;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@Mixin(value = InsolatorManager.class, remap = false)
+public interface InsolatorManagerAccessor {
+
+ @Accessor
+ static Map, InsolatorManager.InsolatorRecipe> getRecipeMap() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static Set getValidationSet() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Accessor
+ static Set