From 1776f0b843beba2fce983b851e4eacdd0f7b6110 Mon Sep 17 00:00:00 2001 From: Ruben Taelman Date: Wed, 25 Dec 2024 20:48:44 +0100 Subject: [PATCH] Restore recipes in infobooks --- .../helper/CraftingHelpersCommon.java | 51 +++++----- .../cyclopscore/helper/ICraftingHelpers.java | 21 ++-- .../resources/META-INF/accesstransformer.cfg | 2 + .../main/resources/cyclopscore.accesswidener | 1 + .../resources/data/cyclopscore/info/test.xml | 1 + .../cyclopscore/CyclopsCoreNeoForge.java | 8 +- .../cyclopscore/helper/RecipeHelpers.java | 97 +++++++++++++++++++ .../infobook/IInfoBookRegistry.java | 2 + .../cyclopscore/infobook/InfoBookParser.java | 37 +++---- .../infobook/InfoBookRegistry.java | 40 ++------ .../pageelement/CraftingRecipeAppendix.java | 49 ++++++---- .../pageelement/FurnaceRecipeAppendix.java | 21 ++-- .../infobook/pageelement/RecipeAppendix.java | 15 ++- .../RegistryExportableRecipeAbstract.java | 2 +- .../packet/RequestRecipeDisplayPacket.java | 74 ++++++++++++++ .../RequestRecipeDisplaysRegexPacket.java | 72 ++++++++++++++ .../packet/SendRecipeDisplayPacket.java | 77 +++++++++++++++ .../SendRecipeDisplaysRegexDonePacket.java | 61 ++++++++++++ ...entProxy.java => ClientProxyNeoForge.java} | 6 +- ...monProxy.java => CommonProxyNeoForge.java} | 6 +- 20 files changed, 510 insertions(+), 133 deletions(-) create mode 100644 loader-neoforge/src/main/java/org/cyclops/cyclopscore/helper/RecipeHelpers.java create mode 100644 loader-neoforge/src/main/java/org/cyclops/cyclopscore/network/packet/RequestRecipeDisplayPacket.java create mode 100644 loader-neoforge/src/main/java/org/cyclops/cyclopscore/network/packet/RequestRecipeDisplaysRegexPacket.java create mode 100644 loader-neoforge/src/main/java/org/cyclops/cyclopscore/network/packet/SendRecipeDisplayPacket.java create mode 100644 loader-neoforge/src/main/java/org/cyclops/cyclopscore/network/packet/SendRecipeDisplaysRegexDonePacket.java rename loader-neoforge/src/main/java/org/cyclops/cyclopscore/proxy/{ClientProxy.java => ClientProxyNeoForge.java} (81%) rename loader-neoforge/src/main/java/org/cyclops/cyclopscore/proxy/{CommonProxy.java => CommonProxyNeoForge.java} (81%) diff --git a/loader-common/src/main/java/org/cyclops/cyclopscore/helper/CraftingHelpersCommon.java b/loader-common/src/main/java/org/cyclops/cyclopscore/helper/CraftingHelpersCommon.java index bd778e0f1b..f22031cc49 100644 --- a/loader-common/src/main/java/org/cyclops/cyclopscore/helper/CraftingHelpersCommon.java +++ b/loader-common/src/main/java/org/cyclops/cyclopscore/helper/CraftingHelpersCommon.java @@ -3,19 +3,21 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; -import net.minecraft.client.Minecraft; +import com.google.common.collect.Lists; import net.minecraft.core.NonNullList; -import net.minecraft.core.RegistryAccess; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.*; +import net.minecraft.world.item.crafting.display.RecipeDisplayEntry; import net.minecraft.world.level.Level; +import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Triple; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -40,58 +42,49 @@ public CraftingHelpersCommon(IModHelpers modHelpers) { this.modHelpers = modHelpers; } - @Override - public > List> findRecipes(Level world, RecipeType recipeType) { - return world.isClientSide() ? getClientRecipes(recipeType) : findServerRecipes((ServerLevel) world, recipeType); - } - @Override public RecipeManager getRecipeManager() { - return modHelpers.getMinecraftHelpers().isClientSide() - ? (RecipeManager) Minecraft.getInstance().getConnection().recipes() - : Objects.requireNonNull(modHelpers.getMinecraftHelpers().getCurrentServer().getLevel(Level.OVERWORLD), "Server is still loading").recipeAccess(); + return Objects.requireNonNull(modHelpers.getMinecraftHelpers().getCurrentServer().getLevel(Level.OVERWORLD), "Server is still loading").recipeAccess(); } @Override - public > Optional> getServerRecipe(RecipeType recipeType, ResourceKey> recipeName) { + public > Optional> getRecipe(RecipeType recipeType, ResourceKey> recipeName) { return Optional.ofNullable(getRecipeManager().byKeyTyped(recipeType, recipeName)); } @Override - public > Optional> findServerRecipe(RecipeType recipeType, C container, Level world) { + public > Optional> findRecipe(RecipeType recipeType, C container, Level world) { return ((RecipeManager) world.recipeAccess()).getRecipeFor(recipeType, container, world); } @Override - public > List> findServerRecipes(RecipeType recipeType) { - return findServerRecipes(Objects.requireNonNull(modHelpers.getMinecraftHelpers().getCurrentServer().getLevel(Level.OVERWORLD)), recipeType); + public > List> findRecipes(RecipeType recipeType) { + return findRecipes(Objects.requireNonNull(modHelpers.getMinecraftHelpers().getCurrentServer().getLevel(Level.OVERWORLD)), recipeType); } @Override - public > List> findServerRecipes(ServerLevel world, RecipeType recipeType) { + public > List> findRecipes(ServerLevel world, RecipeType recipeType) { return (List>) (List) world.recipeAccess().recipes.byType(recipeType); } @Override - public > Optional> getClientRecipe(RecipeType recipeType, ResourceKey> recipeName) { - return Optional.ofNullable(getRecipeManager().byKeyTyped(recipeType, recipeName)); - } - - @Override - public > List> getClientRecipes(RecipeType recipeType) { - return (List>) (List) getRecipeManager().recipes.byType(recipeType); + public List getRecipeDisplays(RecipeType recipeType, ResourceKey> recipeName) { + List displays = Lists.newArrayList(); + modHelpers.getMinecraftHelpers().getCurrentServer().overworld().recipeAccess().listDisplaysForRecipe(recipeName, displays::add); + return displays; } @Override - public > RecipeHolder findClientRecipe(RegistryAccess registryAccess, ItemStack itemStack, RecipeType recipeType, C recipeInput, int index) throws IllegalArgumentException { - int indexAttempt = index; - for(RecipeHolder recipe : getClientRecipes(recipeType)) { - if(ItemStack.isSameItemSameComponents(recipe.value().assemble(recipeInput, registryAccess), itemStack) && indexAttempt-- == 0) { - return recipe; + public List> getRecipeDisplays(RecipeType recipeType, String recipeNameRegex) { + List> displays = Lists.newArrayList(); + for (Map.Entry>, List> entry : modHelpers.getMinecraftHelpers().getCurrentServer().overworld().recipeAccess().recipeToDisplay.entrySet()) { + if (recipeNameRegex.isEmpty() || entry.getKey().location().toString().matches(recipeNameRegex)) { + for (RecipeManager.ServerDisplayInfo display : entry.getValue()) { + displays.add(Pair.of(display.parent().id().location(), display.display())); + } } } - throw new IllegalArgumentException("Could not find recipe for " + itemStack + "::" - + itemStack.getComponents() + " with index " + index); + return displays; } @Override diff --git a/loader-common/src/main/java/org/cyclops/cyclopscore/helper/ICraftingHelpers.java b/loader-common/src/main/java/org/cyclops/cyclopscore/helper/ICraftingHelpers.java index d0cbaa06a9..c9332552eb 100644 --- a/loader-common/src/main/java/org/cyclops/cyclopscore/helper/ICraftingHelpers.java +++ b/loader-common/src/main/java/org/cyclops/cyclopscore/helper/ICraftingHelpers.java @@ -1,11 +1,12 @@ package org.cyclops.cyclopscore.helper; -import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.*; +import net.minecraft.world.item.crafting.display.RecipeDisplayEntry; import net.minecraft.world.level.Level; +import org.apache.commons.lang3.tuple.Pair; import java.util.List; import java.util.Optional; @@ -15,23 +16,19 @@ */ public interface ICraftingHelpers { - public > List> findRecipes(Level world, RecipeType recipeType); - public RecipeManager getRecipeManager(); - public > Optional> getServerRecipe(RecipeType recipeType, ResourceKey> recipeName); - - public > Optional> findServerRecipe(RecipeType recipeType, C container, Level world); + public > Optional> getRecipe(RecipeType recipeType, ResourceKey> recipeName); - public > List> findServerRecipes(RecipeType recipeType); + public > Optional> findRecipe(RecipeType recipeType, C container, Level world); - public > List> findServerRecipes(ServerLevel world, RecipeType recipeType); + public > List> findRecipes(RecipeType recipeType); - public > Optional> getClientRecipe(RecipeType recipeType, ResourceKey> recipeName); + public > List> findRecipes(ServerLevel world, RecipeType recipeType); - public > List> getClientRecipes(RecipeType recipeType); + public List getRecipeDisplays(RecipeType recipeType, ResourceKey> recipeName); - public > RecipeHolder findClientRecipe(RegistryAccess registryAccess, ItemStack itemStack, RecipeType recipeType, C recipeInput, int index) throws IllegalArgumentException; + public List> getRecipeDisplays(RecipeType recipeType, String recipeNameRegex); /** * A cache-based variant of {@link net.minecraft.world.item.crafting.RecipeManager#getRecipeFor(RecipeType, RecipeInput, Level)}. diff --git a/loader-common/src/main/resources/META-INF/accesstransformer.cfg b/loader-common/src/main/resources/META-INF/accesstransformer.cfg index 76b0e9fdde..fbd5866669 100644 --- a/loader-common/src/main/resources/META-INF/accesstransformer.cfg +++ b/loader-common/src/main/resources/META-INF/accesstransformer.cfg @@ -3,6 +3,8 @@ public net.minecraft.world.item.crafting.RecipeManager byKeyTyped(Lnet/minecraft public net.minecraft.world.item.crafting.RecipeManager m_320711_(Lnet/minecraft/world/item/crafting/RecipeType;Lnet/minecraft/resources/ResourceKey;)Lnet/minecraft/world/item/crafting/RecipeHolder; # byKeyTyped public net.minecraft.world.item.crafting.RecipeManager recipes public net.minecraft.world.item.crafting.RecipeManager f_346395_ # recipes +public net.minecraft.world.item.crafting.RecipeManager recipeToDisplay +public net.minecraft.world.item.crafting.RecipeManager f_346716_ # recipeToDisplay # Keybindings public net.minecraft.client.KeyMapping ALL diff --git a/loader-common/src/main/resources/cyclopscore.accesswidener b/loader-common/src/main/resources/cyclopscore.accesswidener index efe3f1010e..1cad70a23c 100644 --- a/loader-common/src/main/resources/cyclopscore.accesswidener +++ b/loader-common/src/main/resources/cyclopscore.accesswidener @@ -3,6 +3,7 @@ accessWidener v1 named # Recipes accessible method net/minecraft/world/item/crafting/RecipeManager byKeyTyped (Lnet/minecraft/world/item/crafting/RecipeType;Lnet/minecraft/resources/ResourceKey;)Lnet/minecraft/world/item/crafting/RecipeHolder; accessible field net/minecraft/world/item/crafting/RecipeManager recipes Lnet/minecraft/world/item/crafting/RecipeMap; +accessible field net/minecraft/world/item/crafting/RecipeManager recipeToDisplay Ljava/util/Map; # Screens accessible method net/minecraft/client/gui/screens/Screen addRenderableWidget (Lnet/minecraft/client/gui/components/events/GuiEventListener;)Lnet/minecraft/client/gui/components/events/GuiEventListener; diff --git a/loader-common/src/main/resources/data/cyclopscore/info/test.xml b/loader-common/src/main/resources/data/cyclopscore/info/test.xml index 0a6c54415d..8a485b51b4 100644 --- a/loader-common/src/main/resources/data/cyclopscore/info/test.xml +++ b/loader-common/src/main/resources/data/cyclopscore/info/test.xml @@ -10,5 +10,6 @@ Hi! Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam egestas nisl vel lorem rhoncus consectetur. Donec ut semper arcu. Etiam suscipit, ex ac varius accumsan, dolor nisi consectetur mauris, pellentesque viverra erat dolor eu turpis. Aliquam dictum, risus aliquet congue scelerisque, nunc elit ullamcorper ante, sit amet vehicula purus purus et nulla. Donec risus neque, ultrices at metus sed, pellentesque imperdiet mi. Etiam imperdiet lectus fermentum, consequat mi et, eleifend elit. Duis felis diam, efficitur id diam et, lacinia elementum libero. Maecenas rutrum nisl tellus, a condimentum elit facilisis sed. Fusce massa ipsum, pharetra vel dui a, molestie congue nulla. Etiam maximus vehicula erat maximus tempor. Cras non commodo nisi. Fusce elementum fringilla lacus et rutrum. Proin viverra et augue sit amet malesuada. Phasellus justo sem, pretium nec sem id, molestie scelerisque massa. Aenean id mauris a ligula finibus faucibus. In varius, felis molestie luctus imperdiet, nisi risus elementum lacus, sed aliquam nisi neque vel felis. Morbi et massa neque. Vivamus imperdiet commodo imperdiet. Vivamus id est a diam dapibus convallis volutpat sit amet mauris. Fusce gravida quam et metus lacinia accumsan. Aliquam a consectetur ligula. Pellentesque ut lobortis turpis, nec vulputate lacus. + minecraft:acacia_.* \ No newline at end of file diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/CyclopsCoreNeoForge.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/CyclopsCoreNeoForge.java index 9b4cb2c1cc..b06af50179 100644 --- a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/CyclopsCoreNeoForge.java +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/CyclopsCoreNeoForge.java @@ -41,8 +41,8 @@ import org.cyclops.cyclopscore.modcompat.curios.ModCompatCurios; import org.cyclops.cyclopscore.network.PacketCodecsNeoForge; import org.cyclops.cyclopscore.persist.nbt.NBTClassTypesNeoForge; -import org.cyclops.cyclopscore.proxy.ClientProxy; -import org.cyclops.cyclopscore.proxy.CommonProxy; +import org.cyclops.cyclopscore.proxy.ClientProxyNeoForge; +import org.cyclops.cyclopscore.proxy.CommonProxyNeoForge; import org.cyclops.cyclopscore.proxy.IClientProxy; import org.cyclops.cyclopscore.proxy.ICommonProxy; import org.cyclops.cyclopscore.tracking.ImportantUsers; @@ -78,13 +78,13 @@ public CyclopsCoreNeoForge(IEventBus modEventBus) { @Override @OnlyIn(Dist.CLIENT) protected IClientProxy constructClientProxy() { - return new ClientProxy(); + return new ClientProxyNeoForge(); } @Override @OnlyIn(Dist.DEDICATED_SERVER) protected ICommonProxy constructCommonProxy() { - return new CommonProxy(); + return new CommonProxyNeoForge(); } @Override diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/helper/RecipeHelpers.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/helper/RecipeHelpers.java new file mode 100644 index 0000000000..1eb156fc07 --- /dev/null +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/helper/RecipeHelpers.java @@ -0,0 +1,97 @@ +package org.cyclops.cyclopscore.helper; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.item.crafting.display.RecipeDisplayEntry; +import org.apache.commons.lang3.tuple.Pair; +import org.cyclops.cyclopscore.CyclopsCoreNeoForge; +import org.cyclops.cyclopscore.infobook.IInfoBookRegistry; +import org.cyclops.cyclopscore.network.packet.RequestRecipeDisplayPacket; +import org.cyclops.cyclopscore.network.packet.RequestRecipeDisplaysRegexPacket; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author rubensworks + */ +public class RecipeHelpers { + + public static final Map, ResourceLocation>, RecipeDisplayEntry> CLIENT_RECIPE_DISPLAYS = Maps.newHashMap(); + private static final Set, ResourceLocation>> CLIENT_RECIPE_DISPLAYS_REQUESTING = Sets.newHashSet(); + private static final Set, String>> CLIENT_RECIPE_DISPLAYS_REGEX_REQUESTING = Sets.newHashSet(); + private static final Set, String>> CLIENT_RECIPE_DISPLAYS_REGEX_DONE = Sets.newHashSet(); + + public static void reset() { + CLIENT_RECIPE_DISPLAYS.clear(); + CLIENT_RECIPE_DISPLAYS_REQUESTING.clear(); + CLIENT_RECIPE_DISPLAYS_REGEX_REQUESTING.clear(); + CLIENT_RECIPE_DISPLAYS_REGEX_DONE.clear(); + } + + public static void requestRecipeDisplay(RecipeType recipeType, ResourceLocation recipe) { + Pair, ResourceLocation> key = Pair.of(recipeType, recipe); + if (!CLIENT_RECIPE_DISPLAYS.containsKey(key) && !CLIENT_RECIPE_DISPLAYS_REQUESTING.contains(key)) { + CLIENT_RECIPE_DISPLAYS_REQUESTING.add(key); + CyclopsCoreNeoForge._instance.getPacketHandler().sendToServer(new RequestRecipeDisplayPacket(recipeType, recipe)); + } + } + + public static void requestRecipeDisplays(RecipeType recipeType, String recipeRegex) { + Pair, String> key = Pair.of(recipeType, recipeRegex); + if (!CLIENT_RECIPE_DISPLAYS_REGEX_REQUESTING.contains(key)) { + CLIENT_RECIPE_DISPLAYS_REGEX_REQUESTING.add(key); + CyclopsCoreNeoForge._instance.getPacketHandler().sendToServer(new RequestRecipeDisplaysRegexPacket(recipeType, recipeRegex)); + } + } + + public static void setRecipeDisplay(RecipeType recipeType, ResourceLocation recipe, RecipeDisplayEntry recipeDisplay) { + CLIENT_RECIPE_DISPLAYS.put(Pair.of(recipeType, recipe), recipeDisplay); + } + + @Nullable + public static RecipeDisplayEntry getRecipeDisplay(RecipeType recipeType, ResourceLocation recipe) { + if (!IModHelpers.get().getMinecraftHelpers().isClientSide()) { + return null; + } + + requestRecipeDisplay(recipeType, recipe); + + Pair, ResourceLocation> key = Pair.of(recipeType, recipe); + return CLIENT_RECIPE_DISPLAYS.get(key); + } + + public static List getRecipeDisplays(RecipeType recipeType, String recipeRegex) { + if (!IModHelpers.get().getMinecraftHelpers().isClientSide()) { + return Lists.newArrayList(); + } + + requestRecipeDisplays(recipeType, recipeRegex); + + List displays = Lists.newArrayList(); + for (Map.Entry, ResourceLocation>, RecipeDisplayEntry> entry : CLIENT_RECIPE_DISPLAYS.entrySet()) { + if (entry.getKey().getLeft() == recipeType && (recipeRegex.isEmpty() || entry.getKey().getRight().toString().matches(recipeRegex))) { + displays.add(entry.getValue()); + } + } + return displays; + } + + public static void setRecipeDisplaysRegexDone(RecipeType value, String recipe) { + CLIENT_RECIPE_DISPLAYS_REGEX_DONE.add(Pair.of(value, recipe)); + + // Re-initialize all books once all regex requests are done + if (!RecipeHelpers.areRecipeDisplayRegexRequestsPending()) { + CyclopsCoreNeoForge._instance.getRegistryManager().getRegistry(IInfoBookRegistry.class).initializeAllBooks(); + } + } + + public static boolean areRecipeDisplayRegexRequestsPending() { + return CLIENT_RECIPE_DISPLAYS_REGEX_REQUESTING.size() > CLIENT_RECIPE_DISPLAYS_REGEX_DONE.size(); + } +} diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/IInfoBookRegistry.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/IInfoBookRegistry.java index 7d1c2921fb..9097cb8c83 100644 --- a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/IInfoBookRegistry.java +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/IInfoBookRegistry.java @@ -32,4 +32,6 @@ public interface IInfoBookRegistry extends IRegistry { */ public InfoSection getRoot(IInfoBook infoBook); + public void initializeAllBooks(); + } diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/InfoBookParser.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/InfoBookParser.java index dfca659bb3..872d3f3d38 100644 --- a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/InfoBookParser.java +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/InfoBookParser.java @@ -6,17 +6,20 @@ import net.minecraft.core.Holder; import net.minecraft.core.NonNullList; import net.minecraft.core.registries.BuiltInRegistries; -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.crafting.*; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeInput; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.item.crafting.display.RecipeDisplayEntry; import net.minecraft.world.level.material.Fluid; import net.neoforged.neoforge.fluids.FluidStack; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.util.Strings; -import org.cyclops.cyclopscore.helper.IModHelpers; import org.cyclops.cyclopscore.helper.IModHelpersNeoForge; +import org.cyclops.cyclopscore.helper.RecipeHelpers; import org.cyclops.cyclopscore.infobook.condition.*; import org.cyclops.cyclopscore.infobook.pageelement.*; import org.cyclops.cyclopscore.init.ModBaseNeoForge; @@ -33,6 +36,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.*; +import java.util.function.Supplier; /** * XML parser which will generate the infobook. @@ -146,16 +150,11 @@ public List create(IInfoBook infoBook, Element node) throws Inv if (recipeType == null) { throw new InvalidAppendixException("Could not find a recipe type: " + type); } - RecipeManager recipeManager = IModHelpers.get().getCraftingHelpers().getRecipeManager(); - Collection recipes = recipeManager.recipes.byType((RecipeType) recipeType); String idRegexString = node.getTextContent().trim(); - - for (RecipeHolder> recipeHolder : recipes) { + for (RecipeDisplayEntry recipeDisplay : RecipeHelpers.getRecipeDisplays(recipeType, idRegexString)) { try { - if (idRegexString.isEmpty() || recipeHolder.toString().matches(idRegexString)) { - appendixList.add(createAppendix(infoBook, type, recipeHolder)); - } + appendixList.add(createAppendix(infoBook, type, () -> recipeDisplay)); } catch (InvalidAppendixException e) { // Skip this appendix. e.setState(infoBook, null); @@ -239,15 +238,9 @@ public static void registerAppendixItemFactory(String name, IAppendixItemFactory public static > void registerAppendixRecipeFactories(RecipeType recipeType, IAppendixItemFactory factory) { String name = BuiltInRegistries.RECIPE_TYPE.getKey(recipeType).toString(); registerAppendixFactory(name, (infoBook, node) -> { - // TODO: rewrite using RecipeDisplayEntry (see ClientRecipeBook) - ResourceKey> recipeId = ResourceKey.create(ResourceKey.createRegistryKey(BuiltInRegistries.RECIPE_TYPE.getKey(recipeType)), getNodeResourceLocation(node)); - Optional> recipe = infoBook.getMod().getModHelpers().getMinecraftHelpers().isClientSide() - ? IModHelpers.get().getCraftingHelpers().getClientRecipe(recipeType, recipeId) - : IModHelpers.get().getCraftingHelpers().getServerRecipe(recipeType, recipeId); - if (!recipe.isPresent()) { - throw new InvalidAppendixException("Could not find " + name + " recipe for " + recipeId); - } - return factory.create(infoBook, recipe.get()); + ResourceLocation recipe = getNodeResourceLocation(node); + RecipeHelpers.requestRecipeDisplay(recipeType, recipe); + return factory.create(infoBook, () -> RecipeHelpers.getRecipeDisplay(recipeType, recipe)); }); registerAppendixItemFactory(name, factory); } @@ -671,13 +664,13 @@ protected static SectionAppendix createAppendix(IInfoBook infoBook, String type, return factory.create(infoBook, node); } - protected static SectionAppendix createAppendix(IInfoBook infoBook, String type, RecipeHolder> recipe) throws InvalidAppendixException { + protected static SectionAppendix createAppendix(IInfoBook infoBook, String type, Supplier recipeDisplay) throws InvalidAppendixException { if(type == null) type = ""; IAppendixItemFactory factory = APPENDIX_RECIPELIST_FACTORIES.get(type); if(factory == null) { throw new InfoBookException("No appendix list of type '" + type + "' was found."); } - return factory.create(infoBook, recipe); + return factory.create(infoBook, recipeDisplay); } protected static List createAppendixes(IInfoBook infoBook, String factory, Element node) throws InvalidAppendixException { @@ -720,7 +713,7 @@ public static interface IAppendixListFactory { public static interface IAppendixItemFactory> { - public SectionAppendix create(IInfoBook infoBook, RecipeHolder recipe) throws InvalidAppendixException; + public SectionAppendix create(IInfoBook infoBook, Supplier recipeDisplay) throws InvalidAppendixException; } diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/InfoBookRegistry.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/InfoBookRegistry.java index 3223c15ee5..b8b04f5e36 100644 --- a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/InfoBookRegistry.java +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/InfoBookRegistry.java @@ -7,6 +7,7 @@ import net.neoforged.neoforge.event.TagsUpdatedEvent; import net.neoforged.neoforge.event.server.ServerStartedEvent; import org.apache.logging.log4j.Level; +import org.cyclops.cyclopscore.helper.RecipeHelpers; import org.cyclops.cyclopscore.infobook.pageelement.AdvancementRewards; import org.cyclops.cyclopscore.init.ModBaseNeoForge; @@ -23,7 +24,6 @@ public class InfoBookRegistry implements IInfoBookRegistry { static { NeoForge.EVENT_BUS.addListener(EventPriority.HIGHEST, InfoBookRegistry::onClientTagsLoadedStatic); -// NeoForge.EVENT_BUS.addListener(EventPriority.HIGHEST, InfoBookRegistry::onClientRecipesLoadedStatic); // TODO: somehow get recipes client-side NeoForge.EVENT_BUS.addListener(EventPriority.HIGHEST, InfoBookRegistry::onServerStartedStatic); } @@ -33,8 +33,6 @@ public class InfoBookRegistry implements IInfoBookRegistry { public InfoBookRegistry() { NeoForge.EVENT_BUS.addListener(this::onPlayerLoggedIn); -// NeoForge.EVENT_BUS.addListener(EventPriority.LOWEST, this::onClientTagsLoaded); -// NeoForge.EVENT_BUS.addListener(EventPriority.LOWEST, this::onClientRecipesLoaded); // TODO: somehow get recipes client-side NeoForge.EVENT_BUS.addListener(this::onServerStarted); } @@ -68,14 +66,6 @@ public static void onClientTagsLoadedStatic(TagsUpdatedEvent event) { AdvancementRewards.reset(); } } -// public static void onClientRecipesLoadedStatic(RecipesUpdatedEvent event) { // TODO: somehow get recipes client-side -// infobookStageRecipesStatic = true; -// if (infobookStageTagsStatic && infobookStageRecipesStatic) { -// infobookStageTagsStatic = false; -// infobookStageRecipesStatic = false; -// AdvancementRewards.reset(); -// } -// } public static void onServerStartedStatic(ServerStartedEvent event) { if (event.getServer().isDedicatedServer()) { infobookStageTagsStatic = false; @@ -85,35 +75,19 @@ public static void onServerStartedStatic(ServerStartedEvent event) { } } - // Reload infobooks if BOTH tags and recipes are initialized (can occur out-of-order in SMP) - private volatile boolean infobookStageTags = false; - private volatile boolean infobookStageRecipes = false; public void onPlayerLoggedIn(ClientPlayerNetworkEvent.LoggingIn event) { - initialize(); + RecipeHelpers.reset(); + initializeAllBooks(); } -// public void onClientTagsLoaded(TagsUpdatedEvent event) { -// infobookStageTags = true; -// if (infobookStageTags /*&& infobookStageRecipes*/) { // TODO: somehow get recipes client-side -// initialize(); -// } -// } -// public void onClientRecipesLoaded(RecipesUpdatedEvent event) { // TODO: somehow get recipes client-side -// infobookStageRecipes = true; -// if (infobookStageTags && infobookStageRecipes) { -// initialize(); -// } -// } + public void onServerStarted(ServerStartedEvent event) { if (event.getServer().isDedicatedServer()) { - // Only call this on dedicated servers, as the RecipesUpdatedEvent won't be emitted there - initialize(); + initializeAllBooks(); } } - public void initialize() { - this.infobookStageTags = false; - this.infobookStageRecipes = false; - + @Override + public void initializeAllBooks() { // Load after recipes are loaded client-side for (Map.Entry entry : bookPaths.entrySet()) { entry.getKey().getMod().log(Level.INFO, "Loading infobook " + entry.getValue()); diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/pageelement/CraftingRecipeAppendix.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/pageelement/CraftingRecipeAppendix.java index 1da8541b9c..2d166e1939 100644 --- a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/pageelement/CraftingRecipeAppendix.java +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/pageelement/CraftingRecipeAppendix.java @@ -3,21 +3,23 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.core.NonNullList; +import net.minecraft.util.context.ContextMap; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingRecipe; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.item.crafting.ShapedRecipe; +import net.minecraft.world.item.crafting.display.RecipeDisplayEntry; +import net.minecraft.world.item.crafting.display.ShapedCraftingRecipeDisplay; +import net.minecraft.world.item.crafting.display.ShapelessCraftingRecipeDisplay; +import net.minecraft.world.item.crafting.display.SlotDisplayContext; import net.minecraft.world.level.block.Blocks; import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.OnlyIn; -import org.cyclops.cyclopscore.helper.IModHelpers; import org.cyclops.cyclopscore.infobook.AdvancedButtonEnum; import org.cyclops.cyclopscore.infobook.IInfoBook; import org.cyclops.cyclopscore.infobook.InfoSection; import org.cyclops.cyclopscore.infobook.ScreenInfoBook; import java.util.List; +import java.util.function.Supplier; /** * Shaped recipes. @@ -35,8 +37,8 @@ public class CraftingRecipeAppendix extends RecipeAppendix { } private static final AdvancedButtonEnum RESULT = AdvancedButtonEnum.create(); - public CraftingRecipeAppendix(IInfoBook infoBook, RecipeHolder recipe) { - super(infoBook, recipe); + public CraftingRecipeAppendix(IInfoBook infoBook, Supplier recipeDisplay) { + super(infoBook, recipeDisplay); } @Override @@ -67,12 +69,17 @@ protected void drawElementInner(ScreenInfoBook gui, GuiGraphics guiGraphics, int gui.drawArrowRight(guiGraphics, x + (SLOT_SIZE + SLOT_OFFSET_X) * 3 - 3, y + SLOT_OFFSET_Y + SLOT_SIZE + 2); // Prepare items + RecipeDisplayEntry recipeDisplay = getRecipeDisplay(); + if (recipeDisplay == null) { + return; + } int tick = getTick(gui); ItemStack[] grid = new ItemStack[9]; - ItemStack result = prepareItemStack(IModHelpers.get().getMinecraftHelpers().getRecipeOutput(recipe, Minecraft.getInstance().level), tick); + ContextMap contextMap = SlotDisplayContext.fromLevel(Minecraft.getInstance().level); + ItemStack result = prepareItemStacks(recipeDisplay.display().result().resolveForStacks(contextMap), tick); for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { - grid[i + j * 3] = prepareItemStacks(getItemStacks(i + j * 3).getValues(), tick); + grid[i + j * 3] = getItemStacks(recipeDisplay, i + j * 3, contextMap, tick); } } @@ -98,9 +105,9 @@ protected void drawElementInner(ScreenInfoBook gui, GuiGraphics guiGraphics, int * @param height The original recipe height. * @return The reformatted object array. */ - private static NonNullList formatShapedGrid(List itemStacksRaw, int width, int height) { + private static NonNullList formatShapedGrid(List itemStacksRaw, int width, int height) { int rawIndex = 0; - NonNullList itemStacks = NonNullList.withSize(9, Ingredient.of()); + NonNullList itemStacks = NonNullList.withSize(9, ItemStack.EMPTY); for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { itemStacks.set(y * 3 + x, itemStacksRaw.get(rawIndex++)); @@ -111,16 +118,22 @@ private static NonNullList formatShapedGrid(List itemSta return itemStacks; } - protected Ingredient getItemStacks(int index) { - List ingredients; - - if(recipe.value() instanceof ShapedRecipe shapedRecipe) { - ingredients = formatShapedGrid(shapedRecipe.placementInfo().ingredients(), - shapedRecipe.getWidth(), shapedRecipe.getHeight()); + protected ItemStack getItemStacks(RecipeDisplayEntry recipeDisplay, int index, ContextMap contextMap, int tick) { + List ingredients; + + if (recipeDisplay.display() instanceof ShapedCraftingRecipeDisplay shapedDisplay) { + ingredients = formatShapedGrid(shapedDisplay.ingredients().stream() + .map(display -> prepareItemStacks(display.resolveForStacks(contextMap), tick)) + .toList(), + shapedDisplay.width(), shapedDisplay.height()); + } else if (recipeDisplay.display() instanceof ShapelessCraftingRecipeDisplay shapelessDisplay) { + ingredients = shapelessDisplay.ingredients().stream() + .map(display -> prepareItemStacks(display.resolveForStacks(contextMap), tick)) + .toList(); } else { - ingredients = recipe.value().placementInfo().ingredients(); + throw new IllegalArgumentException("Unsupported recipe display class: " + recipeDisplay.display()); } - if(ingredients.size() <= index) return Ingredient.of(); + if(ingredients.size() <= index) return ItemStack.EMPTY; return ingredients.get(index); } diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/pageelement/FurnaceRecipeAppendix.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/pageelement/FurnaceRecipeAppendix.java index 42c7d1645a..2ee6bc0250 100644 --- a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/pageelement/FurnaceRecipeAppendix.java +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/pageelement/FurnaceRecipeAppendix.java @@ -2,18 +2,22 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.util.context.ContextMap; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.SmeltingRecipe; +import net.minecraft.world.item.crafting.display.FurnaceRecipeDisplay; +import net.minecraft.world.item.crafting.display.RecipeDisplayEntry; +import net.minecraft.world.item.crafting.display.SlotDisplayContext; import net.minecraft.world.level.block.Blocks; import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.OnlyIn; -import org.cyclops.cyclopscore.helper.IModHelpers; import org.cyclops.cyclopscore.infobook.AdvancedButtonEnum; import org.cyclops.cyclopscore.infobook.IInfoBook; import org.cyclops.cyclopscore.infobook.InfoSection; import org.cyclops.cyclopscore.infobook.ScreenInfoBook; +import java.util.function.Supplier; + /** * Blood Infuser recipes. * @author rubensworks @@ -27,8 +31,8 @@ public class FurnaceRecipeAppendix extends RecipeAppendix { private static final AdvancedButtonEnum INPUT = AdvancedButtonEnum.create(); private static final AdvancedButtonEnum RESULT = AdvancedButtonEnum.create(); - public FurnaceRecipeAppendix(IInfoBook infoBook, RecipeHolder recipe) { - super(infoBook, recipe); + public FurnaceRecipeAppendix(IInfoBook infoBook, Supplier recipeDisplay) { + super(infoBook, recipeDisplay); } @Override @@ -60,9 +64,14 @@ public void drawElementInner(ScreenInfoBook gui, GuiGraphics guiGraphics, int x, gui.drawArrowRight(guiGraphics, x + middle - 3, y + SLOT_OFFSET_Y + 2); // Prepare items + RecipeDisplayEntry recipeDisplay = getRecipeDisplay(); + if (recipeDisplay == null) { + return; + } int tick = getTick(gui); - ItemStack input = prepareItemStacks(recipe.value().placementInfo().ingredients().get(0).getValues(), tick); - ItemStack result = prepareItemStack(IModHelpers.get().getMinecraftHelpers().getRecipeOutput(recipe, Minecraft.getInstance().level), tick); + ContextMap contextMap = SlotDisplayContext.fromLevel(Minecraft.getInstance().level); + ItemStack input = prepareItemStacks(((FurnaceRecipeDisplay) recipeDisplay.display()).ingredient().resolveForStacks(contextMap), tick); + ItemStack result = prepareItemStacks(recipeDisplay.display().result().resolveForStacks(contextMap), tick); // Items renderItem(gui, guiGraphics, x + SLOT_OFFSET_X, y + SLOT_OFFSET_Y, input, mx, my, INPUT); diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/pageelement/RecipeAppendix.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/pageelement/RecipeAppendix.java index d10d1a6d9f..ab95919641 100644 --- a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/pageelement/RecipeAppendix.java +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/infobook/pageelement/RecipeAppendix.java @@ -17,7 +17,7 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.item.crafting.display.RecipeDisplayEntry; import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.OnlyIn; import net.neoforged.neoforge.fluids.FluidStack; @@ -27,8 +27,10 @@ import org.cyclops.cyclopscore.infobook.*; import org.lwjgl.opengl.GL11; +import javax.annotation.Nullable; import java.util.List; import java.util.Map; +import java.util.function.Supplier; /** * Recipes that can be added to sections. @@ -39,7 +41,7 @@ public abstract class RecipeAppendix> extends SectionAppendi protected static final int SLOT_SIZE = 16; protected static final int TICK_DELAY = 30; - protected RecipeHolder recipe; + protected Supplier recipeDisplaySupplier; /** * This map holds advanced buttons that have a unique identifier. @@ -48,9 +50,14 @@ public abstract class RecipeAppendix> extends SectionAppendi */ protected Map renderItemHolders = Maps.newHashMap(); - public RecipeAppendix(IInfoBook infoBook, RecipeHolder recipe) { + public RecipeAppendix(IInfoBook infoBook, Supplier recipeDisplaySupplier) { super(infoBook); - this.recipe = recipe; + this.recipeDisplaySupplier = recipeDisplaySupplier; + } + + @Nullable + public RecipeDisplayEntry getRecipeDisplay() { + return recipeDisplaySupplier.get(); } protected int getTick(ScreenInfoBook gui) { diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/metadata/RegistryExportableRecipeAbstract.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/metadata/RegistryExportableRecipeAbstract.java index 44bfe969b4..230e4d733f 100644 --- a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/metadata/RegistryExportableRecipeAbstract.java +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/metadata/RegistryExportableRecipeAbstract.java @@ -32,7 +32,7 @@ public JsonObject export() { JsonArray elements = new JsonArray(); element.add("recipes", elements); - for (RecipeHolder recipeHolder : IModHelpers.get().getCraftingHelpers().findServerRecipes(getRecipeType())) { + for (RecipeHolder recipeHolder : IModHelpers.get().getCraftingHelpers().findRecipes(getRecipeType())) { JsonObject serializedRecipe = serializeRecipe(recipeHolder); serializedRecipe.addProperty("id", recipeHolder.toString()); diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/network/packet/RequestRecipeDisplayPacket.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/network/packet/RequestRecipeDisplayPacket.java new file mode 100644 index 0000000000..5f13bdec4f --- /dev/null +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/network/packet/RequestRecipeDisplayPacket.java @@ -0,0 +1,74 @@ +package org.cyclops.cyclopscore.network.packet; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.item.crafting.display.RecipeDisplayEntry; +import net.minecraft.world.level.Level; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import org.cyclops.cyclopscore.CyclopsCoreNeoForge; +import org.cyclops.cyclopscore.Reference; +import org.cyclops.cyclopscore.helper.IModHelpers; +import org.cyclops.cyclopscore.network.CodecField; +import org.cyclops.cyclopscore.network.PacketCodec; + +import java.util.List; + +/** + * Packet from client to server to request a recipe display. + * @author rubensworks + * + */ +public class RequestRecipeDisplayPacket extends PacketCodec { + + public static final Type TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(Reference.MOD_ID, "request_recipe_display_packet")); + public static final StreamCodec CODEC = getCodec(RequestRecipeDisplayPacket::new); + + @CodecField + private String recipeType; + @CodecField + private String recipe; + + public RequestRecipeDisplayPacket() { + super(TYPE); + } + + public RequestRecipeDisplayPacket(RecipeType recipeType, ResourceLocation recipe) { + this(); + this.recipeType = recipeType.toString(); + this.recipe = recipe.toString(); + } + + @Override + public boolean isAsync() { + return false; + } + + @Override + @OnlyIn(Dist.CLIENT) + public void actionClient(Level level, Player player) { + + } + + @Override + public void actionServer(Level level, ServerPlayer player) { + List recipeDisplays = IModHelpers.get().getCraftingHelpers().getRecipeDisplays( + BuiltInRegistries.RECIPE_TYPE.getValue(ResourceLocation.parse(this.recipeType)), + ResourceKey.create(Registries.RECIPE, ResourceLocation.parse(this.recipe)) + ); + if (recipeDisplays.isEmpty()) { + CyclopsCoreNeoForge.clog(org.apache.logging.log4j.Level.ERROR, "Received an invalid recipe request for recipe type " + recipeType.toString() + " with recipe id " + recipe + " from " + player.getName()); + return; + } + CyclopsCoreNeoForge._instance.getPacketHandler().sendToPlayer( + new SendRecipeDisplayPacket(recipeType, recipe, recipeDisplays.getFirst()), player); + } + +} diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/network/packet/RequestRecipeDisplaysRegexPacket.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/network/packet/RequestRecipeDisplaysRegexPacket.java new file mode 100644 index 0000000000..734aed16d4 --- /dev/null +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/network/packet/RequestRecipeDisplaysRegexPacket.java @@ -0,0 +1,72 @@ +package org.cyclops.cyclopscore.network.packet; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.item.crafting.display.RecipeDisplayEntry; +import net.minecraft.world.level.Level; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import org.apache.commons.lang3.tuple.Pair; +import org.cyclops.cyclopscore.CyclopsCoreNeoForge; +import org.cyclops.cyclopscore.Reference; +import org.cyclops.cyclopscore.helper.IModHelpers; +import org.cyclops.cyclopscore.network.CodecField; +import org.cyclops.cyclopscore.network.PacketCodec; + +import java.util.List; + +/** + * Packet from client to server to request a recipe display. + * @author rubensworks + * + */ +public class RequestRecipeDisplaysRegexPacket extends PacketCodec { + + public static final Type TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(Reference.MOD_ID, "request_recipe_displays_regex_packet")); + public static final StreamCodec CODEC = getCodec(RequestRecipeDisplaysRegexPacket::new); + + @CodecField + private String recipeType; + @CodecField + private String recipeRegex; + + public RequestRecipeDisplaysRegexPacket() { + super(TYPE); + } + + public RequestRecipeDisplaysRegexPacket(RecipeType recipeType, String recipeRegex) { + this(); + this.recipeType = recipeType.toString(); + this.recipeRegex = recipeRegex; + } + + @Override + public boolean isAsync() { + return false; + } + + @Override + @OnlyIn(Dist.CLIENT) + public void actionClient(Level level, Player player) { + + } + + @Override + public void actionServer(Level level, ServerPlayer player) { + List> recipeDisplays = IModHelpers.get().getCraftingHelpers().getRecipeDisplays( + BuiltInRegistries.RECIPE_TYPE.getValue(ResourceLocation.parse(this.recipeType)), + recipeRegex + ); + for (Pair entry : recipeDisplays) { + CyclopsCoreNeoForge._instance.getPacketHandler().sendToPlayer( + new SendRecipeDisplayPacket(recipeType, entry.getLeft().toString(), entry.getRight()), player); + } + CyclopsCoreNeoForge._instance.getPacketHandler().sendToPlayer(new SendRecipeDisplaysRegexDonePacket(recipeType, recipeRegex), player); + } + +} diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/network/packet/SendRecipeDisplayPacket.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/network/packet/SendRecipeDisplayPacket.java new file mode 100644 index 0000000000..d36546ec20 --- /dev/null +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/network/packet/SendRecipeDisplayPacket.java @@ -0,0 +1,77 @@ +package org.cyclops.cyclopscore.network.packet; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.crafting.display.RecipeDisplayEntry; +import net.minecraft.world.level.Level; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import org.cyclops.cyclopscore.Reference; +import org.cyclops.cyclopscore.helper.RecipeHelpers; +import org.cyclops.cyclopscore.network.CodecField; +import org.cyclops.cyclopscore.network.PacketCodec; + +/** + * Packet from server to client to update player advancement unlocked info. + * @author rubensworks + * + */ +public class SendRecipeDisplayPacket extends PacketCodec { + + public static final Type TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(Reference.MOD_ID, "send_recipe_display_packet")); + public static final StreamCodec CODEC = getCodec(SendRecipeDisplayPacket::new); + + @CodecField + private String recipeType; + @CodecField + private String recipe; + private RecipeDisplayEntry recipeDisplay; + + public SendRecipeDisplayPacket() { + super(TYPE); + } + + public SendRecipeDisplayPacket(String recipeType, String recipe, RecipeDisplayEntry recipeDisplay) { + this(); + this.recipeType = recipeType; + this.recipe = recipe; + this.recipeDisplay = recipeDisplay; + } + + @Override + public boolean isAsync() { + return false; + } + + @Override + public void encode(RegistryFriendlyByteBuf output) { + super.encode(output); + RecipeDisplayEntry.STREAM_CODEC.encode(output, recipeDisplay); + } + + @Override + public void decode(RegistryFriendlyByteBuf input) { + super.decode(input); + recipeDisplay = RecipeDisplayEntry.STREAM_CODEC.decode(input); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void actionClient(Level level, Player player) { + RecipeHelpers.setRecipeDisplay( + BuiltInRegistries.RECIPE_TYPE.getValue(ResourceLocation.parse(this.recipeType)), + ResourceLocation.parse(this.recipe), + recipeDisplay + ); + } + + @Override + public void actionServer(Level level, ServerPlayer player) { + + } + +} diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/network/packet/SendRecipeDisplaysRegexDonePacket.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/network/packet/SendRecipeDisplaysRegexDonePacket.java new file mode 100644 index 0000000000..c67dee5d53 --- /dev/null +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/network/packet/SendRecipeDisplaysRegexDonePacket.java @@ -0,0 +1,61 @@ +package org.cyclops.cyclopscore.network.packet; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import org.cyclops.cyclopscore.Reference; +import org.cyclops.cyclopscore.helper.RecipeHelpers; +import org.cyclops.cyclopscore.network.CodecField; +import org.cyclops.cyclopscore.network.PacketCodec; + +/** + * Packet from server to client to update player advancement unlocked info. + * @author rubensworks + * + */ +public class SendRecipeDisplaysRegexDonePacket extends PacketCodec { + + public static final Type TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(Reference.MOD_ID, "send_recipe_displays_regex_done_packet")); + public static final StreamCodec CODEC = getCodec(SendRecipeDisplaysRegexDonePacket::new); + + @CodecField + private String recipeType; + @CodecField + private String regex; + + public SendRecipeDisplaysRegexDonePacket() { + super(TYPE); + } + + public SendRecipeDisplaysRegexDonePacket(String recipeType, String regex) { + this(); + this.recipeType = recipeType; + this.regex = regex; + } + + @Override + public boolean isAsync() { + return false; + } + + @Override + @OnlyIn(Dist.CLIENT) + public void actionClient(Level level, Player player) { + RecipeHelpers.setRecipeDisplaysRegexDone( + BuiltInRegistries.RECIPE_TYPE.getValue(ResourceLocation.parse(this.recipeType)), + this.regex + ); + } + + @Override + public void actionServer(Level level, ServerPlayer player) { + + } + +} diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/proxy/ClientProxy.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/proxy/ClientProxyNeoForge.java similarity index 81% rename from loader-neoforge/src/main/java/org/cyclops/cyclopscore/proxy/ClientProxy.java rename to loader-neoforge/src/main/java/org/cyclops/cyclopscore/proxy/ClientProxyNeoForge.java index 4dfb8ec13f..771ceac178 100644 --- a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/proxy/ClientProxy.java +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/proxy/ClientProxyNeoForge.java @@ -11,10 +11,10 @@ * @author rubensworks * */ -public class ClientProxy extends ClientProxyComponent { +public class ClientProxyNeoForge extends ClientProxyComponent { - public ClientProxy() { - super(new CommonProxy()); + public ClientProxyNeoForge() { + super(new CommonProxyNeoForge()); NeoForge.EVENT_BUS.addListener(ItemInformationProviderNeoForge::onTooltip); } diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/proxy/CommonProxy.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/proxy/CommonProxyNeoForge.java similarity index 81% rename from loader-neoforge/src/main/java/org/cyclops/cyclopscore/proxy/CommonProxy.java rename to loader-neoforge/src/main/java/org/cyclops/cyclopscore/proxy/CommonProxyNeoForge.java index 79dcffe21c..631e77abf1 100644 --- a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/proxy/CommonProxy.java +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/proxy/CommonProxyNeoForge.java @@ -16,7 +16,7 @@ * @author rubensworks * */ -public class CommonProxy extends CommonProxyComponent { +public class CommonProxyNeoForge extends CommonProxyComponent { @Override public ModBaseNeoForge getMod() { @@ -44,6 +44,10 @@ public void registerPackets(IPacketHandler packetHandler) { packetHandler.register(SendPlayerNbtPacket.class, SendPlayerNbtPacket.TYPE, SendPlayerNbtPacket.CODEC); packetHandler.register(RequestPlayerAdvancementUnlockedPacket.class, RequestPlayerAdvancementUnlockedPacket.TYPE, RequestPlayerAdvancementUnlockedPacket.CODEC); packetHandler.register(SendPlayerAdvancementUnlockedPacket.class, SendPlayerAdvancementUnlockedPacket.TYPE, SendPlayerAdvancementUnlockedPacket.CODEC); + packetHandler.register(RequestRecipeDisplayPacket.class, RequestRecipeDisplayPacket.TYPE, RequestRecipeDisplayPacket.CODEC); + packetHandler.register(RequestRecipeDisplaysRegexPacket.class, RequestRecipeDisplaysRegexPacket.TYPE, RequestRecipeDisplaysRegexPacket.CODEC); + packetHandler.register(SendRecipeDisplayPacket.class, SendRecipeDisplayPacket.TYPE, SendRecipeDisplayPacket.CODEC); + packetHandler.register(SendRecipeDisplaysRegexDonePacket.class, SendRecipeDisplaysRegexDonePacket.TYPE, SendRecipeDisplaysRegexDonePacket.CODEC); // Register debug packets packetHandler.register(PingPongPacketAsync.class, PingPongPacketAsync.TYPE, PingPongPacketAsync.CODEC);