/* * This file is part of Applied Energistics 2. * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. * * Applied Energistics 2 is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Applied Energistics 2 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Applied Energistics 2. If not, see . */ package appeng.tile.crafting; import java.util.Collections; import java.util.EnumSet; import java.util.Iterator; import java.util.LinkedList; import net.minecraft.block.state.IBlockState; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; 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.storage.IMEInventory; import appeng.api.storage.data.IAEItemStack; import appeng.api.util.AEPartLocation; import appeng.api.util.WorldCoord; import appeng.block.crafting.BlockCraftingUnit; import appeng.block.crafting.BlockCraftingUnit.CraftingUnitType; 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 { private final CraftingCPUCalculator calc = new CraftingCPUCalculator( this ); public NBTTagCompound previousState = null; public boolean isCoreBlock = false; CraftingCPUCluster cluster; public TileCraftingTile() { this.gridProxy.setFlags( GridFlags.MULTIBLOCK, GridFlags.REQUIRE_CHANNEL ); this.gridProxy.setValidSides( EnumSet.noneOf( EnumFacing.class ) ); } @Override protected AENetworkProxy createProxy() { return new AENetworkProxyMultiblock( this, "proxy", this.getItemFromTile( this ), true ); } @Override protected ItemStack getItemFromTile( Object obj ) { if( ( (TileCraftingTile) obj ).isAccelerator() ) { for( ItemStack accelerator : AEApi.instance().definitions().blocks().craftingAccelerator().maybeStack( 1 ).asSet() ) { return accelerator; } } return super.getItemFromTile( obj ); } @Override public boolean canBeRotated() { return true;// return BlockCraftingUnit.checkType( worldObj.getBlockMetadata( xCoord, yCoord, zCoord ), // BlockCraftingUnit.BASE_MONITOR ); } @Override public void setName( String name ) { super.setName( name ); if( this.cluster != null ) { this.cluster.updateName(); } } public boolean isAccelerator() { if( this.worldObj == null ) { return false; } BlockCraftingUnit unit = (BlockCraftingUnit)this.worldObj.getBlockState( pos ).getBlock(); return unit.type == CraftingUnitType.ACCELERATOR; } @Override public void onReady() { super.onReady(); this.gridProxy.setVisualRepresentation( this.getItemFromTile( this ) ); this.updateMultiBlock(); } public void updateMultiBlock() { this.calc.calculateMultiblock( this.worldObj, this.getLocation() ); } public void updateStatus( CraftingCPUCluster c ) { if( this.cluster != null && this.cluster != c ) { this.cluster.breakCluster(); } this.cluster = c; this.updateMeta( true ); } public void updateMeta( boolean updateFormed ) { if( this.worldObj == null || this.notLoaded() ) { return; } boolean formed = this.isFormed(); boolean power = false; if( this.gridProxy.isReady() ) { power = this.gridProxy.isActive(); } IBlockState current = this.worldObj.getBlockState( pos ); IBlockState newState = current.withProperty( BlockCraftingUnit.POWERED, power ).withProperty( BlockCraftingUnit.FORMED, formed ); if( current != newState ) { this.worldObj.setBlockState( pos, newState ); } if( updateFormed ) { if( formed ) { this.gridProxy.setValidSides( EnumSet.allOf( EnumFacing.class ) ); } else { this.gridProxy.setValidSides( EnumSet.noneOf( EnumFacing.class ) ); } } } public boolean isFormed() { if( Platform.isClient() ) { return (boolean)this.worldObj.getBlockState( pos ).getValue( BlockCraftingUnit.FORMED ); } return this.cluster != null; } @TileEvent( TileEventType.WORLD_NBT_WRITE ) public void writeToNBT_TileCraftingTile( NBTTagCompound data ) { data.setBoolean( "core", this.isCoreBlock ); if( this.isCoreBlock && this.cluster != null ) { this.cluster.writeToNBT( data ); } } @TileEvent( TileEventType.WORLD_NBT_READ ) public void readFromNBT_TileCraftingTile( NBTTagCompound data ) { this.isCoreBlock = data.getBoolean( "core" ); if( this.isCoreBlock ) { if( this.cluster != null ) { this.cluster.readFromNBT( data ); } else { this.previousState = (NBTTagCompound) data.copy(); } } } @Override public void disconnect( boolean update ) { if( this.cluster != null ) { this.cluster.destroy(); if( update ) { this.updateMeta( true ); } } } @Override public IAECluster getCluster() { return this.cluster; } @Override public boolean isValid() { return true; } @MENetworkEventSubscribe public void onPowerStateChange( MENetworkChannelsChanged ev ) { this.updateMeta( false ); } @MENetworkEventSubscribe public void onPowerStateChange( MENetworkPowerStatusChange ev ) { this.updateMeta( false ); } public boolean isStatus() { return false; } public boolean isStorage() { return false; } public int getStorageBytes() { return 0; } public void breakCluster() { if( this.cluster != null ) { this.cluster.cancel(); IMEInventory inv = this.cluster.getInventory(); LinkedList places = new LinkedList(); Iterator i = this.cluster.getTiles(); while( i.hasNext() ) { IGridHost h = i.next(); if( h == this ) { places.add( new WorldCoord( this ) ); } else { TileEntity te = (TileEntity) h; for( AEPartLocation d : AEPartLocation.SIDE_LOCATIONS ) { WorldCoord wc = new WorldCoord( te ); wc.add( d, 1 ); if( this.worldObj.isAirBlock( wc.getPos() ) ) { places.add( wc ); } } } } Collections.shuffle( places ); if( places.isEmpty() ) { throw new IllegalStateException( this.cluster + " does not contain any kind of blocks, which were 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, this.cluster.getActionSource() ); if( g == null ) { break; } WorldCoord wc = places.poll(); places.add( wc ); Platform.spawnDrops( this.worldObj, wc.getPos(), Collections.singletonList( g.getItemStack() ) ); } } this.cluster.destroy(); } } @Override public boolean isPowered() { if( Platform.isClient() ) { return (boolean)this.worldObj.getBlockState( pos ).getValue( BlockCraftingUnit.POWERED ); } return this.gridProxy.isActive(); } @Override public boolean isActive() { if( Platform.isServer() ) { return this.gridProxy.isActive(); } return this.isPowered() && this.isFormed(); } }