Mechanical network optimization and caching connections

This commit is contained in:
Calclavia 2014-02-27 23:00:38 +08:00
parent ad974aab79
commit bd37a0999b
11 changed files with 166 additions and 208 deletions

View file

@ -43,7 +43,7 @@ public class BlockConveyorBelt extends BlockTile
if (t != null && t instanceof TileConveyorBelt) if (t != null && t instanceof TileConveyorBelt)
{ {
TileConveyorBelt tileEntity = (TileConveyorBelt) t; TileConveyorBelt tileEntity = (TileConveyorBelt) t;
tileEntity.refresh(); tileEntity.getNetwork().reconstruct();
} }
} }
@ -55,7 +55,7 @@ public class BlockConveyorBelt extends BlockTile
if (t != null && t instanceof TileConveyorBelt) if (t != null && t instanceof TileConveyorBelt)
{ {
TileConveyorBelt tileEntity = (TileConveyorBelt) t; TileConveyorBelt tileEntity = (TileConveyorBelt) t;
tileEntity.refresh(); tileEntity.getNetwork().reconstruct();
} }
} }

View file

@ -132,8 +132,7 @@ public class TileConveyorBelt extends TileMechanical implements IBelt, IRotatabl
if (id == PACKET_SLANT) if (id == PACKET_SLANT)
this.slantType = SlantType.values()[data.readInt()]; this.slantType = SlantType.values()[data.readInt()];
else if (id == PACKET_REFRESH) else if (id == PACKET_REFRESH)
refresh(); getNetwork().reconstruct();
} }
public SlantType getSlant() public SlantType getSlant()
@ -149,7 +148,7 @@ public class TileConveyorBelt extends TileMechanical implements IBelt, IRotatabl
} }
this.slantType = slantType; this.slantType = slantType;
refresh(); getNetwork().reconstruct();
this.worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); this.worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
} }
@ -208,8 +207,9 @@ public class TileConveyorBelt extends TileMechanical implements IBelt, IRotatabl
} }
@Override @Override
public void refresh() public Object[] getConnections()
{ {
Object[] connections = new Object[6];
boolean didRefresh = false; boolean didRefresh = false;
for (int i = 2; i < 6; i++) for (int i = 2; i < 6; i++)
@ -248,7 +248,6 @@ public class TileConveyorBelt extends TileMechanical implements IBelt, IRotatabl
if (tile instanceof IBelt) if (tile instanceof IBelt)
{ {
connections[dir.ordinal()] = tile; connections[dir.ordinal()] = tile;
getNetwork().merge(((IBelt) tile).getNetwork());
didRefresh = true; didRefresh = true;
} }
} }
@ -259,7 +258,6 @@ public class TileConveyorBelt extends TileMechanical implements IBelt, IRotatabl
if (mechanical != null) if (mechanical != null)
{ {
connections[dir.ordinal()] = mechanical; connections[dir.ordinal()] = mechanical;
getNetwork().merge(mechanical.getNetwork());
} }
} }
} }
@ -271,6 +269,8 @@ public class TileConveyorBelt extends TileMechanical implements IBelt, IRotatabl
markRefresh = true; markRefresh = true;
} }
} }
return connections;
} }
@Override @Override

View file

@ -1,6 +1,5 @@
package resonantinduction.mechanical.energy.gear; package resonantinduction.mechanical.energy.gear;
import java.lang.ref.WeakReference;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -117,15 +116,10 @@ public class PartGear extends PartMechanical implements IMechanical, IMultiBlock
@Override @Override
public boolean activate(EntityPlayer player, MovingObjectPosition hit, ItemStack itemStack) public boolean activate(EntityPlayer player, MovingObjectPosition hit, ItemStack itemStack)
{ {
if (itemStack != null && itemStack.getItem() instanceof ItemHandCrank) if (!world().isRemote)
{ System.out.println(getNetwork());
getMultiBlock().get().manualCrankTime = 10;
world().playSoundEffect(x() + 0.5, y() + 0.5, z() + 0.5, Reference.PREFIX + "gearCrank", 0.5f, 0.9f + world().rand.nextFloat() * 0.2f);
player.addExhaustion(0.01f);
return true;
}
if (WrenchUtility.isWrench(itemStack)) if (itemStack != null && itemStack.getItem() instanceof ItemHandCrank)
{ {
if (player.isSneaking()) if (player.isSneaking())
{ {
@ -134,21 +128,20 @@ public class PartGear extends PartMechanical implements IMechanical, IMultiBlock
getMultiBlock().get().angularVelocity = -getMultiBlock().get().angularVelocity; getMultiBlock().get().angularVelocity = -getMultiBlock().get().angularVelocity;
player.addChatMessage("Flipped gear to rotate " + (angularVelocity > 0 ? "clockwise" : "anticlockwise") + "."); player.addChatMessage("Flipped gear to rotate " + (angularVelocity > 0 ? "clockwise" : "anticlockwise") + ".");
} }
}
else
{
getMultiBlock().toggleConstruct();
}
return true; return true;
} }
else if (player.isSneaking())
{ getMultiBlock().get().manualCrankTime = 10;
if (!world().isRemote) world().playSoundEffect(x() + 0.5, y() + 0.5, z() + 0.5, Reference.PREFIX + "gearCrank", 0.5f, 0.9f + world().rand.nextFloat() * 0.2f);
{ player.addExhaustion(0.01f);
getMultiBlock().get().angularVelocity = -getMultiBlock().get().angularVelocity; return true;
player.addChatMessage("Flipped gear to rotate " + (angularVelocity > 0 ? "clockwise" : "anticlockwise") + ".");
} }
if (WrenchUtility.isWrench(itemStack))
{
getMultiBlock().toggleConstruct();
return true;
} }
return super.activate(player, hit, itemStack); return super.activate(player, hit, itemStack);
@ -165,16 +158,16 @@ public class PartGear extends PartMechanical implements IMechanical, IMultiBlock
* Refresh should be called sparingly. * Refresh should be called sparingly.
*/ */
@Override @Override
public void refresh() public Object[] getConnections()
{ {
connections = new WeakReference[6]; Object[] connections = new Object[6];
/** /**
* Only call refresh if this is the main block of a multiblock gear or a single gear block. * Only call refresh if this is the main block of a multiblock gear or a single gear block.
*/ */
if (!getMultiBlock().isPrimary()) if (!getMultiBlock().isPrimary() || world() == null)
{ {
return; return connections;
} }
/** Look for gears that are back-to-back with this gear. Equate torque. */ /** Look for gears that are back-to-back with this gear. Equate torque. */
@ -186,10 +179,8 @@ public class PartGear extends PartMechanical implements IMechanical, IMultiBlock
if (instance != null && instance != this && !(instance instanceof PartGearShaft) && instance.canConnect(placementSide.getOpposite(), this)) if (instance != null && instance != this && !(instance instanceof PartGearShaft) && instance.canConnect(placementSide.getOpposite(), this))
{ {
connections[placementSide.ordinal()] = new WeakReference(instance); connections[placementSide.ordinal()] = instance;
getNetwork().merge(instance.getNetwork());
} }
} }
/** /**
@ -217,8 +208,7 @@ public class PartGear extends PartMechanical implements IMechanical, IMultiBlock
if (connections[checkDir.ordinal()] == null && instance != this && checkDir != placementSide && instance != null && instance.canConnect(checkDir.getOpposite(), this)) if (connections[checkDir.ordinal()] == null && instance != this && checkDir != placementSide && instance != null && instance.canConnect(checkDir.getOpposite(), this))
{ {
connections[checkDir.ordinal()] = new WeakReference(instance); connections[checkDir.ordinal()] = instance;
getNetwork().merge(instance.getNetwork());
} }
} }
} }
@ -242,13 +232,12 @@ public class PartGear extends PartMechanical implements IMechanical, IMultiBlock
if (instance != null && instance != this && instance.canConnect(checkDir.getOpposite(), this) && !(instance instanceof PartGearShaft)) if (instance != null && instance != this && instance.canConnect(checkDir.getOpposite(), this) && !(instance instanceof PartGearShaft))
{ {
connections[checkDir.ordinal()] = new WeakReference(instance); connections[checkDir.ordinal()] = instance;
getNetwork().merge(instance.getNetwork());
} }
} }
} }
getNetwork().reconstruct(); return connections;
} }
/** /**
@ -284,17 +273,6 @@ public class PartGear extends PartMechanical implements IMechanical, IMultiBlock
return false; return false;
} }
@Override
public Object[] getConnections()
{
if (!getMultiBlock().isPrimary())
{
return new Object[6];
}
return super.getConnections();
}
@Override @Override
protected ItemStack getItem() protected ItemStack getItem()
{ {

View file

@ -1,6 +1,5 @@
package resonantinduction.mechanical.energy.gear; package resonantinduction.mechanical.energy.gear;
import java.lang.ref.WeakReference;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -78,9 +77,9 @@ public class PartGearShaft extends PartMechanical
* Refresh should be called sparingly. * Refresh should be called sparingly.
*/ */
@Override @Override
public void refresh() public Object[] getConnections()
{ {
connections = new WeakReference[6]; Object[] connections = new Object[6];
/** Check for internal connections, the FRONT and BACK. */ /** Check for internal connections, the FRONT and BACK. */
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
@ -93,8 +92,7 @@ public class PartGearShaft extends PartMechanical
if (instance != null && instance != this && instance.canConnect(checkDir.getOpposite(), this)) if (instance != null && instance != this && instance.canConnect(checkDir.getOpposite(), this))
{ {
connections[checkDir.ordinal()] = new WeakReference(instance); connections[checkDir.ordinal()] = instance;
getNetwork().merge(instance.getNetwork());
} }
} }
} }
@ -115,14 +113,13 @@ public class PartGearShaft extends PartMechanical
// Only connect to shafts outside of this block space. // Only connect to shafts outside of this block space.
if (instance != null && instance != this && instance instanceof PartGearShaft && instance.canConnect(checkDir.getOpposite(), this)) if (instance != null && instance != this && instance instanceof PartGearShaft && instance.canConnect(checkDir.getOpposite(), this))
{ {
connections[checkDir.ordinal()] = new WeakReference(instance); connections[checkDir.ordinal()] = instance;
getNetwork().merge(instance.getNetwork());
} }
} }
} }
} }
getNetwork().reconstruct(); return connections;
} }
@Override @Override

View file

@ -1,15 +1,15 @@
package resonantinduction.mechanical.energy.network; package resonantinduction.mechanical.energy.network;
import java.util.EnumSet; import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.WeakHashMap;
import java.util.LinkedHashSet;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.ForgeDirection; import net.minecraftforge.common.ForgeDirection;
import resonantinduction.api.mechanical.IMechanical; import resonantinduction.api.mechanical.IMechanical;
import resonantinduction.api.mechanical.IMechanicalNetwork; import resonantinduction.api.mechanical.IMechanicalNetwork;
import universalelectricity.api.net.IUpdate; import universalelectricity.api.net.IUpdate;
import universalelectricity.api.vector.Vector3;
import universalelectricity.core.net.Network; import universalelectricity.core.net.Network;
import universalelectricity.core.net.NetworkTickHandler; import universalelectricity.core.net.NetworkTickHandler;
@ -41,7 +41,7 @@ public class MechanicalNetwork extends Network<IMechanicalNetwork, IMechanical>
/** /**
* The cached connections of the mechanical network. * The cached connections of the mechanical network.
*/ */
private final HashMap<Object, EnumSet<ForgeDirection>> connectionMap = new LinkedHashMap<Object, EnumSet<ForgeDirection>>(); private final WeakHashMap<IMechanical, WeakReference[]> connectionCache = new WeakHashMap<IMechanical, WeakReference[]>();
private boolean markUpdateRotation = true; private boolean markUpdateRotation = true;
@ -61,21 +61,27 @@ public class MechanicalNetwork extends Network<IMechanicalNetwork, IMechanical>
*/ */
@Override @Override
public void update() public void update()
{
synchronized (getConnectors())
{ {
/** /**
* Update all mechanical nodes. * Update all mechanical nodes.
*/ */
Iterator<IMechanical> it = new LinkedHashSet<IMechanical>(getConnectors()).iterator(); Iterator<IMechanical> it = getConnectors().iterator();
while (it.hasNext()) while (it.hasNext())
{ {
IMechanical mechanical = it.next(); IMechanical mechanical = it.next();
Object[] connections = mechanical.getConnections(); WeakReference[] connections = connectionCache.get(mechanical);
if (connections != null)
{
for (int i = 0; i < connections.length; i++) for (int i = 0; i < connections.length; i++)
{
if (connections[i] != null)
{ {
ForgeDirection dir = ForgeDirection.getOrientation(i); ForgeDirection dir = ForgeDirection.getOrientation(i);
Object adjacent = connections[i]; Object adjacent = connections[i].get();
if (adjacent instanceof IMechanical) if (adjacent instanceof IMechanical)
{ {
@ -83,7 +89,6 @@ public class MechanicalNetwork extends Network<IMechanicalNetwork, IMechanical>
if (adjacentMech != null && adjacent != mechanical) if (adjacentMech != null && adjacent != mechanical)
{ {
// System.out.println("UPDATING: " + mechanical + " with " + adjacentMech);
float ratio = adjacentMech.getRatio(dir.getOpposite(), mechanical) / mechanical.getRatio(dir, adjacentMech); float ratio = adjacentMech.getRatio(dir.getOpposite(), mechanical) / mechanical.getRatio(dir, adjacentMech);
long torque = mechanical.getTorque(); long torque = mechanical.getTorque();
@ -103,6 +108,9 @@ public class MechanicalNetwork extends Network<IMechanicalNetwork, IMechanical>
} }
} }
} }
}
}
}
@Override @Override
public boolean canUpdate() public boolean canUpdate()
@ -117,18 +125,75 @@ public class MechanicalNetwork extends Network<IMechanicalNetwork, IMechanical>
} }
@Override @Override
public void reconstruct() protected void reconstructConnector(IMechanical node)
{ {
super.reconstruct(); node.setNetwork(this);
if (canUpdate()) /**
NetworkTickHandler.addNetwork(this); * Cache connections.
*/
Object[] conn = node.getConnections();
if (conn == null && node instanceof TileEntity)
{
/**
* Default connection implementation
*/
conn = new Object[6];
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS)
{
TileEntity tile = new Vector3((TileEntity) node).translate(dir).getTileEntity(((TileEntity) node).worldObj);
if (tile instanceof IMechanical)
{
IMechanical mech = ((IMechanical) tile).getInstance(dir.getOpposite());
if (mech != null && node.canConnect(dir, mech) && mech.canConnect(dir.getOpposite(), node))
{
conn[dir.ordinal()] = mech;
}
}
}
}
WeakReference[] connections = new WeakReference[conn.length];
for (int i = 0; i < connections.length; i++)
{
if (conn[i] != null)
{
if (conn[i] instanceof IMechanical)
{
IMechanical connected = ((IMechanical) conn[i]);
if (connected.getNetwork() != this)
{
connected.getNetwork().getConnectors().clear();
connected.setNetwork(this);
addConnector(connected);
reconstructConnector(connected);
}
}
connections[i] = new WeakReference(conn[i]);
}
}
connectionCache.put(node, connections);
} }
@Override @Override
protected void reconstructConnector(IMechanical connector) public Object[] getConnectionsFor(IMechanical connector)
{ {
connector.setNetwork(this); Object[] conn = new Object[6];
WeakReference[] connections = connectionCache.get(connector);
for (int i = 0; i < connections.length; i++)
if (connections[i] != null)
conn[i] = connections[i].get();
return conn;
} }
@Override @Override

View file

@ -28,11 +28,7 @@ public abstract class PartMechanical extends JCuboidPart implements JNormalOcclu
{ {
private IMechanicalNetwork network; private IMechanicalNetwork network;
/** The mechanical connections this connector has made */
protected WeakReference[] connections = new WeakReference[6];
protected float prevAngularVelocity, angularVelocity; protected float prevAngularVelocity, angularVelocity;
protected long torque; protected long torque;
/** /**
@ -55,23 +51,6 @@ public abstract class PartMechanical extends JCuboidPart implements JNormalOcclu
this.tier = itemDamage; this.tier = itemDamage;
} }
@Override
public boolean activate(EntityPlayer player, MovingObjectPosition hit, ItemStack item)
{
if (!world().isRemote)
{
int i = 0;
for (Object obj : connections)
if (obj != null)
i++;
System.out.println("Connected with: " + i + ":" + getNetwork());
// refresh();
}
return false;
}
@Override @Override
public void update() public void update()
{ {
@ -102,33 +81,19 @@ public abstract class PartMechanical extends JCuboidPart implements JNormalOcclu
@Override @Override
public void onWorldJoin() public void onWorldJoin()
{ {
refresh(); getNetwork().reconstruct();
} }
@Override @Override
public void onNeighborChanged() public void onNeighborChanged()
{ {
refresh(); getNetwork().reconstruct();
} }
@Override @Override
public void onPartChanged(TMultiPart part) public void onPartChanged(TMultiPart part)
{ {
refresh(); getNetwork().reconstruct();
}
protected abstract void refresh();
@Override
public Object[] getConnections()
{
Object[] actualConnections = new Object[6];
for (int i = 0; i < connections.length; i++)
if (connections[i] != null)
actualConnections[i] = connections[i].get();
return actualConnections;
} }
@Override @Override

View file

@ -20,8 +20,6 @@ public abstract class TileMechanical extends TileAdvanced implements IMechanical
{ {
protected static final int PACKET_VELOCITY = Mechanical.contentRegistry.getNextPacketID(); protected static final int PACKET_VELOCITY = Mechanical.contentRegistry.getNextPacketID();
/** The mechanical connections this connector has made */
protected Object[] connections = new Object[6];
private IMechanicalNetwork network; private IMechanicalNetwork network;
protected float angularVelocity; protected float angularVelocity;
protected long torque; protected long torque;
@ -36,7 +34,7 @@ public abstract class TileMechanical extends TileAdvanced implements IMechanical
@Override @Override
public void initiate() public void initiate()
{ {
refresh(); getNetwork().reconstruct();
} }
@Override @Override
@ -105,14 +103,6 @@ public abstract class TileMechanical extends TileAdvanced implements IMechanical
super.invalidate(); super.invalidate();
} }
/**
* Refreshes all the connections of this block.
*/
public void refresh()
{
}
protected float getLoad() protected float getLoad()
{ {
return 0.95f; return 0.95f;
@ -121,26 +111,7 @@ public abstract class TileMechanical extends TileAdvanced implements IMechanical
@Override @Override
public Object[] getConnections() public Object[] getConnections()
{ {
connections = new Object[6]; return null;
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS)
{
TileEntity tile = new Vector3(this).translate(dir).getTileEntity(worldObj);
if (tile instanceof IMechanical)
{
IMechanical mech = ((IMechanical) tile).getInstance(dir.getOpposite());
// Don't connect with shafts
if (mech != null && !(mech instanceof PartGearShaft) && canConnect(dir, this) && mech.canConnect(dir.getOpposite(), this))
{
connections[dir.ordinal()] = mech;
getNetwork().merge(mech.getNetwork());
}
}
}
return connections;
} }
@Override @Override

View file

@ -17,36 +17,6 @@ public class TileMechanicalTurbine extends TileTurbine implements IMechanical
energy = new EnergyStorageHandler(0); energy = new EnergyStorageHandler(0);
} }
/**
* Mechanical Methods
*
* @return The connections.
*/
@Override
public Object[] getConnections()
{
Object[] connections = new Object[6];
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS)
{
TileEntity tile = new Vector3(this).translate(dir).getTileEntity(worldObj);
if (tile instanceof IMechanical)
{
IMechanical mech = ((IMechanical) tile).getInstance(dir.getOpposite());
// Don't connect with shafts
if (mech != null && canConnect(dir, this) && mech.canConnect(dir.getOpposite(), this))
{
connections[dir.ordinal()] = mech;
getNetwork().merge(mech.getNetwork());
}
}
}
return connections;
}
private IMechanicalNetwork network; private IMechanicalNetwork network;
@Override @Override
@ -120,4 +90,10 @@ public class TileMechanicalTurbine extends TileTurbine implements IMechanical
} }
return false; return false;
} }
@Override
public Object[] getConnections()
{
return null;
}
} }

View file

@ -58,15 +58,7 @@ public abstract class FluidNetwork extends NodeNetwork<IFluidNetwork, IFluidConn
{ {
this.tank = new FluidTank(0); this.tank = new FluidTank(0);
for (IFluidConnector connector : new HashSet<IFluidConnector>(getConnectors())) super.reconstruct();
{
if (connector.getNetwork() instanceof IFluidNetwork)
{
connector.setNetwork(this);
}
this.reconstructConnector(connector);
}
this.reconstructTankInfo(); this.reconstructTankInfo();
this.distributeConnectors(); this.distributeConnectors();
@ -75,6 +67,9 @@ public abstract class FluidNetwork extends NodeNetwork<IFluidNetwork, IFluidConn
@Override @Override
public void reconstructConnector(IFluidConnector connector) public void reconstructConnector(IFluidConnector connector)
{ {
if (connector.getNetwork() instanceof IFluidNetwork)
connector.setNetwork(this);
FluidTank tank = connector.getInternalTank(); FluidTank tank = connector.getInternalTank();
if (tank != null) if (tank != null)

View file

@ -1,6 +1,7 @@
package resonantinduction.core.resource; package resonantinduction.core.resource;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.world.World;
public class ItemHandCrank extends Item public class ItemHandCrank extends Item
{ {
@ -8,5 +9,9 @@ public class ItemHandCrank extends Item
{ {
super(id); super(id);
} }
@Override
public boolean shouldPassSneakingClickToBlock(World world, int x, int y, int z)
{
return true;
}
} }

View file

@ -49,9 +49,15 @@ public class ItemOreResourceBucket extends Item
{ {
if (getMaterialFromStack(is) != null) if (getMaterialFromStack(is) != null)
{ {
String fluidName = FluidRegistry.getFluid(isMolten ? ResourceGenerator.materialNameToMolten(getMaterialFromStack(is)) : ResourceGenerator.materialNameToMixture(getMaterialFromStack(is))).getLocalizedName(); String fluidID = isMolten ? ResourceGenerator.materialNameToMolten(getMaterialFromStack(is)) : ResourceGenerator.materialNameToMixture(getMaterialFromStack(is));
if (fluidID != null)
{
String fluidName = FluidRegistry.getFluid(fluidID).getLocalizedName();
return (LanguageUtility.getLocal(this.getUnlocalizedName() + ".name")).replace("%v", fluidName).replace(" ", " "); return (LanguageUtility.getLocal(this.getUnlocalizedName() + ".name")).replace("%v", fluidName).replace(" ", " ");
} }
}
return null; return null;
} }