mirror of
https://github.com/GTNewHorizons/TinkersConstruct.git
synced 2026-10-25 20:32:32 +00:00
perf(CraftingStation): cache last matched recipe (#304)
This commit is contained in:
1 parent
b8dd2f9fd9
commit
2123db72e1
6 files changed
+119
-18
No files matched your search
@@ -1,6 +1,7 @@
|
||||
package tconstruct.tools.inventory;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@@ -15,6 +16,7 @@ import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.CraftingManager;
|
||||
import net.minecraft.item.crafting.IRecipe;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import tconstruct.items.tools.Arrow;
|
||||
@@ -48,6 +50,12 @@ public class CraftingStationContainer extends Container {
|
||||
public CraftingStationLogic logic;
|
||||
EntityPlayer player;
|
||||
|
||||
/** Last matched recipe, tried first to avoid rescanning the whole recipe list on every matrix change. */
|
||||
private IRecipe lastRecipe;
|
||||
|
||||
/** While true, matrix changes don't recompute the result. Batches ingredient consumption into one lookup. */
|
||||
private boolean suppressCraftingUpdates;
|
||||
|
||||
public CraftingStationContainer(InventoryPlayer inventoryplayer, CraftingStationLogic logic, int x, int y, int z) {
|
||||
this.worldObj = logic.getWorldObj();
|
||||
this.player = inventoryplayer.player;
|
||||
@@ -74,6 +82,7 @@ public class CraftingStationContainer extends Container {
|
||||
// 0 - crafting slot
|
||||
this.addSlotToContainer(
|
||||
new SlotCraftingStation(
|
||||
this,
|
||||
inventoryplayer.player,
|
||||
this.craftMatrix,
|
||||
this.craftResult,
|
||||
@@ -280,11 +289,74 @@ public class CraftingStationContainer extends Container {
|
||||
}
|
||||
|
||||
public void onCraftMatrixChanged(IInventory par1IInventory) {
|
||||
if (suppressCraftingUpdates) return;
|
||||
|
||||
ItemStack tool = modifyItem();
|
||||
if (tool != null) this.craftResult.setInventorySlotContents(0, tool);
|
||||
else this.craftResult.setInventorySlotContents(
|
||||
0,
|
||||
CraftingManager.getInstance().findMatchingRecipe(this.craftMatrix, this.worldObj));
|
||||
else this.craftResult.setInventorySlotContents(0, findMatchingRecipeCached());
|
||||
}
|
||||
|
||||
/** Like {@link CraftingManager#findMatchingRecipe} but tries the last matched recipe first. */
|
||||
private ItemStack findMatchingRecipeCached() {
|
||||
// Vanilla's two-item tool repair takes precedence over the recipe list
|
||||
if (isVanillaToolRepair()) {
|
||||
return CraftingManager.getInstance().findMatchingRecipe(this.craftMatrix, this.worldObj);
|
||||
}
|
||||
|
||||
IRecipe cached = this.lastRecipe;
|
||||
if (cached != null && cached.matches(this.craftMatrix, this.worldObj)) {
|
||||
return cached.getCraftingResult(this.craftMatrix);
|
||||
}
|
||||
this.lastRecipe = null;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<IRecipe> recipes = CraftingManager.getInstance().getRecipeList();
|
||||
for (int i = 0; i < recipes.size(); i++) {
|
||||
IRecipe recipe = recipes.get(i);
|
||||
if (recipe.matches(this.craftMatrix, this.worldObj)) {
|
||||
this.lastRecipe = recipe;
|
||||
return recipe.getCraftingResult(this.craftMatrix);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirrors the repair check in {@link CraftingManager#findMatchingRecipe}: two size-1 stacks of one repairable item.
|
||||
*/
|
||||
private boolean isVanillaToolRepair() {
|
||||
ItemStack first = null;
|
||||
ItemStack second = null;
|
||||
int found = 0;
|
||||
|
||||
for (int i = 0; i < this.craftMatrix.getSizeInventory(); i++) {
|
||||
ItemStack stack = this.craftMatrix.getStackInSlot(i);
|
||||
if (stack == null) continue;
|
||||
|
||||
found++;
|
||||
if (found == 1) first = stack;
|
||||
else if (found == 2) second = stack;
|
||||
else return false;
|
||||
}
|
||||
|
||||
return found == 2 && first.getItem() == second.getItem()
|
||||
&& first.stackSize == 1
|
||||
&& second.stackSize == 1
|
||||
&& first.getItem().isRepairable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Suppresses result updates until {@link #endBatchCraftingUpdate}; each consumed ingredient fires a lookup
|
||||
* otherwise.
|
||||
*/
|
||||
void beginBatchCraftingUpdate() {
|
||||
suppressCraftingUpdates = true;
|
||||
}
|
||||
|
||||
/** Re-enables result updates and recomputes once. */
|
||||
void endBatchCraftingUpdate() {
|
||||
suppressCraftingUpdates = false;
|
||||
this.onCraftMatrixChanged(this.craftMatrix);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -438,16 +510,19 @@ public class CraftingStationContainer extends Container {
|
||||
public void dumpCraftingGrid() {
|
||||
if (logic.slotCount == 0) return;
|
||||
|
||||
// 46 is the first slot index of the attached inventory
|
||||
for (int i = 0; i < 9; i++) {
|
||||
ItemStack stack = craftMatrix.getStackInSlot(i);
|
||||
if (stack != null && stack.stackSize > 0) {
|
||||
if (mergeItemStack(stack, 46, 46 + logic.slotCount, false)) {
|
||||
craftMatrix.setInventorySlotContents(i, stack.stackSize > 0 ? stack : null);
|
||||
beginBatchCraftingUpdate();
|
||||
try {
|
||||
// 46 is the first slot index of the attached inventory
|
||||
for (int i = 0; i < 9; i++) {
|
||||
ItemStack stack = craftMatrix.getStackInSlot(i);
|
||||
if (stack != null && stack.stackSize > 0) {
|
||||
if (mergeItemStack(stack, 46, 46 + logic.slotCount, false)) {
|
||||
craftMatrix.setInventorySlotContents(i, stack.stackSize > 0 ? stack : null);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
endBatchCraftingUpdate();
|
||||
}
|
||||
|
||||
this.onCraftMatrixChanged(this.craftMatrix);
|
||||
}
|
||||
}
|
||||
@@ -11,18 +11,30 @@ import tconstruct.library.tools.AbilityHelper;
|
||||
|
||||
public class SlotCraftingStation extends SlotCrafting {
|
||||
|
||||
private final CraftingStationContainer container;
|
||||
private final IInventory matrix;
|
||||
private final EntityPlayer player;
|
||||
|
||||
public SlotCraftingStation(EntityPlayer par1EntityPlayer, IInventory par2IInventory, IInventory par3iInventory,
|
||||
int par4, int par5, int par6) {
|
||||
public SlotCraftingStation(CraftingStationContainer container, EntityPlayer par1EntityPlayer,
|
||||
IInventory par2IInventory, IInventory par3iInventory, int par4, int par5, int par6) {
|
||||
super(par1EntityPlayer, par2IInventory, par3iInventory, par4, par5, par6);
|
||||
this.container = container;
|
||||
this.matrix = par2IInventory;
|
||||
this.player = par1EntityPlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickupFromSlot(EntityPlayer player, ItemStack stack) {
|
||||
// Batch ingredient consumption into a single recipe lookup
|
||||
container.beginBatchCraftingUpdate();
|
||||
try {
|
||||
consumeIngredients(player, stack);
|
||||
} finally {
|
||||
container.endBatchCraftingUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private void consumeIngredients(EntityPlayer player, ItemStack stack) {
|
||||
ItemStack tool = this.matrix.getStackInSlot(4);
|
||||
if (stack.getItem() instanceof IModifyable modifyable && tool != null
|
||||
&& tool.getItem() instanceof IModifyable) {
|
||||
|
||||
@@ -32,6 +32,12 @@ public class CraftingStationLogic extends InventoryLogic implements ISidedInvent
|
||||
|
||||
public int invRows, invColumns, slotCount;
|
||||
|
||||
private static final int[] NO_SLOTS = new int[0];
|
||||
|
||||
/** Cached result of {@link #getInventories()}; rebuilt when the adjacent inventories are rescanned. */
|
||||
@SuppressWarnings("rawtypes")
|
||||
private WeakReference[] inventories = new WeakReference[4];
|
||||
|
||||
public CraftingStationLogic() {
|
||||
super(10); // 9 for crafting, 1 for output
|
||||
}
|
||||
@@ -115,6 +121,8 @@ public class CraftingStationLogic extends InventoryLogic implements ISidedInvent
|
||||
}
|
||||
}
|
||||
|
||||
this.inventories = new WeakReference[] { this.chest, this.doubleChest, this.patternChest, this.furnace };
|
||||
|
||||
return new CraftingStationContainer(inventoryplayer, this, x, y, z);
|
||||
}
|
||||
|
||||
@@ -168,12 +176,12 @@ public class CraftingStationLogic extends InventoryLogic implements ISidedInvent
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public WeakReference[] getInventories() {
|
||||
return new WeakReference[] { this.chest, this.doubleChest, this.patternChest, this.furnace };
|
||||
return this.inventories;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getAccessibleSlotsFromSide(int var1) {
|
||||
return new int[] {};
|
||||
return NO_SLOTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,8 @@ import tconstruct.tools.inventory.PartCrafterContainer;
|
||||
|
||||
public class PartBuilderLogic extends InventoryLogic implements ISidedInventory {
|
||||
|
||||
private static final int[] NO_SLOTS = new int[0];
|
||||
|
||||
boolean craftedTop;
|
||||
boolean craftedBottom;
|
||||
|
||||
@@ -138,7 +140,7 @@ public class PartBuilderLogic extends InventoryLogic implements ISidedInventory
|
||||
|
||||
@Override
|
||||
public int[] getAccessibleSlotsFromSide(int side) {
|
||||
return new int[0];
|
||||
return NO_SLOTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,6 +15,8 @@ import tconstruct.tools.inventory.PatternShaperContainer;
|
||||
|
||||
public class StencilTableLogic extends InventoryLogic implements ISidedInventory {
|
||||
|
||||
private static final int[] NO_SLOTS = new int[0];
|
||||
|
||||
private ItemStack selectedStack;
|
||||
|
||||
public StencilTableLogic() {
|
||||
@@ -119,7 +121,7 @@ public class StencilTableLogic extends InventoryLogic implements ISidedInventory
|
||||
|
||||
@Override
|
||||
public int[] getAccessibleSlotsFromSide(int side) {
|
||||
return new int[0];
|
||||
return NO_SLOTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,6 +20,8 @@ import tconstruct.tools.inventory.ToolStationContainer;
|
||||
|
||||
public class ToolStationLogic extends InventoryLogic implements ISidedInventory {
|
||||
|
||||
private static final int[] NO_SLOTS = new int[0];
|
||||
|
||||
public ItemStack previousTool;
|
||||
public String toolName;
|
||||
|
||||
@@ -158,7 +160,7 @@ public class ToolStationLogic extends InventoryLogic implements ISidedInventory
|
||||
|
||||
@Override
|
||||
public int[] getAccessibleSlotsFromSide(int side) {
|
||||
return new int[0];
|
||||
return NO_SLOTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in new issue
Block a user