aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/gregtech/GT_Mod.java4
-rw-r--r--src/main/java/gregtech/api/GregTech_API.java6
-rw-r--r--src/main/java/gregtech/api/enums/OrePrefixes.java14
-rw-r--r--src/main/java/gregtech/api/objects/GT_ItemStack.java38
-rw-r--r--src/main/java/gregtech/api/objects/GT_ItemStack2.java3
-rw-r--r--src/main/java/gregtech/api/util/GT_OreDictUnificator.java43
-rw-r--r--src/main/java/gregtech/api/util/GT_Recipe.java20
-rw-r--r--src/main/java/gregtech/api/util/GT_Utility.java27
8 files changed, 118 insertions, 37 deletions
diff --git a/src/main/java/gregtech/GT_Mod.java b/src/main/java/gregtech/GT_Mod.java
index 645702055b..90791c95f2 100644
--- a/src/main/java/gregtech/GT_Mod.java
+++ b/src/main/java/gregtech/GT_Mod.java
@@ -128,7 +128,7 @@ import ic2.api.recipe.RecipeOutput;
version = "MC1710",
guiFactory = "gregtech.client.GT_GuiFactory",
dependencies = " required-after:IC2;" + " required-after:structurelib;"
- + " required-after:gtnhlib@[0.0.8,);"
+ + " required-after:gtnhlib@[0.2.1,);"
+ " required-after:modularui@[1.1.12,);"
+ " required-after:appliedenergistics2@[rv3-beta-258,);"
+ " after:dreamcraft;"
@@ -796,7 +796,7 @@ public class GT_Mod implements IGT_Mod {
GT_Utility.reInit();
GT_Recipe.reInit();
try {
- for (Map<? extends ItemHolder, ?> gt_itemStackMap : GregTech_API.sItemStackMappings) {
+ for (Map<?, ?> gt_itemStackMap : GregTech_API.sItemStackMappings) {
GT_Utility.reMap(gt_itemStackMap);
}
for (SetMultimap<? extends ItemHolder, ?> gt_itemStackMap : GregTech_API.itemStackMultiMaps) {
diff --git a/src/main/java/gregtech/api/GregTech_API.java b/src/main/java/gregtech/api/GregTech_API.java
index 1f936f3119..7617b2c195 100644
--- a/src/main/java/gregtech/api/GregTech_API.java
+++ b/src/main/java/gregtech/api/GregTech_API.java
@@ -107,8 +107,12 @@ public class GregTech_API {
public static final long FLUID_MATERIAL_UNIT = L;
/**
* Fixes the HashMap Mappings for ItemStacks once the Server started
+ * <br>
+ * <br>
+ * NOTE: We use wildcards generics for the key because it could be for example {@link ItemStack} or
+ * {@link GT_ItemStack}
*/
- public static final Collection<Map<? extends ItemHolder, ?>> sItemStackMappings = new ArrayList<>();
+ public static final Collection<Map<?, ?>> sItemStackMappings = new ArrayList<>();
public static final Collection<SetMultimap<? extends ItemHolder, ?>> itemStackMultiMaps = new ArrayList<>();
/**
diff --git a/src/main/java/gregtech/api/enums/OrePrefixes.java b/src/main/java/gregtech/api/enums/OrePrefixes.java
index e9294e7258..26dee844e7 100644
--- a/src/main/java/gregtech/api/enums/OrePrefixes.java
+++ b/src/main/java/gregtech/api/enums/OrePrefixes.java
@@ -20,13 +20,14 @@ import gregtech.api.interfaces.ICondition;
import gregtech.api.interfaces.IOreRecipeRegistrator;
import gregtech.api.interfaces.ISubTagContainer;
import gregtech.api.objects.GT_ArrayList;
-import gregtech.api.objects.GT_HashSet;
-import gregtech.api.objects.GT_ItemStack2;
+import gregtech.api.objects.GT_ItemStack;
import gregtech.api.objects.ItemData;
import gregtech.api.objects.MaterialStack;
import gregtech.api.util.GT_Log;
import gregtech.api.util.GT_Utility;
import gregtech.loaders.materialprocessing.ProcessingModSupport;
+import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet;
+import it.unimi.dsi.fastutil.objects.ObjectSet;
public enum OrePrefixes {
@@ -1015,7 +1016,10 @@ public enum OrePrefixes {
public MaterialStack mSecondaryMaterial = null;
public OrePrefixes mPrefixInto = this;
public float mHeatDamage = 0.0F; // Negative for Frost Damage
- private final GT_HashSet<GT_ItemStack2> mContainsTestCache = new GT_HashSet<>(512, 0.5f);
+ private final ObjectSet<ItemStack> mContainsTestCache = new ObjectOpenCustomHashSet<>(
+ 512,
+ 0.5f,
+ GT_ItemStack.ITEMSTACK_HASH_STRATEGY2);
public static final List<OrePrefixes> mPreventableComponents = new LinkedList<>(
Arrays.asList(
OrePrefixes.gem,
@@ -1205,13 +1209,13 @@ public enum OrePrefixes {
if (!contains(aStack)) {
mPrefixedItems.add(aStack);
// It's now in there... so update the cache
- mContainsTestCache.add(new GT_ItemStack2(aStack));
+ mContainsTestCache.add(aStack);
}
return true;
}
public boolean contains(ItemStack aStack) {
- return !GT_Utility.isStackInvalid(aStack) && mContainsTestCache.contains(new GT_ItemStack2(aStack));
+ return !GT_Utility.isStackInvalid(aStack) && mContainsTestCache.contains(aStack);
}
public boolean containsUnCached(ItemStack aStack) {
diff --git a/src/main/java/gregtech/api/objects/GT_ItemStack.java b/src/main/java/gregtech/api/objects/GT_ItemStack.java
index 210f807c5d..492655740d 100644
--- a/src/main/java/gregtech/api/objects/GT_ItemStack.java
+++ b/src/main/java/gregtech/api/objects/GT_ItemStack.java
@@ -7,6 +7,7 @@ import net.minecraft.item.ItemStack;
import gregtech.api.enums.GT_Values;
import gregtech.api.util.GT_Utility;
import gregtech.api.util.item.ItemHolder;
+import it.unimi.dsi.fastutil.Hash;
/**
* An optimization of {@link ItemStack} to have a better {@code hashcode} and {@code equals} in order to improve
@@ -14,6 +15,25 @@ import gregtech.api.util.item.ItemHolder;
*/
public class GT_ItemStack extends ItemHolder {
+ /**
+ * A better {@link Hash.Strategy} for {@link ItemStack}. Implementation originally from {@code GT_ItemStack2}.
+ */
+ public static final Hash.Strategy<ItemStack> ITEMSTACK_HASH_STRATEGY2 = new Hash.Strategy<>() {
+
+ @Override
+ public int hashCode(ItemStack o) {
+ return o.getItem()
+ .hashCode() * 38197 + Items.feather.getDamage(o);
+ }
+
+ @Override
+ public boolean equals(ItemStack a, ItemStack b) {
+ if (a == b) return true;
+ if (a == null || b == null) return false;
+ return a.getItem() == b.getItem() && Items.feather.getDamage(a) == Items.feather.getDamage(b);
+ }
+ };
+
public final Item mItem;
public final byte mStackSize;
public final short mMetaData;
@@ -66,4 +86,22 @@ public class GT_ItemStack extends ItemHolder {
public int hashCode() {
return GT_Utility.stackToInt(toStack());
}
+
+ /**
+ * @see #internalCopyStack(ItemStack, boolean)
+ */
+ public static ItemStack internalCopyStack(ItemStack aStack) {
+ return internalCopyStack(aStack, false);
+ }
+
+ /**
+ * Replicates the copy behavior of {@link #toStack()} but for normal {@link ItemStack}s.
+ *
+ * @param aStack the stack to copy
+ * @param wildcard whether to use wildcard damage value
+ * @return a copy of the stack with stack size 1 and no NBT
+ */
+ public static ItemStack internalCopyStack(ItemStack aStack, boolean wildcard) {
+ return new ItemStack(aStack.getItem(), 1, wildcard ? GT_Values.W : Items.feather.getDamage(aStack));
+ }
}
diff --git a/src/main/java/gregtech/api/objects/GT_ItemStack2.java b/src/main/java/gregtech/api/objects/GT_ItemStack2.java
index b137e78829..aa93876830 100644
--- a/src/main/java/gregtech/api/objects/GT_ItemStack2.java
+++ b/src/main/java/gregtech/api/objects/GT_ItemStack2.java
@@ -7,7 +7,10 @@ import net.minecraft.item.ItemStack;
* GT_ItemStack, but with a better hashCode(). Due to this change, it should not be placed in the same hash based data
* structure with GT_ItemStack. It also shouldn't be used to construct search query into a hash based data structure
* that contains GT_ItemStack.
+ *
+ * @deprecated See {@link GT_ItemStack#ITEMSTACK_HASH_STRATEGY2}
*/
+@Deprecated
public class GT_ItemStack2 extends GT_ItemStack {
public GT_ItemStack2(Item aItem, long aStackSize, long aMetaData) {
diff --git a/src/main/java/gregtech/api/util/GT_OreDictUnificator.java b/src/main/java/gregtech/api/util/GT_OreDictUnificator.java
index 2d493ebe2d..7032fc87fc 100644
--- a/src/main/java/gregtech/api/util/GT_OreDictUnificator.java
+++ b/src/main/java/gregtech/api/util/GT_OreDictUnificator.java
@@ -7,7 +7,6 @@ import static gregtech.api.enums.GT_Values.W;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -25,9 +24,10 @@ import gregtech.api.enums.Materials;
import gregtech.api.enums.OrePrefixes;
import gregtech.api.enums.SubTag;
import gregtech.api.objects.GT_ItemStack;
-import gregtech.api.objects.GT_ItemStack2;
import gregtech.api.objects.ItemData;
import gregtech.api.objects.MaterialStack;
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap;
+import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet;
/**
* NEVER INCLUDE THIS FILE IN YOUR MOD!!!
@@ -41,9 +41,12 @@ import gregtech.api.objects.MaterialStack;
public class GT_OreDictUnificator {
private static final Map<String, ItemStack> sName2StackMap = new HashMap<>();
- private static final Map<GT_ItemStack2, ItemData> sItemStack2DataMap = new HashMap<>();
- private static final Map<GT_ItemStack2, List<ItemStack>> sUnificationTable = new HashMap<>();
- private static final Set<GT_ItemStack2> sNoUnificationList = new HashSet<>();
+ private static final Map<ItemStack, ItemData> sItemStack2DataMap = new Object2ObjectOpenCustomHashMap<>(
+ GT_ItemStack.ITEMSTACK_HASH_STRATEGY2);
+ private static final Map<ItemStack, List<ItemStack>> sUnificationTable = new Object2ObjectOpenCustomHashMap<>(
+ GT_ItemStack.ITEMSTACK_HASH_STRATEGY2);
+ private static final Set<ItemStack> sNoUnificationList = new ObjectOpenCustomHashSet<>(
+ GT_ItemStack.ITEMSTACK_HASH_STRATEGY2);
private static int isRegisteringOre = 0, isAddingOre = 0;
private static boolean mRunThroughTheList = true;
@@ -57,12 +60,12 @@ public class GT_OreDictUnificator {
* the Industrial Diamond, which is better than regular Diamond, but also usable in absolutely all Diamond Recipes.
*/
public static void addToBlacklist(ItemStack aStack) {
- if (GT_Utility.isStackValid(aStack) && !GT_Utility.isStackInList(aStack, sNoUnificationList))
- sNoUnificationList.add(new GT_ItemStack2(aStack));
+ if (GT_Utility.isStackValid(aStack) && !GT_Utility.isStackInStackSet(aStack, sNoUnificationList))
+ sNoUnificationList.add(aStack);
}
public static boolean isBlacklisted(ItemStack aStack) {
- return GT_Utility.isStackInList(aStack, sNoUnificationList);
+ return GT_Utility.isStackInStackSet(aStack, sNoUnificationList);
}
public static void add(OrePrefixes aPrefix, Materials aMaterial, ItemStack aStack) {
@@ -281,12 +284,11 @@ public class GT_OreDictUnificator {
// 5900x tries to do NEI lookup
synchronized (sUnificationTable) {
if (sUnificationTable.isEmpty() && !sItemStack2DataMap.isEmpty()) {
- for (GT_ItemStack tGTStack0 : sItemStack2DataMap.keySet()) {
- ItemStack tStack0 = tGTStack0.toStack();
+ for (ItemStack tGTStack0 : sItemStack2DataMap.keySet()) {
+ ItemStack tStack0 = GT_ItemStack.internalCopyStack(tGTStack0);
ItemStack tStack1 = get_nocopy(false, tStack0);
if (!GT_Utility.areStacksEqual(tStack0, tStack1)) {
- GT_ItemStack2 tGTStack1 = new GT_ItemStack2(tStack1);
- List<ItemStack> list = sUnificationTable.computeIfAbsent(tGTStack1, k -> new ArrayList<>());
+ List<ItemStack> list = sUnificationTable.computeIfAbsent(tStack1, k -> new ArrayList<>());
// greg's original code tries to dedupe the list using List#contains, which won't work
// on vanilla ItemStack. I removed it since it never worked and can be slow.
list.add(tStack0);
@@ -303,7 +305,7 @@ public class GT_OreDictUnificator {
for (ItemStack aStack : aStacks) {
if (aStack == null) continue;
rList.add(aStack);
- List<ItemStack> tList = sUnificationTable.get(new GT_ItemStack2(aStack));
+ List<ItemStack> tList = sUnificationTable.get(aStack);
if (tList != null) {
for (ItemStack tStack : tList) {
ItemStack tStack1 = GT_Utility.copyAmount(aStack.stackSize, tStack);
@@ -346,7 +348,7 @@ public class GT_OreDictUnificator {
for (MaterialStack tMaterial : aData.mByProducts) tMaterial.mAmount /= aStack.stackSize;
aStack = GT_Utility.copyAmount(1, aStack);
}
- sItemStack2DataMap.put(new GT_ItemStack2(aStack), aData);
+ sItemStack2DataMap.put(aStack, aData);
if (aData.hasValidMaterialData()) {
long tValidMaterialAmount = aData.mMaterial.mMaterial.contains(SubTag.NO_RECYCLING) ? 0
: aData.mMaterial.mAmount >= 0 ? aData.mMaterial.mAmount : M;
@@ -358,11 +360,10 @@ public class GT_OreDictUnificator {
if (mRunThroughTheList) {
if (GregTech_API.sLoadStarted) {
mRunThroughTheList = false;
- for (Entry<GT_ItemStack2, ItemData> tEntry : sItemStack2DataMap.entrySet()) if (!tEntry.getValue()
+ for (Entry<ItemStack, ItemData> tEntry : sItemStack2DataMap.entrySet()) if (!tEntry.getValue()
.hasValidPrefixData() || tEntry.getValue().mPrefix.mAllowNormalRecycling)
GT_RecipeRegistrator.registerMaterialRecycling(
- tEntry.getKey()
- .toStack(),
+ GT_ItemStack.internalCopyStack(tEntry.getKey()),
tEntry.getValue());
}
} else {
@@ -379,7 +380,7 @@ public class GT_OreDictUnificator {
if (GT_Utility.isStackInvalid(aStack)) {
return;
}
- sItemStack2DataMap.remove(new GT_ItemStack2(aStack));
+ sItemStack2DataMap.remove(aStack);
}
public static void addAssociation(OrePrefixes aPrefix, Materials aMaterial, ItemStack aStack,
@@ -393,8 +394,10 @@ public class GT_OreDictUnificator {
@Nullable
public static ItemData getItemData(ItemStack aStack) {
if (GT_Utility.isStackInvalid(aStack)) return null;
- ItemData rData = sItemStack2DataMap.get(new GT_ItemStack2(aStack));
- if (rData == null) rData = sItemStack2DataMap.get(new GT_ItemStack2(aStack, true));
+ ItemData rData = sItemStack2DataMap.get(aStack);
+ if (rData == null) { // Try the lookup again but with wildcard damage value
+ rData = sItemStack2DataMap.get(GT_ItemStack.internalCopyStack(aStack, true));
+ }
return rData;
}
diff --git a/src/main/java/gregtech/api/util/GT_Recipe.java b/src/main/java/gregtech/api/util/GT_Recipe.java
index a7c6c654e7..b06c7f9e64 100644
--- a/src/main/java/gregtech/api/util/GT_Recipe.java
+++ b/src/main/java/gregtech/api/util/GT_Recipe.java
@@ -36,6 +36,8 @@ import gregtech.api.recipe.metadata.IRecipeMetadataStorage;
import gregtech.api.util.extensions.ArrayExt;
import gregtech.api.util.item.ItemHolder;
import ic2.core.Ic2Items;
+import it.unimi.dsi.fastutil.objects.Reference2LongArrayMap;
+import it.unimi.dsi.fastutil.objects.Reference2LongMap;
public class GT_Recipe implements Comparable<GT_Recipe> {
@@ -486,25 +488,27 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
double currentParallel = maxParallel;
- if (aFluidInputs != null) {
+ // We need to have any fluids inputs, otherwise the code below does nothing. The second check is always true
+ // because of early exit condition above.
+ if (mFluidInputs.length > 0 /* && aFluidInputs != null */) {
// Create map for fluid -> stored amount
- Map<Fluid, Long> fluidMap = new HashMap<>();
- Map<Fluid, Long> fluidCost = new HashMap<>();
+ Reference2LongMap<Fluid> fluidMap = new Reference2LongArrayMap<>(4);
+ Reference2LongMap<Fluid> fluidCost = new Reference2LongArrayMap<>(4);
for (FluidStack fluidStack : aFluidInputs) {
if (fluidStack == null) continue;
- fluidMap.merge(fluidStack.getFluid(), (long) fluidStack.amount, Long::sum);
+ fluidMap.mergeLong(fluidStack.getFluid(), fluidStack.amount, Long::sum);
}
for (FluidStack fluidStack : mFluidInputs) {
if (fluidStack == null) continue;
- fluidCost.merge(fluidStack.getFluid(), (long) fluidStack.amount, Long::sum);
+ fluidCost.mergeLong(fluidStack.getFluid(), fluidStack.amount, Long::sum);
}
// Check how many parallels can it perform for each fluid
- for (Map.Entry<Fluid, Long> costEntry : fluidCost.entrySet()) {
- if (costEntry.getValue() > 0) {
+ for (Reference2LongMap.Entry<Fluid> costEntry : fluidCost.reference2LongEntrySet()) {
+ if (costEntry.getLongValue() > 0) {
currentParallel = Math.min(
currentParallel,
- (double) fluidMap.getOrDefault(costEntry.getKey(), 0L) / costEntry.getValue());
+ (double) fluidMap.getOrDefault(costEntry.getKey(), 0L) / costEntry.getLongValue());
}
if (currentParallel <= 0) {
return 0;
diff --git a/src/main/java/gregtech/api/util/GT_Utility.java b/src/main/java/gregtech/api/util/GT_Utility.java
index d41e2a3b04..7959789532 100644
--- a/src/main/java/gregtech/api/util/GT_Utility.java
+++ b/src/main/java/gregtech/api/util/GT_Utility.java
@@ -3137,6 +3137,13 @@ public class GT_Utility {
return aList[aIndex];
}
+ public static boolean isStackInStackSet(ItemStack aStack, Set<ItemStack> aSet) {
+ if (aStack == null) return false;
+ if (aSet.contains(aStack)) return true;
+
+ return aSet.contains(GT_ItemStack.internalCopyStack(aStack, true));
+ }
+
public static boolean isStackInList(ItemStack aStack, Collection<GT_ItemStack> aList) {
if (aStack == null) {
return false;
@@ -3165,7 +3172,25 @@ public class GT_Utility {
* re-maps all Keys of a Map after the Keys were weakened.
*/
public static <X, Y> Map<X, Y> reMap(Map<X, Y> aMap) {
- Map<X, Y> tMap = new HashMap<>(aMap);
+ Map<X, Y> tMap = null;
+ // We try to clone the Map first (most Maps are Cloneable) in order to retain as much state of the Map as
+ // possible when rehashing. For example, "Custom" HashMaps from fastutil may have a custom hash function which
+ // would not be used to rehash if we just create a new HashMap.
+ if (aMap instanceof Cloneable) {
+ try {
+ tMap = (Map<X, Y>) aMap.getClass()
+ .getMethod("clone")
+ .invoke(aMap);
+ } catch (Throwable e) {
+ GT_Log.err.println("Failed to clone Map of type " + aMap.getClass());
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ if (tMap == null) {
+ tMap = new HashMap<>(aMap);
+ }
+
aMap.clear();
aMap.putAll(tMap);
return aMap;