DimDoors/StevenDimDoors/mod_pocketDim/saving/DDSaveHandler.java

321 lines
9.1 KiB
Java

package StevenDimDoors.mod_pocketDim.saving;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import net.minecraftforge.common.DimensionManager;
import StevenDimDoors.mod_pocketDim.Point3D;
import StevenDimDoors.mod_pocketDim.core.DimLink;
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
import StevenDimDoors.mod_pocketDim.core.NewDimData;
import StevenDimDoors.mod_pocketDim.core.PocketManager;
import StevenDimDoors.mod_pocketDim.dungeon.DungeonData;
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.FileFilters;
import StevenDimDoors.mod_pocketDim.util.Point4D;
import com.google.common.io.Files;
public class DDSaveHandler
{
public static boolean loadAll()
{
// SenseiKiwi: Loading up our save data is not as simple as just reading files.
// To properly restore dimensions, we need to make sure we always load
// a dimension's parent and root before trying to load it. We'll use
// topological sorting to determine the order in which to recreate the
// dimension objects such that we respect those dependencies.
// Links must be loaded after instantiating all the dimensions and must
// be checked against our dimension blacklist.
// 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.
String basePath = DimensionManager.getCurrentSaveRootDirectory() + "/DimensionalDoors/data/";
File dataDirectory = new File(basePath);
// Check if the folder exists. If it doesn't, just return.
if (!dataDirectory.exists())
{
return true;
}
// Load the dimension blacklist
File blacklistFile = new File(basePath+"blacklist.txt");
if(blacklistFile.exists())
{
BlacklistProcessor blacklistReader = new BlacklistProcessor();
List<Integer> blacklist = readBlacklist(blacklistFile,blacklistReader);
PocketManager.createAndRegisterBlacklist(blacklist);
}
// List any dimension data files and read each dimension
DimDataProcessor reader = new DimDataProcessor();
List<PackedDimData> packedDims = new ArrayList<PackedDimData>();
FileFilter dataFileFilter = new FileFilters.RegexFileFilter("dim_-?\\d+\\.txt");
File[] dataFiles = dataDirectory.listFiles(dataFileFilter);
for (File dataFile : dataFiles)
{
PackedDimData packedDim = readDimension(dataFile, reader);
packedDims.add(packedDim);
}
List<PackedLinkData> linksToUnpack = new ArrayList<PackedLinkData>();
//get the grand list of all links to unpack
for(PackedDimData packedDim : packedDims)
{
linksToUnpack.addAll(packedDim.Links);
}
return unpackDimData(packedDims)&&unpackLinkData(linksToUnpack);
}
/**
* Takes a list of packedDimData and rebuilds the DimData for it
* @param packedDims
* @return
*/
public static boolean unpackDimData(List<PackedDimData> packedDims)
{
List<PackedDimData> unpackedDims = new ArrayList<PackedDimData>();
//Load roots
for(PackedDimData packedDim : packedDims)
{
if(packedDim.ParentID==packedDim.ID)
{
PocketManager.registerPackedDimData(packedDim);
unpackedDims.add(packedDim);
}
}
packedDims.removeAll(unpackedDims);
unpackedDims.clear();
//Load the pockets
while(!packedDims.isEmpty())
{
for(PackedDimData packedDim : packedDims)
{
if(PocketManager.isRegisteredInternally(packedDim.ParentID))
{
PocketManager.registerPackedDimData(packedDim);
unpackedDims.add(packedDim);
}
else
{
//break here gracefully
}
}
packedDims.removeAll(unpackedDims);
unpackedDims.clear();
}
return true;
}
public static boolean unpackLinkData(List<PackedLinkData> linksToUnpack)
{
Point3D fakePoint = new Point3D(-1,-1,-1);
List<PackedLinkData> unpackedLinks = new ArrayList<PackedLinkData>();
/**
* sort through the list, unpacking links that do not have parents.
*/
//TODO- what we have a loop of links?
for(PackedLinkData packedLink : linksToUnpack)
{
if(packedLink.parent.equals(fakePoint))
{
NewDimData data = PocketManager.getDimensionData(packedLink.source.getDimension());
int linkType = packedLink.tail.linkType;
if((linkType < LinkTypes.ENUM_MIN || linkType > LinkTypes.ENUM_MAX) && linkType != LinkTypes.CLIENT_SIDE)
{
linkType = LinkTypes.NORMAL;
}
@SuppressWarnings("deprecation")
DimLink link = data.createLink(packedLink.source, linkType, packedLink.orientation);
Point4D destination = packedLink.tail.destination;
if(destination!=null)
{
PocketManager.getDimensionData(destination.getDimension()).setDestination(link, destination.getX(),destination.getY(),destination.getZ());
}
unpackedLinks.add(packedLink);
}
}
linksToUnpack.removeAll(unpackedLinks);
//unpack remaining children
while(!linksToUnpack.isEmpty())
{
for(PackedLinkData packedLink : linksToUnpack)
{
NewDimData data = PocketManager.getDimensionData(packedLink.source.getDimension());
if(data.getLink(packedLink.parent)!=null)
{
data.createChildLink(packedLink.source.getX(), packedLink.source.getY(), packedLink.source.getZ(), data.getLink(packedLink.parent));
}
unpackedLinks.add(packedLink);
}
linksToUnpack.removeAll(unpackedLinks);
}
return true;
}
private static PackedDimData readDimension(File dataFile, DimDataProcessor reader)
{
try
{
return reader.readFromFile(dataFile);
}
catch (Exception e)
{
System.err.println("Could not read dimension data from: " + dataFile.getAbsolutePath());
System.err.println("The following error occurred:");
printException(e, false);
return null;
}
}
public static boolean saveAll(Iterable<? extends IPackable<PackedDimData>> dimensions, List<Integer> blacklist) throws IOException
{
// 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.
String basePath = DimensionManager.getCurrentSaveRootDirectory() + "/DimensionalDoors/data/";
File basePathFile = new File(basePath);
Files.createParentDirs(basePathFile);
basePathFile.mkdir();
BlacklistProcessor blacklistReader = new BlacklistProcessor();
writeBlacklist(blacklist, blacklistReader,basePath);
FileFilter dataFileFilter = new FileFilters.RegexFileFilter("dim_-?\\d+\\.txt");
//TODO Deal with temp files correctly
File[] dataFiles = basePathFile.listFiles(dataFileFilter);
for (File dataFile : dataFiles)
{
dataFile.delete();
}
basePathFile = null;
basePath += "dim_";
boolean succeeded = true;
DimDataProcessor writer = new DimDataProcessor();
for (IPackable<PackedDimData> dimension : dimensions)
{
succeeded &= writeDimension(dimension, writer, basePath);
}
return succeeded;
}
private static boolean writeBlacklist(List<Integer> blacklist, BlacklistProcessor writer, String basePath)
{
try
{
File tempFile = new File(basePath + "blacklist.tmp");
File saveFile = new File(basePath + "blacklist.txt");
writer.writeToFile(tempFile, blacklist);
saveFile.delete();
tempFile.renameTo(saveFile);
return true;
}
catch (Exception e)
{
System.err.println("Could not save blacklist. The following error occurred:");
printException(e, true);
return false;
}
}
private static boolean writeDimension(IPackable<PackedDimData> dimension, DimDataProcessor writer, String basePath)
{
try
{
File tempFile = new File(basePath + (dimension.name() + ".tmp"));
File saveFile = new File(basePath + (dimension.name() + ".txt"));
writer.writeToFile(tempFile, dimension.pack());
saveFile.delete();
tempFile.renameTo(saveFile);
return true;
}
catch (Exception e)
{
System.err.println("Could not save data for dimension #" + dimension.name() + ". The following error occurred:");
printException(e, true);
return false;
}
}
private static void printException(Exception e, boolean verbose)
{
if (e.getCause() == null)
{
if (verbose)
{
e.printStackTrace();
}
else
{
System.err.println(e.getMessage());
}
}
else
{
System.out.println(e.getMessage());
System.err.println("Caused by an underlying error:");
if (verbose)
{
e.getCause().printStackTrace();
}
else
{
System.err.println(e.getCause().getMessage());
}
}
}
//TODO - make this more robust
public static DungeonData unpackDungeonData(PackedDungeonData packedDungeon)
{
for(DungeonData data : DungeonHelper.instance().getRegisteredDungeons())
{
if(data.schematicName().equals(packedDungeon.SchematicName))
{
return data;
}
}
return null;
}
public static List<Integer> readBlacklist(File blacklistFile, BlacklistProcessor reader)
{
try
{
return reader.readFromFile(blacklistFile);
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
}