Compare commits
2 Commits
a1c74b64c0
...
a49c75bce0
Author | SHA1 | Date |
---|---|---|
Tom Dodd | a49c75bce0 | |
Tom Dodd | 84360b38c0 |
|
@ -3,7 +3,7 @@ v2o.4.7
|
|||
+ Added quantum computer Python Qiskit code generation
|
||||
* Code is now generated by using a code generator component rather than the controller
|
||||
|
||||
+ Added salt to recipe hash caching to avoid clashes (salt is incremented if a clash occurs and hashes are recalculated)
|
||||
+ Fixed issues with rare hash clashes while caching recipe inputs
|
||||
|
||||
* Fixed broken quantum computer component recipes
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import com.google.common.collect.Lists;
|
|||
import crafttweaker.annotations.ZenRegister;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import it.unimi.dsi.fastutil.longs.*;
|
||||
import it.unimi.dsi.fastutil.objects.*;
|
||||
import nc.recipe.ingredient.*;
|
||||
import nc.tile.internal.fluid.Tank;
|
||||
import nc.util.*;
|
||||
|
@ -25,8 +26,7 @@ public abstract class AbstractRecipeHandler<RECIPE extends IRecipe> {
|
|||
|
||||
protected @Nonnull List<RECIPE> recipeList = new ArrayList<>();
|
||||
|
||||
protected @Nonnull Long2ObjectMap<RECIPE> recipeCache = new Long2ObjectOpenHashMap<>();
|
||||
protected long cacheSalt = 0L;
|
||||
protected @Nonnull Long2ObjectMap<ObjectSet<RECIPE>> recipeCache = new Long2ObjectOpenHashMap<>();
|
||||
|
||||
private static List<Class<?>> validItemInputs = Lists.newArrayList(IItemIngredient.class, ArrayList.class, String.class, Item.class, Block.class, ItemStack.class, ItemStack[].class);
|
||||
private static List<Class<?>> validFluidInputs = Lists.newArrayList(IFluidIngredient.class, ArrayList.class, String.class, Fluid.class, FluidStack.class, FluidStack[].class);
|
||||
|
@ -46,20 +46,21 @@ public abstract class AbstractRecipeHandler<RECIPE extends IRecipe> {
|
|||
@ZenMethod
|
||||
public abstract List<RECIPE> getRecipeList();
|
||||
|
||||
public Long2ObjectMap<RECIPE> getRecipeCache() {
|
||||
return recipeCache;
|
||||
}
|
||||
|
||||
public abstract void addRecipe(Object... objects);
|
||||
|
||||
public @Nullable RecipeInfo<RECIPE> getRecipeInfoFromInputs(List<ItemStack> itemInputs, List<Tank> fluidInputs) {
|
||||
RECIPE recipe = recipeCache.get(RecipeHelper.hashMaterialsRaw(itemInputs, fluidInputs, cacheSalt));
|
||||
long hash = RecipeHelper.hashMaterialsRaw(itemInputs, fluidInputs);
|
||||
if (recipeCache.containsKey(hash)) {
|
||||
ObjectSet<RECIPE> set = recipeCache.get(hash);
|
||||
for (RECIPE recipe : set) {
|
||||
if (recipe != null) {
|
||||
RecipeMatchResult matchResult = recipe.matchInputs(itemInputs, fluidInputs);
|
||||
if (matchResult.matches()) {
|
||||
return new RecipeInfo(recipe, matchResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -95,15 +96,37 @@ public abstract class AbstractRecipeHandler<RECIPE extends IRecipe> {
|
|||
}
|
||||
|
||||
public void refreshCache() {
|
||||
cacheSalt = 0L;
|
||||
do {
|
||||
recipeCache.clear();
|
||||
}
|
||||
while (!fillHashCache());
|
||||
fillHashCache();
|
||||
}
|
||||
|
||||
public boolean fillHashCache() {
|
||||
recipeLoop: for (RECIPE recipe : recipeList) {
|
||||
protected void fillHashCache() {
|
||||
for (RECIPE recipe : recipeList) {
|
||||
List<Pair<List<ItemStack>, List<FluidStack>>> materialListTuples = new ArrayList<>();
|
||||
|
||||
if (!prepareMaterialListTuples(recipe, materialListTuples)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Pair<List<ItemStack>, List<FluidStack>> materials : materialListTuples) {
|
||||
for (List<ItemStack> items : PermutationHelper.permutations(materials.getLeft())) {
|
||||
for (List<FluidStack> fluids : PermutationHelper.permutations(materials.getRight())) {
|
||||
long hash = RecipeHelper.hashMaterials(items, fluids);
|
||||
if (recipeCache.containsKey(hash)) {
|
||||
recipeCache.get(hash).add(recipe);
|
||||
}
|
||||
else {
|
||||
ObjectSet<RECIPE> set = new ObjectOpenHashSet<>();
|
||||
set.add(recipe);
|
||||
recipeCache.put(hash, set);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean prepareMaterialListTuples(RECIPE recipe, List<Pair<List<ItemStack>, List<FluidStack>>> materialListTuples) {
|
||||
List<List<ItemStack>> itemInputLists = new ArrayList<>();
|
||||
List<List<FluidStack>> fluidInputLists = new ArrayList<>();
|
||||
|
||||
|
@ -122,39 +145,20 @@ public abstract class AbstractRecipeHandler<RECIPE extends IRecipe> {
|
|||
for (int i = 0; i < itemInputLists.size(); i++) {
|
||||
int maxNumber = itemInputLists.get(i).size() - 1;
|
||||
if (maxNumber < 0) {
|
||||
continue recipeLoop;
|
||||
return false;
|
||||
}
|
||||
maxNumbers[i] = maxNumber;
|
||||
}
|
||||
for (int i = 0; i < fluidInputLists.size(); i++) {
|
||||
int maxNumber = fluidInputLists.get(i).size() - 1;
|
||||
if (maxNumber < 0) {
|
||||
continue recipeLoop;
|
||||
return false;
|
||||
}
|
||||
maxNumbers[i + itemInputLists.size()] = maxNumber;
|
||||
}
|
||||
|
||||
List<Pair<List<ItemStack>, List<FluidStack>>> materialListTuples = new ArrayList<>();
|
||||
|
||||
RecipeTupleGenerator.INSTANCE.generateMaterialListTuples(materialListTuples, maxNumbers, inputNumbers, itemInputLists, fluidInputLists);
|
||||
|
||||
for (Pair<List<ItemStack>, List<FluidStack>> materials : materialListTuples) {
|
||||
for (List<ItemStack> items : PermutationHelper.permutations(materials.getLeft())) {
|
||||
for (List<FluidStack> fluids : PermutationHelper.permutations(materials.getRight())) {
|
||||
long hash = RecipeHelper.hashMaterials(items, fluids, cacheSalt);
|
||||
if (recipeCache.containsKey(hash)) {
|
||||
cacheSalt++;
|
||||
NCUtil.getLogger().info(getRecipeName() + " encountered a hash clash [" + RecipeHelper.getRecipeString(recipe) + " == " + RecipeHelper.getRecipeString(recipeCache.get(hash)) + "]! Incrementing salt to " + cacheSalt + " and restarting caching...");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
recipeCache.put(RecipeHelper.hashMaterials(items, fluids, cacheSalt), recipe);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -509,32 +509,32 @@ public class RecipeHelper {
|
|||
return new OreIngredient(oreName, stackSize);
|
||||
}
|
||||
|
||||
public static long hashMaterialsRaw(List<ItemStack> items, List<Tank> fluids, long salt) {
|
||||
public static long hashMaterialsRaw(List<ItemStack> items, List<Tank> fluids) {
|
||||
long hash = 1L;
|
||||
Iterator<ItemStack> itemIter = items.iterator();
|
||||
while (itemIter.hasNext()) {
|
||||
ItemStack stack = itemIter.next();
|
||||
hash = 31L * hash + (stack == null || stack.isEmpty() ? 0L : RecipeItemHelper.pack(stack)) + salt;
|
||||
hash = 31L * hash + (stack == null || stack.isEmpty() ? 0L : RecipeItemHelper.pack(stack));
|
||||
}
|
||||
Iterator<Tank> fluidIter = fluids.iterator();
|
||||
while (fluidIter.hasNext()) {
|
||||
Tank tank = fluidIter.next();
|
||||
hash = 31L * hash + (tank == null || tank.getFluid() == null ? 0L : tank.getFluid().getFluid().getName().hashCode()) + salt;
|
||||
hash = 31L * hash + (tank == null || tank.getFluid() == null ? 0L : tank.getFluid().getFluid().getName().hashCode());
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public static long hashMaterials(List<ItemStack> items, List<FluidStack> fluids, long salt) {
|
||||
public static long hashMaterials(List<ItemStack> items, List<FluidStack> fluids) {
|
||||
long hash = 1L;
|
||||
Iterator<ItemStack> itemIter = items.iterator();
|
||||
while (itemIter.hasNext()) {
|
||||
ItemStack stack = itemIter.next();
|
||||
hash = 31L * hash + (stack == null || stack.isEmpty() ? 0L : RecipeItemHelper.pack(stack)) + salt;
|
||||
hash = 31L * hash + (stack == null || stack.isEmpty() ? 0L : RecipeItemHelper.pack(stack));
|
||||
}
|
||||
Iterator<FluidStack> fluidIter = fluids.iterator();
|
||||
while (fluidIter.hasNext()) {
|
||||
FluidStack stack = fluidIter.next();
|
||||
hash = 31L * hash + (stack == null ? 0L : stack.getFluid().getName().hashCode()) + salt;
|
||||
hash = 31L * hash + (stack == null ? 0L : stack.getFluid().getName().hashCode());
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ public class ManufactoryRecipes extends ProcessorRecipeHandler {
|
|||
addLogRecipes();
|
||||
}
|
||||
|
||||
private static final Set<String> BLACKLIST = Sets.newHashSet("silicon");
|
||||
private static final Set<String> BLACKLIST = Sets.newHashSet("Silicon");
|
||||
|
||||
public void addMetalProcessingRecipes() {
|
||||
for (String ingot : OreDictionary.getOreNames()) {
|
||||
|
|
3
todo.txt
3
todo.txt
|
@ -1,6 +1,3 @@
|
|||
Add salt-based fix for recipe hash caching (start from zero, if there's a clash, start again after incrementing)
|
||||
Test with iron + coal alloy furnace recipe in modified Enigmatica 2 instance
|
||||
|
||||
Suggestions from: This probably won’t happen but in stead of multiblock reactors
|
||||
|
||||
Adjacent MSR vessels with same filter form bundle to share flux, shared criticality factor is sum of single vessel criticality factors
|
||||
|
|
Loading…
Reference in New Issue