/// <summary> Changes the name of the given world. </summary> public static void RenameWorld([NotNull] World world, [NotNull] string newName, bool moveMapFile, bool overwrite) { if (newName == null) { throw new ArgumentNullException("newName"); } if (world == null) { throw new ArgumentNullException("world"); } if (!World.IsValidName(newName)) { throw new WorldOpException(newName, WorldOpExceptionCode.InvalidWorldName); } lock (world.SyncRoot) { string oldName = world.Name; if (oldName == newName) { throw new WorldOpException(world.Name, WorldOpExceptionCode.NoChangeNeeded); } lock ( SyncRoot ) { World newWorld = FindWorldExact(newName); if (newWorld != null && newWorld != world) { if (overwrite) { RemoveWorld(newWorld); } else { throw new WorldOpException(newName, WorldOpExceptionCode.DuplicateWorldName); } } WorldIndex.Remove(world.Name.ToLower()); world.Name = newName; WorldIndex.Add(newName.ToLower(), world); SaveWorldList(); UpdateWorldList(); if (moveMapFile) { string oldMapFile = Path.Combine(Paths.MapPath, oldName + ".fcm"); string newMapFile = newName + ".fcm"; if (File.Exists(oldMapFile)) { try { Paths.ForceRename(oldMapFile, newMapFile); } catch (Exception ex) { throw new WorldOpException(world.Name, WorldOpExceptionCode.MapMoveError, ex); } } using (world.BlockDB.GetWriteLock()) { string oldBlockDBFile = Path.Combine(Paths.BlockDBDirectory, oldName + ".fbdb"); string newBockDBFile = newName + ".fbdb"; if (File.Exists(oldBlockDBFile)) { try { Paths.ForceRename(oldBlockDBFile, newBockDBFile); } catch (Exception ex) { throw new WorldOpException(world.Name, WorldOpExceptionCode.MapMoveError, ex); } } } } } } }
// Makes sure that the map file exists, is properly named, and is loadable. static void CheckMapFile([NotNull] World world) { if (world == null) { throw new ArgumentNullException("world"); } // Check the world's map file string fullMapFileName = world.MapFileName; string fileName = Path.GetFileName(fullMapFileName); if (Paths.FileExists(fullMapFileName, false)) { if (!Paths.FileExists(fullMapFileName, true)) { // Map file has wrong capitalization FileInfo[] matches = Paths.FindFiles(fullMapFileName); if (matches.Length == 1) { // Try to rename the map file to match world's capitalization // ReSharper disable AssignNullToNotNullAttribute Paths.ForceRename(matches[0].FullName, fileName); // ReSharper restore AssignNullToNotNullAttribute if (Paths.FileExists(fullMapFileName, true)) { Logger.Log(LogType.Warning, "WorldManager.CheckMapFile: Map file for world \"{0}\" was renamed from \"{1}\" to \"{2}\"", world.Name, matches[0].Name, fileName); } else { Logger.Log(LogType.Error, "WorldManager.CheckMapFile: Failed to rename map file of \"{0}\" from \"{1}\" to \"{2}\"", world.Name, matches[0].Name, fileName); return; } } else { Logger.Log(LogType.Warning, "WorldManager.CheckMapFile: More than one map file exists matching the world name \"{0}\". " + "Please check the map directory and use /WLoad to load the correct file.", world.Name); return; } } // Try loading the map header try { MapUtility.LoadHeader(world.MapFileName); } catch (Exception ex) { Logger.Log(LogType.Warning, "WorldManager.CheckMapFile: Could not load map file for world \"{0}\": {1}", world.Name, ex); } } else { Logger.Log(LogType.Warning, "WorldManager.CheckMapFile: Map file for world \"{0}\" was not found.", world.Name); } }
/// <summary> Saves the current world list to worlds.xml. Thread-safe. </summary> public static void SaveWorldList() { const string worldListTempFileName = Paths.WorldListFileName + ".tmp"; // Save world list lock ( SyncRoot ) { XDocument doc = new XDocument(); XElement root = new XElement("fCraftWorldList"); foreach (World world in Worlds) { XElement temp = new XElement("World"); temp.Add(new XAttribute("name", world.Name)); if (world.AccessSecurity.HasRestrictions) { temp.Add(world.AccessSecurity.Serialize(AccessSecurityXmlTagName)); } if (world.BuildSecurity.HasRestrictions) { temp.Add(world.BuildSecurity.Serialize(BuildSecurityXmlTagName)); } // save backup settings switch (world.BackupEnabledState) { case YesNoAuto.Yes: temp.Add(new XAttribute("backup", world.BackupInterval.ToSecondsString())); break; case YesNoAuto.No: temp.Add(new XAttribute("backup", 0)); break; } if (world.Preload) { temp.Add(new XAttribute("noUnload", true)); } if (world.IsHidden) { temp.Add(new XAttribute("hidden", true)); } temp.Add(world.BlockDB.SaveSettings()); World world1 = world; // keeping ReSharper happy foreach (Rank mainedRank in RankManager.Ranks.Where(r => r.MainWorld == world1)) { temp.Add(new XElement(RankMainXmlTagName, mainedRank.FullName)); } // save loaded/map-changed information if (!String.IsNullOrEmpty(world.LoadedBy)) { temp.Add(new XElement("LoadedBy", world.LoadedBy)); } if (world.LoadedOn != DateTime.MinValue) { temp.Add(new XElement("LoadedOn", world.LoadedOn.ToUnixTime())); } if (!String.IsNullOrEmpty(world.MapChangedBy)) { temp.Add(new XElement("MapChangedBy", world.MapChangedBy)); } if (world.MapChangedOn != DateTime.MinValue) { temp.Add(new XElement("MapChangedOn", world.MapChangedOn.ToUnixTime())); } // save environmental settings XElement elEnv = new XElement(EnvironmentXmlTagName); if (world.CloudColor > -1) { elEnv.Add(new XAttribute("cloud", world.CloudColor)); } if (world.FogColor > -1) { elEnv.Add(new XAttribute("fog", world.FogColor)); } if (world.SkyColor > -1) { elEnv.Add(new XAttribute("sky", world.SkyColor)); } if (world.EdgeLevel > -1) { elEnv.Add(new XAttribute("level", world.EdgeLevel)); } if (world.EdgeBlock != Block.Water) { elEnv.Add(new XAttribute("edge", world.EdgeBlock)); } if (elEnv.HasAttributes) { temp.Add(elEnv); } // save lock information if (world.IsLocked) { temp.Add(new XAttribute("locked", true)); if (!String.IsNullOrEmpty(world.LockedBy)) { temp.Add(new XElement("LockedBy", world.LockedBy)); } if (world.LockedOn != DateTime.MinValue) { temp.Add(new XElement("LockedOn", world.LockedOn.ToUnixTime())); } } else { if (!String.IsNullOrEmpty(world.UnlockedBy)) { temp.Add(new XElement("UnlockedBy", world.UnlockedBy)); } if (world.UnlockedOn != DateTime.MinValue) { temp.Add(new XElement("UnlockedOn", world.UnlockedOn.ToUnixTime())); } } root.Add(temp); } root.Add(new XAttribute("main", MainWorld.Name)); doc.Add(root); doc.Save(worldListTempFileName); Paths.MoveOrReplaceFile(worldListTempFileName, Paths.WorldListFileName); } }
public static string FindMapFile([NotNull] Player player, [NotNull] string fileName) { if (player == null) { throw new ArgumentNullException("player"); } if (fileName == null) { throw new ArgumentNullException("fileName"); } // Check if path contains missing drives or invalid characters if (!Paths.IsValidPath(fileName)) { player.Message("Invalid file name or path."); return(null); } // Look for the file string sourceFullFileName = Path.Combine(Paths.MapPath, fileName); if (!File.Exists(sourceFullFileName) && !Directory.Exists(sourceFullFileName)) { if (File.Exists(sourceFullFileName + ".fcm")) { // Try with extension added sourceFullFileName += ".fcm"; } else if (MonoCompat.IsCaseSensitive) { try { // If we're on a case-sensitive OS, try case-insensitive search FileInfo[] candidates = Paths.FindFiles(sourceFullFileName + ".fcm"); if (candidates.Length == 0) { candidates = Paths.FindFiles(sourceFullFileName); } if (candidates.Length == 0) { player.Message("File/directory not found: {0}", fileName); } else if (candidates.Length == 1) { player.Message("File names are case-sensitive! Did you mean to load \"{0}\"?", candidates[0].Name); } else { player.Message("File names are case-sensitive! Did you mean to load one of these: {0}", String.Join(", ", candidates.Select(c => c.Name).ToArray())); } } catch (DirectoryNotFoundException ex) { player.Message(ex.Message); } return(null); } else { // Nothing found! player.Message("File/directory not found: {0}", fileName); return(null); } } // Make sure that the given file is within the map directory if (!Paths.Contains(Paths.MapPath, sourceFullFileName)) { player.MessageUnsafePath(); return(null); } return(sourceFullFileName); }