Applied-Energistics-2-tiler.../parts/misc/PartStorageBus.java
AlgorithmX2 2b6cca0267 Fixed some storage bus related crashes.
Fixed an issue where the storage might access inventories that have been removed from the world.
Fixed an issue caused by refactoring.
2014-07-23 23:20:16 -05:00

448 lines
12 KiB
Java

package appeng.parts.misc;
import java.util.Arrays;
import java.util.List;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Vec3;
import net.minecraftforge.common.util.ForgeDirection;
import appeng.api.AEApi;
import appeng.api.config.AccessRestriction;
import appeng.api.config.FuzzyMode;
import appeng.api.config.IncludeExclude;
import appeng.api.config.Settings;
import appeng.api.config.Upgrades;
import appeng.api.networking.IGridNode;
import appeng.api.networking.events.MENetworkCellArrayUpdate;
import appeng.api.networking.events.MENetworkChannelsChanged;
import appeng.api.networking.events.MENetworkEventSubscribe;
import appeng.api.networking.events.MENetworkPowerStatusChange;
import appeng.api.networking.security.BaseActionSource;
import appeng.api.networking.security.MachineSource;
import appeng.api.networking.storage.IBaseMonitor;
import appeng.api.networking.ticking.IGridTickable;
import appeng.api.networking.ticking.ITickManager;
import appeng.api.networking.ticking.TickRateModulation;
import appeng.api.networking.ticking.TickingRequest;
import appeng.api.parts.IPartCollsionHelper;
import appeng.api.parts.IPartRenderHelper;
import appeng.api.storage.ICellContainer;
import appeng.api.storage.IExternalStorageHandler;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.IMEInventoryHandler;
import appeng.api.storage.IMEMonitor;
import appeng.api.storage.IMEMonitorHandlerReceiver;
import appeng.api.storage.StorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.api.util.IConfigManager;
import appeng.client.texture.CableBusTextures;
import appeng.core.settings.TickRates;
import appeng.core.sync.GuiBridge;
import appeng.helpers.IPriorityHost;
import appeng.me.GridAccessException;
import appeng.me.storage.MEInventoryHandler;
import appeng.me.storage.MEMonitorIInventory;
import appeng.parts.automation.PartUpgradeable;
import appeng.tile.inventory.AppEngInternalAEInventory;
import appeng.tile.inventory.InvOperation;
import appeng.transformer.annotations.integration.Interface;
import appeng.transformer.annotations.integration.Method;
import appeng.util.Platform;
import appeng.util.prioitylist.FuzzyPriorityList;
import appeng.util.prioitylist.PrecisePriorityList;
import buildcraft.api.transport.IPipeConnection;
import buildcraft.api.transport.IPipeTile.PipeType;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@Interface(iname = "BC", iface = "buildcraft.api.transport.IPipeConnection")
public class PartStorageBus extends PartUpgradeable implements IGridTickable, ICellContainer, IMEMonitorHandlerReceiver<IAEItemStack>, IPipeConnection,
IPriorityHost
{
int priority = 0;
BaseActionSource mySrc;
AppEngInternalAEInventory Config = new AppEngInternalAEInventory( this, 63 );
public PartStorageBus(ItemStack is) {
super( PartStorageBus.class, is );
getConfigManager().registerSetting( Settings.ACCESS, AccessRestriction.READ_WRITE );
getConfigManager().registerSetting( Settings.FUZZY_MODE, FuzzyMode.IGNORE_ALL );
mySrc = new MachineSource( this );
}
boolean cached = false;
MEMonitorIInventory monitor = null;
MEInventoryHandler handler = null;
int handlerHash = 0;
boolean wasActive = false;
@MENetworkEventSubscribe
public void powerRender(MENetworkPowerStatusChange c)
{
updateStatus();
}
@MENetworkEventSubscribe
public void updateChannels(MENetworkChannelsChanged chann)
{
updateStatus();
}
private void updateStatus()
{
boolean currentActive = proxy.isActive();
if ( wasActive != currentActive )
{
wasActive = currentActive;
try
{
proxy.getGrid().postEvent( new MENetworkCellArrayUpdate() );
host.markForUpdate();
}
catch (GridAccessException e)
{
// :P
}
}
}
@Override
public boolean onPartActivate(EntityPlayer player, Vec3 pos)
{
if ( !player.isSneaking() )
{
if ( Platform.isClient() )
return true;
Platform.openGUI( player, getHost().getTile(), side, GuiBridge.GUI_STORAGEBUS );
return true;
}
return false;
}
protected int getUpgradeSlots()
{
return 5;
}
@Override
public boolean isValid(Object verificationToken)
{
return handler == verificationToken;
}
@Override
public IInventory getInventoryByName(String name)
{
if ( name.equals( "config" ) )
return Config;
return super.getInventoryByName( name );
}
private void resetCache(boolean fullReset)
{
if ( host == null || host.getTile() == null || host.getTile().getWorldObj() == null )
return;
IMEInventory<IAEItemStack> in = getInternalHandler();
IItemList<IAEItemStack> before = AEApi.instance().storage().createItemList();
if ( in != null )
before = in.getAvailableItems( before );
cached = false;
if ( fullReset )
handlerHash = 0;
IMEInventory<IAEItemStack> out = getInternalHandler();
if ( monitor != null )
monitor.onTick();
IItemList<IAEItemStack> after = AEApi.instance().storage().createItemList();
if ( out != null )
after = out.getAvailableItems( after );
Platform.postListChanges( before, after, this, mySrc );
}
@Override
public void onNeighborChanged()
{
resetCache( false );
}
@Override
public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removedStack, ItemStack newStack)
{
super.onChangeInventory( inv, slot, mc, removedStack, newStack );
if ( inv == Config )
resetCache( true );
}
@Override
public void upgradesChanged()
{
super.upgradesChanged();
resetCache( true );
}
@Override
public void updateSetting(IConfigManager manager, Enum settingName, Enum newValue)
{
resetCache( true );
host.markForSave();
}
@Override
public void setPriority(int newValue)
{
priority = newValue;
host.markForSave();
resetCache( true );
}
public MEInventoryHandler getInternalHandler()
{
if ( cached )
return handler;
boolean wasSleeping = monitor == null;
cached = true;
TileEntity self = getHost().getTile();
TileEntity target = self.getWorldObj().getTileEntity( self.xCoord + side.offsetX, self.yCoord + side.offsetY, self.zCoord + side.offsetZ );
int newHandlerHash = Platform.generateTileHash( target );
if ( handlerHash == newHandlerHash && handlerHash != 0 )
return handler;
try
{
// force grid to update handlers...
proxy.getGrid().postEvent( new MENetworkCellArrayUpdate() );
}
catch (GridAccessException e)
{
// :3
}
handlerHash = newHandlerHash;
handler = null;
monitor = null;
if ( target != null )
{
IExternalStorageHandler esh = AEApi.instance().registries().externalStorage().getHandler( target, side.getOpposite(), StorageChannel.ITEMS, mySrc );
if ( esh != null )
{
IMEInventory inv = esh.getInventory( target, side.getOpposite(), StorageChannel.ITEMS, mySrc );
if ( inv instanceof MEMonitorIInventory )
((MEMonitorIInventory) inv).mySource = new MachineSource( this );
if ( inv instanceof MEMonitorIInventory )
monitor = (MEMonitorIInventory) inv;
if ( inv != null )
{
handler = new MEInventoryHandler( inv, StorageChannel.ITEMS );
handler.myAccess = (AccessRestriction) this.getConfigManager().getSetting( Settings.ACCESS );
handler.myWhitelist = getInstalledUpgrades( Upgrades.INVERTER ) > 0 ? IncludeExclude.BLACKLIST : IncludeExclude.WHITELIST;
handler.myPriority = priority;
IItemList<IAEItemStack> priorityList = AEApi.instance().storage().createItemList();
int slotsToUse = 18 + getInstalledUpgrades( Upgrades.CAPACITY ) * 9;
for (int x = 0; x < Config.getSizeInventory() && x < slotsToUse; x++)
{
IAEItemStack is = Config.getAEStackInSlot( x );
if ( is != null )
priorityList.add( is );
}
if ( getInstalledUpgrades( Upgrades.FUZZY ) > 0 )
handler.myPartitionList = new FuzzyPriorityList( priorityList, (FuzzyMode) this.getConfigManager().getSetting( Settings.FUZZY_MODE ) );
else
handler.myPartitionList = new PrecisePriorityList( priorityList );
if ( inv instanceof IMEMonitor )
((IMEMonitor) inv).addListener( this, handler );
}
}
}
// update sleep state...
if ( wasSleeping != (monitor == null) )
{
try
{
ITickManager tm = proxy.getTick();
if ( monitor == null )
tm.sleepDevice( proxy.getNode() );
else
tm.wakeDevice( proxy.getNode() );
}
catch (GridAccessException e)
{
// :(
}
}
return handler;
}
@Override
@SideOnly(Side.CLIENT)
public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer)
{
rh.setTexture( CableBusTextures.PartStorageSides.getIcon(), CableBusTextures.PartStorageSides.getIcon(), CableBusTextures.PartStorageBack.getIcon(),
is.getIconIndex(), CableBusTextures.PartStorageSides.getIcon(), CableBusTextures.PartStorageSides.getIcon() );
rh.setBounds( 3, 3, 15, 13, 13, 16 );
rh.renderInventoryBox( renderer );
rh.setBounds( 2, 2, 14, 14, 14, 15 );
rh.renderInventoryBox( renderer );
rh.setBounds( 5, 5, 12, 11, 11, 14 );
rh.renderInventoryBox( renderer );
}
@Override
@SideOnly(Side.CLIENT)
public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer)
{
renderCache = rh.useSimpliedRendering( x, y, z, this, renderCache );
rh.setTexture( CableBusTextures.PartStorageSides.getIcon(), CableBusTextures.PartStorageSides.getIcon(), CableBusTextures.PartStorageBack.getIcon(),
is.getIconIndex(), CableBusTextures.PartStorageSides.getIcon(), CableBusTextures.PartStorageSides.getIcon() );
rh.setBounds( 3, 3, 15, 13, 13, 16 );
rh.renderBlock( x, y, z, renderer );
rh.setBounds( 2, 2, 14, 14, 14, 15 );
rh.renderBlock( x, y, z, renderer );
rh.setTexture( CableBusTextures.PartStorageSides.getIcon(), CableBusTextures.PartStorageSides.getIcon(), CableBusTextures.PartStorageBack.getIcon(),
is.getIconIndex(), CableBusTextures.PartStorageSides.getIcon(), CableBusTextures.PartStorageSides.getIcon() );
rh.setBounds( 5, 5, 12, 11, 11, 13 );
rh.renderBlock( x, y, z, renderer );
rh.setTexture( CableBusTextures.PartMonitorSidesStatus.getIcon(), CableBusTextures.PartMonitorSidesStatus.getIcon(),
CableBusTextures.PartMonitorBack.getIcon(), is.getIconIndex(), CableBusTextures.PartMonitorSidesStatus.getIcon(),
CableBusTextures.PartMonitorSidesStatus.getIcon() );
rh.setBounds( 5, 5, 13, 11, 11, 14 );
rh.renderBlock( x, y, z, renderer );
renderLights( x, y, z, rh, renderer );
}
@Override
public void getBoxes(IPartCollsionHelper bch)
{
bch.addBox( 3, 3, 15, 13, 13, 16 );
bch.addBox( 2, 2, 14, 14, 14, 15 );
bch.addBox( 5, 5, 12, 11, 11, 14 );
}
@Override
public int cableConnectionRenderTo()
{
return 4;
}
@Override
public TickingRequest getTickingRequest(IGridNode node)
{
return new TickingRequest( TickRates.StorageBus.min, TickRates.StorageBus.max, monitor == null, false );
}
@Override
public TickRateModulation tickingRequest(IGridNode node, int TicksSinceLastCall)
{
if ( monitor != null )
return monitor.onTick();
return TickRateModulation.SLEEP;
}
@Override
public void writeToNBT(NBTTagCompound data)
{
super.writeToNBT( data );
Config.writeToNBT( data, "config" );
data.setInteger( "priority", priority );
}
public void readFromNBT(NBTTagCompound data)
{
super.readFromNBT( data );
Config.readFromNBT( data, "config" );
priority = data.getInteger( "priority" );
};
@Override
public List<IMEInventoryHandler> getCellArray(StorageChannel channel)
{
if ( channel == StorageChannel.ITEMS )
{
IMEInventoryHandler out = proxy.isActive() ? getInternalHandler() : null;
if ( out != null )
return Arrays.asList( new IMEInventoryHandler[] { out } );
}
return Arrays.asList( new IMEInventoryHandler[] {} );
}
@Override
public int getPriority()
{
return priority;
}
@Override
public void blinkCell(int slot)
{
}
@Override
public void postChange(IBaseMonitor<IAEItemStack> monitor, IAEItemStack change, BaseActionSource source)
{
try
{
if ( proxy.isActive() )
proxy.getStorage().postAlterationOfStoredItems( StorageChannel.ITEMS, change, mySrc );
}
catch (GridAccessException e)
{
// :(
}
}
@Override
@Method(iname = "BC")
public ConnectOverride overridePipeConnection(PipeType type, ForgeDirection with)
{
return type == PipeType.ITEM && with == side ? ConnectOverride.CONNECT : ConnectOverride.DISCONNECT;
}
@Override
public void onListUpdate()
{
// not used here.
}
}