Skip to content

Commit f4cfe68

Browse files
authored
add Armor Plus compat (#315)
* add armor plus * add mixins for armor plus * add armor plus compat * remove replacement for anvil crafting * fix methodSignature NPE on size check
1 parent aea7f91 commit f4cfe68

File tree

21 files changed

+667
-2
lines changed

21 files changed

+667
-2
lines changed

dependencies.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ final def mod_dependencies = [
4343
'lemonlib-306926:2639879' : [project.debug_arcane_world, project.debug_arcane_world_rotn],
4444
'arcane-world-302852:2972860' : [project.debug_arcane_world],
4545
'arcane-world-rotn-edition-475553:3523150' : [project.debug_arcane_world_rotn],
46+
'armor-plus-237366:2952741' : [project.debug_armor_plus],
47+
'thedragonlib-248055:2580332' : [project.debug_armor_plus],
4648
'astralsorcery-sorcery-241721:3044416' : [project.debug_astral],
4749
'baubles-227083:2518667' : [project.debug_blood_arsenal, project.debug_astral, project.debug_botania, project.debug_botania_tweaks, project.debug_botanic_additions, project.debug_essentialcraft_4, project.debug_extra_botany, project.debug_thaum],
4850
'the-aurorian-352137:4981736' : [project.debug_aurorian],

examples/postInit/armorplus.groovy

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
2+
// Auto generated groovyscript example file
3+
// MODS_LOADED: armorplus
4+
5+
log.info 'mod \'armorplus\' detected, running script'
6+
7+
// Champion Bench:
8+
// A normal crafting recipe, but with a 9x9 grid and in the Champion Bench.
9+
10+
// mods.armorplus.champion_bench.removeByOutput()
11+
// mods.armorplus.champion_bench.removeAll()
12+
13+
14+
mods.armorplus.champion_bench.shapedBuilder()
15+
.output(item('minecraft:stone') * 64)
16+
.matrix('DLLLLLDDD',
17+
' DNIGIND',
18+
'DDDNIGIND',
19+
' DLLLLLD')
20+
.key('D', item('minecraft:diamond'))
21+
.key('L', item('minecraft:redstone'))
22+
.key('N', item('minecraft:stone'))
23+
.key('I', item('minecraft:iron_ingot'))
24+
.key('G', item('minecraft:gold_ingot'))
25+
.register()
26+
27+
28+
mods.armorplus.champion_bench.shapelessBuilder()
29+
.output(item('minecraft:clay') * 32)
30+
.input(item('minecraft:diamond'), item('minecraft:diamond'), item('minecraft:diamond'), item('minecraft:diamond'), item('minecraft:diamond'), item('minecraft:diamond'), item('minecraft:diamond'), item('minecraft:diamond'))
31+
.register()
32+
33+
34+
// High-Tech Bench:
35+
// A normal crafting recipe, but with a 5x5 grid and in the High-Tech Bench.
36+
37+
mods.armorplus.high_tech_bench.removeByOutput(item('armorplus:emerald_helmet'))
38+
// mods.armorplus.high_tech_bench.removeAll()
39+
40+
41+
mods.armorplus.high_tech_bench.shapedBuilder()
42+
.output(item('minecraft:diamond') * 32)
43+
.matrix([[item('minecraft:gold_ingot'), item('minecraft:gold_ingot'), item('minecraft:gold_ingot')],
44+
[item('minecraft:gold_ingot'), item('minecraft:gold_ingot'), item('minecraft:gold_ingot')],
45+
[item('minecraft:gold_ingot'), item('minecraft:gold_ingot'), item('minecraft:gold_ingot')]])
46+
.register()
47+
48+
49+
mods.armorplus.high_tech_bench.shapelessBuilder()
50+
.output(item('minecraft:clay') * 8)
51+
.input(item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'))
52+
.register()
53+
54+
55+
// Lava Infuser:
56+
// Convert input itemstack to output itemstack over a second, with the ability to reward a configurable amount of
57+
// experience based on the output itemstack. Consumes lava at a rate of 1 bucket per 10 seconds.
58+
59+
mods.armorplus.lava_infuser.removeByInput(item('armorplus:lava_crystal'))
60+
mods.armorplus.lava_infuser.removeByOutput(item('armorplus:lava_infused_obsidian'))
61+
// mods.armorplus.lava_infuser.removeAll()
62+
63+
mods.armorplus.lava_infuser.recipeBuilder()
64+
.input(item('minecraft:gold_ingot'))
65+
.output(item('minecraft:clay') * 2)
66+
.register()
67+
68+
mods.armorplus.lava_infuser.recipeBuilder()
69+
.input(item('minecraft:clay'))
70+
.output(item('minecraft:diamond'))
71+
.experience(5.0d)
72+
.register()
73+
74+
75+
// Ultimate Bench:
76+
// A normal crafting recipe, but with a 7x7 grid and in the Ultimate Bench.
77+
78+
mods.armorplus.ultimate_bench.removeByOutput(item('armorplus:the_ultimate_helmet'))
79+
// mods.armorplus.ultimate_bench.removeAll()
80+
81+
82+
mods.armorplus.ultimate_bench.shapedBuilder()
83+
.output(item('minecraft:diamond'))
84+
.matrix('BXXXBX')
85+
.mirrored()
86+
.key('B', item('minecraft:stone'))
87+
.key('X', item('minecraft:gold_ingot'))
88+
.register()
89+
90+
91+
mods.armorplus.ultimate_bench.shapelessBuilder()
92+
.output(item('minecraft:stone') * 64)
93+
.input(item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'))
94+
.register()
95+
96+
97+
// WorkBench:
98+
// A normal crafting recipe, but with a 3x3 grid and in the WorkBench.
99+
100+
mods.armorplus.work_bench.removeByOutput(item('armorplus:the_gift_of_the_gods'))
101+
// mods.armorplus.work_bench.removeAll()
102+
103+
104+
mods.armorplus.work_bench.shapedBuilder()
105+
.output(item('minecraft:stone') * 8)
106+
.matrix('BXX')
107+
.mirrored()
108+
.key('B', item('minecraft:stone'))
109+
.key('X', item('minecraft:gold_ingot'))
110+
.register()
111+
112+
113+
mods.armorplus.work_bench.shapelessBuilder()
114+
.output(item('minecraft:clay') * 8)
115+
.input(item('minecraft:stone'), item('minecraft:stone'), item('minecraft:stone'))
116+
.register()
117+
118+

gradle.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ debug_applied_energistics_2 = false
2929
debug_arcane_archives = false
3030
debug_arcane_world = false
3131
debug_arcane_world_rotn = false
32+
debug_armor_plus = false
3233
debug_astral = false
3334
debug_atum = false
3435
debug_aurorian = false

src/main/java/com/cleanroommc/groovyscript/compat/mods/ModSupport.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.cleanroommc.groovyscript.compat.mods.appliedenergistics2.AppliedEnergistics2;
1313
import com.cleanroommc.groovyscript.compat.mods.arcanearchives.ArcaneArchives;
1414
import com.cleanroommc.groovyscript.compat.mods.arcaneworld.ArcaneWorld;
15+
import com.cleanroommc.groovyscript.compat.mods.armorplus.ArmorPlus;
1516
import com.cleanroommc.groovyscript.compat.mods.astralsorcery.AstralSorcery;
1617
import com.cleanroommc.groovyscript.compat.mods.atum.Atum;
1718
import com.cleanroommc.groovyscript.compat.mods.avaritia.Avaritia;
@@ -101,6 +102,7 @@ public class ModSupport {
101102
public static final GroovyContainer<AppliedEnergistics2> APPLIED_ENERGISTICS_2 = new InternalModContainer<>("appliedenergistics2", "Applied Energistics 2", AppliedEnergistics2::new, "ae2");
102103
public static final GroovyContainer<ArcaneArchives> ARCANE_ARCHIVES = new InternalModContainer<>("arcanearchives", "Arcane Archives", ArcaneArchives::new);
103104
public static final GroovyContainer<ArcaneWorld> ARCANE_WORLD = new InternalModContainer<>("arcaneworld", "Arcane World", ArcaneWorld::new);
105+
public static final GroovyContainer<ArmorPlus> ARMOR_PLUS = new InternalModContainer<>("armorplus", "Armor Plus", ArmorPlus::new);
104106
public static final GroovyContainer<AstralSorcery> ASTRAL_SORCERY = new InternalModContainer<>("astralsorcery", "Astral Sorcery", AstralSorcery::new, "astral");
105107
public static final GroovyContainer<Atum> ATUM = new InternalModContainer<>("atum", "Atum 2", Atum::new);
106108
public static final GroovyContainer<Avaritia> AVARITIA = new InternalModContainer<>("avaritia", "Avaritia", Avaritia::new);
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.cleanroommc.groovyscript.compat.mods.armorplus;
2+
3+
import com.cleanroommc.groovyscript.api.IIngredient;
4+
import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
5+
import com.cleanroommc.groovyscript.api.documentation.annotations.RecipeBuilderDescription;
6+
import com.cleanroommc.groovyscript.core.mixin.armorplus.BaseCraftingManagerAccessor;
7+
import com.cleanroommc.groovyscript.registry.StandardListRegistry;
8+
import com.sofodev.armorplus.api.crafting.IRecipe;
9+
import com.sofodev.armorplus.api.crafting.base.BaseCraftingManager;
10+
11+
import java.util.Collection;
12+
13+
public abstract class AbstractBenchRegistry extends StandardListRegistry<IRecipe> {
14+
15+
public abstract BaseCraftingManager getInstance();
16+
17+
@Override
18+
public Collection<IRecipe> getRecipes() {
19+
return getInstance().getRecipeList();
20+
}
21+
22+
private int size() {
23+
return ((BaseCraftingManagerAccessor) getInstance()).getSize();
24+
}
25+
26+
@RecipeBuilderDescription
27+
public BenchRecipeBuilder.Shaped shapedBuilder() {
28+
return new BenchRecipeBuilder.Shaped(this, size());
29+
}
30+
31+
@RecipeBuilderDescription
32+
public BenchRecipeBuilder.Shapeless shapelessBuilder() {
33+
return new BenchRecipeBuilder.Shapeless(this, size());
34+
}
35+
36+
// so the <init> of BaseCraftingManager does this sorting... before any recipes are added to the list. and never again.
37+
// @Override
38+
// public void afterScriptLoad() {
39+
// getInstance().getRecipeList().sort((left, right) -> Integer.compare(right.getRecipeSize(), left.getRecipeSize()));
40+
// }
41+
42+
@MethodDescription
43+
public boolean removeByOutput(IIngredient output) {
44+
return getRecipes().removeIf(x -> output.test(x.getRecipeOutput()));
45+
}
46+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.cleanroommc.groovyscript.compat.mods.armorplus;
2+
3+
import com.cleanroommc.groovyscript.compat.mods.GroovyPropertyContainer;
4+
5+
public class ArmorPlus extends GroovyPropertyContainer {
6+
7+
public final ChampionBench championBench = new ChampionBench();
8+
public final HighTechBench highTechBench = new HighTechBench();
9+
public final LavaInfuser lavaInfuser = new LavaInfuser();
10+
public final UltimateBench ultimateBench = new UltimateBench();
11+
public final WorkBench workBench = new WorkBench();
12+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.cleanroommc.groovyscript.compat.mods.armorplus;
2+
3+
import com.cleanroommc.groovyscript.api.GroovyLog;
4+
import com.cleanroommc.groovyscript.api.documentation.annotations.RecipeBuilderRegistrationMethod;
5+
import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper;
6+
import com.cleanroommc.groovyscript.registry.AbstractCraftingRecipeBuilder;
7+
import com.sofodev.armorplus.api.crafting.IRecipe;
8+
import com.sofodev.armorplus.api.crafting.IShapedRecipe;
9+
10+
public interface BenchRecipeBuilder {
11+
12+
class Shaped extends AbstractCraftingRecipeBuilder.AbstractShaped<IRecipe> implements BenchRecipeBuilder {
13+
14+
private final AbstractBenchRegistry registry;
15+
16+
public Shaped(AbstractBenchRegistry registry, int size) {
17+
super(size, size);
18+
this.registry = registry;
19+
}
20+
21+
@Override
22+
@RecipeBuilderRegistrationMethod
23+
public IRecipe register() {
24+
GroovyLog.Msg msg = GroovyLog.msg("Error adding shaped Armor Plus Bench recipe")
25+
.error()
26+
.add((keyBasedMatrix == null || keyBasedMatrix.length == 0) && (ingredientMatrix == null || ingredientMatrix.isEmpty()), () -> "No matrix was defined")
27+
.add(keyBasedMatrix != null && ingredientMatrix != null, () -> "A key based matrix AND a ingredient based matrix was defined. This is not allowed!");
28+
if (msg.postIfNotEmpty()) return null;
29+
msg.add(IngredientHelper.isEmpty(this.output), () -> "Output must not be empty");
30+
IShapedRecipe recipe = null;
31+
if (keyBasedMatrix != null) {
32+
recipe = validateShape(msg, errors, keyBasedMatrix, keyMap, ((width1, height1, ingredients) -> BenchShapedRecipe.make(width, output, ingredients, width1, height1, mirrored, recipeFunction, recipeAction)));
33+
} else if (ingredientMatrix != null) {
34+
recipe = validateShape(msg, ingredientMatrix, ((width1, height1, ingredients) -> BenchShapedRecipe.make(width, output.copy(), ingredients, width1, height1, mirrored, recipeFunction, recipeAction)));
35+
}
36+
if (msg.postIfNotEmpty()) return null;
37+
if (recipe != null) {
38+
registry.add(recipe);
39+
}
40+
return recipe;
41+
}
42+
}
43+
44+
class Shapeless extends AbstractCraftingRecipeBuilder.AbstractShapeless<IRecipe> implements BenchRecipeBuilder {
45+
46+
private final AbstractBenchRegistry registry;
47+
48+
public Shapeless(AbstractBenchRegistry registry, int size) {
49+
super(size, size);
50+
this.registry = registry;
51+
}
52+
53+
public boolean validate() {
54+
GroovyLog.Msg msg = GroovyLog.msg("Error adding shapeless Armor Plus Bench recipe").error();
55+
msg.add(IngredientHelper.isEmpty(this.output), () -> "Output must not be empty");
56+
msg.add(ingredients.isEmpty(), () -> "inputs must not be empty");
57+
msg.add(ingredients.size() > width * height, () -> "maximum inputs are " + (width * height) + " but found " + ingredients.size());
58+
return !msg.postIfNotEmpty();
59+
}
60+
61+
@Override
62+
@RecipeBuilderRegistrationMethod
63+
public IRecipe register() {
64+
if (!validate()) return null;
65+
IRecipe recipe = BenchShapelessRecipe.make(output.copy(), ingredients, recipeFunction, recipeAction);
66+
registry.add(recipe);
67+
return recipe;
68+
}
69+
}
70+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package com.cleanroommc.groovyscript.compat.mods.armorplus;
2+
3+
import com.cleanroommc.groovyscript.api.IIngredient;
4+
import com.cleanroommc.groovyscript.compat.vanilla.ShapedCraftingRecipe;
5+
import com.sofodev.armorplus.api.crafting.IRecipe;
6+
import com.sofodev.armorplus.api.crafting.IShapedRecipe;
7+
import com.sofodev.armorplus.api.crafting.base.BaseShapedOreRecipe;
8+
import com.sofodev.armorplus.common.container.base.InventoryCraftingImproved;
9+
import groovy.lang.Closure;
10+
import net.minecraft.item.ItemStack;
11+
import net.minecraft.item.crafting.Ingredient;
12+
import net.minecraft.util.NonNullList;
13+
import net.minecraft.world.World;
14+
import org.apache.commons.lang3.StringUtils;
15+
import org.jetbrains.annotations.NotNull;
16+
import org.jetbrains.annotations.Nullable;
17+
18+
import java.util.Arrays;
19+
import java.util.List;
20+
21+
public class BenchShapedRecipe extends BaseShapedOreRecipe implements IRecipe, IShapedRecipe {
22+
23+
private final int size;
24+
private final ShapedCraftingRecipe groovyRecipe;
25+
private final Object[] input;
26+
27+
private BenchShapedRecipe(int size, ShapedCraftingRecipe groovyRecipe, Object[] shapeDummy, Object[] input) {
28+
super(size, groovyRecipe.getRecipeOutput(), shapeDummy);
29+
this.size = size;
30+
this.groovyRecipe = groovyRecipe;
31+
this.input = input;
32+
}
33+
34+
public static BenchShapedRecipe make(int size, ItemStack output, List<IIngredient> input, int width, int height, boolean mirrored, @Nullable Closure<ItemStack> recipeFunction, @Nullable Closure<Void> recipeAction) {
35+
ShapedCraftingRecipe recipe = new ShapedCraftingRecipe(output, input, width, height, mirrored, recipeFunction, recipeAction);
36+
Object[] jeiInput = new Object[width * height];
37+
for (int i = 0; i < recipe.getIngredients().size(); i++) {
38+
jeiInput[i] = Arrays.asList(recipe.getIngredients().get(i).getMatchingStacks());
39+
}
40+
Object[] shapeDummy = new Object[height + 2];
41+
var row = StringUtils.repeat(' ', width);
42+
int i = 0;
43+
while (i < height) {
44+
shapeDummy[i++] = row;
45+
}
46+
shapeDummy[i++] = ' ';
47+
shapeDummy[i] = ItemStack.EMPTY;
48+
49+
return new BenchShapedRecipe(size, recipe, shapeDummy, jeiInput);
50+
}
51+
52+
public @NotNull NonNullList<Ingredient> getIngredients() {
53+
return groovyRecipe.getIngredients();
54+
}
55+
56+
@Override
57+
public int getRecipeWidth() {
58+
return size;
59+
}
60+
61+
@Override
62+
public int getRecipeHeight() {
63+
return size;
64+
}
65+
66+
@Override
67+
public boolean matches(@NotNull InventoryCraftingImproved inv, @NotNull World world) {
68+
return groovyRecipe.matches(inv, world);
69+
}
70+
71+
@Override
72+
public @NotNull ItemStack getCraftingResult(@NotNull InventoryCraftingImproved inv) {
73+
return groovyRecipe.getCraftingResult(inv);
74+
}
75+
76+
@Override
77+
public int getRecipeSize() {
78+
return size * size;
79+
}
80+
81+
@Override
82+
public @NotNull ItemStack getRecipeOutput() {
83+
return groovyRecipe.getRecipeOutput();
84+
}
85+
86+
@Override
87+
public Object[] getInput() {
88+
return this.input;
89+
}
90+
91+
@Override
92+
public NonNullList<ItemStack> getRemainingItems(InventoryCraftingImproved inv) {
93+
return groovyRecipe.getRemainingItems(inv);
94+
}
95+
}

0 commit comments

Comments
 (0)