diff options
Diffstat (limited to 'src/main/java/gregtech/api/threads')
3 files changed, 133 insertions, 82 deletions
diff --git a/src/main/java/gregtech/api/threads/GT_Runnable_Cable_Update.java b/src/main/java/gregtech/api/threads/GT_Runnable_Cable_Update.java new file mode 100644 index 0000000000..7093184533 --- /dev/null +++ b/src/main/java/gregtech/api/threads/GT_Runnable_Cable_Update.java @@ -0,0 +1,69 @@ +package gregtech.api.threads; + +import gregtech.GT_Mod; +import gregtech.api.interfaces.tileentity.IMachineBlockUpdateable; +import gregtech.api.metatileentity.BaseMetaPipeEntity; +import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Cable; +import gregtech.common.GT_Proxy; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ChunkCoordinates; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; + +public class GT_Runnable_Cable_Update extends GT_Runnable_MachineBlockUpdate { + protected GT_Runnable_Cable_Update(World aWorld, ChunkCoordinates aCoords) { + super(aWorld, aCoords); + } + + public static void setCableUpdateValues(World aWorld, ChunkCoordinates aCoords) { + if (isEnabled) { + EXECUTOR_SERVICE.submit(new GT_Runnable_Cable_Update(aWorld, aCoords)); + } + } + + @Override + public void run() { + try { + while (!tQueue.isEmpty()) { + final ChunkCoordinates aCoords = tQueue.poll(); + final TileEntity tTileEntity; + + GT_Proxy.TICK_LOCK.lock(); + try { + //we dont want to go over cables that are in unloaded chunks + //keeping the lock just to make sure no CME happens + if (world.blockExists(aCoords.posX, aCoords.posY, aCoords.posZ)) { + tTileEntity = world.getTileEntity(aCoords.posX, aCoords.posY, aCoords.posZ); + } else { + tTileEntity = null; + } + } finally { + GT_Proxy.TICK_LOCK.unlock(); + } + + // See if the block itself needs an update + if (tTileEntity instanceof IMachineBlockUpdateable) + ((IMachineBlockUpdateable) tTileEntity).onMachineBlockUpdate(); + + // Now see if we should add the nearby blocks to the queue: + // only add blocks the cable is connected to + if (tTileEntity instanceof BaseMetaPipeEntity && + ((BaseMetaPipeEntity) tTileEntity).getMetaTileEntity() instanceof GT_MetaPipeEntity_Cable) + { + ChunkCoordinates tCoords; + for (byte i = 0;i<6;i++) { + if (((GT_MetaPipeEntity_Cable) ((BaseMetaPipeEntity) tTileEntity).getMetaTileEntity()).isConnectedAtSide(i)) { + ForgeDirection offset = ForgeDirection.getOrientation(i); + if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX + offset.offsetX, + aCoords.posY + offset.offsetY, aCoords.posZ + offset.offsetZ))) + tQueue.add(tCoords); + } + } + } + } + } catch (Exception e) { + GT_Mod.GT_FML_LOGGER.error( + "Well this update was broken... " + mCoords + ", mWorld={" + world.getProviderName() + " @dimId " + world.provider.dimensionId + "}", e); + } + } +} 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 ee56a0b0c0..cc224b977d 100644 --- a/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java +++ b/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java @@ -3,11 +3,14 @@ package gregtech.api.threads; import gregtech.GT_Mod; import gregtech.api.GregTech_API; import gregtech.api.interfaces.tileentity.IMachineBlockUpdateable; +import gregtech.common.GT_Proxy; import net.minecraft.tileentity.TileEntity; -import net.minecraft.world.ChunkPosition; +import net.minecraft.util.ChunkCoordinates; import net.minecraft.world.World; import java.util.HashSet; +import java.util.LinkedList; +import java.util.Queue; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -15,25 +18,26 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; public class GT_Runnable_MachineBlockUpdate implements Runnable { - //used by runner thread - private final int x, y, z; - private final World world; - private final Set<ChunkPosition> visited = new HashSet<>(80); - - //Threading + // used by runner thread + protected final ChunkCoordinates mCoords; + protected final World world; + protected final Set<ChunkCoordinates> visited = new HashSet<>(80); + protected final Queue<ChunkCoordinates> tQueue = new LinkedList<>(); + + // Threading private static final ThreadFactory THREAD_FACTORY = r -> { Thread thread = new Thread(r); thread.setName("GT_MachineBlockUpdate"); return thread; }; - private static ExecutorService EXECUTOR_SERVICE; + protected static ExecutorService EXECUTOR_SERVICE; - //This class should never be initiated outside of this class! - private GT_Runnable_MachineBlockUpdate(World aWorld, int aX, int aY, int aZ) { + // This class should never be initiated outside of this class! + protected GT_Runnable_MachineBlockUpdate(World aWorld, ChunkCoordinates aCoords) { this.world = aWorld; - this.x = aX; - this.y = aY; - this.z = aZ; + this.mCoords = aCoords; + visited.add(aCoords); + tQueue.add(aCoords); } public static boolean isEnabled() { @@ -52,18 +56,16 @@ public class GT_Runnable_MachineBlockUpdate implements Runnable { GT_Runnable_MachineBlockUpdate.isEnabled = isEnabled; } - private static boolean isEnabled = true; + protected static boolean isEnabled = true; - public static void setMachineUpdateValues(World aWorld, int aX, int aY, int aZ) { - if (isEnabled) - EXECUTOR_SERVICE.submit(new GT_Runnable_MachineBlockUpdate(aWorld, aX, aY, aZ)); + public static void setMachineUpdateValues(World aWorld, ChunkCoordinates aCoords) { + if (isEnabled) { + EXECUTOR_SERVICE.submit(new GT_Runnable_MachineBlockUpdate(aWorld, aCoords)); + } } public static void initExecutorService() { - EXECUTOR_SERVICE = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), THREAD_FACTORY); - //Executors.newSingleThreadExecutor(THREAD_FACTORY); - //Executors.newCachedThreadPool(THREAD_FACTORY); - //Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(),THREAD_FACTORY); + EXECUTOR_SERVICE = Executors.newFixedThreadPool((Runtime.getRuntime().availableProcessors() * 2 / 3), THREAD_FACTORY); } public static void shutdownExecutorService() { @@ -85,7 +87,7 @@ public class GT_Runnable_MachineBlockUpdate implements Runnable { // Preserve interrupt status Thread.currentThread().interrupt(); }catch (Exception e){ - GT_Mod.GT_FML_LOGGER.error("Well this didn't terminated well...",e); + GT_Mod.GT_FML_LOGGER.error("Well this didn't terminated well...", e); // (Re-)Cancel in case EXECUTOR_SERVICE.shutdownNow(); }finally { @@ -93,70 +95,50 @@ public class GT_Runnable_MachineBlockUpdate implements Runnable { } } - private boolean shouldRecurse(TileEntity aTileEntity, int aX, int aY, int aZ) { - //no check on IGregTechTileEntity as it should call the underlying meta tile isMachineBlockUpdateRecursive - //if (aTileEntity instanceof IGregTechTileEntity) { - // return ((IGregTechTileEntity) aTileEntity).isMachineBlockUpdateRecursive(); - //} - return (aTileEntity instanceof IMachineBlockUpdateable && - ((IMachineBlockUpdateable) aTileEntity).isMachineBlockUpdateRecursive()) || - GregTech_API.isMachineBlock(world.getBlock(aX, aY, aZ), world.getBlockMetadata(aX, aY, aZ)); - } - - private void causeUpdate(TileEntity tileEntity) { - //no check for IGregTechTileEntity as it should call the underlying meta tile onMachineBlockUpdate - if (tileEntity instanceof IMachineBlockUpdateable) { - ((IMachineBlockUpdateable) tileEntity).onMachineBlockUpdate(); - } - } - - private void stepToUpdateMachine(int aX, int aY, int aZ) { - if (!visited.add(new ChunkPosition(aX, aY, aZ))) - return; - TileEntity tTileEntity = world.getTileEntity(aX, aY, aZ); - - causeUpdate(tTileEntity); - - if (visited.size() < 5 || shouldRecurse(tTileEntity, aX, aY, aZ)) { - stepToUpdateMachine(aX + 1, aY, aZ); - stepToUpdateMachine(aX - 1, aY, aZ); - stepToUpdateMachine(aX, aY + 1, aZ); - stepToUpdateMachine(aX, aY - 1, aZ); - stepToUpdateMachine(aX, aY, aZ + 1); - stepToUpdateMachine(aX, aY, aZ - 1); - } - } - @Override public void run() { try { - stepToUpdateMachine(x, y, z); + while (!tQueue.isEmpty()) { + final ChunkCoordinates aCoords = tQueue.poll(); + final TileEntity tTileEntity; + final boolean isMachineBlock; + + // This might load a chunk... which might load a TileEntity... which might get added to `loadedTileEntityList`... which might be in the process + // of being iterated over during `UpdateEntities()`... which might cause a ConcurrentModificationException. So, lock that shit. + GT_Proxy.TICK_LOCK.lock(); + try { + tTileEntity = world.getTileEntity(aCoords.posX, aCoords.posY, aCoords.posZ); + isMachineBlock = GregTech_API.isMachineBlock(world.getBlock(aCoords.posX, aCoords.posY, aCoords.posZ), world.getBlockMetadata(aCoords.posX, aCoords.posY, aCoords.posZ)); + } finally { + GT_Proxy.TICK_LOCK.unlock(); + } + + // See if the block itself needs an update + if (tTileEntity instanceof IMachineBlockUpdateable) + ((IMachineBlockUpdateable) tTileEntity).onMachineBlockUpdate(); + + // Now see if we should add the nearby blocks to the queue: + // 1) If we've visited less than 5 blocks, then yes + // 2) If the tile says we should recursively updated (pipes don't, machine blocks do) + // 3) If the block at the coordinates is marked as a machine block + if (visited.size() < 5 + || (tTileEntity instanceof IMachineBlockUpdateable && ((IMachineBlockUpdateable) tTileEntity).isMachineBlockUpdateRecursive()) + || isMachineBlock) + { + ChunkCoordinates tCoords; + + if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX + 1, aCoords.posY, aCoords.posZ))) tQueue.add(tCoords); + if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX - 1, aCoords.posY, aCoords.posZ))) tQueue.add(tCoords); + if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY + 1, aCoords.posZ))) tQueue.add(tCoords); + if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY - 1, aCoords.posZ))) tQueue.add(tCoords); + if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY, aCoords.posZ + 1))) tQueue.add(tCoords); + if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY, aCoords.posZ - 1))) tQueue.add(tCoords); + } + } } catch (Exception e) { - GT_Mod.GT_FML_LOGGER.error("Well this update was broken... " + new Coordinates(x, y, z, world), e); + GT_Mod.GT_FML_LOGGER.error( + "Well this update was broken... " + mCoords + ", mWorld={" + world.getProviderName() + " @dimId " + world.provider.dimensionId + "}", e); } } - public static class Coordinates { - public final int mX; - public final int mY; - public final int mZ; - public 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; - } - - @Override - public String toString() { - return "Coordinates{" + - "mX=" + mX + - ", mY=" + mY + - ", mZ=" + mZ + - ", mWorld=" + mWorld.getProviderName() + " @dimId " + mWorld.provider.dimensionId + - '}'; - } - } } diff --git a/src/main/java/gregtech/api/threads/GT_Runnable_Sound.java b/src/main/java/gregtech/api/threads/GT_Runnable_Sound.java index 6588780624..dad93ff98c 100644 --- a/src/main/java/gregtech/api/threads/GT_Runnable_Sound.java +++ b/src/main/java/gregtech/api/threads/GT_Runnable_Sound.java @@ -31,4 +31,4 @@ public class GT_Runnable_Sound implements Runnable { GT_Utility.sPlayedSoundMap.put(tSound, mTimeUntilNextSound); } catch (Throwable e) {/**/} } -}
\ No newline at end of file +} |