diff options
author | tth05 <36999320+tth05@users.noreply.github.com> | 2024-01-20 23:00:50 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-20 23:00:50 +0100 |
commit | 2a3abcc6b8859b11e13c9d95d7426590edf9fefd (patch) | |
tree | 96b9ba00d09a0390e537abfa47969a1824f7ac9b /src/main/java/gregtech/api/util | |
parent | 8aedb43274634bb4df44b67da7a7fe98a33ecf55 (diff) | |
download | GT5-Unofficial-2a3abcc6b8859b11e13c9d95d7426590edf9fefd.tar.gz GT5-Unofficial-2a3abcc6b8859b11e13c9d95d7426590edf9fefd.tar.bz2 GT5-Unofficial-2a3abcc6b8859b11e13c9d95d7426590edf9fefd.zip |
Remove all usages of GT_ItemStack2 as Set/Map keys by using fastutil (#2465)
* Replace Maps in GT_OreDictUnificator with fastutil implementations with custom hasher
Removes the need to allocate a GT_ItemStack2 every time these Maps are accessed
* Replace local HashMaps with Reference2LongArrayMaps in GT_Recipe and fix if condition
* Remove GT_ItemStack2 usage from OrePrefixes
* Update GTNHLib requirement in @Mod annotation
* Don't modify stack argument when re-trying `setItemStack2DataMap` access with wildcard value
Diffstat (limited to 'src/main/java/gregtech/api/util')
-rw-r--r-- | src/main/java/gregtech/api/util/GT_OreDictUnificator.java | 43 | ||||
-rw-r--r-- | src/main/java/gregtech/api/util/GT_Recipe.java | 20 | ||||
-rw-r--r-- | src/main/java/gregtech/api/util/GT_Utility.java | 27 |
3 files changed, 61 insertions, 29 deletions
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; |