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 }