internal static void DumpStats( Player player, Command cmd ) { string fileName = cmd.Next(); if( fileName == null ) { cdDumpStats.PrintUsage( player ); return; } if( !Paths.Contains( Paths.WorkingPath, fileName ) ) { player.UnsafePathMessage(); return; } if( Paths.IsProtectedFileName( Path.GetFileName( fileName ) ) ) { player.Message( "You may not use this file." ); return; } if( Path.HasExtension( fileName ) && !Path.GetExtension( fileName ).Equals( ".txt", StringComparison.OrdinalIgnoreCase ) ) { player.Message( "Stats filename must end with .txt" ); return; } if( File.Exists( fileName ) && !cmd.IsConfirmed ) { player.AskForConfirmation( cmd, "File \"{0}\" already exists. Overwrite?", Path.GetFileName( fileName ) ); return; } if( !Paths.TestFile( "dumpstats file", fileName, false, true, false ) ) { 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.GetPlayerListCopy(); if( infos.Length == 0 ) { writer.WriteLine( "{0} (0 players)", "(TOTAL)" ); writer.WriteLine(); } else { DumpPlayerGroupStats( writer, infos, "(TOTAL)" ); } foreach( Rank rank in RankManager.Ranks ) { infos = PlayerDB.GetPlayerListCopy( rank ); if( infos.Length == 0 ) { writer.WriteLine( "{0} (0 players)", rank.Name ); writer.WriteLine(); } else { DumpPlayerGroupStats( writer, infos, rank.Name ); } } } } player.Message( "Stats saved to \"{0}\"", Path.GetFileName( fileName ) ); }
internal static void WorldLoad( Player player, Command cmd ) { string fileName = cmd.Next(); string worldName = cmd.Next(); if( worldName == null && player.World == null ) { player.Message( "When using /wload from console, you must specify the world name." ); return; } if( fileName == null ) { // No params given at all cdWorldLoad.PrintUsage( player ); return; } // Check if path contains missing drives or invalid characters if( !Paths.IsValidPath( fileName ) ) { player.Message( "Invalid filename or path." ); return; } player.MessageNow( "Looking for \"{0}\"...", fileName ); // 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 fileName += ".fcm"; 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( "Filenames are case-sensitive! Did you mean to load \"{0}\"?", candidates[0].Name ); } else { player.Message( "Filenames 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; } else { // Nothing found! player.Message( "File/directory not found: {0}", fileName ); return; } } // Make sure that the given file is within the map directory if( !Paths.Contains( Paths.MapPath, sourceFullFileName ) ) { player.UnsafePathMessage(); return; } // Loading map into current world if( worldName == null ) { if( !cmd.IsConfirmed ) { player.AskForConfirmation( cmd, "About to replace THIS MAP with \"{0}\".", fileName ); return; } Map map; try { map = MapUtility.Load( sourceFullFileName ); } catch( Exception ex ) { player.MessageNow( "Could not load specified file: {0}: {1}", ex.GetType().Name, ex.Message ); return; } // Loading to current world player.World.ChangeMap( map ); player.World.SendToAllExcept( "{0}&S loaded a new map for this world.", player, player.GetClassyName() ); player.MessageNow( "New map loaded for the world {0}", player.World.GetClassyName() ); Logger.Log( "{0} loaded new map for world \"{1}\" from {2}", LogType.UserActivity, player.Name, player.World.Name, fileName ); } else { // Loading to some other (or new) world if( !World.IsValidName( worldName ) ) { player.MessageNow( "Invalid world name: \"{0}\".", worldName ); return; } lock( WorldManager.WorldListLock ) { World world = WorldManager.FindWorldExact( worldName ); if( world != null ) { // Replacing existing world's map if( !cmd.IsConfirmed ) { player.AskForConfirmation( cmd, "About to replace map for {0}&S with \"{1}\".", world.GetClassyName(), fileName ); return; } Map map; try { map = MapUtility.Load( sourceFullFileName ); } catch( Exception ex ) { player.MessageNow( "Could not load specified file: {0}: {1}", ex.GetType().Name, ex.Message ); return; } try { world.ChangeMap( map ); } catch( WorldOpException ex ) { Logger.Log( "Could not complete WorldLoad operation: {0}", LogType.Error, ex.Message ); player.Message( "&WWLoad: {0}", ex.Message ); return; } world.SendToAllExcept( "{0}&S loaded a new map for the world {1}", player, player.GetClassyName(), world.GetClassyName() ); player.MessageNow( "New map for the world {0}&S has been loaded.", world.GetClassyName() ); Logger.Log( "{0} loaded new map for world \"{1}\" from {2}", LogType.UserActivity, player.Name, world.Name, sourceFullFileName ); } else { // Adding a new world string targetFullFileName = Path.Combine( Paths.MapPath, worldName + ".fcm" ); if( !cmd.IsConfirmed && File.Exists( targetFullFileName ) && // target file already exists !Paths.Compare( targetFullFileName, sourceFullFileName ) ) { // and is different from sourceFile player.AskForConfirmation( cmd, "A map named \"{0}\" already exists, and will be overwritten with \"{1}\".", Path.GetFileName( targetFullFileName ), Path.GetFileName( sourceFullFileName ) ); return; } Map map; try { map = MapUtility.Load( sourceFullFileName ); } catch( Exception ex ) { player.MessageNow( "Could not load \"{0}\": {1}: {2}", fileName, ex.GetType().Name, ex.Message ); return; } World newWorld; try { newWorld = WorldManager.AddWorld( player, worldName, map, false ); } catch( WorldOpException ex ) { player.Message( "WLoad: {0}", ex.Message ); return; } if( newWorld != null ) { newWorld.BuildSecurity.MinRank = RankManager.ParseRank( ConfigKey.DefaultBuildRank.GetString() ); Server.SendToAll( "{0}&S created a new world named {1}", player.GetClassyName(), newWorld.GetClassyName() ); Logger.Log( "{0} created a new world named \"{1}\" (loaded from \"{2}\")", LogType.UserActivity, player.Name, worldName, fileName ); WorldManager.SaveWorldList(); player.MessageNow( "Reminder: New world's access permission is {0}+&S, and build permission is {1}+", newWorld.AccessSecurity.MinRank.GetClassyName(), newWorld.BuildSecurity.MinRank.GetClassyName() ); } else { player.MessageNow( "Failed to create a new world." ); } } } } Server.RequestGC(); }
internal static void WorldSave( 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, /save 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"; } string fullFileName = Path.Combine( Paths.MapPath, fileName ); if( !Paths.IsValidPath( fullFileName ) ) { player.Message( "Invalid filename." ); return; } if( !Paths.Contains( Paths.MapPath, fullFileName ) ) { player.UnsafePathMessage(); return; } // Ask for confirmation if overwriting if( File.Exists( fullFileName ) ) { FileInfo targetFile = new FileInfo( fullFileName ); FileInfo sourceFile = new FileInfo( world.GetMapName() ); if( !targetFile.FullName.Equals( sourceFile.FullName, StringComparison.OrdinalIgnoreCase ) ) { if( !cmd.IsConfirmed ) { player.AskForConfirmation( 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.GetMapName() ) ) { try { File.Copy( world.GetMapName(), fullFileName, true ); } catch( Exception ex ) { Logger.Log( "StandardCommands.Save: Error occured while trying to copy an unloaded map: {0}", LogType.Error, ex ); player.Message( mapSavingErrorMessage ); } } else { Logger.Log( "StandardCommands.Save: Map for world \"{0}\" is unloaded, and file does not exist.", LogType.Error, world.Name ); player.Message( mapSavingErrorMessage ); } } else if( map.Save( fullFileName ) ) { player.Message( "Map saved succesfully." ); } else { Logger.Log( "StandardCommands.Save: Saving world \"{0}\" failed.", LogType.Error, world.Name ); player.Message( mapSavingErrorMessage ); } }
internal static void Generate( Player player, Command cmd ) { string themeName = cmd.Next(); string templateName = cmd.Next(); if( templateName == null ) { cdGenerate.PrintUsage( player ); return; } MapGenTemplate template; MapGenTheme theme; int wx, wy, height; if( !(cmd.NextInt( out wx ) && cmd.NextInt( out wy ) && cmd.NextInt( out height )) ) { if( player.World != null ) { wx = player.World.Map.WidthX; wy = player.World.Map.WidthY; height = player.World.Map.Height; } else { player.Message( "When used from console, /gen requires map dimensions." ); cdGenerate.PrintUsage( player ); 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 = cmd.Next(); string fullFileName = null; if( fileName == null ) { if( player.World == null ) { player.Message( "When used from console, /gen requires FileName." ); cdGenerate.PrintUsage( player ); return; } if( !cmd.IsConfirmed ) { player.AskForConfirmation( cmd, "Replace this world'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.UnsafePathMessage(); return; } string dirName = fullFileName.Substring( 0, fullFileName.LastIndexOf( Path.DirectorySeparatorChar ) ); if( !Directory.Exists( dirName ) ) { Directory.CreateDirectory( dirName ); } if( !cmd.IsConfirmed && File.Exists( fullFileName ) ) { player.AskForConfirmation( 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 ) ) { cdGenerate.PrintUsage( player ); return; } MapGeneratorArgs args = MapGenerator.MakeTemplate( template ); args.WidthX = wx; args.WidthY = wy; args.Height = 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 = new Map( null, args.WidthX, args.WidthY, args.Height, true ); MapGenerator.GenerateFlatgrass( map ); } else { MapGenerator generator = new MapGenerator( args ); map = generator.Generate(); } map.ResetSpawn(); } catch( Exception ex ) { Logger.Log( "MapGenerator: Generation failed: {0}", LogType.Error, 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 ); } }