From fb1713ae0e665acc2a48611db1a99548949c6f26 Mon Sep 17 00:00:00 2001 From: SenseiKiwi Date: Sat, 12 Jul 2014 03:36:56 -0400 Subject: [PATCH 1/3] Improvements to TileEntityRift Made some improvements to TileEntityRift. The main reason for these changes was to remove the field nearestRift - we should not hold on to references to links. Now we simply track the location of the nearest rift. I also confirmed that closeRift() and updateNearestRift() must be allowed to run on both the client and the server. If the client doesn't run those functions, then adjacent rifts don't connect as expected and the rift removal animation doesn't work. --- .../tileentities/TileEntityRift.java | 77 ++++++++++--------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/tileentities/TileEntityRift.java b/src/main/java/StevenDimDoors/mod_pocketDim/tileentities/TileEntityRift.java index 13f9f96..62bb62b 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/tileentities/TileEntityRift.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/tileentities/TileEntityRift.java @@ -1,6 +1,5 @@ package StevenDimDoors.mod_pocketDim.tileentities; -import java.util.ArrayList; import java.util.List; import java.util.Random; @@ -42,8 +41,7 @@ public class TileEntityRift extends DDTileEntityBase public int yOffset = 0; public int zOffset = 0; public boolean shouldClose = false; - - public DimLink nearestRiftData; + public Point4D nearestRiftLocation = null; public int spawnedEndermenID = 0; public TileEntityRift() @@ -64,20 +62,20 @@ public class TileEntityRift extends DDTileEntityBase } else { - this.invalidate(); + invalidate(); } return; } if (worldObj.getBlockId(xCoord, yCoord, zCoord) != mod_pocketDim.blockRift.blockID) { - this.invalidate(); + invalidate(); return; } // Check if this rift should render white closing particles and // spread the closing effect to other rifts nearby. - if (this.shouldClose) + if (shouldClose) { closeRift(); return; @@ -85,13 +83,13 @@ public class TileEntityRift extends DDTileEntityBase if (updateTimer >= UPDATE_PERIOD) { - this.spawnEndermen(mod_pocketDim.properties); + spawnEndermen(mod_pocketDim.properties); updateTimer = 0; } else if (updateTimer == UPDATE_PERIOD / 2) { - this.calculateParticleOffsets(); - this.spread(mod_pocketDim.properties); + updateNearestRift(); + spread(mod_pocketDim.properties); } updateTimer++; } @@ -136,57 +134,60 @@ public class TileEntityRift extends DDTileEntityBase } } } - - public boolean updateNearestRift() - { - nearestRiftData = PocketManager.getDimensionData(worldObj).findNearestRift(this.worldObj, 5, xCoord, yCoord, zCoord); - return (nearestRiftData != null); - } private void closeRift() { NewDimData dimension = PocketManager.getDimensionData(worldObj); if (closeTimer == CLOSING_PERIOD / 2) { - ArrayList riftLinks = dimension.findRiftsInRange(worldObj, 6, xCoord, yCoord, zCoord); - if (riftLinks.size() > 0) + for (DimLink riftLink : dimension.findRiftsInRange(worldObj, 6, xCoord, yCoord, zCoord)) { - for (DimLink riftLink : riftLinks) + Point4D location = riftLink.source(); + TileEntityRift rift = (TileEntityRift) worldObj.getBlockTileEntity(location.getX(), location.getY(), location.getZ()); + if (rift != null && !rift.shouldClose) { - Point4D location = riftLink.source(); - TileEntityRift rift = (TileEntityRift) worldObj.getBlockTileEntity(location.getX(), location.getY(), location.getZ()); - if (rift != null) - { - rift.shouldClose = true; - rift.onInventoryChanged(); - } + rift.shouldClose = true; + rift.onInventoryChanged(); } } } if (closeTimer >= CLOSING_PERIOD) { - if (!this.worldObj.isRemote) + DimLink link = PocketManager.getLink(this.xCoord, this.yCoord, this.zCoord, worldObj); + if (link != null) { - DimLink link = PocketManager.getLink(this.xCoord, this.yCoord, this.zCoord, worldObj); - if (link != null) - { - dimension.deleteLink(link); - } + dimension.deleteLink(link); } worldObj.setBlockToAir(xCoord, yCoord, zCoord); worldObj.playSound(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5, "mods.DimDoors.sfx.riftClose", 0.7f, 1, false); } closeTimer++; } - - private void calculateParticleOffsets() + + public boolean updateNearestRift() { - if (updateNearestRift()) + Point4D previousNearest = nearestRiftLocation; + DimLink nearestRiftLink = PocketManager.getDimensionData(worldObj).findNearestRift( + worldObj, RIFT_INTERACTION_RANGE, xCoord, yCoord, zCoord); + + nearestRiftLocation = (nearestRiftLink == null) ? null : nearestRiftLink.source(); + + // If the nearest rift location changed, then update particle offsets + if (previousNearest != nearestRiftLocation && + (previousNearest == null || nearestRiftLocation == null || !previousNearest.equals(nearestRiftLocation))) { - Point4D location = nearestRiftData.source(); - this.xOffset = this.xCoord - location.getX(); - this.yOffset = this.yCoord - location.getY(); - this.zOffset = this.zCoord - location.getZ(); + updateParticleOffsets(); + } + return (nearestRiftLocation != null); + } + + private void updateParticleOffsets() + { + if (nearestRiftLocation != null) + { + this.xOffset = this.xCoord - nearestRiftLocation.getX(); + this.yOffset = this.yCoord - nearestRiftLocation.getY(); + this.zOffset = this.zCoord - nearestRiftLocation.getZ(); } else { -- 2.39.5 From b20a0a74d2e2c14cdba06885ed73df06cb7b6c9e Mon Sep 17 00:00:00 2001 From: SenseiKiwi Date: Sun, 13 Jul 2014 07:17:30 -0400 Subject: [PATCH 2/3] Minor Change Autocorrected indentation in PocketManager. I'll be working on changing PocketManager to prevent the risk of creating data for a non-existent dimension through a bad call to getDimensionData(). --- .../mod_pocketDim/core/PocketManager.java | 128 +++++++++--------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/core/PocketManager.java b/src/main/java/StevenDimDoors/mod_pocketDim/core/PocketManager.java index 1939e1d..a509c38 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/core/PocketManager.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/core/PocketManager.java @@ -49,17 +49,17 @@ public class PocketManager // that any link destinations must be real dimensions controlled by PocketManager. public InnerDimData(int id, InnerDimData parent, boolean isPocket, boolean isDungeon, - IUpdateWatcher linkWatcher) + IUpdateWatcher linkWatcher) { super(id, parent, isPocket, isDungeon, linkWatcher); } - + public InnerDimData(int id, InnerDimData root) { // This constructor is meant for client-side code only super(id, root); } - + public void clear() { // If this dimension has a parent, remove it from its parent's list of children @@ -103,7 +103,7 @@ public class PocketManager ArrayList Links = new ArrayList(); ArrayList Tails = new ArrayList(); PackedDungeonData packedDungeon=null; - + if(this.dungeon!=null) { packedDungeon= new PackedDungeonData(dungeon.weight(), dungeon.isOpen(), dungeon.isInternal(), @@ -123,22 +123,22 @@ public class PocketManager { parentPoint=link.parent.link.point.toPoint3D(); } - + for(DimLink childLink : link.children) { children.add(childLink.source().toPoint3D()); } PackedLinkTail tail = new PackedLinkTail(link.tail.getDestination(),link.tail.getLinkType()); Links.add(new PackedLinkData(link.link.point,parentPoint,tail,link.link.orientation,children)); - + PackedLinkTail tempTail = new PackedLinkTail(link.tail.getDestination(),link.tail.getLinkType()); if(Tails.contains(tempTail)) { Tails.add(tempTail); } - - + + } int parentID=this.id; Point3D originPoint=new Point3D(0,0,0); @@ -151,30 +151,30 @@ public class PocketManager originPoint=this.origin.toPoint3D(); } return new PackedDimData(this.id, depth, this.packDepth, parentID, this.root().id(), orientation, - isDungeon, isFilled,packedDungeon, originPoint, ChildIDs, Links, Tails); + isDungeon, isFilled,packedDungeon, originPoint, ChildIDs, Links, Tails); // FIXME: IMPLEMENTATION PLZTHX //I tried } } - - private static class ClientLinkWatcher implements IUpdateWatcher - { - @Override - public void onCreated(ClientLinkData link) - { - Point4D source = link.point; - NewDimData dimension = getDimensionData(source.getDimension()); - dimension.createLink(source.getX(), source.getY(), source.getZ(), LinkTypes.CLIENT_SIDE,link.orientation); - } - @Override - public void onDeleted(ClientLinkData link) - { - Point4D source = link.point; - getDimensionData(source.getDimension()).deleteLink(source); - } - } - + private static class ClientLinkWatcher implements IUpdateWatcher + { + @Override + public void onCreated(ClientLinkData link) + { + Point4D source = link.point; + NewDimData dimension = getDimensionData(source.getDimension()); + dimension.createLink(source.getX(), source.getY(), source.getZ(), LinkTypes.CLIENT_SIDE,link.orientation); + } + + @Override + public void onDeleted(ClientLinkData link) + { + Point4D source = link.point; + getDimensionData(source.getDimension()).deleteLink(source); + } + } + private static class ClientDimWatcher implements IUpdateWatcher { @Override @@ -196,14 +196,14 @@ public class PocketManager // having to instantiate a bunch of data containers and without exposing an "unsafe" // creation method for anyone to call. Integrity protection for the win! It's like // exposing a private constructor ONLY to a very specific trusted class. - + @Override public NewDimData registerDimension(int dimensionID, int rootID) { return registerClientDimension(dimensionID, rootID); } } - + private static int OVERWORLD_DIMENSION_ID = 0; private static volatile boolean isLoading = false; @@ -242,11 +242,11 @@ public class PocketManager return; } isLoading = true; - + dimensionData = new HashMap(); rootDimensions = new ArrayList(); dimensionIDBlackList = new ArrayList(); - + if(FMLCommonHandler.instance().getEffectiveSide().isClient()) { //Shouldnt try to load everything if we are a client @@ -258,19 +258,19 @@ public class PocketManager //Register Limbo DDProperties properties = DDProperties.instance(); registerDimension(properties.LimboDimensionID, null, false, false); - + loadInternal(); - + //Register pocket dimensions registerPockets(properties); - + isLoaded = true; isLoading = false; } - + public static boolean registerPackedDimData(PackedDimData packedData) { - + InnerDimData dimData; //register roots if(packedData.ID==packedData.ParentID) @@ -291,7 +291,7 @@ public class PocketManager dimData.isFilled=packedData.IsFilled; dimData.origin = new Point4D(packedData.Origin.getX(),packedData.Origin.getY(),packedData.Origin.getZ(),packedData.ID); dimData.root=PocketManager.getDimensionData(packedData.RootID); - + if(packedData.DungeonData!=null) { dimData.dungeon=DDSaveHandler.unpackDungeonData(packedData.DungeonData); @@ -303,7 +303,7 @@ public class PocketManager return true; } - + public static boolean deletePocket(NewDimData target, boolean deleteFolder) { // We can't delete the dimension if it's currently loaded or if it's not actually a pocket. @@ -327,7 +327,7 @@ public class PocketManager } return false; } - + private static void deleteDimensionFiles(InnerDimData dimension) { // We assume that the caller checks if the dimension is loaded, for the @@ -339,7 +339,7 @@ public class PocketManager File dataFile = new File(saveRootPath + "/DimensionalDoors/data/dim_" + dimension.id() + ".txt"); dataFile.delete(); } - + private static void deleteDimensionData(InnerDimData dimension) { // We assume that the caller checks if the dimension is loaded, for the @@ -357,7 +357,7 @@ public class PocketManager throw new IllegalArgumentException("The specified dimension is not listed with PocketManager."); } } - + private static void registerPockets(DDProperties properties) { for (NewDimData dimension : dimensionData.values()) @@ -427,7 +427,7 @@ public class PocketManager { System.out.println("Importing old DD save data..."); OldSaveImporter.importOldSave(oldSaveData); - + oldSaveData.renameTo(new File(oldSaveData.getAbsolutePath()+"_IMPORTED")); System.out.println("Import Succesful!"); @@ -440,7 +440,7 @@ public class PocketManager } return; } - + // Load save data System.out.println("Loading Dimensional Doors save data..."); if (DDSaveHandler.loadAll()) @@ -449,7 +449,7 @@ public class PocketManager } } } - + public static void save(boolean checkModified) { if (!isLoaded) @@ -462,7 +462,7 @@ public class PocketManager return; } isSaving = true; - + try { DDSaveHandler.saveAll(dimensionData.values(), dimensionIDBlackList, checkModified); @@ -479,14 +479,14 @@ public class PocketManager isSaving = false; } } - + public static WorldServer loadDimension(int id) { if (!DimensionManager.isDimensionRegistered(id)) { return null; } - + WorldServer world = DimensionManager.getWorld(id); if (world == null) { @@ -512,7 +512,7 @@ public class PocketManager { throw new IllegalArgumentException("parent cannot be null. A pocket dimension must always have a parent dimension."); } - + DDProperties properties = DDProperties.instance(); int dimensionID = DimensionManager.getNextFreeDimId(); DimensionManager.registerDimension(dimensionID, properties.PocketProviderID); @@ -543,10 +543,10 @@ public class PocketManager rootDimensions.add(dimension); } getDimwatcher().onCreated(new ClientDimData(dimension)); - + return dimension; } - + @SideOnly(Side.CLIENT) private static NewDimData registerClientDimension(int dimensionID, int rootID) { @@ -556,7 +556,7 @@ public class PocketManager // SenseiKiwi: I'm a little worried about how getDimensionData will raise // an event when it creates any root dimensions... Needs checking later. - + InnerDimData root = (InnerDimData) getDimensionData(rootID); InnerDimData dimension; @@ -577,12 +577,12 @@ public class PocketManager { //Im registering pocket dims here. I *think* we can assume that if its a pocket and we are //registering its dim data, we also need to register it with forge. - + //New packet stuff prevents this from always being true, unfortuantly. I send the dimdata to the client when they teleport. //Steven DimensionManager.registerDimension(dimensionID, mod_pocketDim.properties.PocketProviderID); } - return dimension; + return dimension; } public static NewDimData getDimensionData(World world) @@ -597,7 +597,7 @@ public class PocketManager //and create a NewDimData instance for it. //Any pocket dimension must be listed with PocketManager to have a dimension ID //assigned, so it's safe to assume that any unknown dimensions don't belong to us. - + //FIXME: What's the point of this condition? Most calls to this function will crash anyway! ~SenseiKiwi if(PocketManager.dimensionData == null) { @@ -630,14 +630,14 @@ public class PocketManager { throw new IllegalStateException("Pocket dimensions have already been unloaded!"); } - + unregisterPockets(); dimensionData = null; rootDimensions = null; isLoaded = false; isConnected = false; } - + public static DimLink getLink(int x, int y, int z, World world) { return getLink(x, y, z, world.provider.dimensionId); @@ -647,7 +647,7 @@ public class PocketManager { return getLink(point.getX(), point.getY(), point.getZ(), point.getDimension()); } - + public static DimLink getLink(int x, int y, int z, int dimensionID) { NewDimData dimension = dimensionData.get(dimensionID); @@ -657,7 +657,7 @@ public class PocketManager } return null; } - + public static boolean isBlackListed(int dimensionID) { return PocketManager.dimensionIDBlackList.contains(dimensionID); @@ -670,12 +670,12 @@ public class PocketManager { return getDimwatcher().unregisterReceiver(watcher); } - + public static void registerLinkWatcher(IUpdateWatcher watcher) { linkWatcher.registerReceiver(watcher); } - + public static boolean unregisterLinkWatcher(IUpdateWatcher watcher) { return linkWatcher.unregisterReceiver(watcher); @@ -685,18 +685,18 @@ public class PocketManager { updateSource.registerWatchers(new ClientDimWatcher(), new ClientLinkWatcher()); } - + public static void writePacket(DataOutputStream output) throws IOException { // Write a very compact description of our dimensions and links to be sent to a client Compactor.write(dimensionData.values(), output); } - + public static boolean isRegisteredInternally(int dimensionID) { return dimensionData.containsKey(dimensionID); } - + public static void createAndRegisterBlacklist(List blacklist) { //TODO - create a special blacklist provider @@ -720,7 +720,7 @@ public class PocketManager // Load compacted client-side dimension data load(); Compactor.readDimensions(input, new DimRegistrationCallback()); - + isLoaded = true; isLoading = false; isConnected = true; -- 2.39.5 From 8544aa17eea214363bb441f86215a2080ab05c11 Mon Sep 17 00:00:00 2001 From: SenseiKiwi Date: Sun, 13 Jul 2014 14:22:23 -0400 Subject: [PATCH 3/3] Fixed Crash on World Creation Fixed an issue. DD would crash when MC created a completely new world because onChunkLoad() would be called before onWorldLoad(). That's not the usual order. PocketManager would be unloaded at that point and would return a null dimension. --- .../StevenDimDoors/mod_pocketDim/EventHookContainer.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/EventHookContainer.java b/src/main/java/StevenDimDoors/mod_pocketDim/EventHookContainer.java index 9fd2d41..e40d7c2 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/EventHookContainer.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/EventHookContainer.java @@ -230,8 +230,11 @@ public class EventHookContainer { // Schedule rift regeneration for any links located in this chunk. // This event runs on both the client and server. Allow server only. + // Also, check that PocketManager is loaded, because onChunkLoad() can + // fire while chunks are being initialized in a new world, before + // onWorldLoad() fires. Chunk chunk = event.getChunk(); - if (!chunk.worldObj.isRemote) + if (!chunk.worldObj.isRemote && PocketManager.isLoaded()) { NewDimData dimension = PocketManager.getDimensionData(chunk.worldObj); for (DimLink link : dimension.getChunkLinks(chunk.xPosition, chunk.zPosition)) -- 2.39.5