Exemple #1
0
        /// <summary> Attempts to save this level (can be cancelled) </summary>
        /// <param name="force"> Whether to save even if nothing changed since last save </param>
        /// <returns> Whether this level was successfully saved to disc </returns>
        public bool Save(bool force = false)
        {
            if (blocks == null || IsMuseum)
            {
                return(false);                            // museums do not save changes
            }
            string path   = LevelInfo.MapPath(MapName);
            bool   cancel = false;

            OnLevelSaveEvent.Call(this, ref cancel);
            if (cancel)
            {
                return(false);
            }

            try {
                if (!Directory.Exists("levels"))
                {
                    Directory.CreateDirectory("levels");
                }
                if (!Directory.Exists("levels/level properties"))
                {
                    Directory.CreateDirectory("levels/level properties");
                }
                if (!Directory.Exists("levels/prev"))
                {
                    Directory.CreateDirectory("levels/prev");
                }

                if (Changed || force || !File.Exists(path))
                {
                    lock (saveLock) SaveCore(path);
                }
                else
                {
                    Logger.Log(LogType.SystemActivity, "Skipping level save for " + name + ".");
                }
            } catch (Exception e) {
                Logger.Log(LogType.Warning, "FAILED TO SAVE :" + name);
                Chat.MessageGlobal("FAILED TO SAVE {0}", ColoredName);
                Logger.LogError(e);
                return(false);
            }
            Server.DoGC();
            return(true);
        }
Exemple #2
0
 static void DoAll(string src, string dst, byte action)
 {
     DoAction(LevelInfo.MapPath(src) + ".backup",
              LevelInfo.MapPath(dst) + ".backup", action);
     DoAction(LevelInfo.PropsPath(src),
              LevelInfo.PropsPath(dst), action);
     DoAction("levels/level properties/" + src,
              LevelInfo.PropsPath(dst), action);
     DoAction(Paths.MapBlockDefs(src),
              Paths.MapBlockDefs(dst), action);
     DoAction(BlockPropsOldPath(src),
              BlockPropsOldPath(dst), action);
     DoAction(BlockPropsLvlPath(src),
              BlockPropsLvlPath(dst), action);
     DoAction(BotsFile.BotsPath(src),
              BotsFile.BotsPath(dst), action);
 }
Exemple #3
0
        static Level ReadLevel(Player p, string map)
        {
            Level lvl = Level.Load(map);

            if (lvl != null)
            {
                return(lvl);
            }

            string path = LevelInfo.MapPath(map) + ".backup";

            if (!File.Exists(path))
            {
                p.Message("%WBackup of {0} does not exist.", map); return(null);
            }
            Logger.Log(LogType.Warning, "Attempting to load backup map for " + map);

            lvl = Level.Load(map, path);
            if (lvl != null)
            {
                return(lvl);
            }
            p.Message("%WLoading backup of {0} failed too.", map);

            string backupDir = LevelInfo.BackupBasePath(map);

            if (Directory.Exists(backupDir))
            {
                int latest = LevelInfo.LatestBackup(map);
                Logger.Log(LogType.Warning, "Attempting to load latest backup ({1}) of {0} instead", map, latest);

                path = LevelInfo.BackupFilePath(map, latest.ToString());
                lvl  = Level.Load(map, path);
                if (lvl == null)
                {
                    p.Message("%WLoading latest backup failed too.");
                }
            }
            else
            {
                p.Message("%WLatest backup of {0} does not exist.", map);
            }
            return(lvl);
        }
Exemple #4
0
        /*static void MoveBackups(string src, string dst) {
         *  string srcBase = LevelInfo.BackupBasePath(src);
         *  string dstBase = LevelInfo.BackupBasePath(dst);
         *  if (!Directory.Exists(srcBase)) return;
         *  Directory.CreateDirectory(dstBase);
         *
         *  string[] backups = Directory.GetDirectories(srcBase);
         *  for (int i = 0; i < backups.Length; i++) {
         *      string name = LevelInfo.BackupNameFrom(backups[i]);
         *      string srcFile = LevelInfo.BackupFilePath(src, name);
         *      string dstFile = LevelInfo.BackupFilePath(dst, name);
         *      string dstDir = LevelInfo.BackupDirPath(dst, name);
         *
         *      Directory.CreateDirectory(dstDir);
         *      File.Move(srcFile, dstFile);
         *      Directory.Delete(backups[i]);
         *  }
         *  Directory.Delete(srcBase);
         * }*/


        /// <summary> Deletes a map and associated metadata. </summary>
        public static bool Delete(Player p, string map)
        {
            Level lvl = LevelInfo.FindExact(map);

            if (lvl == Server.mainLevel)
            {
                p.Message("Cannot delete the main level."); return(false);
            }

            if (lvl != null && !lvl.Unload())
            {
                p.Message("Unable to delete the level, because it could not be unloaded. " +
                          "A game may currently be running on it.");
                return(false);
            }

            p.Message("Created backup.");
            if (!Directory.Exists("levels/deleted"))
            {
                Directory.CreateDirectory("levels/deleted");
            }

            if (File.Exists(Paths.DeletedMapFile(map)))
            {
                int num = 0;
                while (File.Exists(Paths.DeletedMapFile(map + num)))
                {
                    num++;
                }

                File.Move(LevelInfo.MapPath(map), Paths.DeletedMapFile(map + num));
            }
            else
            {
                File.Move(LevelInfo.MapPath(map), Paths.DeletedMapFile(map));
            }

            DoAll(map, "", action_delete);
            DeleteDatabaseTables(map);
            BlockDBFile.DeleteBackingFile(map);
            OnLevelDeletedEvent.Call(map);
            return(true);
        }
Exemple #5
0
        static Level ReadLevel(Player p, string map)
        {
            Level lvl = Level.Load(map);

            if (lvl != null)
            {
                return(lvl);
            }

            string path = LevelInfo.MapPath(map) + ".backup";

            if (!File.Exists(path))
            {
                p.Message("Level \"{0}\" does not exist", map); return(lvl);
            }
            lvl = ReadBackup(p, map, path, "backup copy");
            if (lvl != null)
            {
                return(lvl);
            }

            path = Paths.PrevMapFile(map);
            lvl  = ReadBackup(p, map, path, "previous save");
            if (lvl != null)
            {
                return(lvl);
            }

            string backupDir = LevelInfo.BackupBasePath(map);

            if (Directory.Exists(backupDir))
            {
                int latest = LevelInfo.LatestBackup(map);
                path = LevelInfo.BackupFilePath(map, latest.ToString());
                lvl  = ReadBackup(p, map, path, "latest backup");
            }
            else
            {
                p.Message("&WLatest backup of {0} does not exist.", map);
            }
            return(lvl);
        }
Exemple #6
0
        public static bool Backup(string map, string backupName)
        {
            string basePath = LevelInfo.BackupBasePath(map);

            if (!Directory.Exists(basePath))
            {
                Directory.CreateDirectory(basePath);
            }
            string path = Path.Combine(basePath, backupName);

            Directory.CreateDirectory(path);

            bool lvl    = DoAction(LevelInfo.MapPath(map), Path.Combine(path, map + ".lvl"), action_copy);
            bool props  = DoAction(LevelInfo.PropsPath(map), Path.Combine(path, "map.properties"), action_copy);
            bool defs   = DoAction(BlockDefsPath(map), Path.Combine(path, "blockdefs.json"), action_copy);
            bool blkOld = DoAction(BlockPropsOldPath(map), Path.Combine(path, "blockprops.txt"), action_copy);
            bool blkCur = DoAction(BlockPropsLvlPath(map), Path.Combine(path, "blockprops.txt"), action_copy);
            bool bots   = DoAction(BotsFile.BotsPath(map), Path.Combine(path, "bots.json"), action_copy);

            return(lvl && props && defs && blkOld && blkCur && bots);
        }
Exemple #7
0
        /// <summary> Copies a map and related metadata. </summary>
        /// <remarks> Backups and BlockDB are NOT copied. </remarks>
        public static bool Copy(Player p, string src, string dst)
        {
            if (LevelInfo.MapExists(dst))
            {
                p.Message("&WLevel \"{0}\" already exists.", dst); return(false);
            }

            // Make sure any changes to live map are saved first
            Level lvl = LevelInfo.FindExact(src);

            if (lvl != null && !lvl.Save(true))
            {
                p.Message("&WUnable to save {0}! Some recent block changes may not be copied.", src);
            }

            File.Copy(LevelInfo.MapPath(src), LevelInfo.MapPath(dst));
            DoAll(src, dst, action_copy);
            CopyDatabaseTables(src, dst);
            OnLevelCopiedEvent.Call(src, dst);
            return(true);
        }
Exemple #8
0
        /// <summary> Deletes the .lvl (and related) files and database tables. Unloads level if it is loaded. </summary>
        public static bool Delete(string name)
        {
            Level lvl = LevelInfo.FindExact(name);

            if (lvl != null && !lvl.Unload())
            {
                return(false);
            }

            if (!Directory.Exists("levels/deleted"))
            {
                Directory.CreateDirectory("levels/deleted");
            }

            if (File.Exists(LevelInfo.DeletedPath(name)))
            {
                int num = 0;
                while (File.Exists(LevelInfo.DeletedPath(name + num)))
                {
                    num++;
                }

                File.Move(LevelInfo.MapPath(name), LevelInfo.DeletedPath(name + num));
            }
            else
            {
                File.Move(LevelInfo.MapPath(name), LevelInfo.DeletedPath(name));
            }

            DeleteIfExists(LevelInfo.MapPath(name) + ".backup");
            DeleteIfExists("levels/level properties/" + name);
            DeleteIfExists("levels/level properties/" + name + ".properties");
            DeleteIfExists("blockdefs/lvl_" + name + ".json");
            DeleteIfExists("blockprops/lvl_" + name + ".txt");
            DeleteIfExists(BotsFile.BotsPath(name));

            DeleteDatabaseTables(name);
            BlockDBFile.DeleteBackingFile(name);
            return(true);
        }
        public override void Use(Player p, string message)
        {
            string[] args = message.SplitSpaces(2);
            string   src  = args[0].ToLower();
            string   dst  = args.Length > 1 ? args[1].ToLower() : src;

            if (message.Length == 0)
            {
                Help(p); return;
            }
            if (!Formatter.ValidMapName(p, src))
            {
                return;
            }
            if (!Formatter.ValidMapName(p, dst))
            {
                return;
            }

            string path = Path.Combine(oldServer, LevelInfo.MapPath(src));

            if (!File.Exists(path))
            {
                p.Message("%WLevel {0} does not exist on old server.", src); return;
            }
            if (LevelInfo.MapExists(dst))
            {
                p.Message("%WLevel {0} already exists on new server.", dst); return;
            }

            File.Copy(path, LevelInfo.MapPath(dst), true);
            CopyProperties(src, dst);
            CopyBlockDefs(src, dst);
            CopyBlockProps(src, dst);
            ExportPortals(p, src, dst);
            ExportMessages(p, src, dst);
            p.Message("Successfully imported level {0} as {1}", src, dst);
        }
Exemple #10
0
 public static Level Load(string name)
 {
     return(Load(name, LevelInfo.MapPath(name)));
 }
Exemple #11
0
 public static void CopyLevel(string src, string dst)
 {
     File.Copy(LevelInfo.MapPath(src), LevelInfo.MapPath(dst));
     DoAll(src, dst, action_copy);
     CopyDatabaseTables(src, dst);
 }
Exemple #12
0
        public static void Resize(ref Level lvl, int width, int height, int length)
        {
            Level res = new Level(lvl.name, (ushort)width, (ushort)height, (ushort)length);

            res.hasPortals       = lvl.hasPortals;
            res.hasMessageBlocks = lvl.hasMessageBlocks;
            byte[] src = lvl.blocks, dst = res.blocks;

            // Copy blocks in bulk
            width  = Math.Min(lvl.Width, res.Width);
            height = Math.Min(lvl.Height, res.Height);
            length = Math.Min(lvl.Length, res.Length);
            for (int y = 0; y < height; y++)
            {
                for (int z = 0; z < length; z++)
                {
                    int srcI = lvl.Width * (z + y * lvl.Length);
                    int dstI = res.Width * (z + y * res.Length);
                    Buffer.BlockCopy(src, srcI, dst, dstI, width);
                }
            }

            // Copy extended blocks in bulk
            width  = Math.Min(lvl.ChunksX, res.ChunksX);
            height = Math.Min(lvl.ChunksY, res.ChunksY);
            length = Math.Min(lvl.ChunksZ, res.ChunksZ);
            for (int cy = 0; cy < height; cy++)
            {
                for (int cz = 0; cz < length; cz++)
                {
                    for (int cx = 0; cx < width; cx++)
                    {
                        src = lvl.CustomBlocks[(cy * lvl.ChunksZ + cz) * lvl.ChunksX + cx];
                        if (src == null)
                        {
                            continue;
                        }

                        dst = new byte[16 * 16 * 16];
                        res.CustomBlocks[(cy * res.ChunksZ + cz) * res.ChunksX + cx] = dst;
                        Buffer.BlockCopy(src, 0, dst, 0, 16 * 16 * 16);
                    }
                }
            }

            // TODO: This copying is really ugly and probably not 100% right
            res.spawnx = lvl.spawnx; res.spawny = lvl.spawny; res.spawnz = lvl.spawnz;
            res.rotx   = lvl.rotx; res.roty = lvl.roty;

            lock (lvl.saveLock) {
                lvl.Backup(true);

                // Make sure zones are kept
                res.Zones = lvl.Zones;
                lvl.Zones = new VolatileArray <Zone>(false);

                IMapExporter.Formats[0].Write(LevelInfo.MapPath(lvl.name), res);
                lvl.SaveChanges = false;
            }

            res.backedup = true;
            Level.LoadMetadata(res);
            BotsFile.Load(res);

            LevelActions.Replace(lvl, res);
            lvl = res;
        }