diff --git a/block/networking/BlockCableBus.java b/block/networking/BlockCableBus.java index d08d8459f..6f2092a9a 100644 --- a/block/networking/BlockCableBus.java +++ b/block/networking/BlockCableBus.java @@ -6,6 +6,8 @@ import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.material.Material; +import net.minecraft.client.particle.EffectRenderer; +import net.minecraft.client.particle.EntityDiggingFX; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.Entity; @@ -20,6 +22,8 @@ import net.minecraft.util.Vec3; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartHost; import appeng.api.parts.PartItemStack; import appeng.api.parts.SelectedPart; import appeng.block.AEBaseBlock; @@ -39,6 +43,8 @@ import appeng.tile.AEBaseTile; import appeng.tile.networking.TileCableBus; import appeng.tile.networking.TileCableBusTESR; import appeng.util.Platform; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; public class BlockCableBus extends AEBaseBlock { @@ -75,6 +81,117 @@ public class BlockCableBus extends AEBaseBlock return 0; } + @SideOnly(Side.CLIENT) + public boolean addHitEffects(World world, MovingObjectPosition target, EffectRenderer effectRenderer) + { + Object pobj = cb( world, target.blockX, target.blockY, target.blockZ ); + if ( pobj instanceof IPartHost ) + { + IPartHost host = (IPartHost) pobj; + + for (ForgeDirection side : ForgeDirection.values()) + { + IPart p = host.getPart( side ); + IIcon ico = getIcon( p ); + + if ( ico == null ) + continue; + + byte b0 = (byte) (Platform.getRandomInt() % 2 == 0 ? 1 : 0); + + for (int i1 = 0; i1 < b0; ++i1) + { + for (int j1 = 0; j1 < b0; ++j1) + { + for (int k1 = 0; k1 < b0; ++k1) + { + double d0 = (double) target.blockX + ((double) i1 + 0.5D) / (double) b0; + double d1 = (double) target.blockY + ((double) j1 + 0.5D) / (double) b0; + double d2 = (double) target.blockZ + ((double) k1 + 0.5D) / (double) b0; + + double dd0 = target.hitVec.xCoord; + double dd1 = target.hitVec.yCoord; + double dd2 = target.hitVec.zCoord; + EntityDiggingFX fx = (new EntityDiggingFX( world, dd0, dd1, dd2, d0 - (double) target.blockX - 0.5D, d1 - (double) target.blockY + - 0.5D, d2 - (double) target.blockZ - 0.5D, this, 0 )).applyColourMultiplier( target.blockX, target.blockY, target.blockZ ); + + fx.setParticleIcon( ico ); + + effectRenderer.addEffect( fx ); + } + } + } + } + } + + return true; + } + + @SideOnly(Side.CLIENT) + public boolean addDestroyEffects(World world, int x, int y, int z, int meta, EffectRenderer effectRenderer) + { + Object pobj = cb( world, x, y, z ); + if ( pobj instanceof IPartHost ) + { + IPartHost host = (IPartHost) pobj; + + for (ForgeDirection side : ForgeDirection.values()) + { + IPart p = host.getPart( side ); + IIcon ico = getIcon( p ); + + if ( ico == null ) + continue; + + byte b0 = 3; + + for (int i1 = 0; i1 < b0; ++i1) + { + for (int j1 = 0; j1 < b0; ++j1) + { + for (int k1 = 0; k1 < b0; ++k1) + { + double d0 = (double) x + ((double) i1 + 0.5D) / (double) b0; + double d1 = (double) y + ((double) j1 + 0.5D) / (double) b0; + double d2 = (double) z + ((double) k1 + 0.5D) / (double) b0; + EntityDiggingFX fx = (new EntityDiggingFX( world, d0, d1, d2, d0 - (double) x - 0.5D, d1 - (double) y - 0.5D, d2 - (double) z + - 0.5D, this, meta )).applyColourMultiplier( x, y, z ); + + fx.setParticleIcon( ico ); + + effectRenderer.addEffect( fx ); + } + } + } + } + } + + return true; + } + + private IIcon getIcon(IPart p) + { + if ( p == null ) + return null; + + try + { + IIcon ico = p.getBreakingTexture(); + if ( ico != null ) + return ico; + } + catch (Throwable t) + { + // nothing. + } + + ItemStack is = p.getItemStack( PartItemStack.Network ); + if ( is == null || is.getItem() == null ) + return null; + + return is.getItem().getIcon( is, 0 ); + } + @Override public boolean canRenderInPass(int pass) { diff --git a/client/render/CableRenderHelper.java b/client/render/CableRenderHelper.java index 02caf2263..6211f4a7d 100644 --- a/client/render/CableRenderHelper.java +++ b/client/render/CableRenderHelper.java @@ -29,6 +29,9 @@ public class CableRenderHelper TileEntity te = cableBusContainer.getTile(); RenderBlocksWorkaround renderer = BusRenderer.instance.renderer; + if ( renderer.overrideBlockTexture != null ) + BusRenderHelper.instance.setPass( 0 ); + if ( renderer.blockAccess == null ) renderer.blockAccess = Minecraft.getMinecraft().theWorld; diff --git a/items/misc/ItemCrystalSeed.java b/items/misc/ItemCrystalSeed.java index 54dd22f9c..bd0f67cdf 100644 --- a/items/misc/ItemCrystalSeed.java +++ b/items/misc/ItemCrystalSeed.java @@ -13,6 +13,7 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.IIcon; import net.minecraft.world.World; import appeng.api.AEApi; @@ -22,6 +23,7 @@ import appeng.core.features.AEFeature; import appeng.entity.EntityGrowingCrystal; import appeng.entity.EntityIds; import appeng.items.AEBaseItem; +import appeng.util.Platform; import cpw.mods.fml.common.registry.EntityRegistry; public class ItemCrystalSeed extends AEBaseItem implements IGrowableCrystal @@ -39,6 +41,29 @@ public class ItemCrystalSeed extends AEBaseItem implements IGrowableCrystal IIcon fluix[] = new IIcon[3]; IIcon nether[] = new IIcon[3]; + private int getProgress(ItemStack is) + { + if ( is.hasTagCompound() ) + { + return is.getTagCompound().getInteger( "progress" ); + } + else + { + int progress; + NBTTagCompound comp = Platform.openNbtData( is ); + comp.setInteger( "progress", progress = is.getItemDamage() ); + is.setItemDamage( (is.getItemDamage() / SINGLE_OFFSET) * SINGLE_OFFSET ); + return progress; + } + } + + private void setProgress(ItemStack is, int newDamage) + { + NBTTagCompound comp = Platform.openNbtData( is ); + comp.setInteger( "progress", newDamage ); + is.setItemDamage( (is.getItemDamage() / SINGLE_OFFSET) * SINGLE_OFFSET ); + } + public ItemCrystalSeed() { super( ItemCrystalSeed.class ); setHasSubtypes( true ); @@ -52,7 +77,7 @@ public class ItemCrystalSeed extends AEBaseItem implements IGrowableCrystal @Override public String getUnlocalizedName(ItemStack is) { - int damage = is.getItemDamage(); + int damage = getProgress( is ); if ( damage < Certus + SINGLE_OFFSET ) return getUnlocalizedName() + ".Certus"; @@ -69,7 +94,7 @@ public class ItemCrystalSeed extends AEBaseItem implements IGrowableCrystal @Override public ItemStack triggerGrowth(ItemStack is) { - int newDamage = is.getItemDamage() + 1; + int newDamage = getProgress( is ) + 1; if ( newDamage == Certus + SINGLE_OFFSET ) return AEApi.instance().materials().materialPureifiedCertusQuartzCrystal.stack( is.stackSize ); @@ -80,49 +105,43 @@ public class ItemCrystalSeed extends AEBaseItem implements IGrowableCrystal if ( newDamage > END ) return null; - is.setItemDamage( newDamage ); + setProgress( is, newDamage ); return is; } @Override public boolean isDamageable() { - return true; + return false; } @Override public void addInformation(ItemStack stack, EntityPlayer p, List l, boolean b) { - int progress = stack.getItemDamage() % 200; - l.add( Math.floor( (float) progress / 2.0f ) + "%" ); + int progress = getProgress( stack ) % SINGLE_OFFSET; + l.add( Math.floor( (float) progress / (float) (SINGLE_OFFSET / 100) ) + "%" ); super.addInformation( stack, p, l, b ); } @Override public boolean isDamaged(ItemStack stack) { - // if ( stack.getItemDamage() % 200 == 0 ) - // return false; return false; } - @Override - public int getDisplayDamage(ItemStack stack) - { - return stack.getItemDamage() % 200; - } - @Override public int getMaxDamage(ItemStack stack) { - return 200; + return END; } @Override - public IIcon getIconFromDamage(int damage) + public IIcon getIconIndex(ItemStack stack) { IIcon list[] = null; + int damage = getProgress( stack ); + if ( damage < Certus + SINGLE_OFFSET ) list = certus; @@ -198,19 +217,25 @@ public class ItemCrystalSeed extends AEBaseItem implements IGrowableCrystal public void getSubItems(Item i, CreativeTabs t, List l) { // lvl 0 - l.add( new ItemStack( this, 1, Certus ) ); - l.add( new ItemStack( this, 1, Nether ) ); - l.add( new ItemStack( this, 1, Fluix ) ); + l.add( newStyle( new ItemStack( this, 1, Certus ) ) ); + l.add( newStyle( new ItemStack( this, 1, Nether ) ) ); + l.add( newStyle( new ItemStack( this, 1, Fluix ) ) ); // lvl 1 - l.add( new ItemStack( this, 1, LEVEL_OFFSET + Certus ) ); - l.add( new ItemStack( this, 1, LEVEL_OFFSET + Nether ) ); - l.add( new ItemStack( this, 1, LEVEL_OFFSET + Fluix ) ); + l.add( newStyle( new ItemStack( this, 1, LEVEL_OFFSET + Certus ) ) ); + l.add( newStyle( new ItemStack( this, 1, LEVEL_OFFSET + Nether ) ) ); + l.add( newStyle( new ItemStack( this, 1, LEVEL_OFFSET + Fluix ) ) ); // lvl 2 - l.add( new ItemStack( this, 1, LEVEL_OFFSET * 2 + Certus ) ); - l.add( new ItemStack( this, 1, LEVEL_OFFSET * 2 + Nether ) ); - l.add( new ItemStack( this, 1, LEVEL_OFFSET * 2 + Fluix ) ); + l.add( newStyle( new ItemStack( this, 1, LEVEL_OFFSET * 2 + Certus ) ) ); + l.add( newStyle( new ItemStack( this, 1, LEVEL_OFFSET * 2 + Nether ) ) ); + l.add( newStyle( new ItemStack( this, 1, LEVEL_OFFSET * 2 + Fluix ) ) ); + } + + private ItemStack newStyle(ItemStack itemStack) + { + getProgress( itemStack ); + return itemStack; } } diff --git a/me/Grid.java b/me/Grid.java index 8bc2b1f1c..dce6123a9 100644 --- a/me/Grid.java +++ b/me/Grid.java @@ -1,238 +1,236 @@ -package appeng.me; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Set; - -import appeng.api.AEApi; -import appeng.api.networking.IGrid; -import appeng.api.networking.IGridCache; -import appeng.api.networking.IGridHost; -import appeng.api.networking.IGridNode; -import appeng.api.networking.IMachineSet; -import appeng.api.networking.events.MENetworkEvent; -import appeng.api.networking.events.MENetworkPostCacheConstruction; -import appeng.api.util.IReadOnlyCollection; -import appeng.core.WorldSettings; -import appeng.hooks.TickHandler; -import appeng.util.ReadOnlyCollection; - -public class Grid implements IGrid -{ - - GridStorage myStorage; - - NetworkEventBus bus = new NetworkEventBus(); - HashMap, Set> Machines = new HashMap, Set>(); - HashMap, GridCacheWrapper> caches = new HashMap, GridCacheWrapper>(); - - GridNode pivot; - int isImportant; // how import is this network? - - public Grid(GridNode center) { - this.pivot = center; - - HashMap, IGridCache> myCaches = AEApi.instance().registries().gridCache().createCacheInstance( this ); - for (Class c : myCaches.keySet()) - { - bus.readClass( c, myCaches.get( c ).getClass() ); - caches.put( c, new GridCacheWrapper( myCaches.get( c ) ) ); - } - - TickHandler.instance.addNetwork( this ); - center.setGrid( this ); - - postEvent( new MENetworkPostCacheConstruction() ); - } - - public Set> getMachineClasses() - { - return Machines.keySet(); - } - - @Override - public IGridNode getPivot() - { - return pivot; - } - - public int size() - { - int out = 0; - for (Collection x : Machines.values()) - out += x.size(); - return out; - } - - public void remove(GridNode gridNode) - { - for (IGridCache c : caches.values()) - c.removeNode( gridNode, gridNode.getMachine() ); - - Collection nodes = Machines.get( gridNode.getMachineClass() ); - if ( nodes != null ) - nodes.remove( gridNode ); - - gridNode.setGridStorage( null ); - - if ( pivot == gridNode ) - { - Iterator n = getNodes().iterator(); - if ( n.hasNext() ) - pivot = (GridNode) n.next(); - else - { - pivot = null; - TickHandler.instance.removeNetwork( this ); - myStorage.remove(); - } - } - } - - public void add(GridNode gridNode) - { - Class mClass = gridNode.getMachineClass(); - Set nodes = Machines.get( mClass ); - if ( nodes == null ) - { - Machines.put( mClass, nodes = new MachineSet( mClass ) ); - bus.readClass( mClass, mClass ); - } - - // handle loading grid storages. - if ( gridNode.getGridStorage() != null ) - { - GridStorage gs = gridNode.getGridStorage(); - - if ( gs.getGrid() == null ) - { - myStorage = gs; - myStorage.setGrid( this ); - - for (IGridCache gc : caches.values()) - gc.onJoin( myStorage ); - } - else if ( gs.getGrid() != this ) - { - if ( myStorage == null ) - { - myStorage = WorldSettings.getInstance().getNewGridStorage(); - myStorage.setGrid( this ); - } - - GridStorage tmp = new GridStorage(); - if ( !gs.hasDivided( myStorage ) ) - { - gs.addDivided( myStorage ); - - for (IGridCache gc : ((Grid) gs.getGrid()).caches.values()) - gc.onSplit( tmp ); - - for (IGridCache gc : caches.values()) - gc.onJoin( tmp ); - } - } - } - else if ( myStorage == null ) - { - myStorage = WorldSettings.getInstance().getNewGridStorage(); - myStorage.setGrid( this ); - } - - // update grid node... - gridNode.setGridStorage( myStorage ); - - // track node. - nodes.add( gridNode ); - - for (IGridCache c : caches.values()) - c.addNode( gridNode, gridNode.getMachine() ); - - gridNode.gridProxy.gridChanged(); - // postEventTo( gridNode, networkChanged ); - } - - @Override - public IReadOnlyCollection getNodes() - { - return new NodeIteratable( Machines ); - } - - @Override - public IReadOnlyCollection> getMachinesClasses() - { - return new ReadOnlyCollection>( Machines.keySet() ); - } - - @Override - public IMachineSet getMachines(Class c) - { - MachineSet s = (MachineSet) Machines.get( c ); - if ( s == null ) - return new MachineSet( c ); - return s; - } - - @Override - public C getCache(Class iface) - { - return (C) caches.get( iface ).myCache; - } - - @Override - public MENetworkEvent postEventTo(IGridNode node, MENetworkEvent ev) - { - return bus.postEventTo( this, (GridNode) node, ev ); - } - - @Override - public MENetworkEvent postEvent(MENetworkEvent ev) - { - return bus.postEvent( this, ev ); - } - - public void requestSave() - { - myStorage.markDirty(); - WorldSettings.getInstance().save(); - } - - public void update() - { - // are ther any nodes left? - if ( pivot != null ) - { - for (IGridCache gc : caches.values()) - { - gc.onUpdateTick(); - } - } - } - - public Iterable getCacheWrappers() - { - return caches.values(); - } - - @Override - public boolean isEmpty() - { - return pivot == null; - } - - public void saveState() - { - for (IGridCache c : caches.values()) - { - c.populateGridStorage( myStorage ); - } - } - - public void setImportantFlag(int i, boolean publicHasPower) - { - int flag = 1 << i; - isImportant = (isImportant & ~flag) | (publicHasPower ? flag : 0); - } - -} +package appeng.me; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Set; + +import appeng.api.AEApi; +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridCache; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.IMachineSet; +import appeng.api.networking.events.MENetworkEvent; +import appeng.api.networking.events.MENetworkPostCacheConstruction; +import appeng.api.util.IReadOnlyCollection; +import appeng.core.WorldSettings; +import appeng.hooks.TickHandler; +import appeng.util.ReadOnlyCollection; + +public class Grid implements IGrid +{ + + GridStorage myStorage; + + NetworkEventBus bus = new NetworkEventBus(); + HashMap, Set> Machines = new HashMap, Set>(); + HashMap, GridCacheWrapper> caches = new HashMap, GridCacheWrapper>(); + + GridNode pivot; + int isImportant; // how import is this network? + + public Grid(GridNode center) { + this.pivot = center; + + HashMap, IGridCache> myCaches = AEApi.instance().registries().gridCache().createCacheInstance( this ); + for (Class c : myCaches.keySet()) + { + bus.readClass( c, myCaches.get( c ).getClass() ); + caches.put( c, new GridCacheWrapper( myCaches.get( c ) ) ); + } + + TickHandler.instance.addNetwork( this ); + center.setGrid( this ); + + postEvent( new MENetworkPostCacheConstruction() ); + } + + public Set> getMachineClasses() + { + return Machines.keySet(); + } + + @Override + public IGridNode getPivot() + { + return pivot; + } + + public int size() + { + int out = 0; + for (Collection x : Machines.values()) + out += x.size(); + return out; + } + + public void remove(GridNode gridNode) + { + for (IGridCache c : caches.values()) + c.removeNode( gridNode, gridNode.getMachine() ); + + Collection nodes = Machines.get( gridNode.getMachineClass() ); + if ( nodes != null ) + nodes.remove( gridNode ); + + gridNode.setGridStorage( null ); + + if ( pivot == gridNode ) + { + Iterator n = getNodes().iterator(); + if ( n.hasNext() ) + pivot = (GridNode) n.next(); + else + { + pivot = null; + TickHandler.instance.removeNetwork( this ); + myStorage.remove(); + } + } + } + + public void add(GridNode gridNode) + { + Class mClass = gridNode.getMachineClass(); + Set nodes = Machines.get( mClass ); + if ( nodes == null ) + { + Machines.put( mClass, nodes = new MachineSet( mClass ) ); + bus.readClass( mClass, mClass ); + } + + // handle loading grid storages. + if ( gridNode.getGridStorage() != null ) + { + GridStorage gs = gridNode.getGridStorage(); + + if ( gs.getGrid() == null ) + { + myStorage = gs; + myStorage.setGrid( this ); + + for (IGridCache gc : caches.values()) + gc.onJoin( myStorage ); + } + else if ( gs.getGrid() != this ) + { + if ( myStorage == null ) + { + myStorage = WorldSettings.getInstance().getNewGridStorage(); + myStorage.setGrid( this ); + } + + GridStorage tmp = new GridStorage(); + if ( !gs.hasDivided( myStorage ) ) + { + gs.addDivided( myStorage ); + + for (IGridCache gc : ((Grid) gs.getGrid()).caches.values()) + gc.onSplit( tmp ); + + for (IGridCache gc : caches.values()) + gc.onJoin( tmp ); + } + } + } + else if ( myStorage == null ) + { + myStorage = WorldSettings.getInstance().getNewGridStorage(); + myStorage.setGrid( this ); + } + + // update grid node... + gridNode.setGridStorage( myStorage ); + + // track node. + nodes.add( gridNode ); + + for (IGridCache c : caches.values()) + c.addNode( gridNode, gridNode.getMachine() ); + + gridNode.gridProxy.gridChanged(); + // postEventTo( gridNode, networkChanged ); + } + + @Override + public IReadOnlyCollection getNodes() + { + return new NodeIteratable( Machines ); + } + + @Override + public IReadOnlyCollection> getMachinesClasses() + { + return new ReadOnlyCollection>( Machines.keySet() ); + } + + @Override + public IMachineSet getMachines(Class c) + { + MachineSet s = (MachineSet) Machines.get( c ); + if ( s == null ) + return new MachineSet( c ); + return s; + } + + @Override + public C getCache(Class iface) + { + return (C) caches.get( iface ).myCache; + } + + @Override + public MENetworkEvent postEventTo(IGridNode node, MENetworkEvent ev) + { + return bus.postEventTo( this, (GridNode) node, ev ); + } + + @Override + public MENetworkEvent postEvent(MENetworkEvent ev) + { + return bus.postEvent( this, ev ); + } + + public void requestSave() + { + myStorage.markDirty(); + WorldSettings.getInstance().save(); + } + + public void update() + { + for (IGridCache gc : caches.values()) + { + // are there any nodes left? + if ( pivot != null ) + gc.onUpdateTick(); + } + } + + public Iterable getCacheWrappers() + { + return caches.values(); + } + + @Override + public boolean isEmpty() + { + return pivot == null; + } + + public void saveState() + { + for (IGridCache c : caches.values()) + { + c.populateGridStorage( myStorage ); + } + } + + public void setImportantFlag(int i, boolean publicHasPower) + { + int flag = 1 << i; + isImportant = (isImportant & ~flag) | (publicHasPower ? flag : 0); + } + +} diff --git a/me/cache/GridStorageCache.java b/me/cache/GridStorageCache.java index 5966e328a..d427ed810 100644 --- a/me/cache/GridStorageCache.java +++ b/me/cache/GridStorageCache.java @@ -27,6 +27,7 @@ import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IItemList; +import appeng.me.helpers.StorageInterestManager; import appeng.me.storage.ItemWatcher; import appeng.me.storage.NetworkInventoryHandler; @@ -36,7 +37,8 @@ import com.google.common.collect.SetMultimap; public class GridStorageCache implements IStorageGrid { - public SetMultimap interests = HashMultimap.create(); + final private SetMultimap interests = HashMultimap.create(); + final public StorageInterestManager interestManager = new StorageInterestManager( interests ); final HashSet activeCellProviders = new HashSet(); final HashSet inactiveCellProviders = new HashSet(); diff --git a/me/cache/NetworkMonitor.java b/me/cache/NetworkMonitor.java index 9fe06d5b4..dfccffc91 100644 --- a/me/cache/NetworkMonitor.java +++ b/me/cache/NetworkMonitor.java @@ -59,9 +59,9 @@ public class NetworkMonitor> extends MEMonitorHandler sendEvent = true; super.postChange( diff, src ); - if ( myGridCache.interests.containsKey( diff ) ) + if ( myGridCache.interestManager.containsKey( diff ) ) { - Set list = myGridCache.interests.get( diff ); + Set list = myGridCache.interestManager.get( diff ); if ( !list.isEmpty() ) { IItemList myStorageList = getStorageList(); @@ -72,9 +72,13 @@ public class NetworkMonitor> extends MEMonitorHandler fullStack = diff.copy(); fullStack.setStackSize( 0 ); } - + + myGridCache.interestManager.enableTransactions(); + for (ItemWatcher iw : list) iw.getHost().onStackChange( myStorageList, fullStack, diff, src, getChannel() ); + + myGridCache.interestManager.disableTransactions(); } } diff --git a/me/helpers/StorageInterestManager.java b/me/helpers/StorageInterestManager.java new file mode 100644 index 000000000..c4e9761f8 --- /dev/null +++ b/me/helpers/StorageInterestManager.java @@ -0,0 +1,84 @@ +package appeng.me.helpers; + +import java.util.LinkedList; +import java.util.Set; + +import appeng.api.storage.data.IAEStack; +import appeng.me.storage.ItemWatcher; + +import com.google.common.collect.SetMultimap; + +public class StorageInterestManager { + + class SavedTransactions { + public final boolean put; + public final IAEStack stack; + public final ItemWatcher iw; + + public SavedTransactions( boolean putOperation, IAEStack myStack, ItemWatcher watcher ) + { + put = putOperation; + stack = myStack; + iw = watcher; + } + }; + + private final SetMultimap container; + private LinkedList transactions = null; + + public StorageInterestManager(SetMultimap interests) { + container = interests; + } + + public void enableTransactions() + { + transactions = new LinkedList(); + } + + public void disableTransactions() + { + LinkedList myActions = transactions; + transactions = null; + + for ( SavedTransactions t : myActions ) + { + if ( t.put ) + put( t.stack, t.iw ); + else + remove( t.stack, t.iw ); + } + } + + public boolean containsKey( IAEStack stack ) + { + return container.containsKey( stack ); + } + + public Set get( IAEStack stack ) + { + return container.get( stack ); + } + + public boolean put( IAEStack stack, ItemWatcher iw ) + { + if ( transactions != null ) + { + transactions.add( new SavedTransactions( true, stack, iw ) ); + return true; + } + else + return container.put( stack, iw ); + } + + public boolean remove( IAEStack stack, ItemWatcher iw ) + { + if ( transactions != null ) + { + transactions.add( new SavedTransactions( true, stack, iw ) ); + return true; + } + else + return container.remove( stack, iw ); + } + +} diff --git a/me/storage/ItemWatcher.java b/me/storage/ItemWatcher.java index a97539ebe..08a990f68 100644 --- a/me/storage/ItemWatcher.java +++ b/me/storage/ItemWatcher.java @@ -42,7 +42,7 @@ public class ItemWatcher implements IStackWatcher @Override public void remove() { - gsc.interests.remove( myLast, watcher ); + gsc.interestManager.remove( myLast, watcher ); interestIterator.remove(); } @@ -68,7 +68,7 @@ public class ItemWatcher implements IStackWatcher if ( myInterests.contains( e ) ) return false; - return myInterests.add( e.copy() ) && gsc.interests.put( e, this ); + return myInterests.add( e.copy() ) && gsc.interestManager.put( e, this ); } @Override @@ -88,7 +88,7 @@ public class ItemWatcher implements IStackWatcher Iterator i = myInterests.iterator(); while (i.hasNext()) { - gsc.interests.remove( i.next(), this ); + gsc.interestManager.remove( i.next(), this ); i.remove(); } } @@ -120,7 +120,7 @@ public class ItemWatcher implements IStackWatcher @Override public boolean remove(Object o) { - return myInterests.remove( o ) && gsc.interests.remove( o, this ); + return myInterests.remove( o ) && gsc.interestManager.remove( (IAEStack)o, this ); } @Override diff --git a/parts/AEBasePart.java b/parts/AEBasePart.java index fb3db4067..0ba1f2a29 100644 --- a/parts/AEBasePart.java +++ b/parts/AEBasePart.java @@ -16,6 +16,7 @@ import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.IIcon; import net.minecraft.util.Vec3; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; @@ -500,4 +501,10 @@ public class AEBasePart implements IPart, IGridProxyable, IActionHost, IUpgradea return is.hasDisplayName(); } + @Override + @SideOnly(Side.CLIENT) + public IIcon getBreakingTexture() + { + return null; + } } \ No newline at end of file diff --git a/parts/CableBusContainer.java b/parts/CableBusContainer.java index e60d11081..2e4347710 100644 --- a/parts/CableBusContainer.java +++ b/parts/CableBusContainer.java @@ -434,7 +434,6 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer bch.addBox( 6.0, 6.0, 6.0, 10.0, 10.0, 10.0 ); else part.getBoxes( bch ); - } if ( includeFacades && s != null && s != ForgeDirection.UNKNOWN ) diff --git a/parts/PartBasicState.java b/parts/PartBasicState.java index c0fc15e27..6fedb290f 100644 --- a/parts/PartBasicState.java +++ b/parts/PartBasicState.java @@ -7,6 +7,7 @@ import java.io.IOException; import net.minecraft.client.renderer.RenderBlocks; import net.minecraft.client.renderer.Tessellator; import net.minecraft.item.ItemStack; +import net.minecraft.util.IIcon; import net.minecraftforge.common.util.ForgeDirection; import appeng.api.implementations.IPowerChannelState; import appeng.api.networking.GridFlags; @@ -129,4 +130,10 @@ public class PartBasicState extends AEBasePart implements IPowerChannelState return (clientFlags & CHANNEL_FLAG) == CHANNEL_FLAG; } + @Override + @SideOnly(Side.CLIENT) + public IIcon getBreakingTexture() + { + return CableBusTextures.PartTransitionPlaneBack.getIcon(); + } } diff --git a/parts/automation/PartExportBus.java b/parts/automation/PartExportBus.java index 488521cb9..82a15de18 100644 --- a/parts/automation/PartExportBus.java +++ b/parts/automation/PartExportBus.java @@ -27,6 +27,9 @@ import appeng.core.sync.GuiBridge; import appeng.me.GridAccessException; import appeng.util.InventoryAdaptor; import appeng.util.Platform; + +import com.google.common.collect.ImmutableList; + import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -166,7 +169,7 @@ public class PartExportBus extends PartSharedItemBus implements IGridTickable if ( getInstalledUpgrades( Upgrades.FUZZY ) > 0 ) { - for (IAEItemStack o : inv.getStorageList().findFuzzy( ais, fzMode )) + for (IAEItemStack o : ImmutableList.copyOf( inv.getStorageList().findFuzzy( ais, fzMode ) )) { pushItemIntoTarget( d, energy, fzMode, inv, o ); if ( itemToSend <= 0 ) diff --git a/parts/automation/PartLevelEmitter.java b/parts/automation/PartLevelEmitter.java index 4711d8e3d..bfba6970e 100644 --- a/parts/automation/PartLevelEmitter.java +++ b/parts/automation/PartLevelEmitter.java @@ -531,6 +531,12 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH // super.renderWorldBlock( world, x, y, z, block, modelId, renderer ); } + @Override + public IIcon getBreakingTexture() + { + return is.getIconIndex(); + } + @Override public void getBoxes(IPartCollsionHelper bch) { diff --git a/parts/misc/PartCableAnchor.java b/parts/misc/PartCableAnchor.java index 036262ff5..f60e13b64 100644 --- a/parts/misc/PartCableAnchor.java +++ b/parts/misc/PartCableAnchor.java @@ -230,4 +230,10 @@ public class PartCableAnchor implements IPart { return what == BusSupport.CABLE || what == BusSupport.DENSE_CABLE; } + + @Override + public IIcon getBreakingTexture() + { + return null; + } } diff --git a/parts/misc/PartInterface.java b/parts/misc/PartInterface.java index 14236ce9d..89f744afb 100644 --- a/parts/misc/PartInterface.java +++ b/parts/misc/PartInterface.java @@ -11,6 +11,7 @@ import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.IIcon; import net.minecraft.util.Vec3; import net.minecraftforge.common.util.ForgeDirection; import appeng.api.implementations.tiles.ISegmentedInventory; @@ -131,6 +132,12 @@ public class PartInterface extends PartBasicState implements IGridTickable, ISeg renderLights( x, y, z, rh, renderer ); } + @Override + public IIcon getBreakingTexture() + { + return is.getIconIndex(); + } + @Override public void getBoxes(IPartCollsionHelper bch) { diff --git a/parts/misc/PartToggleBus.java b/parts/misc/PartToggleBus.java index fc71b3430..d9ca8a11e 100644 --- a/parts/misc/PartToggleBus.java +++ b/parts/misc/PartToggleBus.java @@ -9,6 +9,7 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.IIcon; import net.minecraftforge.common.util.ForgeDirection; import org.lwjgl.opengl.GL11; @@ -186,6 +187,12 @@ public class PartToggleBus extends PartBasicState renderLights( x, y, z, rh, renderer ); } + @Override + public IIcon getBreakingTexture() + { + return is.getIconIndex(); + } + @Override public void getBoxes(IPartCollsionHelper bch) { diff --git a/parts/networking/PartCable.java b/parts/networking/PartCable.java index 1c63e96cd..7b71d7e0c 100644 --- a/parts/networking/PartCable.java +++ b/parts/networking/PartCable.java @@ -330,6 +330,46 @@ public class PartCable extends AEBasePart implements IPartCable connections.clear(); } + IPartHost ph = getHost(); + if ( ph != null ) + { + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) + { + IPart p = ph.getPart( dir ); + if ( p instanceof IGridHost ) + { + double dist = p.cableConnectionRenderTo(); + + if ( dist > 8 ) + continue; + + switch (dir) + { + case DOWN: + bch.addBox( 6.0, dist, 6.0, 10.0, 6.0, 10.0 ); + break; + case EAST: + bch.addBox( 10.0, 6.0, 6.0, 16.0 - dist, 10.0, 10.0 ); + break; + case NORTH: + bch.addBox( 6.0, 6.0, dist, 10.0, 10.0, 6.0 ); + break; + case SOUTH: + bch.addBox( 6.0, 6.0, 10.0, 10.0, 10.0, 16.0 - dist ); + break; + case UP: + bch.addBox( 6.0, 10.0, 6.0, 10.0, 16.0 - dist, 10.0 ); + break; + case WEST: + bch.addBox( dist, 6.0, 6.0, 6.0, 10.0, 10.0 ); + break; + default: + continue; + } + } + } + } + for (ForgeDirection of : connections) { switch (of) @@ -370,6 +410,13 @@ public class PartCable extends AEBasePart implements IPartCable rh.setTexture( null ); } + @Override + @SideOnly(Side.CLIENT) + public IIcon getBreakingTexture() + { + return getTexture( getCableColor() ); + } + @SideOnly(Side.CLIENT) public void rendereGlassConection(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer, ForgeDirection of) { diff --git a/parts/p2p/PartP2PTunnel.java b/parts/p2p/PartP2PTunnel.java index fad470381..bf61d8cc8 100644 --- a/parts/p2p/PartP2PTunnel.java +++ b/parts/p2p/PartP2PTunnel.java @@ -331,6 +331,13 @@ public class PartP2PTunnel extends PartBasicState renderLights( x, y, z, rh, renderer ); } + @Override + @SideOnly(Side.CLIENT) + public IIcon getBreakingTexture() + { + return CableBusTextures.BlockP2PTunnel2.getIcon(); + } + protected void QueueTunnelDrain(PowerUnits unit, double f) { double ae_to_tax = unit.convertTo( PowerUnits.AE, f * AEConfig.TunnelPowerLoss ); diff --git a/util/inv/IMEAdaptor.java b/util/inv/IMEAdaptor.java index 26e4d1c7c..11af2efe7 100644 --- a/util/inv/IMEAdaptor.java +++ b/util/inv/IMEAdaptor.java @@ -13,6 +13,8 @@ import appeng.api.storage.data.IItemList; import appeng.util.InventoryAdaptor; import appeng.util.item.AEItemStack; +import com.google.common.collect.ImmutableList; + public class IMEAdaptor extends InventoryAdaptor { @@ -44,7 +46,7 @@ public class IMEAdaptor extends InventoryAdaptor IAEItemStack out = null; - for (IAEItemStack req : getList().findFuzzy( reqFilter, fuzzyMode )) + for (IAEItemStack req : ImmutableList.copyOf( getList().findFuzzy( reqFilter, fuzzyMode ) )) { if ( req != null ) {