aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/gregtech/api')
-rw-r--r--src/main/java/gregtech/api/enums/GT_Values.java11
-rw-r--r--src/main/java/gregtech/api/interfaces/IChunkLoader.java9
-rw-r--r--src/main/java/gregtech/api/objects/GT_ChunkManager.java184
3 files changed, 203 insertions, 1 deletions
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();
+ }
+ }
+}