001 package net.minecraft.world.chunk.storage; 002 003 import cpw.mods.fml.relauncher.Side; 004 import cpw.mods.fml.relauncher.SideOnly; 005 import java.io.DataInputStream; 006 import java.io.DataOutputStream; 007 import java.io.File; 008 import java.io.IOException; 009 import java.util.ArrayList; 010 import java.util.Collection; 011 import java.util.Collections; 012 import java.util.Iterator; 013 import java.util.List; 014 import net.minecraft.nbt.CompressedStreamTools; 015 import net.minecraft.nbt.NBTTagCompound; 016 import net.minecraft.util.IProgressUpdate; 017 import net.minecraft.util.MathHelper; 018 import net.minecraft.world.WorldType; 019 import net.minecraft.world.biome.BiomeGenBase; 020 import net.minecraft.world.biome.WorldChunkManager; 021 import net.minecraft.world.biome.WorldChunkManagerHell; 022 import net.minecraft.world.storage.ISaveHandler; 023 import net.minecraft.world.storage.SaveFormatComparator; 024 import net.minecraft.world.storage.SaveFormatOld; 025 import net.minecraft.world.storage.WorldInfo; 026 027 public class AnvilSaveConverter extends SaveFormatOld 028 { 029 public AnvilSaveConverter(File par1File) 030 { 031 super(par1File); 032 } 033 034 @SideOnly(Side.CLIENT) 035 public List getSaveList() 036 { 037 ArrayList var1 = new ArrayList(); 038 File[] var2 = this.savesDirectory.listFiles(); 039 File[] var3 = var2; 040 int var4 = var2.length; 041 042 for (int var5 = 0; var5 < var4; ++var5) 043 { 044 File var6 = var3[var5]; 045 046 if (var6.isDirectory()) 047 { 048 String var7 = var6.getName(); 049 WorldInfo var8 = this.getWorldInfo(var7); 050 051 if (var8 != null && (var8.getSaveVersion() == 19132 || var8.getSaveVersion() == 19133)) 052 { 053 boolean var9 = var8.getSaveVersion() != this.getSaveVersion(); 054 String var10 = var8.getWorldName(); 055 056 if (var10 == null || MathHelper.stringNullOrLengthZero(var10)) 057 { 058 var10 = var7; 059 } 060 061 long var11 = 0L; 062 var1.add(new SaveFormatComparator(var7, var10, var8.getLastTimePlayed(), var11, var8.getGameType(), var9, var8.isHardcoreModeEnabled(), var8.areCommandsAllowed())); 063 } 064 } 065 } 066 067 return var1; 068 } 069 070 protected int getSaveVersion() 071 { 072 return 19133; 073 } 074 075 public void flushCache() 076 { 077 RegionFileCache.clearRegionFileReferences(); 078 } 079 080 /** 081 * Returns back a loader for the specified save directory 082 */ 083 public ISaveHandler getSaveLoader(String par1Str, boolean par2) 084 { 085 return new AnvilSaveHandler(this.savesDirectory, par1Str, par2); 086 } 087 088 /** 089 * Checks if the save directory uses the old map format 090 */ 091 public boolean isOldMapFormat(String par1Str) 092 { 093 WorldInfo var2 = this.getWorldInfo(par1Str); 094 return var2 != null && var2.getSaveVersion() != this.getSaveVersion(); 095 } 096 097 /** 098 * Converts the specified map to the new map format. Args: worldName, loadingScreen 099 */ 100 public boolean convertMapFormat(String par1Str, IProgressUpdate par2IProgressUpdate) 101 { 102 par2IProgressUpdate.setLoadingProgress(0); 103 ArrayList var3 = new ArrayList(); 104 ArrayList var4 = new ArrayList(); 105 ArrayList var5 = new ArrayList(); 106 File var6 = new File(this.savesDirectory, par1Str); 107 File var7 = new File(var6, "DIM-1"); 108 File var8 = new File(var6, "DIM1"); 109 System.out.println("Scanning folders..."); 110 this.addRegionFilesToCollection(var6, var3); 111 112 if (var7.exists()) 113 { 114 this.addRegionFilesToCollection(var7, var4); 115 } 116 117 if (var8.exists()) 118 { 119 this.addRegionFilesToCollection(var8, var5); 120 } 121 122 int var9 = var3.size() + var4.size() + var5.size(); 123 System.out.println("Total conversion count is " + var9); 124 WorldInfo var10 = this.getWorldInfo(par1Str); 125 Object var11 = null; 126 127 if (var10.getTerrainType() == WorldType.FLAT) 128 { 129 var11 = new WorldChunkManagerHell(BiomeGenBase.plains, 0.5F, 0.5F); 130 } 131 else 132 { 133 var11 = new WorldChunkManager(var10.getSeed(), var10.getTerrainType()); 134 } 135 136 this.convertFile(new File(var6, "region"), var3, (WorldChunkManager)var11, 0, var9, par2IProgressUpdate); 137 this.convertFile(new File(var7, "region"), var4, new WorldChunkManagerHell(BiomeGenBase.hell, 1.0F, 0.0F), var3.size(), var9, par2IProgressUpdate); 138 this.convertFile(new File(var8, "region"), var5, new WorldChunkManagerHell(BiomeGenBase.sky, 0.5F, 0.0F), var3.size() + var4.size(), var9, par2IProgressUpdate); 139 var10.setSaveVersion(19133); 140 141 if (var10.getTerrainType() == WorldType.DEFAULT_1_1) 142 { 143 var10.setTerrainType(WorldType.DEFAULT); 144 } 145 146 this.createFile(par1Str); 147 ISaveHandler var12 = this.getSaveLoader(par1Str, false); 148 var12.saveWorldInfo(var10); 149 return true; 150 } 151 152 /** 153 * par: filename for the level.dat_mcr backup 154 */ 155 private void createFile(String par1Str) 156 { 157 File var2 = new File(this.savesDirectory, par1Str); 158 159 if (!var2.exists()) 160 { 161 System.out.println("Warning: Unable to create level.dat_mcr backup"); 162 } 163 else 164 { 165 File var3 = new File(var2, "level.dat"); 166 167 if (!var3.exists()) 168 { 169 System.out.println("Warning: Unable to create level.dat_mcr backup"); 170 } 171 else 172 { 173 File var4 = new File(var2, "level.dat_mcr"); 174 175 if (!var3.renameTo(var4)) 176 { 177 System.out.println("Warning: Unable to create level.dat_mcr backup"); 178 } 179 } 180 } 181 } 182 183 private void convertFile(File par1File, Iterable par2Iterable, WorldChunkManager par3WorldChunkManager, int par4, int par5, IProgressUpdate par6IProgressUpdate) 184 { 185 Iterator var7 = par2Iterable.iterator(); 186 187 while (var7.hasNext()) 188 { 189 File var8 = (File)var7.next(); 190 this.convertChunks(par1File, var8, par3WorldChunkManager, par4, par5, par6IProgressUpdate); 191 ++par4; 192 int var9 = (int)Math.round(100.0D * (double)par4 / (double)par5); 193 par6IProgressUpdate.setLoadingProgress(var9); 194 } 195 } 196 197 /** 198 * copies a 32x32 chunk set from par2File to par1File, via AnvilConverterData 199 */ 200 private void convertChunks(File par1File, File par2File, WorldChunkManager par3WorldChunkManager, int par4, int par5, IProgressUpdate par6IProgressUpdate) 201 { 202 try 203 { 204 String var7 = par2File.getName(); 205 RegionFile var8 = new RegionFile(par2File); 206 RegionFile var9 = new RegionFile(new File(par1File, var7.substring(0, var7.length() - ".mcr".length()) + ".mca")); 207 208 for (int var10 = 0; var10 < 32; ++var10) 209 { 210 int var11; 211 212 for (var11 = 0; var11 < 32; ++var11) 213 { 214 if (var8.isChunkSaved(var10, var11) && !var9.isChunkSaved(var10, var11)) 215 { 216 DataInputStream var12 = var8.getChunkDataInputStream(var10, var11); 217 218 if (var12 == null) 219 { 220 System.out.println("Failed to fetch input stream"); 221 } 222 else 223 { 224 NBTTagCompound var13 = CompressedStreamTools.read(var12); 225 var12.close(); 226 NBTTagCompound var14 = var13.getCompoundTag("Level"); 227 AnvilConverterData var15 = ChunkLoader.load(var14); 228 NBTTagCompound var16 = new NBTTagCompound(); 229 NBTTagCompound var17 = new NBTTagCompound(); 230 var16.setTag("Level", var17); 231 ChunkLoader.convertToAnvilFormat(var15, var17, par3WorldChunkManager); 232 DataOutputStream var18 = var9.getChunkDataOutputStream(var10, var11); 233 CompressedStreamTools.write(var16, var18); 234 var18.close(); 235 } 236 } 237 } 238 239 var11 = (int)Math.round(100.0D * (double)(par4 * 1024) / (double)(par5 * 1024)); 240 int var20 = (int)Math.round(100.0D * (double)((var10 + 1) * 32 + par4 * 1024) / (double)(par5 * 1024)); 241 242 if (var20 > var11) 243 { 244 par6IProgressUpdate.setLoadingProgress(var20); 245 } 246 } 247 248 var8.close(); 249 var9.close(); 250 } 251 catch (IOException var19) 252 { 253 var19.printStackTrace(); 254 } 255 } 256 257 /** 258 * filters the files in the par1 directory, and adds them to the par2 collections 259 */ 260 private void addRegionFilesToCollection(File par1File, Collection par2Collection) 261 { 262 File var3 = new File(par1File, "region"); 263 File[] var4 = var3.listFiles(new AnvilSaveConverterFileFilter(this)); 264 265 if (var4 != null) 266 { 267 Collections.addAll(par2Collection, var4); 268 } 269 } 270 }