package appeng.tile.crafting; import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; import java.util.Iterator; import java.util.LinkedList; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.util.ForgeDirection; import appeng.api.AEApi; import appeng.api.config.Actionable; import appeng.api.implementations.IPowerChannelState; import appeng.api.networking.GridFlags; import appeng.api.networking.IGridHost; import appeng.api.networking.events.MENetworkChannelsChanged; import appeng.api.networking.events.MENetworkEventSubscribe; import appeng.api.networking.events.MENetworkPowerStatusChange; import appeng.api.parts.ISimplifiedBundle; import appeng.api.storage.IMEInventory; import appeng.api.storage.data.IAEItemStack; import appeng.api.util.WorldCoord; import appeng.me.cluster.IAECluster; import appeng.me.cluster.IAEMultiBlock; import appeng.me.cluster.implementations.CraftingCPUCalculator; import appeng.me.cluster.implementations.CraftingCPUCluster; import appeng.me.helpers.AENetworkProxy; import appeng.me.helpers.AENetworkProxyMultiblock; import appeng.tile.TileEvent; import appeng.tile.events.TileEventType; import appeng.tile.grid.AENetworkTile; import appeng.util.Platform; public class TileCraftingTile extends AENetworkTile implements IAEMultiBlock, IPowerChannelState { CraftingCPUCluster clust; final CraftingCPUCalculator calc = new CraftingCPUCalculator( this ); public ISimplifiedBundle lightCache; public NBTTagCompound previousState = null; public boolean isCoreBlock = false; static final ItemStack coProcessorStack = AEApi.instance().blocks().blockCraftingAccelerator.stack( 1 ); @Override protected AENetworkProxy createProxy() { return new AENetworkProxyMultiblock( this, "proxy", getItemFromTile( this ), true ); } @Override protected ItemStack getItemFromTile(Object obj) { if ( ((TileCraftingTile) obj).isAccelerator() ) return coProcessorStack; return super.getItemFromTile( obj ); } public void updateStatus(CraftingCPUCluster c) { if ( clust != null && clust != c ) clust.breakCluster(); clust = c; updateMeta( true ); } public void updateMultiBlock() { calc.calculateMultiblock( worldObj, getLocation() ); } public void setName(String name) { super.setName( name ); if ( clust != null ) clust.updateName(); } @TileEvent(TileEventType.WORLD_NBT_WRITE) public void writeToNBT_TileCraftingTile(NBTTagCompound data) { data.setBoolean( "core", isCoreBlock ); if ( isCoreBlock && clust != null ) clust.writeToNBT( data ); } @TileEvent(TileEventType.WORLD_NBT_READ) public void readFromNBT_TileCraftingTile(NBTTagCompound data) { isCoreBlock = data.getBoolean( "core" ); if ( isCoreBlock ) { if ( clust != null ) clust.readFromNBT( data ); else previousState = (NBTTagCompound) data.copy(); } } public TileCraftingTile() { gridProxy.setFlags( GridFlags.MULTIBLOCK, GridFlags.REQUIRE_CHANNEL ); gridProxy.setValidSides( EnumSet.noneOf( ForgeDirection.class ) ); } @Override public void onReady() { super.onReady(); gridProxy.setVisualRepresentation( getItemFromTile( this ) ); updateMultiBlock(); } @Override public boolean canBeRotated() { return true;// return BlockCraftingUnit.checkType( worldObj.getBlockMetadata( xCoord, yCoord, zCoord ), // BlockCraftingUnit.BASE_MONITOR ); } @Override public void disconnect(boolean update) { if ( clust != null ) { clust.destroy(); if ( update ) updateMeta( true ); } } @MENetworkEventSubscribe public void onPowerStateChage(MENetworkChannelsChanged ev) { updateMeta( false ); } @MENetworkEventSubscribe public void onPowerStateChage(MENetworkPowerStatusChange ev) { updateMeta( false ); } public void updateMeta(boolean updateFormed) { if ( worldObj == null || notLoaded() ) return; boolean formed = isFormed(); boolean power = false; if ( gridProxy.isReady() ) power = gridProxy.isActive(); int current = worldObj.getBlockMetadata( xCoord, yCoord, zCoord ); int newmeta = (current & 3) | (formed ? 8 : 0) | (power ? 4 : 0); if ( current != newmeta ) worldObj.setBlockMetadataWithNotify( xCoord, yCoord, zCoord, newmeta, 2 ); if ( updateFormed ) { if ( formed ) gridProxy.setValidSides( EnumSet.allOf( ForgeDirection.class ) ); else gridProxy.setValidSides( EnumSet.noneOf( ForgeDirection.class ) ); } } @Override public IAECluster getCluster() { return clust; } @Override public boolean isValid() { return true; } @Override public boolean isPowered() { if ( Platform.isClient() ) return (worldObj.getBlockMetadata( xCoord, yCoord, zCoord ) & 4) == 4; return gridProxy.isActive(); } public boolean isFormed() { if ( Platform.isClient() ) return (worldObj.getBlockMetadata( xCoord, yCoord, zCoord ) & 8) == 8; return clust != null; } public boolean isAccelerator() { if ( worldObj == null ) return false; return (worldObj.getBlockMetadata( xCoord, yCoord, zCoord ) & 3) == 1; } public boolean isStatus() { return false; } public boolean isStorage() { return false; } public int getStorageBytes() { return 0; } @Override public boolean isActive() { if ( Platform.isServer() ) return gridProxy.isActive(); return isPowered() && isFormed(); } public void breakCluster() { if ( clust != null ) { clust.cancel(); IMEInventory inv = clust.getInventory(); LinkedList places = new LinkedList(); Iterator i = clust.getTiles(); while (i.hasNext()) { IGridHost h = i.next(); if ( h == this ) places.add( new WorldCoord( this ) ); else { TileEntity te = (TileEntity) h; for (ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) { WorldCoord wc = new WorldCoord( te ); wc.add( d, 1 ); if ( worldObj.isAirBlock( wc.x, wc.y, wc.z ) ) places.add( wc ); } } } Collections.shuffle( places ); if ( places.isEmpty() ) throw new RuntimeException( "No air or even the tile hat was destroyed?!?!" ); for (IAEItemStack ais : inv.getAvailableItems( AEApi.instance().storage().createItemList() )) { ais = ais.copy(); ais.setStackSize( ais.getItemStack().getMaxStackSize() ); while (true) { IAEItemStack g = inv.extractItems( ais.copy(), Actionable.MODULATE, clust.getActionSource() ); if ( g == null ) break; WorldCoord wc = places.poll(); places.add( wc ); Platform.spawnDrops( worldObj, wc.x, wc.y, wc.z, Arrays.asList( g.getItemStack() ) ); } } clust.destroy(); } } }