Skip to content

Commit

Permalink
Fix dynamic recipes in crafting interfaces broken after reload
Browse files Browse the repository at this point in the history
Related to #110
  • Loading branch information
rubensworks committed Aug 20, 2024
1 parent 7b341b4 commit 46c961c
Showing 1 changed file with 33 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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<ICraftingNetwork> 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);
});
}
Expand All @@ -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);
}

Expand All @@ -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();
Expand All @@ -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<IRecipeDefinition> recipes = state.getRecipesIndexed();
IRecipeDefinition oldRecipe = recipes.get(slot);
Expand All @@ -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);
Expand All @@ -269,8 +275,10 @@ public void update(INetwork network, IPartNetwork partNetwork, PartTarget target
}
}
}
slots.clear();
}

// Internal tick counter
state.ticksAfterReload++;
}

@Nullable
Expand Down Expand Up @@ -317,6 +325,8 @@ public void addDrops(PartTarget target, State state, List<ItemStack> itemStacks,
public static class State extends PartStateBase<PartTypeInterfaceCrafting>
implements ICraftingInterface, ICraftingResultsSink {

protected int ticksAfterReload = 0;

private final CraftingJobHandler craftingJobHandler;
private final SimpleInventory inventoryVariables;
private final List<InventoryVariableEvaluator<ValueObjectTypeRecipe.ValueRecipe>> variableEvaluators;
Expand Down Expand Up @@ -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();
Expand All @@ -469,7 +479,7 @@ public void onErrorsChanged() {
}
if (this.partNetwork != null) {
for (int i = 0; i < getInventoryVariables().getContainerSize(); i++) {
reloadRecipe(i);
reloadRecipe(i, initialize);
}
}
}
Expand All @@ -484,7 +494,7 @@ private void setLocalErrors(int slot, List<MutableComponent> 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);
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand All @@ -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);
}
Expand Down

0 comments on commit 46c961c

Please sign in to comment.