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    }