diff --git a/src/main/java/thedarkcolour/exdeorum/blockentity/AbstractSieveBlockEntity.java b/src/main/java/thedarkcolour/exdeorum/blockentity/AbstractSieveBlockEntity.java index 608d49ea..328a085c 100644 --- a/src/main/java/thedarkcolour/exdeorum/blockentity/AbstractSieveBlockEntity.java +++ b/src/main/java/thedarkcolour/exdeorum/blockentity/AbstractSieveBlockEntity.java @@ -26,7 +26,6 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.stats.Stats; import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; import net.minecraft.world.ItemInteractionResult; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; diff --git a/src/main/java/thedarkcolour/exdeorum/blockentity/BarrelBlockEntity.java b/src/main/java/thedarkcolour/exdeorum/blockentity/BarrelBlockEntity.java index 1f22f892..25ab33af 100644 --- a/src/main/java/thedarkcolour/exdeorum/blockentity/BarrelBlockEntity.java +++ b/src/main/java/thedarkcolour/exdeorum/blockentity/BarrelBlockEntity.java @@ -266,7 +266,7 @@ public class BarrelBlockEntity extends ETankBlockEntity { var itemFluidCap = playerItem.getCapability(Capabilities.FluidHandler.ITEM); if (itemFluidCap != null) { var itemFluid = itemFluidCap.drain(1000, IFluidHandler.FluidAction.SIMULATE); - BarrelFluidMixingRecipe recipe = RecipeUtil.getFluidMixingRecipe(this.tank.getFluid(), itemFluid.getFluid()); + BarrelFluidMixingRecipe recipe = getRecipeCaches().getFluidMixingRecipe(this.tank.getFluid(), itemFluid.getFluid()); // If draining item fluid was possible and tank has enough fluid to mix... if (recipe != null && this.tank.getFluidAmount() >= recipe.baseFluid().amount() && itemFluid.getAmount() == 1000) { @@ -370,7 +370,7 @@ public class BarrelBlockEntity extends ETankBlockEntity { return false; } - var recipe = RecipeUtil.getBarrelMixingRecipe(this.level.getRecipeManager(), playerItem, this.tank.getFluid()); + var recipe = getRecipeCaches().getBarrelMixingRecipe(this.level.getRecipeManager(), playerItem, this.tank.getFluid()); if (recipe != null) { if (!simulate) { @@ -389,9 +389,9 @@ public class BarrelBlockEntity extends ETankBlockEntity { private boolean tryComposting(ItemStack stack, boolean simulate) { if (simulate) { - return RecipeUtil.isCompostable(stack); + return getRecipeCaches().isCompostable(stack); } else { - var recipe = RecipeUtil.getBarrelCompostRecipe(stack); + var recipe = getRecipeCaches().getBarrelCompostRecipe(stack); if (recipe != null) { addCompost(stack, recipe.getVolume()); return true; @@ -437,7 +437,7 @@ public class BarrelBlockEntity extends ETankBlockEntity { var aboveFluid = aboveFluidState.getType(); if (aboveFluid != Fluids.EMPTY) { - BarrelFluidMixingRecipe recipe = RecipeUtil.getFluidMixingRecipe(this.tank.getFluid(), aboveFluid instanceof FlowingFluid flowing ? flowing.getSource() : aboveFluid); + BarrelFluidMixingRecipe recipe = getRecipeCaches().getFluidMixingRecipe(this.tank.getFluid(), aboveFluid instanceof FlowingFluid flowing ? flowing.getSource() : aboveFluid); if (recipe != null) { // If additive is not consumed, just craft @@ -464,7 +464,7 @@ public class BarrelBlockEntity extends ETankBlockEntity { this.currentTransformRecipe = null; } else { var belowState = this.level.getBlockState(this.worldPosition.below()); - this.currentTransformRecipe = RecipeUtil.getFluidTransformationRecipe(this.tank.getFluid().getFluid(), belowState); + this.currentTransformRecipe = getRecipeCaches().getFluidTransformationRecipe(this.tank.getFluid().getFluid(), belowState); if (this.currentTransformRecipe != null) { var color = this.currentTransformRecipe.resultColor(); diff --git a/src/main/java/thedarkcolour/exdeorum/blockentity/EBlockEntity.java b/src/main/java/thedarkcolour/exdeorum/blockentity/EBlockEntity.java index 544663fb..f7463d53 100644 --- a/src/main/java/thedarkcolour/exdeorum/blockentity/EBlockEntity.java +++ b/src/main/java/thedarkcolour/exdeorum/blockentity/EBlockEntity.java @@ -34,6 +34,10 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import thedarkcolour.exdeorum.network.VisualUpdateTracker; +import thedarkcolour.exdeorum.recipe.RecipeCaches; +import thedarkcolour.exdeorum.recipe.RecipeUtil; + +import java.util.Objects; public abstract class EBlockEntity extends BlockEntity { public EBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { @@ -78,4 +82,8 @@ public abstract class EBlockEntity extends BlockEntity { public InteractionResult useWithoutItem(Level level, Player player) { return InteractionResult.PASS; } + + public RecipeCaches getRecipeCaches() { + return RecipeUtil.getCaches(Objects.requireNonNull(this.level)); + } } diff --git a/src/main/java/thedarkcolour/exdeorum/blockentity/LavaCrucibleBlockEntity.java b/src/main/java/thedarkcolour/exdeorum/blockentity/LavaCrucibleBlockEntity.java index cdcd06cb..21ad4224 100644 --- a/src/main/java/thedarkcolour/exdeorum/blockentity/LavaCrucibleBlockEntity.java +++ b/src/main/java/thedarkcolour/exdeorum/blockentity/LavaCrucibleBlockEntity.java @@ -23,7 +23,6 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; -import thedarkcolour.exdeorum.recipe.RecipeUtil; import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe; import thedarkcolour.exdeorum.registry.EBlockEntities; @@ -36,12 +35,12 @@ public class LavaCrucibleBlockEntity extends AbstractCrucibleBlockEntity { @Override public int getMeltingRate() { - return RecipeUtil.getHeatValue(this.level.getBlockState(getBlockPos().below())); + return getRecipeCaches().getHeatValue(this.level.getBlockState(getBlockPos().below())); } @Override protected @Nullable CrucibleRecipe getRecipe(ItemStack item) { - return RecipeUtil.getLavaCrucibleRecipe(item); + return getRecipeCaches().getLavaCrucibleRecipe(item); } @Override diff --git a/src/main/java/thedarkcolour/exdeorum/blockentity/MechanicalHammerBlockEntity.java b/src/main/java/thedarkcolour/exdeorum/blockentity/MechanicalHammerBlockEntity.java index 400175ec..6b71fd0f 100644 --- a/src/main/java/thedarkcolour/exdeorum/blockentity/MechanicalHammerBlockEntity.java +++ b/src/main/java/thedarkcolour/exdeorum/blockentity/MechanicalHammerBlockEntity.java @@ -20,20 +20,18 @@ package thedarkcolour.exdeorum.blockentity; import net.minecraft.core.BlockPos; import net.minecraft.core.HolderLookup; -import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.RandomSource; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.storage.loot.LootContext; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import thedarkcolour.exdeorum.block.MechanicalHammerBlock; import thedarkcolour.exdeorum.blockentity.helper.ItemHelper; @@ -64,8 +62,8 @@ public class MechanicalHammerBlockEntity extends AbstractMachineBlockEntity implements SieveLogic.Owner { private static final Component TITLE = Component.translatable(TranslationKeys.MECHANICAL_SIEVE_SCREEN_TITLE); private static final int INPUT_SLOT = 0; @@ -181,7 +184,7 @@ public class MechanicalSieveBlockEntity extends AbstractMachineBlockEntity getDropsFor(ItemStack contents) { - return RecipeUtil.getCompressedSieveRecipes(this.mesh.getItem(), contents); + return owner.getRecipeCaches().getCompressedSieveRecipes(this.mesh.getItem(), contents); } } diff --git a/src/main/java/thedarkcolour/exdeorum/blockentity/logic/SieveLogic.java b/src/main/java/thedarkcolour/exdeorum/blockentity/logic/SieveLogic.java index e1217430..98522a11 100644 --- a/src/main/java/thedarkcolour/exdeorum/blockentity/logic/SieveLogic.java +++ b/src/main/java/thedarkcolour/exdeorum/blockentity/logic/SieveLogic.java @@ -32,6 +32,7 @@ import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.storage.loot.LootContext; import thedarkcolour.exdeorum.config.EConfig; +import thedarkcolour.exdeorum.recipe.RecipeCaches; import thedarkcolour.exdeorum.recipe.RecipeUtil; import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe; import thedarkcolour.exdeorum.tag.EItemTags; @@ -39,7 +40,7 @@ import thedarkcolour.exdeorum.tag.EItemTags; import java.util.List; public class SieveLogic { - private final Owner owner; + protected final Owner owner; private final boolean mechanical; // block currently being sifted @@ -129,7 +130,7 @@ public class SieveLogic { } protected List getDropsFor(ItemStack contents) { - return RecipeUtil.getSieveRecipes(this.mesh.getItem(), contents); + return owner.getRecipeCaches().getSieveRecipes(this.mesh.getItem(), contents); } protected int getResultAmount(SieveRecipe recipe, LootContext context, RandomSource rand) { @@ -237,6 +238,8 @@ public class SieveLogic { // implement on the owner of this sieve logic public interface Owner { + RecipeCaches getRecipeCaches(); + ServerLevel getServerLevel(); // Return whether the result item was consumed diff --git a/src/main/java/thedarkcolour/exdeorum/client/ClientHandler.java b/src/main/java/thedarkcolour/exdeorum/client/ClientHandler.java index ee12b26d..48fc0139 100644 --- a/src/main/java/thedarkcolour/exdeorum/client/ClientHandler.java +++ b/src/main/java/thedarkcolour/exdeorum/client/ClientHandler.java @@ -31,6 +31,7 @@ import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; import net.minecraft.util.Unit; import net.minecraft.world.level.levelgen.presets.WorldPreset; +import net.neoforged.bus.api.EventPriority; import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.ModList; import net.neoforged.fml.event.config.ModConfigEvent; @@ -70,7 +71,7 @@ public class ClientHandler { fmlBus.addListener(ClientHandler::onPlayerRespawn); fmlBus.addListener(ClientHandler::onPlayerLogout); fmlBus.addListener(ClientHandler::onScreenOpen); - fmlBus.addListener(ClientHandler::onRecipesUpdated); + fmlBus.addListener(EventPriority.HIGHEST, ClientHandler::onRecipesUpdated); // We need to be at HIGH or HIGHEST to be called before JEI if (ModList.get().isLoaded(ModIds.JEI) || ModList.get().isLoaded(ModIds.EMI)) { modBus.addListener(ClientHandler::registerAdditionalModels); @@ -106,6 +107,7 @@ public class ClientHandler { private static void onPlayerLogout(ClientPlayerNetworkEvent.LoggingOut event) { isInVoidWorld = false; + ClientsideCode.getRecipeCaches().unload(); } private static void onConfigChanged(ModConfigEvent.Reloading event) { @@ -160,9 +162,7 @@ public class ClientHandler { } private static void onRecipesUpdated(RecipesUpdatedEvent event) { - if (!Minecraft.getInstance().isSingleplayer()) { - RecipeUtil.reload(event.getRecipeManager()); - } + ClientsideCode.getRecipeCaches().reload(event.getRecipeManager()); } public static void disableVoidFogRendering() { diff --git a/src/main/java/thedarkcolour/exdeorum/client/ClientsideCode.java b/src/main/java/thedarkcolour/exdeorum/client/ClientsideCode.java index cd9830bc..5fec128e 100644 --- a/src/main/java/thedarkcolour/exdeorum/client/ClientsideCode.java +++ b/src/main/java/thedarkcolour/exdeorum/client/ClientsideCode.java @@ -21,9 +21,18 @@ package thedarkcolour.exdeorum.client; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.world.item.crafting.RecipeManager; +import net.neoforged.fml.util.thread.EffectiveSide; import org.jetbrains.annotations.Nullable; +import thedarkcolour.exdeorum.recipe.RecipeCaches; public class ClientsideCode { + private static final RecipeCaches RECIPE_CACHES = new RecipeCaches(); + + public static RecipeCaches getRecipeCaches() { + assert EffectiveSide.get().isClient() : Thread.currentThread().getName(); + return RECIPE_CACHES; + } + @Nullable public static RecipeManager getRecipeManager() { ClientPacketListener connection = Minecraft.getInstance().getConnection(); diff --git a/src/main/java/thedarkcolour/exdeorum/compat/CompatUtil.java b/src/main/java/thedarkcolour/exdeorum/compat/CompatUtil.java index 7b9d7f85..23f6085b 100644 --- a/src/main/java/thedarkcolour/exdeorum/compat/CompatUtil.java +++ b/src/main/java/thedarkcolour/exdeorum/compat/CompatUtil.java @@ -27,6 +27,7 @@ import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.RecipeInput; +import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.item.enchantment.ItemEnchantments; import net.minecraft.world.level.ItemLike; @@ -34,7 +35,6 @@ import net.minecraft.world.level.Level; import net.neoforged.fml.ModList; import thedarkcolour.exdeorum.material.DefaultMaterials; import thedarkcolour.exdeorum.material.MaterialRegistry; -import thedarkcolour.exdeorum.recipe.RecipeUtil; import thedarkcolour.exdeorum.registry.EItems; import java.util.ArrayList; @@ -79,8 +79,8 @@ public class CompatUtil { return materials; } - public static , T> List collectAllRecipes(RecipeType recipeType, Function mapper) { - var byType = RecipeUtil.getRecipeManager().byType(recipeType); + public static , T> List collectAllRecipes(RecipeManager recipeManager, RecipeType recipeType, Function mapper) { + var byType = recipeManager.byType(recipeType); List recipes = new ObjectArrayList<>(byType.size()); for (RecipeHolder value : byType) { recipes.add(mapper.apply(value.value())); diff --git a/src/main/java/thedarkcolour/exdeorum/compat/XeiSieveRecipe.java b/src/main/java/thedarkcolour/exdeorum/compat/XeiSieveRecipe.java index 54c5473b..fae10f49 100644 --- a/src/main/java/thedarkcolour/exdeorum/compat/XeiSieveRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/compat/XeiSieveRecipe.java @@ -47,7 +47,7 @@ public record XeiSieveRecipe(Ingredient ingredient, ItemStack mesh, List public static ImmutableList getAllRecipesGrouped(RecipeType recipeType, MutableInt maxRows) { int maxSieveRows = 1; - var recipes = CompatUtil.collectAllRecipes(recipeType, Function.identity()); + var recipes = CompatUtil.collectAllRecipes(RecipeUtil.getClientRecipeManager(), recipeType, Function.identity()); Multimap ingredientGrouper = ArrayListMultimap.create(); for (int i = 0; i < recipes.size(); i++) { diff --git a/src/main/java/thedarkcolour/exdeorum/compat/XeiUtil.java b/src/main/java/thedarkcolour/exdeorum/compat/XeiUtil.java index d9a9bc21..66afb78c 100644 --- a/src/main/java/thedarkcolour/exdeorum/compat/XeiUtil.java +++ b/src/main/java/thedarkcolour/exdeorum/compat/XeiUtil.java @@ -234,33 +234,33 @@ public class XeiUtil { tooltipLines.accept(Component.translatable(TranslationKeys.SIEVE_RECIPE_MAX_OUTPUT, maxFormatted).withStyle(ChatFormatting.GRAY)); } - public interface HeatRecipeAcceptor { - void accept(int heat, BlockState state); - } - - public static void addCrucibleHeatRecipes(HeatRecipeAcceptor acceptor) { - var values = new Object2IntOpenHashMap(); - for (var entry : RecipeUtil.getHeatSources()) { - var state = entry.getKey(); - var block = state.getBlock(); - - if (block instanceof WallTorchBlock) continue; - - if (block != Blocks.AIR) { - final int newValue = entry.getIntValue(); - - values.computeInt(block, (key, value) -> { - if (value != null) { - return Math.max(value, newValue); - } else { - return newValue == 0 ? null : newValue; - } - }); - } - } - - for (var entry : values.object2IntEntrySet()) { - acceptor.accept(entry.getIntValue(), entry.getKey().defaultBlockState()); - } - } +// public interface HeatRecipeAcceptor { +// void accept(int heat, BlockState state); +// } +// +// public static void addCrucibleHeatRecipes(HeatRecipeAcceptor acceptor) { +// var values = new Object2IntOpenHashMap(); +// for (var entry : RecipeUtil.getHeatSources()) { +// var state = entry.getKey(); +// var block = state.getBlock(); +// +// if (block instanceof WallTorchBlock) continue; +// +// if (block != Blocks.AIR) { +// final int newValue = entry.getIntValue(); +// +// values.computeInt(block, (key, value) -> { +// if (value != null) { +// return Math.max(value, newValue); +// } else { +// return newValue == 0 ? null : newValue; +// } +// }); +// } +// } +// +// for (var entry : values.object2IntEntrySet()) { +// acceptor.accept(entry.getIntValue(), entry.getKey().defaultBlockState()); +// } +// } } diff --git a/src/main/java/thedarkcolour/exdeorum/compat/jei/ExDeorumJeiPlugin.java b/src/main/java/thedarkcolour/exdeorum/compat/jei/ExDeorumJeiPlugin.java index 177b3eb8..d0929ac0 100644 --- a/src/main/java/thedarkcolour/exdeorum/compat/jei/ExDeorumJeiPlugin.java +++ b/src/main/java/thedarkcolour/exdeorum/compat/jei/ExDeorumJeiPlugin.java @@ -46,6 +46,7 @@ import net.neoforged.fml.ModList; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.registries.DeferredHolder; import thedarkcolour.exdeorum.ExDeorum; +import thedarkcolour.exdeorum.client.ClientsideCode; import thedarkcolour.exdeorum.client.screen.MechanicalHammerScreen; import thedarkcolour.exdeorum.client.screen.MechanicalSieveScreen; import thedarkcolour.exdeorum.compat.CompatUtil; @@ -215,7 +216,7 @@ public class ExDeorumJeiPlugin implements IModPlugin { addRecipes(registration, HAMMER, ERecipeTypes.HAMMER); //noinspection rawtypes,unchecked addRecipes(registration, COMPRESSED_HAMMER, ((DeferredHolder) ERecipeTypes.COMPRESSED_HAMMER)); - registration.addRecipes(CROOK, CompatUtil.collectAllRecipes(ERecipeTypes.CROOK.get(), CrookJeiRecipe::create)); + registration.addRecipes(CROOK, CompatUtil.collectAllRecipes(RecipeUtil.getClientRecipeManager(), ERecipeTypes.CROOK.get(), CrookJeiRecipe::create)); registration.addRecipes(SIEVE, XeiSieveRecipe.getAllRecipesGrouped(ERecipeTypes.SIEVE.get(), XeiSieveRecipe.SIEVE_ROWS)); registration.addRecipes(COMPRESSED_SIEVE, XeiSieveRecipe.getAllRecipesGrouped(ERecipeTypes.COMPRESSED_SIEVE.get(), XeiSieveRecipe.COMPRESSED_SIEVE_ROWS)); @@ -224,7 +225,7 @@ public class ExDeorumJeiPlugin implements IModPlugin { private static void addCrucibleHeatSources(IRecipeRegistration registration) { var values = new Object2IntOpenHashMap(); - for (var entry : RecipeUtil.getHeatSources()) { + for (var entry : ClientsideCode.getRecipeCaches().getHeatSources()) { var state = entry.getKey(); var block = state.getBlock(); @@ -300,6 +301,6 @@ public class ExDeorumJeiPlugin implements IModPlugin { } private static > void addRecipes(IRecipeRegistration registration, RecipeType category, Supplier> type) { - registration.addRecipes(category, CompatUtil.collectAllRecipes(type.get(), Function.identity())); + registration.addRecipes(category, CompatUtil.collectAllRecipes(RecipeUtil.getClientRecipeManager(), type.get(), Function.identity())); } } diff --git a/src/main/java/thedarkcolour/exdeorum/event/EventHandler.java b/src/main/java/thedarkcolour/exdeorum/event/EventHandler.java index a43dfe53..897ad24f 100644 --- a/src/main/java/thedarkcolour/exdeorum/event/EventHandler.java +++ b/src/main/java/thedarkcolour/exdeorum/event/EventHandler.java @@ -58,6 +58,7 @@ import net.neoforged.neoforge.fluids.FluidInteractionRegistry; import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; import thedarkcolour.exdeorum.ExDeorum; import thedarkcolour.exdeorum.blockentity.helper.ItemHelper; +import thedarkcolour.exdeorum.client.ClientsideCode; import thedarkcolour.exdeorum.client.CompostColors; import thedarkcolour.exdeorum.compat.ModIds; import thedarkcolour.exdeorum.config.EConfig; @@ -66,6 +67,7 @@ import thedarkcolour.exdeorum.item.WateringCanItem; import thedarkcolour.exdeorum.material.BarrelMaterial; import thedarkcolour.exdeorum.network.NetworkHandler; import thedarkcolour.exdeorum.network.VisualUpdateTracker; +import thedarkcolour.exdeorum.recipe.RecipeCaches; import thedarkcolour.exdeorum.recipe.RecipeUtil; import thedarkcolour.exdeorum.registry.EBlockEntities; import thedarkcolour.exdeorum.registry.EFluids; @@ -95,7 +97,7 @@ public final class EventHandler { } private static void serverShutdown(ServerStoppingEvent event) { - RecipeUtil.unload(); + RecipeUtil.getServerRecipeCaches().unload(); } private static void handleDebugCommands(ClientChatEvent event) { @@ -209,10 +211,6 @@ public final class EventHandler { ExDeorum.LOGGER.error("Unable to grant player the Void World advancement. Ex Deorum advancements will not show"); } } - } else { - if (Minecraft.getInstance().getConnection() != null) { - RecipeUtil.reload(Minecraft.getInstance().getConnection().getRecipeManager()); - } } } @@ -231,7 +229,8 @@ public final class EventHandler { var recipes = event.getServerResources().getRecipeManager(); event.addListener((prepBarrier, resourceManager, prepProfiler, reloadProfiler, backgroundExecutor, gameExecutor) -> { return prepBarrier.wait(Unit.INSTANCE).thenRunAsync(() -> { - RecipeUtil.reload(recipes); + // This is called on render thread when joining a singleplayer world, so we skip assertions + RecipeUtil.getServerRecipeCaches(true).reload(recipes); }, gameExecutor); }); } diff --git a/src/main/java/thedarkcolour/exdeorum/loot/CompressedHammerLootModifier.java b/src/main/java/thedarkcolour/exdeorum/loot/CompressedHammerLootModifier.java index 7a15f616..065820c8 100644 --- a/src/main/java/thedarkcolour/exdeorum/loot/CompressedHammerLootModifier.java +++ b/src/main/java/thedarkcolour/exdeorum/loot/CompressedHammerLootModifier.java @@ -3,6 +3,7 @@ package thedarkcolour.exdeorum.loot; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.world.item.Item; +import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; import net.neoforged.neoforge.common.loot.IGlobalLootModifier; import net.neoforged.neoforge.common.loot.LootModifier; @@ -24,7 +25,7 @@ public class CompressedHammerLootModifier extends HammerLootModifier { } @Override - protected @Nullable HammerRecipe getRecipe(Item itemForm) { - return RecipeUtil.getCompressedHammerRecipe(itemForm); + protected @Nullable HammerRecipe getRecipe(Item itemForm, LootContext context) { + return RecipeUtil.getCaches(context.getLevel()).getCompressedHammerRecipe(itemForm); } } diff --git a/src/main/java/thedarkcolour/exdeorum/loot/CrookLootModifier.java b/src/main/java/thedarkcolour/exdeorum/loot/CrookLootModifier.java index 92596a8f..4a5564c6 100644 --- a/src/main/java/thedarkcolour/exdeorum/loot/CrookLootModifier.java +++ b/src/main/java/thedarkcolour/exdeorum/loot/CrookLootModifier.java @@ -34,7 +34,6 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; import net.neoforged.neoforge.common.loot.IGlobalLootModifier; import net.neoforged.neoforge.common.loot.LootModifier; -import org.jetbrains.annotations.NotNull; import thedarkcolour.exdeorum.recipe.RecipeUtil; import thedarkcolour.exdeorum.recipe.crook.CrookRecipe; @@ -48,7 +47,7 @@ public class CrookLootModifier extends LootModifier { } @Override - protected @NotNull ObjectArrayList doApply(ObjectArrayList generatedLoot, LootContext context) { + protected ObjectArrayList doApply(ObjectArrayList generatedLoot, LootContext context) { var state = context.getParamOrNull(LootContextParams.BLOCK_STATE); var stack = context.getParamOrNull(LootContextParams.TOOL); @@ -59,7 +58,7 @@ public class CrookLootModifier extends LootModifier { var fortune = stack.getEnchantmentLevel(context.getLevel().holderLookup(Registries.ENCHANTMENT).getOrThrow(Enchantments.FORTUNE)); var rolls = Math.max(1, Mth.ceil(fortune / 3f)); - for (CrookRecipe recipe : RecipeUtil.getCrookRecipes(state)) { + for (CrookRecipe recipe : RecipeUtil.getCaches(context.getLevel()).getCrookRecipes(state)) { for (int i = 0; i < rolls; i++) { if (rand.nextFloat() < recipe.chance()) { generatedLoot.add(recipe.result().copy()); diff --git a/src/main/java/thedarkcolour/exdeorum/loot/HammerLootModifier.java b/src/main/java/thedarkcolour/exdeorum/loot/HammerLootModifier.java index bd002e23..599fd231 100644 --- a/src/main/java/thedarkcolour/exdeorum/loot/HammerLootModifier.java +++ b/src/main/java/thedarkcolour/exdeorum/loot/HammerLootModifier.java @@ -69,7 +69,7 @@ public class HammerLootModifier extends LootModifier { return generatedLoot; } - var recipe = getRecipe(itemForm); + var recipe = getRecipe(itemForm, context); if (recipe == null) { return generatedLoot; } @@ -91,8 +91,8 @@ public class HammerLootModifier extends LootModifier { } @Nullable - protected HammerRecipe getRecipe(Item itemForm) { - return RecipeUtil.getHammerRecipe(itemForm); + protected HammerRecipe getRecipe(Item itemForm, LootContext context) { + return RecipeUtil.getCaches(context.getLevel()).getHammerRecipe(itemForm); } @Override diff --git a/src/main/java/thedarkcolour/exdeorum/menu/MechanicalHammerMenu.java b/src/main/java/thedarkcolour/exdeorum/menu/MechanicalHammerMenu.java index e9c42351..dccea65a 100644 --- a/src/main/java/thedarkcolour/exdeorum/menu/MechanicalHammerMenu.java +++ b/src/main/java/thedarkcolour/exdeorum/menu/MechanicalHammerMenu.java @@ -70,7 +70,7 @@ public class MechanicalHammerMenu extends AbstractMachineMenu barrelCompostRecipeCache; + private SingleIngredientRecipeCache lavaCrucibleRecipeCache; + private SingleIngredientRecipeCache waterCrucibleRecipeCache; + private SingleIngredientRecipeCache hammerRecipeCache; + private SingleIngredientRecipeCache compressedHammerRecipeCache; + private SieveRecipeCache sieveRecipeCache; + private SieveRecipeCache compressedSieveRecipeCache; + private BarrelFluidMixingRecipeCache barrelFluidMixingRecipeCache; + private FluidTransformationRecipeCache fluidTransformationRecipeCache; + private CrookRecipeCache crookRecipeCache; + private CrucibleHeatRecipeCache crucibleHeatRecipeCache; + + public List getSieveRecipes(Item mesh, ItemStack item) { + return sieveRecipeCache.getRecipe(mesh, item); + } + + public List getCompressedSieveRecipes(Item mesh, ItemStack item) { + return compressedSieveRecipeCache.getRecipe(mesh, item); + } + + @Nullable + public CrucibleRecipe getLavaCrucibleRecipe(ItemStack item) { + return lavaCrucibleRecipeCache.getRecipe(item); + } + + @Nullable + public CrucibleRecipe getWaterCrucibleRecipe(ItemStack item) { + return waterCrucibleRecipeCache.getRecipe(item); + } + + @Nullable + public BarrelCompostRecipe getBarrelCompostRecipe(ItemStack item) { + return barrelCompostRecipeCache.getRecipe(item); + } + + @Nullable + public HammerRecipe getHammerRecipe(Item item) { + return hammerRecipeCache.getRecipe(item); + } + + public Collection> getCachedHammerRecipes() { + return hammerRecipeCache.getAllRecipes(); + } + + @Nullable + public CompressedHammerRecipe getCompressedHammerRecipe(Item item) { + return compressedHammerRecipeCache.getRecipe(item); + } + + public Collection> getCachedCompressedHammerRecipes() { + return compressedHammerRecipeCache.getAllRecipes(); + } + + public List getCrookRecipes(BlockState state) { + return crookRecipeCache.getRecipes(state); + } + + public boolean isCompostable(ItemStack stack) { + return barrelCompostRecipeCache != null && barrelCompostRecipeCache.getRecipe(stack) != null; + } + + public int getHeatValue(BlockState state) { + return crucibleHeatRecipeCache.getValue(state); + } + + public ObjectSet> getHeatSources() { + return crucibleHeatRecipeCache.getEntries(); + } + + // todo stop using the RecipeManager + @Nullable + public BarrelMixingRecipe getBarrelMixingRecipe(RecipeManager recipes, ItemStack stack, FluidStack fluid) { + for (var recipe : recipes.byType(ERecipeTypes.BARREL_MIXING.get())) { + if (recipe.value().matches(stack, fluid)) { + return recipe.value(); + } + } + + return null; + } + + @Nullable + public BarrelFluidMixingRecipe getFluidMixingRecipe(FluidStack base, Fluid additive) { + var recipe = barrelFluidMixingRecipeCache.getRecipe(base.getFluid(), additive); + if (recipe != null && base.getAmount() >= recipe.baseFluid().amount()) { + return recipe; + } else { + return null; + } + } + + @Nullable + public FluidTransformationRecipe getFluidTransformationRecipe(Fluid baseFluid, BlockState catalystState) { + if (baseFluid != Fluids.EMPTY) { + return fluidTransformationRecipeCache.getRecipe(baseFluid, catalystState); + } else { + return null; + } + } + + public void reload(RecipeManager recipes) { + barrelCompostRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.BARREL_COMPOST); + lavaCrucibleRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.LAVA_CRUCIBLE); + waterCrucibleRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.WATER_CRUCIBLE); + hammerRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.HAMMER).trackAllRecipes(); + compressedHammerRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.COMPRESSED_HAMMER).trackAllRecipes(); + sieveRecipeCache = new SieveRecipeCache<>(recipes, ERecipeTypes.SIEVE); + compressedSieveRecipeCache = new SieveRecipeCache<>(recipes, ERecipeTypes.COMPRESSED_SIEVE); + barrelFluidMixingRecipeCache = new BarrelFluidMixingRecipeCache(recipes); + fluidTransformationRecipeCache = new FluidTransformationRecipeCache(recipes); + crookRecipeCache = new CrookRecipeCache(recipes); + crucibleHeatRecipeCache = new CrucibleHeatRecipeCache(recipes); + } + + public void unload() { + barrelCompostRecipeCache = null; + lavaCrucibleRecipeCache = null; + waterCrucibleRecipeCache = null; + hammerRecipeCache = null; + compressedHammerRecipeCache = null; + sieveRecipeCache = null; + compressedSieveRecipeCache = null; + barrelFluidMixingRecipeCache = null; + fluidTransformationRecipeCache = null; + crookRecipeCache = null; + crucibleHeatRecipeCache = null; + } +} diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/RecipeUtil.java b/src/main/java/thedarkcolour/exdeorum/recipe/RecipeUtil.java index f2729739..de66e4e0 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/RecipeUtil.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/RecipeUtil.java @@ -19,52 +19,32 @@ package thedarkcolour.exdeorum.recipe; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import it.unimi.dsi.fastutil.objects.ObjectSet; import net.minecraft.commands.arguments.blocks.BlockStateParser; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; 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.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.RecipeManager; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.Property; -import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootParams; import net.minecraft.world.level.storage.loot.providers.number.*; -import net.neoforged.api.distmarker.Dist; -import net.neoforged.fml.loading.FMLEnvironment; -import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.fml.util.thread.EffectiveSide; import net.neoforged.neoforge.server.ServerLifecycleHooks; -import org.jetbrains.annotations.Nullable; -import thedarkcolour.exdeorum.compat.PreferredOres; import thedarkcolour.exdeorum.client.ClientsideCode; +import thedarkcolour.exdeorum.compat.PreferredOres; import thedarkcolour.exdeorum.loot.SummationGenerator; -import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe; -import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe; -import thedarkcolour.exdeorum.recipe.barrel.BarrelMixingRecipe; -import thedarkcolour.exdeorum.recipe.barrel.FluidTransformationRecipe; -import thedarkcolour.exdeorum.recipe.cache.*; -import thedarkcolour.exdeorum.recipe.crook.CrookRecipe; -import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe; -import thedarkcolour.exdeorum.recipe.hammer.CompressedHammerRecipe; -import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe; -import thedarkcolour.exdeorum.recipe.sieve.CompressedSieveRecipe; -import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe; import thedarkcolour.exdeorum.registry.ENumberProviders; -import thedarkcolour.exdeorum.registry.ERecipeTypes; import java.util.*; @@ -75,85 +55,19 @@ public final class RecipeUtil { private static final int SUMMATION_TYPE = 4; private static final int UNKNOWN_TYPE = 99; - private static SingleIngredientRecipeCache barrelCompostRecipeCache; - private static SingleIngredientRecipeCache lavaCrucibleRecipeCache; - private static SingleIngredientRecipeCache waterCrucibleRecipeCache; - private static SingleIngredientRecipeCache hammerRecipeCache; - private static SingleIngredientRecipeCache compressedHammerRecipeCache; - private static SieveRecipeCache sieveRecipeCache; - private static SieveRecipeCache compressedSieveRecipeCache; - private static BarrelFluidMixingRecipeCache barrelFluidMixingRecipeCache; - private static FluidTransformationRecipeCache fluidTransformationRecipeCache; - private static CrookRecipeCache crookRecipeCache; - private static CrucibleHeatRecipeCache crucibleHeatRecipeCache; + private static final RecipeCaches SERVER_RECIPE_CACHES = new RecipeCaches(); - public static void reload(RecipeManager recipes) { - barrelCompostRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.BARREL_COMPOST); - lavaCrucibleRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.LAVA_CRUCIBLE); - waterCrucibleRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.WATER_CRUCIBLE); - hammerRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.HAMMER).trackAllRecipes(); - compressedHammerRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.COMPRESSED_HAMMER).trackAllRecipes(); - sieveRecipeCache = new SieveRecipeCache<>(recipes, ERecipeTypes.SIEVE); - compressedSieveRecipeCache = new SieveRecipeCache<>(recipes, ERecipeTypes.COMPRESSED_SIEVE); - barrelFluidMixingRecipeCache = new BarrelFluidMixingRecipeCache(recipes); - fluidTransformationRecipeCache = new FluidTransformationRecipeCache(recipes); - crookRecipeCache = new CrookRecipeCache(recipes); - crucibleHeatRecipeCache = new CrucibleHeatRecipeCache(recipes); + public static RecipeCaches getServerRecipeCaches() { + return getServerRecipeCaches(false); } - public static void unload() { - barrelCompostRecipeCache = null; - lavaCrucibleRecipeCache = null; - waterCrucibleRecipeCache = null; - hammerRecipeCache = null; - compressedHammerRecipeCache = null; - sieveRecipeCache = null; - compressedSieveRecipeCache = null; - barrelFluidMixingRecipeCache = null; - fluidTransformationRecipeCache = null; - crookRecipeCache = null; - crucibleHeatRecipeCache = null; + public static RecipeCaches getServerRecipeCaches(boolean skipAssert) { + assert skipAssert || EffectiveSide.get().isServer() : Thread.currentThread().getName(); + return SERVER_RECIPE_CACHES; } - public static List getSieveRecipes(Item mesh, ItemStack item) { - return sieveRecipeCache.getRecipe(mesh, item); - } - - public static List getCompressedSieveRecipes(Item mesh, ItemStack item) { - return compressedSieveRecipeCache.getRecipe(mesh, item); - } - - @Nullable - public static CrucibleRecipe getLavaCrucibleRecipe(ItemStack item) { - return lavaCrucibleRecipeCache.getRecipe(item); - } - - @Nullable - public static CrucibleRecipe getWaterCrucibleRecipe(ItemStack item) { - return waterCrucibleRecipeCache.getRecipe(item); - } - - @Nullable - public static BarrelCompostRecipe getBarrelCompostRecipe(ItemStack item) { - return barrelCompostRecipeCache.getRecipe(item); - } - - @Nullable - public static HammerRecipe getHammerRecipe(Item item) { - return hammerRecipeCache.getRecipe(item); - } - - public static Collection> getCachedHammerRecipes() { - return hammerRecipeCache.getAllRecipes(); - } - - @Nullable - public static CompressedHammerRecipe getCompressedHammerRecipe(Item item) { - return compressedHammerRecipeCache.getRecipe(item); - } - - public static Collection> getCachedCompressedHammerRecipes() { - return compressedHammerRecipeCache.getAllRecipes(); + public static RecipeCaches getCaches(Level level) { + return level.isClientSide() ? ClientsideCode.getRecipeCaches() : getServerRecipeCaches(); } public static void toNetworkNumberProvider(FriendlyByteBuf buffer, NumberProvider provider) { @@ -281,41 +195,6 @@ public final class RecipeUtil { } } - public static boolean isCompostable(ItemStack stack) { - return barrelCompostRecipeCache != null && barrelCompostRecipeCache.getRecipe(stack) != null; - } - - // todo stop using the RecipeManager - @Nullable - public static BarrelMixingRecipe getBarrelMixingRecipe(RecipeManager recipes, ItemStack stack, FluidStack fluid) { - for (var recipe : recipes.byType(ERecipeTypes.BARREL_MIXING.get())) { - if (recipe.value().matches(stack, fluid)) { - return recipe.value(); - } - } - - return null; - } - - @Nullable - public static BarrelFluidMixingRecipe getFluidMixingRecipe(FluidStack base, Fluid additive) { - var recipe = barrelFluidMixingRecipeCache.getRecipe(base.getFluid(), additive); - if (recipe != null && base.getAmount() >= recipe.baseFluid().amount()) { - return recipe; - } else { - return null; - } - } - - @Nullable - public static FluidTransformationRecipe getFluidTransformationRecipe(Fluid baseFluid, BlockState catalystState) { - if (baseFluid != Fluids.EMPTY) { - return fluidTransformationRecipeCache.getRecipe(baseFluid, catalystState); - } else { - return null; - } - } - @SuppressWarnings("IfCanBeSwitch") public static double getExpectedValue(NumberProvider provider) { if (provider instanceof ConstantValue constant) { @@ -352,18 +231,6 @@ public final class RecipeUtil { return new LootContext.Builder(new LootParams(level, Map.of(), Map.of(), 0)).create(Optional.empty()); } - public static List getCrookRecipes(BlockState state) { - return crookRecipeCache.getRecipes(state); - } - - public static int getHeatValue(BlockState state) { - return crucibleHeatRecipeCache.getValue(state); - } - - public static ObjectSet> getHeatSources() { - return crucibleHeatRecipeCache.getEntries(); - } - @SuppressWarnings({"unchecked", "rawtypes"}) public static String writeBlockState(BlockState state) { var registryKey = BuiltInRegistries.BLOCK.getKey(state.getBlock()); @@ -410,13 +277,11 @@ public final class RecipeUtil { return ResourceLocation.tryParse(string) != null; } - /** - * From Forestry: Community Edition - * @return The global registry manager. {@code null} on server when there is no server, or when there is no world (on client). - */ - @Nullable - public static RecipeManager getRecipeManager() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - return server == null ? (FMLEnvironment.dist == Dist.CLIENT ? ClientsideCode.getRecipeManager() : null) : server.getRecipeManager(); + public static RecipeManager getClientRecipeManager() { + return Objects.requireNonNull(ClientsideCode.getRecipeManager()); + } + + public static RecipeManager getServerRecipeManager() { + return Objects.requireNonNull(ServerLifecycleHooks.getCurrentServer()).getRecipeManager(); } }