package net.minecraft.world.storage; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.StartupQuery; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.server.MinecraftServer; import net.minecraft.world.MinecraftException; import net.minecraft.world.WorldProvider; import net.minecraft.world.chunk.storage.IChunkLoader; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class SaveHandler implements ISaveHandler, IPlayerFileData { private static final Logger logger = LogManager.getLogger(); /** The directory in which to save world data. */ private final File worldDirectory; /** The directory in which to save player data. */ private final File playersDirectory; private final File mapDataDir; /** The time in milliseconds when this field was initialized. Stored in the session lock file. */ private final long initializationTime = MinecraftServer.getCurrentTimeMillis(); /** The directory name of the world */ private final String saveDirectoryName; private static final String __OBFID = "CL_00000585"; public SaveHandler(File p_i2146_1_, String p_i2146_2_, boolean p_i2146_3_) { this.worldDirectory = new File(p_i2146_1_, p_i2146_2_); this.worldDirectory.mkdirs(); this.playersDirectory = new File(this.worldDirectory, "playerdata"); this.mapDataDir = new File(this.worldDirectory, "data"); this.mapDataDir.mkdirs(); this.saveDirectoryName = p_i2146_2_; if (p_i2146_3_) { this.playersDirectory.mkdirs(); } this.setSessionLock(); } /** * Creates a session lock file for this process */ private void setSessionLock() { try { File file1 = new File(this.worldDirectory, "session.lock"); DataOutputStream dataoutputstream = new DataOutputStream(new FileOutputStream(file1)); try { dataoutputstream.writeLong(this.initializationTime); } finally { dataoutputstream.close(); } } catch (IOException ioexception) { ioexception.printStackTrace(); throw new RuntimeException("Failed to check session lock, aborting"); } } /** * Gets the File object corresponding to the base directory of this world. */ public File getWorldDirectory() { return this.worldDirectory; } /** * Checks the session lock to prevent save collisions */ public void checkSessionLock() throws MinecraftException { try { File file1 = new File(this.worldDirectory, "session.lock"); DataInputStream datainputstream = new DataInputStream(new FileInputStream(file1)); try { if (datainputstream.readLong() != this.initializationTime) { throw new MinecraftException("The save is being accessed from another location, aborting"); } } finally { datainputstream.close(); } } catch (IOException ioexception) { throw new MinecraftException("Failed to check session lock, aborting"); } } /** * initializes and returns the chunk loader for the specified world provider */ public IChunkLoader getChunkLoader(WorldProvider p_75763_1_) { throw new RuntimeException("Old Chunk Storage is no longer supported."); } /** * Loads and returns the world info */ public WorldInfo loadWorldInfo() { File file1 = new File(this.worldDirectory, "level.dat"); NBTTagCompound nbttagcompound; NBTTagCompound nbttagcompound1; WorldInfo worldInfo = null; if (file1.exists()) { try { nbttagcompound = CompressedStreamTools.readCompressed(new FileInputStream(file1)); nbttagcompound1 = nbttagcompound.getCompoundTag("Data"); worldInfo = new WorldInfo(nbttagcompound1); FMLCommonHandler.instance().handleWorldDataLoad(this, worldInfo, nbttagcompound); return worldInfo; } catch (StartupQuery.AbortedException e) { throw e; } catch (Exception exception1) { exception1.printStackTrace(); } } FMLCommonHandler.instance().confirmBackupLevelDatUse(this); file1 = new File(this.worldDirectory, "level.dat_old"); if (file1.exists()) { try { nbttagcompound = CompressedStreamTools.readCompressed(new FileInputStream(file1)); nbttagcompound1 = nbttagcompound.getCompoundTag("Data"); worldInfo = new WorldInfo(nbttagcompound1); FMLCommonHandler.instance().handleWorldDataLoad(this, worldInfo, nbttagcompound); return worldInfo; } catch (StartupQuery.AbortedException e) { throw e; } catch (Exception exception) { exception.printStackTrace(); } } return null; } /** * Saves the given World Info with the given NBTTagCompound as the Player. */ public void saveWorldInfoWithPlayer(WorldInfo p_75755_1_, NBTTagCompound p_75755_2_) { NBTTagCompound nbttagcompound1 = p_75755_1_.cloneNBTCompound(p_75755_2_); NBTTagCompound nbttagcompound2 = new NBTTagCompound(); nbttagcompound2.setTag("Data", nbttagcompound1); FMLCommonHandler.instance().handleWorldDataSave(this, p_75755_1_, nbttagcompound2); try { File file1 = new File(this.worldDirectory, "level.dat_new"); File file2 = new File(this.worldDirectory, "level.dat_old"); File file3 = new File(this.worldDirectory, "level.dat"); CompressedStreamTools.writeCompressed(nbttagcompound2, new FileOutputStream(file1)); if (file2.exists()) { file2.delete(); } file3.renameTo(file2); if (file3.exists()) { file3.delete(); } file1.renameTo(file3); if (file1.exists()) { file1.delete(); } } catch (Exception exception) { exception.printStackTrace(); } } /** * used to update level.dat from old format to MCRegion format */ public void saveWorldInfo(WorldInfo p_75761_1_) { NBTTagCompound nbttagcompound = p_75761_1_.getNBTTagCompound(); NBTTagCompound nbttagcompound1 = new NBTTagCompound(); nbttagcompound1.setTag("Data", nbttagcompound); FMLCommonHandler.instance().handleWorldDataSave(this, p_75761_1_, nbttagcompound1); try { File file1 = new File(this.worldDirectory, "level.dat_new"); File file2 = new File(this.worldDirectory, "level.dat_old"); File file3 = new File(this.worldDirectory, "level.dat"); CompressedStreamTools.writeCompressed(nbttagcompound1, new FileOutputStream(file1)); if (file2.exists()) { file2.delete(); } file3.renameTo(file2); if (file3.exists()) { file3.delete(); } file1.renameTo(file3); if (file1.exists()) { file1.delete(); } } catch (Exception exception) { exception.printStackTrace(); } } /** * Writes the player data to disk from the specified PlayerEntityMP. */ public void writePlayerData(EntityPlayer p_75753_1_) { try { NBTTagCompound nbttagcompound = new NBTTagCompound(); p_75753_1_.writeToNBT(nbttagcompound); File file1 = new File(this.playersDirectory, p_75753_1_.getUniqueID().toString() + ".dat.tmp"); File file2 = new File(this.playersDirectory, p_75753_1_.getUniqueID().toString() + ".dat"); CompressedStreamTools.writeCompressed(nbttagcompound, new FileOutputStream(file1)); if (file2.exists()) { file2.delete(); } file1.renameTo(file2); net.minecraftforge.event.ForgeEventFactory.firePlayerSavingEvent(p_75753_1_, this.playersDirectory, p_75753_1_.getUniqueID().toString()); } catch (Exception exception) { logger.warn("Failed to save player data for " + p_75753_1_.getCommandSenderName()); } } /** * Reads the player data from disk into the specified PlayerEntityMP. */ public NBTTagCompound readPlayerData(EntityPlayer p_75752_1_) { NBTTagCompound nbttagcompound = null; try { File file1 = new File(this.playersDirectory, p_75752_1_.getUniqueID().toString() + ".dat"); if (file1.exists() && file1.isFile()) { nbttagcompound = CompressedStreamTools.readCompressed(new FileInputStream(file1)); } } catch (Exception exception) { logger.warn("Failed to load player data for " + p_75752_1_.getCommandSenderName()); } if (nbttagcompound != null) { p_75752_1_.readFromNBT(nbttagcompound); } net.minecraftforge.event.ForgeEventFactory.firePlayerLoadingEvent(p_75752_1_, playersDirectory, p_75752_1_.getUniqueID().toString()); return nbttagcompound; } public IPlayerFileData getPlayerNBTManager() { return this; } /** * Returns an array of usernames for which player.dat exists for. */ public String[] getAvailablePlayerDat() { String[] astring = this.playersDirectory.list(); for (int i = 0; i < astring.length; ++i) { if (astring[i].endsWith(".dat")) { astring[i] = astring[i].substring(0, astring[i].length() - 4); } } return astring; } /** * Called to flush all changes to disk, waiting for them to complete. */ public void flush() {} /** * Gets the file location of the given map */ public File getMapFileFromName(String p_75758_1_) { return new File(this.mapDataDir, p_75758_1_ + ".dat"); } /** * Returns the name of the directory where world information is saved. */ public String getWorldDirectoryName() { return this.saveDirectoryName; } public NBTTagCompound getPlayerNBT(EntityPlayerMP player) { try { File file1 = new File(this.playersDirectory, player.getUniqueID().toString() + ".dat"); if (file1.exists() && file1.isFile()) { return CompressedStreamTools.readCompressed(new FileInputStream(file1)); } } catch (Exception exception) { logger.warn("Failed to load player data for " + player.getCommandSenderName()); } return null; } }