diff options
13 files changed, 218 insertions, 39 deletions
diff --git a/src/main/java/gregtech/GT_Mod.java b/src/main/java/gregtech/GT_Mod.java index 6d5c9e375c..22b677337e 100644 --- a/src/main/java/gregtech/GT_Mod.java +++ b/src/main/java/gregtech/GT_Mod.java @@ -12,6 +12,7 @@ import gregtech.api.enums.*; import gregtech.api.interfaces.internal.IGT_Mod; import gregtech.api.objects.ItemData; import gregtech.api.objects.XSTR; +import gregtech.api.threads.GT_Runnable_MachineBlockUpdate; import gregtech.api.util.*; import gregtech.common.GT_DummyWorld; import gregtech.common.GT_Network; @@ -1187,6 +1188,8 @@ public class GT_Mod implements IGT_Mod { } aEvent.registerServerCommand(new GT_Command()); + //Sets a new Machine Block Update Thread everytime a world is loaded + GT_Runnable_MachineBlockUpdate.initExecutorService(); } public boolean isServerSide() { @@ -1229,7 +1232,6 @@ public class GT_Mod implements IGT_Mod { @Mod.EventHandler public void onServerStopping(FMLServerStoppingEvent aEvent) { - for (Runnable tRunnable : GregTech_API.sBeforeGTServerstop) { try { tRunnable.run(); @@ -1312,6 +1314,8 @@ public class GT_Mod implements IGT_Mod { e.printStackTrace(GT_Log.err); } } + //Interrupt IDLE Threads to close down cleanly + GT_Runnable_MachineBlockUpdate.shutdownExecutorService(); } private void addSolidFakeLargeBoilerFuels() { diff --git a/src/main/java/gregtech/api/GregTech_API.java b/src/main/java/gregtech/api/GregTech_API.java index dac494d9bc..1cc19e7de4 100644 --- a/src/main/java/gregtech/api/GregTech_API.java +++ b/src/main/java/gregtech/api/GregTech_API.java @@ -389,9 +389,11 @@ 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.setMachineUpdateValues(aWorld, aX, aY, aZ); + return true; + } + return false; } /** diff --git a/src/main/java/gregtech/api/interfaces/metatileentity/IMetaTileEntity.java b/src/main/java/gregtech/api/interfaces/metatileentity/IMetaTileEntity.java index a518b3baaf..f0ca426616 100644 --- a/src/main/java/gregtech/api/interfaces/metatileentity/IMetaTileEntity.java +++ b/src/main/java/gregtech/api/interfaces/metatileentity/IMetaTileEntity.java @@ -5,6 +5,7 @@ import cpw.mods.fml.relauncher.SideOnly; import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.tileentity.IGearEnergyTileEntity; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.interfaces.tileentity.IMachineBlockUpdateable; import gregtech.api.objects.GT_ItemStack; import gregtech.api.util.GT_Config; import net.minecraft.block.Block; @@ -31,7 +32,7 @@ import java.util.List; * <p/> * Don't implement this yourself and expect it to work. Extend @MetaTileEntity itself. */ -public interface IMetaTileEntity extends ISidedInventory, IFluidTank, IFluidHandler, IGearEnergyTileEntity { +public interface IMetaTileEntity extends ISidedInventory, IFluidTank, IFluidHandler, IGearEnergyTileEntity, IMachineBlockUpdateable { /** * This determines the BaseMetaTileEntity belonging to this MetaTileEntity by using the Meta ID of the Block itself. * <p/> @@ -234,11 +235,6 @@ public interface IMetaTileEntity extends ISidedInventory, IFluidTank, IFluidHand boolean isAccessAllowed(EntityPlayer aPlayer); /** - * When a Machine Update occurs - */ - void onMachineBlockUpdate(); - - /** * a Player rightclicks the Machine * Sneaky rightclicks are not getting passed to this! * @@ -408,4 +404,22 @@ public interface IMetaTileEntity extends ISidedInventory, IFluidTank, IFluidHand String getAlternativeModeText(); boolean shouldJoinIc2Enet(); + + /** + * The Machine Update, which is called when the Machine needs an Update of its Parts. + * I suggest to wait 1-5 seconds before actually checking the Machine Parts. + * RP-Frames could for example cause Problems when you instacheck the Machine Parts. + * + * just do stuff since we are already in meta tile... + */ + @Override + void onMachineBlockUpdate(); + + /** + * just return in should recurse since we are already in meta tile... + */ + @Override + default boolean isMachineBlockUpdateRecursive(){ + return true; + } } diff --git a/src/main/java/gregtech/api/interfaces/tileentity/IGregTechTileEntity.java b/src/main/java/gregtech/api/interfaces/tileentity/IGregTechTileEntity.java index af9ead9543..8e135fbc85 100644 --- a/src/main/java/gregtech/api/interfaces/tileentity/IGregTechTileEntity.java +++ b/src/main/java/gregtech/api/interfaces/tileentity/IGregTechTileEntity.java @@ -135,4 +135,25 @@ public interface IGregTechTileEntity extends ITexturedTileEntity, IGearEnergyTil AxisAlignedBB getCollisionBoundingBoxFromPool(World aWorld, int aX, int aY, int aZ); void onEntityCollidedWithBlock(World aWorld, int aX, int aY, int aZ, Entity collider); + + /** + * Checks validity of meta tile and delegates to it + */ + @Override + default void onMachineBlockUpdate(){ + if(!isDead() && getMetaTileEntity()!=null && + getMetaTileEntity().getBaseMetaTileEntity()==this){ + getMetaTileEntity().onMachineBlockUpdate(); + } + } + + /** + * Checks validity of meta tile and delegates to it + */ + @Override + default boolean isMachineBlockUpdateRecursive() { + return !isDead() && getMetaTileEntity()!=null && + getMetaTileEntity().getBaseMetaTileEntity()==this && + getMetaTileEntity().isMachineBlockUpdateRecursive(); + } }
\ No newline at end of file diff --git a/src/main/java/gregtech/api/interfaces/tileentity/IMachineBlockUpdateable.java b/src/main/java/gregtech/api/interfaces/tileentity/IMachineBlockUpdateable.java index c7f6fe5f23..31590f3d57 100644 --- a/src/main/java/gregtech/api/interfaces/tileentity/IMachineBlockUpdateable.java +++ b/src/main/java/gregtech/api/interfaces/tileentity/IMachineBlockUpdateable.java @@ -13,4 +13,11 @@ public interface IMachineBlockUpdateable { * RP-Frames could for example cause Problems when you instacheck the Machine Parts. */ void onMachineBlockUpdate(); + + /** + * Should recurse? + */ + default boolean isMachineBlockUpdateRecursive(){ + return true; + } } diff --git a/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java b/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java index 881d4a814e..ae8fc7324d 100644 --- a/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java +++ b/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java @@ -584,11 +584,22 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE return stack; } + /** + * Checks validity of meta tile and delegates to it + */ @Override public void onMachineBlockUpdate() { if (canAccessData()) mMetaTileEntity.onMachineBlockUpdate(); } + /** + * Checks validity of meta tile and delegates to it + */ + @Override + public boolean isMachineBlockUpdateRecursive() { + return canAccessData() && mMetaTileEntity.isMachineBlockUpdateRecursive(); + } + @Override public int getProgress() { return canAccessData() ? mMetaTileEntity.getProgresstime() : 0; diff --git a/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java index 58a97f644a..1ae88ade41 100644 --- a/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java @@ -913,11 +913,22 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE return stack; } + /** + * Checks validity of meta tile and delegates to it + */ @Override public void onMachineBlockUpdate() { if (canAccessData()) mMetaTileEntity.onMachineBlockUpdate(); } + /** + * Checks validity of meta tile and delegates to it + */ + @Override + public boolean isMachineBlockUpdateRecursive() { + return canAccessData() && mMetaTileEntity.isMachineBlockUpdateRecursive(); + } + @Override public int getProgress() { return canAccessData() ? mMetaTileEntity.getProgresstime() : 0; diff --git a/src/main/java/gregtech/api/metatileentity/MetaPipeEntity.java b/src/main/java/gregtech/api/metatileentity/MetaPipeEntity.java index 6614cca210..9fa16b9890 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaPipeEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaPipeEntity.java @@ -840,4 +840,8 @@ public abstract class MetaPipeEntity implements IMetaTileEntity, IConnectable { public boolean shouldJoinIc2Enet() { return false; } + @Override + public boolean isMachineBlockUpdateRecursive() { + return false; + } } diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index 1753d2677c..d08a8d9da5 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -85,7 +85,6 @@ public abstract class MetaTileEntity implements IMetaTileEntity { getBaseMetaTileEntity().setMetaTileID((short) aID); GT_LanguageManager.addStringLocalization("gt.blockmachines." + mName + ".name", aRegionalName); mInventory = new ItemStack[aInvSlotCount]; - } /** diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Frame.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Frame.java index 9db9ad910e..7074d63422 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Frame.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Frame.java @@ -97,4 +97,9 @@ public class GT_MetaPipeEntity_Frame extends MetaPipeEntity { @Override public void disconnect(byte aSide) {/* Do nothing*/} + + @Override + public boolean isMachineBlockUpdateRecursive() { + return true; + } }
\ No newline at end of file diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java index da80a9e231..3efbe0d57b 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java @@ -33,7 +33,8 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity { public static boolean disableMaintenance; public boolean mMachine = false, mWrench = false, mScrewdriver = false, mSoftHammer = false, mHardHammer = false, mSolderingTool = false, mCrowbar = false, mRunningOnLoad = false; - public int mPollution = 0, mProgresstime = 0, mMaxProgresstime = 0, mEUt = 0, mEfficiencyIncrease = 0, mUpdate = 0, mStartUpCheck = 100, mRuntime = 0, mEfficiency = 0; + public int mPollution = 0, mProgresstime = 0, mMaxProgresstime = 0, mEUt = 0, mEfficiencyIncrease = 0, mStartUpCheck = 100, mRuntime = 0, mEfficiency = 0; + public volatile int mUpdate = 0; public ItemStack[] mOutputItems = null; public FluidStack[] mOutputFluids = null; public String mNEI; 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..3d28a94de9 100644 --- a/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java +++ b/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java @@ -1,43 +1,143 @@ package gregtech.api.threads; +import gregtech.GT_Mod; import gregtech.api.GregTech_API; import gregtech.api.interfaces.tileentity.IMachineBlockUpdateable; 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.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; 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 void stepToUpdateMachine(World aWorld, int aX, int aY, int aZ, ArrayList<ChunkPosition> aList) { - aList.add(new ChunkPosition(aX, aY, aZ)); - TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ); - if (tTileEntity instanceof IMachineBlockUpdateable) - ((IMachineBlockUpdateable) tTileEntity).onMachineBlockUpdate(); - if (aList.size() < 5 || (tTileEntity instanceof IMachineBlockUpdateable) || GregTech_API.isMachineBlock(aWorld.getBlock(aX, aY, aZ), aWorld.getBlockMetadata(aX, aY, aZ))) { - if (!aList.contains(new ChunkPosition(aX + 1, aY, aZ))) stepToUpdateMachine(aWorld, aX + 1, aY, aZ, aList); - if (!aList.contains(new ChunkPosition(aX - 1, aY, aZ))) stepToUpdateMachine(aWorld, aX - 1, aY, aZ, aList); - if (!aList.contains(new ChunkPosition(aX, aY + 1, aZ))) stepToUpdateMachine(aWorld, aX, aY + 1, aZ, aList); - if (!aList.contains(new ChunkPosition(aX, aY - 1, aZ))) stepToUpdateMachine(aWorld, aX, aY - 1, aZ, aList); - 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); + //used by runner thread + private final int x, y, z; + private final World world; + private final Set<ChunkPosition> visited = new HashSet<>(80); + + //Threading + private static final ThreadFactory THREAD_FACTORY = r -> { + Thread thread = new Thread(r); + thread.setName("GT_MachineBlockUpdate"); + return thread; + }; + private 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.world = aWorld; + this.x = aX; + this.y = aY; + this.z = aZ; + } + + public static void setMachineUpdateValues(World aWorld, int aX, int aY, int aZ) { + EXECUTOR_SERVICE.submit(new GT_Runnable_MachineBlockUpdate(aWorld, aX, aY, aZ)); + } + + 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); + } + + public static void shutdownExecutorService() { + try { + GT_Mod.GT_FML_LOGGER.info("Shutting down Machine block update executor service"); + EXECUTOR_SERVICE.shutdown(); // Disable new tasks from being submitted + // Wait a while for existing tasks to terminate + if (!EXECUTOR_SERVICE.awaitTermination(60, TimeUnit.SECONDS)) { + EXECUTOR_SERVICE.shutdownNow(); // Cancel currently executing tasks + // Wait a while for tasks to respond to being cancelled + if (!EXECUTOR_SERVICE.awaitTermination(60, TimeUnit.SECONDS)) { + GT_Mod.GT_FML_LOGGER.error("Well this didn't terminated well... GT_Runnable_MachineBlockUpdate.shutdownExecutorService"); + } + } + } catch (InterruptedException ie) { + GT_Mod.GT_FML_LOGGER.error("Well this interruption got interrupted...", ie); + // (Re-)Cancel if current thread also interrupted + EXECUTOR_SERVICE.shutdownNow(); + // Preserve interrupt status + Thread.currentThread().interrupt(); + }catch (Exception e){ + GT_Mod.GT_FML_LOGGER.error("Well this didn't terminated well...",e); + // (Re-)Cancel in case + EXECUTOR_SERVICE.shutdownNow(); + }finally { + GT_Mod.GT_FML_LOGGER.info("Leaving... GT_Runnable_MachineBlockUpdate.shutdownExecutorService"); + } + } + + 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(mWorld, mX, mY, mZ, new ArrayList<ChunkPosition>()); - } catch (Throwable e) {/**/} + stepToUpdateMachine(x, y, z); + } catch (Exception e) { + GT_Mod.GT_FML_LOGGER.error("Well this update was broken... " + new Coordinates(x, y, z, world), 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 + + '}'; + } } -}
\ No newline at end of file +} diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PrimitiveBlastFurnace.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PrimitiveBlastFurnace.java index c0eb143f25..eeeef95dc3 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PrimitiveBlastFurnace.java +++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PrimitiveBlastFurnace.java @@ -25,7 +25,7 @@ public abstract class GT_MetaTileEntity_PrimitiveBlastFurnace extends MetaTileEn public static final int INPUT_SLOTS = 3, OUTPUT_SLOTS = 3; public int mMaxProgresstime = 0; - public int mUpdate = 5; + public volatile int mUpdate = 5; public int mProgresstime = 0; public boolean mMachine = false; |