diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/EventHookContainer.java b/src/main/java/StevenDimDoors/mod_pocketDim/EventHookContainer.java index f241c24e..aa04337d 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/EventHookContainer.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/EventHookContainer.java @@ -185,7 +185,7 @@ public class EventHookContainer { if (event.world.provider.dimensionId == 0) { - PocketManager.save(); + PocketManager.save(true); if (mod_pocketDim.deathTracker != null && mod_pocketDim.deathTracker.isModified()) { diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/core/NewDimData.java b/src/main/java/StevenDimDoors/mod_pocketDim/core/NewDimData.java index ba977d58..22b783f1 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/core/NewDimData.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/core/NewDimData.java @@ -19,7 +19,7 @@ public abstract class NewDimData { private static class InnerDimLink extends DimLink { - public InnerDimLink(Point4D source, DimLink parent,int orientation) + public InnerDimLink(Point4D source, DimLink parent, int orientation) { super(new ClientLinkData(source, orientation), parent); } @@ -130,6 +130,7 @@ public abstract class NewDimData protected Point4D origin; protected int orientation; protected DungeonData dungeon; + protected boolean modified; public IUpdateWatcher linkWatcher; protected NewDimData(int id, NewDimData parent, boolean isPocket, boolean isDungeon, @@ -157,6 +158,7 @@ public abstract class NewDimData this.origin = null; this.dungeon = null; this.linkWatcher = linkWatcher; + this.modified = true; //Register with parent if (parent != null) @@ -165,6 +167,7 @@ public abstract class NewDimData this.root = parent.root; this.depth = parent.depth + 1; parent.children.add(this); + parent.modified = true; } else { @@ -288,27 +291,30 @@ public abstract class NewDimData { return Math.abs(i) + Math.abs(j) + Math.abs(k); } - public DimLink createLink(int x, int y, int z, int linkType,int orientation) + + public DimLink createLink(int x, int y, int z, int linkType, int orientation) { - return createLink(new Point4D(x, y, z, id), linkType,orientation); + return createLink(new Point4D(x, y, z, id), linkType, orientation); } - public DimLink createLink(Point4D source, int linkType,int orientation) + public DimLink createLink(Point4D source, int linkType, int orientation) { //Return an existing link if there is one to avoid creating multiple links starting at the same point. InnerDimLink link = linkMapping.get(source); if (link == null) { - link = new InnerDimLink(source, linkType,orientation); + link = new InnerDimLink(source, linkType, orientation); linkMapping.put(source, link); linkList.add(link); } else { - link.overwrite(linkType,orientation); + link.overwrite(linkType, orientation); } + modified = true; + //Link created! - if(linkType!=LinkTypes.CLIENT_SIDE) + if (linkType != LinkTypes.CLIENT_SIDE) { linkWatcher.onCreated(link.link); } @@ -348,6 +354,7 @@ public abstract class NewDimData linkWatcher.onCreated(link.link); } } + modified = true; return link; } @@ -364,6 +371,7 @@ public abstract class NewDimData //Raise deletion event linkWatcher.onDeleted(target.link); target.clear(); + modified = true; } return (target != null); } @@ -418,6 +426,7 @@ public abstract class NewDimData public void setFilled(boolean isFilled) { this.isFilled = isFilled; + this.modified = true; } public int id() @@ -499,16 +508,19 @@ public abstract class NewDimData this.orientation = orientation; this.dungeon = dungeon; this.packDepth = calculatePackDepth(parent, dungeon); + this.modified = true; } /** - * effectivly moves the dungeon to the 'top' of a chain as far as dungeon generation is concerend. + * Effectively moves the dungeon to the 'top' of a chain as far as dungeon generation is concerned. */ public void setParentToRoot() { - this.depth=1; - this.parent=this.root; + this.depth = 1; + this.parent = this.root; this.root.children.add(this); + this.root.modified = true; + this.modified = true; } public static int calculatePackDepth(NewDimData parent, DungeonData current) @@ -557,12 +569,14 @@ public abstract class NewDimData setDestination(incoming, originX, originY, originZ); this.origin = incoming.destination(); this.orientation = orientation; + this.modified = true; } public void setDestination(DimLink incoming, int x, int y, int z) { InnerDimLink link = (InnerDimLink) incoming; link.setDestination(x, y, z, this); + this.modified = true; } public DimLink getRandomLink() @@ -581,8 +595,18 @@ public abstract class NewDimData } } + public boolean isModified() + { + return modified; + } + + public void clearModified() + { + this.modified = false; + } + public String toString() { - return "DimID= "+this.id; + return "DimID= " + this.id; } } \ No newline at end of file diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/core/PocketManager.java b/src/main/java/StevenDimDoors/mod_pocketDim/core/PocketManager.java index 4d8a07af..2bf9f591 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/core/PocketManager.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/core/PocketManager.java @@ -446,17 +446,12 @@ public class PocketManager } } - public static void save() + public static void save(boolean checkModified) { if (!isLoaded) { return; } - World world = DimensionManager.getWorld(OVERWORLD_DIMENSION_ID); - if (world == null || world.isRemote || DimensionManager.getCurrentSaveRootDirectory() == null) - { - return; - } //Check this last to make sure we set the flag shortly after. if (isSaving) { @@ -466,7 +461,7 @@ public class PocketManager try { - DDSaveHandler.saveAll(dimensionData.values(), dimensionIDBlackList); + DDSaveHandler.saveAll(dimensionData.values(), dimensionIDBlackList, checkModified); } catch (Exception e) { @@ -627,7 +622,7 @@ public class PocketManager throw new IllegalStateException("Pocket dimensions have already been unloaded!"); } - save(); + save(false); unregisterPockets(); dimensionData = null; rootDimensions = null; diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/mod_pocketDim.java b/src/main/java/StevenDimDoors/mod_pocketDim/mod_pocketDim.java index 7d6a8003..529a0324 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/mod_pocketDim.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/mod_pocketDim.java @@ -63,6 +63,7 @@ import StevenDimDoors.mod_pocketDim.tileentities.TileEntityDimDoor; import StevenDimDoors.mod_pocketDim.tileentities.TileEntityDimDoorGold; import StevenDimDoors.mod_pocketDim.tileentities.TileEntityRift; import StevenDimDoors.mod_pocketDim.tileentities.TileEntityTransTrapdoor; +import StevenDimDoors.mod_pocketDim.util.DDLogger; import StevenDimDoors.mod_pocketDim.world.BiomeGenLimbo; import StevenDimDoors.mod_pocketDim.world.BiomeGenPocket; import StevenDimDoors.mod_pocketDim.world.DDBiomeGenBase; @@ -145,6 +146,9 @@ public class mod_pocketDim public static GatewayGenerator gatewayGenerator; public static DeathTracker deathTracker; + //TODO this is a temporary workaround for saving data + private String currrentSaveRootDirectory; + public static CreativeTabs dimDoorsCreativeTab = new CreativeTabs("dimDoorsCreativeTab") { @Override @@ -313,6 +317,7 @@ public class mod_pocketDim deathTracker.writeToFile(); deathTracker = null; worldProperties = null; + this.currrentSaveRootDirectory=null; } catch (Exception e) { @@ -323,13 +328,13 @@ public class mod_pocketDim @EventHandler public void onServerAboutToStart(FMLServerAboutToStartEvent event) { - final String saveRootDirectory = DimensionManager.getCurrentSaveRootDirectory().getAbsolutePath(); + currrentSaveRootDirectory = DimensionManager.getCurrentSaveRootDirectory().getAbsolutePath(); // Load the config file that's specific to this world - worldProperties = new DDWorldProperties(new File(saveRootDirectory + "/DimensionalDoors/DimDoorsWorld.cfg")); + worldProperties = new DDWorldProperties(new File(currrentSaveRootDirectory + "/DimensionalDoors/DimDoorsWorld.cfg")); // Initialize a new DeathTracker - deathTracker = new DeathTracker(saveRootDirectory + "/DimensionalDoors/data/deaths.txt"); + deathTracker = new DeathTracker(currrentSaveRootDirectory + "/DimensionalDoors/data/deaths.txt"); } @EventHandler @@ -361,6 +366,11 @@ public class mod_pocketDim } } + public String getCurrentSavePath() + { + return this.currrentSaveRootDirectory; + } + public static void sendChat(EntityPlayer player, String message) { ChatMessageComponent cmp = new ChatMessageComponent(); diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/saving/DDSaveHandler.java b/src/main/java/StevenDimDoors/mod_pocketDim/saving/DDSaveHandler.java index eed33b22..d8278be8 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/saving/DDSaveHandler.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/saving/DDSaveHandler.java @@ -15,6 +15,7 @@ import org.apache.commons.io.FileUtils; import net.minecraftforge.common.DimensionManager; import StevenDimDoors.mod_pocketDim.Point3D; +import StevenDimDoors.mod_pocketDim.mod_pocketDim; import StevenDimDoors.mod_pocketDim.core.DimLink; import StevenDimDoors.mod_pocketDim.core.LinkTypes; import StevenDimDoors.mod_pocketDim.core.NewDimData; @@ -24,6 +25,7 @@ import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonPack; import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonType; import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper; import StevenDimDoors.mod_pocketDim.util.ConfigurationProcessingException; +import StevenDimDoors.mod_pocketDim.util.DDLogger; import StevenDimDoors.mod_pocketDim.util.FileFilters; import StevenDimDoors.mod_pocketDim.util.Point4D; @@ -44,6 +46,8 @@ public class DDSaveHandler // Don't surround this code with try-catch. Our mod should crash if an error // occurs at this level, since it could lead to some nasty problems. + DDLogger.logger().startTimer("Loading data"); + String basePath = DimensionManager.getCurrentSaveRootDirectory() + "/DimensionalDoors/data/"; File dataDirectory = new File(basePath); @@ -65,7 +69,7 @@ public class DDSaveHandler // List any dimension data files and read each dimension DimDataProcessor reader = new DimDataProcessor(); - HashMap packedDims = new HashMap(); + HashMap packedDims = new HashMap(); FileFilter dataFileFilter = new FileFilters.RegexFileFilter("dim_-?\\d+\\.txt"); File[] dataFiles = dataDirectory.listFiles(dataFileFilter); @@ -77,6 +81,7 @@ public class DDSaveHandler throw new IllegalStateException("The DD data for "+dataFile.getName().replace(".txt", "")+" at "+dataFile.getPath()+" is corrupted. Please report this on the MCF or on the DD github issues tracker."); } packedDims.put(packedDim.ID,packedDim); + } List linksToUnpack = new ArrayList(); @@ -85,7 +90,7 @@ public class DDSaveHandler { linksToUnpack.addAll(packedDim.Links); } - return unpackDimData(packedDims)&&unpackLinkData(linksToUnpack); + return unpackDimData(packedDims) && unpackLinkData(linksToUnpack); } /** @@ -244,20 +249,19 @@ public class DDSaveHandler } } - public static boolean saveAll(Iterable> dimensions, List blacklist) throws IOException + public static boolean saveAll(Iterable> dimensions, + List blacklist, boolean checkModified) throws IOException { - long startTime = System.nanoTime(); - + DDLogger.startTimer("Saving data"); // Create the data directory for our dimensions // Don't catch exceptions here. If we can't create this folder, // the mod should crash to let the user know early on. // Get the save directory path - File saveDirectory = new File(DimensionManager.getCurrentSaveRootDirectory() + "/DimensionalDoors/data/"); + File saveDirectory = new File(mod_pocketDim.instance.getCurrentSavePath() + "/DimensionalDoors/data/"); File backupDir = new File(saveDirectory+"/backup"); String savePath = saveDirectory.getAbsolutePath(); - if(!saveDirectory.exists()) { // Create the save directory @@ -268,16 +272,28 @@ public class DDSaveHandler // Create and write the blackList writeBlacklist(blacklist, savePath); - // Write the dimension save data, and remove the ones we save from the mapping + // Write the dimension save data boolean succeeded = true; DimDataProcessor writer = new DimDataProcessor(); for (IPackable dimension : dimensions) { - succeeded &= writeDimension(dimension, writer, savePath + "/dim_",backupDir); + + // Check if the dimension should be saved + if (!checkModified || dimension.isModified()) + { + if (writeDimension(dimension, writer, savePath + "/dim_",backupDir)) + { + dimension.clearModified(); + } + else + { + succeeded = false; + } + } } - startTime = System.nanoTime()-startTime; - System.out.println("Saving took "+startTime/1000000000D+" seconds"); + DDLogger.stopTimer("Saving data"); + System.out.println(DDLogger.logger().printLog()); return succeeded; } diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/saving/IPackable.java b/src/main/java/StevenDimDoors/mod_pocketDim/saving/IPackable.java index 78908d8c..687ca08a 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/saving/IPackable.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/saving/IPackable.java @@ -4,4 +4,6 @@ public interface IPackable { public String name(); public T pack(); + public boolean isModified(); + public void clearModified(); } diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/util/DDLogger.java b/src/main/java/StevenDimDoors/mod_pocketDim/util/DDLogger.java new file mode 100644 index 00000000..6a929674 --- /dev/null +++ b/src/main/java/StevenDimDoors/mod_pocketDim/util/DDLogger.java @@ -0,0 +1,106 @@ +package StevenDimDoors.mod_pocketDim.util; + +import java.util.ArrayList; +import java.util.HashMap; + +public class DDLogger +{ + private static DDLogger instance; + private StringBuilder log; + private HashMap timers = new HashMap(); + + private DDLogger() + { + this.log = new StringBuilder(); + this.log.append("Logger started.\n"); + } + + private static DDLogger logger() + { + if( instance == null) + { + instance = new DDLogger(); + } + return instance; + } + + private class DDTimer + { + final String description; + Long startTime; + Long endTime; + boolean stopped = false; + + private DDTimer(String description) + { + this.description=description; + } + private DDTimer start() + { + this.startTime=System.nanoTime(); + return this; + } + private void stop(long endTime) + { + this.endTime=endTime; + if(!this.stopped) + { + this.stopped=true; + log.append(this.description+" took "+this.getDuration()+" seconds to execute.\n"); + } + } + /** + * @return the duration in seconds, returns -1 if it still running + */ + public double getDuration() + { + if(this.stopped) + { + return (this.endTime-this.startTime)/1000000000D; + } + return -1; + } + } + + /** + * Creates and starts a timer. + * + * @param description: The string used to identify the timer + * @return + */ + public static void startTimer(String description) + { + DDTimer timer = logger().new DDTimer(description); + logger().timers.put(description, timer); + timer.start(); + } + + /**Stops and records a timer to the log + * + * @param description + * @return + */ + public static double stopTimer(String description) + { + long endTime = System.nanoTime(); + DDTimer timer = logger().timers.get(description); + if(timer==null) + { + return -1; + } + timer.stop(endTime); + logger().timers.remove(description); + return timer.getDuration(); + } + + public String printLog() + { + return this.log.toString(); + } + + public void clearLog() + { + this.log = new StringBuilder(); + } + +} diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/util/Logger.java b/src/main/java/StevenDimDoors/mod_pocketDim/util/Logger.java deleted file mode 100644 index c544f05f..00000000 --- a/src/main/java/StevenDimDoors/mod_pocketDim/util/Logger.java +++ /dev/null @@ -1,12 +0,0 @@ -package StevenDimDoors.mod_pocketDim.util; - -public class Logger -{ - private static Logger instance; - - public Logger() - { - instance = this; - } - -}