diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/IChunkLoader.java b/src/main/java/StevenDimDoors/mod_pocketDim/IChunkLoader.java index bbe989e..06f0059 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/IChunkLoader.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/IChunkLoader.java @@ -4,5 +4,6 @@ import net.minecraftforge.common.ForgeChunkManager.Ticket; public interface IChunkLoader { - public void forceChunkLoading(Ticket ticket,int x, int z); + public boolean isInitialized(); + public void initialize(Ticket ticket); } diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/helpers/ChunkLoaderHelper.java b/src/main/java/StevenDimDoors/mod_pocketDim/helpers/ChunkLoaderHelper.java index 06d22d5..e866ec4 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/helpers/ChunkLoaderHelper.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/helpers/ChunkLoaderHelper.java @@ -1,54 +1,98 @@ package StevenDimDoors.mod_pocketDim.helpers; -import StevenDimDoors.mod_pocketDim.IChunkLoader; -import StevenDimDoors.mod_pocketDim.mod_pocketDim; -import StevenDimDoors.mod_pocketDim.core.NewDimData; -import StevenDimDoors.mod_pocketDim.core.PocketManager; - -import cpw.mods.fml.common.event.FMLServerStartingEvent; - import java.io.File; import java.util.List; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.World; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.ForgeChunkManager; import net.minecraftforge.common.ForgeChunkManager.LoadingCallback; import net.minecraftforge.common.ForgeChunkManager.Ticket; +import net.minecraftforge.common.ForgeChunkManager.Type; +import StevenDimDoors.experimental.BoundingBox; +import StevenDimDoors.mod_pocketDim.IChunkLoader; +import StevenDimDoors.mod_pocketDim.Point3D; +import StevenDimDoors.mod_pocketDim.mod_pocketDim; +import StevenDimDoors.mod_pocketDim.core.NewDimData; +import StevenDimDoors.mod_pocketDim.core.PocketManager; +import StevenDimDoors.mod_pocketDim.world.PocketBuilder; +import cpw.mods.fml.common.event.FMLServerStartingEvent; public class ChunkLoaderHelper implements LoadingCallback { - @Override public void ticketsLoaded(List tickets, World world) { for (Ticket ticket : tickets) { - int goldDimDoorX = ticket.getModData().getInteger("goldDimDoorX"); - int goldDimDoorY = ticket.getModData().getInteger("goldDimDoorY"); - int goldDimDoorZ = ticket.getModData().getInteger("goldDimDoorZ"); - if(world.getBlockId(goldDimDoorX, goldDimDoorY, goldDimDoorZ) != mod_pocketDim.properties.GoldenDimensionalDoorID) + boolean loaded = false; + int x = ticket.getModData().getInteger("goldDimDoorX"); + int y = ticket.getModData().getInteger("goldDimDoorY"); + int z = ticket.getModData().getInteger("goldDimDoorZ"); + + if (world.getBlockId(x, y, z) == mod_pocketDim.properties.GoldenDimensionalDoorID) + { + IChunkLoader loader = (IChunkLoader) world.getBlockTileEntity(x, y, z); + if (!loader.isInitialized()) + { + loader.initialize(ticket); + loaded = true; + } + } + if (!loaded) { ForgeChunkManager.releaseTicket(ticket); } - else + } + } + + public static Ticket createTicket(int x, int y, int z, World world) + { + NBTTagCompound data; + Ticket ticket = ForgeChunkManager.requestTicket(mod_pocketDim.instance, world, Type.NORMAL); + if (ticket != null) + { + data = ticket.getModData(); + data.setInteger("goldDimDoorX", x); + data.setInteger("goldDimDoorY", y); + data.setInteger("goldDimDoorZ", z); + } + return ticket; + } + + public static void forcePocketChunks(NewDimData pocket, Ticket ticket) + { + BoundingBox bounds = PocketBuilder.calculateDefaultBounds(pocket); + Point3D minCorner = bounds.minCorner(); + Point3D maxCorner = bounds.maxCorner(); + int minX = minCorner.getX() >> 4; + int minZ = minCorner.getZ() >> 4; + int maxX = maxCorner.getX() >> 4; + int maxZ = maxCorner.getZ() >> 4; + int chunkX; + int chunkZ; + + for (chunkX = minX; chunkX <= maxX; chunkX++) + { + for (chunkZ = minZ; chunkZ <= maxZ; chunkZ++) { - IChunkLoader tile = (IChunkLoader) world.getBlockTileEntity(goldDimDoorX, goldDimDoorY, goldDimDoorZ); - tile.forceChunkLoading(ticket,goldDimDoorX,goldDimDoorZ); - } + ForgeChunkManager.forceChunk(ticket, new ChunkCoordIntPair(chunkX, chunkZ)); + } } } public static void loadChunkForcedWorlds(FMLServerStartingEvent event) { - for(NewDimData data : PocketManager.getDimensions()) + for (NewDimData data : PocketManager.getDimensions()) { if(data.isPocketDimension()) { String chunkDir = DimensionManager.getCurrentSaveRootDirectory()+"/DimensionalDoors/pocketDimID" + data.id(); - + File file = new File(chunkDir); - + if(file.exists()) { if(ForgeChunkManager.savedWorldHasForcedChunkTickets(file)) diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/tileentities/TileEntityDimDoorGold.java b/src/main/java/StevenDimDoors/mod_pocketDim/tileentities/TileEntityDimDoorGold.java index 7dc1c64..093c1e8 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/tileentities/TileEntityDimDoorGold.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/tileentities/TileEntityDimDoorGold.java @@ -1,85 +1,93 @@ package StevenDimDoors.mod_pocketDim.tileentities; -import net.minecraft.world.ChunkCoordIntPair; import net.minecraftforge.common.ForgeChunkManager; import net.minecraftforge.common.ForgeChunkManager.Ticket; -import net.minecraftforge.common.ForgeChunkManager.Type; import StevenDimDoors.mod_pocketDim.IChunkLoader; -import StevenDimDoors.mod_pocketDim.mod_pocketDim; +import StevenDimDoors.mod_pocketDim.core.NewDimData; import StevenDimDoors.mod_pocketDim.core.PocketManager; -import StevenDimDoors.mod_pocketDim.util.Point4D; +import StevenDimDoors.mod_pocketDim.helpers.ChunkLoaderHelper; import StevenDimDoors.mod_pocketDim.world.PocketBuilder; public class TileEntityDimDoorGold extends TileEntityDimDoor implements IChunkLoader { private Ticket chunkTicket; + private boolean initialized = false; @Override public boolean canUpdate() { - return true; + return !initialized; + } + + @Override + public boolean isInitialized() + { + return initialized; } @Override public void updateEntity() - { // every tick? - if (PocketManager.getDimensionData(this.worldObj) != null && - PocketManager.getDimensionData(this.worldObj).isPocketDimension() && - !this.worldObj.isRemote) - { - if(PocketManager.getLink(this.xCoord,this.yCoord,this.zCoord,this.worldObj)==null) + { + if (!initialized) + { + initialize(null); + } + } + + @Override + public void initialize(Ticket ticket) + { + initialized = true; + chunkTicket = ticket; + + // Only do anything if this function is running on the server side + // NOTE: We don't have to check whether this block is the upper door + // block or the lower one because only one of them should have a + // link associated with it. + if (!worldObj.isRemote) + { + NewDimData dimension = PocketManager.getDimensionData(worldObj); + + // Check whether a ticket has already been assigned to this door + if (chunkTicket == null) { - return; - } - if (this.chunkTicket == null) - { - chunkTicket = ForgeChunkManager.requestTicket(mod_pocketDim.instance, worldObj, Type.NORMAL); - if(chunkTicket == null) + // No ticket yet. + // Check if this area should be loaded and request a new ticket. + if (isValidChunkLoaderSetup(dimension)) { - return; + chunkTicket = ChunkLoaderHelper.createTicket(xCoord, yCoord, zCoord, worldObj); } - chunkTicket.getModData().setInteger("goldDimDoorX", xCoord); - chunkTicket.getModData().setInteger("goldDimDoorY", yCoord); - chunkTicket.getModData().setInteger("goldDimDoorZ", zCoord); - forceChunkLoading(chunkTicket,this.xCoord,this.zCoord); + } + else + { + // A ticket has already been provided. + // Check if this area should be loaded. If not, release the ticket. + if (!isValidChunkLoaderSetup(dimension)) + { + ForgeChunkManager.releaseTicket(chunkTicket); + chunkTicket = null; + } + } + + // If chunkTicket isn't null at this point, then this is a valid door setup. + // The last step is to request force loading of the pocket's chunks. + if (chunkTicket != null) + { + ChunkLoaderHelper.forcePocketChunks(dimension, chunkTicket); } } } - - @Override - public void forceChunkLoading(Ticket chunkTicket,int x,int z) + + private boolean isValidChunkLoaderSetup(NewDimData dimension) { - Point4D origin = PocketManager.getDimensionData(this.worldObj).origin(); - int orientation = PocketManager.getDimensionData(this.worldObj).orientation(); + // Check the various conditions that make this a valid door setup. + // 1. The door must be inside the pocket's XZ boundaries, + // to prevent loading of chunks with a distant door + // 2. The dimension must be a pocket dimension + // 3. The door must be linked so that it's clear that it's not a normal door - int xOffset=0; - int zOffset=0; - - switch(orientation) - { - case 0: - xOffset = PocketBuilder.DEFAULT_POCKET_SIZE/2; - break; - case 1: - zOffset = PocketBuilder.DEFAULT_POCKET_SIZE/2; - - break; - case 2: - xOffset = -PocketBuilder.DEFAULT_POCKET_SIZE/2; - - break; - case 3: - zOffset = -PocketBuilder.DEFAULT_POCKET_SIZE/2; - - break; - } - for(int chunkX = -2; chunkX<3;chunkX++) - { - for(int chunkZ = -2; chunkZ<3;chunkZ++) - { - ForgeChunkManager.forceChunk(chunkTicket, new ChunkCoordIntPair((origin.getX()+xOffset >> 4)+chunkX, (origin.getZ()+zOffset >> 4)+chunkZ)); - } - } + return (dimension.isPocketDimension() && dimension.getLink(xCoord, yCoord, zCoord) != null && + PocketBuilder.calculateDefaultBounds(dimension).contains(xCoord, yCoord, zCoord)); } @Override diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java b/src/main/java/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java index 15ddecc..515fbee 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java @@ -8,7 +8,7 @@ import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraftforge.common.DimensionManager; -import StevenDimDoors.experimental.MazeBuilder; +import StevenDimDoors.experimental.BoundingBox; import StevenDimDoors.mod_pocketDim.Point3D; import StevenDimDoors.mod_pocketDim.blocks.IDimDoor; import StevenDimDoors.mod_pocketDim.config.DDProperties; @@ -21,13 +21,13 @@ import StevenDimDoors.mod_pocketDim.dungeon.DungeonSchematic; import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonPackConfig; import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper; import StevenDimDoors.mod_pocketDim.helpers.yCoordHelper; +import StevenDimDoors.mod_pocketDim.items.ItemDimensionalDoor; import StevenDimDoors.mod_pocketDim.schematic.BlockRotator; import StevenDimDoors.mod_pocketDim.util.Pair; import StevenDimDoors.mod_pocketDim.util.Point4D; -import StevenDimDoors.mod_pocketDim.items.ItemDimensionalDoor; public class PocketBuilder -{ +{ public static final int MIN_POCKET_SIZE = 5; public static final int MAX_POCKET_SIZE = 51; public static final int DEFAULT_POCKET_SIZE = 39; @@ -559,4 +559,39 @@ public class PocketBuilder extBlockStorage.setExtBlockMetadata(localX, y & 15, localZ, metadata); chunk.setChunkModified(); } + + public static BoundingBox calculateDefaultBounds(NewDimData pocket) + { + // Calculate the XZ bounds of this pocket assuming that it has the default size + // The Y bounds will be set to encompass the height of a chunk. + + int minX = 0; + int minZ = 0; + Point4D origin = pocket.origin(); + int orientation = pocket.orientation(); + if (orientation < 0 || orientation > 3) + { + throw new IllegalArgumentException("pocket has an invalid orientation value."); + } + switch (orientation) + { + case 0: + minX = origin.getX() - DEFAULT_POCKET_WALL_THICKNESS + 1; + minZ = origin.getZ() - DEFAULT_POCKET_SIZE / 2; + break; + case 1: + minX = origin.getX() - DEFAULT_POCKET_SIZE / 2; + minZ = origin.getZ() - DEFAULT_POCKET_WALL_THICKNESS + 1; + break; + case 2: + minX = origin.getX() + DEFAULT_POCKET_WALL_THICKNESS - DEFAULT_POCKET_SIZE; + minZ = origin.getZ() - DEFAULT_POCKET_SIZE / 2; + break; + case 3: + minX = origin.getX() - DEFAULT_POCKET_SIZE / 2; + minZ = origin.getZ() + DEFAULT_POCKET_WALL_THICKNESS - DEFAULT_POCKET_SIZE; + break; + } + return new BoundingBox(minX, 0, minZ, DEFAULT_POCKET_SIZE, 255, DEFAULT_POCKET_SIZE); + } }