Skip to content

Commit 0cb0b23

Browse files
authored
recipe manager handling refactor (#3975)
1 parent b4e580d commit 0cb0b23

3 files changed

Lines changed: 114 additions & 62 deletions

File tree

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.gregtechceu.gtceu.api.recipe.lookup;
2+
3+
import com.gregtechceu.gtceu.GTCEu;
4+
import com.gregtechceu.gtceu.api.recipe.GTRecipe;
5+
import com.gregtechceu.gtceu.api.recipe.GTRecipeType;
6+
7+
import net.minecraft.resources.ResourceLocation;
8+
import net.minecraft.world.item.crafting.Recipe;
9+
import net.minecraft.world.item.crafting.RecipeType;
10+
import net.minecraftforge.registries.ForgeRegistries;
11+
12+
import org.jetbrains.annotations.ApiStatus;
13+
import org.jetbrains.annotations.NotNull;
14+
15+
import java.util.List;
16+
import java.util.Map;
17+
18+
/**
19+
* Internal class handling adding recipes to GT's lookup system.
20+
* <p>
21+
* Intended for use by {@link com.gregtechceu.gtceu.core.mixins.RecipeManagerMixin} and
22+
* {@link com.gregtechceu.gtceu.integration.kjs.GregTechKubeJSPlugin}
23+
*/
24+
@ApiStatus.Internal
25+
public final class RecipeManagerHandler {
26+
27+
/**
28+
* Adds proxy recipes to an {@link GTRecipeType}'s {@link GTRecipeLookup} and adds them to a list.
29+
*
30+
* @param recipesByID the recipes stored by their ID
31+
* @param gtRecipeType the recipe type to add the recipes to, which owns the proxy recipes
32+
* @param proxyType the recipeType for the proxy recipes
33+
* @param proxyRecipes the list of proxy recipes to populate
34+
*/
35+
public static void addProxyRecipesToLookup(@NotNull Map<ResourceLocation, Recipe<?>> recipesByID,
36+
@NotNull GTRecipeType gtRecipeType, @NotNull RecipeType<?> proxyType,
37+
@NotNull List<GTRecipe> proxyRecipes) {
38+
var lookup = gtRecipeType.getLookup();
39+
proxyRecipes.clear();
40+
recipesByID.forEach((id, recipe) -> {
41+
if (recipe.getType() != proxyType) {
42+
// should not happen
43+
GTCEu.LOGGER.warn("Proxy Recipe '{}' with RecipeType '{}' did not match GTRecipeType '{}'.",
44+
recipe.getId(), ForgeRegistries.RECIPE_TYPES.getKey(recipe.getType()),
45+
gtRecipeType.registryName);
46+
return;
47+
}
48+
GTRecipe gtRecipe = gtRecipeType.toGTrecipe(id, recipe);
49+
proxyRecipes.add(gtRecipe);
50+
lookup.addRecipe(gtRecipe);
51+
});
52+
}
53+
54+
/**
55+
* Adds recipes to an {@link GTRecipeType}'s {@link GTRecipeLookup}
56+
*
57+
* @param recipesByID the recipes stored by their ID
58+
* @param gtRecipeType the recipe type to add recipes to
59+
*/
60+
public static void addRecipesToLookup(@NotNull Map<ResourceLocation, Recipe<?>> recipesByID,
61+
@NotNull GTRecipeType gtRecipeType) {
62+
var lookup = gtRecipeType.getLookup();
63+
for (var r : recipesByID.values()) {
64+
if (r.getType() != gtRecipeType) {
65+
// should not happen
66+
GTCEu.LOGGER.warn("Recipe '{}' with RecipeType '{}' did not match GTRecipeType '{}'.",
67+
r.getId(), ForgeRegistries.RECIPE_TYPES.getKey(r.getType()),
68+
gtRecipeType.registryName);
69+
continue;
70+
}
71+
if (r instanceof GTRecipe recipe) {
72+
lookup.addRecipe(recipe);
73+
}
74+
}
75+
}
76+
}
Lines changed: 20 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
package com.gregtechceu.gtceu.core.mixins;
22

3-
import com.gregtechceu.gtceu.api.recipe.GTRecipe;
43
import com.gregtechceu.gtceu.api.recipe.GTRecipeType;
4+
import com.gregtechceu.gtceu.api.recipe.lookup.RecipeManagerHandler;
55
import com.gregtechceu.gtceu.common.item.armor.PowerlessJetpack;
66

7-
import net.minecraft.core.registries.BuiltInRegistries;
87
import net.minecraft.resources.ResourceLocation;
98
import net.minecraft.server.packs.resources.ResourceManager;
109
import net.minecraft.util.profiling.ProfilerFiller;
1110
import net.minecraft.world.item.crafting.Recipe;
1211
import net.minecraft.world.item.crafting.RecipeManager;
1312
import net.minecraft.world.item.crafting.RecipeType;
13+
import net.minecraftforge.registries.ForgeRegistries;
1414

1515
import com.google.gson.JsonElement;
1616
import org.spongepowered.asm.mixin.Mixin;
@@ -19,11 +19,11 @@
1919
import org.spongepowered.asm.mixin.injection.Inject;
2020
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
2121

22-
import java.util.List;
2322
import java.util.Map;
24-
import java.util.stream.Stream;
2523

26-
// only fires if KJS is NOT loaded.
24+
/**
25+
* Only fires if KubeJS is not interacting with GT recipes.
26+
*/
2727
@Mixin(RecipeManager.class)
2828
public abstract class RecipeManagerMixin {
2929

@@ -35,36 +35,23 @@ public abstract class RecipeManagerMixin {
3535
private void gtceu$cloneVanillaRecipes(Map<ResourceLocation, JsonElement> map, ResourceManager resourceManager,
3636
ProfilerFiller profiler, CallbackInfo ci) {
3737
PowerlessJetpack.FUELS.clear();
38-
for (RecipeType<?> recipeType : BuiltInRegistries.RECIPE_TYPE) {
39-
if (recipeType instanceof GTRecipeType gtRecipeType) {
40-
gtRecipeType.getLookup().removeAllRecipes();
41-
42-
var proxyRecipes = gtRecipeType.getProxyRecipes();
43-
for (Map.Entry<RecipeType<?>, List<GTRecipe>> entry : proxyRecipes.entrySet()) {
44-
var type = entry.getKey();
45-
var recipes = entry.getValue();
46-
recipes.clear();
47-
if (this.recipes.containsKey(type)) {
48-
for (var recipe : this.recipes.get(type).entrySet()) {
49-
recipes.add(gtRecipeType.toGTrecipe(recipe.getKey(), recipe.getValue()));
50-
}
51-
}
52-
}
53-
54-
if (this.recipes.containsKey(gtRecipeType)) {
55-
Stream.concat(
56-
this.recipes.get(gtRecipeType).values().stream(),
57-
proxyRecipes.entrySet().stream()
58-
.flatMap(entry -> entry.getValue().stream()))
59-
.filter(GTRecipe.class::isInstance)
60-
.map(GTRecipe.class::cast)
61-
.forEach(gtRecipe -> gtRecipeType.getLookup().addRecipe(gtRecipe));
62-
} else if (!proxyRecipes.isEmpty()) {
63-
proxyRecipes.values().stream()
64-
.flatMap(List::stream)
65-
.forEach(gtRecipe -> gtRecipeType.getLookup().addRecipe(gtRecipe));
38+
for (RecipeType<?> recipeType : ForgeRegistries.RECIPE_TYPES) {
39+
if (!(recipeType instanceof GTRecipeType gtRecipeType)) {
40+
continue;
41+
}
42+
gtRecipeType.getLookup().removeAllRecipes();
43+
gtRecipeType.getProxyRecipes().forEach((type, list) -> {
44+
var recipesByID = recipes.get(type);
45+
if (recipesByID == null) {
46+
return;
6647
}
48+
RecipeManagerHandler.addProxyRecipesToLookup(recipesByID, gtRecipeType, type, list);
49+
});
50+
var recipesByID = recipes.get(gtRecipeType);
51+
if (recipesByID == null) {
52+
continue;
6753
}
54+
RecipeManagerHandler.addRecipesToLookup(recipesByID, gtRecipeType);
6855
}
6956
}
7057
}

src/main/java/com/gregtechceu/gtceu/integration/kjs/GregTechKubeJSPlugin.java

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,13 @@
4747
import com.gregtechceu.gtceu.api.pattern.MultiblockShapeInfo;
4848
import com.gregtechceu.gtceu.api.pattern.Predicates;
4949
import com.gregtechceu.gtceu.api.recipe.DummyCraftingContainer;
50-
import com.gregtechceu.gtceu.api.recipe.GTRecipe;
5150
import com.gregtechceu.gtceu.api.recipe.GTRecipeSerializer;
5251
import com.gregtechceu.gtceu.api.recipe.GTRecipeType;
5352
import com.gregtechceu.gtceu.api.recipe.OverclockingLogic;
5453
import com.gregtechceu.gtceu.api.recipe.category.GTRecipeCategory;
5554
import com.gregtechceu.gtceu.api.recipe.chance.logic.ChanceLogic;
5655
import com.gregtechceu.gtceu.api.recipe.ingredient.EnergyStack;
56+
import com.gregtechceu.gtceu.api.recipe.lookup.RecipeManagerHandler;
5757
import com.gregtechceu.gtceu.api.recipe.modifier.ModifierFunction;
5858
import com.gregtechceu.gtceu.api.registry.GTRegistries;
5959
import com.gregtechceu.gtceu.api.registry.registrate.MultiblockMachineBuilder;
@@ -92,7 +92,6 @@
9292
import com.gregtechceu.gtceu.integration.kjs.recipe.components.GTRecipeComponents;
9393
import com.gregtechceu.gtceu.utils.data.RuntimeBlockStateProvider;
9494

95-
import net.minecraft.core.registries.BuiltInRegistries;
9695
import net.minecraft.data.PackOutput;
9796
import net.minecraft.nbt.NbtOps;
9897
import net.minecraft.resources.ResourceLocation;
@@ -105,6 +104,7 @@
105104
import net.minecraft.world.level.block.SoundType;
106105
import net.minecraft.world.level.levelgen.placement.HeightRangePlacement;
107106
import net.minecraftforge.items.ItemStackHandler;
107+
import net.minecraftforge.registries.ForgeRegistries;
108108

109109
import com.mojang.serialization.DataResult;
110110
import dev.latvian.mods.kubejs.KubeJSPaths;
@@ -133,7 +133,6 @@
133133
import java.util.*;
134134
import java.util.Map;
135135
import java.util.stream.Collectors;
136-
import java.util.stream.Stream;
137136

138137
import static dev.latvian.mods.kubejs.recipe.schema.minecraft.ShapedRecipeSchema.KEY;
139138
import static dev.latvian.mods.kubejs.recipe.schema.minecraft.ShapedRecipeSchema.PATTERN;
@@ -523,39 +522,29 @@ public void injectRuntimeRecipes(RecipesEventJS event, RecipeManager manager,
523522
GTRecipeSerializer.SERIALIZER.fromJson(builtRecipe.getId(), builtRecipe.serializeRecipe())));
524523

525524
// clone vanilla recipes for stuff like electric furnaces, etc
526-
for (RecipeType<?> recipeType : BuiltInRegistries.RECIPE_TYPE) {
527-
if (recipeType instanceof GTRecipeType gtRecipeType) {
528-
gtRecipeType.getLookup().removeAllRecipes();
529-
530-
var proxyRecipes = gtRecipeType.getProxyRecipes();
531-
for (Map.Entry<RecipeType<?>, List<GTRecipe>> entry : proxyRecipes.entrySet()) {
532-
var type = entry.getKey();
533-
var recipes = entry.getValue();
534-
recipes.clear();
535-
for (var recipe : recipesByName.entrySet().stream()
536-
.filter(recipe -> recipe.getValue().getType() == type).collect(Collectors.toSet())) {
537-
recipes.add(gtRecipeType.toGTrecipe(recipe.getKey(), recipe.getValue()));
538-
}
539-
}
540-
541-
Stream.concat(
542-
recipesByName.values().stream()
543-
.filter(recipe -> recipe.getType() == gtRecipeType),
544-
proxyRecipes.entrySet().stream()
545-
.flatMap(entry -> entry.getValue().stream()))
546-
.filter(GTRecipe.class::isInstance)
547-
.map(GTRecipe.class::cast)
548-
.forEach(gtRecipe -> gtRecipeType.getLookup().addRecipe(gtRecipe));
525+
for (RecipeType<?> recipeType : ForgeRegistries.RECIPE_TYPES) {
526+
if (!(recipeType instanceof GTRecipeType gtRecipeType)) {
527+
continue;
549528
}
529+
gtRecipeType.getLookup().removeAllRecipes();
530+
gtRecipeType.getProxyRecipes().forEach((type, list) -> {
531+
RecipeManagerHandler.addProxyRecipesToLookup(recipesByName, gtRecipeType, type, list);
532+
});
533+
RecipeManagerHandler.addRecipesToLookup(recipesByName, gtRecipeType);
550534
}
551535
}
552536

553537
private static void handleGTRecipe(Map<ResourceLocation, Recipe<?>> recipesByName,
554538
GTRecipeSchema.GTRecipeJS gtRecipe) {
555-
// get the recipe ID without the leading type path
556-
GTRecipeBuilder builder = ((GTRecipeType) BuiltInRegistries.RECIPE_TYPE.get(gtRecipe.type.id))
557-
.recipeBuilder(gtRecipe.idWithoutType());
539+
GTRecipeType gtRecipeType = (GTRecipeType) ForgeRegistries.RECIPE_TYPES.getValue(gtRecipe.getType());
540+
if (gtRecipeType == null) {
541+
GTCEu.LOGGER.error("Failed to get GTRecipeType from GTRecipe: '{}' with type '{}'", gtRecipe.getId(),
542+
gtRecipe.getType());
543+
return;
544+
}
558545

546+
// get the recipe ID without the leading type path
547+
GTRecipeBuilder builder = gtRecipeType.recipeBuilder(gtRecipe.idWithoutType());
559548
if (gtRecipe.getValue(GTRecipeSchema.DURATION) != null) {
560549
builder.duration = gtRecipe.getValue(GTRecipeSchema.DURATION).intValue();
561550
}

0 commit comments

Comments
 (0)