Skip to content

Commit

Permalink
add Extra Utilities 2 compat (#129)
Browse files Browse the repository at this point in the history
* add extra utilities 2

* add core compat

* basic and broken generator compat

* GP generator failed attempts

* rename to ExtraUtils2, rework GP Mill compat

* implement XU generator compat

* add setPowerMultiplier and cleanup

* document

* add generated example file

* remove removeByOutput, add more examples

* fix ModSupport ordering

* return true if anything was removed

* use dsi.fastutil Maps

* chat am i delusional

* address review without using labels

* add metadata warning for furnace and fix removal example

* make closure debug instead

* apply prior change as desired and make closure types not required
  • Loading branch information
WaitingIdly authored Mar 22, 2024
1 parent 38e841a commit eec25f4
Show file tree
Hide file tree
Showing 18 changed files with 1,431 additions and 1 deletion.
5 changes: 5 additions & 0 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ dependencies {
runtimeOnly rfg.deobf('curse.maven:ae2-extended-life-570458:4553942')
}

compileOnly rfg.deobf('curse.maven:extra-utilities-2-225561:2678374')
if (project.debug_extra_utilities_2.toBoolean()) {
runtimeOnly rfg.deobf('curse.maven:extra-utilities-2-225561:2678374')
}

compileOnly rfg.deobf('curse.maven:redstone_flux-270789:2920436')
if (project.debug_thermal.toBoolean() || project.debug_draconic_evolution.toBoolean()) {
runtimeOnly rfg.deobf('curse.maven:redstone_flux-270789:2920436')
Expand Down
137 changes: 137 additions & 0 deletions examples/postInit/extrautils2.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@

// Auto generated groovyscript example file
// MODS_LOADED: extrautils2

import com.rwtema.extrautils2.power.IWorldPowerMultiplier
import com.rwtema.extrautils2.tile.TilePassiveGenerator

println 'mod \'extrautils2\' detected, running script'

// Crusher:
// Converts an input itemstack into an output itemstack with a chance of an additional itemstack output, consuming energy.

mods.extrautils2.crusher.removeByInput(item('minecraft:blaze_rod'))
// mods.extrautils2.crusher.removeAll()

mods.extrautils2.crusher.recipeBuilder()
.input(item('minecraft:gold_ingot'))
.output(item('minecraft:clay'))
.energy(1000)
.time(5)
.register()

mods.extrautils2.crusher.recipeBuilder()
.input(item('minecraft:blaze_rod'))
.output(item('minecraft:gold_ingot') * 3)
.output(item('minecraft:gold_ingot'))
.chance(0.2f)
.energy(1000)
.time(5)
.register()


// Enchanter:
// Converts two input itemstacks into an output itemstack, consuming energy and require nearby enchantment power providers.

mods.extrautils2.enchanter.removeByInput(item('minecraft:bookshelf'))
// mods.extrautils2.enchanter.removeAll()

mods.extrautils2.enchanter.recipeBuilder()
.input(item('minecraft:gold_ingot'), item('minecraft:diamond'))
.output(item('minecraft:clay'))
.energy(1000)
.time(5)
.register()


// Furnace:
// Converts an input itemstack into an output itemstack, consuming energy.

mods.extrautils2.furnace.removeByInput(item('minecraft:emerald_ore:*'))
// mods.extrautils2.furnace.removeAll()

mods.extrautils2.furnace.recipeBuilder()
.input(item('minecraft:gold_ingot'))
.output(item('minecraft:clay'))
.energy(1000)
.time(5)
.register()


// Generators:
// Converts up to two input itemstacks and an input fluidstack into energy over time.

mods.extrautils2.generator.remove('extrautils2:generator_lava', fluid('lava'))
mods.extrautils2.generator.remove('extrautils2:generator_culinary', item('minecraft:apple'))
mods.extrautils2.generator.removeByGenerator('extrautils2:generator_death')
// mods.extrautils2.generator.removeAll()

mods.extrautils2.generator.recipeBuilder()
.generator('extrautils2:generator_pink')
.input(item('minecraft:clay'))
.energy(1000)
.energyPerTick(100)
.register()

mods.extrautils2.generator.recipeBuilder()
.generator('extrautils2:generator_slime')
.input(item('minecraft:clay') * 3)
.input(item('minecraft:gold_ingot'))
.energy(1000000)
.energyPerTick(100)
.register()

mods.extrautils2.generator.recipeBuilder()
.generator('extrautils2:generator_redstone')
.input(item('minecraft:clay') * 3)
.fluidInput(fluid('water') * 300)
.energy(1000)
.energyPerTick(100)
.register()

mods.extrautils2.generator.recipeBuilder()
.generator('extrautils2:generator_lava')
.fluidInput(fluid('water') * 300)
.energy(100)
.energyPerTick(1000)
.register()


// Grid Power Generators:
// Passively produces Grid Power into the Owner's GP network

mods.extrautils2.grid_power_passive_generator.setBasePower(resource('generators:creative'), 5f)
mods.extrautils2.grid_power_passive_generator.setBasePower(resource('generators:player_wind_up'), 100f)
mods.extrautils2.grid_power_passive_generator.setPowerLevel(resource('generators:solar'), { TilePassiveGenerator generator, World world -> 100f })
mods.extrautils2.grid_power_passive_generator.setPowerMultiplier(resource('generators:wind'), IWorldPowerMultiplier.CONSTANT)
mods.extrautils2.grid_power_passive_generator.setScaling(resource('generators:creative'), 500.0F, 0.5F, 1000.0F, 0.25F, 1500.0F, 0.05F)

// Resonator:
// Converts and input itemstack into an output itemstack, consuming Grid Power from the Owner's GP network. Can also
// require an active Rainbow Generator.

mods.extrautils2.resonator.removeByInput(item('minecraft:quartz_block'))
mods.extrautils2.resonator.removeByOutput(item('extrautils2:ingredients:4'))
// mods.extrautils2.resonator.removeAll()

mods.extrautils2.resonator.recipeBuilder()
.input(item('minecraft:gold_ingot'))
.output(item('minecraft:clay'))
.rainbow()
.energy(1000)
.register()

mods.extrautils2.resonator.recipeBuilder()
.input(item('minecraft:gold_block'))
.output(item('minecraft:clay') * 5)
.energy(100)
.register()

mods.extrautils2.resonator.recipeBuilder()
.input(item('minecraft:redstone'))
.output(item('extrautils2:ingredients:4'))
.ownerTag()
.energy(5000)
.register()


3 changes: 2 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ debug_draconic_evolution = false
debug_enderio = false
debug_evilcraft = false
debug_extended_crafting = false
debug_extra_utilities_2 = false
debug_forestry = false
debug_immersive_engineering = false
debug_integrated_dynamics = false
debug_industrial_craft_2_classic = false
debug_industrial_craft_2_experimental = false
debug_inspirations = false
debug_integrated_dynamics = false
debug_mekanism = false
debug_packmode = false
debug_pyrotech = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.cleanroommc.groovyscript.compat.mods.enderio.EnderIO;
import com.cleanroommc.groovyscript.compat.mods.evilcraft.EvilCraft;
import com.cleanroommc.groovyscript.compat.mods.extendedcrafting.ExtendedCrafting;
import com.cleanroommc.groovyscript.compat.mods.extrautils2.ExtraUtils2;
import com.cleanroommc.groovyscript.compat.mods.forestry.Forestry;
import com.cleanroommc.groovyscript.compat.mods.ic2.IC2;
import com.cleanroommc.groovyscript.compat.mods.immersiveengineering.ImmersiveEngineering;
Expand Down Expand Up @@ -72,6 +73,7 @@ public class ModSupport implements IDynamicGroovyProperty {
public static final GroovyContainer<EnderIO> ENDER_IO = new InternalModContainer<>("enderio", "Ender IO", EnderIO::new, "eio");
public static final GroovyContainer<EvilCraft> EVILCRAFT = new InternalModContainer<>("evilcraft", "EvilCraft", EvilCraft::new);
public static final GroovyContainer<ExtendedCrafting> EXTENDED_CRAFTING = new InternalModContainer<>("extendedcrafting", "Extended Crafting", ExtendedCrafting::new);
public static final GroovyContainer<ExtraUtils2> EXTRA_UTILITIES_2 = new InternalModContainer<>("extrautils2", "Extra Utilities 2", ExtraUtils2::new, "extrautilities2");
public static final GroovyContainer<Forestry> FORESTRY = new InternalModContainer<>("forestry", "Forestry", Forestry::new);
public static final GroovyContainer<ImmersiveEngineering> IMMERSIVE_ENGINEERING = new InternalModContainer<>("immersiveengineering", "Immersive Engineering", ImmersiveEngineering::new, "ie");
public static final GroovyContainer<IC2> INDUSTRIALCRAFT = new InternalModContainer<>("ic2", "Industrial Craft 2", IC2::new, "industrialcraft");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package com.cleanroommc.groovyscript.compat.mods.extrautils2;

import com.cleanroommc.groovyscript.api.GroovyLog;
import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
import com.rwtema.extrautils2.api.machine.IMachineRecipe;
import com.rwtema.extrautils2.api.machine.XUMachineCrusher;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@RegistryDescription
public class Crusher extends VirtualizedRegistry<IMachineRecipe> {

@Override
public void onReload() {
removeScripted().forEach(XUMachineCrusher.INSTANCE.recipes_registry::removeRecipe);
restoreFromBackup().forEach(XUMachineCrusher.INSTANCE.recipes_registry::addRecipe);
}

public IMachineRecipe add(IMachineRecipe recipe) {
if (recipe != null) {
addScripted(recipe);
XUMachineCrusher.INSTANCE.recipes_registry.addRecipe(recipe);
}
return recipe;
}

public boolean remove(IMachineRecipe recipe) {
if (XUMachineCrusher.INSTANCE.recipes_registry.removeRecipe(recipe)) {
addBackup(recipe);
return true;
}
return false;
}

@MethodDescription(description = "groovyscript.wiki.removeByInput", example = @Example("item('minecraft:blaze_rod')"))
public boolean removeByInput(IIngredient input) {
List<IMachineRecipe> agony = new ArrayList<>();
for (IMachineRecipe recipe : XUMachineCrusher.INSTANCE.recipes_registry) {
if (recipe.getJEIInputItemExamples().stream().flatMap(x -> x.getKey().get(XUMachineCrusher.INPUT).stream()).anyMatch(input)) {
agony.add(recipe);
}
}
for (IMachineRecipe recipe : agony) {
addBackup(recipe);
XUMachineCrusher.INSTANCE.recipes_registry.removeRecipe(recipe);
}
return !agony.isEmpty();
}

@MethodDescription(description = "groovyscript.wiki.streamRecipes", type = MethodDescription.Type.QUERY)
public SimpleObjectStream<IMachineRecipe> streamRecipes() {
List<IMachineRecipe> list = new ArrayList<>();
for (IMachineRecipe recipe : XUMachineCrusher.INSTANCE.recipes_registry) {
list.add(recipe);
}
return new SimpleObjectStream<>(list).setRemover(this::remove);
}

@MethodDescription(description = "groovyscript.wiki.removeAll", priority = 2000, example = @Example(commented = true))
public void removeAll() {
List<IMachineRecipe> agony = new ArrayList<>();
for (IMachineRecipe recipe : XUMachineCrusher.INSTANCE.recipes_registry) {
agony.add(recipe);
}
for (IMachineRecipe recipe : agony) {
addBackup(recipe);
XUMachineCrusher.INSTANCE.recipes_registry.removeRecipe(recipe);
}
}


@RecipeBuilderDescription(example = {
@Example(".input(item('minecraft:gold_ingot')).output(item('minecraft:clay')).energy(1000).time(5)"),
@Example(".input(item('minecraft:blaze_rod')).output(item('minecraft:gold_ingot') * 3).output(item('minecraft:gold_ingot')).chance(0.2f).energy(1000).time(5)"),
})
public RecipeBuilder recipeBuilder() {
return new RecipeBuilder();
}

@Property(property = "input", valid = @Comp("1"))
@Property(property = "output", valid = {@Comp(value = "1", type = Comp.Type.GTE), @Comp(value = "2", type = Comp.Type.LTE)})
public static class RecipeBuilder extends AbstractRecipeBuilder<IMachineRecipe> {

@Property(valid = @Comp(value = "0", type = Comp.Type.GTE))
private int energy;
@Property(valid = @Comp(value = "0", type = Comp.Type.GT))
private int time;
@Property(valid = {@Comp(value = "0", type = Comp.Type.GTE), @Comp(value = "1", type = Comp.Type.LTE)})
private float chance;

@RecipeBuilderMethodDescription
public RecipeBuilder energy(int energy) {
this.energy = energy;
return this;
}

@RecipeBuilderMethodDescription
public RecipeBuilder time(int time) {
this.time = time;
return this;
}

@RecipeBuilderMethodDescription
public RecipeBuilder chance(float chance) {
this.chance = chance;
return this;
}

@Override
public String getErrorMsg() {
return "Error adding Extra Utilities 2 Crusher recipe";
}

@Override
public void validate(GroovyLog.Msg msg) {
validateItems(msg, 1, 1, 1, 2);
validateFluids(msg);
msg.add(energy < 0, () -> "energy must not be negative");
msg.add(time <= 0, () -> "time must not be less than or equal to 0");
msg.add(chance < 0 || chance > 1, "chance must be between 0 and 1, yet it was {}", chance);
}

@Override
@RecipeBuilderRegistrationMethod
public IMachineRecipe register() {
if (!validate()) return null;
com.rwtema.extrautils2.api.machine.RecipeBuilder builder = com.rwtema.extrautils2.api.machine.RecipeBuilder.newbuilder(XUMachineCrusher.INSTANCE);
builder.setItemInput(XUMachineCrusher.INPUT, Arrays.asList(input.get(0).getMatchingStacks()), input.get(0).getAmount());
builder.setItemOutput(XUMachineCrusher.OUTPUT, output.get(0));
if (!IngredientHelper.isEmpty(output.getOrEmpty(1))) {
builder.setItemOutput(XUMachineCrusher.OUTPUT_SECONDARY, output.get(1));
builder.setProbability(XUMachineCrusher.OUTPUT_SECONDARY, chance);
}
builder.setEnergy(energy);
builder.setProcessingTime(time);

IMachineRecipe recipe = builder.build();

ModSupport.EXTRA_UTILITIES_2.get().crusher.add(recipe);
return recipe;
}
}
}
Loading

0 comments on commit eec25f4

Please sign in to comment.