static void DumpStatsHandler( Player player, Command cmd ) { string fileName = cmd.Next(); if( fileName == null ) { CdDumpStats.PrintUsage( player ); return; } if( !Paths.Contains( Paths.WorkingPath, fileName ) ) { player.MessageUnsafePath(); return; } // ReSharper disable AssignNullToNotNullAttribute if( Paths.IsProtectedFileName( Path.GetFileName( fileName ) ) ) { // ReSharper restore AssignNullToNotNullAttribute player.Message( "You may not use this file." ); return; } string extension = Path.GetExtension( fileName ); if( extension == null || !extension.Equals( ".txt", StringComparison.OrdinalIgnoreCase ) ) { player.Message( "Stats filename must end with .txt" ); return; } if( File.Exists( fileName ) && !cmd.IsConfirmed ) { player.Confirm( cmd, "File \"{0}\" already exists. Overwrite?", Path.GetFileName( fileName ) ); return; } if( !Paths.TestFile( "DumpStats file", fileName, false, FileAccess.Write ) ) { player.Message( "Cannot create specified file. See log for details." ); return; } PlayerInfo[] infos; using( FileStream fs = File.Create( fileName ) ) { using( StreamWriter writer = new StreamWriter( fs ) ) { infos = PlayerDB.PlayerInfoList; if( infos.Length == 0 ) { writer.WriteLine( "(TOTAL) (0 players)" ); writer.WriteLine(); } else { DumpPlayerGroupStats( writer, infos, "(TOTAL)" ); } List<PlayerInfo> rankPlayers = new List<PlayerInfo>(); foreach( Rank rank in RankManager.Ranks ) { // ReSharper disable LoopCanBeConvertedToQuery for( int i = 0; i < infos.Length; i++ ) { // ReSharper restore LoopCanBeConvertedToQuery if( infos[i].Rank == rank ) rankPlayers.Add( infos[i] ); } if( rankPlayers.Count == 0 ) { writer.WriteLine( "{0}: 0 players, 0 banned, 0 inactive", rank.Name ); writer.WriteLine(); } else { DumpPlayerGroupStats( writer, rankPlayers, rank.Name ); } rankPlayers.Clear(); } } } player.Message( "Stats saved to \"{0}\"", fileName ); }
static void GenHandler(Player player, Command cmd) { World playerWorld = player.World; string themeName = cmd.Next(); string templateName; bool genOcean = false; bool genEmpty = false; bool noTrees = false; if (themeName == null) { CdGenerate.PrintUsage(player); return; } MapGenTheme theme = MapGenTheme.Forest; MapGenTemplate template = MapGenTemplate.Flat; // parse special template names (which do not need a theme) if (themeName.Equals("ocean")) { genOcean = true; } else if (themeName.Equals("empty")) { genEmpty = true; } else { templateName = cmd.Next(); if (templateName == null) { CdGenerate.PrintUsage(player); return; } // parse theme bool swapThemeAndTemplate = false; if (themeName.Equals("grass", StringComparison.OrdinalIgnoreCase)) { theme = MapGenTheme.Forest; noTrees = true; } else if (templateName.Equals("grass", StringComparison.OrdinalIgnoreCase)) { theme = MapGenTheme.Forest; noTrees = true; swapThemeAndTemplate = true; } else if (EnumUtil.TryParse(themeName, out theme, true)) { noTrees = (theme != MapGenTheme.Forest); } else if (EnumUtil.TryParse(templateName, out theme, true)) { noTrees = (theme != MapGenTheme.Forest); swapThemeAndTemplate = true; } else { player.Message("Gen: Unrecognized theme \"{0}\". Available themes are: Grass, {1}", themeName, Enum.GetNames(typeof(MapGenTheme)).JoinToString()); return; } // parse template if (swapThemeAndTemplate) { if (!EnumUtil.TryParse(themeName, out template, true)) { player.Message("Unrecognized template \"{0}\". Available terrain types: Empty, Ocean, {1}", themeName, Enum.GetNames(typeof(MapGenTemplate)).JoinToString()); return; } } else { if (!EnumUtil.TryParse(templateName, out template, true)) { player.Message("Unrecognized template \"{0}\". Available terrain types: Empty, Ocean, {1}", templateName, Enum.GetNames(typeof(MapGenTemplate)).JoinToString()); return; } } } // parse map dimensions int mapWidth, mapLength, mapHeight; if (cmd.HasNext) { int offset = cmd.Offset; if (!(cmd.NextInt(out mapWidth) && cmd.NextInt(out mapLength) && cmd.NextInt(out mapHeight))) { if (playerWorld != null) { Map oldMap = player.WorldMap; // If map dimensions were not given, use current map's dimensions mapWidth = oldMap.Width; mapLength = oldMap.Length; mapHeight = oldMap.Height; } else { player.Message("When used from console, /Gen requires map dimensions."); CdGenerate.PrintUsage(player); return; } cmd.Offset = offset; } } else if (playerWorld != null) { Map oldMap = player.WorldMap; // If map dimensions were not given, use current map's dimensions mapWidth = oldMap.Width; mapLength = oldMap.Length; mapHeight = oldMap.Height; } else { player.Message("When used from console, /Gen requires map dimensions."); CdGenerate.PrintUsage(player); return; } // Check map dimensions const string dimensionRecommendation = "Dimensions must be between 16 and 2047. " + "Recommended values: 16, 32, 64, 128, 256, 512, and 1024."; if (!Map.IsValidDimension(mapWidth)) { player.Message("Cannot make map with width {0}. {1}", mapWidth, dimensionRecommendation); return; } else if (!Map.IsValidDimension(mapLength)) { player.Message("Cannot make map with length {0}. {1}", mapLength, dimensionRecommendation); return; } else if (!Map.IsValidDimension(mapHeight)) { player.Message("Cannot make map with height {0}. {1}", mapHeight, dimensionRecommendation); return; } long volume = (long)mapWidth * (long)mapLength * (long)mapHeight; if (volume > Int32.MaxValue) { player.Message("Map volume may not exceed {0}", Int32.MaxValue); return; } if (!cmd.IsConfirmed && (!Map.IsRecommendedDimension(mapWidth) || !Map.IsRecommendedDimension(mapLength) || !Map.IsRecommendedDimension(mapHeight))) { player.Message("&WThe map will have non-standard dimensions. " + "You may see glitched blocks or visual artifacts. " + "The only recommended map dimensions are: 16, 32, 64, 128, 256, 512, and 1024."); } // figure out full template name bool genFlatgrass = (theme == MapGenTheme.Forest && noTrees && template == MapGenTemplate.Flat); string templateFullName; if (genEmpty) { templateFullName = "Empty"; } else if (genOcean) { templateFullName = "Ocean"; } else if (genFlatgrass) { templateFullName = "Flatgrass"; } else { if (theme == MapGenTheme.Forest && noTrees) { templateFullName = "Grass " + template; } else { templateFullName = theme + " " + template; } } // check file/world name string fileName = cmd.Next(); string fullFileName = null; if (fileName == null) { // replacing current world if (playerWorld == null) { player.Message("When used from console, /Gen requires FileName."); CdGenerate.PrintUsage(player); return; } if (!cmd.IsConfirmed) { player.Confirm(cmd, "Replace THIS MAP with a generated one ({0})?", templateFullName); return; } } else { if (cmd.HasNext) { CdGenerate.PrintUsage(player); return; } // saving to file fileName = fileName.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); if (!fileName.EndsWith(".fcm", StringComparison.OrdinalIgnoreCase)) { fileName += ".fcm"; } if (!Paths.IsValidPath(fileName)) { player.Message("Invalid filename."); return; } fullFileName = Path.Combine(Paths.MapPath, fileName); if (!Paths.Contains(Paths.MapPath, fullFileName)) { player.MessageUnsafePath(); return; } string dirName = fullFileName.Substring(0, fullFileName.LastIndexOf(Path.DirectorySeparatorChar)); if (!Directory.Exists(dirName)) { Directory.CreateDirectory(dirName); } if (!cmd.IsConfirmed && File.Exists(fullFileName)) { player.Confirm(cmd, "The mapfile \"{0}\" already exists. Overwrite?", fileName); return; } } // generate the map Map map; player.MessageNow("Generating {0}...", templateFullName); if (genEmpty) { map = MapGenerator.GenerateEmpty(mapWidth, mapLength, mapHeight); } else if (genOcean) { map = MapGenerator.GenerateOcean(mapWidth, mapLength, mapHeight); } else if (genFlatgrass) { map = MapGenerator.GenerateFlatgrass(mapWidth, mapLength, mapHeight); } else { MapGeneratorArgs args = MapGenerator.MakeTemplate(template); if (theme == MapGenTheme.Desert) { args.AddWater = false; } float ratio = mapHeight / (float)args.MapHeight; args.MapWidth = mapWidth; args.MapLength = mapLength; args.MapHeight = mapHeight; args.MaxHeight = (int)Math.Round(args.MaxHeight * ratio); args.MaxDepth = (int)Math.Round(args.MaxDepth * ratio); args.SnowAltitude = (int)Math.Round(args.SnowAltitude * ratio); args.Theme = theme; args.AddTrees = !noTrees; MapGenerator generator = new MapGenerator(args); map = generator.Generate(); } // save map to file, or load it into a world if (fileName != null) { if (map.Save(fullFileName)) { player.Message("Generation done. Saved to {0}", fileName); } else { player.Message("&WAn error occured while saving generated map to {0}", fileName); } } else { if (playerWorld == null) PlayerOpException.ThrowNoWorld(player); player.MessageNow("Generation done. Changing map..."); playerWorld.MapChangedBy = player.Name; playerWorld.ChangeMap(map); } Server.RequestGC(); }
static void WorldSaveHandler(Player player, Command cmd) { string p1 = cmd.Next(), p2 = cmd.Next(); if (p1 == null) { CdWorldSave.PrintUsage(player); return; } World world = player.World; string fileName; if (p2 == null) { fileName = p1; if (world == null) { player.Message("When called from console, /wsave requires WorldName. See \"/Help save\" for details."); return; } } else { world = WorldManager.FindWorldOrPrintMatches(player, p1); if (world == null) return; fileName = p2; } // normalize the path fileName = fileName.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); if (fileName.EndsWith("/") && fileName.EndsWith(@"\")) { fileName += world.Name + ".fcm"; } else if (!fileName.ToLower().EndsWith(".fcm", StringComparison.OrdinalIgnoreCase)) { fileName += ".fcm"; } if (!Paths.IsValidPath(fileName)) { player.Message("Invalid filename."); return; } string fullFileName = Path.Combine(Paths.MapPath, fileName); if (!Paths.Contains(Paths.MapPath, fullFileName)) { player.MessageUnsafePath(); return; } // Ask for confirmation if overwriting if (File.Exists(fullFileName)) { FileInfo targetFile = new FileInfo(fullFileName); FileInfo sourceFile = new FileInfo(world.MapFileName); if (!targetFile.FullName.Equals(sourceFile.FullName, StringComparison.OrdinalIgnoreCase)) { if (!cmd.IsConfirmed) { player.Confirm(cmd, "Target file \"{0}\" already exists, and will be overwritten.", targetFile.Name); return; } } } // Create the target directory if it does not exist string dirName = fullFileName.Substring(0, fullFileName.LastIndexOf(Path.DirectorySeparatorChar)); if (!Directory.Exists(dirName)) { Directory.CreateDirectory(dirName); } player.MessageNow("Saving map to {0}", fileName); const string mapSavingErrorMessage = "Map saving failed. See server logs for details."; Map map = world.Map; if (map == null) { if (File.Exists(world.MapFileName)) { try { File.Copy(world.MapFileName, fullFileName, true); } catch (Exception ex) { Logger.Log(LogType.Error, "WorldCommands.WorldSave: Error occured while trying to copy an unloaded map: {0}", ex); player.Message(mapSavingErrorMessage); } } else { Logger.Log(LogType.Error, "WorldCommands.WorldSave: Map for world \"{0}\" is unloaded, and file does not exist.", world.Name); player.Message(mapSavingErrorMessage); } } else if (map.Save(fullFileName)) { player.Message("Map saved succesfully."); } else { Logger.Log(LogType.Error, "WorldCommands.WorldSave: Saving world \"{0}\" failed.", world.Name); player.Message(mapSavingErrorMessage); } }
static void GenHandler( Player player, CommandReader cmd ) { World playerWorld = player.World; World world = null; string fileName = null; int mapWidth, mapLength, mapHeight; // make sure the player has generator parameters set MapGeneratorParameters genParams = player.GenParams; if( genParams == null ) { player.Message( "No gen parameters set. Use &H/SetGen&S to configure map generation." ); return; } if( cmd.HasNext ) { // Something's given, assume that it's map dimensions. if( !(cmd.NextInt( out mapWidth ) && cmd.NextInt( out mapLength ) && cmd.NextInt( out mapHeight )) ) { CdGen.PrintUsage( player ); return; } } else if( playerWorld != null ) { // Nothing is given. Assume that we're replacing the current world. // Use dimensions of the currently-loaded map. Map oldMap = playerWorld.LoadMap(); mapWidth = oldMap.Width; mapLength = oldMap.Length; mapHeight = oldMap.Height; world = playerWorld; } else { player.Message( "When used from console, /Gen requires map dimensions." ); CdGen.PrintUsage( player ); return; } // Check map dimensions and volume const string dimensionRecommendation = "Dimensions must be between 16 and 2047. " + "Recommended values: 16, 32, 64, 128, 256, 512, and 1024."; if( !Map.IsValidDimension( mapWidth ) ) { player.Message( "Cannot make map with width {0}. {1}", mapWidth, dimensionRecommendation ); return; } else if( !Map.IsValidDimension( mapLength ) ) { player.Message( "Cannot make map with length {0}. {1}", mapLength, dimensionRecommendation ); return; } else if( !Map.IsValidDimension( mapHeight ) ) { player.Message( "Cannot make map with height {0}. {1}", mapHeight, dimensionRecommendation ); return; } long volume = (long)mapWidth*mapLength*mapHeight; if( volume > Int32.MaxValue ) { player.Message( "Map volume may not exceed {0}", Int32.MaxValue ); return; } // Print dimension warning, if applicable. if( !cmd.IsConfirmed && // Only print once -- before confirmation is given. (!Map.IsRecommendedDimension( mapWidth ) || !Map.IsRecommendedDimension( mapLength ) || mapHeight%16 != 0) ) { player.Message( "&WThe map will have non-standard dimensions. " + "You may see glitched blocks or visual artifacts. " + "The only recommended map dimensions are: 16, 32, 64, 128, 256, 512, and 1024." ); } // See what else the player has given us... string givenName = cmd.Next(); if( givenName == null ) { // No name given. Assume that we're replacing the current world. if( playerWorld != null ) { world = playerWorld; if( !cmd.IsConfirmed ) { Logger.Log( LogType.UserActivity, "Gen: Asked {0} to confirm replacing the map of world {1} (\"this map\")", player.Name, playerWorld.Name ); player.Confirm( cmd, "Gen: Replace THIS MAP with a generated one ({0})?", genParams ); return; } } else { player.Message( "When used from console, /Gen requires a world name or map file name." ); CdGen.PrintUsage( player ); return; } } else { // Either a world name or a filename was given. Check worlds first. World existingWorld = WorldManager.FindWorldExact( givenName ); if( existingWorld != null ) { // A matching world name found. Assume that we're replacing it. if( !cmd.IsConfirmed ) { Logger.Log( LogType.UserActivity, "Gen: Asked {0} to confirm replacing the map of world {1}", player.Name, existingWorld.Name ); player.Confirm( cmd, "Gen: Replace the map of world {0}&S with a generated one ({1})?", existingWorld.ClassyName, genParams ); return; } world = existingWorld; } else { // No world with this name found. Assume that we were given a filename. givenName = givenName.Replace( Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar ); if( !givenName.EndsWith( ".fcm", StringComparison.OrdinalIgnoreCase ) ) { givenName += ".fcm"; } if( !Paths.IsValidPath( givenName ) ) { player.Message( "Gen: Invalid file name given." ); return; } fileName = Path.Combine( Paths.MapPath, givenName ); if( !Paths.Contains( Paths.MapPath, fileName ) ) { player.MessageUnsafePath(); return; } if( File.Exists( fileName ) ) { if( !cmd.IsConfirmed ) { Logger.Log( LogType.UserActivity, "Gen: Asked {0} to confirm overwriting map file \"{1}\"", player.Name, givenName ); player.Confirm( cmd, "Gen: The map file \"{0}\" already exists. Overwrite?", givenName ); return; } } } } // Warn players on the affected world, if applicable if( world != null ) { world.Players .Except( player ) .Message( "&SIncoming map change!" ); } // Prepare to generate genParams.MapWidth = mapWidth; genParams.MapLength = mapLength; genParams.MapHeight = mapHeight; GenTaskParams genTaskParams = new GenTaskParams { Player = player, World = world, FileName = givenName, FullFileName = fileName, GenState = genParams.CreateGenerator() }; player.MessageNow( "Generating (please wait): {0}", genParams ); // Do the rest in a background thread Scheduler.NewBackgroundTask( GenTaskCallback, genTaskParams ) .RunOnce(); }
public static void RealmCreate(Player player, Command cmd, string themeName, string templateName) { MapGenTemplate template; MapGenTheme theme; int wx, wy, height = 128; if (!(cmd.NextInt(out wx) && cmd.NextInt(out wy) && cmd.NextInt(out height))) { if (player.World != null) { wx = 128; wy = 128; height = 128; } else { player.Message("When used from console, /gen requires map dimensions."); return; } cmd.Rewind(); cmd.Next(); cmd.Next(); } if (!Map.IsValidDimension(wx)) { player.Message("Cannot make map with width {0}: dimensions must be multiples of 16.", wx); return; } else if (!Map.IsValidDimension(wy)) { player.Message("Cannot make map with length {0}: dimensions must be multiples of 16.", wy); return; } else if (!Map.IsValidDimension(height)) { player.Message("Cannot make map with height {0}: dimensions must be multiples of 16.", height); return; } string fileName = player.Name; string fullFileName = null; if (fileName == null) { if (player.World == null) { player.Message("When used from console, /gen requires FileName."); return; } if (!cmd.IsConfirmed) { player.Confirm(cmd, "Replace this realm's map with a generated one?"); return; } } else { fileName = fileName.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); if (!fileName.EndsWith(".fcm", StringComparison.OrdinalIgnoreCase)) { fileName += ".fcm"; } fullFileName = Path.Combine(Paths.MapPath, fileName); if (!Paths.IsValidPath(fullFileName)) { player.Message("Invalid filename."); return; } if (!Paths.Contains(Paths.MapPath, fullFileName)) { player.MessageUnsafePath(); return; } string dirName = fullFileName.Substring(0, fullFileName.LastIndexOf(Path.DirectorySeparatorChar)); if (!Directory.Exists(dirName)) { Directory.CreateDirectory(dirName); } if (!cmd.IsConfirmed && File.Exists(fullFileName)) { player.Confirm(cmd, "The mapfile \"{0}\" already exists. Overwrite?", fileName); return; } } bool noTrees; if (themeName.Equals("grass", StringComparison.OrdinalIgnoreCase)) { theme = MapGenTheme.Forest; noTrees = true; } else { try { theme = (MapGenTheme)Enum.Parse(typeof(MapGenTheme), themeName, true); noTrees = (theme != MapGenTheme.Forest); } catch (Exception) { player.MessageNow("Unrecognized theme \"{0}\". Available themes are: Grass, {1}", themeName, String.Join(", ", Enum.GetNames(typeof(MapGenTheme)))); return; } } try { template = (MapGenTemplate)Enum.Parse(typeof(MapGenTemplate), templateName, true); } catch (Exception) { player.Message("Unrecognized template \"{0}\". Available templates are: {1}", templateName, String.Join(", ", Enum.GetNames(typeof(MapGenTemplate)))); return; } if (!Enum.IsDefined(typeof(MapGenTheme), theme) || !Enum.IsDefined(typeof(MapGenTemplate), template)) { return; } MapGeneratorArgs args = MapGenerator.MakeTemplate(template); args.MapWidth = wx; args.MapLength = wy; args.MapHeight = height; args.MaxHeight = (int)(args.MaxHeight / 80d * height); args.MaxDepth = (int)(args.MaxDepth / 80d * height); args.Theme = theme; args.AddTrees = !noTrees; Map map; try { if (theme == MapGenTheme.Forest && noTrees) { player.MessageNow("Generating Grass {0}...", template); } else { player.MessageNow("Generating {0} {1}...", theme, template); } if (theme == MapGenTheme.Forest && noTrees && template == MapGenTemplate.Flat) { map = MapGenerator.GenerateFlatgrass(args.MapWidth, args.MapLength, args.MapHeight); } else { MapGenerator generator = new MapGenerator(args); map = generator.Generate(); } } catch (Exception ex) { Logger.Log(LogType.Error, "MapGenerator: Generation failed: {0}", ex); player.MessageNow("&WAn error occured while generating the map."); return; } if (fileName != null) { if (map.Save(fullFileName)) { player.MessageNow("Generation done. Saved to {0}", fileName); } else { player.Message("&WAn error occured while saving generated map to {0}", fileName); } } else { player.MessageNow("Generation done. Changing map..."); player.World.ChangeMap(map); } }
static void DumpStatsHandler( Player player, CommandReader cmd ) { string fileName = cmd.Next(); if( fileName == null ) { CdDumpStats.PrintUsage( player ); return; } if( !Paths.Contains( Paths.WorkingPath, fileName ) ) { player.MessageUnsafePath(); return; } if( Paths.IsProtectedFileName( Path.GetFileName( fileName ) ) ) { player.Message( "You may not use this file." ); return; } string extension = Path.GetExtension( fileName ); if( extension == null || !extension.Equals( ".txt", StringComparison.OrdinalIgnoreCase ) ) { player.Message( "Stats file name must end with .txt" ); return; } if( File.Exists( fileName ) && !cmd.IsConfirmed ) { Logger.Log( LogType.UserActivity, "DumpStats: Asked {0} for confirmation to overwrite \"{1}\"", player.Name, fileName ); player.Confirm( cmd, "File \"{0}\" already exists. Overwrite?", Path.GetFileName( fileName ) ); return; } if( !Paths.TestFile( "DumpStats file", fileName, false, FileAccess.Write ) ) { player.Message( "Cannot create specified file. See log for details." ); return; } using( FileStream fs = File.Create( fileName ) ) { using( StreamWriter writer = new StreamWriter( fs ) ) { PlayerInfo[] infos = PlayerDB.PlayerInfoList; if( infos.Length == 0 ) { writer.WriteLine( "(TOTAL) (0 players)" ); writer.WriteLine(); } else { DumpPlayerGroupStats( writer, infos, "(TOTAL)" ); } List<PlayerInfo> rankPlayers = new List<PlayerInfo>(); foreach( Rank rank in RankManager.Ranks ) { rankPlayers.AddRange( infos.Where( t => t.Rank == rank ) ); if( rankPlayers.Count == 0 ) { writer.WriteLine( "{0}: 0 players, 0 banned, 0 inactive", rank.Name ); writer.WriteLine(); } else { DumpPlayerGroupStats( writer, rankPlayers, rank.Name ); } rankPlayers.Clear(); } } } player.Message( "Stats saved to \"{0}\"", fileName ); }
static void WorldClearSaveHandler(Player player, CommandReader cmd) { string WorldCSave = player.World.Name; if (player.World.Name == null) { CdWorldSave.PrintUsage(player); return; } World world = player.World; string fileName; fileName = WorldCSave; { world = WorldManager.FindWorldOrPrintMatches(player, WorldCSave); if (world == null) return; fileName = WorldCSave; } // normalize the path fileName = fileName.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); fileName = "World(" + WorldCSave + ")clear.fcm"; if (!Paths.IsValidPath(fileName)) { player.Message("Invalid file name."); return; } string fullFileName = Path.Combine(Paths.WClearPath, fileName); if (!Paths.Contains(Paths.WClearPath, fullFileName)) { player.MessageUnsafePath(); return; } // Ask for confirmation if overwriting if (File.Exists(fullFileName)) { FileInfo targetFile = new FileInfo(fullFileName); FileInfo sourceFile = new FileInfo(world.MapFileName); if (!targetFile.FullName.Equals(sourceFile.FullName, StringComparison.OrdinalIgnoreCase)) { if (!cmd.IsConfirmed) { Logger.Log(LogType.UserActivity, "WCSave: Asked {0} to confirm overwriting map file \"{1}\"", player.Name, targetFile.FullName); player.Confirm(cmd, "Target file \"{0}\" already exists, and will be overwritten.", targetFile.Name); return; } } } // Create the target directory if it does not exist string dirName = fullFileName.Substring(0, fullFileName.LastIndexOf(Path.DirectorySeparatorChar)); if (!Directory.Exists(dirName)) { Directory.CreateDirectory(dirName); } player.Message("Saving map to {0}", fileName); const string mapSavingErrorMessage = "Map saving failed. See server logs for details."; Map map = world.Map; if (map == null) { if (File.Exists(world.MapFileName)) { try { File.Copy(world.MapFileName, fullFileName, true); } catch (Exception ex) { Logger.Log(LogType.Error, "WorldCommands.WorldCSave: Error occurred while trying to copy an unloaded map: {0}", ex); player.Message(mapSavingErrorMessage); } } else { Logger.Log(LogType.Error, "WorldCommands.WorldCSave: Map for world \"{0}\" is unloaded, and file does not exist.", world.Name); player.Message(mapSavingErrorMessage); } } else if (map.Save(fullFileName)) { player.Message("Map saved succesfully."); } else { Logger.Log(LogType.Error, "WorldCommands.WorldCSave: Saving world \"{0}\" failed.", world.Name); player.Message(mapSavingErrorMessage); } }
// TODO: document the fact that this only promotes (unlike "/Import Ranks") static void ImportRankListHandler( Player player, CommandReader cmd ) { string fileName = cmd.Next(); string rankName = cmd.Next(); string reason = cmd.NextAll(); if( fileName == null || rankName == null ) { CdImportRankList.PrintUsage( player ); return; } // parse rank name Rank rank = RankManager.FindRank( rankName ); if( rank == null ) { player.MessageNoRank( rankName ); return; } // Make sure that the target file is legit if( !Paths.Contains( Paths.WorkingPath, fileName ) ) { Logger.Log( LogType.SuspiciousActivity, "ImportRankList: Player {0} tried to import from \"{1}\"", player.Name, fileName ); player.MessageUnsafePath(); return; } // Make sure file exists if( !File.Exists( fileName ) ) { player.Message( "Rank list file not found: " + fileName ); return; } // Read list of names from file. // Using List list to preserve capitalization and a HashSet to avoid duplicates. List<string> nameList = new List<string>(); using( StreamReader reader = new StreamReader( fileName ) ) { HashSet<string> lowerNameSet = new HashSet<string>(); while( true ) { string nextName = reader.ReadLine(); if( nextName == null ) break; if( !Player.IsValidPlayerName( nextName ) ) { player.Message( "ImportRankList: Invalid player name skipped: {0}", nextName ); continue; } string nameToLower = nextName.ToLowerInvariant(); if( lowerNameSet.Contains( nameToLower ) ) { player.Message( "ImportRankList: Skipping a duplicate name: {0}", nextName ); continue; } nameList.Add( nextName ); lowerNameSet.Add( nameToLower ); } } // Ask player to confirm before continuing if( !cmd.IsConfirmed ) { Logger.Log( LogType.UserActivity, "Import: Asked {0} to confirm importing {1} ranks from {2}", player.Name, nameList.Count, fileName ); player.Confirm( cmd, "ImportRankList: Are you sure you want to rank {0} players to {1}&S?", nameList.Count, rank.ClassyName ); return; } // Carry out the promotions int newPlayers = 0, promotedPlayers = 0, skippedPlayers = 0; foreach( string name in nameList ) { PlayerInfo info = PlayerDB.FindPlayerInfoExact( name ); if( info == null ) { // Create and promote a new record newPlayers++; PlayerInfo newInfo = PlayerDB.CreateNewPlayerInfo( name, RankChangeType.Promoted ); newInfo.ChangeRank( player, rank, reason, true, true, false ); Logger.Log( LogType.UserActivity, "ImportRankList: Created a new player record for {0}", name ); } else { // Check if an existing record needs updating if( info.Rank < rank && // don't demote anyone !info.IsBanned && // don't promote banned players info.RankChangeType != RankChangeType.Demoted && // don't re-promote demoted players info.RankChangeType != RankChangeType.AutoDemoted ) { // Promote! info.ChangeRank( player, rank, reason, true, true, false ); promotedPlayers++; } else { skippedPlayers++; } } } string successMsg = String.Format( "ImportRankList: Created {0} new records, promoted {1} players, " + "skipped {2} records from file \"{3}\"", newPlayers, promotedPlayers, skippedPlayers, Path.GetFileName( fileName ) ); Logger.Log( LogType.UserActivity, successMsg ); player.Message( successMsg ); }
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 + Map.SaveExt)) { // Try with extension added sourceFullFileName += Map.SaveExt; } else if (MonoCompat.IsCaseSensitive) { try { // If we're on a case-sensitive OS, try case-insensitive search FileInfo[] candidates = Paths.FindFiles(sourceFullFileName + Map.SaveExt); if (candidates.Length == 0) { candidates = Paths.FindFiles(sourceFullFileName); } switch (candidates.Length) { case 0: player.Message("File/directory not found: {0}", fileName); break; case 1: player.Message("File names are case-sensitive! Did you mean to load \"{0}\"?", candidates[0].Name); break; default: player.Message("File names are case-sensitive! Did you mean to load one of these: {0}", String.Join(", ", candidates.Select(c => c.Name).ToArray())); break; } } 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); }
public static void RealmCreate(Player player, Command cmd, string themeName, string templateName) { MapGenTemplate template; MapGenTheme theme; int wx, wy, height = 128; if (!(cmd.NextInt(out wx) && cmd.NextInt(out wy) && cmd.NextInt(out height))) { if (player.World != null) { wx = 128; wy = 128; height = 128; } else { player.Message("When used from console, /gen requires map dimensions."); return; } cmd.Rewind(); cmd.Next(); cmd.Next(); } if (!Map.IsValidDimension(wx)) { player.Message("Cannot make map with width {0}: dimensions must be multiples of 16.", wx); return; } else if (!Map.IsValidDimension(wy)) { player.Message("Cannot make map with length {0}: dimensions must be multiples of 16.", wy); return; } else if (!Map.IsValidDimension(height)) { player.Message("Cannot make map with height {0}: dimensions must be multiples of 16.", height); return; } string fileName = player.Name; if (player.Name.Contains('.')) { fileName = player.Name.Replace(".", "-"); //support for email names } string fullFileName = null; if (fileName == null) { if (player.World == null) { player.Message("When used from console, /gen requires FileName."); return; } if (!cmd.IsConfirmed) { player.Confirm(cmd, "Replace this realm's map with a generated one?"); return; } } else { fileName = fileName.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); if (!fileName.EndsWith(".fcm", StringComparison.OrdinalIgnoreCase)) { fileName += ".fcm"; } fullFileName = Path.Combine(Paths.MapPath, fileName); if (!Paths.IsValidPath(fullFileName)) { player.Message("Invalid filename."); return; } if (!Paths.Contains(Paths.MapPath, fullFileName)) { player.MessageUnsafePath(); return; } string dirName = fullFileName.Substring(0, fullFileName.LastIndexOf(Path.DirectorySeparatorChar)); if (!Directory.Exists(dirName)) { Directory.CreateDirectory(dirName); } if (!cmd.IsConfirmed && File.Exists(fullFileName)) { player.Confirm(cmd, "The mapfile \"{0}\" already exists. Overwrite?", fileName); return; } } bool noTrees; if (themeName.Equals("grass", StringComparison.OrdinalIgnoreCase)) { theme = MapGenTheme.Forest; noTrees = true; } else { try { theme = (MapGenTheme)Enum.Parse(typeof(MapGenTheme), themeName, true); noTrees = (theme != MapGenTheme.Forest); } catch (Exception) { player.MessageNow("Unrecognized theme \"{0}\". Available themes are: Grass, {1}", themeName, String.Join(", ", Enum.GetNames(typeof(MapGenTheme)))); return; } } try { template = (MapGenTemplate)Enum.Parse(typeof(MapGenTemplate), templateName, true); } catch (Exception) { player.Message("Unrecognized template \"{0}\". Available templates are: {1}", templateName, String.Join(", ", Enum.GetNames(typeof(MapGenTemplate)))); return; } if (!Enum.IsDefined(typeof(MapGenTheme), theme) || !Enum.IsDefined(typeof(MapGenTemplate), template)) { return; } MapGeneratorArgs args = MapGenerator.MakeTemplate(template); args.MapWidth = wx; args.MapLength = wy; args.MapHeight = height; args.MaxHeight = (int)(args.MaxHeight / 80d * height); args.MaxDepth = (int)(args.MaxDepth / 80d * height); args.Theme = theme; args.AddTrees = !noTrees; Map map; try { if (theme == MapGenTheme.Forest && noTrees) { player.MessageNow("Generating Grass {0}...", template); } else { player.MessageNow("Generating {0} {1}...", theme, template); } if (theme == MapGenTheme.Forest && noTrees && template == MapGenTemplate.Flat) { map = MapGenerator.GenerateFlatgrass(args.MapWidth, args.MapLength, args.MapHeight); } else { MapGenerator generator = new MapGenerator(args); map = generator.Generate(); } } catch (Exception ex) { Logger.Log(LogType.Error, "MapGenerator: Generation failed: {0}", ex); player.MessageNow("&WAn error occured while generating the map."); return; } if (fileName != null) { if (map.Save(fullFileName)) { player.MessageNow("Generation done. Saved to {0}", fileName); } else { player.Message("&WAn error occured while saving generated map to {0}", fileName); } } else { player.MessageNow("Generation done. Changing map..."); player.World.ChangeMap(map); } }