Alloy furnace - Alloying!

This commit is contained in:
Emmanuel BENOîT 2016-06-23 16:40:53 +02:00
parent b68a081350
commit b5176a9f49
6 changed files with 382 additions and 7 deletions

View file

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

View file

@ -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,10 +294,11 @@ 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 );
final TileEntity te = worldIn.getTileEntity( pos );
if ( ! ( te instanceof TBAlloyFurnaceTileEntity ) || playerIn.isSneaking( ) ) {
return false;
}
@ -276,4 +306,22 @@ public class TBAlloyFurnaceBlock
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 );
}
}

View file

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

View file

@ -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
* <p>
* In order to do that, we need to check that:
* <ul>
* <li>the current recipe's requirements are present in the input slot, AND
* <li>either there is a free output slot OR there is an output slot with the current output
* which can accept enough items.
* </ul>
*
* @return <code>true</code> 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 );
}
}
}

View file

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

View file

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