From f121e8bd3d89100cf10e150d4322cd586d5eeb10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Sun, 17 Jul 2016 18:28:45 +0200 Subject: [PATCH] Workbench - Actual crafting! YAY! --- .../api/recipes/I_RecipeRequirements.java | 8 + src/java/mmm/recipes/RRequirements.java | 53 ++++++- .../tech/base/workbench/TBWBContainer.java | 138 ++++++++++++++++-- .../tech/base/workbench/TBWBCraftingSlot.java | 87 +++++++++++ src/java/mmm/utils/UAchievements.java | 52 +++++++ src/java/mmm/utils/gui/UGSlotGroups.java | 12 ++ 6 files changed, 338 insertions(+), 12 deletions(-) create mode 100644 src/java/mmm/tech/base/workbench/TBWBCraftingSlot.java create mode 100644 src/java/mmm/utils/UAchievements.java diff --git a/src/java/mmm/core/api/recipes/I_RecipeRequirements.java b/src/java/mmm/core/api/recipes/I_RecipeRequirements.java index f365b01..12e578b 100644 --- a/src/java/mmm/core/api/recipes/I_RecipeRequirements.java +++ b/src/java/mmm/core/api/recipes/I_RecipeRequirements.java @@ -25,4 +25,12 @@ public interface I_RecipeRequirements boolean checkInventory( IInventory inventory ); + + boolean checkInventory( IInventory inventory , int amount ); + + + public int getMaxOutput( IInventory inventory ); + + + void removeFromInventory( IInventory inventory, int amount ); } \ No newline at end of file diff --git a/src/java/mmm/recipes/RRequirements.java b/src/java/mmm/recipes/RRequirements.java index ee8ee14..0520f32 100644 --- a/src/java/mmm/recipes/RRequirements.java +++ b/src/java/mmm/recipes/RRequirements.java @@ -90,10 +90,17 @@ class RRequirements @Override public boolean checkInventory( final IInventory inventory ) + { + return this.checkInventory( inventory , 1 ); + } + + + @Override + public boolean checkInventory( final IInventory inventory , final int amount ) { final int nInvItems = inventory.getSizeInventory( ); for ( int i = 0 ; i < this.quantities.length ; i++ ) { - int nLeft = this.quantities[ i ]; + int nLeft = this.quantities[ i ] * amount; for ( int j = 0 ; j < nInvItems && nLeft > 0 ; j++ ) { final ItemStack invStack = inventory.getStackInSlot( j ); @@ -108,4 +115,48 @@ class RRequirements } return true; } + + + @Override + public int getMaxOutput( final IInventory inventory ) + { + final int nInvItems = inventory.getSizeInventory( ); + int maxQuantity = Integer.MAX_VALUE; + for ( int i = 0 ; i < this.quantities.length && maxQuantity > 0 ; i++ ) { + int nFound = 0; + + for ( int j = 0 ; j < nInvItems ; j++ ) { + final ItemStack invStack = inventory.getStackInSlot( j ); + if ( this.checkItemStack( i , invStack ) ) { + nFound += invStack.stackSize; + } + } + + maxQuantity = Math.min( maxQuantity , nFound / this.quantities[ i ] ); + } + return maxQuantity; + } + + + @Override + public void removeFromInventory( final IInventory inventory , final int amount ) + { + final int nInvItems = inventory.getSizeInventory( ); + for ( int i = 0 ; i < this.quantities.length ; i++ ) { + int nLeft = this.quantities[ i ] * amount; + for ( int j = 0 ; j < nInvItems && nLeft > 0 ; j++ ) { + final ItemStack invStack = inventory.getStackInSlot( j ); + if ( this.checkItemStack( i , invStack ) ) { + final int used = Math.min( nLeft , invStack.stackSize ); + nLeft -= used; + if ( invStack.stackSize == used ) { + inventory.setInventorySlotContents( j , invStack.getItem( ).getContainerItem( invStack ) ); + } else { + invStack.stackSize -= used; + } + } + } + assert nLeft == 0; + } + } } diff --git a/src/java/mmm/tech/base/workbench/TBWBContainer.java b/src/java/mmm/tech/base/workbench/TBWBContainer.java index 7887522..eb3b349 100644 --- a/src/java/mmm/tech/base/workbench/TBWBContainer.java +++ b/src/java/mmm/tech/base/workbench/TBWBContainer.java @@ -1,14 +1,21 @@ package mmm.tech.base.workbench; +import javax.annotation.Nullable; + import mmm.MmmTech; import mmm.core.api.recipes.I_CraftingRecipeWrapper; +import mmm.recipes.RCraftingWrappers; import mmm.utils.UInventoryDisplay; import mmm.utils.gui.UGContainer; import mmm.utils.gui.UGSlotDisplay; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.InventoryCraftResult; import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -20,7 +27,9 @@ public class TBWBContainer public final TBWBTileEntity tileEntity; public final World world; public final BlockPos position; - public final UInventoryDisplay recipe; + public final UInventoryDisplay recipeDisplay; + public final InventoryCraftResult recipeOutput; + private I_CraftingRecipeWrapper recipeWrapper; public TBWBContainer( final InventoryPlayer playerInv , final TBWBTileEntity tileEntity ) @@ -35,12 +44,19 @@ public class TBWBContainer this.addGrid( Slot::new , tileEntity.storage , 8 , 15 ); this.slotGroups.nextGroup( ); - this.recipe = new UInventoryDisplay( "Recipe" , 10 ); - this.addGrid( UGSlotDisplay::new , this.recipe , // + this.recipeDisplay = new UInventoryDisplay( "Recipe" , 10 ); + this.addGrid( UGSlotDisplay::new , this.recipeDisplay , // 3 , 3 , 0 , 86 , 32 ); - this.addSlotToContainer( new UGSlotDisplay( this.recipe , 9 , 174 , 50 ) ); + + this.slotGroups.nextGroup( ); + this.recipeOutput = new InventoryCraftResult( ); + this.addSlotToContainer( new TBWBCraftingSlot( playerInv.player , this , // + this.recipeOutput , 0 , 174 , 50 ) ); this.slotGroups.endGroups( ); + + this.recipeWrapper = RCraftingWrappers.RECIPES.get( 0 ); + this.onRecipeChanged( ); } @@ -53,20 +69,120 @@ public class TBWBContainer } - public void setCurrentRecipe( final I_CraftingRecipeWrapper wrapper , final boolean setDefault ) + @Nullable + public ItemStack transferStackInSlot( EntityPlayer playerIn , int index ) { - this.recipe.clear( ); - if ( wrapper == null ) { - // XXX log if confirm is set - return; + Slot slot = (Slot) this.inventorySlots.get( index ); + if ( slot == null || !slot.getHasStack( ) ) { + return null; } - wrapper.addInputsToDisplay( this.recipe ); - this.recipe.setInventorySlotContents( 9 , wrapper.getOutput( ) ); + ItemStack slotStack = slot.getStack( ); + ItemStack outStack = slotStack.copy( ); + + int group = this.slotGroups.getGroup( index ); + if ( group == 3 ) { + // Craft as many as possible + if ( this.recipeWrapper == null ) { + return null; + } + IInventory storage = this.getStorage( ); + if ( storage == null ) { + return null; + } + + // Can we? + if ( !this.recipeWrapper.getRequirements( ).checkInventory( storage ) ) { + return null; + } + + // Merge it and remove ingredients + if ( !this.mergeItemStack( outStack , 0 , 36 , false ) ) { + return null; + } + ( (TBWBCraftingSlot) slot ).handleCrafting( 1 ); + + // Drop any items that didn't fit in the inventory + if ( outStack.stackSize != 0 ) { + playerIn.dropItem( outStack , false ); + return null; + } + + return slotStack; + + } + + if ( group == 0 ) { + // Player inventory to storage + if ( !this.mergeItemStack( slotStack , 36 , 51 , false ) ) { + return null; + } + } else if ( group == 1 ) { + // Storage to player inventory + if ( !this.mergeItemStack( slotStack , 0 , 36 , false ) ) { + return null; + } + } else { + return null; + } + + if ( slotStack.stackSize == 0 ) { + slot.putStack( (ItemStack) null ); + } else { + slot.onSlotChanged( ); + } + + if ( slotStack.stackSize == outStack.stackSize ) { + return null; + } + slot.onPickupFromSlot( playerIn , slotStack ); + return outStack; + } + + + public boolean canMergeSlot( ItemStack stack , Slot slotIn ) + { + return slotIn.inventory != this.recipeOutput && super.canMergeSlot( stack , slotIn ); + } + + + public void setCurrentRecipe( final I_CraftingRecipeWrapper wrapper , final boolean setDefault ) + { + this.recipeWrapper = wrapper; + + onRecipeChanged( ); if ( setDefault ) { // this.tileEntity.setDefaultRecipe( wrapper.getIdentifier( ) ); } } + + private void onRecipeChanged( ) + { + this.recipeDisplay.clear( ); + if ( this.recipeWrapper == null ) { + // XXX log if confirm is set + return; + } + this.recipeWrapper.addInputsToDisplay( this.recipeDisplay ); + this.recipeOutput.setInventorySlotContents( 0 , this.recipeWrapper.getOutput( ) ); + } + + + public IInventory getStorage( ) + { + TileEntity te = this.world.getTileEntity( position ); + if ( te instanceof TBWBTileEntity ) { + return ( (TBWBTileEntity) te ).storage; + } + return null; + } + + + public I_CraftingRecipeWrapper getCurrentRecipe( ) + { + return this.recipeWrapper; + } + } diff --git a/src/java/mmm/tech/base/workbench/TBWBCraftingSlot.java b/src/java/mmm/tech/base/workbench/TBWBCraftingSlot.java new file mode 100644 index 0000000..b4c0836 --- /dev/null +++ b/src/java/mmm/tech/base/workbench/TBWBCraftingSlot.java @@ -0,0 +1,87 @@ +package mmm.tech.base.workbench; + + +import javax.annotation.Nullable; + +import mmm.core.api.recipes.I_CraftingRecipeWrapper; +import mmm.utils.UAchievements; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fml.common.FMLCommonHandler; + + + +public class TBWBCraftingSlot + extends Slot +{ + + private final EntityPlayer player; + private final TBWBContainer container; + + + public TBWBCraftingSlot( final EntityPlayer player , final TBWBContainer container , final IInventory inventory , + final int index , final int x , final int y ) + { + super( inventory , index , x , y ); + this.player = player; + this.container = container; + } + + + @Override + public boolean isItemValid( @Nullable final ItemStack stack ) + { + return false; + } + + + @Override + public ItemStack decrStackSize( final int amount ) + { + if ( !this.getHasStack( ) ) { + return null; + } + + final I_CraftingRecipeWrapper wrapper = this.container.getCurrentRecipe( ); + if ( wrapper == null ) { + return null; + } + + final ItemStack stack = this.getStack( ); + final int qt = Math.max( amount - amount % stack.stackSize , stack.stackSize ) / stack.stackSize; + final IInventory storage = this.container.getStorage( ); + if ( storage == null || !wrapper.getRequirements( ).checkInventory( storage , qt ) ) { + return null; + } + return this.handleCrafting( qt ); + } + + + public ItemStack handleCrafting( final int quantity ) + { + if ( !this.getHasStack( ) ) { + return null; + } + + final I_CraftingRecipeWrapper wrapper = this.container.getCurrentRecipe( ); + if ( wrapper == null ) { + return null; + } + + final IInventory storage = this.container.getStorage( ); + if ( storage == null ) { + return null; + } + + final ItemStack stack = this.getStack( ).copy( ); + stack.stackSize *= quantity; + + FMLCommonHandler.instance( ).firePlayerCraftingEvent( this.player , stack , this.inventory ); + stack.onCrafting( this.player.worldObj , this.player , quantity ); + UAchievements.checkCraftingAchievements( this.player , stack.getItem( ) ); + wrapper.getRequirements( ).removeFromInventory( storage , quantity ); + return stack; + } +} diff --git a/src/java/mmm/utils/UAchievements.java b/src/java/mmm/utils/UAchievements.java new file mode 100644 index 0000000..0d63af3 --- /dev/null +++ b/src/java/mmm/utils/UAchievements.java @@ -0,0 +1,52 @@ +package mmm.utils; + + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemHoe; +import net.minecraft.item.ItemPickaxe; +import net.minecraft.item.ItemSword; +import net.minecraft.stats.AchievementList; + + + +public class UAchievements +{ + + public static void checkCraftingAchievements( final EntityPlayer playerIn , final Item item ) + { + if ( item == Item.getItemFromBlock( Blocks.CRAFTING_TABLE ) ) { + playerIn.addStat( AchievementList.BUILD_WORK_BENCH ); + + } else if ( item instanceof ItemPickaxe ) { + playerIn.addStat( AchievementList.BUILD_PICKAXE ); + if ( ( (ItemPickaxe) item ).getToolMaterial( ) != Item.ToolMaterial.WOOD ) { + playerIn.addStat( AchievementList.BUILD_BETTER_PICKAXE ); + } + + } else if ( item == Item.getItemFromBlock( Blocks.FURNACE ) ) { + playerIn.addStat( AchievementList.BUILD_FURNACE ); + + } else if ( item instanceof ItemHoe ) { + playerIn.addStat( AchievementList.BUILD_HOE ); + + } else if ( item == Items.BREAD ) { + playerIn.addStat( AchievementList.MAKE_BREAD ); + + } else if ( item == Items.CAKE ) { + playerIn.addStat( AchievementList.BAKE_CAKE ); + + } else if ( item instanceof ItemSword ) { + playerIn.addStat( AchievementList.BUILD_SWORD ); + + } else if ( item == Item.getItemFromBlock( Blocks.ENCHANTING_TABLE ) ) { + playerIn.addStat( AchievementList.ENCHANTMENTS ); + + } else if ( item == Item.getItemFromBlock( Blocks.BOOKSHELF ) ) { + playerIn.addStat( AchievementList.BOOKCASE ); + } + } + +} diff --git a/src/java/mmm/utils/gui/UGSlotGroups.java b/src/java/mmm/utils/gui/UGSlotGroups.java index c5ec2aa..505c7a1 100644 --- a/src/java/mmm/utils/gui/UGSlotGroups.java +++ b/src/java/mmm/utils/gui/UGSlotGroups.java @@ -100,4 +100,16 @@ public class UGSlotGroups return this; } + + + public int getGroup( int slotIndex ) + { + int nGroups = this.firstSlots.size( ); + for ( int i = 1 ; i < nGroups ; i++ ) { + if ( slotIndex < this.firstSlots.getInt( i ) ) { + return i - 1; + } + } + return nGroups - 1; + } }