From b8e685b1b6b6b45c19fbfdc39b1a43d67efa637c Mon Sep 17 00:00:00 2001 From: yueh Date: Sun, 20 Aug 2017 21:31:30 +0200 Subject: [PATCH] Fixes #3040: Cache recipe and revalidate it (#3042) * Fixes #3040: Cache recipe and revalidate it This caches the last used recipe instead of only the result. Which allows to revalidate the crafting grid against the recipe itself before hitting the CraftingManager again. Therefore avoiding a high performance hit for recipe lookups, just find the potential same recipe again. * Remove old recipe lookup as forge provides it now. * Further optimizations. These are a bit quick'n'dirty and need a better solution with a full container/gui refactoring. But for now they provide some great benefits in terms of performance. --- .../ContainerCraftingTerm.java | 23 ++++++++++- .../implementations/ContainerPatternTerm.java | 4 +- .../container/slot/AppEngCraftingSlot.java | 9 +++- .../container/slot/SlotCraftingTerm.java | 41 ++++++++++++++++++- .../core/sync/packets/PacketJEIRecipe.java | 3 +- .../java/appeng/helpers/PatternHelper.java | 2 +- src/main/java/appeng/util/Platform.java | 19 --------- 7 files changed, 75 insertions(+), 26 deletions(-) diff --git a/src/main/java/appeng/container/implementations/ContainerCraftingTerm.java b/src/main/java/appeng/container/implementations/ContainerCraftingTerm.java index 1547ca3d5..850aa9c1c 100644 --- a/src/main/java/appeng/container/implementations/ContainerCraftingTerm.java +++ b/src/main/java/appeng/container/implementations/ContainerCraftingTerm.java @@ -24,6 +24,7 @@ import net.minecraft.inventory.IInventory; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.CraftingManager; +import net.minecraft.item.crafting.IRecipe; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.wrapper.PlayerInvWrapper; @@ -46,6 +47,7 @@ public class ContainerCraftingTerm extends ContainerMEMonitorable implements IAE private final AppEngInternalInventory output = new AppEngInternalInventory( this, 1 ); private final SlotCraftingMatrix[] craftingSlots = new SlotCraftingMatrix[9]; private final SlotCraftingTerm outputSlot; + private IRecipe currentRecipe; public ContainerCraftingTerm( final InventoryPlayer ip, final ITerminalHost monitorable ) { @@ -85,7 +87,21 @@ public class ContainerCraftingTerm extends ContainerMEMonitorable implements IAE ic.setInventorySlotContents( x, this.craftingSlots[x].getStack() ); } - this.outputSlot.putStack( CraftingManager.findMatchingResult( ic, this.getPlayerInv().player.world ) ); + if( this.currentRecipe == null || !this.currentRecipe.matches( ic, this.getPlayerInv().player.world ) ) + { + this.currentRecipe = CraftingManager.findMatchingRecipe( ic, this.getPlayerInv().player.world ); + } + + if( this.currentRecipe == null ) + { + this.outputSlot.putStack( ItemStack.EMPTY ); + } + else + { + final ItemStack craftingResult = this.currentRecipe.getCraftingResult( ic ); + + this.outputSlot.putStack( craftingResult ); + } } @Override @@ -115,4 +131,9 @@ public class ContainerCraftingTerm extends ContainerMEMonitorable implements IAE { return true; } + + public IRecipe getCurrentRecipe() + { + return this.currentRecipe; + } } diff --git a/src/main/java/appeng/container/implementations/ContainerPatternTerm.java b/src/main/java/appeng/container/implementations/ContainerPatternTerm.java index 2415b2be3..a58721675 100644 --- a/src/main/java/appeng/container/implementations/ContainerPatternTerm.java +++ b/src/main/java/appeng/container/implementations/ContainerPatternTerm.java @@ -391,7 +391,7 @@ public class ContainerPatternTerm extends ContainerMEMonitorable implements IAEA ic.setInventorySlotContents( x, packetPatternSlot.pattern[x] == null ? ItemStack.EMPTY : packetPatternSlot.pattern[x].getItemStack() ); } - final IRecipe r = Platform.findMatchingRecipe( ic, p.world ); + final IRecipe r = CraftingManager.findMatchingRecipe( ic, p.world ); if( r == null ) { @@ -413,7 +413,7 @@ public class ContainerPatternTerm extends ContainerMEMonitorable implements IAEA } } - final IRecipe rr = Platform.findMatchingRecipe( real, p.world ); + final IRecipe rr = CraftingManager.findMatchingRecipe( real, p.world ); if( rr == r && Platform.itemComparisons().isSameItem( rr.getCraftingResult( real ), is ) ) { diff --git a/src/main/java/appeng/container/slot/AppEngCraftingSlot.java b/src/main/java/appeng/container/slot/AppEngCraftingSlot.java index be48b3e55..b0e93cdff 100644 --- a/src/main/java/appeng/container/slot/AppEngCraftingSlot.java +++ b/src/main/java/appeng/container/slot/AppEngCraftingSlot.java @@ -24,6 +24,7 @@ import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.CraftingManager; import net.minecraft.util.NonNullList; +import net.minecraft.world.World; import net.minecraftforge.items.IItemHandler; import appeng.util.helpers.ItemHandlerUtil; @@ -149,7 +150,7 @@ public class AppEngCraftingSlot extends AppEngSlot ic.setInventorySlotContents( x, this.craftMatrix.getStackInSlot( x ) ); } - final NonNullList aitemstack = CraftingManager.getRemainingItems( ic, playerIn.world ); + final NonNullList aitemstack = this.getRemainingItems( ic, playerIn.world ); ItemHandlerUtil.copy( ic, this.craftMatrix, false ); @@ -195,4 +196,10 @@ public class AppEngCraftingSlot extends AppEngSlot return super.decrStackSize( par1 ); } + + // TODO: This is really hacky and NEEDS to be solved with a full container/gui refactoring. + protected NonNullList getRemainingItems( InventoryCrafting ic, World world ) + { + return CraftingManager.getRemainingItems( ic, world ); + } } diff --git a/src/main/java/appeng/container/slot/SlotCraftingTerm.java b/src/main/java/appeng/container/slot/SlotCraftingTerm.java index e3dffbe38..be9d33ab3 100644 --- a/src/main/java/appeng/container/slot/SlotCraftingTerm.java +++ b/src/main/java/appeng/container/slot/SlotCraftingTerm.java @@ -27,8 +27,11 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.InventoryCrafting; 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.util.NonNullList; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; import net.minecraftforge.items.IItemHandler; import appeng.api.config.Actionable; @@ -39,6 +42,7 @@ import appeng.api.storage.IStorageMonitorable; import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IItemList; import appeng.container.ContainerNull; +import appeng.container.implementations.ContainerCraftingTerm; import appeng.helpers.IContainerCraftingPacket; import appeng.helpers.InventoryAction; import appeng.items.storage.ItemViewCell; @@ -153,6 +157,41 @@ public class SlotCraftingTerm extends AppEngCraftingSlot } } + // TODO: This is really hacky and NEEDS to be solved with a full container/gui refactoring. + protected IRecipe findRecipe( InventoryCrafting ic, World world ) + { + if( this.container instanceof ContainerCraftingTerm ) + { + final ContainerCraftingTerm containerTerminal = (ContainerCraftingTerm) this.container; + final IRecipe recipe = containerTerminal.getCurrentRecipe(); + + if( recipe != null && recipe.matches( ic, world ) ) + { + return containerTerminal.getCurrentRecipe(); + } + } + + return CraftingManager.findMatchingRecipe( ic, world ); + } + + // TODO: This is really hacky and NEEDS to be solved with a full container/gui refactoring. + @Override + protected NonNullList getRemainingItems( InventoryCrafting ic, World world ) + { + if( this.container instanceof ContainerCraftingTerm ) + { + final ContainerCraftingTerm containerTerminal = (ContainerCraftingTerm) this.container; + final IRecipe recipe = containerTerminal.getCurrentRecipe(); + + if( recipe != null && recipe.matches( ic, world ) ) + { + return containerTerminal.getCurrentRecipe().getRemainingItems( ic ); + } + } + + return CraftingManager.getRemainingItems( ic, world ); + } + private int capCraftingAttempts( final int maxTimesToCraft ) { return maxTimesToCraft; @@ -178,7 +217,7 @@ public class SlotCraftingTerm extends AppEngCraftingSlot ic.setInventorySlotContents( x, this.getPattern().getStackInSlot( x ) ); } - final IRecipe r = Platform.findMatchingRecipe( ic, p.world ); + final IRecipe r = this.findRecipe( ic, p.world ); if( r == null ) { diff --git a/src/main/java/appeng/core/sync/packets/PacketJEIRecipe.java b/src/main/java/appeng/core/sync/packets/PacketJEIRecipe.java index 91bafece9..72865e247 100644 --- a/src/main/java/appeng/core/sync/packets/PacketJEIRecipe.java +++ b/src/main/java/appeng/core/sync/packets/PacketJEIRecipe.java @@ -32,6 +32,7 @@ import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.Container; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.CraftingManager; import net.minecraft.item.crafting.IRecipe; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; @@ -145,7 +146,7 @@ public class PacketJEIRecipe extends AppEngPacket } } - final IRecipe r = Platform.findMatchingRecipe( testInv, pmp.world ); + final IRecipe r = CraftingManager.findMatchingRecipe( testInv, pmp.world ); if( r != null && security.hasPermission( player, SecurityPermissions.EXTRACT ) ) { diff --git a/src/main/java/appeng/helpers/PatternHelper.java b/src/main/java/appeng/helpers/PatternHelper.java index 6a1d9ab86..ed54352f7 100644 --- a/src/main/java/appeng/helpers/PatternHelper.java +++ b/src/main/java/appeng/helpers/PatternHelper.java @@ -106,7 +106,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable recipes = ForgeRegistries.RECIPES; - final List rl = recipes.getValues(); - - for( final IRecipe r : rl ) - { - if( r.matches( inventoryCrafting, par2World ) ) - { - return r; - } - } - - return null; - } - public static ItemStack[] getBlockDrops( final World w, final BlockPos pos ) { List out = new ArrayList<>();