    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}