Fixed Bugs in Golden Dimensional Doors
1. We weren't giving old tickets to the doors that owned them. That would result in doors requesting new tickets and the old ones wouldn't be released. Each time a server rebooted, a new ticket would be created. Then Opis would report that many chunks were forcefully loaded in a pocket because it doesn't consider overlapping tickets. We now give doors their old tickets when they're reloaded and we release extra tickets referring to the same door. That will also deal with the excess tickets that already exist on servers. 2. Rewrote the logic for checking if a Golden Dimensional Door is allowed to force-load a pocket. We now check if the door is within the horizontal bounds of the pocket. This prevents the confusing scenario where someone places a door far away from the pocket but the only chunks affected are in the pocket. 3. Fixed the calculation for determining which chunks must be force-loaded to cover a pocket. This has the benefit that fewer chunks should need to be loaded. It should be enough to load 16 chunks. We previously loaded 25 chunks just to err on the side of caution. 4. Golden Dimensional Doors only try to initialize as chunk loaders once. We previously allowed them to keep trying every tick until they could get a ticket.
This commit is contained in:
parent
b2e086e7c1
commit
3d88e72ecb
4 changed files with 166 additions and 78 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<Ticket> 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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue