2b6cca0267
Fixed an issue where the storage might access inventories that have been removed from the world. Fixed an issue caused by refactoring.
448 lines
12 KiB
Java
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.
|
|
}
|
|
|
|
}
|