diff options
| author | repo-alt <wvk17@yandex.ru> | 2019-12-28 21:38:45 +0300 | 
|---|---|---|
| committer | bartimaeusnek <33183715+bartimaeusnek@users.noreply.github.com> | 2019-12-28 19:38:45 +0100 | 
| commit | 317804772b74bbecffc2f92120768d1c768a9abf (patch) | |
| tree | b1f5611f4fc5a387e79ed897cb0c282fa8c056be | |
| parent | e94ffcf40114574062d4d7223c7f6f7933034ec5 (diff) | |
| download | GT5-Unofficial-317804772b74bbecffc2f92120768d1c768a9abf.tar.gz GT5-Unofficial-317804772b74bbecffc2f92120768d1c768a9abf.tar.bz2 GT5-Unofficial-317804772b74bbecffc2f92120768d1c768a9abf.zip | |
Chunkloading support for multiblock miner (#227)
* WIP, doesn't do anything yet, up to RFC
* Initial attempt at Chunk manager
* Added chunkloading support to multiblock miner.
* moved basic miner-independent chunkloading-related stuff up tier, to be more reusable
Co-authored-by: Richard Hendricks <richardhendricks@pobox.com>
8 files changed, 373 insertions, 18 deletions
| diff --git a/src/main/java/gregtech/GT_Mod.java b/src/main/java/gregtech/GT_Mod.java index deaf40027f..d121e75d07 100644 --- a/src/main/java/gregtech/GT_Mod.java +++ b/src/main/java/gregtech/GT_Mod.java @@ -10,6 +10,7 @@ import gregtech.api.enchants.Enchantment_EnderDamage;  import gregtech.api.enchants.Enchantment_Radioactivity;  import gregtech.api.enums.*;  import gregtech.api.interfaces.internal.IGT_Mod; +import gregtech.api.objects.GT_ChunkManager;  import gregtech.api.objects.ItemData;  import gregtech.api.objects.XSTR;  import gregtech.api.util.*; @@ -269,6 +270,9 @@ public class GT_Mod implements IGT_Mod {          //GT_Values.oreveinMaxSize = tMainConfig.get(aTextGeneral, "oreveinMaxSize_64",64).getInt(64);          GT_Values.ticksBetweenSounds = tMainConfig.get("machines", "TicksBetweenSounds", 30).getInt(30);          GT_Values.cleanroomGlass= (float) tMainConfig.get("machines","ReinforcedGlassPercentageForCleanroom",5D).getDouble(5D); +        GT_Values.enableChunkloaders = tMainConfig.get("machines",  "enableChunkloaders", true).getBoolean(true); +        GT_Values.alwaysReloadChunkloaders = tMainConfig.get("machines",  "alwaysReloadChunkloaders", false).getBoolean(false); +        GT_Values.debugChunkloaders = tMainConfig.get("machines",  "debugChunkloaders", false).getBoolean(false);          GregTech_API.TICKS_FOR_LAG_AVERAGING = tMainConfig.get(aTextGeneral, "TicksForLagAveragingWithScanner", 25).getInt(25);          GregTech_API.MILLISECOND_THRESHOLD_UNTIL_LAG_WARNING = tMainConfig.get(aTextGeneral, "MillisecondsPassedInGTTileEntityUntilLagWarning", 100).getInt(100); @@ -1177,6 +1181,8 @@ public class GT_Mod implements IGT_Mod {                  tRunnable.run();              }          } catch (Throwable e) {e.printStackTrace(GT_Log.err);} +        if (GT_Values.debugChunkloaders) +            aEvent.registerServerCommand(new GT_ChunkManager.DebugCommand());      }      @Mod.EventHandler diff --git a/src/main/java/gregtech/api/enums/GT_Values.java b/src/main/java/gregtech/api/enums/GT_Values.java index c89d447d66..43c93450ab 100644 --- a/src/main/java/gregtech/api/enums/GT_Values.java +++ b/src/main/java/gregtech/api/enums/GT_Values.java @@ -183,9 +183,18 @@ public class GT_Values {       * This will prevent NEI from crashing but spams the Log.       */      public static boolean allow_broken_recipemap = false; -      /**       * This will set the percentage how much ReinforcedGlass is Allowed in Cleanroom Walls.       */      public static float cleanroomGlass = 5.0f; +    /** +     * This will let machines such as drills and pumps chunkload their work area. +     */ +    public static boolean enableChunkloaders = true; +    /** +     * This will make all chunkloading machines act as World Anchors (true) or Passive Anchors (false) +     */ +    public static boolean alwaysReloadChunkloaders = false; + +    public static boolean debugChunkloaders = false;  } diff --git a/src/main/java/gregtech/api/interfaces/IChunkLoader.java b/src/main/java/gregtech/api/interfaces/IChunkLoader.java new file mode 100644 index 0000000000..adba5e721e --- /dev/null +++ b/src/main/java/gregtech/api/interfaces/IChunkLoader.java @@ -0,0 +1,9 @@ +package gregtech.api.interfaces; + +import net.minecraft.world.ChunkCoordIntPair; + +// This interface is implemented by the machines that actively load a working chunk +public interface IChunkLoader { +    // return a working chunk coordinates, may be null +    ChunkCoordIntPair getActiveChunk(); +} diff --git a/src/main/java/gregtech/api/objects/GT_ChunkManager.java b/src/main/java/gregtech/api/objects/GT_ChunkManager.java new file mode 100644 index 0000000000..1ec8134777 --- /dev/null +++ b/src/main/java/gregtech/api/objects/GT_ChunkManager.java @@ -0,0 +1,184 @@ +package gregtech.api.objects; + +import com.google.common.collect.HashMultimap; +import cpw.mods.fml.common.eventhandler.EventPriority; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import gregtech.GT_Mod; +import gregtech.api.enums.GT_Values; +import gregtech.api.interfaces.IChunkLoader; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.util.GT_Log; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ListMultimap; +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommandSender; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeChunkManager; +import net.minecraftforge.common.ForgeChunkManager.Ticket; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.WorldEvent; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +// This class handles re-initializing chunks after a server restart +public class GT_ChunkManager implements ForgeChunkManager.OrderedLoadingCallback, ForgeChunkManager.PlayerOrderedLoadingCallback { +    private Map<TileEntity, Ticket> registeredTickets = new HashMap<>(); +    public static GT_ChunkManager instance = new GT_ChunkManager(); + +    public static void init() { +        ForgeChunkManager.setForcedChunkLoadingCallback(GT_Mod.instance, instance); +        //MinecraftForge.EVENT_BUS.register(instance); +    } + +    @Override +    public void ticketsLoaded(List<Ticket> tickets, World world) {} + +    // Determine if tickets should be kept.  Based on if the ticket is a machine or working chunk ticket. Working chunk tickets are tossed +    // and re-created when the machine re-activates.  Machine tickets are kept only if the config alwaysReloadChunkloaders is true. Otherwise +    // machine chunks are tossed and re-created only when the machine re-activates, similar to a Passive Anchor. +    @Override +    public List<Ticket> ticketsLoaded(List<Ticket> tickets, World world, int maxTicketCount) { +        List<Ticket> validTickets = new ArrayList<>(); +        if (GT_Values.alwaysReloadChunkloaders) { +            for (Ticket ticket : tickets) { +                int x = ticket.getModData().getInteger("OwnerX"); +                int y = ticket.getModData().getInteger("OwnerY"); +                int z = ticket.getModData().getInteger("OwnerZ"); +                if (y > 0) { +                    TileEntity tile = world.getTileEntity(x, y, z); +                    if (tile != null && tile instanceof IGregTechTileEntity && ((IGregTechTileEntity)tile).isAllowedToWork()) { +                        ForgeChunkManager.forceChunk(ticket, new ChunkCoordIntPair(x >> 4, z >> 4)); +                        if (!registeredTickets.containsKey(tile)) { +                            registeredTickets.put(tile, ticket); +                            if (((IGregTechTileEntity)tile).getMetaTileEntity() instanceof IChunkLoader) +                                ForgeChunkManager.forceChunk(ticket, ((IChunkLoader)((IGregTechTileEntity)tile).getMetaTileEntity()).getActiveChunk()); +                            validTickets.add(ticket); +                        } +                    } +                } +            } +        } +        return validTickets ; +    } + +    // Determine if player tickets should be kept.  This is where a ticket list per player would be created and maintained. When +    // a player join event occurs, their name/UUID/whatevs is compared against tickets on this list and those tickets reactivated. +    // Since that info would be maintained/dealt with on a per-player startup, the list returned back to Forge is empty. +    @Override +    public ListMultimap<String, Ticket> playerTicketsLoaded(ListMultimap<String, Ticket> tickets, World world) { +        // Not currently used, so just return an empty list. +        return ArrayListMultimap.create(); +    } + +    // Request a chunk to be loaded for this machine +    // may pass null chunk to load just the machine itself, if "alwaysReloadChunkloaders" is enabled in config +    static public boolean requestPlayerChunkLoad(TileEntity owner, ChunkCoordIntPair chunkXZ, String player) { +        if (!GT_Values.enableChunkloaders) +            return false; +        if (!GT_Values.alwaysReloadChunkloaders && chunkXZ == null) +            return false; +        if (GT_Values.debugChunkloaders && chunkXZ != null) +            GT_Log.out.println("GT_ChunkManager: Chunk request: (" + chunkXZ.chunkXPos + ", " + chunkXZ.chunkZPos + ")"); +        if (instance.registeredTickets.containsKey(owner)) { +            ForgeChunkManager.forceChunk(instance.registeredTickets.get(owner), chunkXZ); +        } else { +            Ticket ticket = null; +            if (player != "") +                ticket = ForgeChunkManager.requestPlayerTicket(GT_Mod.instance, player, owner.getWorldObj(), ForgeChunkManager.Type.NORMAL); +            else +                ticket = ForgeChunkManager.requestTicket(GT_Mod.instance, owner.getWorldObj(), ForgeChunkManager.Type.NORMAL); +            if (ticket == null) { +                if (GT_Values.debugChunkloaders) +                    GT_Log.out.println("GT_ChunkManager: ForgeChunkManager.requestTicket failed"); +                return false; +            } +            if (GT_Values.debugChunkloaders) +                GT_Log.out.println("GT_ChunkManager: ticket issued for machine at: (" + owner.xCoord + ", " + owner.yCoord + ", " + owner.zCoord + ")" ); +            NBTTagCompound tag = ticket.getModData(); +            tag.setInteger("OwnerX", owner.xCoord); +            tag.setInteger("OwnerY", owner.yCoord); +            tag.setInteger("OwnerZ", owner.zCoord); +            ForgeChunkManager.forceChunk(ticket, chunkXZ); +            if (GT_Values.alwaysReloadChunkloaders) +                ForgeChunkManager.forceChunk(ticket, new ChunkCoordIntPair(owner.xCoord << 4, owner.zCoord << 4)); +            instance.registeredTickets.put(owner, ticket); +        } +        return true; +    } + +    static public boolean requestChunkLoad(TileEntity owner, ChunkCoordIntPair chunkXZ) { +        return requestPlayerChunkLoad(owner, chunkXZ, ""); +    } + +    static public void releaseChunk(TileEntity owner, ChunkCoordIntPair chunkXZ) { +        if (!GT_Values.enableChunkloaders) +            return; +        Ticket ticket = instance.registeredTickets.get(owner); +        if (ticket != null) { +            if (GT_Values.debugChunkloaders) +                GT_Log.out.println("GT_ChunkManager: Chunk release: (" + chunkXZ.chunkXPos + ", " + chunkXZ.chunkZPos + ")"); +            ForgeChunkManager.unforceChunk(ticket, chunkXZ); +        } +    } + +    static public void releaseTicket(TileEntity owner) { +        if (!GT_Values.enableChunkloaders) +            return; +        Ticket ticket = instance.registeredTickets.get(owner); +        if (ticket != null) { +            if (GT_Values.debugChunkloaders) { +                GT_Log.out.println("GT_ChunkManager: ticket released by machine at: (" + owner.xCoord + ", " + owner.yCoord + ", " + owner.zCoord + ")" ); +                for (ChunkCoordIntPair chunk : ticket.getChunkList()) +                    GT_Log.out.println("GT_ChunkManager: Chunk release: (" + chunk.chunkXPos + ", " + chunk.chunkZPos + ")"); +            } +            ForgeChunkManager.releaseTicket(ticket); +            instance.registeredTickets.remove(owner); +        } +    } + +    public static void printTickets() { +        if (!GT_Values.debugChunkloaders) +            return; +        GT_Log.out.println("GT_ChunkManager: Start forced chunks dump:"); +        instance.registeredTickets.forEach((machine, ticket) -> { +            GT_Log.out.print("GT_ChunkManager: Chunks forced by the machine at (" + machine.xCoord + ", " + machine.yCoord + ", " + machine.zCoord + ")"); +            if (ticket.isPlayerTicket()) +                GT_Log.out.print(" Owner: " + ticket.getPlayerName()); +            GT_Log.out.print(" :"); +            for (ChunkCoordIntPair c : ticket.getChunkList()) { +                GT_Log.out.print("("); +                GT_Log.out.print(c.chunkXPos); +                GT_Log.out.print(", "); +                GT_Log.out.print(c.chunkZPos); +                GT_Log.out.print("), "); +            } +        }); +        GT_Log.out.println("GT_ChunkManager: End forced chunks dump:"); +    } +    public static class DebugCommand extends CommandBase { +        @Override +        public String getCommandName() { +            return "gt5u:dump_chunks"; +        } +        @Override +        public int getRequiredPermissionLevel() { +            return 0; +        } +        @Override +        public String getCommandUsage(ICommandSender sender) { +            return "/" + getCommandName(); +        } +        @Override +        public void processCommand(ICommandSender sender, String[] args) { +            printTickets(); +        } +    } +} diff --git a/src/main/java/gregtech/common/GT_Proxy.java b/src/main/java/gregtech/common/GT_Proxy.java index 20fec0b8c5..6ac8264dee 100644 --- a/src/main/java/gregtech/common/GT_Proxy.java +++ b/src/main/java/gregtech/common/GT_Proxy.java @@ -9,6 +9,7 @@ import cpw.mods.fml.common.network.IGuiHandler;  import cpw.mods.fml.common.network.NetworkRegistry;  import cpw.mods.fml.common.registry.GameRegistry;  import forestry.api.genetics.AlleleManager; +import gregtech.GT_Mod;  import gregtech.api.GregTech_API;  import gregtech.api.enums.*;  import gregtech.api.enums.TC_Aspects.TC_AspectStack; @@ -25,6 +26,7 @@ import gregtech.api.objects.GT_Fluid;  import gregtech.api.objects.GT_FluidStack;  import gregtech.api.objects.GT_UO_DimensionList;  import gregtech.api.objects.ItemData; +import gregtech.api.objects.GT_ChunkManager;  import gregtech.api.util.*;  import gregtech.common.entities.GT_Entity_Arrow;  import gregtech.common.gui.GT_ContainerVolumetricFlask; @@ -60,6 +62,7 @@ import net.minecraft.world.World;  import net.minecraft.world.WorldSettings.GameType;  import net.minecraft.world.gen.feature.WorldGenMinable;  import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.ForgeChunkManager;  import net.minecraftforge.event.ForgeEventFactory;  import net.minecraftforge.event.entity.EntityJoinWorldEvent;  import net.minecraftforge.event.entity.living.EnderTeleportEvent; @@ -499,6 +502,9 @@ public abstract class GT_Proxy implements IGT_Mod, IGuiHandler, IFuelHandler {          RecipeSorter.register("gregtech:shaped", GT_Shaped_Recipe.class, RecipeSorter.Category.SHAPED, "after:minecraft:shaped before:minecraft:shapeless");          RecipeSorter.register("gregtech:shapeless", GT_Shapeless_Recipe.class, RecipeSorter.Category.SHAPELESS, "after:minecraft:shapeless"); +         +        // Register chunk manager with Forge +        GT_ChunkManager.init();      }      public void onLoad() { diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java index 52ec86e2cc..4a8bddbd39 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java +++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java @@ -11,13 +11,17 @@ import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;  import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_DataAccess;  import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy;  import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase; +import gregtech.api.objects.GT_ChunkManager;  import gregtech.api.objects.GT_RenderedTexture;  import gregtech.api.util.GT_ModHandler;  import gregtech.api.util.GT_Utility;  import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer;  import net.minecraft.init.Blocks;  import net.minecraft.item.ItemStack;  import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.ChunkCoordIntPair;  import net.minecraftforge.common.util.FakePlayer;  import net.minecraftforge.common.util.ForgeDirection; @@ -43,6 +47,10 @@ public abstract class GT_MetaTileEntity_DrillerBase extends GT_MetaTileEntity_Mu      protected int workState;      protected static final int STATE_DOWNWARD = 0, STATE_AT_BOTTOM = 1, STATE_UPWARD = 2; +    protected boolean mChunkLoadingEnabled = true; +    protected ChunkCoordIntPair mCurrentChunk = null; +    protected boolean mWorkChunkNeedsReload = true; +      public GT_MetaTileEntity_DrillerBase(int aID, String aName, String aNameRegional) {          super(aID, aName, aNameRegional);          initFields(); @@ -72,13 +80,51 @@ public abstract class GT_MetaTileEntity_DrillerBase extends GT_MetaTileEntity_Mu      public void saveNBTData(NBTTagCompound aNBT) {          super.saveNBTData(aNBT);          aNBT.setInteger("workState", workState); +        aNBT.setBoolean("chunkLoadingEnabled", mChunkLoadingEnabled); +        aNBT.setBoolean("isChunkloading", mCurrentChunk != null); +        if (mCurrentChunk != null) { +            aNBT.setInteger("loadedChunkXPos", mCurrentChunk.chunkXPos); +            aNBT.setInteger("loadedChunkZPos", mCurrentChunk.chunkZPos); +        }      }      @Override      public void loadNBTData(NBTTagCompound aNBT) {          super.loadNBTData(aNBT);          workState = aNBT.getInteger("workState"); -        if (aNBT.hasKey("isPickingPipes")) workState = aNBT.getBoolean("isPickingPipes") ? STATE_UPWARD : STATE_DOWNWARD; +        if (aNBT.hasKey("isPickingPipes")) +            workState = aNBT.getBoolean("isPickingPipes") ? STATE_UPWARD : STATE_DOWNWARD; +        if (aNBT.hasKey("chunkLoadingEnabled")) +            mChunkLoadingEnabled = aNBT.getBoolean("chunkLoadingEnabled"); +        if (aNBT.getBoolean("isChunkloading")) { +            mCurrentChunk = new ChunkCoordIntPair(aNBT.getInteger("loadedChunkXPos"), aNBT.getInteger("loadedChunkZPos")); +        } +    } + +    @Override +    public boolean onSolderingToolRightClick(byte aSide, byte aWrenchingSide, EntityPlayer aPlayer, float aX, float aY, float aZ) { +        if (aSide == getBaseMetaTileEntity().getFrontFacing()) { +            mChunkLoadingEnabled = !mChunkLoadingEnabled; +            GT_Utility.sendChatToPlayer(aPlayer, mChunkLoadingEnabled ? trans("502", "Mining chunk loading enabled") : trans("503", "Mining chunk loading disabled")); +        } +        return super.onSolderingToolRightClick(aSide, aWrenchingSide, aPlayer, aX, aY, aZ); +    } + +    @Override +    public void onRemoval() { +        if (mChunkLoadingEnabled) +            GT_ChunkManager.releaseTicket((TileEntity)getBaseMetaTileEntity()); +        super.onRemoval(); +    } + +    @Override +    public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { +        super.onPostTick(aBaseMetaTileEntity, aTick); +        if (aBaseMetaTileEntity.isServerSide() && mCurrentChunk != null && !mWorkChunkNeedsReload && !aBaseMetaTileEntity.isAllowedToWork()) { +            // if machine has stopped, stop chunkloading +            GT_ChunkManager.releaseTicket((TileEntity)aBaseMetaTileEntity); +            mWorkChunkNeedsReload = true; +        }      }      protected boolean tryPickPipe() { @@ -413,5 +459,4 @@ public abstract class GT_MetaTileEntity_DrillerBase extends GT_MetaTileEntity_Mu          }          return false;      } -  } diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillBase.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillBase.java index 109bcf91c3..9f3e03b99c 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillBase.java +++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillBase.java @@ -47,7 +47,8 @@ public abstract class GT_MetaTileEntity_OilDrillBase extends GT_MetaTileEntity_D      public void loadNBTData(NBTTagCompound aNBT) {          super.loadNBTData(aNBT);          mOilId = aNBT.getInteger("mOilId"); -        chunkRangeConfig = aNBT.getInteger("chunkRangeConfig"); +        if (aNBT.hasKey("chunkRangeConfig")) +            chunkRangeConfig = aNBT.getInteger("chunkRangeConfig");      }      protected String[] getDescriptionInternal(String tierSuffix) { diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlantBase.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlantBase.java index c7255e0e74..5a384f66ed 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlantBase.java +++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlantBase.java @@ -4,7 +4,9 @@ import gregtech.api.enums.ItemList;  import gregtech.api.enums.Materials;  import gregtech.api.enums.OrePrefixes;  import gregtech.api.gui.GT_GUIContainer_MultiMachine; +import gregtech.api.interfaces.IChunkLoader;  import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.objects.GT_ChunkManager;  import gregtech.api.objects.ItemData;  import gregtech.api.util.GT_OreDictUnificator;  import gregtech.api.util.GT_Recipe; @@ -18,6 +20,7 @@ import net.minecraft.init.Blocks;  import net.minecraft.item.ItemStack;  import net.minecraft.nbt.NBTTagCompound;  import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.ChunkCoordIntPair;  import net.minecraft.world.ChunkPosition;  import net.minecraftforge.fluids.FluidStack; @@ -28,11 +31,9 @@ import java.util.HashSet;  import static gregtech.api.enums.GT_Values.VN; -public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTileEntity_DrillerBase { - +public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTileEntity_DrillerBase implements IChunkLoader {      private final ArrayList<ChunkPosition> oreBlockPositions = new ArrayList<>(); -    protected int mTier=1; - +    protected int mTier = 1;      private int chunkRadiusConfig = getRadiusInChunks();      GT_MetaTileEntity_OreDrillingPlantBase(int aID, String aName, String aNameRegional) { @@ -52,10 +53,14 @@ public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTile      @Override      public void loadNBTData(NBTTagCompound aNBT) {          super.loadNBTData(aNBT); -        chunkRadiusConfig = aNBT.getInteger("chunkRadiusConfig"); +        if (aNBT.hasKey("chunkRadiusConfig")) +            chunkRadiusConfig = aNBT.getInteger("chunkRadiusConfig");      }      @Override +    public ChunkCoordIntPair getActiveChunk(){return mCurrentChunk;} + +    @Override      public Object getClientGUI(int aID, InventoryPlayer aPlayerInventory, IGregTechTileEntity aBaseMetaTileEntity) {          return new GT_GUIContainer_MultiMachine(aPlayerInventory, aBaseMetaTileEntity, getLocalName(), "OreDrillingPlant.png");      } @@ -81,8 +86,14 @@ public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTile      @Override      protected boolean workingDownward(ItemStack aStack, int xDrill, int yDrill, int zDrill, int xPipe, int zPipe, int yHead, int oldYHead) { +        if (mChunkLoadingEnabled) +            return super.workingDownward(aStack, xDrill, yDrill, zDrill, xPipe, zPipe, yHead, oldYHead);          if (yHead != oldYHead) oreBlockPositions.clear(); +        if (mWorkChunkNeedsReload && mChunkLoadingEnabled) { // ask to load machine itself +            GT_ChunkManager.requestChunkLoad((TileEntity) getBaseMetaTileEntity(), null); +            mWorkChunkNeedsReload = false; +        }          fillMineListIfEmpty(xDrill, yDrill, zDrill, xPipe, zPipe, yHead);          if (oreBlockPositions.isEmpty()) {              switch (tryLowerPipeState()) { @@ -93,7 +104,9 @@ public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTile              //new layer - fill again              fillMineListIfEmpty(xDrill, yDrill, zDrill, xPipe, zPipe, yHead);          } - +        return processOreList(); +    } +    private boolean processOreList(){          ChunkPosition oreBlockPos = null;          Block oreBlock = null; @@ -112,10 +125,72 @@ public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTile              getBaseMetaTileEntity().getWorld().setBlockToAir(oreBlockPos.chunkPosX, oreBlockPos.chunkPosY, oreBlockPos.chunkPosZ);              mOutputItems = getOutputByDrops(oreBlockDrops);          } -          return true;      } +    @Override +    protected boolean workingAtBottom(ItemStack aStack, int xDrill, int yDrill, int zDrill, int xPipe, int zPipe, int yHead, int oldYHead) { +        if (!mChunkLoadingEnabled || chunkRadiusConfig == 1) +            return super.workingAtBottom(aStack, xDrill, yDrill, zDrill, xPipe, zPipe, yHead, oldYHead); + +        if (mCurrentChunk == null) { +            createInitialWorkingChunk(xDrill, zDrill); +            return true; +        } + +        if (mWorkChunkNeedsReload) { +            GT_ChunkManager.requestChunkLoad((TileEntity)getBaseMetaTileEntity(), mCurrentChunk); +            mWorkChunkNeedsReload = false; +            return true; +        } +        if (oreBlockPositions.isEmpty()){ +            fillChunkMineList(yHead, yDrill); +            if (oreBlockPositions.isEmpty()) { +                GT_ChunkManager.releaseChunk((TileEntity)getBaseMetaTileEntity(), mCurrentChunk); +                if (!moveToNextChunk(xDrill >> 4, zDrill >> 4)) +                    workState = STATE_UPWARD; +                return true; +            } +        } +        return processOreList(); +    } +    private void createInitialWorkingChunk(int xDrill, int zDrill) { +        final int centerX = xDrill >> 4; +        final int centerZ = zDrill >> 4; +        mCurrentChunk = new ChunkCoordIntPair(centerX - chunkRadiusConfig + 1, centerZ - chunkRadiusConfig + 1); +        GT_ChunkManager.requestChunkLoad((TileEntity)getBaseMetaTileEntity(), mCurrentChunk); +        mWorkChunkNeedsReload = false; +    } + +    @Override +    protected boolean workingUpward(ItemStack aStack, int xDrill, int yDrill, int zDrill, int xPipe, int zPipe, int yHead, int oldYHead) { +        if (!mChunkLoadingEnabled || chunkRadiusConfig == 1 || oreBlockPositions.isEmpty()) +            return super.workingUpward(aStack, xDrill, yDrill, zDrill, xPipe, zPipe, yHead, oldYHead); +        boolean result = processOreList(); +        if (oreBlockPositions.isEmpty()) +            GT_ChunkManager.releaseTicket((TileEntity)getBaseMetaTileEntity()); +        return result; +    } +    private boolean moveToNextChunk(int centerX, int centerZ){ +        if (mCurrentChunk == null) +            return false; +        int nextChunkX = mCurrentChunk.chunkXPos + 1; +        int nextChunkZ = mCurrentChunk.chunkZPos; +        if (nextChunkX >= (centerX + chunkRadiusConfig)){ +            nextChunkX = centerX - chunkRadiusConfig + 1; +            ++nextChunkZ; +        } +        if (nextChunkZ >= (centerZ + chunkRadiusConfig)) { +            mCurrentChunk = null; +            return false; +        } +        // skip center chunk - dug in workingDownward() +        if (nextChunkX == centerX && nextChunkZ == centerZ) +            ++nextChunkX; +        mCurrentChunk = new ChunkCoordIntPair(nextChunkX, nextChunkZ); +        GT_ChunkManager.requestChunkLoad((TileEntity)getBaseMetaTileEntity(), new ChunkCoordIntPair(nextChunkX, nextChunkZ)); +        return true; +    }      @Override      protected boolean checkHatches(){          return !mMaintenanceHatches.isEmpty() && !mInputHatches.isEmpty() && !mOutputBusses.isEmpty() && !mEnergyHatches.isEmpty(); @@ -127,7 +202,7 @@ public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTile          this.mEfficiencyIncrease = 10000;          int tier = Math.max(1, GT_Utility.getTier(getMaxInputVoltage()));          this.mEUt = -3 * (1 << (tier << 1)); -        this.mMaxProgresstime = (workState == STATE_DOWNWARD ? getBaseProgressTime() : 80) / (1 <<tier); +        this.mMaxProgresstime = ((workState == STATE_DOWNWARD || workState == STATE_AT_BOTTOM) ? getBaseProgressTime() : 80) / (1 <<tier);          this.mMaxProgresstime = Math.max(1, this.mMaxProgresstime);      } @@ -184,6 +259,19 @@ public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTile          return true;      } +    private void fillChunkMineList(int yHead, int yDrill) { +        if (mCurrentChunk == null || !oreBlockPositions.isEmpty()) +            return; +        final int minX = mCurrentChunk.chunkXPos << 4; +        final int maxX = minX + 16; +        final int minZ = mCurrentChunk.chunkZPos << 4; +        final int maxZ = minZ + 16; +        for (int x = minX; x < maxX; ++x) +            for (int z = minZ; z < maxZ; ++z) +                for (int y = yHead; y < yDrill; ++y) +                    tryAddOreBlockToMineList(x, y, z); +    } +      private void fillMineListIfEmpty(int xDrill, int yDrill, int zDrill, int xPipe, int zPipe, int yHead) {          if (!oreBlockPositions.isEmpty())              return; @@ -192,11 +280,18 @@ public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTile          if (yHead == yDrill)              return; //skip controller block layer -        int radius = Math.min(Math.max(chunkRadiusConfig, 1), getRadiusInChunks()) << 4; - -        for (int xOff = -radius; xOff <= radius; xOff++) -            for (int zOff = -radius; zOff <= radius; zOff++) -                tryAddOreBlockToMineList(xDrill + xOff, yHead, zDrill + zOff); +        if (mChunkLoadingEnabled) { +            int startX = (xDrill >> 4) << 4; +            int startZ = (zDrill >> 4) << 4; +            for (int x = startX; x < (startX + 16); ++x) +                for (int z = startZ; z < (startZ + 16); ++z) +                    tryAddOreBlockToMineList(x, yHead, z); +        } else { +            int radius = chunkRadiusConfig << 4; +            for (int xOff = -radius; xOff <= radius; xOff++) +                for (int zOff = -radius; zOff <= radius; zOff++) +                    tryAddOreBlockToMineList(xDrill + xOff, yHead, zDrill + zOff); +        }      }      private void tryAddOreBlockToMineList(int x, int y, int z) { @@ -237,4 +332,4 @@ public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTile                  "Maximum radius is " + (getRadiusInChunks() << 4) + " blocks",                  "Fortune bonus of " + (mTier + 3)};      } -}
\ No newline at end of file +} | 
