From c6f6319591eb34eef0d3d7d4b2b98fec29675a8a Mon Sep 17 00:00:00 2001 From: AlgorithmX2 Date: Wed, 27 Aug 2014 00:57:37 -0500 Subject: [PATCH] Revamped Multipart Memory Usage. --- client/render/CableRenderHelper.java | 11 +-- facade/FacadeContainer.java | 69 +++++++++-------- fmp/FMPPlacementHelper.java | 23 +++++- parts/CableBusContainer.java | 98 ++++++++++++------------ parts/CableBusStorage.java | 108 +++++++++++++++++++++++++++ 5 files changed, 225 insertions(+), 84 deletions(-) create mode 100644 parts/CableBusStorage.java diff --git a/client/render/CableRenderHelper.java b/client/render/CableRenderHelper.java index 05278e36..4fbc2b90 100644 --- a/client/render/CableRenderHelper.java +++ b/client/render/CableRenderHelper.java @@ -8,9 +8,9 @@ import net.minecraft.client.Minecraft; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import net.minecraftforge.common.util.ForgeDirection; +import appeng.api.parts.IFacadeContainer; import appeng.api.parts.IFacadePart; import appeng.api.parts.IPart; -import appeng.facade.FacadeContainer; import appeng.parts.BusCollisionHelper; import appeng.parts.CableBusContainer; @@ -71,7 +71,7 @@ public class CableRenderHelper BusRenderHelper.instance.setOrientation( ax, ay, az ); } - public void renderStatic(CableBusContainer cableBusContainer, FacadeContainer fc) + public void renderStatic(CableBusContainer cableBusContainer, IFacadeContainer iFacadeContainer) { TileEntity te = cableBusContainer.getTile(); RenderBlocksWorkaround renderer = BusRenderer.instance.renderer; @@ -101,7 +101,7 @@ public class CableRenderHelper } } - if ( !fc.isEmpty() ) + if ( !iFacadeContainer.isEmpty() ) { /** * snag list of boxes... @@ -139,7 +139,7 @@ public class CableRenderHelper for (ForgeDirection s : ForgeDirection.VALID_DIRECTIONS) { - IFacadePart fPart = fc.getFacade( s ); + IFacadePart fPart = iFacadeContainer.getFacade( s ); if ( fPart != null ) { AxisAlignedBB b = null; @@ -167,7 +167,8 @@ public class CableRenderHelper renderer.uvRotateBottom = renderer.uvRotateEast = renderer.uvRotateNorth = renderer.uvRotateSouth = renderer.uvRotateTop = renderer.uvRotateWest = 0; setSide( s ); - fPart.renderStatic( te.xCoord, te.yCoord, te.zCoord, BusRenderHelper.instance, renderer, fc, b, cableBusContainer.getPart( s ) == null ); + fPart.renderStatic( te.xCoord, te.yCoord, te.zCoord, BusRenderHelper.instance, renderer, iFacadeContainer, b, + cableBusContainer.getPart( s ) == null ); } } diff --git a/facade/FacadeContainer.java b/facade/FacadeContainer.java index ffdea422..3cc46c29 100644 --- a/facade/FacadeContainer.java +++ b/facade/FacadeContainer.java @@ -17,23 +17,29 @@ import appeng.core.AppEng; import appeng.integration.IntegrationType; import appeng.integration.abstraction.IBC; import appeng.items.parts.ItemFacade; +import appeng.parts.CableBusStorage; public class FacadeContainer implements IFacadeContainer { - final private IFacadePart facades[] = new FacadePart[6]; + final int facades = 6; + final CableBusStorage storage; + + public FacadeContainer(CableBusStorage cbs) { + storage = cbs; + } public void writeToStream(ByteBuf out) throws IOException { int facadeSides = 0; - for (int x = 0; x < facades.length; x++) + for (int x = 0; x < facades; x++) { if ( getFacade( ForgeDirection.getOrientation( x ) ) != null ) facadeSides = facadeSides | (1 << x); } out.writeByte( (byte) facadeSides ); - for (int x = 0; x < facades.length; x++) + for (int x = 0; x < facades; x++) { IFacadePart part = getFacade( ForgeDirection.getOrientation( x ) ); if ( part != null ) @@ -53,7 +59,7 @@ public class FacadeContainer implements IFacadeContainer boolean changed = false; int ids[] = new int[2]; - for (int x = 0; x < facades.length; x++) + for (int x = 0; x < facades; x++) { ForgeDirection side = ForgeDirection.getOrientation( x ); int ix = (1 << x); @@ -67,8 +73,8 @@ public class FacadeContainer implements IFacadeContainer if ( isBC && AppEng.instance.isIntegrationEnabled( IntegrationType.BC ) ) { IBC bc = (IBC) AppEng.instance.getIntegration( IntegrationType.BC ); - changed = changed || facades[x] == null; - facades[x] = bc.createFacadePart( (Block) Block.blockRegistry.getObjectById( ids[0] ), ids[1], side ); + changed = changed || storage.getFacade( x ) == null; + storage.setFacade( x, bc.createFacadePart( (Block) Block.blockRegistry.getObjectById( ids[0] ), ids[1], side ) ); } else if ( !isBC ) { @@ -76,15 +82,15 @@ public class FacadeContainer implements IFacadeContainer ItemStack facade = ifa.createFromInts( ids ); if ( facade != null ) { - changed = changed || facades[x] == null; - facades[x] = ifa.createPartFromItemStack( facade, side ); + changed = changed || storage.getFacade( x ) == null; + storage.setFacade( x, ifa.createPartFromItemStack( facade, side ) ); } } } else { - changed = changed || facades[x] != null; - facades[x] = null; + changed = changed || storage.getFacade( x ) != null; + storage.setFacade( x, null ); } } @@ -93,9 +99,9 @@ public class FacadeContainer implements IFacadeContainer public void readFromNBT(NBTTagCompound c) { - for (int x = 0; x < facades.length; x++) + for (int x = 0; x < facades; x++) { - facades[x] = null; + storage.setFacade( x, null ); NBTTagCompound t = c.getCompoundTag( "facade:" + x ); if ( t != null ) @@ -105,14 +111,14 @@ public class FacadeContainer implements IFacadeContainer { Item i = is.getItem(); if ( i instanceof IFacadeItem ) - facades[x] = ((IFacadeItem) i).createPartFromItemStack( is, ForgeDirection.getOrientation( x ) ); + storage.setFacade( x, ((IFacadeItem) i).createPartFromItemStack( is, ForgeDirection.getOrientation( x ) ) ); else { if ( AppEng.instance.isIntegrationEnabled( IntegrationType.BC ) ) { IBC bc = (IBC) AppEng.instance.getIntegration( IntegrationType.BC ); if ( bc.isFacade( is ) ) - facades[x] = bc.createFacadePart( is, ForgeDirection.getOrientation( x ) ); + storage.setFacade( x, bc.createFacadePart( is, ForgeDirection.getOrientation( x ) ) ); } } } @@ -122,12 +128,12 @@ public class FacadeContainer implements IFacadeContainer public void writeToNBT(NBTTagCompound c) { - for (int x = 0; x < facades.length; x++) + for (int x = 0; x < facades; x++) { - if ( facades[x] != null ) + if ( storage.getFacade( x ) != null ) { NBTTagCompound data = new NBTTagCompound(); - facades[x].getItemStack().writeToNBT( data ); + storage.getFacade( x ).getItemStack().writeToNBT( data ); c.setTag( "facade:" + x, data ); } } @@ -138,7 +144,7 @@ public class FacadeContainer implements IFacadeContainer { if ( getFacade( a.getSide() ) == null ) { - facades[a.getSide().ordinal()] = a; + storage.setFacade( a.getSide().ordinal(), a ); return true; } return false; @@ -149,9 +155,9 @@ public class FacadeContainer implements IFacadeContainer { if ( side != null && side != ForgeDirection.UNKNOWN ) { - if ( facades[side.ordinal()] != null ) + if ( storage.getFacade( side.ordinal() ) != null ) { - facades[side.ordinal()] = null; + storage.setFacade( side.ordinal(), null ); if ( host != null ) host.markForUpdate(); } @@ -161,13 +167,13 @@ public class FacadeContainer implements IFacadeContainer @Override public IFacadePart getFacade(ForgeDirection s) { - return facades[s.ordinal()]; + return storage.getFacade( s.ordinal() ); } public boolean isEmpty() { - for (int x = 0; x < facades.length; x++) - if ( facades[x] != null ) + for (int x = 0; x < facades; x++) + if ( storage.getFacade( x ) != null ) return false; return true; } @@ -176,15 +182,16 @@ public class FacadeContainer implements IFacadeContainer { IFacadePart newfacades[] = new FacadePart[6]; - newfacades[ForgeDirection.UP.ordinal()] = facades[ForgeDirection.UP.ordinal()]; - newfacades[ForgeDirection.DOWN.ordinal()] = facades[ForgeDirection.DOWN.ordinal()]; + newfacades[ForgeDirection.UP.ordinal()] = storage.getFacade( ForgeDirection.UP.ordinal() ); + newfacades[ForgeDirection.DOWN.ordinal()] = storage.getFacade( ForgeDirection.DOWN.ordinal() ); - newfacades[ForgeDirection.EAST.ordinal()] = facades[ForgeDirection.NORTH.ordinal()]; - newfacades[ForgeDirection.SOUTH.ordinal()] = facades[ForgeDirection.EAST.ordinal()]; - newfacades[ForgeDirection.WEST.ordinal()] = facades[ForgeDirection.SOUTH.ordinal()]; - newfacades[ForgeDirection.NORTH.ordinal()] = facades[ForgeDirection.WEST.ordinal()]; + newfacades[ForgeDirection.EAST.ordinal()] = storage.getFacade( ForgeDirection.NORTH.ordinal() ); + newfacades[ForgeDirection.SOUTH.ordinal()] = storage.getFacade( ForgeDirection.EAST.ordinal() ); - for (int x = 0; x < facades.length; x++) - facades[x] = newfacades[x]; + newfacades[ForgeDirection.WEST.ordinal()] = storage.getFacade( ForgeDirection.SOUTH.ordinal() ); + newfacades[ForgeDirection.NORTH.ordinal()] = storage.getFacade( ForgeDirection.WEST.ordinal() ); + + for (int x = 0; x < facades; x++) + storage.setFacade( x, newfacades[x] ); } } diff --git a/fmp/FMPPlacementHelper.java b/fmp/FMPPlacementHelper.java index 2c0fd213..6e3d26b3 100644 --- a/fmp/FMPPlacementHelper.java +++ b/fmp/FMPPlacementHelper.java @@ -9,6 +9,7 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Vec3; import net.minecraftforge.common.util.ForgeDirection; import appeng.api.parts.IFacadeContainer; +import appeng.api.parts.IFacadePart; import appeng.api.parts.IPart; import appeng.api.parts.IPartHost; import appeng.api.parts.LayerFlags; @@ -16,6 +17,7 @@ import appeng.api.parts.SelectedPart; import appeng.api.util.AEColor; import appeng.api.util.DimensionalCoord; import appeng.facade.FacadeContainer; +import appeng.parts.CableBusStorage; import appeng.util.Platform; import codechicken.lib.vec.BlockCoord; import codechicken.multipart.TMultiPart; @@ -24,6 +26,25 @@ import codechicken.multipart.TileMultipart; public class FMPPlacementHelper implements IPartHost { + static class NullStorage extends CableBusStorage + { + + @Override + public IFacadePart getFacade(int x) + { + return null; + } + + @Override + public void setFacade(int x, IFacadePart facade) + { + + } + + }; + + final private static CableBusStorage nullStorage = new NullStorage(); + private boolean hasPart = false; private TileMultipart myMP; private CableBusPart myPart; @@ -79,7 +100,7 @@ public class FMPPlacementHelper implements IPartHost public IFacadeContainer getFacadeContainer() { if ( myPart == null ) - return new FacadeContainer(); + return new FacadeContainer( nullStorage ); return myPart.getFacadeContainer(); } diff --git a/parts/CableBusContainer.java b/parts/CableBusContainer.java index 4741c3dd..06a033da 100644 --- a/parts/CableBusContainer.java +++ b/parts/CableBusContainer.java @@ -50,12 +50,9 @@ import appeng.util.Platform; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -public class CableBusContainer implements AEMultiTile, ICableBusContainer +public class CableBusContainer extends CableBusStorage implements AEMultiTile, ICableBusContainer { - private IPartCable center; - private IPart sides[] = new IPart[6]; - private FacadeContainer fc = new FacadeContainer(); private EnumSet myLayerFlags = EnumSet.noneOf( LayerFlags.class ); public YesNo hasRedstone = YesNo.UNDECIDED; @@ -84,25 +81,26 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer public IPart getPart(ForgeDirection side) { if ( side == ForgeDirection.UNKNOWN ) - return center; - return sides[side.ordinal()]; + return getCenter(); + return getSide( side ); } public void rotateLeft() { IPart newSides[] = new IPart[6]; - newSides[ForgeDirection.UP.ordinal()] = sides[ForgeDirection.UP.ordinal()]; - newSides[ForgeDirection.DOWN.ordinal()] = sides[ForgeDirection.DOWN.ordinal()]; + newSides[ForgeDirection.UP.ordinal()] = getSide( ForgeDirection.UP ); + newSides[ForgeDirection.DOWN.ordinal()] = getSide( ForgeDirection.DOWN ); - newSides[ForgeDirection.EAST.ordinal()] = sides[ForgeDirection.NORTH.ordinal()]; - newSides[ForgeDirection.SOUTH.ordinal()] = sides[ForgeDirection.EAST.ordinal()]; - newSides[ForgeDirection.WEST.ordinal()] = sides[ForgeDirection.SOUTH.ordinal()]; - newSides[ForgeDirection.NORTH.ordinal()] = sides[ForgeDirection.WEST.ordinal()]; + newSides[ForgeDirection.EAST.ordinal()] = getSide( ForgeDirection.NORTH ); + newSides[ForgeDirection.SOUTH.ordinal()] = getSide( ForgeDirection.EAST ); + newSides[ForgeDirection.WEST.ordinal()] = getSide( ForgeDirection.SOUTH ); + newSides[ForgeDirection.NORTH.ordinal()] = getSide( ForgeDirection.WEST ); - sides = newSides; + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) + setSide( dir, newSides[dir.ordinal()] ); - fc.rotateLeft(); + getFacadeContainer().rotateLeft(); } public void updateDynamicRender() @@ -121,15 +119,15 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer { if ( side == ForgeDirection.UNKNOWN ) { - if ( center != null ) - center.removeFromWorld(); - center = null; + if ( getCenter() != null ) + getCenter().removeFromWorld(); + setCenter( null ); } else { - if ( sides[side.ordinal()] != null ) - sides[side.ordinal()].removeFromWorld(); - sides[side.ordinal()] = null; + if ( getSide( side ) != null ) + getSide( side ).removeFromWorld(); + setSide( side, null ); } if ( !supressUpdate ) @@ -146,7 +144,7 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer */ public void updateConnections() { - if ( center != null ) + if ( getCenter() != null ) { EnumSet sides = EnumSet.allOf( ForgeDirection.class ); @@ -156,8 +154,8 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer sides.remove( s ); } - center.setValidSides( sides ); - IGridNode n = center.getGridNode(); + getCenter().setValidSides( sides ); + IGridNode n = getCenter().getGridNode(); if ( n != null ) n.updateState(); } @@ -230,7 +228,7 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer if ( getPart( ForgeDirection.UNKNOWN ) != null ) return null; - center = (IPartCable) bp; + setCenter( (IPartCable) bp ); bp.setPartHostInfo( ForgeDirection.UNKNOWN, this, tcb.getTile() ); if ( player != null ) @@ -239,7 +237,7 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer if ( inWorld ) bp.addToWorld(); - IGridNode cn = center.getGridNode(); + IGridNode cn = getCenter().getGridNode(); if ( cn != null ) { for (ForgeDirection ins : ForgeDirection.VALID_DIRECTIONS) @@ -259,7 +257,7 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer // ekk! bp.removeFromWorld(); - center = null; + setCenter( null ); return null; } } @@ -278,7 +276,7 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer if ( cable != null && !bp.canBePlacedOn( ((IPartCable) cable).supportsBuses() ) ) return null; - sides[side.ordinal()] = bp; + setSide( side, bp ); bp.setPartHostInfo( side, this, this.getTile() ); if ( player != null ) @@ -287,9 +285,9 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer if ( inWorld ) bp.addToWorld(); - if ( center != null ) + if ( getCenter() != null ) { - IGridNode cn = center.getGridNode(); + IGridNode cn = getCenter().getGridNode(); IGridNode sn = bp.getGridNode(); if ( cn != null && sn != null ) @@ -303,7 +301,7 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer // ekk! bp.removeFromWorld(); - sides[side.ordinal()] = null; + setSide( side, null ); return null; } } @@ -424,8 +422,8 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer return n; } - if ( center != null ) - return center.getGridNode(); + if ( getCenter() != null ) + return getCenter().getGridNode(); return null; } @@ -434,6 +432,7 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer { List boxes = new LinkedList(); + IFacadeContainer fc = getFacadeContainer(); for (ForgeDirection s : ForgeDirection.values()) { IPartCollsionHelper bch = new BusCollisionHelper( boxes, s, e, visual ); @@ -473,6 +472,7 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer public boolean isEmpty() { + IFacadeContainer fc = getFacadeContainer(); for (ForgeDirection s : ForgeDirection.values()) { IPart part = getPart( s ); @@ -514,7 +514,7 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer return false; // facades are solid.. - IFacadePart fp = fc.getFacade( side ); + IFacadePart fp = getFacadeContainer().getFacade( side ); if ( fp != null ) return true; @@ -538,7 +538,7 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer @SideOnly(Side.CLIENT) public void renderStatic(double x, double y, double z) { - CableRenderHelper.getInstance().renderStatic( this, fc ); + CableRenderHelper.getInstance().renderStatic( this, getFacadeContainer() ); } @SideOnly(Side.CLIENT) @@ -577,7 +577,7 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer } } - fc.writeToStream( data ); + getFacadeContainer().writeToStream( data ); } public boolean readFromStream(ByteBuf data) throws IOException @@ -621,21 +621,22 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer removePart( side, false ); } - if ( fc.readFromStream( data ) ) + if ( getFacadeContainer().readFromStream( data ) ) return true; + return updateBlock; } ForgeDirection getSide(IPart part) { - if ( center == part ) + if ( getCenter() == part ) return ForgeDirection.UNKNOWN; else { - for (int x = 0; x < 6; x++) - if ( sides[x] == part ) + for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) + if ( getSide( side ) == part ) { - return ForgeDirection.getOrientation( x ); + return side; } } throw new RuntimeException( "Uhh Bad Part on Side." ); @@ -645,6 +646,7 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer { data.setInteger( "hasRedstone", hasRedstone.ordinal() ); + IFacadeContainer fc = getFacadeContainer(); for (ForgeDirection s : ForgeDirection.values()) { fc.writeToNBT( data ); @@ -705,7 +707,7 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer removePart( side, false ); } - fc.readFromNBT( data ); + getFacadeContainer().readFromNBT( data ); } public List getDrops(List drops) @@ -759,9 +761,9 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer return t; } - if ( center != null ) + if ( getCenter() != null ) { - IPartCable c = center; + IPartCable c = getCenter(); return c.getCableConnectionType(); } return AECableType.NONE; @@ -770,9 +772,9 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer @Override public AEColor getColor() { - if ( center != null ) + if ( getCenter() != null ) { - IPartCable c = center; + IPartCable c = getCenter(); return c.getCableColor(); } return AEColor.Transparent; @@ -781,7 +783,7 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer @Override public IFacadeContainer getFacadeContainer() { - return fc; + return new FacadeContainer( this ); } @Override @@ -860,6 +862,7 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer if ( AEApi.instance().partHelper().getCableRenderMode().opaqueFacades ) { + IFacadeContainer fc = getFacadeContainer(); for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) { IFacadePart p = fc.getFacade( side ); @@ -887,10 +890,11 @@ public class CableBusContainer implements AEMultiTile, ICableBusContainer @Override public void partChanged() { - if ( center == null ) + if ( getCenter() == null ) { List facades = new LinkedList(); + IFacadeContainer fc = getFacadeContainer(); for (ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) { IFacadePart fp = fc.getFacade( d ); diff --git a/parts/CableBusStorage.java b/parts/CableBusStorage.java new file mode 100644 index 00000000..e231c8c6 --- /dev/null +++ b/parts/CableBusStorage.java @@ -0,0 +1,108 @@ +package appeng.parts; + +import net.minecraftforge.common.util.ForgeDirection; +import appeng.api.implementations.parts.IPartCable; +import appeng.api.parts.IFacadePart; +import appeng.api.parts.IPart; + +/** + * Thin data storage to optimize memory usage for cables. + */ +public class CableBusStorage +{ + + private IPartCable center; + private IPart sides[]; + private IFacadePart facades[]; + + protected IPartCable getCenter() + { + return center; + } + + protected void setCenter(IPartCable center) + { + this.center = center; + } + + protected IPart getSide(ForgeDirection side) + { + int x = side.ordinal(); + if ( sides != null && sides.length > x ) + return sides[x]; + + return null; + } + + protected void setSide(ForgeDirection side, IPart part) + { + int x = side.ordinal(); + + if ( sides != null && sides.length > x && part == null ) + { + sides[x] = null; + sides = shrink( sides, true ); + } + else if ( part != null ) + { + sides = grow( sides, x, true ); + sides[x] = part; + } + } + + public IFacadePart getFacade(int x) + { + if ( facades != null && facades.length > x ) + return facades[x]; + + return null; + } + + public void setFacade(int x, IFacadePart facade) + { + if ( facades != null && facades.length > x && facade == null ) + { + facades[x] = null; + facades = shrink( facades, false ); + } + else + { + facades = grow( facades, x, false ); + facades[x] = facade; + } + } + + private T[] grow(T[] in, int new_value, boolean parts) + { + if ( in != null && in.length > new_value ) + return in; + + int newSize = new_value + 1; + + T[] newArray = (T[]) (parts ? new IPart[newSize] : new IFacadePart[newSize]); + if ( in != null ) + System.arraycopy( in, 0, newArray, 0, in.length ); + + return newArray; + } + + private T[] shrink(T[] in, boolean parts) + { + int newSize = 0; + for (int x = 0; x < in.length; x++) + if ( in[x] != null ) + newSize = x; + + if ( newSize == 0 ) + return null; + + newSize++; + if ( newSize == in.length ) + return in; + + T[] newArray = (T[]) (parts ? new IPart[newSize] : new IFacadePart[newSize]); + System.arraycopy( in, 0, newArray, 0, newSize ); + + return newArray; + } +}