    001    package net.minecraft.world.chunk.storage;
    002
    003    import cpw.mods.fml.common.Side;
    004    import cpw.mods.fml.common.asm.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    }