From b5176a9f49925a1ea5ac7391384c057293d4ddee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Thu, 23 Jun 2016 16:40:53 +0200 Subject: [PATCH] Alloy furnace - Alloying! --- src/java/mmm/materials/MAlloyRecipe.java | 30 ++ .../mmm/tech/base/TBAlloyFurnaceBlock.java | 56 +++- src/java/mmm/tech/base/TBAlloyFurnaceGui.java | 22 ++ .../tech/base/TBAlloyFurnaceTileEntity.java | 277 +++++++++++++++++- src/java/mmm/tech/base/TechBase.java | 2 +- src/java/mmm/utils/UInventoryGrid.java | 2 +- 6 files changed, 382 insertions(+), 7 deletions(-) diff --git a/src/java/mmm/materials/MAlloyRecipe.java b/src/java/mmm/materials/MAlloyRecipe.java index 7ee07e3..4069428 100644 --- a/src/java/mmm/materials/MAlloyRecipe.java +++ b/src/java/mmm/materials/MAlloyRecipe.java @@ -7,6 +7,7 @@ import java.util.HashMap; import mmm.Mmm; import mmm.utils.UItemId; import net.minecraft.block.Block; +import net.minecraft.inventory.IInventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; @@ -234,4 +235,33 @@ public class MAlloyRecipe return this.output.getItem( ).getItemStackDisplayName( this.output ); } + + public boolean checkInventory( final IInventory input ) + { + return this.checkInventory( input , 0 , input.getSizeInventory( ) ); + } + + + public boolean checkInventory( final IInventory input , final int first , final int last ) + { + for ( int i = 0 ; i < this.inputs.length ; i++ ) { + final ItemStack inputStack = this.inputs[ i ]; + int found = 0; + for ( int slot = first ; slot < last ; slot++ ) { + final ItemStack stackInSlot = input.getStackInSlot( slot ); + if ( stackInSlot == null || !inputStack.isItemEqual( stackInSlot ) ) { + continue; + } + found += stackInSlot.stackSize; + if ( found >= inputStack.stackSize ) { + break; + } + } + if ( found < inputStack.stackSize ) { + return false; + } + } + return true; + } + } diff --git a/src/java/mmm/tech/base/TBAlloyFurnaceBlock.java b/src/java/mmm/tech/base/TBAlloyFurnaceBlock.java index 82505ff..44504b7 100644 --- a/src/java/mmm/tech/base/TBAlloyFurnaceBlock.java +++ b/src/java/mmm/tech/base/TBAlloyFurnaceBlock.java @@ -22,6 +22,7 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; +import net.minecraft.inventory.InventoryHelper; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; @@ -50,6 +51,8 @@ public class TBAlloyFurnaceBlock public static final PropertyDirection FACING = BlockHorizontal.FACING; + private static boolean keepInventory = false; + public final boolean active; @@ -79,6 +82,32 @@ public class TBAlloyFurnaceBlock } + public static void setState( final boolean burning , final World world , final BlockPos pos ) + { + final IBlockState iblockstate = world.getBlockState( pos ); + final TileEntity tileentity = world.getTileEntity( pos ); + + TBAlloyFurnaceBlock.keepInventory = true; + if ( burning ) { + world.setBlockState( pos , TechBase.ALLOY_FURNACE_BLOCK_ACTIVE.getDefaultState( ).withProperty( + TBAlloyFurnaceBlock.FACING , iblockstate.getValue( TBAlloyFurnaceBlock.FACING ) ) , 3 ); + world.setBlockState( pos , TechBase.ALLOY_FURNACE_BLOCK_ACTIVE.getDefaultState( ).withProperty( + TBAlloyFurnaceBlock.FACING , iblockstate.getValue( TBAlloyFurnaceBlock.FACING ) ) , 3 ); + } else { + world.setBlockState( pos , TechBase.ALLOY_FURNACE_BLOCK_INACTIVE.getDefaultState( ).withProperty( + TBAlloyFurnaceBlock.FACING , iblockstate.getValue( TBAlloyFurnaceBlock.FACING ) ) , 3 ); + world.setBlockState( pos , TechBase.ALLOY_FURNACE_BLOCK_INACTIVE.getDefaultState( ).withProperty( + TBAlloyFurnaceBlock.FACING , iblockstate.getValue( TBAlloyFurnaceBlock.FACING ) ) , 3 ); + } + TBAlloyFurnaceBlock.keepInventory = false; + + if ( tileentity != null ) { + tileentity.validate( ); + world.setTileEntity( pos , tileentity ); + } + } + + // ************************************************************************************************* // RENDERING AND COLLISIONS // ************************************************************************************************* @@ -265,15 +294,34 @@ public class TBAlloyFurnaceBlock // ************************************************************************************************* @Override - public boolean onBlockActivated( World worldIn , BlockPos pos , IBlockState state , EntityPlayer playerIn , - EnumHand hand , ItemStack heldItem , EnumFacing side , float hitX , float hitY , float hitZ ) + public boolean onBlockActivated( final World worldIn , final BlockPos pos , final IBlockState state , + final EntityPlayer playerIn , final EnumHand hand , final ItemStack heldItem , final EnumFacing side , + final float hitX , final float hitY , final float hitZ ) { - TileEntity te = worldIn.getTileEntity( pos ); - if ( !(te instanceof TBAlloyFurnaceTileEntity ) || playerIn.isSneaking( ) ) { + final TileEntity te = worldIn.getTileEntity( pos ); + if ( ! ( te instanceof TBAlloyFurnaceTileEntity ) || playerIn.isSneaking( ) ) { return false; } playerIn.openGui( Mmm.get( ) , 0 , worldIn , pos.getX( ) , pos.getY( ) , pos.getZ( ) ); return true; } + + @Override + public void breakBlock( final World worldIn , final BlockPos pos , final IBlockState state ) + { + if ( !TBAlloyFurnaceBlock.keepInventory ) { + final TileEntity tileEntity = worldIn.getTileEntity( pos ); + + if ( tileEntity instanceof TBAlloyFurnaceTileEntity ) { + final TBAlloyFurnaceTileEntity afte = (TBAlloyFurnaceTileEntity) tileEntity; + InventoryHelper.dropInventoryItems( worldIn , pos , afte.input ); + InventoryHelper.dropInventoryItems( worldIn , pos , afte.fuel ); + InventoryHelper.dropInventoryItems( worldIn , pos , afte.output ); + } + } + + super.breakBlock( worldIn , pos , state ); + } + } diff --git a/src/java/mmm/tech/base/TBAlloyFurnaceGui.java b/src/java/mmm/tech/base/TBAlloyFurnaceGui.java index 2e0303e..574f50f 100644 --- a/src/java/mmm/tech/base/TBAlloyFurnaceGui.java +++ b/src/java/mmm/tech/base/TBAlloyFurnaceGui.java @@ -12,6 +12,7 @@ import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -194,6 +195,27 @@ public class TBAlloyFurnaceGui this.mc.getTextureManager( ).bindTexture( TBAlloyFurnaceGui.TEXTURES[ this.selectedTab.ordinal( ) ] ); this.drawTexturedModalRect( this.guiLeft , this.guiTop , 0 , 0 , this.xSize , this.ySize ); + if ( this.selectedTab == Tab.MAIN ) { + int x = ( this.width - this.xSize ) / 2; + int y = ( this.height - this.ySize ) / 2; + + TileEntity atPos = this.container.world.getTileEntity( this.container.position ); + if ( atPos instanceof TBAlloyFurnaceTileEntity ) { + TBAlloyFurnaceTileEntity te = (TBAlloyFurnaceTileEntity) atPos; + // Burn + if ( te.isBurning( ) ) { + int burn = te.getBurnProgress( 13 ); + this.drawTexturedModalRect( x + 89 , y + 38 + 13 - burn , 176 , 28 - burn , 14 , burn + 1 ); + } + + // Alloying progress + if ( te.isAlloying( ) ) { + int alloy = te.getAlloyingProgress( 47 ); + this.drawTexturedModalRect( x + 73 , y + 17 , 176 , 29 , alloy + 1 , 16 ); + } + } + } + // Active tab this.mc.getTextureManager( ).bindTexture( TBAlloyFurnaceGui.TEXTURES[ 0 ] ); this.drawTab( this.selectedTab ); diff --git a/src/java/mmm/tech/base/TBAlloyFurnaceTileEntity.java b/src/java/mmm/tech/base/TBAlloyFurnaceTileEntity.java index 9a8fa56..fc3ff26 100644 --- a/src/java/mmm/tech/base/TBAlloyFurnaceTileEntity.java +++ b/src/java/mmm/tech/base/TBAlloyFurnaceTileEntity.java @@ -4,10 +4,13 @@ package mmm.tech.base; import mmm.materials.MAlloyRecipe; import mmm.utils.UInventoryGrid; import net.minecraft.block.state.IBlockState; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; import net.minecraft.network.play.server.SPacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityFurnace; +import net.minecraft.util.ITickable; import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.util.Constants.NBT; @@ -15,6 +18,7 @@ import net.minecraftforge.common.util.Constants.NBT; public class TBAlloyFurnaceTileEntity extends TileEntity + implements ITickable { public final UInventoryGrid input; @@ -23,6 +27,11 @@ public class TBAlloyFurnaceTileEntity public MAlloyRecipe recipe; + private MAlloyRecipe alloying; + private int alloyCurrent; + private int burnCurrent; + private int burnTotal; + public TBAlloyFurnaceTileEntity( ) { @@ -52,7 +61,6 @@ public class TBAlloyFurnaceTileEntity compound.setTag( "Fuel" , this.fuel.serializeNBT( ) ); compound.setTag( "Output" , this.output.serializeNBT( ) ); this.writeSyncData( compound ); - System.err.println( "tag " + compound.toString( ) ); return compound; } @@ -86,6 +94,61 @@ public class TBAlloyFurnaceTileEntity } + @Override + public void update( ) + { + if ( this.worldObj.isRemote ) { + return; + } + + final boolean wasBurning = this.isBurning( ); + boolean dirty = false; + + if ( wasBurning ) { + dirty = true; + this.burnCurrent--; + + if ( this.alloying != null ) { + this.alloyCurrent--; + if ( this.alloyCurrent == 0 ) { + this.addOutput( ); + if ( this.canAlloy( ) ) { + this.startAlloying( ); + } else { + this.alloying = null; + } + } + } + + if ( this.burnCurrent == 0 ) { + if ( this.alloying != null ) { + if ( !this.startBurning( this.alloyCurrent ) ) { + // XXX produce slag + this.alloying = null; + this.alloyCurrent = this.burnCurrent = this.burnTotal = 0; + } + } else { + this.burnTotal = this.burnCurrent = 0; + } + } + + } else if ( this.canAlloy( ) && this.startBurning( this.recipe.burnTime ) ) { + this.startAlloying( ); + dirty = true; + } + + if ( this.isBurning( ) != wasBurning ) { + TBAlloyFurnaceBlock.setState( this.isBurning( ) , this.worldObj , this.pos ); + } + + if ( dirty ) { + this.markDirty( ); + final IBlockState state = this.worldObj.getBlockState( this.pos ); + this.worldObj.notifyBlockUpdate( this.pos , state , state , 3 ); + } + } + + public void setRecipe( final ResourceLocation location ) { MAlloyRecipe recipe = MAlloyRecipe.REGISTRY.getRecipe( location ); @@ -106,6 +169,195 @@ public class TBAlloyFurnaceTileEntity } + public boolean isBurning( ) + { + return this.burnTotal != 0; + } + + + public int getBurnProgress( int max ) + { + int t = this.burnTotal; + if ( t == 0 ) { + t = 200; + } + return Math.min( max , this.burnCurrent * max / t ); + } + + + /** + * Find the most appropriate fuel for the specified burn time. + * + * @param requiredBurnTime + * the burn time we need + * + * @return the fuel slot's index, or -1 if there is no fuel. + */ + private int getBestFuel( final int requiredBurnTime ) + { + int bestStack = -1 , bestDiff = Integer.MAX_VALUE; + for ( int i = 0 ; i < this.fuel.slotsCount ; i++ ) { + final ItemStack fuel = this.fuel.inventoryContents[ i ]; + if ( fuel == null || fuel.stackSize == 0 ) { + continue; + } + final int fuelBurnTime = TileEntityFurnace.getItemBurnTime( fuel ); + final int diff = Math.abs( requiredBurnTime - fuelBurnTime ); + if ( diff < bestDiff ) { + bestStack = i; + bestDiff = diff; + } + } + return bestStack; + } + + + private boolean startBurning( final int requiredBurnTime ) + { + final int fuelSlot = this.getBestFuel( requiredBurnTime ); + if ( fuelSlot == -1 ) { + return false; + } + + final ItemStack fuelStack = this.fuel.inventoryContents[ fuelSlot ]; + this.burnCurrent = this.burnTotal = TileEntityFurnace.getItemBurnTime( fuelStack ); + + fuelStack.stackSize--; + if ( fuelStack.stackSize == 0 ) { + final ItemStack replace = fuelStack.getItem( ).getContainerItem( fuelStack ); + this.fuel.inventoryContents[ fuelSlot ] = replace; + } + + return true; + } + + + /** + * Checks if alloying is possible + *

+ * In order to do that, we need to check that: + *

+ * + * @return true if alloying is possible + */ + public boolean canAlloy( ) + { + if ( !this.recipe.checkInventory( this.input ) ) { + return false; + } + + final ItemStack output = this.recipe.output; + final int fullStack = Math.min( this.output.getInventoryStackLimit( ) , output.getMaxStackSize( ) ); + int freeSpace = 0; + + for ( int i = 0 ; i < this.output.slotsCount && freeSpace < output.stackSize ; i++ ) { + final ItemStack outputSlot = this.output.inventoryContents[ i ]; + if ( outputSlot == null ) { + freeSpace += fullStack; + } else if ( outputSlot.isItemEqual( output ) ) { + freeSpace += fullStack - outputSlot.stackSize; + } + } + + return freeSpace >= output.stackSize; + } + + + public boolean isAlloying( ) + { + return this.alloying != null; + } + + + public int getAlloyingProgress( int max ) + { + if ( this.alloying == null ) { + return max; + } + + int t = this.alloying.burnTime; + if ( t == 0 ) { + t = 200; + } + return Math.min( max , ( t - this.alloyCurrent ) * max / t ); + } + + + private void startAlloying( ) + { + this.removeRecipeInput( ); + this.alloying = this.recipe; + this.alloyCurrent = this.recipe.burnTime; + } + + + private void removeRecipeInput( ) + { + final ItemStack[] rIn = this.recipe.inputs; + final int inSlots = this.input.slotsCount; + for ( int i = 0 ; i < rIn.length ; i++ ) { + final ItemStack inputStack = rIn[ i ]; + int found = 0; + for ( int slot = 0 ; slot < inSlots ; slot++ ) { + final ItemStack stackInSlot = this.input.inventoryContents[ slot ]; + if ( stackInSlot == null || !inputStack.isItemEqual( stackInSlot ) ) { + continue; + } + + final int take = Math.min( inputStack.stackSize - found , stackInSlot.stackSize ); + found += take; + stackInSlot.stackSize -= take; + if ( stackInSlot.stackSize == 0 ) { + final ItemStack replace = stackInSlot.getItem( ).getContainerItem( stackInSlot ); + this.input.inventoryContents[ slot ] = replace; + } + + if ( found == inputStack.stackSize ) { + break; + } + } + } + } + + + private void addOutput( ) + { + final ItemStack wanted = this.alloying.output; + final int maxStackSize = Math.min( this.output.getInventoryStackLimit( ) , wanted.getMaxStackSize( ) ); + int added = 0; + for ( int i = 0 ; i < this.output.slotsCount ; i++ ) { + ItemStack outputStack = this.output.inventoryContents[ i ]; + int canAdd; + if ( outputStack == null ) { + canAdd = maxStackSize; + outputStack = new ItemStack( wanted.getItem( ) , 0 , wanted.getItemDamage( ) ); + this.output.inventoryContents[ i ] = outputStack; + + } else if ( outputStack.isItemEqual( wanted ) ) { + canAdd = maxStackSize - outputStack.stackSize; + + } else { + canAdd = 0; + } + + if ( canAdd == 0 ) { + continue; + } + + final int doAdd = Math.min( canAdd , wanted.stackSize - added ); + added += doAdd; + outputStack.stackSize += doAdd; + if ( added == wanted.stackSize ) { + break; + } + } + } + + private void readSyncData( final NBTTagCompound compound ) { final String recipeName = compound.getString( "Recipe" ); @@ -113,12 +365,35 @@ public class TBAlloyFurnaceTileEntity if ( this.recipe == null ) { this.recipe = MAlloyRecipe.REGISTRY.getRecipes( ).get( 0 ); } + + this.burnCurrent = compound.getInteger( "BurnCurrent" ); + this.burnTotal = compound.getInteger( "BurnTotal" ); + + final String alloyingRecipeName = compound.getString( "AlloyRecipe" ); + if ( "".equals( alloyingRecipeName ) ) { + this.alloying = null; + } else { + this.alloying = MAlloyRecipe.REGISTRY.getRecipe( new ResourceLocation( recipeName ) ); + } + if ( this.alloying == null ) { + this.alloyCurrent = 0; + } else { + this.alloyCurrent = compound.getInteger( "AlloyCurrent" ); + } } private void writeSyncData( final NBTTagCompound compound ) { compound.setString( "Recipe" , this.recipe.name.toString( ) ); + if ( this.alloying != null ) { + compound.setString( "AlloyRecipe" , this.alloying.name.toString( ) ); + compound.setInteger( "AlloyCurrent" , this.alloyCurrent ); + } + if ( this.burnTotal != 0 ) { + compound.setInteger( "BurnTotal" , this.burnTotal ); + compound.setInteger( "BurnCurrent" , this.burnCurrent ); + } } } diff --git a/src/java/mmm/tech/base/TechBase.java b/src/java/mmm/tech/base/TechBase.java index 87c73d9..92317cf 100644 --- a/src/java/mmm/tech/base/TechBase.java +++ b/src/java/mmm/tech/base/TechBase.java @@ -32,7 +32,7 @@ public class TechBase URegistry.addServerMessage( TBAlloyFurnaceMessage.class ); // FIXME test, remove this later - MAlloyRecipe.build( ).setName( "test" ).setBurnTime( 200 ).setExperience( .05f ) + MAlloyRecipe.build( ).setName( "test" ).setBurnTime( 50 ).setExperience( .05f ) .setOutput( Items.COOKED_CHICKEN , 10 ).addInput( Items.COOKED_BEEF ).addInput( Items.COOKED_PORKCHOP ) .register( ); } diff --git a/src/java/mmm/utils/UInventoryGrid.java b/src/java/mmm/utils/UInventoryGrid.java index a6eabe8..763cb48 100644 --- a/src/java/mmm/utils/UInventoryGrid.java +++ b/src/java/mmm/utils/UInventoryGrid.java @@ -24,7 +24,7 @@ public class UInventoryGrid public final int width; public final int height; public final int slotsCount; - private final ItemStack[] inventoryContents; + public final ItemStack[] inventoryContents; public UInventoryGrid( final String name , final int width , final int height )