diff options
Diffstat (limited to 'src/main/java/gregtech/api')
-rw-r--r-- | src/main/java/gregtech/api/GregTech_API.java | 12 | ||||
-rw-r--r-- | src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java | 133 |
2 files changed, 131 insertions, 14 deletions
diff --git a/src/main/java/gregtech/api/GregTech_API.java b/src/main/java/gregtech/api/GregTech_API.java index dac494d9bc..c7d02c7bed 100644 --- a/src/main/java/gregtech/api/GregTech_API.java +++ b/src/main/java/gregtech/api/GregTech_API.java @@ -389,9 +389,15 @@ public class GregTech_API { * @param aZ is the Z-Coord of the update causing Block */ public static boolean causeMachineUpdate(World aWorld, int aX, int aY, int aZ) { - if (!aWorld.isRemote) - new Thread(new GT_Runnable_MachineBlockUpdate(aWorld, aX, aY, aZ), "Machine Block Updating").start(); - return true; + if (!aWorld.isRemote && !GT_Runnable_MachineBlockUpdate.getINSTANCETHREAD().isAlive()) { + GT_Runnable_MachineBlockUpdate.setMachineUpdateValues(aWorld, aX, aY, aZ); + GT_Runnable_MachineBlockUpdate.getINSTANCETHREAD().start(); + return true; + } else if (!aWorld.isRemote && !GT_Runnable_MachineBlockUpdate.isAllowedToRun()){ + GT_Runnable_MachineBlockUpdate.setMachineUpdateValues(aWorld, aX, aY, aZ); + return true; + } + return false; } /** diff --git a/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java b/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java index 92944d3e32..0eed84ef2e 100644 --- a/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java +++ b/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java @@ -1,22 +1,119 @@ package gregtech.api.threads; import gregtech.api.GregTech_API; + +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.interfaces.tileentity.IMachineBlockUpdateable; +import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Cable; +import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Fluid; +import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Item; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.ChunkPosition; import net.minecraft.world.World; -import java.util.ArrayList; +import java.util.HashSet; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.ConcurrentLinkedQueue; public class GT_Runnable_MachineBlockUpdate implements Runnable { - private final int mX, mY, mZ; - private final World mWorld; - public GT_Runnable_MachineBlockUpdate(World aWorld, int aX, int aY, int aZ) { - mWorld = aWorld; - mX = aX; - mY = aY; - mZ = aZ; + private static int mX; + private static int mY; + private static int mZ; + private static World mWorld; + private static final Set<ChunkPosition> mVisited = new HashSet<>(80); + + //Threading + private static boolean allowedToRun; //makes if this thread is idle + private static final Queue<Coordinates> toUpdate = new ConcurrentLinkedQueue<>(); //blocks added while this thread ran + private static final Thread INSTANCETHREAD = new Thread(new GT_Runnable_MachineBlockUpdate()); //Instance of this thread + + //This class should never be initiated outside of this class! + private GT_Runnable_MachineBlockUpdate() { + } + + public static synchronized void setmX(int mX) { + GT_Runnable_MachineBlockUpdate.mX = mX; + } + + public static synchronized void setmY(int mY) { + GT_Runnable_MachineBlockUpdate.mY = mY; + } + + public static synchronized void setmZ(int mZ) { + GT_Runnable_MachineBlockUpdate.mZ = mZ; + } + + public static synchronized void setmWorld(World mWorld) { + GT_Runnable_MachineBlockUpdate.mWorld = mWorld; + } + + /** + * Clears the mVisited HashSet + */ + public static synchronized void resetVisited() { + synchronized (GT_Runnable_MachineBlockUpdate.mVisited) { + GT_Runnable_MachineBlockUpdate.mVisited.clear(); + } + } + + /** + * Never call this Method without checking if the thead is NOT allowed to run! + */ + private static void setMachineUpdateValuesUnsafe(World aWorld, int aX, int aY, int aZ){ + GT_Runnable_MachineBlockUpdate.setmZ(aZ); + GT_Runnable_MachineBlockUpdate.setmY(aY); + GT_Runnable_MachineBlockUpdate.setmX(aX); + GT_Runnable_MachineBlockUpdate.setmWorld(aWorld); + GT_Runnable_MachineBlockUpdate.resetVisited(); + GT_Runnable_MachineBlockUpdate.setAllowedToRun(true); + } + + /** + * If the thread is idleing, sets new values and remove the idle flag, otherwise, queue the cooridinates. + */ + public static synchronized void setMachineUpdateValues(World aWorld, int aX, int aY, int aZ) { + if (GT_Runnable_MachineBlockUpdate.isAllowedToRun()) { + toUpdate.add(new Coordinates(aX, aY, aZ, aWorld)); + } else { + GT_Runnable_MachineBlockUpdate.setMachineUpdateValuesUnsafe(aWorld, aX, aY, aZ); + } + } + + private static class Coordinates { + + private final int mX; + private final int mY; + private final int mZ; + private final World mWorld; + + public Coordinates(int mX, int mY, int mZ, World mWorld) { + this.mX = mX; + this.mY = mY; + this.mZ = mZ; + this.mWorld = mWorld; + } + + /** + * Updated the Main Update Thread while its Idle + */ + public void update() { + GT_Runnable_MachineBlockUpdate.setMachineUpdateValues(this.mWorld,this.mX,this.mY,this.mZ); + } + } + + public static synchronized boolean isAllowedToRun() { + return allowedToRun; + } + + public static synchronized void setAllowedToRun(boolean unlocked) { + GT_Runnable_MachineBlockUpdate.allowedToRun = unlocked; + } + + public static Thread getINSTANCETHREAD() { + return INSTANCETHREAD; } private static void stepToUpdateMachine(World aWorld, int aX, int aY, int aZ, ArrayList<ChunkPosition> aList) { @@ -32,12 +129,26 @@ public class GT_Runnable_MachineBlockUpdate implements Runnable { if (!aList.contains(new ChunkPosition(aX, aY, aZ + 1))) stepToUpdateMachine(aWorld, aX, aY, aZ + 1, aList); if (!aList.contains(new ChunkPosition(aX, aY, aZ - 1))) stepToUpdateMachine(aWorld, aX, aY, aZ - 1, aList); } + } @Override public void run() { - try { - stepToUpdateMachine(mWorld, mX, mY, mZ, new ArrayList<ChunkPosition>()); - } catch (Throwable e) {/**/} + for(;;) { //infinite loop + if (isAllowedToRun()) {//Are we ready to work? + try { + stepToUpdateMachine(mX, mY, mZ); + } catch (Throwable e) {/**/} + setAllowedToRun(false); //Work is finished, wait for new Coords. + } else { + //Checkes if the Update Queue has members + //DO NOT USE OPTIONALS HERE! + synchronized (toUpdate) { + Coordinates coordinates = toUpdate.poll(); + if (coordinates != null) + coordinates.update(); + } + } + } } }
\ No newline at end of file |