Workbench - Actual crafting! YAY!

This commit is contained in:
Emmanuel BENOîT 2016-07-17 18:28:45 +02:00
parent 218a93ef9f
commit f121e8bd3d
6 changed files with 338 additions and 12 deletions

View file

@ -25,4 +25,12 @@ public interface I_RecipeRequirements
boolean checkInventory( IInventory inventory ); boolean checkInventory( IInventory inventory );
boolean checkInventory( IInventory inventory , int amount );
public int getMaxOutput( IInventory inventory );
void removeFromInventory( IInventory inventory, int amount );
} }

View file

@ -90,10 +90,17 @@ class RRequirements
@Override @Override
public boolean checkInventory( final IInventory inventory ) 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( ); final int nInvItems = inventory.getSizeInventory( );
for ( int i = 0 ; i < this.quantities.length ; i++ ) { 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++ ) { for ( int j = 0 ; j < nInvItems && nLeft > 0 ; j++ ) {
final ItemStack invStack = inventory.getStackInSlot( j ); final ItemStack invStack = inventory.getStackInSlot( j );
@ -108,4 +115,48 @@ class RRequirements
} }
return true; 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;
}
}
} }

View file

@ -1,14 +1,21 @@
package mmm.tech.base.workbench; package mmm.tech.base.workbench;
import javax.annotation.Nullable;
import mmm.MmmTech; import mmm.MmmTech;
import mmm.core.api.recipes.I_CraftingRecipeWrapper; import mmm.core.api.recipes.I_CraftingRecipeWrapper;
import mmm.recipes.RCraftingWrappers;
import mmm.utils.UInventoryDisplay; import mmm.utils.UInventoryDisplay;
import mmm.utils.gui.UGContainer; import mmm.utils.gui.UGContainer;
import mmm.utils.gui.UGSlotDisplay; import mmm.utils.gui.UGSlotDisplay;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryCraftResult;
import net.minecraft.inventory.Slot; import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -20,7 +27,9 @@ public class TBWBContainer
public final TBWBTileEntity tileEntity; public final TBWBTileEntity tileEntity;
public final World world; public final World world;
public final BlockPos position; 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 ) public TBWBContainer( final InventoryPlayer playerInv , final TBWBTileEntity tileEntity )
@ -35,12 +44,19 @@ public class TBWBContainer
this.addGrid( Slot::new , tileEntity.storage , 8 , 15 ); this.addGrid( Slot::new , tileEntity.storage , 8 , 15 );
this.slotGroups.nextGroup( ); this.slotGroups.nextGroup( );
this.recipe = new UInventoryDisplay( "Recipe" , 10 ); this.recipeDisplay = new UInventoryDisplay( "Recipe" , 10 );
this.addGrid( UGSlotDisplay::new , this.recipe , // this.addGrid( UGSlotDisplay::new , this.recipeDisplay , //
3 , 3 , 0 , 86 , 32 ); 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.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( ); Slot slot = (Slot) this.inventorySlots.get( index );
if ( wrapper == null ) { if ( slot == null || !slot.getHasStack( ) ) {
// XXX log if confirm is set return null;
return;
} }
wrapper.addInputsToDisplay( this.recipe ); ItemStack slotStack = slot.getStack( );
this.recipe.setInventorySlotContents( 9 , wrapper.getOutput( ) ); 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 ) { if ( setDefault ) {
// this.tileEntity.setDefaultRecipe( wrapper.getIdentifier( ) ); // 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;
}
} }

View file

@ -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;
}
}

View file

@ -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 );
}
}
}

View file

@ -100,4 +100,16 @@ public class UGSlotGroups
return this; 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;
}
} }