From a19d423d6eb4649fd5871ff7eca78a6bf1b46410 Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Fri, 31 Jul 2026 19:38:25 +0300 Subject: [PATCH 01/19] Fix half of #3981 not being ported to 1.21 somebody-a forgot to merge half of #3981. not having it broke reloading. --- .../recipe/lookup/RecipeManagerHandler.java | 66 +++++++++++++++++++ .../core/mixins/RecipeManagerLateMixin.java | 52 +++++---------- 2 files changed, 83 insertions(+), 35 deletions(-) create mode 100644 src/main/java/com/gregtechceu/gtceu/api/recipe/lookup/RecipeManagerHandler.java diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/lookup/RecipeManagerHandler.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/lookup/RecipeManagerHandler.java new file mode 100644 index 00000000000..f5e5bd08c5d --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/lookup/RecipeManagerHandler.java @@ -0,0 +1,66 @@ +package com.gregtechceu.gtceu.api.recipe.lookup; + +import com.gregtechceu.gtceu.api.recipe.GTRecipe; +import com.gregtechceu.gtceu.api.recipe.GTRecipeType; + +import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.item.crafting.RecipeType; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.List; + +/** + * Internal class handling adding recipes to GT's lookup system. + *

+ * Intended for use by {@link com.gregtechceu.gtceu.core.mixins.RecipeManagerLateMixin} and + * {@link com.gregtechceu.gtceu.integration.kjs.GregTechKubeJSPlugin} + */ +@ApiStatus.Internal +public final class RecipeManagerHandler { + + /** + * Adds proxy recipes to an {@link GTRecipeType}'s {@link RecipeAdditionHandler} and adds them to a list. + * + * @param recipes the recipes stored by their ID + * @param gtRecipeType the recipe type to add the recipes to, which owns the proxy recipes + * @param proxyRecipes the list of proxy recipes to populate + */ + public static void addProxyRecipesToLookup(@NotNull Collection> recipes, + @NotNull GTRecipeType gtRecipeType, @NotNull RecipeType proxyType, + @NotNull List> proxyRecipes) { + var lookup = gtRecipeType.getAdditionHandler(); + proxyRecipes.clear(); + recipes.forEach((recipe) -> { + if (recipe.value().getType() != proxyType) { + // do not add recipes of incompatible type + return; + } + RecipeHolder gtRecipe = gtRecipeType.toGTRecipe(recipe); + proxyRecipes.add(gtRecipe); + lookup.addStaging(gtRecipe.value()); + }); + } + + /** + * Adds recipes to an {@link GTRecipeType}'s {@link RecipeAdditionHandler} + * + * @param recipes the recipes stored by their ID + * @param gtRecipeType the recipe type to add recipes to + */ + public static void addRecipesToLookup(@NotNull Collection> recipes, + @NotNull GTRecipeType gtRecipeType) { + var lookup = gtRecipeType.getAdditionHandler(); + for (RecipeHolder r : recipes) { + if (r.value().getType() != gtRecipeType) { + // do not add recipes of incompatible type + continue; + } + if (r.value() instanceof GTRecipe recipe) { + lookup.addStaging(recipe); + } + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerLateMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerLateMixin.java index 563c9523382..03da562da57 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerLateMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerLateMixin.java @@ -2,7 +2,8 @@ import com.gregtechceu.gtceu.api.recipe.GTRecipe; import com.gregtechceu.gtceu.api.recipe.GTRecipeType; -import com.gregtechceu.gtceu.api.recipe.lookup.StagingRecipeDB; +import com.gregtechceu.gtceu.api.recipe.lookup.MapIngredientPool; +import com.gregtechceu.gtceu.api.recipe.lookup.RecipeManagerHandler; import com.gregtechceu.gtceu.data.recipe.builder.GTRecipeBuilder; import net.minecraft.advancements.Advancement; @@ -31,10 +32,9 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.Collection; import java.util.HashMap; -import java.util.List; import java.util.Map; -import java.util.stream.Stream; @Mixin(value = RecipeManager.class, priority = 1500) public abstract class RecipeManagerLateMixin { @@ -76,40 +76,22 @@ public void accept(@NotNull ResourceLocation id, @NotNull Recipe recipe, gtceu$replaceRecipes(recipesByName); for (RecipeType recipeType : BuiltInRegistries.RECIPE_TYPE) { - if (recipeType instanceof GTRecipeType gtRecipeType) { - var stagingDB = new StagingRecipeDB(); - - var proxyRecipes = gtRecipeType.getProxyRecipes(); - for (Map.Entry, List>> entry : proxyRecipes.entrySet()) { - var type = entry.getKey(); - var recipes = entry.getValue(); - recipes.clear(); - if (this.byType.containsKey(type)) { - for (var recipe : this.byType.get(type)) { - recipes.add(gtRecipeType.toGTRecipe(recipe)); - } - } - } - - if (this.byType.containsKey(gtRecipeType)) { - Stream.concat( - this.byType.get(gtRecipeType).stream(), - proxyRecipes.entrySet().stream().flatMap(entry -> entry.getValue().stream())) - .filter(holder -> holder != null && holder.value() instanceof GTRecipe) - .forEach(holder -> { - GTRecipe recipe = (GTRecipe) holder.value(); - recipe.setId(holder.id()); - stagingDB.add(recipe); - }); - } else if (!proxyRecipes.isEmpty()) { - proxyRecipes.values().stream() - .flatMap(List::stream) - .forEach(gtRecipe -> stagingDB.add(gtRecipe.value())); - } - - stagingDB.populateDB(gtRecipeType.db()); + if (!(recipeType instanceof GTRecipeType gtRecipeType)) { + continue; } + gtRecipeType.beginStagingRecipes(); + gtRecipeType.getProxyRecipes().forEach((type, list) -> { + Collection> recipes = this.byType.get(type); + if (recipes.isEmpty()) { + return; + } + RecipeManagerHandler.addProxyRecipesToLookup(recipes, gtRecipeType, type, list); + }); + Collection> recipesByID = this.byType.get(gtRecipeType); + RecipeManagerHandler.addRecipesToLookup(recipesByID, gtRecipeType); + gtRecipeType.getAdditionHandler().completeStaging(); } + MapIngredientPool.clear(); } @Unique From a211f0fb84643ddfef354c84be56ea3f1dde17e2 Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Wed, 5 Aug 2026 12:00:47 +0300 Subject: [PATCH 02/19] Use vanilla's `replaceRecipes` method instead of adding our own --- .../core/mixins/RecipeManagerLateMixin.java | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerLateMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerLateMixin.java index 03da562da57..28770123d8f 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerLateMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerLateMixin.java @@ -20,20 +20,18 @@ import net.minecraft.world.item.crafting.RecipeType; import net.neoforged.neoforge.common.conditions.ICondition; -import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Multimap; import com.google.gson.JsonElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.Collection; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; @Mixin(value = RecipeManager.class, priority = 1500) @@ -45,11 +43,16 @@ public abstract class RecipeManagerLateMixin { @Shadow private Map> byName; + @Shadow + public abstract void replaceRecipes(Iterable> recipes); + @Inject(method = "apply(Ljava/util/Map;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V", at = @At(value = "TAIL")) private void gtceu$cloneVanillaRecipes(Map map, ResourceManager resourceManager, ProfilerFiller profiler, CallbackInfo ci) { - var recipesByName = new HashMap<>(byName); + // use a linked hash map to keep the immutable map's order + Map> recipesByName = new LinkedHashMap<>(byName); + // regenerate child recipes byName.values().forEach(holder -> { if (holder.value() instanceof GTRecipe gtRecipe) { new GTRecipeBuilder(gtRecipe, gtRecipe.recipeType) @@ -73,7 +76,7 @@ public void accept(@NotNull ResourceLocation id, @NotNull Recipe recipe, }); } }); - gtceu$replaceRecipes(recipesByName); + replaceRecipes(recipesByName.values()); for (RecipeType recipeType : BuiltInRegistries.RECIPE_TYPE) { if (!(recipeType instanceof GTRecipeType gtRecipeType)) { @@ -93,17 +96,4 @@ public void accept(@NotNull ResourceLocation id, @NotNull Recipe recipe, } MapIngredientPool.clear(); } - - @Unique - public void gtceu$replaceRecipes(Map> map) { - byName = map; - - var recipesByType = ImmutableMultimap., RecipeHolder>builder(); - - for (var entry : map.entrySet()) { - recipesByType.put(entry.getValue().value().getType(), entry.getValue()); - } - - byType = recipesByType.build(); - } } From 78a41fc4b4006a7811b93d9462b0e03a7349ae17 Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Wed, 5 Aug 2026 21:18:30 +0300 Subject: [PATCH 03/19] Move dynamic recipe generation/loading to a handler class[^1] and delay it to only happen when recipes are parsed so we have a more complete registry context [^1]: from the mixins it used to reside in --- .../gtceu/api/recipe/GTRecipeType.java | 5 + .../recipe/lookup/RecipeManagerHandler.java | 4 +- .../core/mixins/RecipeManagerEarlyMixin.java | 24 ++- .../core/mixins/RecipeManagerLateMixin.java | 86 ++-------- .../ReloadableServerResourcesMixin.java | 23 +-- .../data/dynamic/DynamicRecipeHandler.java | 155 ++++++++++++++++++ .../gtceu/data/pack/GTDynamicDataPack.java | 25 ++- 7 files changed, 212 insertions(+), 110 deletions(-) create mode 100644 src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicRecipeHandler.java diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipeType.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipeType.java index db990d0abbb..ffc03e4ae6b 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipeType.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipeType.java @@ -324,6 +324,11 @@ public void beginStagingRecipes() { additionHandler.beginStaging(); } + @ApiStatus.Internal + public void completeStagingRecipes() { + additionHandler.completeStaging(); + } + public interface ICustomRecipeLogic { /** diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/lookup/RecipeManagerHandler.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/lookup/RecipeManagerHandler.java index f5e5bd08c5d..f7ec6345ad4 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/lookup/RecipeManagerHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/lookup/RecipeManagerHandler.java @@ -28,7 +28,7 @@ public final class RecipeManagerHandler { * @param gtRecipeType the recipe type to add the recipes to, which owns the proxy recipes * @param proxyRecipes the list of proxy recipes to populate */ - public static void addProxyRecipesToLookup(@NotNull Collection> recipes, + public static void addProxyRecipesToLookup(@NotNull Collection> recipes, @NotNull GTRecipeType gtRecipeType, @NotNull RecipeType proxyType, @NotNull List> proxyRecipes) { var lookup = gtRecipeType.getAdditionHandler(); @@ -50,7 +50,7 @@ public static void addProxyRecipesToLookup(@NotNull Collection> * @param recipes the recipes stored by their ID * @param gtRecipeType the recipe type to add recipes to */ - public static void addRecipesToLookup(@NotNull Collection> recipes, + public static void addRecipesToLookup(@NotNull Collection> recipes, @NotNull GTRecipeType gtRecipeType) { var lookup = gtRecipeType.getAdditionHandler(); for (RecipeHolder r : recipes) { diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerEarlyMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerEarlyMixin.java index 2cb9557f2a8..d9cc4e81277 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerEarlyMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerEarlyMixin.java @@ -1,14 +1,19 @@ package com.gregtechceu.gtceu.core.mixins; -import com.gregtechceu.gtceu.common.data.GTRecipes; +import com.gregtechceu.gtceu.data.dynamic.DynamicRecipeHandler; +import net.minecraft.core.HolderLookup; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.item.crafting.RecipeManager; +import com.google.gson.Gson; import com.google.gson.JsonElement; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -16,12 +21,21 @@ import java.util.Map; @Mixin(value = RecipeManager.class, priority = 500) -public abstract class RecipeManagerEarlyMixin { +public abstract class RecipeManagerEarlyMixin extends SimpleJsonResourceReloadListener { + + @Shadow + @Final + private HolderLookup.Provider registries; + + private RecipeManagerEarlyMixin(Gson gson, String directory) { + super(gson, directory); + } @Inject(method = "apply(Ljava/util/Map;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V", at = @At("HEAD")) - private void gtceu$removeRecipes(Map map, ResourceManager pResourceManager, - ProfilerFiller pProfiler, CallbackInfo ci) { - GTRecipes.recipeRemoval(map::remove); + private void gtceu$handleDynamicRecipesEarly(Map map, + ResourceManager resourceManager, ProfilerFiller profiler, + CallbackInfo ci) { + DynamicRecipeHandler.handleRecipesEarly(map, this.registries, this.makeConditionalOps()); } } diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerLateMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerLateMixin.java index 28770123d8f..8e97a5239c2 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerLateMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerLateMixin.java @@ -1,99 +1,33 @@ package com.gregtechceu.gtceu.core.mixins; -import com.gregtechceu.gtceu.api.recipe.GTRecipe; -import com.gregtechceu.gtceu.api.recipe.GTRecipeType; -import com.gregtechceu.gtceu.api.recipe.lookup.MapIngredientPool; -import com.gregtechceu.gtceu.api.recipe.lookup.RecipeManagerHandler; -import com.gregtechceu.gtceu.data.recipe.builder.GTRecipeBuilder; +import com.gregtechceu.gtceu.data.dynamic.DynamicRecipeHandler; -import net.minecraft.advancements.Advancement; -import net.minecraft.advancements.AdvancementHolder; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.data.recipes.RecipeBuilder; -import net.minecraft.data.recipes.RecipeOutput; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; import net.minecraft.util.profiling.ProfilerFiller; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.RecipeManager; -import net.minecraft.world.item.crafting.RecipeType; -import net.neoforged.neoforge.common.conditions.ICondition; -import com.google.common.collect.Multimap; +import com.google.gson.Gson; import com.google.gson.JsonElement; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.Collection; -import java.util.LinkedHashMap; import java.util.Map; @Mixin(value = RecipeManager.class, priority = 1500) -public abstract class RecipeManagerLateMixin { +public abstract class RecipeManagerLateMixin extends SimpleJsonResourceReloadListener { - @Shadow - private Multimap, RecipeHolder> byType; - - @Shadow - private Map> byName; - - @Shadow - public abstract void replaceRecipes(Iterable> recipes); + public RecipeManagerLateMixin(Gson gson, String directory) { + super(gson, directory); + } @Inject(method = "apply(Ljava/util/Map;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V", at = @At(value = "TAIL")) - private void gtceu$cloneVanillaRecipes(Map map, ResourceManager resourceManager, - ProfilerFiller profiler, CallbackInfo ci) { - // use a linked hash map to keep the immutable map's order - Map> recipesByName = new LinkedHashMap<>(byName); - // regenerate child recipes - byName.values().forEach(holder -> { - if (holder.value() instanceof GTRecipe gtRecipe) { - new GTRecipeBuilder(gtRecipe, gtRecipe.recipeType) - .id(holder.id().withPath(path -> path.substring(path.indexOf('/') + 1))) - .onSave(gtRecipe.recipeType.getRecipeBuilder().onSave) - .save(new RecipeOutput() { - - @SuppressWarnings("removal") - @Override - public Advancement.@NotNull Builder advancement() { - return Advancement.Builder.recipeAdvancement() - .parent(RecipeBuilder.ROOT_RECIPE_ADVANCEMENT); - } - - @Override - public void accept(@NotNull ResourceLocation id, @NotNull Recipe recipe, - @Nullable AdvancementHolder advancement, - ICondition @NotNull... conditions) { - recipesByName.put(id, new RecipeHolder<>(id, recipe)); - } - }); - } - }); - replaceRecipes(recipesByName.values()); - - for (RecipeType recipeType : BuiltInRegistries.RECIPE_TYPE) { - if (!(recipeType instanceof GTRecipeType gtRecipeType)) { - continue; - } - gtRecipeType.beginStagingRecipes(); - gtRecipeType.getProxyRecipes().forEach((type, list) -> { - Collection> recipes = this.byType.get(type); - if (recipes.isEmpty()) { - return; - } - RecipeManagerHandler.addProxyRecipesToLookup(recipes, gtRecipeType, type, list); - }); - Collection> recipesByID = this.byType.get(gtRecipeType); - RecipeManagerHandler.addRecipesToLookup(recipesByID, gtRecipeType); - gtRecipeType.getAdditionHandler().completeStaging(); - } - MapIngredientPool.clear(); + private void gtceu$handleDynamicRecipesLate(Map map, ResourceManager resourceManager, + ProfilerFiller profiler, CallbackInfo ci) { + DynamicRecipeHandler.handleRecipesLate((RecipeManager) (Object) this); } } diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/ReloadableServerResourcesMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/ReloadableServerResourcesMixin.java index 6df3a51520e..bba30f8e232 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/ReloadableServerResourcesMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/ReloadableServerResourcesMixin.java @@ -41,35 +41,18 @@ public abstract class ReloadableServerResourcesMixin { FeatureFlagSet featureFlags, Commands.CommandSelection commands, int functionCompilationLevel, Executor backgroundExecutor, Executor gameExecutor, CallbackInfoReturnable> cir) { - // load and loot tables recipes *before* other data so that we have the registries loaded - // before saving recipes to JSON. + // load loot tables *before* other data so we have the registries loaded before saving recipes to JSON. // because it breaks if we don't do that. // this doesn't have dynamic registries available, by the way. RegistryAccess.Frozen frozen = access.compositeAccess(); - // Register recipes & unification data again + // Register dynamic loot long startTime = System.currentTimeMillis(); - GTCraftingComponents.init(); - SteamBoilerLogic.clearBoilerRecipeCaches(); - GTRecipes.recipeAddition(new RecipeOutput() { - - @Override - public Advancement.@NotNull Builder advancement() { - // noinspection removal - return Advancement.Builder.recipeAdvancement().parent(RecipeBuilder.ROOT_RECIPE_ADVANCEMENT); - } - - @Override - public void accept(@NotNull ResourceLocation id, @NotNull Recipe recipe, - @Nullable AdvancementHolder advancement, ICondition @NotNull... conditions) { - GTDynamicDataPack.addRecipe(id, recipe, advancement, frozen); - } - }); MixinHelpers.generateGTDynamicLoot(GTDynamicDataPack::addLootTable, frozen); // Initialize dungeon loot additions DungeonLootLoader.init(); - GTCEu.LOGGER.info("GregTech Data loading took {}ms", System.currentTimeMillis() - startTime); + GTCEu.LOGGER.info("GregTech Loot table loading took {}ms", System.currentTimeMillis() - startTime); } } diff --git a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicRecipeHandler.java b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicRecipeHandler.java new file mode 100644 index 00000000000..3b598794464 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicRecipeHandler.java @@ -0,0 +1,155 @@ +package com.gregtechceu.gtceu.data.dynamic; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.api.machine.trait.customlogic.SteamBoilerLogic; +import com.gregtechceu.gtceu.api.recipe.GTRecipe; +import com.gregtechceu.gtceu.api.recipe.GTRecipeType; +import com.gregtechceu.gtceu.api.recipe.lookup.MapIngredientPool; +import com.gregtechceu.gtceu.api.recipe.lookup.RecipeManagerHandler; +import com.gregtechceu.gtceu.common.data.GTRecipes; +import com.gregtechceu.gtceu.config.ConfigHolder; +import com.gregtechceu.gtceu.data.pack.GTDynamicDataPack; +import com.gregtechceu.gtceu.data.recipe.GTCraftingComponents; +import com.gregtechceu.gtceu.data.recipe.builder.GTRecipeBuilder; + +import net.minecraft.advancements.Advancement; +import net.minecraft.advancements.AdvancementHolder; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.data.recipes.RecipeBuilder; +import net.minecraft.data.recipes.RecipeOutput; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.crafting.*; +import net.neoforged.neoforge.common.conditions.ConditionalOps; +import net.neoforged.neoforge.common.conditions.ICondition; +import net.neoforged.neoforge.common.conditions.WithConditions; + +import com.google.gson.JsonElement; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Function; +import java.util.stream.Collectors; + +@ApiStatus.Internal +public final class DynamicRecipeHandler { + + private DynamicRecipeHandler() {} + + // reload time spent in handleRecipesEarly, in milliseconds. + private static final AtomicLong earlyLoadElapsed = new AtomicLong(); + + public static void handleRecipesEarly(Map map, HolderLookup.Provider registries, + final ConditionalOps serializationContext) { + long startTime = System.currentTimeMillis(); + + // first, remove old recipes & clear caches + GTRecipes.recipeRemoval(map::remove); + SteamBoilerLogic.clearBoilerRecipeCaches(); + GTCraftingComponents.init(); + + GTRecipes.recipeAddition(new RecipeOutput() { + + @Override + public Advancement.@NotNull Builder advancement() { + // noinspection removal + return Advancement.Builder.recipeAdvancement().parent(RecipeBuilder.ROOT_RECIPE_ADVANCEMENT); + } + + @Override + public void accept(@NotNull ResourceLocation id, @NotNull Recipe recipe, + @Nullable AdvancementHolder advancement, ICondition @NotNull... conditions) { + JsonElement recipeJson = Recipe.CONDITIONAL_CODEC + .encodeStart(serializationContext, Optional.of(new WithConditions<>(recipe, conditions))) + .getOrThrow(); + map.put(id, recipeJson); + + if (ConfigHolder.INSTANCE.dev.dumpRecipes) { + // add the recipe JSON to the generated datapack if data dumping is enabled so it can be dumped + // immediately or with a command + GTDynamicDataPack.addResource(GTDynamicDataPack.RECIPE_ID_CONVERTER.idToFile(id), recipeJson); + } + + if (advancement != null) { + GTDynamicDataPack.addAdvancement(advancement, serializationContext); + } + } + }); + + earlyLoadElapsed.set(System.currentTimeMillis() - startTime); + } + + public static void handleRecipesLate(RecipeManager recipeManager) { + long startTime = System.currentTimeMillis(); + + cloneVanillaRecipes(recipeManager); + addRecipesToLookup(recipeManager); + + long elapsed = (System.currentTimeMillis() - startTime) + earlyLoadElapsed.get(); + GTCEu.LOGGER.info("GregTech Dynamic Recipe loading took {}ms", elapsed); + } + + private static void addRecipesToLookup(RecipeManager recipeManager) { + for (RecipeType t : BuiltInRegistries.RECIPE_TYPE) { + if (!(t instanceof GTRecipeType recipeType)) { + continue; + } + recipeType.beginStagingRecipes(); + + for (var entry : recipeType.getProxyRecipes().entrySet()) { + RecipeType proxyRecipeType = entry.getKey(); + Collection> recipes = recipeManager.getAllRecipesFor(proxyRecipeType); + if (recipes.isEmpty()) { + continue; + } + List> proxyRecipes = entry.getValue(); + RecipeManagerHandler.addProxyRecipesToLookup(recipes, recipeType, proxyRecipeType, proxyRecipes); + } + + Collection> recipesByID = recipeManager.getAllRecipesFor(recipeType); + RecipeManagerHandler.addRecipesToLookup(recipesByID, recipeType); + recipeType.completeStagingRecipes(); + } + MapIngredientPool.clear(); + } + + private static void cloneVanillaRecipes(RecipeManager recipeManager) { + Collection> originalRecipes = recipeManager.getRecipes(); + + // use a linked map to keep the immutable map's order + // this is a map so duplicate recipes can replace older ones easily without adding a bunch of useless entries to + // a list or set + Map> replacementRecipes = originalRecipes.stream() + .collect(Collectors.toMap(RecipeHolder::id, Function.identity(), + (oldValue, value) -> value, LinkedHashMap::new)); + + // regenerate child recipes + originalRecipes.forEach(holder -> { + if (holder.value() instanceof GTRecipe gtRecipe) { + new GTRecipeBuilder(gtRecipe, gtRecipe.recipeType) + .id(holder.id().withPath(path -> path.substring(path.indexOf('/') + 1))) + .onSave(gtRecipe.recipeType.getRecipeBuilder().onSave) + .save(new RecipeOutput() { + + @SuppressWarnings("removal") + @Override + public Advancement.@NotNull Builder advancement() { + return Advancement.Builder.recipeAdvancement() + .parent(RecipeBuilder.ROOT_RECIPE_ADVANCEMENT); + } + + @Override + public void accept(@NotNull ResourceLocation id, @NotNull Recipe recipe, + @Nullable AdvancementHolder advancement, + ICondition @NotNull... conditions) { + replacementRecipes.put(id, new RecipeHolder<>(id, recipe)); + } + }); + } + }); + recipeManager.replaceRecipes(replacementRecipes.values()); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/data/pack/GTDynamicDataPack.java b/src/main/java/com/gregtechceu/gtceu/data/pack/GTDynamicDataPack.java index 0b7246c2593..fccb873cbea 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/pack/GTDynamicDataPack.java +++ b/src/main/java/com/gregtechceu/gtceu/data/pack/GTDynamicDataPack.java @@ -2,12 +2,14 @@ import com.gregtechceu.gtceu.GTCEu; import com.gregtechceu.gtceu.api.addon.AddonFinder; +import com.gregtechceu.gtceu.api.addon.IGTAddon; import com.gregtechceu.gtceu.config.ConfigHolder; import net.minecraft.SharedConstants; import net.minecraft.advancements.Advancement; import net.minecraft.advancements.AdvancementHolder; import net.minecraft.core.HolderLookup; +import net.minecraft.data.recipes.RecipeOutput; import net.minecraft.network.chat.Component; import net.minecraft.resources.FileToIdConverter; import net.minecraft.resources.ResourceLocation; @@ -22,6 +24,7 @@ import com.google.common.collect.Sets; import com.google.gson.JsonElement; +import com.mojang.serialization.DynamicOps; import com.mojang.serialization.JsonOps; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectSet; @@ -41,7 +44,7 @@ public class GTDynamicDataPack implements PackResources { protected static final ObjectSet SERVER_DOMAINS = new ObjectOpenHashSet<>(); protected static final GTDynamicPackContents CONTENTS = new GTDynamicPackContents(); - private static final FileToIdConverter RECIPE_ID_CONVERTER = FileToIdConverter.json("recipe"); + public static final FileToIdConverter RECIPE_ID_CONVERTER = FileToIdConverter.json("recipe"); private static final FileToIdConverter LOOT_TABLE_ID_CONVERTER = FileToIdConverter.json("loot_table"); private static final FileToIdConverter ADVANCEMENT_ID_CONVERTER = FileToIdConverter.json("advancement"); @@ -80,25 +83,33 @@ public static void addResource(ResourceLocation location, byte[] data) { CONTENTS.addToData(location, data); } + /** + * @deprecated API consumers shouldn't use this method. Instead, they should implement their recipe additions in + * {@link IGTAddon#addRecipes(RecipeOutput) IGTAddon.addRecipes}. + * @see IGTAddon#addRecipes(RecipeOutput) + */ + @Deprecated(since = "8.0.0", forRemoval = true) public static void addRecipe(ResourceLocation recipeId, Recipe recipe, @Nullable AdvancementHolder advancement, HolderLookup.Provider registries) { + DynamicOps serializationContext = registries.createSerializationContext(JsonOps.INSTANCE); JsonElement recipeJson = Recipe.CODEC - .encodeStart(registries.createSerializationContext(JsonOps.INSTANCE), recipe) + .encodeStart(serializationContext, recipe) .getOrThrow(); addResource(RECIPE_ID_CONVERTER.idToFile(recipeId), recipeJson); if (advancement != null) { - addAdvancement(advancement, registries); + addAdvancement(advancement, serializationContext); } } - public static void addAdvancement(AdvancementHolder advancement, HolderLookup.Provider registries) { - addAdvancement(advancement.id(), advancement.value(), registries); + public static void addAdvancement(AdvancementHolder advancement, DynamicOps serializationContext) { + addAdvancement(advancement.id(), advancement.value(), serializationContext); } - public static void addAdvancement(ResourceLocation loc, Advancement advancement, HolderLookup.Provider registries) { + public static void addAdvancement(ResourceLocation loc, Advancement advancement, + DynamicOps serializationContext) { JsonElement advancementJson = Advancement.CODEC - .encodeStart(registries.createSerializationContext(JsonOps.INSTANCE), advancement) + .encodeStart(serializationContext, advancement) .getOrThrow(); addResource(ADVANCEMENT_ID_CONVERTER.idToFile(loc), advancementJson); } From e510d5af59592250607e7fbb4591b0e402efa704 Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Wed, 5 Aug 2026 21:20:39 +0300 Subject: [PATCH 04/19] clean up/optimize ingredient compression code slightly --- .../recipe/FluidRecipeCapability.java | 47 +++++++++---------- .../recipe/ItemRecipeCapability.java | 42 ++++++----------- .../api/recipe/lookup/StagingRecipeDB.java | 4 +- 3 files changed, 37 insertions(+), 56 deletions(-) diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/FluidRecipeCapability.java b/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/FluidRecipeCapability.java index 29e01660a6b..db5c7e6dbee 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/FluidRecipeCapability.java +++ b/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/FluidRecipeCapability.java @@ -68,42 +68,37 @@ public IntProviderFluidIngredient copyWithModifier(IntProviderFluidIngredient co @Override public List compressIngredients(@Unmodifiable Collection ingredients) { - List list = new ObjectArrayList<>(ingredients.size()); - for (Object item : ingredients) { - if (item instanceof SizedFluidIngredient fluid) { - boolean isEqual = false; + List list = new ArrayList<>(ingredients.size()); + mainLoop: + for (Object entry : ingredients) { + if (entry instanceof SizedFluidIngredient ingredient) { for (Object obj : list) { - if (obj instanceof SizedFluidIngredient SizedFluidIngredient) { - if (fluid.equals(SizedFluidIngredient)) { - isEqual = true; - break; + if (obj instanceof SizedFluidIngredient other) { + if (ingredient.equals(other)) { + continue mainLoop; } - } else if (obj instanceof FluidStack fluidStack) { - if (fluid.ingredient().test(fluidStack)) { - isEqual = true; - break; + } else if (obj instanceof FluidStack other) { + if (ingredient.ingredient().test(other)) { + continue mainLoop; } } } - if (isEqual) continue; - list.add(fluid); - } else if (item instanceof FluidStack fluidStack) { - boolean isEqual = false; + + list.add(ingredient); + } else if (entry instanceof FluidStack stack) { for (Object obj : list) { - if (obj instanceof SizedFluidIngredient fluidIngredient) { - if (fluidIngredient.ingredient().test(fluidStack)) { - isEqual = true; - break; + if (obj instanceof SizedFluidIngredient other) { + if (other.ingredient().test(stack)) { + continue mainLoop; } - } else if (obj instanceof FluidStack stack) { - if (FluidStack.isSameFluidSameComponents(fluidStack, stack)) { - isEqual = true; - break; + } else if (obj instanceof FluidStack other) { + if (FluidStack.isSameFluidSameComponents(stack, other)) { + continue mainLoop; } } } - if (isEqual) continue; - list.add(fluidStack); + + list.add(stack); } } return list; diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/ItemRecipeCapability.java b/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/ItemRecipeCapability.java index 3ffe7e8428e..3efb8c3da4e 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/ItemRecipeCapability.java +++ b/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/ItemRecipeCapability.java @@ -69,50 +69,36 @@ public IntProviderIngredient copyWithModifier(IntProviderIngredient content, Con @Override public List compressIngredients(@Unmodifiable Collection ingredients) { - List list = new ObjectArrayList<>(ingredients.size()); - for (Object item : ingredients) { - if (item instanceof SizedIngredient ingredient) { - boolean isEqual = false; + List list = new ArrayList<>(ingredients.size()); + MAIN_LOOP: + for (Object entry : ingredients) { + if (entry instanceof SizedIngredient ingredient) { for (Object obj : list) { if (obj instanceof SizedIngredient ingredient1) { if (ingredient.ingredient().equals(ingredient1.ingredient())) { - isEqual = true; - break; + continue MAIN_LOOP; } } else if (obj instanceof ItemStack stack) { if (ingredient.ingredient().test(stack)) { - isEqual = true; - break; + continue MAIN_LOOP; } } } - if (isEqual) continue; - // spotless:off - if (ingredient.getContainedCustom() instanceof IntCircuitIngredient) { - list.addFirst(ingredient); - } else if (ingredient.getContainedCustom() instanceof IntProviderIngredient intProvider && - intProvider.getInner().getCustomIngredient() instanceof IntCircuitIngredient) { - list.addFirst(ingredient); - } else { - list.add(ingredient); - } - // spotless:on - } else if (item instanceof ItemStack stack) { - boolean isEqual = false; + + list.add(ingredient); + } else if (entry instanceof ItemStack stack) { for (Object obj : list) { - if (obj instanceof Ingredient ingredient) { - if (ingredient.test(stack)) { - isEqual = true; - break; + if (obj instanceof SizedIngredient ingredient) { + if (ingredient.ingredient().test(stack)) { + continue MAIN_LOOP; } } else if (obj instanceof ItemStack stack1) { if (ItemStack.isSameItemSameComponents(stack, stack1)) { - isEqual = true; - break; + continue MAIN_LOOP; } } } - if (isEqual) continue; + list.add(stack); } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/lookup/StagingRecipeDB.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/lookup/StagingRecipeDB.java index cc8928f522e..4f282c5d73d 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/lookup/StagingRecipeDB.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/lookup/StagingRecipeDB.java @@ -68,12 +68,12 @@ public void populateDB(@NotNull RecipeDB db) { for (GTRecipe recipe : recipes) { recipe.inputs.forEach((cap, list) -> { for (var input : compressedContent(list, cap)) { - map.mergeInt(input, 1, Integer::sum); + map.addTo(input, 1); } }); recipe.tickInputs.forEach((cap, list) -> { for (var input : compressedContent(list, cap)) { - map.mergeInt(input, 1, Integer::sum); + map.addTo(input, 1); } }); } From f6306e061e0209570a37fd1077f4bf252f0b97a4 Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Wed, 5 Aug 2026 21:28:05 +0300 Subject: [PATCH 05/19] Move dynamic tag generation/loading from `MixinHelpers` to a handler class --- .../gregtechceu/gtceu/core/MixinHelpers.java | 231 --------------- .../gtceu/core/mixins/TagLoaderMixin.java | 4 +- .../gtceu/data/dynamic/DynamicTagHandler.java | 269 ++++++++++++++++++ 3 files changed, 271 insertions(+), 233 deletions(-) create mode 100644 src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java diff --git a/src/main/java/com/gregtechceu/gtceu/core/MixinHelpers.java b/src/main/java/com/gregtechceu/gtceu/core/MixinHelpers.java index 5a87016da76..ee67bcf3965 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/MixinHelpers.java +++ b/src/main/java/com/gregtechceu/gtceu/core/MixinHelpers.java @@ -1,29 +1,19 @@ package com.gregtechceu.gtceu.core; import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.api.GTValues; import com.gregtechceu.gtceu.api.data.chemical.ChemicalHelper; -import com.gregtechceu.gtceu.api.data.chemical.material.ItemMaterialData; import com.gregtechceu.gtceu.api.data.chemical.material.Material; -import com.gregtechceu.gtceu.api.data.chemical.material.properties.FluidProperty; -import com.gregtechceu.gtceu.api.data.chemical.material.properties.OreProperty; import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; import com.gregtechceu.gtceu.api.data.chemical.material.stack.MaterialStack; import com.gregtechceu.gtceu.api.data.tag.TagPrefix; import com.gregtechceu.gtceu.api.data.worldgen.GTOreDefinition; import com.gregtechceu.gtceu.api.data.worldgen.bedrockfluid.BedrockFluidDefinition; import com.gregtechceu.gtceu.api.data.worldgen.bedrockore.BedrockOreDefinition; -import com.gregtechceu.gtceu.api.fluids.FluidState; -import com.gregtechceu.gtceu.api.fluids.GTFluid; import com.gregtechceu.gtceu.api.fluids.store.FluidStorage; -import com.gregtechceu.gtceu.api.fluids.store.FluidStorageKey; import com.gregtechceu.gtceu.api.registry.GTRegistries; import com.gregtechceu.gtceu.api.registry.registrate.GTClientFluidTypeExtensions; import com.gregtechceu.gtceu.common.data.GTMaterialBlocks; -import com.gregtechceu.gtceu.common.data.GTMaterialItems; -import com.gregtechceu.gtceu.config.ConfigHolder; import com.gregtechceu.gtceu.core.mixins.BlockBehaviourAccessor; -import com.gregtechceu.gtceu.data.recipe.CustomTags; import com.gregtechceu.gtceu.integration.kjs.GTCEuServerEvents; import com.gregtechceu.gtceu.integration.kjs.events.GTBedrockFluidVeinEventJS; import com.gregtechceu.gtceu.integration.kjs.events.GTBedrockOreVeinEventJS; @@ -31,22 +21,15 @@ import net.minecraft.client.Minecraft; import net.minecraft.core.*; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.data.loot.packs.VanillaBlockLoot; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.*; -import net.minecraft.world.item.ArmorItem; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.storage.loot.IntRange; import net.minecraft.world.level.storage.loot.LootPool; import net.minecraft.world.level.storage.loot.LootTable; @@ -67,225 +50,11 @@ import java.util.*; import java.util.function.Consumer; -import java.util.function.Supplier; -import java.util.stream.Collector; -import java.util.stream.Collectors; @SuppressWarnings("deprecation") @ApiStatus.Internal public class MixinHelpers { - public static void generateGTDynamicTags(Map> tagMap, - Registry registry) { - if (registry == BuiltInRegistries.ITEM) { - ItemMaterialData.MATERIAL_ENTRY_ITEM_MAP.forEach((entry, itemLikes) -> { - if (itemLikes.isEmpty()) return; - var material = entry.material(); - if (material.isNull()) return; - var entries = itemLikes.stream() - .map(Supplier::get) - .map(MixinHelpers::makeItemEntry) - .collect(toArrayList()); - - var prefixTagKeys = entry.tagPrefix().getAllItemTags(material); - for (TagKey prefixTag : prefixTagKeys) { - tagMap.computeIfAbsent(prefixTag.location(), path -> new ArrayList<>()).addAll(entries); - } - for (TagKey materialTag : material.getItemTags()) { - tagMap.computeIfAbsent(materialTag.location(), path -> new ArrayList<>()).addAll(entries); - } - - if (entry.tagPrefix() == TagPrefix.crushed && material.hasProperty(PropertyKey.ORE)) { - OreProperty ore = material.getProperty(PropertyKey.ORE); - Material washedIn = ore.getWashedIn().first(); - if (washedIn.isNull()) return; - ResourceLocation generalTag = CustomTags.CHEM_BATH_WASHABLE.location(); - ResourceLocation specificTag = generalTag.withSuffix("/" + washedIn.getName()); - - tagMap.computeIfAbsent(generalTag, path -> new ArrayList<>()).addAll(entries); - tagMap.computeIfAbsent(specificTag, path -> new ArrayList<>()).addAll(entries); - } - }); - - GTMaterialItems.TOOL_ITEMS.rowMap().forEach((material, map) -> { - map.values().forEach(item -> { - if (item == null) return; - var entry = makeItemEntry(item); - for (TagKey tag : item.get().getToolType().itemTags) { - tagMap.computeIfAbsent(tag.location(), path -> new ArrayList<>()).add(entry); - } - }); - }); - - GTMaterialItems.ARMOR_ITEMS.rowMap().forEach((material, map) -> { - map.forEach((type, item) -> { - if (type == null || type == ArmorItem.Type.BODY) { - return; - } - if (item != null) { - var entry = new TagLoader.EntryWithSource(TagEntry.element(item.getId()), - GTValues.CUSTOM_TAG_SOURCE); - tagMap.computeIfAbsent(ItemTags.TRIMMABLE_ARMOR.location(), $ -> new ArrayList<>()) - .add(entry); - tagMap.computeIfAbsent(switch (type) { - case HELMET -> ItemTags.HEAD_ARMOR.location(); - case CHESTPLATE -> ItemTags.CHEST_ARMOR.location(); - case LEGGINGS -> ItemTags.LEG_ARMOR.location(); - case BOOTS -> ItemTags.FOOT_ARMOR.location(); - default -> throw new IllegalStateException("Unexpected value: " + type); - }, $ -> new ArrayList<>()).add(entry); - } - }); - }); - - if (!GTCEu.Mods.isAE2Loaded()) { - return; - } - // If AE2 is loaded, add the Fluid P2P attunement tag to all the buckets - var p2pFluidAttunements = ResourceLocation.fromNamespaceAndPath(GTValues.MODID_APPENG, - "p2p_attunements/fluid_p2p_tunnel"); - for (Material material : GTRegistries.MATERIALS) { - FluidProperty property = material.getProperty(PropertyKey.FLUID); - if (property == null) { - continue; - } - for (FluidStorageKey key : FluidStorageKey.allKeys()) { - Fluid fluid = property.get(key); - if (fluid == null || fluid.getBucket() == Items.AIR) { - continue; - } - var entry = makeItemEntry(fluid.getBucket()); - tagMap.computeIfAbsent(p2pFluidAttunements, path -> new ArrayList<>()).add(entry); - } - } - } else if (registry == BuiltInRegistries.BLOCK) { - ItemMaterialData.MATERIAL_ENTRY_BLOCK_MAP.forEach((entry, blocks) -> { - if (blocks.isEmpty()) return; - var material = entry.material(); - if (material.isNull()) return; - - var entries = blocks.stream().map(MixinHelpers::makeBlockEntry).collect(toArrayList()); - var materialTags = entry.tagPrefix().getAllBlockTags(material); - for (TagKey materialTag : materialTags) { - tagMap.computeIfAbsent(materialTag.location(), path -> new ArrayList<>()).addAll(entries); - } - // Add tool tags - if (!entry.isIgnored() && !entry.tagPrefix().miningToolTag().isEmpty()) { - tagMap.computeIfAbsent(CustomTags.TOOL_TIERS[material.getBlockHarvestLevel()].location(), - path -> new ArrayList<>()).addAll(entries); - if (material.hasProperty(PropertyKey.WOOD)) { - // Wood blocks with this tag always allow a Wrench, but only allow an Axe if the config is - // not set. Pickaxe is never allowed (special case) - if (entry.tagPrefix().miningToolTag() - .contains(CustomTags.MINEABLE_WITH_CONFIG_VALID_PICKAXE_WRENCH)) { - tagMap.computeIfAbsent(CustomTags.MINEABLE_WITH_WRENCH.location(), - path -> new ArrayList<>()).addAll(entries); - if (!ConfigHolder.INSTANCE.machines.requireGTToolsForBlocks) { - tagMap.computeIfAbsent(BlockTags.MINEABLE_WITH_AXE.location(), - path -> new ArrayList<>()) - .addAll(entries); - } - } else { - // Other wood stuff should still get the Axe tag - tagMap.computeIfAbsent(BlockTags.MINEABLE_WITH_AXE.location(), path -> new ArrayList<>()) - .addAll(entries); - } - } else { - for (var tag : entry.tagPrefix().miningToolTag()) { - tagMap.computeIfAbsent(tag.location(), path -> new ArrayList<>()).addAll(entries); - } - } - } - - if (entry.tagPrefix() == TagPrefix.oreEndstone) { - // Make endstone-based ores dragon-immune - tagMap.computeIfAbsent(BlockTags.DRAGON_IMMUNE.location(), $ -> new ArrayList<>()).addAll(entries); - } - - if (entry.tagPrefix() == TagPrefix.frameGt) { - tagMap.computeIfAbsent(CustomTags.SLOW_WALKABLE_BLOCKS.location(), path -> new ArrayList<>()) - .addAll(entries); - } - }); - - GTRegistries.MACHINES.forEach(machine -> { - tagMap.computeIfAbsent(CustomTags.MINEABLE_WITH_CONFIG_VALID_PICKAXE_WRENCH.location(), - path -> new ArrayList<>()).add(makeBlockEntry(machine.getBlock())); - }); - - // if config is NOT enabled, add the "configurable" mineability tags to the pickaxe tag - if (!ConfigHolder.INSTANCE.machines.requireGTToolsForBlocks) { - var tagList = tagMap.computeIfAbsent(BlockTags.MINEABLE_WITH_PICKAXE.location(), - path -> new ArrayList<>()); - - tagList.add(makeTagEntry(CustomTags.MINEABLE_WITH_CONFIG_VALID_PICKAXE_WRENCH)); - tagList.add(makeTagEntry(CustomTags.MINEABLE_WITH_CONFIG_VALID_PICKAXE_WIRE_CUTTER)); - } - } else if (registry == BuiltInRegistries.FLUID) { - for (Material material : GTRegistries.MATERIALS) { - FluidProperty property = material.getProperty(PropertyKey.FLUID); - if (property == null) { - continue; - } - for (FluidStorageKey key : FluidStorageKey.allKeys()) { - Fluid fluid = property.get(key); - if (fluid == null) { - continue; - } - ItemMaterialData.FLUID_MATERIAL.put(fluid, material); - - TagLoader.EntryWithSource entry = makeFluidEntry(fluid); - - ResourceLocation fluidIdTag = fluid.builtInRegistryHolder().key().location(); - fluidIdTag = ResourceLocation.fromNamespaceAndPath("c", fluidIdTag.getPath()); - tagMap.computeIfAbsent(fluidIdTag, path -> new ArrayList<>()).add(entry); - - FluidState state; - if (fluid instanceof GTFluid gtFluid) { - state = gtFluid.getState(); - } else { - state = key.getDefaultFluidState(); - } - if (state != null) { - tagMap.computeIfAbsent(state.getTagKey().location(), path -> new ArrayList<>()).add(entry); - } - - if (key.getExtraTag() != null) { - tagMap.computeIfAbsent(key.getExtraTag().location(), path -> new ArrayList<>()).add(entry); - } - } - } - } - } - - private static Collector> toArrayList() { - return Collectors.toCollection(ArrayList::new); - } - - public static TagLoader.EntryWithSource makeItemEntry(ItemLike item) { - return makeElementEntry(item.asItem().builtInRegistryHolder().key().location()); - } - - public static TagLoader.EntryWithSource makeBlockEntry(Supplier block) { - return makeBlockEntry(block.get()); - } - - public static TagLoader.EntryWithSource makeBlockEntry(Block block) { - return makeElementEntry(block.builtInRegistryHolder().key().location()); - } - - public static TagLoader.EntryWithSource makeFluidEntry(Fluid fluid) { - return makeElementEntry(fluid.builtInRegistryHolder().key().location()); - } - - public static TagLoader.EntryWithSource makeElementEntry(ResourceLocation id) { - return new TagLoader.EntryWithSource(TagEntry.element(id), GTValues.CUSTOM_TAG_SOURCE); - } - - public static TagLoader.EntryWithSource makeTagEntry(TagKey tag) { - return new TagLoader.EntryWithSource(TagEntry.tag(tag.location()), GTValues.CUSTOM_TAG_SOURCE); - } - public static void generateGTDynamicLoot(TriConsumer lootTables, final RegistryAccess.Frozen access) { final VanillaBlockLoot blockLoot = new VanillaBlockLoot(access); diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/TagLoaderMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/TagLoaderMixin.java index 062af0de349..17eec8f6139 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/TagLoaderMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/TagLoaderMixin.java @@ -1,7 +1,7 @@ package com.gregtechceu.gtceu.core.mixins; import com.gregtechceu.gtceu.core.IGTTagLoader; -import com.gregtechceu.gtceu.core.MixinHelpers; +import com.gregtechceu.gtceu.data.dynamic.DynamicTagHandler; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceLocation; @@ -29,7 +29,7 @@ public class TagLoaderMixin implements IGTTagLoader { public void gtceu$load(ResourceManager resourceManager, CallbackInfoReturnable>> cir) { if (gtceu$storedRegistry == null) return; - MixinHelpers.generateGTDynamicTags(cir.getReturnValue(), gtceu$storedRegistry); + DynamicTagHandler.generateGTDynamicTags(cir.getReturnValue(), gtceu$storedRegistry); } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java new file mode 100644 index 00000000000..6cdca5540ef --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java @@ -0,0 +1,269 @@ +package com.gregtechceu.gtceu.data.dynamic; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.api.GTValues; +import com.gregtechceu.gtceu.api.data.chemical.material.ItemMaterialData; +import com.gregtechceu.gtceu.api.data.chemical.material.Material; +import com.gregtechceu.gtceu.api.data.chemical.material.properties.FluidProperty; +import com.gregtechceu.gtceu.api.data.chemical.material.properties.OreProperty; +import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; +import com.gregtechceu.gtceu.api.data.tag.TagPrefix; +import com.gregtechceu.gtceu.api.fluids.FluidState; +import com.gregtechceu.gtceu.api.fluids.GTFluid; +import com.gregtechceu.gtceu.api.fluids.store.FluidStorageKey; +import com.gregtechceu.gtceu.api.registry.GTRegistries; +import com.gregtechceu.gtceu.common.data.GTMaterialItems; +import com.gregtechceu.gtceu.config.ConfigHolder; +import com.gregtechceu.gtceu.data.recipe.CustomTags; + +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.*; +import net.minecraft.world.item.ArmorItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.material.Fluid; + +import org.jetbrains.annotations.ApiStatus; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import java.util.stream.Collector; +import java.util.stream.Collectors; + +@SuppressWarnings("deprecation") +@ApiStatus.Internal +public final class DynamicTagHandler { + + private DynamicTagHandler() {} + + public static void generateGTDynamicTags(Map> parsedTags, + Registry registry) { + if (registry == BuiltInRegistries.ITEM) { + generateItemTags(parsedTags); + } else if (registry == BuiltInRegistries.BLOCK) { + generateBlockTags(parsedTags); + } else if (registry == BuiltInRegistries.FLUID) { + generateFluidTags(parsedTags); + } + } + + private static void generateItemTags(Map> tags) { + ItemMaterialData.MATERIAL_ENTRY_ITEM_MAP.forEach((entry, itemLikes) -> { + if (itemLikes.isEmpty()) return; + Material material = entry.material(); + if (material.isNull()) return; + var entries = itemLikes.stream() + .map(Supplier::get) + .map(DynamicTagHandler::makeItemEntry) + .collect(toArrayList()); + + var prefixTagKeys = entry.tagPrefix().getAllItemTags(material); + for (TagKey prefixTag : prefixTagKeys) { + tags.computeIfAbsent(prefixTag.location(), path -> new ArrayList<>()).addAll(entries); + } + for (TagKey materialTag : material.getItemTags()) { + tags.computeIfAbsent(materialTag.location(), path -> new ArrayList<>()).addAll(entries); + } + + if (entry.tagPrefix() == TagPrefix.crushed && material.hasProperty(PropertyKey.ORE)) { + OreProperty ore = material.getProperty(PropertyKey.ORE); + Material washedIn = ore.getWashedIn().first(); + if (washedIn.isNull()) return; + ResourceLocation generalTag = CustomTags.CHEM_BATH_WASHABLE.location(); + ResourceLocation specificTag = generalTag.withSuffix("/" + washedIn.getName()); + + tags.computeIfAbsent(generalTag, path -> new ArrayList<>()).addAll(entries); + tags.computeIfAbsent(specificTag, path -> new ArrayList<>()).addAll(entries); + } + }); + + GTMaterialItems.TOOL_ITEMS.rowMap().forEach((material, map) -> { + map.values().forEach(item -> { + if (item == null) return; + var entry = makeItemEntry(item); + for (TagKey tag : item.get().getToolType().itemTags) { + tags.computeIfAbsent(tag.location(), path -> new ArrayList<>()).add(entry); + } + }); + }); + + GTMaterialItems.ARMOR_ITEMS.rowMap().forEach((material, map) -> { + map.forEach((type, item) -> { + if (type == null || type == ArmorItem.Type.BODY) { + return; + } + if (item != null) { + var entry = new TagLoader.EntryWithSource(TagEntry.element(item.getId()), + GTValues.CUSTOM_TAG_SOURCE); + tags.computeIfAbsent(ItemTags.TRIMMABLE_ARMOR.location(), $ -> new ArrayList<>()) + .add(entry); + tags.computeIfAbsent(switch (type) { + case HELMET -> ItemTags.HEAD_ARMOR.location(); + case CHESTPLATE -> ItemTags.CHEST_ARMOR.location(); + case LEGGINGS -> ItemTags.LEG_ARMOR.location(); + case BOOTS -> ItemTags.FOOT_ARMOR.location(); + default -> throw new IllegalStateException("Unexpected value: " + type); + }, $ -> new ArrayList<>()).add(entry); + } + }); + }); + + if (GTCEu.Mods.isAE2Loaded()) { + // If AE2 is loaded, add the Fluid P2P attunement tag to all the buckets + ResourceLocation p2pFluidAttunementsTag = ResourceLocation.fromNamespaceAndPath(GTValues.MODID_APPENG, + "p2p_attunements/fluid_p2p_tunnel"); + for (Material material : GTRegistries.MATERIALS) { + FluidProperty property = material.getProperty(PropertyKey.FLUID); + if (property == null) { + continue; + } + for (FluidStorageKey key : FluidStorageKey.allKeys()) { + Fluid fluid = property.get(key); + if (fluid == null || fluid.getBucket() == Items.AIR) { + continue; + } + var entry = makeItemEntry(fluid.getBucket()); + tags.computeIfAbsent(p2pFluidAttunementsTag, path -> new ArrayList<>()).add(entry); + } + } + } + } + + private static void generateBlockTags(Map> tags) { + ItemMaterialData.MATERIAL_ENTRY_BLOCK_MAP.forEach((entry, blocks) -> { + if (blocks.isEmpty()) return; + Material material = entry.material(); + if (material.isNull()) return; + var entries = blocks.stream() + .map(DynamicTagHandler::makeBlockEntry) + .collect(toArrayList()); + + var prefixTagKeys = entry.tagPrefix().getAllBlockTags(material); + for (TagKey prefixTag : prefixTagKeys) { + tags.computeIfAbsent(prefixTag.location(), path -> new ArrayList<>()).addAll(entries); + } + + // Add mineability tags + if (!entry.isIgnored() && !entry.tagPrefix().miningToolTag().isEmpty()) { + tags.computeIfAbsent(CustomTags.TOOL_TIERS[material.getBlockHarvestLevel()].location(), + path -> new ArrayList<>()).addAll(entries); + if (material.hasProperty(PropertyKey.WOOD)) { + // Wood blocks with this tag always allow a Wrench, but only allow an Axe if the config is + // not set. Pickaxe is never allowed (special case) + if (entry.tagPrefix().miningToolTag() + .contains(CustomTags.MINEABLE_WITH_CONFIG_VALID_PICKAXE_WRENCH)) { + tags.computeIfAbsent(CustomTags.MINEABLE_WITH_WRENCH.location(), + path -> new ArrayList<>()).addAll(entries); + if (!ConfigHolder.INSTANCE.machines.requireGTToolsForBlocks) { + tags.computeIfAbsent(BlockTags.MINEABLE_WITH_AXE.location(), + path -> new ArrayList<>()) + .addAll(entries); + } + } else { + // Other wood stuff should still get the Axe tag + tags.computeIfAbsent(BlockTags.MINEABLE_WITH_AXE.location(), path -> new ArrayList<>()) + .addAll(entries); + } + } else { + for (var tag : entry.tagPrefix().miningToolTag()) { + tags.computeIfAbsent(tag.location(), path -> new ArrayList<>()).addAll(entries); + } + } + } + + if (entry.tagPrefix() == TagPrefix.oreEndstone) { + // Make endstone-based ores dragon-immune + tags.computeIfAbsent(BlockTags.DRAGON_IMMUNE.location(), $ -> new ArrayList<>()).addAll(entries); + } + + if (entry.tagPrefix() == TagPrefix.frameGt) { + tags.computeIfAbsent(CustomTags.SLOW_WALKABLE_BLOCKS.location(), path -> new ArrayList<>()) + .addAll(entries); + } + }); + + GTRegistries.MACHINES.forEach(machine -> { + tags.computeIfAbsent(CustomTags.MINEABLE_WITH_CONFIG_VALID_PICKAXE_WRENCH.location(), + path -> new ArrayList<>()).add(makeBlockEntry(machine.getBlock())); + }); + + // if config is NOT enabled, add the "configurable" mineability tags to the pickaxe tag + if (!ConfigHolder.INSTANCE.machines.requireGTToolsForBlocks) { + var tagList = tags.computeIfAbsent(BlockTags.MINEABLE_WITH_PICKAXE.location(), + path -> new ArrayList<>()); + + tagList.add(makeTagEntry(CustomTags.MINEABLE_WITH_CONFIG_VALID_PICKAXE_WRENCH)); + tagList.add(makeTagEntry(CustomTags.MINEABLE_WITH_CONFIG_VALID_PICKAXE_WIRE_CUTTER)); + } + } + + private static void generateFluidTags(Map> tags) { + for (Material material : GTRegistries.MATERIALS) { + FluidProperty property = material.getProperty(PropertyKey.FLUID); + if (property == null) { + continue; + } + for (FluidStorageKey key : FluidStorageKey.allKeys()) { + Fluid fluid = property.get(key); + if (fluid == null) { + continue; + } + ItemMaterialData.FLUID_MATERIAL.put(fluid, material); + + TagLoader.EntryWithSource entry = makeFluidEntry(fluid); + + ResourceLocation fluidIdTag = fluid.builtInRegistryHolder().key().location(); + fluidIdTag = ResourceLocation.fromNamespaceAndPath("c", fluidIdTag.getPath()); + tags.computeIfAbsent(fluidIdTag, path -> new ArrayList<>()).add(entry); + + FluidState state; + if (fluid instanceof GTFluid gtFluid) { + state = gtFluid.getState(); + } else { + state = key.getDefaultFluidState(); + } + if (state != null) { + tags.computeIfAbsent(state.getTagKey().location(), path -> new ArrayList<>()).add(entry); + } + + if (key.getExtraTag() != null) { + tags.computeIfAbsent(key.getExtraTag().location(), path -> new ArrayList<>()).add(entry); + } + } + } + } + + private static Collector> toArrayList() { + return Collectors.toCollection(ArrayList::new); + } + + private static TagLoader.EntryWithSource makeItemEntry(ItemLike item) { + return makeElementEntry(item.asItem().builtInRegistryHolder().key().location()); + } + + private static TagLoader.EntryWithSource makeBlockEntry(Supplier block) { + return makeBlockEntry(block.get()); + } + + private static TagLoader.EntryWithSource makeBlockEntry(Block block) { + return makeElementEntry(block.builtInRegistryHolder().key().location()); + } + + private static TagLoader.EntryWithSource makeFluidEntry(Fluid fluid) { + return makeElementEntry(fluid.builtInRegistryHolder().key().location()); + } + + private static TagLoader.EntryWithSource makeElementEntry(ResourceLocation id) { + return new TagLoader.EntryWithSource(TagEntry.element(id), GTValues.CUSTOM_TAG_SOURCE); + } + + private static TagLoader.EntryWithSource makeTagEntry(TagKey tag) { + return new TagLoader.EntryWithSource(TagEntry.tag(tag.location()), GTValues.CUSTOM_TAG_SOURCE); + } +} From d7d3cabbccfd4345bf5dd506c633108d0d6b89e3 Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Wed, 5 Aug 2026 21:30:22 +0300 Subject: [PATCH 06/19] Somewhat rewrite how TagType works internally it's an internal class, so this is fine! --- .../gtceu/api/data/tag/TagType.java | 55 +++++++++---------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagType.java b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagType.java index 7d14384c0db..866600226a6 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagType.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagType.java @@ -8,35 +8,33 @@ import net.minecraft.world.item.Item; import lombok.Getter; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.function.BiFunction; import java.util.function.Predicate; -public class TagType { +@ApiStatus.Internal +public final class TagType { - private final String tagPath; @Getter private boolean isParentTag = false; // this is now memoized because creating tag keys interns them and that's slow - private BiFunction> formatter; - private Predicate filter; + private final @NotNull BiFunction> formatter; + private @Nullable Predicate filter; - private TagType(String tagPath) { - this.tagPath = tagPath; + private TagType(BiFunction> formatter) { + this.formatter = Util.memoize(formatter); } - // formatter:off + // spotless:off /** * Create a tag with a specified path, with the "default" formatter, meaning * that there is 1 "%s" format character in the path, intended for the Material name. */ public static TagType withDefaultFormatter(String tagPath, boolean isVanilla) { - TagType type = new TagType(tagPath); - type.formatter = Util - .memoize((prefix, mat) -> TagUtil.createItemTag(type.tagPath.formatted(mat.getName()), isVanilla)); - return type; + return new TagType((prefix, mat) -> TagUtil.createItemTag(tagPath.formatted(mat.getName()), isVanilla)); } /** @@ -45,10 +43,7 @@ public static TagType withDefaultFormatter(String tagPath, boolean isVanilla) { * prefix name, and the second being the material name. */ public static TagType withPrefixFormatter(String tagPath) { - TagType type = new TagType(tagPath); - type.formatter = Util.memoize((prefix, mat) -> TagUtil.createItemTag( - type.tagPath.formatted(prefix.name, mat.getName()))); - return type; + return new TagType((prefix, mat) -> TagUtil.createItemTag(tagPath.formatted(prefix.name, mat.getName()))); } /** @@ -56,37 +51,37 @@ public static TagType withPrefixFormatter(String tagPath) { * that there is 1 "%s" format character in the path, intended for the prefix name. */ public static TagType withPrefixOnlyFormatter(String tagPath) { - TagType type = new TagType(tagPath); - type.formatter = Util.memoize((prefix, mat) -> TagUtil - .createItemTag(type.tagPath.formatted(prefix.name))); + TagType type = new TagType((prefix, mat) -> TagUtil.createItemTag(tagPath.formatted(prefix.name))); type.isParentTag = true; return type; } public static TagType withNoFormatter(String tagPath, boolean isVanilla) { - TagType type = new TagType(tagPath); - type.formatter = Util.memoize((prefix, material) -> TagUtil.createItemTag(type.tagPath, isVanilla)); + TagType type = new TagType((prefix, material) -> TagUtil.createItemTag(tagPath, isVanilla)); type.isParentTag = true; return type; } - public static TagType withCustomFormatter(String tagPath, BiFunction> formatter) { - TagType type = new TagType(tagPath); - type.formatter = Util.memoize(formatter); + public static TagType withCustomFormatter(BiFunction> formatter) { + return new TagType(formatter); + } + + public static TagType filteredCustomFormatter(Predicate filter, + BiFunction> formatter) { + TagType type = new TagType(formatter); + type.filter = filter; return type; } - public static TagType withCustomFilter(String tagPath, boolean isVanilla, Predicate filter) { - TagType type = new TagType(tagPath); + public static TagType filteredNoFormatter(String tagPath, boolean isVanilla, Predicate filter) { + TagType type = new TagType((prefix, material) -> TagUtil.createItemTag(tagPath, isVanilla)); type.filter = filter; - type.formatter = Util.memoize((prefix, material) -> TagUtil.createItemTag(type.tagPath, isVanilla)); return type; } // spotless:on - @Nullable - public TagKey getTag(TagPrefix prefix, @NotNull Material material) { - if (filter != null && !material.isNull() && !filter.test(material)) return null; - return formatter.apply(prefix, material); + public @Nullable TagKey getTag(TagPrefix prefix, @NotNull Material material) { + if (this.filter != null && !material.isNull() && !this.filter.test(material)) return null; + return this.formatter.apply(prefix, material); } } From bea12aeff8a70c58550239796516ccf598a53ac8 Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Wed, 5 Aug 2026 21:30:43 +0300 Subject: [PATCH 07/19] Add back the `chemical_bath_washable/*` tags but make them less special casey this time --- .../gtceu/api/data/tag/TagPrefix.java | 25 +++++++++++++++++++ .../kjs/builders/prefix/TagPrefixBuilder.java | 11 ++++++++ 2 files changed, 36 insertions(+) diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java index ef2a896100f..7183027e811 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java @@ -23,6 +23,7 @@ import com.gregtechceu.gtceu.data.recipe.CustomTags; import com.gregtechceu.gtceu.integration.recipeviewer.widgets.GTOreByProduct; import com.gregtechceu.gtceu.utils.FormattingUtil; +import com.gregtechceu.gtceu.utils.TagUtil; import com.gregtechceu.gtceu.utils.memoization.GTMemoizer; import net.minecraft.client.renderer.RenderType; @@ -239,6 +240,19 @@ public boolean isEmpty() { .idPattern("crushed_%s_ore") .defaultTagPath("crushed_ores/%s") .unformattedTagPath("crushed_ores") + .filteredCustomTag("chemical_bath_washable/%s", mat -> { + if (!mat.hasProperty(PropertyKey.ORE)) return false; + Material washedIn = mat.getProperty(PropertyKey.ORE).getWashedIn().first(); + return !washedIn.isNull(); + }, (path, mat) -> { + Material washedIn = mat.getProperty(PropertyKey.ORE).getWashedIn().first(); + return TagUtil.createItemTag(path.formatted(washedIn.getName())); + }) + .filteredUnformattedTag("chemical_bath_washable", false, mat -> { + if (!mat.hasProperty(PropertyKey.ORE)) return false; + Material washedIn = mat.getProperty(PropertyKey.ORE).getWashedIn().first(); + return !washedIn.isNull(); + }) .langValue("Crushed %s Ore") .materialIconType(MaterialIconType.crushed) .unificationEnabled(true) @@ -1160,6 +1174,17 @@ public TagPrefix customTagPredicate(String path, boolean isVanilla, Predicate materialPredicate) { + this.tags.add(TagType.filteredNoFormatter(path, isVanilla, materialPredicate)); + return this; + } + + public TagPrefix filteredCustomTag(String path, Predicate materialPredicate, + BiFunction> formatter) { + this.tags.add(TagType.filteredCustomFormatter(materialPredicate, (self, mat) -> formatter.apply(path, mat))); + return this; + } + public TagPrefix miningToolTag(TagKey tag) { this.miningToolTag.add(tag); return this; diff --git a/src/main/java/com/gregtechceu/gtceu/integration/kjs/builders/prefix/TagPrefixBuilder.java b/src/main/java/com/gregtechceu/gtceu/integration/kjs/builders/prefix/TagPrefixBuilder.java index a51af258ec0..e984f6f0964 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/kjs/builders/prefix/TagPrefixBuilder.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/kjs/builders/prefix/TagPrefixBuilder.java @@ -151,6 +151,17 @@ public TagPrefixBuilder customTagPredicate(String path, boolean isVanilla, Predi return this; } + public TagPrefixBuilder filteredUnformattedTag(String path, boolean isVanilla, Predicate materialPredicate) { + base.filteredUnformattedTag(path, isVanilla, materialPredicate); + return this; + } + + public TagPrefixBuilder filteredCustomTag(String path, Predicate materialPredicate, + BiFunction> formatter) { + base.filteredCustomTag(path, materialPredicate, formatter); + return this; + } + public TagPrefixBuilder miningToolTag(TagKey tag) { base.miningToolTag(tag); return this; From a7622fc98746e700da7f37c23465a04863623b86 Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Wed, 5 Aug 2026 21:32:03 +0300 Subject: [PATCH 08/19] fix stone blocks' tags (e.g. `#c:stones`) not being plural on 1.21, causing a warning to be logged --- .../java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java index 7183027e811..e4ae20626a5 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java @@ -218,7 +218,7 @@ public boolean isEmpty() { public static final TagPrefix crushedRefined = new TagPrefix(GTCEu.id("refined_ore")) .idPattern("refined_%s_ore") .defaultTagPath("refined_ores/%s") - .defaultTagPath("refined_ores") + .unformattedTagPath("refined_ores") .langValue("Refined %s Ore") .materialIconType(MaterialIconType.crushedRefined) .unificationEnabled(true) @@ -228,7 +228,7 @@ public boolean isEmpty() { public static final TagPrefix crushedPurified = new TagPrefix(GTCEu.id("purified_ore")) .idPattern("purified_%s_ore") .defaultTagPath("purified_ores/%s") - .defaultTagPath("purified_ores") + .unformattedTagPath("purified_ores") .customTagPredicate("siftables", false, m -> m.hasProperty(PropertyKey.GEM)) .langValue("Purified %s Ore") .materialIconType(MaterialIconType.crushedPurified) @@ -755,7 +755,8 @@ public boolean isEmpty() { // Prefix to determine which kind of Rock this is. // Also has a base tag path of only the material, for things like obsidian etc. public static final TagPrefix rock = new TagPrefix(GTCEu.id("rock")) - .defaultTagPath("%s") + // the 2nd 's' makes the tag plural, which is what Common tags are expected to be. + .defaultTagPath("%ss") .langValue("%s") .miningToolTag(BlockTags.MINEABLE_WITH_PICKAXE) .unificationEnabled(false) From dc436f3f19ceb8489b70f214b549ebde271ab20a Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Wed, 5 Aug 2026 21:45:23 +0300 Subject: [PATCH 09/19] Rename TagPrefix's tag addition methods and add `@Deprecated(forRemoval = true)` on the old ones --- .../gtceu/api/data/tag/TagPrefix.java | 288 ++++++++++++------ .../builders/prefix/OreTagPrefixBuilder.java | 6 +- .../kjs/builders/prefix/TagPrefixBuilder.java | 59 +++- 3 files changed, 250 insertions(+), 103 deletions(-) diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java index e4ae20626a5..a369558be27 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java @@ -196,8 +196,8 @@ public boolean isEmpty() { public static final TagPrefix rawOre = new TagPrefix(GTCEu.id("raw"), true) .idPattern("raw_%s") - .defaultTagPath("raw_materials/%s") - .unformattedTagPath("raw_materials") + .defaultTag("raw_materials/%s") + .unformattedTag("raw_materials") .langValue("Raw %s") .materialIconType(MaterialIconType.rawOre) .unificationEnabled(true) @@ -206,8 +206,8 @@ public boolean isEmpty() { public static final TagPrefix rawOreBlock = new TagPrefix(GTCEu.id("raw_ore_block")) .idPattern("raw_%s_block") - .defaultTagPath("storage_blocks/raw_%s") - .unformattedTagPath("storage_blocks") + .defaultTag("storage_blocks/raw_%s") + .unformattedTag("storage_blocks") .langValue("Block of Raw %s") .materialIconType(MaterialIconType.rawOreBlock) .miningToolTag(BlockTags.MINEABLE_WITH_PICKAXE) @@ -217,8 +217,8 @@ public boolean isEmpty() { public static final TagPrefix crushedRefined = new TagPrefix(GTCEu.id("refined_ore")) .idPattern("refined_%s_ore") - .defaultTagPath("refined_ores/%s") - .unformattedTagPath("refined_ores") + .defaultTag("refined_ores/%s") + .unformattedTag("refined_ores") .langValue("Refined %s Ore") .materialIconType(MaterialIconType.crushedRefined) .unificationEnabled(true) @@ -227,8 +227,8 @@ public boolean isEmpty() { public static final TagPrefix crushedPurified = new TagPrefix(GTCEu.id("purified_ore")) .idPattern("purified_%s_ore") - .defaultTagPath("purified_ores/%s") - .unformattedTagPath("purified_ores") + .defaultTag("purified_ores/%s") + .unformattedTag("purified_ores") .customTagPredicate("siftables", false, m -> m.hasProperty(PropertyKey.GEM)) .langValue("Purified %s Ore") .materialIconType(MaterialIconType.crushedPurified) @@ -238,8 +238,8 @@ public boolean isEmpty() { public static final TagPrefix crushed = new TagPrefix(GTCEu.id("crushed_ore")) .idPattern("crushed_%s_ore") - .defaultTagPath("crushed_ores/%s") - .unformattedTagPath("crushed_ores") + .defaultTag("crushed_ores/%s") + .unformattedTag("crushed_ores") .filteredCustomTag("chemical_bath_washable/%s", mat -> { if (!mat.hasProperty(PropertyKey.ORE)) return false; Material washedIn = mat.getProperty(PropertyKey.ORE).getWashedIn().first(); @@ -263,8 +263,8 @@ public boolean isEmpty() { // A hot Ingot, which has to be cooled down by a Vacuum Freezer. public static final TagPrefix ingotHot = new TagPrefix(GTCEu.id("hot_ingot")) .idPattern("hot_%s_ingot") - .defaultTagPath("hot_ingots/%s") - .unformattedTagPath("hot_ingots") + .defaultTag("hot_ingots/%s") + .unformattedTag("hot_ingots") .langValue("Hot %s Ingot") .materialAmount(GTValues.M) .materialIconType(MaterialIconType.ingotHot) @@ -275,8 +275,8 @@ public boolean isEmpty() { // A regular Ingot. public static final TagPrefix ingot = new TagPrefix(GTCEu.id("ingot")) - .defaultTagPath("ingots/%s") - .unformattedTagPath("ingots") + .defaultTag("ingots/%s") + .unformattedTag("ingots") .materialAmount(GTValues.M) .materialIconType(MaterialIconType.ingot) .unificationEnabled(true) @@ -286,8 +286,8 @@ public boolean isEmpty() { // A regular Gem worth one Dust. public static final TagPrefix gem = new TagPrefix(GTCEu.id("gem")) - .defaultTagPath("gems/%s") - .unformattedTagPath("gems") + .defaultTag("gems/%s") + .unformattedTag("gems") .langValue("%s") .materialAmount(GTValues.M) .materialIconType(MaterialIconType.gem) @@ -299,8 +299,8 @@ public boolean isEmpty() { // A regular Gem worth one small Dust. public static final TagPrefix gemChipped = new TagPrefix(GTCEu.id("chipped_gem")) .idPattern("chipped_%s_gem") - .defaultTagPath("chipped_gems/%s") - .unformattedTagPath("chipped_gems") + .defaultTag("chipped_gems/%s") + .unformattedTag("chipped_gems") .langValue("Chipped %s") .materialAmount(GTValues.M / 4) .materialIconType(MaterialIconType.gemChipped) @@ -312,8 +312,8 @@ public boolean isEmpty() { // A regular Gem worth two small Dusts. public static final TagPrefix gemFlawed = new TagPrefix(GTCEu.id("flawed_gem")) .idPattern("flawed_%s_gem") - .defaultTagPath("flawed_gems/%s") - .unformattedTagPath("flawed_gems") + .defaultTag("flawed_gems/%s") + .unformattedTag("flawed_gems") .langValue("Flawed %s") .materialAmount(GTValues.M / 2) .materialIconType(MaterialIconType.gemFlawed) @@ -325,8 +325,8 @@ public boolean isEmpty() { // A regular Gem worth two Dusts. public static final TagPrefix gemFlawless = new TagPrefix(GTCEu.id("flawless_gem")) .idPattern("flawless_%s_gem") - .defaultTagPath("flawless_gems/%s") - .unformattedTagPath("flawless_gems") + .defaultTag("flawless_gems/%s") + .unformattedTag("flawless_gems") .langValue("Flawless %s") .materialAmount(GTValues.M * 2) .maxStackSize(32) @@ -339,8 +339,8 @@ public boolean isEmpty() { // A regular Gem worth four Dusts. public static final TagPrefix gemExquisite = new TagPrefix(GTCEu.id("exquisite_gem")) .idPattern("exquisite_%s_gem") - .defaultTagPath("exquisite_gems/%s") - .unformattedTagPath("exquisite_gems") + .defaultTag("exquisite_gems/%s") + .unformattedTag("exquisite_gems") .langValue("Exquisite %s") .materialAmount(GTValues.M * 4) .maxStackSize(16) @@ -353,8 +353,8 @@ public boolean isEmpty() { // 1/4th of a Dust. public static final TagPrefix dustSmall = new TagPrefix(GTCEu.id("small_dust")) .idPattern("small_%s_dust") - .defaultTagPath("small_dusts/%s") - .unformattedTagPath("small_dusts") + .defaultTag("small_dusts/%s") + .unformattedTag("small_dusts") .langValue("Small Pile of %s Dust") .materialAmount(GTValues.M / 4) .materialIconType(MaterialIconType.dustSmall) @@ -365,8 +365,8 @@ public boolean isEmpty() { // 1/9th of a Dust. public static final TagPrefix dustTiny = new TagPrefix(GTCEu.id("tiny_dust")) .idPattern("tiny_%s_dust") - .defaultTagPath("tiny_dusts/%s") - .unformattedTagPath("tiny_dusts") + .defaultTag("tiny_dusts/%s") + .unformattedTag("tiny_dusts") .langValue("Tiny Pile of %s Dust") .materialAmount(GTValues.M / 9) .materialIconType(MaterialIconType.dustTiny) @@ -377,8 +377,8 @@ public boolean isEmpty() { // Dust with impurities. 1 Unit of Main Material and 1/9 - 1/4 Unit of secondary Material public static final TagPrefix dustImpure = new TagPrefix(GTCEu.id("impure_dust")) .idPattern("impure_%s_dust") - .defaultTagPath("impure_dusts/%s") - .unformattedTagPath("impure_dusts") + .defaultTag("impure_dusts/%s") + .unformattedTag("impure_dusts") .langValue("Impure Pile of %s Dust") .materialAmount(GTValues.M) .materialIconType(MaterialIconType.dustImpure) @@ -390,8 +390,8 @@ public boolean isEmpty() { // Pure Dust worth of one Ingot or Gem. public static final TagPrefix dustPure = new TagPrefix(GTCEu.id("pure_dust")) .idPattern("pure_%s_dust") - .defaultTagPath("pure_dusts/%s") - .unformattedTagPath("pure_dusts") + .defaultTag("pure_dusts/%s") + .unformattedTag("pure_dusts") .langValue("Purified Pile of %s Dust") .materialAmount(GTValues.M) .materialIconType(MaterialIconType.dustPure) @@ -401,8 +401,8 @@ public boolean isEmpty() { .tooltip((mat, tooltips) -> tooltips.add(Component.translatable("metaitem.dust.tooltip.purify"))); public static final TagPrefix dust = new TagPrefix(GTCEu.id("dust")) - .defaultTagPath("dusts/%s") - .unformattedTagPath("dusts") + .defaultTag("dusts/%s") + .unformattedTag("dusts") .materialAmount(GTValues.M) .materialIconType(MaterialIconType.dust) .unificationEnabled(true) @@ -412,8 +412,8 @@ public boolean isEmpty() { // A Nugget. public static final TagPrefix nugget = new TagPrefix(GTCEu.id("nugget")) - .defaultTagPath("nuggets/%s") - .unformattedTagPath("nuggets") + .defaultTag("nuggets/%s") + .unformattedTag("nuggets") .materialAmount(GTValues.M / 9) .materialIconType(MaterialIconType.nugget) .unificationEnabled(true) @@ -424,8 +424,8 @@ public boolean isEmpty() { // 9 Plates combined in one Item. public static final TagPrefix plateDense = new TagPrefix(GTCEu.id("dense_plate")) .idPattern("dense_%s_plate") - .defaultTagPath("dense_plates/%s") - .unformattedTagPath("dense_plates") + .defaultTag("dense_plates/%s") + .unformattedTag("dense_plates") .langValue("Dense %s Plate") .materialAmount(GTValues.M * 9) .maxStackSize(7) @@ -438,8 +438,8 @@ public boolean isEmpty() { // 2 Plates combined in one Item public static final TagPrefix plateDouble = new TagPrefix(GTCEu.id("double_plate")) .idPattern("double_%s_plate") - .defaultTagPath("double_plates/%s") - .unformattedTagPath("double_plates") + .defaultTag("double_plates/%s") + .unformattedTag("double_plates") .langValue("Double %s Plate") .materialAmount(GTValues.M * 2) .maxStackSize(32) @@ -452,8 +452,8 @@ public boolean isEmpty() { // Regular Plate made of one Ingot/Dust. public static final TagPrefix plate = new TagPrefix(GTCEu.id("plate")) - .defaultTagPath("plates/%s") - .unformattedTagPath("plates") + .defaultTag("plates/%s") + .unformattedTag("plates") .materialAmount(GTValues.M) .materialIconType(MaterialIconType.plate) .unificationEnabled(true) @@ -463,8 +463,8 @@ public boolean isEmpty() { // Round made of 1 Nugget public static final TagPrefix round = new TagPrefix(GTCEu.id("round")) - .defaultTagPath("rounds/%s") - .unformattedTagPath("rounds") + .defaultTag("rounds/%s") + .unformattedTag("rounds") .materialAmount(GTValues.M / 9) .materialIconType(MaterialIconType.round) .unificationEnabled(true) @@ -474,8 +474,8 @@ public boolean isEmpty() { // Foil made of 1/4 Ingot/Dust. public static final TagPrefix foil = new TagPrefix(GTCEu.id("foil")) - .defaultTagPath("foils/%s") - .unformattedTagPath("foils") + .defaultTag("foils/%s") + .unformattedTag("foils") .materialAmount(GTValues.M / 4) .materialIconType(MaterialIconType.foil) .unificationEnabled(true) @@ -486,8 +486,8 @@ public boolean isEmpty() { // Stick made of an Ingot. public static final TagPrefix rodLong = new TagPrefix(GTCEu.id("long_rod")) .idPattern("long_%s_rod") - .defaultTagPath("rods/long/%s") - .unformattedTagPath("rods/long") + .defaultTag("rods/long/%s") + .unformattedTag("rods/long") .langValue("Long %s Rod") .materialAmount(GTValues.M) .materialIconType(MaterialIconType.rodLong) @@ -498,8 +498,8 @@ public boolean isEmpty() { // Stick made of half an Ingot. public static final TagPrefix rod = new TagPrefix(GTCEu.id("rod")) - .defaultTagPath("rods/%s") - .unformattedTagPath("rods") + .defaultTag("rods/%s") + .unformattedTag("rods") .langValue("%s Rod") .materialAmount(GTValues.M / 2) .materialIconType(MaterialIconType.rod) @@ -510,8 +510,8 @@ public boolean isEmpty() { // consisting out of 1/8 Ingot or 1/4 Stick. public static final TagPrefix bolt = new TagPrefix(GTCEu.id("bolt")) - .defaultTagPath("bolts/%s") - .unformattedTagPath("bolts") + .defaultTag("bolts/%s") + .unformattedTag("bolts") .materialAmount(GTValues.M / 8) .materialIconType(MaterialIconType.bolt) .unificationEnabled(true) @@ -521,8 +521,8 @@ public boolean isEmpty() { // consisting out of 1/9 Ingot. public static final TagPrefix screw = new TagPrefix(GTCEu.id("screw")) - .defaultTagPath("screws/%s") - .unformattedTagPath("screws") + .defaultTag("screws/%s") + .unformattedTag("screws") .materialAmount(GTValues.M / 9) .materialIconType(MaterialIconType.screw) .unificationEnabled(true) @@ -532,8 +532,8 @@ public boolean isEmpty() { // consisting out of 1/2 Stick. public static final TagPrefix ring = new TagPrefix(GTCEu.id("ring")) - .defaultTagPath("rings/%s") - .unformattedTagPath("rings") + .defaultTag("rings/%s") + .unformattedTag("rings") .materialAmount(GTValues.M / 4) .materialIconType(MaterialIconType.ring) .unificationEnabled(true) @@ -544,8 +544,8 @@ public boolean isEmpty() { // consisting out of 1 Fine Wire. public static final TagPrefix springSmall = new TagPrefix(GTCEu.id("small_spring")) .idPattern("small_%s_spring") - .defaultTagPath("small_springs/%s") - .unformattedTagPath("small_springs") + .defaultTag("small_springs/%s") + .unformattedTag("small_springs") .langValue("Small %s Spring") .materialAmount(GTValues.M / 4) .materialIconType(MaterialIconType.springSmall) @@ -557,8 +557,8 @@ public boolean isEmpty() { // consisting out of 2 Sticks. public static final TagPrefix spring = new TagPrefix(GTCEu.id("spring")) - .defaultTagPath("springs/%s") - .unformattedTagPath("springs") + .defaultTag("springs/%s") + .unformattedTag("springs") .materialAmount(GTValues.M) .materialIconType(MaterialIconType.spring) .unificationEnabled(true) @@ -570,8 +570,8 @@ public boolean isEmpty() { // consisting out of 1/8 Ingot or 1/4 Wire. public static final TagPrefix wireFine = new TagPrefix(GTCEu.id("fine_wire")) .idPattern("fine_%s_wire") - .defaultTagPath("fine_wires/%s") - .unformattedTagPath("fine_wires") + .defaultTag("fine_wires/%s") + .unformattedTag("fine_wires") .langValue("Fine %s Wire") .materialAmount(GTValues.M / 8) .materialIconType(MaterialIconType.wireFine) @@ -582,8 +582,8 @@ public boolean isEmpty() { // consisting out of 4 Plates, 1 Ring and 1 Screw. public static final TagPrefix rotor = new TagPrefix(GTCEu.id("rotor")) - .defaultTagPath("rotors/%s") - .unformattedTagPath("rotors") + .defaultTag("rotors/%s") + .unformattedTag("rotors") .materialAmount(GTValues.M * 4) .maxStackSize(16) .materialIconType(MaterialIconType.rotor) @@ -595,8 +595,8 @@ public boolean isEmpty() { // Consisting of 1 Plate. public static final TagPrefix gearSmall = new TagPrefix(GTCEu.id("small_gear")) .idPattern("small_%s_gear") - .defaultTagPath("small_gears/%s") - .unformattedTagPath("small_gears") + .defaultTag("small_gears/%s") + .unformattedTag("small_gears") .langValue("Small %s Gear") .materialAmount(GTValues.M) .materialIconType(MaterialIconType.gearSmall) @@ -607,8 +607,8 @@ public boolean isEmpty() { // Consisting of 4 Plates. public static final TagPrefix gear = new TagPrefix(GTCEu.id("gear")) - .defaultTagPath("gears/%s") - .unformattedTagPath("gears") + .defaultTag("gears/%s") + .unformattedTag("gears") .materialAmount(GTValues.M * 4) .maxStackSize(16) .materialIconType(MaterialIconType.gear) @@ -619,8 +619,8 @@ public boolean isEmpty() { // 3/4 of a Plate or Gem used to shape a Lens. Normally only used on Transparent Materials. public static final TagPrefix lens = new TagPrefix(GTCEu.id("lens")) - .defaultTagPath("lenses/%s") - .unformattedTagPath("lenses") + .defaultTag("lenses/%s") + .unformattedTag("lenses") .materialAmount((GTValues.M * 3) / 4) .materialIconType(MaterialIconType.lens) .unificationEnabled(true) @@ -629,8 +629,8 @@ public boolean isEmpty() { .generationCondition(mat -> mat.hasFlag(MaterialFlags.GENERATE_LENS)); public static final TagPrefix dye = new TagPrefix(GTCEu.id("dye")) - .defaultTagPath("dyes/%s") - .unformattedTagPath("dyes") + .defaultTag("dyes/%s") + .unformattedTag("dyes") .materialAmount(-1); // made of 4 Ingots. @@ -725,8 +725,8 @@ public boolean isEmpty() { // Storage Block consisting out of 9 Ingots/Gems/Dusts. public static final TagPrefix block = new TagPrefix(GTCEu.id("block")) - .defaultTagPath("storage_blocks/%s") - .unformattedTagPath("storage_blocks") + .defaultTag("storage_blocks/%s") + .unformattedTag("storage_blocks") .langValue("Block of %s") .materialAmount(GTValues.M * 9) .materialIconType(MaterialIconType.block) @@ -738,25 +738,25 @@ public boolean isEmpty() { .enableRecycling(); public static final TagPrefix log = new TagPrefix(GTCEu.id("log")) - .unformattedTagPath("logs", true); + .unformattedTag("logs", true); public static final TagPrefix planks = new TagPrefix(GTCEu.id("planks")) - .unformattedTagPath("planks", true); + .unformattedTag("planks", true); public static final TagPrefix slab = new TagPrefix(GTCEu.id("slab")) - .unformattedTagPath("slabs", true); + .unformattedTag("slabs", true); public static final TagPrefix stairs = new TagPrefix(GTCEu.id("stairs")) - .unformattedTagPath("stairs", true); + .unformattedTag("stairs", true); public static final TagPrefix fence = new TagPrefix(GTCEu.id("fence")) - .unformattedTagPath("fences"); + .unformattedTag("fences"); public static final TagPrefix fenceGate = new TagPrefix(GTCEu.id("fence_gate")) - .unformattedTagPath("fence_gates"); + .unformattedTag("fence_gates"); public static final TagPrefix door = new TagPrefix(GTCEu.id("door")) - .unformattedTagPath("doors", true); + .unformattedTag("doors", true); // Prefix to determine which kind of Rock this is. // Also has a base tag path of only the material, for things like obsidian etc. public static final TagPrefix rock = new TagPrefix(GTCEu.id("rock")) // the 2nd 's' makes the tag plural, which is what Common tags are expected to be. - .defaultTagPath("%ss") + .defaultTag("%ss") .langValue("%s") .miningToolTag(BlockTags.MINEABLE_WITH_PICKAXE) .unificationEnabled(false) @@ -764,8 +764,8 @@ public boolean isEmpty() { .generationCondition((material) -> false); public static final TagPrefix frameGt = new TagPrefix(GTCEu.id("frame")) - .defaultTagPath("frames/%s") - .unformattedTagPath("frames") + .defaultTag("frames/%s") + .unformattedTag("frames") .langValue("%s Frame") .materialAmount(GTValues.M * 2) .materialIconType(MaterialIconType.frameGt) @@ -960,8 +960,8 @@ public boolean isEmpty() { public static final TagPrefix surfaceRock = new TagPrefix(GTCEu.id("surface_rock")) .langValue("%s Surface Rock") - .defaultTagPath("surface_rocks/%s") - .unformattedTagPath("surface_rocks") + .defaultTag("surface_rocks/%s") + .unformattedTag("surface_rocks") .materialAmount(GTValues.M / 3); public static class Conditions { @@ -1093,9 +1093,9 @@ public static TagPrefix oreTagPrefix(String name, TagKey miningToolTag) { public static TagPrefix oreTagPrefix(ResourceLocation id, TagKey miningToolTag) { return new TagPrefix(id) - .defaultTagPath("ores/%s") - .prefixOnlyTagPath("ores_in_ground/%s") - .unformattedTagPath("ores") + .defaultTag("ores/%s") + .prefixOnlyTag("ores_in_ground/%s") + .unformattedTag("ores") .materialIconType(MaterialIconType.ore) .miningToolTag(miningToolTag) .unificationEnabled(true) @@ -1137,49 +1137,149 @@ public TagPrefix registerOre(Supplier stoneType, Supplier return this; } + /** + * @deprecated use {@link #defaultTag(String)} instead. + */ + @Deprecated(since = "8.0.0", forRemoval = true) public TagPrefix defaultTagPath(String path) { - return this.defaultTagPath(path, false); + return defaultTag(path); } + /** + * Create a tag with a specified path with the "default" formatter, meaning there should be one "%s" format + * specifier in the path, intended for the material name. + */ + public TagPrefix defaultTag(String path) { + return defaultTag(path, false); + } + + /** + * @deprecated use {@link #defaultTag(String, boolean)} instead. + */ + @Deprecated(since = "8.0.0", forRemoval = true) public TagPrefix defaultTagPath(String path, boolean isVanilla) { + return defaultTag(path, false); + } + + /** + * Create a tag with a specified path with the "default" formatter, meaning there should be one "%s" format + * specifier in the path, intended for the material name. + */ + public TagPrefix defaultTag(String path, boolean isVanilla) { this.tags.add(TagType.withDefaultFormatter(path, isVanilla)); return this; } + /** + * @deprecated use {@link #prefixTag(String)} instead. + */ + @Deprecated(since = "8.0.0", forRemoval = true) public TagPrefix prefixTagPath(String path) { + return prefixTag(path); + } + + /** + * Create a tag with a specified path with the "prefix" formatter, meaning there should be two "%s" format + * specifiers in the path, with the first being the prefix name and the second being the material name. + */ + public TagPrefix prefixTag(String path) { this.tags.add(TagType.withPrefixFormatter(path)); return this; } + /** + * @deprecated use {@link #prefixOnlyTag(String)} instead. + */ + @Deprecated(since = "8.0.0", forRemoval = true) public TagPrefix prefixOnlyTagPath(String path) { + return prefixOnlyTag(path); + } + + /** + * Create a tag with a specified path with the "prefix only" formatter, meaning there should be one "%s" format + * specifier in the path, intended for the prefix name. + */ + public TagPrefix prefixOnlyTag(String path) { this.tags.add(TagType.withPrefixOnlyFormatter(path)); return this; } + /** + * @deprecated use {@link #unformattedTag(String)} instead. + */ + @Deprecated(since = "8.0.0", forRemoval = true) public TagPrefix unformattedTagPath(String path) { - return unformattedTagPath(path, false); + return unformattedTag(path); } + /** + * Create a tag with a specified path with no formatter, meaning there should be no "%s" format specifiers in + * the path and that it's usable as a tag key's path as is. + */ + public TagPrefix unformattedTag(String path) { + return unformattedTag(path, false); + } + + /** + * @deprecated use {@link #unformattedTag(String)} instead. + */ + @Deprecated(since = "8.0.0", forRemoval = true) public TagPrefix unformattedTagPath(String path, boolean isVanilla) { + return unformattedTag(path, isVanilla); + } + + /** + * Create a tag with a specified path with no formatter, meaning there should be no "%s" format specifiers in + * the path and that it's usable as a tag key's path as is. + */ + public TagPrefix unformattedTag(String path, boolean isVanilla) { this.tags.add(TagType.withNoFormatter(path, isVanilla)); return this; } + /** + * @deprecated use {@link #customFormattedTag(String, BiFunction)} instead. + */ + @Deprecated(since = "8.0.0", forRemoval = true) public TagPrefix customTagPath(String path, BiFunction> formatter) { - this.tags.add(TagType.withCustomFormatter(path, formatter)); + this.tags.add(TagType.withCustomFormatter(formatter)); return this; } - public TagPrefix customTagPredicate(String path, boolean isVanilla, Predicate materialPredicate) { - this.tags.add(TagType.withCustomFilter(path, isVanilla, materialPredicate)); + /** + * Create a tag with a specified path with a custom formatter. + */ + public TagPrefix customFormattedTag(String path, BiFunction> formatter) { + this.tags.add(TagType.withCustomFormatter((self, mat) -> formatter.apply(path, mat))); return this; } + /** + * @deprecated use {@link #filteredUnformattedTag(String, boolean, Predicate)} instead. + */ + @Deprecated(since = "8.0.0", forRemoval = true) + public TagPrefix customTagPredicate(String path, boolean isVanilla, Predicate materialPredicate) { + return this.filteredUnformattedTag(path, isVanilla, materialPredicate); + } + + /** + * Create a tag with a specified path with no formatter, meaning there should be no "%s" format specifiers in + * the path and that it's usable as a tag key's path as is. + *

+ * This variant of the method accepts an additional argument for a filter that'll be used to decide whether a + * specific material should be added to the tag. + */ public TagPrefix filteredUnformattedTag(String path, boolean isVanilla, Predicate materialPredicate) { this.tags.add(TagType.filteredNoFormatter(path, isVanilla, materialPredicate)); return this; } + /** + * Create a tag with a specified path with a custom formatter. + *

+ * This variant of the method accepts an additional argument for a filter that'll be used to decide whether a + * specific material should be added to the tag. + */ public TagPrefix filteredCustomTag(String path, Predicate materialPredicate, BiFunction> formatter) { this.tags.add(TagType.filteredCustomFormatter(materialPredicate, (self, mat) -> formatter.apply(path, mat))); diff --git a/src/main/java/com/gregtechceu/gtceu/integration/kjs/builders/prefix/OreTagPrefixBuilder.java b/src/main/java/com/gregtechceu/gtceu/integration/kjs/builders/prefix/OreTagPrefixBuilder.java index 73c4f1fb231..d9d232e844a 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/kjs/builders/prefix/OreTagPrefixBuilder.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/kjs/builders/prefix/OreTagPrefixBuilder.java @@ -43,9 +43,9 @@ public OreTagPrefixBuilder(ResourceLocation id) { @Override public TagPrefix create(String id) { return new TagPrefix(id) - .defaultTagPath("ores/%s") - .prefixOnlyTagPath("ores_in_ground/%s") - .unformattedTagPath("ores") + .defaultTag("ores/%s") + .prefixOnlyTag("ores_in_ground/%s") + .unformattedTag("ores") .materialIconType(MaterialIconType.ore) .unificationEnabled(true) .blockConstructor(OreBlock::new) diff --git a/src/main/java/com/gregtechceu/gtceu/integration/kjs/builders/prefix/TagPrefixBuilder.java b/src/main/java/com/gregtechceu/gtceu/integration/kjs/builders/prefix/TagPrefixBuilder.java index e984f6f0964..7242c0a44bb 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/kjs/builders/prefix/TagPrefixBuilder.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/kjs/builders/prefix/TagPrefixBuilder.java @@ -15,6 +15,7 @@ import net.minecraft.world.level.block.state.BlockBehaviour; import dev.latvian.mods.kubejs.registry.BuilderBase; +import dev.latvian.mods.kubejs.typings.Info; import lombok.Getter; import lombok.experimental.Accessors; @@ -111,41 +112,87 @@ public TagPrefixBuilder addSecondaryMaterial(MaterialStack secondaryMaterial) { return this; } + @Info(""" + Deprecated. Use `defaultTag(path)` instead. + """) public TagPrefixBuilder defaultTagPath(String path) { - base.defaultTagPath(path); + return defaultTag(path); + } + + public TagPrefixBuilder defaultTag(String path) { + base.defaultTag(path); return this; } + @Info(""" + Deprecated. Use `defaultTag(path, isVanilla)` instead. + """) public TagPrefixBuilder defaultTagPath(String path, boolean isVanilla) { - base.defaultTagPath(path, isVanilla); + return defaultTag(path, isVanilla); + } + + public TagPrefixBuilder defaultTag(String path, boolean isVanilla) { + base.defaultTag(path, isVanilla); return this; } public TagPrefixBuilder prefixTagPath(String path) { - base.prefixTagPath(path); + return prefixTag(path); + } + + public TagPrefixBuilder prefixTag(String path) { + base.prefixTag(path); return this; } public TagPrefixBuilder prefixOnlyTagPath(String path) { - base.prefixOnlyTagPath(path); + return prefixOnlyTag(path); + } + + public TagPrefixBuilder prefixOnlyTag(String path) { + base.prefixOnlyTag(path); return this; } public TagPrefixBuilder unformattedTagPath(String path) { - base.unformattedTagPath(path); + return unformattedTag(path); + } + + public TagPrefixBuilder unformattedTag(String path) { + base.unformattedTag(path); return this; } + @Info(""" + Deprecated. Use `unformattedTag(path, isVanilla)` instead. + """) public TagPrefixBuilder unformattedTagPath(String path, boolean isVanilla) { - base.unformattedTagPath(path, isVanilla); + return unformattedTag(path, isVanilla); + } + + public TagPrefixBuilder unformattedTag(String path, boolean isVanilla) { + base.unformattedTag(path, isVanilla); return this; } + @Info(""" + Deprecated. Use `customFormattedTag(path, (path, mat) => ...)` instead. + """) + @SuppressWarnings("removal") public TagPrefixBuilder customTagPath(String path, BiFunction> formatter) { base.customTagPath(path, formatter); return this; } + public TagPrefixBuilder customFormattedTag(String path, BiFunction> formatter) { + base.customFormattedTag(path, formatter); + return this; + } + + @Info(""" + Deprecated. Use `filteredUnformattedTag(path, isVanilla, (mat) => ...shouldAdd...)` instead. + """) + @SuppressWarnings("removal") public TagPrefixBuilder customTagPredicate(String path, boolean isVanilla, Predicate materialPredicate) { base.customTagPredicate(path, isVanilla, materialPredicate); return this; From 422a250a5f57ed14cc52c9e7b7b1cd0b5c16d8e2 Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Wed, 5 Aug 2026 22:06:45 +0300 Subject: [PATCH 10/19] Move tag filter addition from TagType to TagPrefix --- .../gregtechceu/gtceu/api/data/tag/TagPrefix.java | 8 ++++++-- .../gregtechceu/gtceu/api/data/tag/TagType.java | 15 +-------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java index a369558be27..d95f9a95ec7 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java @@ -1270,7 +1270,9 @@ public TagPrefix customTagPredicate(String path, boolean isVanilla, Predicate materialPredicate) { - this.tags.add(TagType.filteredNoFormatter(path, isVanilla, materialPredicate)); + TagType entry = TagType.withNoFormatter(path, isVanilla); + entry.filter = materialPredicate; + this.tags.add(entry); return this; } @@ -1282,7 +1284,9 @@ public TagPrefix filteredUnformattedTag(String path, boolean isVanilla, Predicat */ public TagPrefix filteredCustomTag(String path, Predicate materialPredicate, BiFunction> formatter) { - this.tags.add(TagType.filteredCustomFormatter(materialPredicate, (self, mat) -> formatter.apply(path, mat))); + TagType entry = TagType.withCustomFormatter((self, mat) -> formatter.apply(path, mat)); + entry.filter = materialPredicate; + this.tags.add(entry); return this; } diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagType.java b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagType.java index 866600226a6..b281a1985a6 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagType.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagType.java @@ -22,7 +22,7 @@ public final class TagType { private boolean isParentTag = false; // this is now memoized because creating tag keys interns them and that's slow private final @NotNull BiFunction> formatter; - private @Nullable Predicate filter; + /* package-private */ @Nullable Predicate filter; private TagType(BiFunction> formatter) { this.formatter = Util.memoize(formatter); @@ -65,19 +65,6 @@ public static TagType withNoFormatter(String tagPath, boolean isVanilla) { public static TagType withCustomFormatter(BiFunction> formatter) { return new TagType(formatter); } - - public static TagType filteredCustomFormatter(Predicate filter, - BiFunction> formatter) { - TagType type = new TagType(formatter); - type.filter = filter; - return type; - } - - public static TagType filteredNoFormatter(String tagPath, boolean isVanilla, Predicate filter) { - TagType type = new TagType((prefix, material) -> TagUtil.createItemTag(tagPath, isVanilla)); - type.filter = filter; - return type; - } // spotless:on public @Nullable TagKey getTag(TagPrefix prefix, @NotNull Material material) { From 5e202d9821b4b35a05f388553a93088c790ee26c Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Wed, 5 Aug 2026 22:07:28 +0300 Subject: [PATCH 11/19] Simplify PostRegistryListener --- .../data/loader/PostRegistryListener.java | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/gregtechceu/gtceu/data/loader/PostRegistryListener.java b/src/main/java/com/gregtechceu/gtceu/data/loader/PostRegistryListener.java index c51348f6f76..8f98a3d3357 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/loader/PostRegistryListener.java +++ b/src/main/java/com/gregtechceu/gtceu/data/loader/PostRegistryListener.java @@ -7,24 +7,21 @@ import com.gregtechceu.gtceu.integration.map.cache.server.ServerCache; import net.minecraft.core.HolderLookup; -import net.minecraft.server.packs.resources.PreparableReloadListener; import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.server.packs.resources.ResourceManagerReloadListener; import net.neoforged.neoforge.resource.ContextAwareReloadListener; import org.jetbrains.annotations.NotNullByDefault; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; - @NotNullByDefault -public class PostRegistryListener extends ContextAwareReloadListener implements PreparableReloadListener { +public class PostRegistryListener extends ContextAwareReloadListener implements ResourceManagerReloadListener { public static final PostRegistryListener INSTANCE = new PostRegistryListener(); private PostRegistryListener() {} - protected void apply() { + @Override + public void onResourceManagerReload(ResourceManager resourceManager) { var lookup = getRegistryLookup().lookupOrThrow(GTRegistries.Keys.ORE_VEIN); buildVeinGenerators(lookup); GTOreVeins.updateLargestVeinSize(lookup); @@ -42,11 +39,4 @@ public static void buildVeinGenerators(HolderLookup.RegistryLookup reload(PreparationBarrier stage, ResourceManager resourceManager, - ProfilerFiller preparationsProfiler, ProfilerFiller reloadProfiler, - Executor backgroundExecutor, Executor gameExecutor) { - return stage.wait(null).thenRunAsync(this::apply); - } } From 31b6e0092cfad39cf6e50cba0b54f9bab9115499 Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Wed, 5 Aug 2026 22:38:18 +0300 Subject: [PATCH 12/19] Move dynamic loot table generation from `MixinHelpers` to a handler class --- .../api/data/chemical/ChemicalHelper.java | 11 ++ .../gregtechceu/gtceu/core/MixinHelpers.java | 133 ------------- .../ReloadableServerResourcesMixin.java | 30 +-- .../data/dynamic/DynamicLootHandler.java | 177 ++++++++++++++++++ .../gtceu/data/pack/GTDynamicDataPack.java | 11 +- 5 files changed, 201 insertions(+), 161 deletions(-) create mode 100644 src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicLootHandler.java diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/ChemicalHelper.java b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/ChemicalHelper.java index b691d4694de..aacc7f93cb4 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/ChemicalHelper.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/ChemicalHelper.java @@ -19,6 +19,7 @@ import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Block; @@ -245,6 +246,16 @@ public static List getItems(MaterialEntry materialEntry) { }).stream().map(Supplier::get).collect(Collectors.toList()); } + public static @Nullable Item getItem(MaterialEntry materialEntry) { + List items = getItems(materialEntry); + if (items.isEmpty()) return null; + return items.get(0).asItem(); + } + + public static Item getItem(TagPrefix tagPrefix, Material material) { + return getItem(new MaterialEntry(tagPrefix, material)); + } + public static ItemStack get(MaterialEntry materialEntry, int size) { var list = getItems(materialEntry); if (list.isEmpty()) return ItemStack.EMPTY; diff --git a/src/main/java/com/gregtechceu/gtceu/core/MixinHelpers.java b/src/main/java/com/gregtechceu/gtceu/core/MixinHelpers.java index ee67bcf3965..42a0f6e41d7 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/MixinHelpers.java +++ b/src/main/java/com/gregtechceu/gtceu/core/MixinHelpers.java @@ -1,156 +1,30 @@ package com.gregtechceu.gtceu.core; import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.api.data.chemical.ChemicalHelper; import com.gregtechceu.gtceu.api.data.chemical.material.Material; -import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; -import com.gregtechceu.gtceu.api.data.chemical.material.stack.MaterialStack; -import com.gregtechceu.gtceu.api.data.tag.TagPrefix; import com.gregtechceu.gtceu.api.data.worldgen.GTOreDefinition; import com.gregtechceu.gtceu.api.data.worldgen.bedrockfluid.BedrockFluidDefinition; import com.gregtechceu.gtceu.api.data.worldgen.bedrockore.BedrockOreDefinition; import com.gregtechceu.gtceu.api.fluids.store.FluidStorage; import com.gregtechceu.gtceu.api.registry.GTRegistries; import com.gregtechceu.gtceu.api.registry.registrate.GTClientFluidTypeExtensions; -import com.gregtechceu.gtceu.common.data.GTMaterialBlocks; -import com.gregtechceu.gtceu.core.mixins.BlockBehaviourAccessor; import com.gregtechceu.gtceu.integration.kjs.GTCEuServerEvents; import com.gregtechceu.gtceu.integration.kjs.events.GTBedrockFluidVeinEventJS; import com.gregtechceu.gtceu.integration.kjs.events.GTBedrockOreVeinEventJS; import com.gregtechceu.gtceu.integration.kjs.events.GTOreVeinEventJS; -import net.minecraft.client.Minecraft; import net.minecraft.core.*; -import net.minecraft.core.registries.Registries; -import net.minecraft.data.loot.packs.VanillaBlockLoot; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.Enchantment; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.storage.loot.IntRange; -import net.minecraft.world.level.storage.loot.LootPool; -import net.minecraft.world.level.storage.loot.LootTable; -import net.minecraft.world.level.storage.loot.entries.LootItem; -import net.minecraft.world.level.storage.loot.functions.ApplyBonusCount; -import net.minecraft.world.level.storage.loot.functions.ApplyExplosionDecay; -import net.minecraft.world.level.storage.loot.functions.LimitCount; -import net.minecraft.world.level.storage.loot.functions.SetItemCountFunction; -import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; -import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; -import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator; import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; -import com.tterrag.registrate.util.entry.BlockEntry; import dev.latvian.mods.kubejs.util.RegistryAccessContainer; -import org.apache.logging.log4j.util.TriConsumer; import org.jetbrains.annotations.ApiStatus; -import java.util.*; import java.util.function.Consumer; @SuppressWarnings("deprecation") @ApiStatus.Internal public class MixinHelpers { - public static void generateGTDynamicLoot(TriConsumer lootTables, - final RegistryAccess.Frozen access) { - final VanillaBlockLoot blockLoot = new VanillaBlockLoot(access); - - Holder fortune = access.registryOrThrow(Registries.ENCHANTMENT) - .getHolderOrThrow(Enchantments.FORTUNE); - GTMaterialBlocks.MATERIAL_BLOCKS.rowMap().forEach((prefix, map) -> { - if (TagPrefix.ORES.containsKey(prefix)) { - final TagPrefix.OreType type = TagPrefix.ORES.get(prefix); - map.forEach((material, blockEntry) -> { - ResourceLocation lootTableId = blockEntry.getId().withPrefix("blocks/"); - Block block = blockEntry.get(); - - ItemStack dropItem = ChemicalHelper.get(TagPrefix.rawOre, material); - if (dropItem.isEmpty()) dropItem = ChemicalHelper.get(TagPrefix.gem, material); - if (dropItem.isEmpty()) dropItem = ChemicalHelper.get(TagPrefix.dust, material); - int oreMultiplier = type.isDoubleDrops() ? 2 : 1; - - LootTable.Builder builder = blockLoot.createSilkTouchDispatchTable(block, - blockLoot.applyExplosionDecay(block, - LootItem.lootTableItem(dropItem.getItem()) - .apply(SetItemCountFunction - .setCount(ConstantValue.exactly(oreMultiplier))))); - // disable fortune for balance reasons. (for now, until we can think of a better solution.) - // .apply(ApplyBonusCount.addOreBonusCount(Enchantments.BLOCK_FORTUNE)))); - - LootPool.Builder pool = LootPool.lootPool(); - boolean isEmpty = true; - for (MaterialStack secondaryMaterial : prefix.secondaryMaterials()) { - if (secondaryMaterial.material().hasProperty(PropertyKey.DUST)) { - ItemStack dustStack = ChemicalHelper.getGem(secondaryMaterial); - pool.add(LootItem.lootTableItem(dustStack.getItem()) - .when(blockLoot.doesNotHaveSilkTouch()) - .apply(SetItemCountFunction.setCount(UniformGenerator.between(0, 1))) - // .apply(ApplyBonusCount.addUniformBonusCount(fortune)) - .apply(LimitCount.limitCount(IntRange.range(0, 2))) - .apply(ApplyExplosionDecay.explosionDecay())); - isEmpty = false; - } - } - if (!isEmpty) { - builder.withPool(pool); - } - lootTables.accept(lootTableId, builder.setParamSet(LootContextParamSets.BLOCK).build(), access); - ((BlockBehaviourAccessor) blockEntry.get()) - .setDrops(ResourceKey.create(Registries.LOOT_TABLE, lootTableId)); - }); - } else { - MixinHelpers.addMaterialBlockLootTables(lootTables, prefix, map, blockLoot, access); - } - }); - GTMaterialBlocks.CABLE_BLOCKS.rowMap().forEach((prefix, map) -> { - MixinHelpers.addMaterialBlockLootTables(lootTables, prefix, map, blockLoot, access); - }); - GTMaterialBlocks.FLUID_PIPE_BLOCKS.rowMap().forEach((prefix, map) -> { - MixinHelpers.addMaterialBlockLootTables(lootTables, prefix, map, blockLoot, access); - }); - GTMaterialBlocks.ITEM_PIPE_BLOCKS.rowMap().forEach((prefix, map) -> { - MixinHelpers.addMaterialBlockLootTables(lootTables, prefix, map, blockLoot, access); - }); - GTMaterialBlocks.SURFACE_ROCK_BLOCKS.forEach((material, blockEntry) -> { - ResourceLocation lootTableId = ResourceLocation.fromNamespaceAndPath(blockEntry.getId().getNamespace(), - "blocks/" + blockEntry.getId().getPath()); - LootTable.Builder builder = blockLoot - .createSingleItemTable(ChemicalHelper.get(TagPrefix.dustTiny, material).getItem(), - UniformGenerator.between(3, 5)) - .apply(ApplyBonusCount.addUniformBonusCount(fortune)); - lootTables.accept(lootTableId, builder.setParamSet(LootContextParamSets.BLOCK).build(), access); - ((BlockBehaviourAccessor) blockEntry.get()) - .setDrops(ResourceKey.create(Registries.LOOT_TABLE, lootTableId)); - }); - GTRegistries.MACHINES.forEach(machine -> { - Block block = machine.getBlock(); - ResourceLocation id = machine.getId(); - ResourceLocation lootTableId = ResourceLocation.fromNamespaceAndPath(id.getNamespace(), - "blocks/" + id.getPath()); - ((BlockBehaviourAccessor) block).setDrops(ResourceKey.create(Registries.LOOT_TABLE, lootTableId)); - lootTables.accept(lootTableId, - blockLoot.createSingleItemTable(block).setParamSet(LootContextParamSets.BLOCK).build(), access); - }); - } - - public static void addMaterialBlockLootTables(TriConsumer lootTables, - TagPrefix prefix, - Map> map, - VanillaBlockLoot blockLoot, RegistryAccess.Frozen access) { - map.forEach((material, blockEntry) -> { - ResourceLocation lootTableId = blockEntry.getId().withPrefix("blocks/"); - ((BlockBehaviourAccessor) blockEntry.get()) - .setDrops(ResourceKey.create(Registries.LOOT_TABLE, lootTableId)); - lootTables.accept(lootTableId, - blockLoot.createSingleItemTable(blockEntry.get()).setParamSet(LootContextParamSets.BLOCK).build(), - access); - }); - } - public static void postKJSVeinEvents(RegistryAccess.Frozen registries) { if (!GTCEu.Mods.isKubeJSLoaded()) { return; @@ -208,11 +82,4 @@ private static void updateRegistryAccessContainer(RegistryAccess.Frozen registri } } } - - public static final class ClientCallWrapper { - - public static Level getClientLevel() { - return Minecraft.getInstance().level; - } - } } diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/ReloadableServerResourcesMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/ReloadableServerResourcesMixin.java index bba30f8e232..6a2f1536199 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/ReloadableServerResourcesMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/ReloadableServerResourcesMixin.java @@ -1,30 +1,15 @@ package com.gregtechceu.gtceu.core.mixins; -import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.api.machine.trait.customlogic.SteamBoilerLogic; -import com.gregtechceu.gtceu.common.data.GTRecipes; -import com.gregtechceu.gtceu.core.MixinHelpers; -import com.gregtechceu.gtceu.data.loot.DungeonLootLoader; -import com.gregtechceu.gtceu.data.pack.GTDynamicDataPack; -import com.gregtechceu.gtceu.data.recipe.GTCraftingComponents; - -import net.minecraft.advancements.Advancement; -import net.minecraft.advancements.AdvancementHolder; +import com.gregtechceu.gtceu.data.dynamic.DynamicLootHandler; + import net.minecraft.commands.Commands; import net.minecraft.core.LayeredRegistryAccess; import net.minecraft.core.RegistryAccess; -import net.minecraft.data.recipes.RecipeBuilder; -import net.minecraft.data.recipes.RecipeOutput; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.RegistryLayer; import net.minecraft.server.ReloadableServerResources; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.world.flag.FeatureFlagSet; -import net.minecraft.world.item.crafting.Recipe; -import net.neoforged.neoforge.common.conditions.ICondition; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -44,15 +29,10 @@ public abstract class ReloadableServerResourcesMixin { // load loot tables *before* other data so we have the registries loaded before saving recipes to JSON. // because it breaks if we don't do that. - // this doesn't have dynamic registries available, by the way. - RegistryAccess.Frozen frozen = access.compositeAccess(); + // this doesn't have reloadable registries available, by the way. + RegistryAccess.Frozen registries = access.compositeAccess(); // Register dynamic loot - long startTime = System.currentTimeMillis(); - MixinHelpers.generateGTDynamicLoot(GTDynamicDataPack::addLootTable, frozen); - // Initialize dungeon loot additions - DungeonLootLoader.init(); - - GTCEu.LOGGER.info("GregTech Loot table loading took {}ms", System.currentTimeMillis() - startTime); + DynamicLootHandler.generateDynamicLoot(registries); } } diff --git a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicLootHandler.java b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicLootHandler.java new file mode 100644 index 00000000000..81cb73c0011 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicLootHandler.java @@ -0,0 +1,177 @@ +package com.gregtechceu.gtceu.data.dynamic; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.api.data.chemical.ChemicalHelper; +import com.gregtechceu.gtceu.api.data.chemical.material.Material; +import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; +import com.gregtechceu.gtceu.api.data.chemical.material.stack.MaterialStack; +import com.gregtechceu.gtceu.api.data.tag.TagPrefix; +import com.gregtechceu.gtceu.api.registry.GTRegistries; +import com.gregtechceu.gtceu.common.data.GTMaterialBlocks; +import com.gregtechceu.gtceu.core.mixins.BlockBehaviourAccessor; +import com.gregtechceu.gtceu.data.loot.DungeonLootLoader; +import com.gregtechceu.gtceu.data.pack.GTDynamicDataPack; + +import net.minecraft.core.HolderLookup; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.loot.packs.VanillaBlockLoot; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.storage.loot.IntRange; +import net.minecraft.world.level.storage.loot.LootPool; +import net.minecraft.world.level.storage.loot.LootTable; +import net.minecraft.world.level.storage.loot.entries.LootItem; +import net.minecraft.world.level.storage.loot.functions.ApplyBonusCount; +import net.minecraft.world.level.storage.loot.functions.ApplyExplosionDecay; +import net.minecraft.world.level.storage.loot.functions.LimitCount; +import net.minecraft.world.level.storage.loot.functions.SetItemCountFunction; +import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; +import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; +import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator; + +import com.google.gson.JsonElement; +import com.mojang.serialization.DynamicOps; +import com.mojang.serialization.JsonOps; +import com.tterrag.registrate.util.entry.BlockEntry; +import org.jetbrains.annotations.ApiStatus; + +import java.util.Map; +import java.util.function.BiFunction; + +@ApiStatus.Internal +public final class DynamicLootHandler { + + private DynamicLootHandler() {} + + public static void generateDynamicLoot(HolderLookup.Provider registries) { + long startTime = System.currentTimeMillis(); + DynamicLootHandler.generateDynamicLoot0(registries); + // Initialize dungeon loot additions + DungeonLootLoader.init(); + + GTCEu.LOGGER.info("GregTech dynamic loot table generation took {}ms", System.currentTimeMillis() - startTime); + } + + private static void generateDynamicLoot0(final HolderLookup.Provider registries) { + final VanillaBlockLoot helpers = new VanillaBlockLoot(registries); + final DynamicOps serializationContext = registries.createSerializationContext(JsonOps.INSTANCE); + + GTMaterialBlocks.MATERIAL_BLOCKS.rowMap().forEach((prefix, map) -> { + if (TagPrefix.ORES.containsKey(prefix)) { + final TagPrefix.OreType oreType = TagPrefix.ORES.get(prefix); + map.forEach((material, block) -> { + generateOreBlockLoot(prefix, material, block, oreType, helpers, serializationContext); + }); + } else { + addMaterialBlockLootTables(map, helpers, serializationContext); + } + }); + + // spotless:off + GTMaterialBlocks.CABLE_BLOCKS.rowMap().values().forEach((map) -> addMaterialBlockLootTables(map, helpers, serializationContext)); + GTMaterialBlocks.FLUID_PIPE_BLOCKS.rowMap().values().forEach((map) -> addMaterialBlockLootTables(map, helpers, serializationContext)); + GTMaterialBlocks.ITEM_PIPE_BLOCKS.rowMap().values().forEach((map) -> addMaterialBlockLootTables(map, helpers, serializationContext)); + addMaterialBlockLootTables(GTMaterialBlocks.SURFACE_ROCK_BLOCKS, serializationContext, (material, block) -> { + Item tinyDust = ChemicalHelper.getItem(TagPrefix.dustTiny, material); + if (tinyDust != null && tinyDust != Items.AIR) { + return helpers.createSilkTouchDispatchTable(block.get(), + helpers.applyExplosionDecay(block, + LootItem.lootTableItem(tinyDust) + .apply(SetItemCountFunction.setCount(UniformGenerator.between(3, 5))) + ) + ); + } else { + // fallback if the tiny dust doesn't exist + return helpers.createSingleItemTable(block.get()); + } + }); + // spotless:on + + GTRegistries.MACHINES.forEach(machine -> { + Block block = machine.getBlock(); + ResourceLocation lootTableId = machine.getId().withPrefix("blocks/"); + ((BlockBehaviourAccessor) block).setDrops(ResourceKey.create(Registries.LOOT_TABLE, lootTableId)); + + LootTable lootTable = helpers.createSingleItemTable(block) + .setParamSet(LootContextParamSets.BLOCK) + .build(); + GTDynamicDataPack.addLootTable(lootTableId, lootTable, serializationContext); + }); + } + + private static void addMaterialBlockLootTables(Map> map, + VanillaBlockLoot blockLoot, + DynamicOps serializationContext) { + addMaterialBlockLootTables(map, serializationContext, + (material, block) -> blockLoot.createSingleItemTable(block.get())); + } + + private static void addMaterialBlockLootTables(Map> map, + DynamicOps serializationContext, + BiFunction, LootTable.Builder> lootTableBuilder) { + map.forEach((material, block) -> { + ResourceLocation lootTableId = block.getId().withPrefix("blocks/"); + ((BlockBehaviourAccessor) block.get()).setDrops(ResourceKey.create(Registries.LOOT_TABLE, lootTableId)); + + LootTable lootTable = lootTableBuilder.apply(material, block) + .setParamSet(LootContextParamSets.BLOCK) + .build(); + GTDynamicDataPack.addLootTable(lootTableId, lootTable, serializationContext); + }); + } + + private static void generateOreBlockLoot(TagPrefix prefix, Material material, BlockEntry blockEntry, + TagPrefix.OreType oreType, + VanillaBlockLoot helpers, DynamicOps serializationContext) { + ResourceLocation lootTableId = blockEntry.getId().withPrefix("blocks/"); + Block block = blockEntry.get(); + ((BlockBehaviourAccessor) block).setDrops(ResourceKey.create(Registries.LOOT_TABLE, lootTableId)); + + ItemStack dropItem = ChemicalHelper.get(TagPrefix.rawOre, material); + if (dropItem.isEmpty()) dropItem = ChemicalHelper.get(TagPrefix.gem, material); + if (dropItem.isEmpty()) dropItem = ChemicalHelper.get(TagPrefix.dust, material); + + int oreMultiplier = oreType.isDoubleDrops() ? 2 : 1; + + // spotless:off + LootTable.Builder builder = helpers.createSilkTouchDispatchTable(block, + helpers.applyExplosionDecay(block, + LootItem.lootTableItem(dropItem.getItem()) + .apply(SetItemCountFunction.setCount(ConstantValue.exactly(oreMultiplier))) + ) + ); + // disable fortune for balance reasons. (for now, until we can think of a better solution.) + //.apply(ApplyBonusCount.addOreBonusCount(Enchantments.BLOCK_FORTUNE)))); + // spotless:on + + LootPool.Builder pool = LootPool.lootPool(); + boolean isEmpty = true; + for (MaterialStack secondaryMaterial : prefix.secondaryMaterials()) { + if (!secondaryMaterial.material().hasProperty(PropertyKey.DUST)) { + continue; + } + ItemStack dustStack = ChemicalHelper.getGem(secondaryMaterial); + pool.add(LootItem.lootTableItem(dustStack.getItem()) + .when(helpers.doesNotHaveSilkTouch()) + .apply(SetItemCountFunction.setCount(UniformGenerator.between(0, 1))) + // .apply(ApplyBonusCount.addUniformBonusCount(fortune)) + .apply(LimitCount.limitCount(IntRange.range(0, 2))) + .apply(ApplyExplosionDecay.explosionDecay())); + isEmpty = false; + } + if (!isEmpty) { + builder.withPool(pool); + } + + LootTable lootTable = builder + .setParamSet(LootContextParamSets.BLOCK) + .build(); + GTDynamicDataPack.addLootTable(lootTableId, lootTable, serializationContext); + + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/data/pack/GTDynamicDataPack.java b/src/main/java/com/gregtechceu/gtceu/data/pack/GTDynamicDataPack.java index fccb873cbea..aac4bcdaf10 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/pack/GTDynamicDataPack.java +++ b/src/main/java/com/gregtechceu/gtceu/data/pack/GTDynamicDataPack.java @@ -114,9 +114,14 @@ public static void addAdvancement(ResourceLocation loc, Advancement advancement, addResource(ADVANCEMENT_ID_CONVERTER.idToFile(loc), advancementJson); } - public static void addLootTable(ResourceLocation lootTableId, LootTable table, HolderLookup.Provider registries) { - JsonElement lootTableJson = LootTable.DIRECT_CODEC - .encodeStart(registries.createSerializationContext(JsonOps.INSTANCE), table).getOrThrow(); + public static void addLootTable(ResourceLocation lootTableId, LootTable table, + HolderLookup.Provider registries) { + addLootTable(lootTableId, table, registries.createSerializationContext(JsonOps.INSTANCE)); + } + + public static void addLootTable(ResourceLocation lootTableId, LootTable table, + DynamicOps serializationContext) { + JsonElement lootTableJson = LootTable.DIRECT_CODEC.encodeStart(serializationContext, table).getOrThrow(); ResourceLocation fileName = LOOT_TABLE_ID_CONVERTER.idToFile(lootTableId); if (CONTENTS.getResource(fileName) != null) { From 06b8c56694ce13745454f04424d71b6019c6152a Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Wed, 5 Aug 2026 22:38:40 +0300 Subject: [PATCH 13/19] time everything, everything! --- .../gregtechceu/gtceu/core/mixins/TagLoaderMixin.java | 2 +- .../gtceu/data/dynamic/DynamicRecipeHandler.java | 2 +- .../gtceu/data/dynamic/DynamicTagHandler.java | 9 +++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/TagLoaderMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/TagLoaderMixin.java index 17eec8f6139..35a2570f9fe 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/TagLoaderMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/TagLoaderMixin.java @@ -29,7 +29,7 @@ public class TagLoaderMixin implements IGTTagLoader { public void gtceu$load(ResourceManager resourceManager, CallbackInfoReturnable>> cir) { if (gtceu$storedRegistry == null) return; - DynamicTagHandler.generateGTDynamicTags(cir.getReturnValue(), gtceu$storedRegistry); + DynamicTagHandler.generateDynamicTags(cir.getReturnValue(), gtceu$storedRegistry); } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicRecipeHandler.java b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicRecipeHandler.java index 3b598794464..3f7573ec0af 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicRecipeHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicRecipeHandler.java @@ -89,7 +89,7 @@ public static void handleRecipesLate(RecipeManager recipeManager) { addRecipesToLookup(recipeManager); long elapsed = (System.currentTimeMillis() - startTime) + earlyLoadElapsed.get(); - GTCEu.LOGGER.info("GregTech Dynamic Recipe loading took {}ms", elapsed); + GTCEu.LOGGER.info("GregTech dynamic recipe generation took {}ms", elapsed); } private static void addRecipesToLookup(RecipeManager recipeManager) { diff --git a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java index 6cdca5540ef..add795c3a74 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java @@ -42,8 +42,10 @@ public final class DynamicTagHandler { private DynamicTagHandler() {} - public static void generateGTDynamicTags(Map> parsedTags, - Registry registry) { + public static void generateDynamicTags(Map> parsedTags, + Registry registry) { + long startTime = System.currentTimeMillis(); + if (registry == BuiltInRegistries.ITEM) { generateItemTags(parsedTags); } else if (registry == BuiltInRegistries.BLOCK) { @@ -51,6 +53,9 @@ public static void generateGTDynamicTags(Map> tags) { From de3b2945f98d10ab73e5158c9a4f1e45f0b556e1 Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Fri, 7 Aug 2026 16:49:39 +0300 Subject: [PATCH 14/19] =?UTF-8?q?Bypass=20Java=20Generic=20Hell=E2=84=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../recipe/lookup/RecipeManagerHandler.java | 23 +++++++++---------- .../data/dynamic/DynamicRecipeHandler.java | 6 +++-- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/lookup/RecipeManagerHandler.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/lookup/RecipeManagerHandler.java index f7ec6345ad4..dd3c498aa74 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/lookup/RecipeManagerHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/lookup/RecipeManagerHandler.java @@ -24,11 +24,11 @@ public final class RecipeManagerHandler { /** * Adds proxy recipes to an {@link GTRecipeType}'s {@link RecipeAdditionHandler} and adds them to a list. * - * @param recipes the recipes stored by their ID + * @param recipes the recipes * @param gtRecipeType the recipe type to add the recipes to, which owns the proxy recipes * @param proxyRecipes the list of proxy recipes to populate */ - public static void addProxyRecipesToLookup(@NotNull Collection> recipes, + public static void addProxyRecipesToLookup(@NotNull Collection> recipes, @NotNull GTRecipeType gtRecipeType, @NotNull RecipeType proxyType, @NotNull List> proxyRecipes) { var lookup = gtRecipeType.getAdditionHandler(); @@ -47,20 +47,19 @@ public static void addProxyRecipesToLookup(@NotNull Collection> recipes, - @NotNull GTRecipeType gtRecipeType) { - var lookup = gtRecipeType.getAdditionHandler(); - for (RecipeHolder r : recipes) { - if (r.value().getType() != gtRecipeType) { + public static void addRecipesToLookup(@NotNull Collection> recipes, + @NotNull GTRecipeType recipeType) { + var lookup = recipeType.getAdditionHandler(); + for (RecipeHolder r : recipes) { + GTRecipe recipe = r.value(); + if (recipe.getType() != recipeType) { // do not add recipes of incompatible type continue; } - if (r.value() instanceof GTRecipe recipe) { - lookup.addStaging(recipe); - } + lookup.addStaging(recipe); } } } diff --git a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicRecipeHandler.java b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicRecipeHandler.java index 3f7573ec0af..e4629adaeba 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicRecipeHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicRecipeHandler.java @@ -101,7 +101,9 @@ private static void addRecipesToLookup(RecipeManager recipeManager) { for (var entry : recipeType.getProxyRecipes().entrySet()) { RecipeType proxyRecipeType = entry.getKey(); - Collection> recipes = recipeManager.getAllRecipesFor(proxyRecipeType); + // Bypass Java Generic Hellâ„¢ + @SuppressWarnings({ "unchecked", "rawtypes" }) + List> recipes = recipeManager.getAllRecipesFor((RecipeType) proxyRecipeType); if (recipes.isEmpty()) { continue; } @@ -109,7 +111,7 @@ private static void addRecipesToLookup(RecipeManager recipeManager) { RecipeManagerHandler.addProxyRecipesToLookup(recipes, recipeType, proxyRecipeType, proxyRecipes); } - Collection> recipesByID = recipeManager.getAllRecipesFor(recipeType); + List> recipesByID = recipeManager.getAllRecipesFor(recipeType); RecipeManagerHandler.addRecipesToLookup(recipesByID, recipeType); recipeType.completeStagingRecipes(); } From aa1c3a4e6673392945823f2a7e0edefc426847ba Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Fri, 7 Aug 2026 17:29:15 +0300 Subject: [PATCH 15/19] Fix the RegistryOps we have ""not supporting"" items. Is this Mojank? maybe --- .../core/mixins/RecipeManagerEarlyMixin.java | 9 +--- .../data/dynamic/DynamicRecipeHandler.java | 20 +++++-- ...redOwnerUnwrappingHolderLookupAdapter.java | 54 +++++++++++++++++++ .../data/loader/PostRegistryListener.java | 3 -- .../gtceu/data/loader/package-info.java | 4 ++ 5 files changed, 75 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/gregtechceu/gtceu/data/loader/DeferredOwnerUnwrappingHolderLookupAdapter.java create mode 100644 src/main/java/com/gregtechceu/gtceu/data/loader/package-info.java diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerEarlyMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerEarlyMixin.java index d9cc4e81277..3b56686e338 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerEarlyMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerEarlyMixin.java @@ -2,7 +2,6 @@ import com.gregtechceu.gtceu.data.dynamic.DynamicRecipeHandler; -import net.minecraft.core.HolderLookup; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; @@ -11,9 +10,7 @@ import com.google.gson.Gson; import com.google.gson.JsonElement; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -23,10 +20,6 @@ @Mixin(value = RecipeManager.class, priority = 500) public abstract class RecipeManagerEarlyMixin extends SimpleJsonResourceReloadListener { - @Shadow - @Final - private HolderLookup.Provider registries; - private RecipeManagerEarlyMixin(Gson gson, String directory) { super(gson, directory); } @@ -36,6 +29,6 @@ private RecipeManagerEarlyMixin(Gson gson, String directory) { private void gtceu$handleDynamicRecipesEarly(Map map, ResourceManager resourceManager, ProfilerFiller profiler, CallbackInfo ci) { - DynamicRecipeHandler.handleRecipesEarly(map, this.registries, this.makeConditionalOps()); + DynamicRecipeHandler.handleRecipesEarly(map, this.getRegistryLookup(), this.getContext()); } } diff --git a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicRecipeHandler.java b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicRecipeHandler.java index e4629adaeba..5fcdbda2b8e 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicRecipeHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicRecipeHandler.java @@ -8,6 +8,7 @@ import com.gregtechceu.gtceu.api.recipe.lookup.RecipeManagerHandler; import com.gregtechceu.gtceu.common.data.GTRecipes; import com.gregtechceu.gtceu.config.ConfigHolder; +import com.gregtechceu.gtceu.data.loader.DeferredOwnerUnwrappingHolderLookupAdapter; import com.gregtechceu.gtceu.data.pack.GTDynamicDataPack; import com.gregtechceu.gtceu.data.recipe.GTCraftingComponents; import com.gregtechceu.gtceu.data.recipe.builder.GTRecipeBuilder; @@ -18,6 +19,7 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.recipes.RecipeBuilder; import net.minecraft.data.recipes.RecipeOutput; +import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.crafting.*; import net.neoforged.neoforge.common.conditions.ConditionalOps; @@ -25,6 +27,7 @@ import net.neoforged.neoforge.common.conditions.WithConditions; import com.google.gson.JsonElement; +import com.mojang.serialization.JsonOps; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -42,12 +45,21 @@ private DynamicRecipeHandler() {} // reload time spent in handleRecipesEarly, in milliseconds. private static final AtomicLong earlyLoadElapsed = new AtomicLong(); - public static void handleRecipesEarly(Map map, HolderLookup.Provider registries, - final ConditionalOps serializationContext) { + public static void handleRecipesEarly(Map recipes, + HolderLookup.Provider registryLookup, + ICondition.IContext conditionContext) { long startTime = System.currentTimeMillis(); + // this has to be final, so... + final ConditionalOps serializationContext; + { + // using a block here removes the possibility of accidentally using the context without condition support. + RegistryOps registryOps = RegistryOps.create(JsonOps.INSTANCE, + new DeferredOwnerUnwrappingHolderLookupAdapter(registryLookup)); + serializationContext = new ConditionalOps<>(registryOps, conditionContext); + } // first, remove old recipes & clear caches - GTRecipes.recipeRemoval(map::remove); + GTRecipes.recipeRemoval(recipes::remove); SteamBoilerLogic.clearBoilerRecipeCaches(); GTCraftingComponents.init(); @@ -65,7 +77,7 @@ public void accept(@NotNull ResourceLocation id, @NotNull Recipe recipe, JsonElement recipeJson = Recipe.CONDITIONAL_CODEC .encodeStart(serializationContext, Optional.of(new WithConditions<>(recipe, conditions))) .getOrThrow(); - map.put(id, recipeJson); + recipes.put(id, recipeJson); if (ConfigHolder.INSTANCE.dev.dumpRecipes) { // add the recipe JSON to the generated datapack if data dumping is enabled so it can be dumped diff --git a/src/main/java/com/gregtechceu/gtceu/data/loader/DeferredOwnerUnwrappingHolderLookupAdapter.java b/src/main/java/com/gregtechceu/gtceu/data/loader/DeferredOwnerUnwrappingHolderLookupAdapter.java new file mode 100644 index 00000000000..a13bf9cbb50 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/data/loader/DeferredOwnerUnwrappingHolderLookupAdapter.java @@ -0,0 +1,54 @@ +package com.gregtechceu.gtceu.data.loader; + + +import net.minecraft.core.HolderLookup; +import net.minecraft.core.HolderOwner; +import net.minecraft.core.Registry; +import net.minecraft.resources.RegistryOps; +import net.minecraft.resources.ResourceKey; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +public class DeferredOwnerUnwrappingHolderLookupAdapter implements RegistryOps.RegistryInfoLookup { + public final HolderLookup.Provider lookupProvider; + private final Map>, + Optional>> lookups = new ConcurrentHashMap<>(); + + public DeferredOwnerUnwrappingHolderLookupAdapter(HolderLookup.Provider lookupProvider) { + this.lookupProvider = lookupProvider; + } + + @SuppressWarnings("unchecked") + @Override + public Optional> lookup(ResourceKey> registryKey) { + return (Optional>) this.lookups.computeIfAbsent(registryKey, this::createLookup); + } + + // the special sauce + private Optional> createLookup(ResourceKey> registryKey) { + return this.lookupProvider.lookup(registryKey).map(registryLookup -> { + // unwrap the real holder *owner* from whatever delegates it might be buried in so using + // RegistryFileCodec#encode works with this RegistryOps + HolderOwner owner = registryLookup; + while (owner instanceof HolderLookup.RegistryLookup.Delegate delegate) { + owner = delegate.parent(); + } + // still hand vanilla the original holder *getter* so adding entries works if this is a tag adding lookup + return new RegistryOps.RegistryInfo<>(owner, registryLookup, registryLookup.registryLifecycle()); + }); + } + + @Override + public boolean equals(Object other) { + if (this == other) return true; + return other instanceof DeferredOwnerUnwrappingHolderLookupAdapter holderLookupAdapter + && this.lookupProvider.equals(holderLookupAdapter.lookupProvider); + } + + @Override + public int hashCode() { + return this.lookupProvider.hashCode(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/data/loader/PostRegistryListener.java b/src/main/java/com/gregtechceu/gtceu/data/loader/PostRegistryListener.java index 8f98a3d3357..3daf3f47489 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/loader/PostRegistryListener.java +++ b/src/main/java/com/gregtechceu/gtceu/data/loader/PostRegistryListener.java @@ -11,9 +11,6 @@ import net.minecraft.server.packs.resources.ResourceManagerReloadListener; import net.neoforged.neoforge.resource.ContextAwareReloadListener; -import org.jetbrains.annotations.NotNullByDefault; - -@NotNullByDefault public class PostRegistryListener extends ContextAwareReloadListener implements ResourceManagerReloadListener { public static final PostRegistryListener INSTANCE = new PostRegistryListener(); diff --git a/src/main/java/com/gregtechceu/gtceu/data/loader/package-info.java b/src/main/java/com/gregtechceu/gtceu/data/loader/package-info.java new file mode 100644 index 00000000000..e790ffb39e2 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/data/loader/package-info.java @@ -0,0 +1,4 @@ +@NotNullByDefault +package com.gregtechceu.gtceu.data.loader; + +import org.jetbrains.annotations.NotNullByDefault; From ff8f21e8037bf9a0f00917dbd6c9873970d50cd2 Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Fri, 7 Aug 2026 18:31:12 +0300 Subject: [PATCH 16/19] Fix "tag not in data packs" warnings --- .../com/gregtechceu/gtceu/data/tags/BlockTagLoader.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/gregtechceu/gtceu/data/tags/BlockTagLoader.java b/src/main/java/com/gregtechceu/gtceu/data/tags/BlockTagLoader.java index 24392760845..a8f2c79cf24 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/tags/BlockTagLoader.java +++ b/src/main/java/com/gregtechceu/gtceu/data/tags/BlockTagLoader.java @@ -32,7 +32,6 @@ public static void init(RegistrateTagsProvider.IntrinsicImpl provider) { provider.addTag(CustomTags.NEEDS_NEUTRONIUM_TOOL); provider.addTag(CustomTags.NEEDS_DURANIUM_TOOL); - @SuppressWarnings("unchecked") TagKey[] newToolRequirements = new TagKey[] { CustomTags.NEEDS_NEUTRONIUM_TOOL, @@ -54,6 +53,12 @@ public static void init(RegistrateTagsProvider.IntrinsicImpl provider) { provider.addTag(CustomTags.INCORRECT_FOR_NEUTRONIUM_TOOL); provider.addTag(CustomTags.INCORRECT_FOR_DURANIUM_TOOL).addTag(CustomTags.NEEDS_NEUTRONIUM_TOOL); + provider.addTag(CustomTags.MINEABLE_WITH_SAW).addTag(BlockTags.ICE); + // create empty tag files for the (currently) unused ones so MC is happy + provider.addTag(CustomTags.MINEABLE_WITH_HAMMER); + provider.addTag(CustomTags.MINEABLE_WITH_CROWBAR); + provider.addTag(CustomTags.MINEABLE_WITH_KNIFE); + // this is awful. I don't care, though. provider.addTag(BlockTags.REPLACEABLE) .add(GTMaterials.Oil.getFluid().defaultFluidState().createLegacyBlock().getBlock()) From 55170e7a24f9acf6f3780aef6d68f8e728c833d8 Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Fri, 7 Aug 2026 18:31:39 +0300 Subject: [PATCH 17/19] Add waxed copper doors to cleanroom doors tag --- .../com/gregtechceu/gtceu/data/tags/BlockTagLoader.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/gregtechceu/gtceu/data/tags/BlockTagLoader.java b/src/main/java/com/gregtechceu/gtceu/data/tags/BlockTagLoader.java index a8f2c79cf24..ad719353c03 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/tags/BlockTagLoader.java +++ b/src/main/java/com/gregtechceu/gtceu/data/tags/BlockTagLoader.java @@ -100,6 +100,12 @@ public static void init(RegistrateTagsProvider.IntrinsicImpl provider) { .addTag(Tags.Blocks.SANDS).addTag(BlockTags.SAND) // any sand blocks .addTag(BlockTags.TERRACOTTA); // any terracotta - provider.addTag(CustomTags.CLEANROOM_DOORS).add(Blocks.IRON_DOOR).addTag(BlockTags.WOODEN_DOORS); + provider.addTag(CustomTags.CLEANROOM_DOORS) + .add(Blocks.IRON_DOOR).addTag(BlockTags.WOODEN_DOORS) + // disallow unwaxed copper doors specifically + .add(Blocks.WAXED_COPPER_DOOR, + Blocks.WAXED_EXPOSED_COPPER_DOOR, + Blocks.WAXED_WEATHERED_COPPER_DOOR, + Blocks.WAXED_OXIDIZED_COPPER_DOOR); } } From 24f9d61d5ab95d4b2b5be2d5f699336365c97b9e Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Fri, 7 Aug 2026 18:32:15 +0300 Subject: [PATCH 18/19] Remove log spam from registries without dynamic tags printing "GregTech dynamic ... tag generation took 0ms" --- .../com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java index add795c3a74..732d0909936 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java @@ -52,6 +52,10 @@ public static void generateDynamicTags(Map Date: Sat, 15 Aug 2026 20:53:05 +0300 Subject: [PATCH 19/19] spotless + datagen --- .../data/c/tags/block/mineable/crowbar.json | 3 +++ .../data/c/tags/block/mineable/hammer.json | 3 +++ .../data/c/tags/block/mineable/knife.json | 3 +++ .../data/c/tags/block/mineable/saw.json | 5 +++++ .../resources/data/c/tags/item/dyes.json | 20 +++++++++++++++++++ .../resources/data/c/tags/item/lenses.json | 19 ++++++++++++++++++ .../data/c/tags/item/lenses/glass.json | 19 ++++++++++++++++++ .../resources/data/forge/tags/items/dyes.json | 20 ------------------- .../data/forge/tags/items/lenses.json | 19 ------------------ .../data/forge/tags/items/lenses/black.json | 5 ----- .../data/forge/tags/items/lenses/brown.json | 5 ----- .../data/forge/tags/items/lenses/cyan.json | 5 ----- .../data/forge/tags/items/lenses/glass.json | 19 ------------------ .../data/forge/tags/items/lenses/gray.json | 5 ----- .../forge/tags/items/lenses/light_gray.json | 5 ----- .../data/forge/tags/items/lenses/lime.json | 5 ----- .../data/forge/tags/items/lenses/magenta.json | 5 ----- .../data/forge/tags/items/lenses/orange.json | 5 ----- .../data/forge/tags/items/lenses/pink.json | 5 ----- .../data/forge/tags/items/lenses/yellow.json | 5 ----- .../gtceu/tags/block/cleanroom_doors.json | 6 +++++- .../data/gtceu/tags/items/lenses/blue.json | 5 ----- .../data/gtceu/tags/items/lenses/green.json | 5 ----- .../gtceu/tags/items/lenses/light_blue.json | 5 ----- .../data/gtceu/tags/items/lenses/purple.json | 5 ----- .../data/gtceu/tags/items/lenses/red.json | 5 ----- .../api/data/chemical/ChemicalHelper.java | 4 ++-- .../gtceu/api/data/tag/TagPrefix.java | 2 +- .../gtceu/api/data/tag/TagType.java | 3 ++- .../core/mixins/RecipeManagerLateMixin.java | 3 --- .../gtceu/data/GregTechDatagen.java | 2 -- .../data/dynamic/DynamicLootHandler.java | 13 +++++------- .../gtceu/data/dynamic/DynamicTagHandler.java | 2 +- .../gtceu/data/lang/LangHandler.java | 6 ------ ...redOwnerUnwrappingHolderLookupAdapter.java | 9 ++++----- .../gtceu/data/pack/GTDynamicDataPack.java | 2 +- .../kjs/builders/prefix/TagPrefixBuilder.java | 3 ++- 37 files changed, 95 insertions(+), 165 deletions(-) create mode 100644 src/generated/resources/data/c/tags/block/mineable/crowbar.json create mode 100644 src/generated/resources/data/c/tags/block/mineable/hammer.json create mode 100644 src/generated/resources/data/c/tags/block/mineable/knife.json create mode 100644 src/generated/resources/data/c/tags/block/mineable/saw.json create mode 100644 src/generated/resources/data/c/tags/item/dyes.json create mode 100644 src/generated/resources/data/c/tags/item/lenses.json create mode 100644 src/generated/resources/data/c/tags/item/lenses/glass.json delete mode 100644 src/generated/resources/data/forge/tags/items/dyes.json delete mode 100644 src/generated/resources/data/forge/tags/items/lenses.json delete mode 100644 src/generated/resources/data/forge/tags/items/lenses/black.json delete mode 100644 src/generated/resources/data/forge/tags/items/lenses/brown.json delete mode 100644 src/generated/resources/data/forge/tags/items/lenses/cyan.json delete mode 100644 src/generated/resources/data/forge/tags/items/lenses/glass.json delete mode 100644 src/generated/resources/data/forge/tags/items/lenses/gray.json delete mode 100644 src/generated/resources/data/forge/tags/items/lenses/light_gray.json delete mode 100644 src/generated/resources/data/forge/tags/items/lenses/lime.json delete mode 100644 src/generated/resources/data/forge/tags/items/lenses/magenta.json delete mode 100644 src/generated/resources/data/forge/tags/items/lenses/orange.json delete mode 100644 src/generated/resources/data/forge/tags/items/lenses/pink.json delete mode 100644 src/generated/resources/data/forge/tags/items/lenses/yellow.json delete mode 100644 src/generated/resources/data/gtceu/tags/items/lenses/blue.json delete mode 100644 src/generated/resources/data/gtceu/tags/items/lenses/green.json delete mode 100644 src/generated/resources/data/gtceu/tags/items/lenses/light_blue.json delete mode 100644 src/generated/resources/data/gtceu/tags/items/lenses/purple.json delete mode 100644 src/generated/resources/data/gtceu/tags/items/lenses/red.json diff --git a/src/generated/resources/data/c/tags/block/mineable/crowbar.json b/src/generated/resources/data/c/tags/block/mineable/crowbar.json new file mode 100644 index 00000000000..f72d209df78 --- /dev/null +++ b/src/generated/resources/data/c/tags/block/mineable/crowbar.json @@ -0,0 +1,3 @@ +{ + "values": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/block/mineable/hammer.json b/src/generated/resources/data/c/tags/block/mineable/hammer.json new file mode 100644 index 00000000000..f72d209df78 --- /dev/null +++ b/src/generated/resources/data/c/tags/block/mineable/hammer.json @@ -0,0 +1,3 @@ +{ + "values": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/block/mineable/knife.json b/src/generated/resources/data/c/tags/block/mineable/knife.json new file mode 100644 index 00000000000..f72d209df78 --- /dev/null +++ b/src/generated/resources/data/c/tags/block/mineable/knife.json @@ -0,0 +1,3 @@ +{ + "values": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/block/mineable/saw.json b/src/generated/resources/data/c/tags/block/mineable/saw.json new file mode 100644 index 00000000000..ad211a820b2 --- /dev/null +++ b/src/generated/resources/data/c/tags/block/mineable/saw.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#minecraft:ice" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/dyes.json b/src/generated/resources/data/c/tags/item/dyes.json new file mode 100644 index 00000000000..6feacc47d99 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/dyes.json @@ -0,0 +1,20 @@ +{ + "values": [ + "gtceu:chemical_white_dye", + "gtceu:chemical_orange_dye", + "gtceu:chemical_magenta_dye", + "gtceu:chemical_light_blue_dye", + "gtceu:chemical_yellow_dye", + "gtceu:chemical_lime_dye", + "gtceu:chemical_pink_dye", + "gtceu:chemical_gray_dye", + "gtceu:chemical_light_gray_dye", + "gtceu:chemical_cyan_dye", + "gtceu:chemical_purple_dye", + "gtceu:chemical_blue_dye", + "gtceu:chemical_brown_dye", + "gtceu:chemical_green_dye", + "gtceu:chemical_red_dye", + "gtceu:chemical_black_dye" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/lenses.json b/src/generated/resources/data/c/tags/item/lenses.json new file mode 100644 index 00000000000..98066efcbad --- /dev/null +++ b/src/generated/resources/data/c/tags/item/lenses.json @@ -0,0 +1,19 @@ +{ + "values": [ + "gtceu:orange_glass_lens", + "gtceu:magenta_glass_lens", + "gtceu:light_blue_glass_lens", + "gtceu:yellow_glass_lens", + "gtceu:lime_glass_lens", + "gtceu:pink_glass_lens", + "gtceu:gray_glass_lens", + "gtceu:light_gray_glass_lens", + "gtceu:cyan_glass_lens", + "gtceu:purple_glass_lens", + "gtceu:blue_glass_lens", + "gtceu:brown_glass_lens", + "gtceu:green_glass_lens", + "gtceu:red_glass_lens", + "gtceu:black_glass_lens" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/lenses/glass.json b/src/generated/resources/data/c/tags/item/lenses/glass.json new file mode 100644 index 00000000000..98066efcbad --- /dev/null +++ b/src/generated/resources/data/c/tags/item/lenses/glass.json @@ -0,0 +1,19 @@ +{ + "values": [ + "gtceu:orange_glass_lens", + "gtceu:magenta_glass_lens", + "gtceu:light_blue_glass_lens", + "gtceu:yellow_glass_lens", + "gtceu:lime_glass_lens", + "gtceu:pink_glass_lens", + "gtceu:gray_glass_lens", + "gtceu:light_gray_glass_lens", + "gtceu:cyan_glass_lens", + "gtceu:purple_glass_lens", + "gtceu:blue_glass_lens", + "gtceu:brown_glass_lens", + "gtceu:green_glass_lens", + "gtceu:red_glass_lens", + "gtceu:black_glass_lens" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/dyes.json b/src/generated/resources/data/forge/tags/items/dyes.json deleted file mode 100644 index b092e39a3f4..00000000000 --- a/src/generated/resources/data/forge/tags/items/dyes.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "values": [ - "gtceu:chemical_white_dye", - "gtceu:chemical_orange_dye", - "gtceu:chemical_magenta_dye", - "gtceu:chemical_light_blue_dye", - "gtceu:chemical_yellow_dye", - "gtceu:chemical_lime_dye", - "gtceu:chemical_pink_dye", - "gtceu:chemical_gray_dye", - "gtceu:chemical_light_gray_dye", - "gtceu:chemical_cyan_dye", - "gtceu:chemical_purple_dye", - "gtceu:chemical_blue_dye", - "gtceu:chemical_brown_dye", - "gtceu:chemical_green_dye", - "gtceu:chemical_red_dye", - "gtceu:chemical_black_dye" - ] -} diff --git a/src/generated/resources/data/forge/tags/items/lenses.json b/src/generated/resources/data/forge/tags/items/lenses.json deleted file mode 100644 index f562ddef957..00000000000 --- a/src/generated/resources/data/forge/tags/items/lenses.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "values": [ - "gtceu:orange_glass_lens", - "gtceu:magenta_glass_lens", - "gtceu:light_blue_glass_lens", - "gtceu:yellow_glass_lens", - "gtceu:lime_glass_lens", - "gtceu:pink_glass_lens", - "gtceu:gray_glass_lens", - "gtceu:light_gray_glass_lens", - "gtceu:cyan_glass_lens", - "gtceu:purple_glass_lens", - "gtceu:blue_glass_lens", - "gtceu:brown_glass_lens", - "gtceu:green_glass_lens", - "gtceu:red_glass_lens", - "gtceu:black_glass_lens" - ] -} diff --git a/src/generated/resources/data/forge/tags/items/lenses/black.json b/src/generated/resources/data/forge/tags/items/lenses/black.json deleted file mode 100644 index 784d39335c9..00000000000 --- a/src/generated/resources/data/forge/tags/items/lenses/black.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "gtceu:black_glass_lens" - ] -} diff --git a/src/generated/resources/data/forge/tags/items/lenses/brown.json b/src/generated/resources/data/forge/tags/items/lenses/brown.json deleted file mode 100644 index 611fbfd7703..00000000000 --- a/src/generated/resources/data/forge/tags/items/lenses/brown.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "gtceu:brown_glass_lens" - ] -} diff --git a/src/generated/resources/data/forge/tags/items/lenses/cyan.json b/src/generated/resources/data/forge/tags/items/lenses/cyan.json deleted file mode 100644 index 2495d0e8413..00000000000 --- a/src/generated/resources/data/forge/tags/items/lenses/cyan.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "gtceu:cyan_glass_lens" - ] -} diff --git a/src/generated/resources/data/forge/tags/items/lenses/glass.json b/src/generated/resources/data/forge/tags/items/lenses/glass.json deleted file mode 100644 index f562ddef957..00000000000 --- a/src/generated/resources/data/forge/tags/items/lenses/glass.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "values": [ - "gtceu:orange_glass_lens", - "gtceu:magenta_glass_lens", - "gtceu:light_blue_glass_lens", - "gtceu:yellow_glass_lens", - "gtceu:lime_glass_lens", - "gtceu:pink_glass_lens", - "gtceu:gray_glass_lens", - "gtceu:light_gray_glass_lens", - "gtceu:cyan_glass_lens", - "gtceu:purple_glass_lens", - "gtceu:blue_glass_lens", - "gtceu:brown_glass_lens", - "gtceu:green_glass_lens", - "gtceu:red_glass_lens", - "gtceu:black_glass_lens" - ] -} diff --git a/src/generated/resources/data/forge/tags/items/lenses/gray.json b/src/generated/resources/data/forge/tags/items/lenses/gray.json deleted file mode 100644 index 79f4d5c5bfa..00000000000 --- a/src/generated/resources/data/forge/tags/items/lenses/gray.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "gtceu:gray_glass_lens" - ] -} diff --git a/src/generated/resources/data/forge/tags/items/lenses/light_gray.json b/src/generated/resources/data/forge/tags/items/lenses/light_gray.json deleted file mode 100644 index 3b5fd9a2450..00000000000 --- a/src/generated/resources/data/forge/tags/items/lenses/light_gray.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "gtceu:light_gray_glass_lens" - ] -} diff --git a/src/generated/resources/data/forge/tags/items/lenses/lime.json b/src/generated/resources/data/forge/tags/items/lenses/lime.json deleted file mode 100644 index 4446b2cb7a5..00000000000 --- a/src/generated/resources/data/forge/tags/items/lenses/lime.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "gtceu:lime_glass_lens" - ] -} diff --git a/src/generated/resources/data/forge/tags/items/lenses/magenta.json b/src/generated/resources/data/forge/tags/items/lenses/magenta.json deleted file mode 100644 index c6e0fde7fca..00000000000 --- a/src/generated/resources/data/forge/tags/items/lenses/magenta.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "gtceu:magenta_glass_lens" - ] -} diff --git a/src/generated/resources/data/forge/tags/items/lenses/orange.json b/src/generated/resources/data/forge/tags/items/lenses/orange.json deleted file mode 100644 index d96b918b3b5..00000000000 --- a/src/generated/resources/data/forge/tags/items/lenses/orange.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "gtceu:orange_glass_lens" - ] -} diff --git a/src/generated/resources/data/forge/tags/items/lenses/pink.json b/src/generated/resources/data/forge/tags/items/lenses/pink.json deleted file mode 100644 index 92420825223..00000000000 --- a/src/generated/resources/data/forge/tags/items/lenses/pink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "gtceu:pink_glass_lens" - ] -} diff --git a/src/generated/resources/data/forge/tags/items/lenses/yellow.json b/src/generated/resources/data/forge/tags/items/lenses/yellow.json deleted file mode 100644 index f637bb522dd..00000000000 --- a/src/generated/resources/data/forge/tags/items/lenses/yellow.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "gtceu:yellow_glass_lens" - ] -} diff --git a/src/generated/resources/data/gtceu/tags/block/cleanroom_doors.json b/src/generated/resources/data/gtceu/tags/block/cleanroom_doors.json index 065692498ac..d04d629668e 100644 --- a/src/generated/resources/data/gtceu/tags/block/cleanroom_doors.json +++ b/src/generated/resources/data/gtceu/tags/block/cleanroom_doors.json @@ -1,6 +1,10 @@ { "values": [ "minecraft:iron_door", - "#minecraft:wooden_doors" + "#minecraft:wooden_doors", + "minecraft:waxed_copper_door", + "minecraft:waxed_exposed_copper_door", + "minecraft:waxed_weathered_copper_door", + "minecraft:waxed_oxidized_copper_door" ] } \ No newline at end of file diff --git a/src/generated/resources/data/gtceu/tags/items/lenses/blue.json b/src/generated/resources/data/gtceu/tags/items/lenses/blue.json deleted file mode 100644 index 29acddf8fe0..00000000000 --- a/src/generated/resources/data/gtceu/tags/items/lenses/blue.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "gtceu:blue_glass_lens" - ] -} diff --git a/src/generated/resources/data/gtceu/tags/items/lenses/green.json b/src/generated/resources/data/gtceu/tags/items/lenses/green.json deleted file mode 100644 index 3bdc5c2fc45..00000000000 --- a/src/generated/resources/data/gtceu/tags/items/lenses/green.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "gtceu:green_glass_lens" - ] -} diff --git a/src/generated/resources/data/gtceu/tags/items/lenses/light_blue.json b/src/generated/resources/data/gtceu/tags/items/lenses/light_blue.json deleted file mode 100644 index f3fc383fb97..00000000000 --- a/src/generated/resources/data/gtceu/tags/items/lenses/light_blue.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "gtceu:light_blue_glass_lens" - ] -} diff --git a/src/generated/resources/data/gtceu/tags/items/lenses/purple.json b/src/generated/resources/data/gtceu/tags/items/lenses/purple.json deleted file mode 100644 index 2700b502d24..00000000000 --- a/src/generated/resources/data/gtceu/tags/items/lenses/purple.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "gtceu:purple_glass_lens" - ] -} diff --git a/src/generated/resources/data/gtceu/tags/items/lenses/red.json b/src/generated/resources/data/gtceu/tags/items/lenses/red.json deleted file mode 100644 index b9216925055..00000000000 --- a/src/generated/resources/data/gtceu/tags/items/lenses/red.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "gtceu:red_glass_lens" - ] -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/ChemicalHelper.java b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/ChemicalHelper.java index aacc7f93cb4..7aa0534ef4e 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/ChemicalHelper.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/ChemicalHelper.java @@ -246,9 +246,9 @@ public static List getItems(MaterialEntry materialEntry) { }).stream().map(Supplier::get).collect(Collectors.toList()); } - public static @Nullable Item getItem(MaterialEntry materialEntry) { + public static Item getItem(MaterialEntry materialEntry) { List items = getItems(materialEntry); - if (items.isEmpty()) return null; + if (items.isEmpty()) return Items.AIR; return items.get(0).asItem(); } diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java index 98d65767e9c..ee4d4b68db0 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java @@ -244,7 +244,7 @@ public boolean isEmpty() { if (!mat.hasProperty(PropertyKey.ORE)) return false; Material washedIn = mat.getProperty(PropertyKey.ORE).getWashedIn().first(); return !washedIn.isNull(); - }, (path, mat) -> { + }, (path, mat) -> { Material washedIn = mat.getProperty(PropertyKey.ORE).getWashedIn().first(); return TagUtil.createItemTag(path.formatted(washedIn.getName())); }) diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagType.java b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagType.java index b281a1985a6..09429a8ea19 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagType.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagType.java @@ -22,7 +22,8 @@ public final class TagType { private boolean isParentTag = false; // this is now memoized because creating tag keys interns them and that's slow private final @NotNull BiFunction> formatter; - /* package-private */ @Nullable Predicate filter; + @Nullable + /* package-private */ Predicate filter; private TagType(BiFunction> formatter) { this.formatter = Util.memoize(formatter); diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerLateMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerLateMixin.java index 5c26b8d8e40..8e97a5239c2 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerLateMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/RecipeManagerLateMixin.java @@ -24,9 +24,6 @@ public RecipeManagerLateMixin(Gson gson, String directory) { super(gson, directory); } - @Shadow - public abstract void replaceRecipes(Iterable> recipes); - @Inject(method = "apply(Ljava/util/Map;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V", at = @At(value = "TAIL")) private void gtceu$handleDynamicRecipesLate(Map map, ResourceManager resourceManager, diff --git a/src/main/java/com/gregtechceu/gtceu/data/GregTechDatagen.java b/src/main/java/com/gregtechceu/gtceu/data/GregTechDatagen.java index 874393400f8..8401fd15fa3 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/GregTechDatagen.java +++ b/src/main/java/com/gregtechceu/gtceu/data/GregTechDatagen.java @@ -11,8 +11,6 @@ import com.gregtechceu.gtceu.data.tags.FluidTagLoader; import com.gregtechceu.gtceu.data.tags.ItemTagLoader; -import net.minecraft.data.DataProvider; - import com.tterrag.registrate.providers.ProviderType; public class GregTechDatagen { diff --git a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicLootHandler.java b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicLootHandler.java index 81cb73c0011..e35b8210b82 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicLootHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicLootHandler.java @@ -20,13 +20,11 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.storage.loot.IntRange; import net.minecraft.world.level.storage.loot.LootPool; import net.minecraft.world.level.storage.loot.LootTable; import net.minecraft.world.level.storage.loot.entries.LootItem; -import net.minecraft.world.level.storage.loot.functions.ApplyBonusCount; import net.minecraft.world.level.storage.loot.functions.ApplyExplosionDecay; import net.minecraft.world.level.storage.loot.functions.LimitCount; import net.minecraft.world.level.storage.loot.functions.SetItemCountFunction; @@ -78,7 +76,7 @@ private static void generateDynamicLoot0(final HolderLookup.Provider registries) GTMaterialBlocks.ITEM_PIPE_BLOCKS.rowMap().values().forEach((map) -> addMaterialBlockLootTables(map, helpers, serializationContext)); addMaterialBlockLootTables(GTMaterialBlocks.SURFACE_ROCK_BLOCKS, serializationContext, (material, block) -> { Item tinyDust = ChemicalHelper.getItem(TagPrefix.dustTiny, material); - if (tinyDust != null && tinyDust != Items.AIR) { + if (tinyDust != Items.AIR) { return helpers.createSilkTouchDispatchTable(block.get(), helpers.applyExplosionDecay(block, LootItem.lootTableItem(tinyDust) @@ -105,15 +103,15 @@ private static void generateDynamicLoot0(final HolderLookup.Provider registries) } private static void addMaterialBlockLootTables(Map> map, - VanillaBlockLoot blockLoot, - DynamicOps serializationContext) { + VanillaBlockLoot blockLoot, + DynamicOps serializationContext) { addMaterialBlockLootTables(map, serializationContext, (material, block) -> blockLoot.createSingleItemTable(block.get())); } private static void addMaterialBlockLootTables(Map> map, - DynamicOps serializationContext, - BiFunction, LootTable.Builder> lootTableBuilder) { + DynamicOps serializationContext, + BiFunction, LootTable.Builder> lootTableBuilder) { map.forEach((material, block) -> { ResourceLocation lootTableId = block.getId().withPrefix("blocks/"); ((BlockBehaviourAccessor) block.get()).setDrops(ResourceKey.create(Registries.LOOT_TABLE, lootTableId)); @@ -172,6 +170,5 @@ private static void generateOreBlockLoot(TagPrefix prefix, Material material, Bl .setParamSet(LootContextParamSets.BLOCK) .build(); GTDynamicDataPack.addLootTable(lootTableId, lootTable, serializationContext); - } } diff --git a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java index 732d0909936..d20d159ddad 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/dynamic/DynamicTagHandler.java @@ -171,7 +171,7 @@ private static void generateBlockTags(Map new ArrayList<>()).addAll(entries); if (!ConfigHolder.INSTANCE.machines.requireGTToolsForBlocks) { tags.computeIfAbsent(BlockTags.MINEABLE_WITH_AXE.location(), - path -> new ArrayList<>()) + path -> new ArrayList<>()) .addAll(entries); } } else { diff --git a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java index 20c2824b788..d8b4d0db599 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java @@ -612,12 +612,6 @@ public static void init(RegistrateLangProvider provider) { replace(provider, "item.gtceu.bucket", "%s Bucket"); - replace(provider, "block.gtceu.oil_heavy", "Heavy Oil"); - replace(provider, "block.gtceu.oil_light", "Light Oil"); - replace(provider, "block.gtceu.oil_medium", "Raw Oil"); - replace(provider, "block.gtceu.oil", "Oil"); - replace(provider, "block.gtceu.creosote", "Creosote"); - replace(provider, GTBlocks.BATTERY_EMPTY_TIER_I.get().getDescriptionId(), "Empty Tier I Capacitor"); replace(provider, GTBlocks.BATTERY_LAPOTRONIC_EV.get().getDescriptionId(), "EV Lapotronic Capacitor"); replace(provider, GTBlocks.BATTERY_LAPOTRONIC_IV.get().getDescriptionId(), "IV Lapotronic Capacitor"); diff --git a/src/main/java/com/gregtechceu/gtceu/data/loader/DeferredOwnerUnwrappingHolderLookupAdapter.java b/src/main/java/com/gregtechceu/gtceu/data/loader/DeferredOwnerUnwrappingHolderLookupAdapter.java index a13bf9cbb50..df71272b1a9 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/loader/DeferredOwnerUnwrappingHolderLookupAdapter.java +++ b/src/main/java/com/gregtechceu/gtceu/data/loader/DeferredOwnerUnwrappingHolderLookupAdapter.java @@ -1,6 +1,5 @@ package com.gregtechceu.gtceu.data.loader; - import net.minecraft.core.HolderLookup; import net.minecraft.core.HolderOwner; import net.minecraft.core.Registry; @@ -12,9 +11,9 @@ import java.util.concurrent.ConcurrentHashMap; public class DeferredOwnerUnwrappingHolderLookupAdapter implements RegistryOps.RegistryInfoLookup { + public final HolderLookup.Provider lookupProvider; - private final Map>, - Optional>> lookups = new ConcurrentHashMap<>(); + private final Map>, Optional>> lookups = new ConcurrentHashMap<>(); public DeferredOwnerUnwrappingHolderLookupAdapter(HolderLookup.Provider lookupProvider) { this.lookupProvider = lookupProvider; @@ -43,8 +42,8 @@ private Optional> createLookup(ResourceKey materialPredicate) { + public TagPrefixBuilder filteredUnformattedTag(String path, boolean isVanilla, + Predicate materialPredicate) { base.filteredUnformattedTag(path, isVanilla, materialPredicate); return this; }