Skip to content

Commit

Permalink
GTI Recipe Lookups - Supersedes #530 (#666)
Browse files Browse the repository at this point in the history
* first work on porting recipe map

* Cleanup

* Implement removal of recipes + removal tests

* Disallow dupe recipes

* fix merge issues

* strip "nonConsumable" NBT tag from fluids before mapping to a recipe

* implement recipe removal to lookup map

* fix tests to reflect new behavior

* restore exactVoltage argument for craftweaker recipes

* Formatting and removal of unused variables

* CountableIngredient....

* simplify recipe equals and hashcode, to match lookup

* hide recipe duplicates due to itemstack combinations (ex. oredict)

* actually remove them recipes..

* Implement fluid accepting in machines limited to valid recipes

* tiny optimization on the fluid input check

* NBT special case matching. Cleaning needed

Directly from the future ( Tesseract API )

* clean up 1/?

make stuff simpler. NBT match on cached recipe too
more work towards NBT selective matching

* hash itemstacks both with and without NBT comparison ingredients

* trim branches. more removal work

* more work on NBT matching

* allow batteries with NBT tags to be extractable in the extractor

* fix recipe removal

* move ingredient NBT matching to an upper class

* comments

* canonalize ingredients

* remove some copies and sums since we dont use them or modify them

rename a few more methods for clarity

* remove unused constructor

* implement oredict ingredient

* save some memory

* patch ore dictionary support for CraftTweaker

* fix ct exact voltage removal

move to an NBT-checking ingredient. small renames

* Removal of CountableIngredient and implementation of IGTRecipeInput

* renames and clean up on lookup

* fix safes

* fix fluidingredient hash.

* Switch to an abstract class instead of an interface

* address some review issues

* use a list to sort and return the available recipes

* more NBT work

* NBT fix

* show recipes with special ingredients; initial patch for CT removal

of ingredients with NBT conditions

* more NBBT

* more wildcard changes. micro optimizations

* small fix for consistency

delete unimplemented test command

* down recipe check failure down to 7 errors

* fix duplicated recipe inputs with differing amounts

being counted twice

* Branch only once if a ingredient has variations

Add oredict string to output

* Co-Pilot my butt

* misc cleaning

* Itemstack Wildcard issues... yay

* string formating

* recipe conflict checker rework

* unify cache and reformat recipe check command

* more recipe checks

* old mans ramblings, might be reverted fully later

* faster itemstack matching

* avoid hashing some stacks to match some ingredients we dont care for

* only mark output as full if we have that kind of output to fill

* move the item list to a private class

* some javadocs + more human-friendly logging

* more abstracting of recipe inputs + reformatting

* Update src/main/java/gregtech/api/recipes/ingredients/GTRecipeItemInput.java

Co-authored-by: TechLord22 <[email protected]>

* Update src/main/java/gregtech/api/recipes/RecipeMap.java

Co-authored-by: TechLord22 <[email protected]>

* Update src/main/java/gregtech/api/recipes/RecipeMap.java

Co-authored-by: TechLord22 <[email protected]>

* address reviews + run formatter on some files

* move inner classes to another class

* review issues

* Fix JEI not displaying recipe with Fluid only inputs.

Fix parallel multiplying input requirements permanently.

* javadoc typos

* defensive copies

equals tweak
recipe conflict check just uses max int for item/fluid sizes.

* limit recipe matching to proper machine tier

* More suitable GTRecipeInput caching collection + cache release

* Stream's map instead of peek

* Fix no return statement for map

* Do not add parallel multiplied ingredients to the ingredient cache

to avoid possible memory leak.
annotate some Overriden methods

* misc renames.

remove some item/fluid copies.

* Support equality checks for non-numerical nbt types

* Cleaned up RecipeBuilder input methods + hash/equal impl for NBCondition

* RecipePropertyStorage stuff + optimized collections in Recipe

- Now resides in RecipeBuilder before being passed to Recipe
- Immutable when it is in Recipe
- EMPTY variant to save memory
- Utilize applyProperty and made it make... more sense?
- Removed some redundant overrides
- GasCollectorDimensionProperty now uses an IntList instead of ArrayList<Integer>

Co-authored-by: Abbe <[email protected]>
Co-authored-by: PrototypeTrousers <[email protected]>
Co-authored-by: TechLord22 <[email protected]>
  • Loading branch information
4 people authored Aug 3, 2022
1 parent 128d9d9 commit acc9963
Show file tree
Hide file tree
Showing 68 changed files with 3,038 additions and 1,199 deletions.
20 changes: 10 additions & 10 deletions src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import gregtech.api.recipes.RecipeMap;
import gregtech.api.recipes.logic.IParallelableRecipeLogic;
import gregtech.api.recipes.recipeproperties.CleanroomProperty;
import gregtech.api.recipes.recipeproperties.IRecipePropertyStorage;
import gregtech.api.recipes.recipeproperties.RecipePropertyStorage;
import gregtech.api.util.GTTransferUtils;
import gregtech.api.util.GTUtility;
Expand Down Expand Up @@ -183,14 +184,13 @@ protected boolean hasNotifiedOutputs() {
protected boolean canFitNewOutputs() {
// if the output is full check if the output changed so we can process recipes results again.
if (this.isOutputsFull && !hasNotifiedOutputs()) {
if (!hasNotifiedInputs() && checkPreviousRecipe()) {
return false;
}
return false;
} else {
this.isOutputsFull = false;
metaTileEntity.getNotifiedItemOutputList().clear();
metaTileEntity.getNotifiedFluidOutputList().clear();
return true;
}
this.isOutputsFull = false;
metaTileEntity.getNotifiedItemOutputList().clear();
metaTileEntity.getNotifiedFluidOutputList().clear();
return true;
}

protected boolean canWorkWithInputs() {
Expand Down Expand Up @@ -434,13 +434,13 @@ protected boolean setupAndConsumeRecipeInputs(Recipe recipe, IItemHandlerModifia

// We have already trimmed outputs and chanced outputs at this time
// Attempt to merge all outputs + chanced outputs into the output bus, to prevent voiding chanced outputs
if (!metaTileEntity.canVoidRecipeItemOutputs() && !GTTransferUtils.addItemsToItemHandler(exportInventory, true, recipe.getAllItemOutputs())) {
if (!metaTileEntity.canVoidRecipeItemOutputs() && exportInventory.getSlots() > 0 && !GTTransferUtils.addItemsToItemHandler(exportInventory, true, recipe.getAllItemOutputs())) {
this.isOutputsFull = true;
return false;
}

// We have already trimmed fluid outputs at this time
if (!metaTileEntity.canVoidRecipeFluidOutputs() && !GTTransferUtils.addFluidsToFluidHandler(exportFluids, true, recipe.getFluidOutputs())) {
if (!metaTileEntity.canVoidRecipeFluidOutputs() && exportFluids.getTanks() > 0 && !GTTransferUtils.addFluidsToFluidHandler(exportFluids, true, recipe.getFluidOutputs())) {
this.isOutputsFull = true;
return false;
}
Expand Down Expand Up @@ -580,7 +580,7 @@ protected int[] performOverclocking(Recipe recipe) {
*
* @return an int array of {OverclockedEUt, OverclockedDuration}
*/
protected int[] runOverclockingLogic(RecipePropertyStorage propertyStorage, int recipeEUt, long maxVoltage, int duration, int maxOverclocks) {
protected int[] runOverclockingLogic(IRecipePropertyStorage propertyStorage, int recipeEUt, long maxVoltage, int duration, int maxOverclocks) {
return standardOverclockingLogic(Math.abs(recipeEUt),
maxVoltage,
duration,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ protected void trySearchNewRecipe() {
Recipe dieselRecipe = RecipeMaps.COMBUSTION_GENERATOR_FUELS.findRecipe(
GTValues.V[GTValues.MAX], dummyList, Collections.singletonList(fuelStack), Integer.MAX_VALUE);
// run only if it can apply a certain amount of "parallel", this is to mitigate int division
if (dieselRecipe != null && fuelStack.amount >= dieselRecipe.getFluidInputs().get(0).amount * FLUID_DRAIN_MULTIPLIER) {
fluidTank.drain(dieselRecipe.getFluidInputs().get(0).amount * FLUID_DRAIN_MULTIPLIER, true);
if (dieselRecipe != null && fuelStack.amount >= dieselRecipe.getFluidInputs().get(0).getAmount() * FLUID_DRAIN_MULTIPLIER) {
fluidTank.drain(dieselRecipe.getFluidInputs().get(0).getAmount() * FLUID_DRAIN_MULTIPLIER, true);
// divide by 2, as it is half burntime for combustion
setMaxProgress(adjustBurnTimeForThrottle(Math.max(1, boiler.boilerType.runtimeBoost((Math.abs(dieselRecipe.getEUt()) * dieselRecipe.getDuration()) / FLUID_BURNTIME_TO_EU / 2))));
didStartRecipe = true;
Expand All @@ -81,8 +81,8 @@ protected void trySearchNewRecipe() {
Recipe denseFuelRecipe = RecipeMaps.SEMI_FLUID_GENERATOR_FUELS.findRecipe(
GTValues.V[GTValues.MAX], dummyList, Collections.singletonList(fuelStack), Integer.MAX_VALUE);
// run only if it can apply a certain amount of "parallel", this is to mitigate int division
if (denseFuelRecipe != null && fuelStack.amount >= denseFuelRecipe.getFluidInputs().get(0).amount * FLUID_DRAIN_MULTIPLIER) {
fluidTank.drain(denseFuelRecipe.getFluidInputs().get(0).amount * FLUID_DRAIN_MULTIPLIER, true);
if (denseFuelRecipe != null && fuelStack.amount >= denseFuelRecipe.getFluidInputs().get(0).getAmount() * FLUID_DRAIN_MULTIPLIER) {
fluidTank.drain(denseFuelRecipe.getFluidInputs().get(0).getAmount() * FLUID_DRAIN_MULTIPLIER, true);
// multiply by 2, as it is 2x burntime for semi-fluid
setMaxProgress(adjustBurnTimeForThrottle(Math.max(1, boiler.boilerType.runtimeBoost((Math.abs(denseFuelRecipe.getEUt()) * denseFuelRecipe.getDuration() / FLUID_BURNTIME_TO_EU * 2)))));
didStartRecipe = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import gregtech.api.recipes.Recipe;
import gregtech.api.recipes.RecipeBuilder;
import gregtech.api.recipes.RecipeMap;
import gregtech.api.recipes.recipeproperties.RecipePropertyStorage;
import gregtech.api.recipes.recipeproperties.IRecipePropertyStorage;

import javax.annotation.Nonnull;
import java.util.function.Supplier;
Expand All @@ -20,7 +20,7 @@ public FuelRecipeLogic(MetaTileEntity tileEntity, RecipeMap<?> recipeMap, Suppli
}

@Override
protected int[] runOverclockingLogic(RecipePropertyStorage propertyStorage, int recipeEUt, long maxVoltage, int recipeDuration, int maxOverclocks) {
protected int[] runOverclockingLogic(IRecipePropertyStorage propertyStorage, int recipeEUt, long maxVoltage, int recipeDuration, int maxOverclocks) {
// no overclocking happens other than parallelization,
// so return the recipe's values, with EUt made positive for it to be made negative later
return new int[]{recipeEUt * -1, recipeDuration};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import gregtech.api.capability.IHeatingCoil;
import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController;
import gregtech.api.recipes.recipeproperties.RecipePropertyStorage;
import gregtech.api.recipes.recipeproperties.IRecipePropertyStorage;
import gregtech.api.recipes.recipeproperties.TemperatureProperty;

import javax.annotation.Nonnull;
Expand All @@ -20,7 +20,7 @@ public HeatingCoilRecipeLogic(RecipeMapMultiblockController metaTileEntity) {
}

@Override
protected int[] runOverclockingLogic(@Nonnull RecipePropertyStorage propertyStorage, int recipeEUt, long maxVoltage, int duration, int maxOverclocks) {
protected int[] runOverclockingLogic(@Nonnull IRecipePropertyStorage propertyStorage, int recipeEUt, long maxVoltage, int duration, int maxOverclocks) {
return heatingCoilOverclockingLogic(Math.abs(recipeEUt),
maxVoltage,
duration,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import gregtech.api.metatileentity.multiblock.ParallelLogicType;
import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController;
import gregtech.api.recipes.RecipeBuilder;
import gregtech.api.recipes.recipeproperties.RecipePropertyStorage;
import gregtech.api.recipes.recipeproperties.IRecipePropertyStorage;
import gregtech.common.ConfigHolder;

import javax.annotation.Nonnull;
Expand All @@ -20,7 +20,7 @@ public MultiblockFuelRecipeLogic(RecipeMapMultiblockController tileEntity) {
}

@Override
protected int[] runOverclockingLogic(RecipePropertyStorage propertyStorage, int recipeEUt, long maxVoltage, int recipeDuration, int maxOverclocks) {
protected int[] runOverclockingLogic(IRecipePropertyStorage propertyStorage, int recipeEUt, long maxVoltage, int recipeDuration, int maxOverclocks) {
// apply maintenance penalties
MultiblockWithDisplayBase displayBase = this.metaTileEntity instanceof MultiblockWithDisplayBase ? (MultiblockWithDisplayBase) metaTileEntity : null;
int numMaintenanceProblems = displayBase == null ? 0 : displayBase.getNumMaintenanceProblems();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController;
import gregtech.api.recipes.Recipe;
import gregtech.api.recipes.RecipeMap;
import gregtech.api.recipes.recipeproperties.RecipePropertyStorage;
import gregtech.api.recipes.recipeproperties.IRecipePropertyStorage;
import gregtech.common.ConfigHolder;
import net.minecraft.util.Tuple;
import net.minecraftforge.items.IItemHandlerModifiable;
Expand Down Expand Up @@ -250,7 +250,7 @@ protected boolean prepareRecipeDistinct(Recipe recipe) {
}

@Override
protected int[] runOverclockingLogic(RecipePropertyStorage propertyStorage, int recipeEUt, long maxVoltage, int recipeDuration, int maxOverclocks) {
protected int[] runOverclockingLogic(IRecipePropertyStorage propertyStorage, int recipeEUt, long maxVoltage, int recipeDuration, int maxOverclocks) {
// apply maintenance penalties
Tuple<Integer, Double> maintenanceValues = getMaintenanceValues();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import gregtech.api.GTValues;
import gregtech.api.metatileentity.multiblock.RecipeMapPrimitiveMultiblockController;
import gregtech.api.recipes.RecipeMap;
import gregtech.api.recipes.recipeproperties.RecipePropertyStorage;
import gregtech.api.recipes.recipeproperties.IRecipePropertyStorage;

import static gregtech.api.recipes.logic.OverclockingLogic.standardOverclockingLogic;

Expand Down Expand Up @@ -42,7 +42,7 @@ protected long getMaxVoltage() {
}

@Override
protected int[] runOverclockingLogic(RecipePropertyStorage propertyStorage, int recipeEUt, long maxVoltage, int recipeDuration, int maxOverclocks) {
protected int[] runOverclockingLogic(IRecipePropertyStorage propertyStorage, int recipeEUt, long maxVoltage, int recipeDuration, int maxOverclocks) {
return standardOverclockingLogic(1,
getMaxVoltage(),
recipeDuration,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,69 +135,17 @@ protected FluidTankList createExportFluidHandler() {

protected boolean canInputFluid(FluidStack inputFluid) {
RecipeMap<?> recipeMap = workable.getRecipeMap();
if (recipeMap.canInputFluidForce(inputFluid.getFluid())) {
return true; // RecipeMap forces input
}
Collection<Recipe> inputCapableRecipes = recipeMap.getRecipesForFluid(inputFluid);
if (inputCapableRecipes.isEmpty()) {
// Fluid cannot be inputted anyway, short-circuit and inform that the fluid cannot be inputted
return false;
}
boolean hasEmpty = false;
Collection<FluidKey> fluids = null;
for (IFluidTank fluidTank : importFluids) {
FluidStack fluidInTank = fluidTank.getFluid();
if (fluidInTank != null) {
if (inputFluid.isFluidEqual(fluidInTank)) {
// Both fluids are equal, short-circuit and inform that the fluid can be inputted
List<FluidStack> fluidInputs = new ArrayList<>();
for (IFluidTank fluidTank : this.importFluids.getFluidTanks()) {
FluidStack fluidStack = fluidTank.getFluid();
if (fluidStack != null && fluidStack.amount > 0){
if (fluidStack.isFluidEqual(inputFluid)) {
return true;
} else {
if (fluids == null) {
// Avoid object allocation + array expansion as this is a hotspot
if (fluidKeyCache == null) {
fluids = new ObjectArraySet<>(new FluidKey[] { new FluidKey(fluidInTank) });
} else {
fluidKeyCache.clear();
fluids = fluidKeyCache;
}
} else {
fluids.add(new FluidKey(fluidInTank));
}
}
} else {
hasEmpty = true;
}
}
if (!hasEmpty) {
// No empty slots to fill input in, inform that the fluid cannot be inputted
return false;
}
if (fluids == null) {
// There are empty slots to fill, and there are no other fluids, inform that the fluid can be inputted
return true;
}
for (FluidKey fluidKey : fluids) {
Collection<Recipe> iter = recipeMap.getRecipesForFluid(fluidKey);
Collection<Recipe> check;
// Iterate with the smaller collection as base
if (iter.size() > inputCapableRecipes.size()) {
check = iter;
iter = inputCapableRecipes;
} else {
check = inputCapableRecipes;
}
for (Recipe it : iter) {
for (Recipe ch : check) {
// Check identity equality, fast-track instead of doing Recipe#equals' tedious checks
if (it == ch) {
// Recipe exists in both collections, inform that the fluid can be inputted
return true;
}
}
fluidInputs.add(fluidStack);
}
}
// Ultimatum
return false;
return recipeMap != null && recipeMap.acceptsFluid(fluidInputs, inputFluid);
}

@Override
Expand Down
100 changes: 0 additions & 100 deletions src/main/java/gregtech/api/recipes/CountableIngredient.java

This file was deleted.

Loading

0 comments on commit acc9963

Please sign in to comment.