001package net.minecraft.world.chunk.storage;
002
003import cpw.mods.fml.relauncher.Side;
004import cpw.mods.fml.relauncher.SideOnly;
005import java.io.DataInputStream;
006import java.io.DataOutputStream;
007import java.io.File;
008import java.io.IOException;
009import java.util.ArrayList;
010import java.util.Collection;
011import java.util.Collections;
012import java.util.Iterator;
013import java.util.List;
014import net.minecraft.nbt.CompressedStreamTools;
015import net.minecraft.nbt.NBTTagCompound;
016import net.minecraft.util.IProgressUpdate;
017import net.minecraft.util.MathHelper;
018import net.minecraft.world.WorldType;
019import net.minecraft.world.biome.BiomeGenBase;
020import net.minecraft.world.biome.WorldChunkManager;
021import net.minecraft.world.biome.WorldChunkManagerHell;
022import net.minecraft.world.storage.ISaveHandler;
023import net.minecraft.world.storage.SaveFormatComparator;
024import net.minecraft.world.storage.SaveFormatOld;
025import net.minecraft.world.storage.WorldInfo;
026
027public 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}