Skip to content

Commit

Permalink
Fix issues with factories displaying wrong warnings at times on serve…
Browse files Browse the repository at this point in the history
…rs due to Map#of iteration order having been different on the client than the server
  • Loading branch information
pupnewfster committed Jul 21, 2022
1 parent fec4c6d commit 19a5d53
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 52 deletions.
@@ -1,6 +1,7 @@
package mekanism.common.tile.factory;

import java.util.Map;
import java.util.List;
import java.util.Set;
import mekanism.api.IContentsListener;
import mekanism.api.inventory.IInventorySlot;
import mekanism.api.math.MathUtils;
Expand Down Expand Up @@ -33,12 +34,16 @@

public class TileEntityCombiningFactory extends TileEntityItemToItemFactory<CombinerRecipe> implements DoubleItemRecipeLookupHandler<CombinerRecipe> {

private static final Map<RecipeError, Boolean> TRACKED_ERROR_TYPES = Map.of(
RecipeError.NOT_ENOUGH_ENERGY, true,
RecipeError.NOT_ENOUGH_INPUT, false,
RecipeError.NOT_ENOUGH_SECONDARY_INPUT, true,
RecipeError.NOT_ENOUGH_OUTPUT_SPACE, false,
RecipeError.INPUT_DOESNT_PRODUCE_OUTPUT, false
private static final List<RecipeError> TRACKED_ERROR_TYPES = List.of(
RecipeError.NOT_ENOUGH_ENERGY,
RecipeError.NOT_ENOUGH_INPUT,
RecipeError.NOT_ENOUGH_SECONDARY_INPUT,
RecipeError.NOT_ENOUGH_OUTPUT_SPACE,
RecipeError.INPUT_DOESNT_PRODUCE_OUTPUT
);
private static final Set<RecipeError> GLOBAL_ERROR_TYPES = Set.of(
RecipeError.NOT_ENOUGH_ENERGY,
RecipeError.NOT_ENOUGH_SECONDARY_INPUT
);

private final IInputHandler<@NotNull ItemStack> extraInputHandler;
Expand All @@ -47,7 +52,7 @@ public class TileEntityCombiningFactory extends TileEntityItemToItemFactory<Comb
private InputInventorySlot extraSlot;

public TileEntityCombiningFactory(IBlockProvider blockProvider, BlockPos pos, BlockState state) {
super(blockProvider, pos, state, TRACKED_ERROR_TYPES);
super(blockProvider, pos, state, TRACKED_ERROR_TYPES, GLOBAL_ERROR_TYPES);
extraInputHandler = InputHelper.getInputHandler(extraSlot, RecipeError.NOT_ENOUGH_SECONDARY_INPUT);
}

Expand Down
19 changes: 10 additions & 9 deletions src/main/java/mekanism/common/tile/factory/TileEntityFactory.java
@@ -1,7 +1,7 @@
package mekanism.common.tile.factory;

import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntArraySet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -114,7 +114,7 @@ public abstract class TileEntityFactory<RECIPE extends MekanismRecipe> extends T
@WrappingComputerMethod(wrapper = ComputerIInventorySlotWrapper.class, methodNames = "getEnergyItem")
protected EnergyInventorySlot energySlot;

protected TileEntityFactory(IBlockProvider blockProvider, BlockPos pos, BlockState state, Map<RecipeError, Boolean> errorTypes) {
protected TileEntityFactory(IBlockProvider blockProvider, BlockPos pos, BlockState state, List<RecipeError> errorTypes, Set<RecipeError> globalErrorTypes) {
super(blockProvider, pos, state);
type = Attribute.get(blockProvider, AttributeFactoryType.class).getFactoryType();
configComponent = new TileComponentConfig(this, TransmissionType.ITEM, TransmissionType.ENERGY);
Expand Down Expand Up @@ -149,7 +149,7 @@ protected TileEntityFactory(IBlockProvider blockProvider, BlockPos pos, BlockSta
//Note: We store one per slot so that we can recheck the different slots at different times to reduce the load on the server
recheckAllRecipeErrors[i] = TileEntityRecipeMachine.shouldRecheckAllErrors(this);
}
errorTracker = new ErrorTracker(errorTypes, tier.processes);
errorTracker = new ErrorTracker(errorTypes, globalErrorTypes, tier.processes);
}

/**
Expand Down Expand Up @@ -744,18 +744,19 @@ public int getMinPerSlot() {
protected static class ErrorTracker {

private final List<RecipeError> errorTypes;
private final IntList globalTypes;
private final IntSet globalTypes;

//TODO: See if we can get it so we only have to sync a single version of global types?
private final boolean[][] trackedErrors;
private final int processes;

public ErrorTracker(Map<RecipeError, Boolean> errorTypes, int processes) {
this.errorTypes = List.copyOf(errorTypes.keySet());
globalTypes = new IntArrayList();
public ErrorTracker(List<RecipeError> errorTypes, Set<RecipeError> globalErrorTypes, int processes) {
//Copy the list if it is mutable to ensure it doesn't get changed, otherwise just use the list
this.errorTypes = List.copyOf(errorTypes);
globalTypes = new IntArraySet(globalErrorTypes.size());
for (int i = 0; i < this.errorTypes.size(); i++) {
RecipeError error = this.errorTypes.get(i);
if (errorTypes.get(error)) {
if (globalErrorTypes.contains(error)) {
globalTypes.add(i);
}
}
Expand Down
@@ -1,7 +1,8 @@
package mekanism.common.tile.factory;

import java.util.Arrays;
import java.util.Map;
import java.util.List;
import java.util.Set;
import mekanism.api.IContentsListener;
import mekanism.api.NBTConstants;
import mekanism.api.Upgrade;
Expand Down Expand Up @@ -56,12 +57,16 @@
public class TileEntityItemStackGasToItemStackFactory extends TileEntityItemToItemFactory<ItemStackGasToItemStackRecipe> implements IHasDumpButton,
ItemChemicalRecipeLookupHandler<Gas, GasStack, ItemStackGasToItemStackRecipe>, ConstantUsageRecipeLookupHandler {

private static final Map<RecipeError, Boolean> TRACKED_ERROR_TYPES = Map.of(
RecipeError.NOT_ENOUGH_ENERGY, true,
RecipeError.NOT_ENOUGH_INPUT, false,
RecipeError.NOT_ENOUGH_SECONDARY_INPUT, true,
RecipeError.NOT_ENOUGH_OUTPUT_SPACE, false,
RecipeError.INPUT_DOESNT_PRODUCE_OUTPUT, false
private static final List<RecipeError> TRACKED_ERROR_TYPES = List.of(
RecipeError.NOT_ENOUGH_ENERGY,
RecipeError.NOT_ENOUGH_INPUT,
RecipeError.NOT_ENOUGH_SECONDARY_INPUT,
RecipeError.NOT_ENOUGH_OUTPUT_SPACE,
RecipeError.INPUT_DOESNT_PRODUCE_OUTPUT
);
private static final Set<RecipeError> GLOBAL_ERROR_TYPES = Set.of(
RecipeError.NOT_ENOUGH_ENERGY,
RecipeError.NOT_ENOUGH_SECONDARY_INPUT
);

private final ILongInputHandler<@NotNull GasStack> gasInputHandler;
Expand All @@ -76,7 +81,7 @@ public class TileEntityItemStackGasToItemStackFactory extends TileEntityItemToIt
private long baseTotalUsage;

public TileEntityItemStackGasToItemStackFactory(IBlockProvider blockProvider, BlockPos pos, BlockState state) {
super(blockProvider, pos, state, TRACKED_ERROR_TYPES);
super(blockProvider, pos, state, TRACKED_ERROR_TYPES, GLOBAL_ERROR_TYPES);
gasInputHandler = InputHelper.getConstantInputHandler(gasTank);
configComponent.addSupported(TransmissionType.GAS);
configComponent.setupInputConfig(TransmissionType.GAS, gasTank);
Expand Down
@@ -1,6 +1,7 @@
package mekanism.common.tile.factory;

import java.util.Map;
import java.util.List;
import java.util.Set;
import mekanism.api.inventory.IInventorySlot;
import mekanism.api.math.MathUtils;
import mekanism.api.providers.IBlockProvider;
Expand All @@ -25,15 +26,16 @@
public class TileEntityItemStackToItemStackFactory extends TileEntityItemToItemFactory<ItemStackToItemStackRecipe> implements
ItemRecipeLookupHandler<ItemStackToItemStackRecipe> {

private static final Map<RecipeError, Boolean> TRACKED_ERROR_TYPES = Map.of(
RecipeError.NOT_ENOUGH_ENERGY, true,
RecipeError.NOT_ENOUGH_INPUT, false,
RecipeError.NOT_ENOUGH_OUTPUT_SPACE, false,
RecipeError.INPUT_DOESNT_PRODUCE_OUTPUT, false
private static final List<RecipeError> TRACKED_ERROR_TYPES = List.of(
RecipeError.NOT_ENOUGH_ENERGY,
RecipeError.NOT_ENOUGH_INPUT,
RecipeError.NOT_ENOUGH_OUTPUT_SPACE,
RecipeError.INPUT_DOESNT_PRODUCE_OUTPUT
);
private static final Set<RecipeError> GLOBAL_ERROR_TYPES = Set.of(RecipeError.NOT_ENOUGH_ENERGY);

public TileEntityItemStackToItemStackFactory(IBlockProvider blockProvider, BlockPos pos, BlockState state) {
super(blockProvider, pos, state, TRACKED_ERROR_TYPES);
super(blockProvider, pos, state, TRACKED_ERROR_TYPES, GLOBAL_ERROR_TYPES);
}

@Override
Expand Down
@@ -1,6 +1,7 @@
package mekanism.common.tile.factory;

import java.util.Map;
import java.util.List;
import java.util.Set;
import mekanism.api.IContentsListener;
import mekanism.api.providers.IBlockProvider;
import mekanism.api.recipes.MekanismRecipe;
Expand All @@ -24,8 +25,8 @@ public abstract class TileEntityItemToItemFactory<RECIPE extends MekanismRecipe>
protected IInputHandler<@NotNull ItemStack>[] inputHandlers;
protected IOutputHandler<@NotNull ItemStack>[] outputHandlers;

protected TileEntityItemToItemFactory(IBlockProvider blockProvider, BlockPos pos, BlockState state, Map<RecipeError, Boolean> errorTypes) {
super(blockProvider, pos, state, errorTypes);
protected TileEntityItemToItemFactory(IBlockProvider blockProvider, BlockPos pos, BlockState state, List<RecipeError> errorTypes, Set<RecipeError> globalErrorTypes) {
super(blockProvider, pos, state, errorTypes, globalErrorTypes);
}

@Override
Expand Down
@@ -1,6 +1,7 @@
package mekanism.common.tile.factory;

import java.util.Map;
import java.util.List;
import java.util.Set;
import mekanism.api.IContentsListener;
import mekanism.api.RelativeSide;
import mekanism.api.chemical.ChemicalTankBuilder;
Expand Down Expand Up @@ -46,12 +47,16 @@
public class TileEntityMetallurgicInfuserFactory extends TileEntityItemToItemFactory<MetallurgicInfuserRecipe> implements IHasDumpButton,
ItemChemicalRecipeLookupHandler<InfuseType, InfusionStack, MetallurgicInfuserRecipe> {

private static final Map<RecipeError, Boolean> TRACKED_ERROR_TYPES = Map.of(
RecipeError.NOT_ENOUGH_ENERGY, true,
RecipeError.NOT_ENOUGH_INPUT, false,
RecipeError.NOT_ENOUGH_SECONDARY_INPUT, true,
RecipeError.NOT_ENOUGH_OUTPUT_SPACE, false,
RecipeError.INPUT_DOESNT_PRODUCE_OUTPUT, false
private static final List<RecipeError> TRACKED_ERROR_TYPES = List.of(
RecipeError.NOT_ENOUGH_ENERGY,
RecipeError.NOT_ENOUGH_INPUT,
RecipeError.NOT_ENOUGH_SECONDARY_INPUT,
RecipeError.NOT_ENOUGH_OUTPUT_SPACE,
RecipeError.INPUT_DOESNT_PRODUCE_OUTPUT
);
private static final Set<RecipeError> GLOBAL_ERROR_TYPES = Set.of(
RecipeError.NOT_ENOUGH_ENERGY,
RecipeError.NOT_ENOUGH_SECONDARY_INPUT
);

private final IInputHandler<@NotNull InfusionStack> infusionInputHandler;
Expand All @@ -63,7 +68,7 @@ public class TileEntityMetallurgicInfuserFactory extends TileEntityItemToItemFac
private IInfusionTank infusionTank;

public TileEntityMetallurgicInfuserFactory(IBlockProvider blockProvider, BlockPos pos, BlockState state) {
super(blockProvider, pos, state, TRACKED_ERROR_TYPES);
super(blockProvider, pos, state, TRACKED_ERROR_TYPES, GLOBAL_ERROR_TYPES);
infusionInputHandler = InputHelper.getInputHandler(infusionTank, RecipeError.NOT_ENOUGH_SECONDARY_INPUT);
configComponent.addSupported(TransmissionType.INFUSION);
configComponent.setupIOConfig(TransmissionType.INFUSION, infusionTank, RelativeSide.RIGHT).setCanEject(false);
Expand Down
@@ -1,6 +1,7 @@
package mekanism.common.tile.factory;

import java.util.Map;
import java.util.List;
import java.util.Set;
import mekanism.api.IContentsListener;
import mekanism.api.inventory.IInventorySlot;
import mekanism.api.math.MathUtils;
Expand Down Expand Up @@ -40,19 +41,20 @@

public class TileEntitySawingFactory extends TileEntityFactory<SawmillRecipe> implements ItemRecipeLookupHandler<SawmillRecipe> {

private static final Map<RecipeError, Boolean> TRACKED_ERROR_TYPES = Map.of(
RecipeError.NOT_ENOUGH_ENERGY, true,
RecipeError.NOT_ENOUGH_INPUT, false,
RecipeError.NOT_ENOUGH_OUTPUT_SPACE, false,
TileEntityPrecisionSawmill.NOT_ENOUGH_SPACE_SECONDARY_OUTPUT_ERROR, false,
RecipeError.INPUT_DOESNT_PRODUCE_OUTPUT, false
private static final List<RecipeError> TRACKED_ERROR_TYPES = List.of(
RecipeError.NOT_ENOUGH_ENERGY,
RecipeError.NOT_ENOUGH_INPUT,
RecipeError.NOT_ENOUGH_OUTPUT_SPACE,
TileEntityPrecisionSawmill.NOT_ENOUGH_SPACE_SECONDARY_OUTPUT_ERROR,
RecipeError.INPUT_DOESNT_PRODUCE_OUTPUT
);
private static final Set<RecipeError> GLOBAL_ERROR_TYPES = Set.of(RecipeError.NOT_ENOUGH_ENERGY);

protected IInputHandler<@NotNull ItemStack>[] inputHandlers;
protected IOutputHandler<@NotNull ChanceOutput>[] outputHandlers;

public TileEntitySawingFactory(IBlockProvider blockProvider, BlockPos pos, BlockState state) {
super(blockProvider, pos, state, TRACKED_ERROR_TYPES);
super(blockProvider, pos, state, TRACKED_ERROR_TYPES, GLOBAL_ERROR_TYPES);
}

@Override
Expand Down
Expand Up @@ -49,7 +49,8 @@ public abstract class TileEntityRecipeMachine<RECIPE extends MekanismRecipe> ext

protected TileEntityRecipeMachine(IBlockProvider blockProvider, BlockPos pos, BlockState state, List<RecipeError> errorTypes) {
super(blockProvider, pos, state);
this.errorTypes = errorTypes;
//Copy the list if it is mutable to ensure it doesn't get changed, otherwise just use the list
this.errorTypes = List.copyOf(errorTypes);
recheckAllRecipeErrors = shouldRecheckAllErrors(this);
trackedErrors = new boolean[this.errorTypes.size()];
//Clear the memory if we didn't use it. Note: We can set this to null as we pass it by reference so if it is not used
Expand Down

0 comments on commit 19a5d53

Please sign in to comment.