Skip to content

Commit 2622070

Browse files
authored
allow recycling recipes to generate from assembler (GregTechCEu#2012)
1 parent 2fed5d4 commit 2622070

File tree

6 files changed

+183
-95
lines changed

6 files changed

+183
-95
lines changed

src/main/java/gregtech/api/recipes/ModHandler.java

Lines changed: 6 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import gregtech.api.items.toolitem.ToolHelper;
1010
import gregtech.api.recipes.recipes.DummyRecipe;
1111
import gregtech.api.unification.OreDictUnifier;
12-
import gregtech.api.unification.material.MarkerMaterial;
1312
import gregtech.api.unification.material.Material;
1413
import gregtech.api.unification.material.Materials;
1514
import gregtech.api.unification.material.properties.PropertyKey;
@@ -26,10 +25,6 @@
2625
import gregtech.common.crafting.GTShapedOreRecipe;
2726
import gregtech.common.crafting.GTShapelessOreRecipe;
2827
import gregtech.common.crafting.ShapedOreEnergyTransferRecipe;
29-
import it.unimi.dsi.fastutil.chars.Char2IntFunction;
30-
import it.unimi.dsi.fastutil.chars.Char2IntOpenHashMap;
31-
import it.unimi.dsi.fastutil.objects.Object2LongMap;
32-
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap;
3328
import net.minecraft.block.Block;
3429
import net.minecraft.inventory.InventoryCrafting;
3530
import net.minecraft.item.Item;
@@ -48,6 +43,7 @@
4843
import net.minecraftforge.registries.IForgeRegistry;
4944
import org.apache.commons.lang3.tuple.ImmutablePair;
5045
import org.apache.commons.lang3.tuple.Pair;
46+
import org.jetbrains.annotations.ApiStatus;
5147

5248
import javax.annotation.Nonnull;
5349
import javax.annotation.Nullable;
@@ -290,7 +286,7 @@ public static void addShapedRecipe(boolean withUnificationData, @Nonnull String
290286
addRecipe(regName, result, isNBTClearing, isMirrored, recipe);
291287

292288
if (withUnificationData) {
293-
OreDictUnifier.registerOre(result, getRecyclingIngredients(result.getCount(), recipe));
289+
OreDictUnifier.registerOre(result, RecyclingHandler.getRecyclingIngredients(result.getCount(), recipe));
294290
}
295291
}
296292

@@ -437,97 +433,13 @@ public static Object finalizeIngredient(@Nonnull Object ingredient) {
437433
* @param outputCount the amount of outputs the recipe has
438434
* @param recipe the recipe to retrieve from
439435
* @return the recycling ingredients for a recipe
436+
* @deprecated Use {@link RecyclingHandler#getRecyclingIngredients(int, Object...)}. Will be removed in 2.9
440437
*/
438+
@Deprecated
439+
@ApiStatus.ScheduledForRemoval(inVersion = "2.9")
441440
@Nullable
442441
public static ItemMaterialInfo getRecyclingIngredients(int outputCount, @Nonnull Object... recipe) {
443-
Char2IntOpenHashMap inputCountMap = new Char2IntOpenHashMap();
444-
Object2LongMap<Material> materialStacksExploded = new Object2LongOpenHashMap<>();
445-
446-
int itr = 0;
447-
while (recipe[itr] instanceof String s) {
448-
for (char c : s.toCharArray()) {
449-
if (ToolHelper.getToolFromSymbol(c) != null) continue; // skip tools
450-
int count = inputCountMap.getOrDefault(c, 0);
451-
inputCountMap.put(c, count + 1);
452-
}
453-
itr++;
454-
}
455-
456-
char lastChar = ' ';
457-
for (int i = itr; i < recipe.length; i++) {
458-
Object ingredient = recipe[i];
459-
460-
// Track the current working ingredient symbol
461-
if (ingredient instanceof Character) {
462-
lastChar = (char) ingredient;
463-
continue;
464-
}
465-
466-
// Should never happen if recipe is formatted correctly
467-
// In the case that it isn't, this error should be handled
468-
// by an earlier method call parsing the recipe.
469-
if (lastChar == ' ') return null;
470-
471-
ItemStack stack;
472-
if (ingredient instanceof MetaItem.MetaValueItem) {
473-
stack = ((MetaItem<?>.MetaValueItem) ingredient).getStackForm();
474-
} else if (ingredient instanceof UnificationEntry) {
475-
stack = OreDictUnifier.get((UnificationEntry) ingredient);
476-
} else if (ingredient instanceof ItemStack) {
477-
stack = (ItemStack) ingredient;
478-
} else if (ingredient instanceof Item) {
479-
stack = new ItemStack((Item) ingredient, 1);
480-
} else if (ingredient instanceof Block) {
481-
stack = new ItemStack((Block) ingredient, 1);
482-
} else if (ingredient instanceof String) {
483-
stack = OreDictUnifier.get((String) ingredient);
484-
} else continue; // throw out bad entries
485-
486-
// First try to get ItemMaterialInfo
487-
ItemMaterialInfo info = OreDictUnifier.getMaterialInfo(stack);
488-
if (info != null) {
489-
for (MaterialStack ms : info.getMaterials()) {
490-
if (!(ms.material instanceof MarkerMaterial)) {
491-
addMaterialStack(materialStacksExploded, inputCountMap, ms, lastChar);
492-
}
493-
}
494-
continue;
495-
}
496-
497-
// Then try to get a single Material (UnificationEntry needs this, for example)
498-
MaterialStack materialStack = OreDictUnifier.getMaterial(stack);
499-
if (materialStack != null && !(materialStack.material instanceof MarkerMaterial)) {
500-
addMaterialStack(materialStacksExploded, inputCountMap, materialStack, lastChar);
501-
}
502-
503-
// Gather any secondary materials if this item has an OrePrefix
504-
OrePrefix prefix = OreDictUnifier.getPrefix(stack);
505-
if (prefix != null && !prefix.secondaryMaterials.isEmpty()) {
506-
for (MaterialStack ms : prefix.secondaryMaterials) {
507-
addMaterialStack(materialStacksExploded, inputCountMap, ms, lastChar);
508-
}
509-
}
510-
}
511-
512-
return new ItemMaterialInfo(materialStacksExploded.entrySet().stream()
513-
.map(e -> new MaterialStack(e.getKey(), e.getValue() / outputCount))
514-
.sorted(Comparator.comparingLong(m -> -m.amount))
515-
.collect(Collectors.toList())
516-
);
517-
}
518-
519-
/**
520-
* Adds a MaterialStack to a map of {@code <Material, Quantity>}
521-
*
522-
* @param materialStacksExploded the map to add to
523-
* @param inputCountMap the map supplying quantities by char
524-
* @param ms the stack to add
525-
* @param c the char for quantities
526-
*/
527-
private static void addMaterialStack(@Nonnull Object2LongMap<Material> materialStacksExploded,
528-
@Nonnull Char2IntFunction inputCountMap, @Nonnull MaterialStack ms, char c) {
529-
long amount = materialStacksExploded.getOrDefault(ms.material, 0L);
530-
materialStacksExploded.put(ms.material, (ms.amount * inputCountMap.get(c)) + amount);
442+
return RecyclingHandler.getRecyclingIngredients(outputCount, recipe);
531443
}
532444

533445
/**

src/main/java/gregtech/api/recipes/RecipeMaps.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@
88
import gregtech.api.recipes.builders.*;
99
import gregtech.api.recipes.ingredients.GTRecipeInput;
1010
import gregtech.api.recipes.machines.*;
11+
import gregtech.api.unification.OreDictUnifier;
1112
import gregtech.api.unification.material.Materials;
13+
import gregtech.api.unification.stack.ItemMaterialInfo;
1214
import gregtech.api.util.AssemblyLineManager;
1315
import gregtech.core.sound.GTSoundEvents;
1416
import net.minecraft.init.SoundEvents;
17+
import net.minecraft.item.ItemStack;
1518
import stanhebben.zenscript.annotations.ZenClass;
1619
import stanhebben.zenscript.annotations.ZenProperty;
1720

@@ -111,6 +114,15 @@ public class RecipeMaps {
111114

112115
recipeBuilder.copy().clearFluidInputs().fluidInputs(Materials.Tin.getFluid(amount * 2)).buildAndRegister();
113116
}
117+
118+
if (recipeBuilder.isWithRecycling()) {
119+
// ignore input fluids for recycling
120+
ItemStack outputStack = recipeBuilder.getOutputs().get(0);
121+
ItemMaterialInfo info = RecyclingHandler.getRecyclingIngredients(recipeBuilder.getInputs(), outputStack.getCount());
122+
if (info != null) {
123+
OreDictUnifier.registerOre(outputStack, info);
124+
}
125+
}
114126
});
115127

116128
/**
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package gregtech.api.recipes;
2+
3+
import gregtech.api.items.metaitem.MetaItem;
4+
import gregtech.api.items.toolitem.ToolHelper;
5+
import gregtech.api.recipes.ingredients.GTRecipeInput;
6+
import gregtech.api.unification.OreDictUnifier;
7+
import gregtech.api.unification.material.MarkerMaterial;
8+
import gregtech.api.unification.material.Material;
9+
import gregtech.api.unification.ore.OrePrefix;
10+
import gregtech.api.unification.stack.ItemMaterialInfo;
11+
import gregtech.api.unification.stack.MaterialStack;
12+
import gregtech.api.unification.stack.UnificationEntry;
13+
import it.unimi.dsi.fastutil.chars.Char2IntOpenHashMap;
14+
import it.unimi.dsi.fastutil.objects.Object2LongMap;
15+
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap;
16+
import net.minecraft.block.Block;
17+
import net.minecraft.item.Item;
18+
import net.minecraft.item.ItemStack;
19+
import org.jetbrains.annotations.NotNull;
20+
import org.jetbrains.annotations.Nullable;
21+
22+
import java.util.Comparator;
23+
import java.util.List;
24+
import java.util.stream.Collectors;
25+
26+
public class RecyclingHandler {
27+
28+
public static @Nullable ItemMaterialInfo getRecyclingIngredients(int outputCount, @NotNull Object... recipe) {
29+
Char2IntOpenHashMap inputCountMap = new Char2IntOpenHashMap();
30+
Object2LongMap<Material> materialStacksExploded = new Object2LongOpenHashMap<>();
31+
32+
int itr = 0;
33+
while (recipe[itr] instanceof String s) {
34+
for (char c : s.toCharArray()) {
35+
if (ToolHelper.getToolFromSymbol(c) != null) continue; // skip tools
36+
int count = inputCountMap.getOrDefault(c, 0);
37+
inputCountMap.put(c, count + 1);
38+
}
39+
itr++;
40+
}
41+
42+
char lastChar = ' ';
43+
for (int i = itr; i < recipe.length; i++) {
44+
Object ingredient = recipe[i];
45+
46+
// Track the current working ingredient symbol
47+
if (ingredient instanceof Character) {
48+
lastChar = (char) ingredient;
49+
continue;
50+
}
51+
52+
// Should never happen if recipe is formatted correctly
53+
// In the case that it isn't, this error should be handled
54+
// by an earlier method call parsing the recipe.
55+
if (lastChar == ' ') return null;
56+
57+
ItemStack stack;
58+
if (ingredient instanceof MetaItem.MetaValueItem) {
59+
stack = ((MetaItem<?>.MetaValueItem) ingredient).getStackForm();
60+
} else if (ingredient instanceof UnificationEntry) {
61+
stack = OreDictUnifier.get((UnificationEntry) ingredient);
62+
} else if (ingredient instanceof ItemStack) {
63+
stack = (ItemStack) ingredient;
64+
} else if (ingredient instanceof Item) {
65+
stack = new ItemStack((Item) ingredient, 1);
66+
} else if (ingredient instanceof Block) {
67+
stack = new ItemStack((Block) ingredient, 1);
68+
} else if (ingredient instanceof String) {
69+
stack = OreDictUnifier.get((String) ingredient);
70+
} else continue; // throw out bad entries
71+
72+
addItemStackToMaterialStacks(stack, materialStacksExploded, inputCountMap.get(lastChar));
73+
}
74+
75+
return new ItemMaterialInfo(materialStacksExploded.entrySet().stream()
76+
.map(e -> new MaterialStack(e.getKey(), e.getValue() / outputCount))
77+
.sorted(Comparator.comparingLong(m -> -m.amount))
78+
.collect(Collectors.toList())
79+
);
80+
}
81+
82+
public static @Nullable ItemMaterialInfo getRecyclingIngredients(List<GTRecipeInput> inputs, int outputCount) {
83+
Object2LongMap<Material> materialStacksExploded = new Object2LongOpenHashMap<>();
84+
for (GTRecipeInput input : inputs) {
85+
if (input == null) continue;
86+
ItemStack[] inputStacks = input.getInputStacks();
87+
if (inputStacks == null || inputStacks.length == 0) continue;
88+
ItemStack inputStack = inputStacks[0];
89+
addItemStackToMaterialStacks(inputStack, materialStacksExploded, inputStack.getCount());
90+
}
91+
92+
return new ItemMaterialInfo(materialStacksExploded.entrySet().stream()
93+
.map(e -> new MaterialStack(e.getKey(), e.getValue() / outputCount))
94+
.sorted(Comparator.comparingLong(m -> -m.amount))
95+
.collect(Collectors.toList()));
96+
}
97+
98+
private static void addItemStackToMaterialStacks(@NotNull ItemStack itemStack,
99+
@NotNull Object2LongMap<Material> materialStacksExploded,
100+
int inputCount) {
101+
// First try to get ItemMaterialInfo
102+
ItemMaterialInfo info = OreDictUnifier.getMaterialInfo(itemStack);
103+
if (info != null) {
104+
for (MaterialStack ms : info.getMaterials()) {
105+
if (!(ms.material instanceof MarkerMaterial)) {
106+
addMaterialStack(materialStacksExploded, inputCount, ms);
107+
}
108+
}
109+
return;
110+
}
111+
112+
// Then try to get a single Material (UnificationEntry needs this, for example)
113+
MaterialStack materialStack = OreDictUnifier.getMaterial(itemStack);
114+
if (materialStack != null && !(materialStack.material instanceof MarkerMaterial)) {
115+
addMaterialStack(materialStacksExploded, inputCount, materialStack);
116+
}
117+
118+
// Gather any secondary materials if this item has an OrePrefix
119+
OrePrefix prefix = OreDictUnifier.getPrefix(itemStack);
120+
if (prefix != null && !prefix.secondaryMaterials.isEmpty()) {
121+
for (MaterialStack ms : prefix.secondaryMaterials) {
122+
addMaterialStack(materialStacksExploded, inputCount, ms);
123+
}
124+
}
125+
}
126+
127+
/**
128+
* Adds a MaterialStack to a map of {@code <Material, Quantity>}
129+
*
130+
* @param materialStacksExploded the map to add to
131+
* @param inputCount the number of items in the stack
132+
* @param ms the stack to add
133+
*/
134+
private static void addMaterialStack(@NotNull Object2LongMap<Material> materialStacksExploded,
135+
int inputCount, @NotNull MaterialStack ms) {
136+
long amount = materialStacksExploded.getOrDefault(ms.material, 0L);
137+
materialStacksExploded.put(ms.material, (ms.amount * inputCount) + amount);
138+
}
139+
}

src/main/java/gregtech/api/recipes/builders/AssemblerRecipeBuilder.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
public class AssemblerRecipeBuilder extends RecipeBuilder<AssemblerRecipeBuilder> {
88

9+
private boolean withRecycling;
10+
911
public AssemblerRecipeBuilder() {/**/}
1012

1113
@SuppressWarnings("unused")
@@ -15,10 +17,26 @@ public AssemblerRecipeBuilder(Recipe recipe, RecipeMap<AssemblerRecipeBuilder> r
1517

1618
public AssemblerRecipeBuilder(AssemblerRecipeBuilder recipeBuilder) {
1719
super(recipeBuilder);
20+
if (recipeBuilder.isWithRecycling()) {
21+
this.withRecycling = true;
22+
}
1823
}
1924

2025
@Override
2126
public AssemblerRecipeBuilder copy() {
22-
return new AssemblerRecipeBuilder(this);
27+
var builder = new AssemblerRecipeBuilder(this);
28+
if (withRecycling) {
29+
return builder.withRecycling();
30+
}
31+
return builder;
32+
}
33+
34+
public AssemblerRecipeBuilder withRecycling() {
35+
withRecycling = true;
36+
return this;
37+
}
38+
39+
public boolean isWithRecycling() {
40+
return withRecycling;
2341
}
2442
}

src/main/java/gregtech/loaders/recipe/ComponentRecipes.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ public static void register() {
352352
.outputs(FLUID_REGULATOR_LV.getStackForm())
353353
.EUt(VA[LV])
354354
.duration(400)
355+
.withRecycling()
355356
.buildAndRegister();
356357

357358
ASSEMBLER_RECIPES.recipeBuilder()
@@ -361,6 +362,7 @@ public static void register() {
361362
.outputs(FLUID_REGULATOR_MV.getStackForm())
362363
.EUt(VA[MV])
363364
.duration(350)
365+
.withRecycling()
364366
.buildAndRegister();
365367

366368
ASSEMBLER_RECIPES.recipeBuilder()
@@ -370,6 +372,7 @@ public static void register() {
370372
.outputs(FLUID_REGULATOR_HV.getStackForm())
371373
.EUt(VA[HV])
372374
.duration(300)
375+
.withRecycling()
373376
.buildAndRegister();
374377

375378
ASSEMBLER_RECIPES.recipeBuilder()
@@ -379,6 +382,7 @@ public static void register() {
379382
.outputs(FLUID_REGULATOR_EV.getStackForm())
380383
.EUt(VA[EV])
381384
.duration(250)
385+
.withRecycling()
382386
.buildAndRegister();
383387

384388
ASSEMBLER_RECIPES.recipeBuilder()
@@ -388,6 +392,7 @@ public static void register() {
388392
.outputs(FLUID_REGULATOR_IV.getStackForm())
389393
.EUt(VA[IV])
390394
.duration(200)
395+
.withRecycling()
391396
.buildAndRegister();
392397

393398
ASSEMBLER_RECIPES.recipeBuilder()

0 commit comments

Comments
 (0)