From 46c961ca0dadf515e377316fa3b7228ff4e1d054 Mon Sep 17 00:00:00 2001 From: Ruben Taelman Date: Tue, 20 Aug 2024 20:32:57 +0200 Subject: [PATCH 1/3] Fix dynamic recipes in crafting interfaces broken after reload Related to CyclopsMC/IntegratedCrafting#110 --- .../part/PartTypeInterfaceCrafting.java | 50 ++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/cyclops/integratedcrafting/part/PartTypeInterfaceCrafting.java b/src/main/java/org/cyclops/integratedcrafting/part/PartTypeInterfaceCrafting.java index 9b9e18eb..c43e1e23 100644 --- a/src/main/java/org/cyclops/integratedcrafting/part/PartTypeInterfaceCrafting.java +++ b/src/main/java/org/cyclops/integratedcrafting/part/PartTypeInterfaceCrafting.java @@ -7,6 +7,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.IntArraySet; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -159,7 +160,7 @@ protected PartTypeInterfaceCrafting.State constructDefaultState() { @Override public void afterNetworkReAlive(INetwork network, IPartNetwork partNetwork, PartTarget target, PartTypeInterfaceCrafting.State state) { super.afterNetworkReAlive(network, partNetwork, target, state); - addTargetToNetwork(network, target, state); + addTargetToNetwork(network, target, state, true); } @Override @@ -171,7 +172,7 @@ public void onNetworkRemoval(INetwork network, IPartNetwork partNetwork, PartTar @Override public void onNetworkAddition(INetwork network, IPartNetwork partNetwork, PartTarget target, PartTypeInterfaceCrafting.State state) { super.onNetworkAddition(network, partNetwork, target, state); - addTargetToNetwork(network, target, state); + addTargetToNetwork(network, target, state, true); } @Override @@ -180,19 +181,19 @@ public void setPriorityAndChannel(INetwork network, IPartNetwork partNetwork, Pa // so we have to re-add it. removeTargetFromNetwork(network, target.getTarget(), state); super.setPriorityAndChannel(network, partNetwork, target, state, priority, channel); - addTargetToNetwork(network, target, state); + addTargetToNetwork(network, target, state, false); } protected Capability getNetworkCapability() { return CraftingNetworkConfig.CAPABILITY; } - protected void addTargetToNetwork(INetwork network, PartTarget pos, PartTypeInterfaceCrafting.State state) { + protected void addTargetToNetwork(INetwork network, PartTarget pos, PartTypeInterfaceCrafting.State state, boolean initialize) { network.getCapability(getNetworkCapability()) .ifPresent(craftingNetwork -> { int channelCrafting = state.getChannelCrafting(); state.setTarget(pos); - state.setNetworks(network, craftingNetwork, NetworkHelpers.getPartNetworkChecked(network), channelCrafting); + state.setNetworks(network, craftingNetwork, NetworkHelpers.getPartNetworkChecked(network), channelCrafting, initialize); state.setShouldAddToCraftingNetwork(true); }); } @@ -203,7 +204,7 @@ protected void removeTargetFromNetwork(INetwork network, PartPos pos, PartTypeIn network.getCapability(getNetworkCapability()) .ifPresent(n -> n.removeCraftingInterface(state.getChannelCrafting(), state)); } - state.setNetworks(null, null, null, -1); + state.setNetworks(null, null, null, -1, false); state.setTarget(null); } @@ -224,7 +225,7 @@ public void update(INetwork network, IPartNetwork partNetwork, PartTarget target // Init network data in part state if it has not been done yet. // This can occur when the part chunk is being reloaded. if (state.getCraftingNetwork() == null) { - addTargetToNetwork(network, target, state); + addTargetToNetwork(network, target, state, false); } int channel = state.getChannelCrafting(); @@ -251,7 +252,9 @@ public void update(INetwork network, IPartNetwork partNetwork, PartTarget target if (!slots.isEmpty()) { ICraftingNetwork craftingNetwork = network.getCapability(getNetworkCapability()).orElse(null); if (craftingNetwork != null) { - for (Integer slot : slots) { + IntSet slotsCopy = new IntOpenHashSet(slots); // Create a copy, to allow insertion into slots during this loop + slots.clear(); + for (Integer slot : slotsCopy) { // Remove the old recipe from the network Int2ObjectMap recipes = state.getRecipesIndexed(); IRecipeDefinition oldRecipe = recipes.get(slot); @@ -260,7 +263,10 @@ public void update(INetwork network, IPartNetwork partNetwork, PartTarget target } // Reload the recipe in the slot - state.reloadRecipe(slot); + // We simulate initialization for the first two ticks, as dependency variables may still be loading, + // and errored may only go away after these dependencies are fully loaded. + // Related to CyclopsMC/IntegratedCrafting#110 + state.reloadRecipe(slot, state.ticksAfterReload <= 1); // Add the new recipe to the network IRecipeDefinition newRecipe = recipes.get(slot); @@ -269,8 +275,10 @@ public void update(INetwork network, IPartNetwork partNetwork, PartTarget target } } } - slots.clear(); } + + // Internal tick counter + state.ticksAfterReload++; } @Nullable @@ -317,6 +325,8 @@ public void addDrops(PartTarget target, State state, List itemStacks, public static class State extends PartStateBase implements ICraftingInterface, ICraftingResultsSink { + protected int ticksAfterReload = 0; + private final CraftingJobHandler craftingJobHandler; private final SimpleInventory inventoryVariables; private final List> variableEvaluators; @@ -451,7 +461,7 @@ public int getChannelCrafting() { return channelCrafting; } - public void reloadRecipes() { + public void reloadRecipes(boolean initialize) { this.currentRecipes.clear(); this.recipeSlotMessages.clear(); this.recipeSlotValidated.clear(); @@ -469,7 +479,7 @@ public void onErrorsChanged() { } if (this.partNetwork != null) { for (int i = 0; i < getInventoryVariables().getContainerSize(); i++) { - reloadRecipe(i); + reloadRecipe(i, initialize); } } } @@ -484,7 +494,7 @@ private void setLocalErrors(int slot, List errors) { } } - protected void reloadRecipe(int slot) { + protected void reloadRecipe(int slot, boolean initialize) { this.currentRecipes.remove(slot); if (this.recipeSlotMessages.size() > slot) { this.recipeSlotMessages.remove(slot); @@ -528,7 +538,13 @@ protected void reloadRecipe(int slot) { this.recipeSlotMessages.put(slot, e.getErrorMessage()); } } else { - this.recipeSlotMessages.put(slot, Component.translatable("gui.integratedcrafting.partinterface.slot.message.norecipe")); + // If we're initializing, the variable might be referencing other variables that are not yet loaded. + // So let's retry once in the next tick. + if (initialize && evaluator.hasVariable()) { + this.delayedReloadRecipe(slot); + } else { + this.recipeSlotMessages.put(slot, Component.translatable("gui.integratedcrafting.partinterface.slot.message.norecipe")); + } } try { @@ -594,7 +610,7 @@ public void onDirty() { // Recalculate recipes if (getTarget() != null && !getTarget().getCenter().getPos().getLevel(true).isClientSide) { - reloadRecipes(); + reloadRecipes(false); } // Re-register to the network, to force an update for all new recipes @@ -612,12 +628,12 @@ public PartTarget getTarget() { } public void setNetworks(@Nullable INetwork network, @Nullable ICraftingNetwork craftingNetwork, - @Nullable IPartNetwork partNetwork, int channel) { + @Nullable IPartNetwork partNetwork, int channel, boolean initialize) { this.network = network; this.craftingNetwork = craftingNetwork; this.partNetwork = partNetwork; this.channel = channel; - reloadRecipes(); + reloadRecipes(initialize); if (network != null) { this.getCraftingJobHandler().reRegisterObservers(network); } From 19f63979951907dbc47edd71548108909e5ec230 Mon Sep 17 00:00:00 2001 From: Ruben Taelman Date: Wed, 21 Aug 2024 17:31:09 +0200 Subject: [PATCH 2/3] Bump ID version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index a23abd81..a33dfa69 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ mod_version=1.1.6 minecraft_version=1.19.2 forge_version=43.0.8 cyclopscore_version=1.17.0-237 -integrateddynamics_version=1.19.2-1.20.0-659 +integrateddynamics_version=1.19.2-1.22.0-726 release_type=release fingerprint=bd0353b3e8a2810d60dd584e256e364bc3bedd44 From d6f8cbac50ad3786a8418a2d8a6461266073704a Mon Sep 17 00:00:00 2001 From: Ruben Taelman Date: Wed, 21 Aug 2024 17:34:05 +0200 Subject: [PATCH 3/3] Bump mod version --- gradle.properties | 2 +- resources/changelog/1.19.2-1.1.7.txt | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 resources/changelog/1.19.2-1.1.7.txt diff --git a/gradle.properties b/gradle.properties index a33dfa69..355d5c14 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -mod_version=1.1.6 +mod_version=1.1.7 minecraft_version=1.19.2 forge_version=43.0.8 cyclopscore_version=1.17.0-237 diff --git a/resources/changelog/1.19.2-1.1.7.txt b/resources/changelog/1.19.2-1.1.7.txt new file mode 100644 index 00000000..e9f69bbb --- /dev/null +++ b/resources/changelog/1.19.2-1.1.7.txt @@ -0,0 +1,7 @@ +As always, don't forget to backup your world before updating! +Requires CyclopsCore version 1.17.0 or higher. + +Fixes: +* Fix dynamic recipes in crafting interfaces broken after reload + Related to CyclopsMC/IntegratedCrafting#110 +