static void ZoneMarkHandler(Player player, CommandReader cmd) { if (player.SelectionMarksExpected == 0) { player.MessageNow("Cannot use ZMark - no selection in progress."); } else if (player.SelectionMarksExpected == 2) { string zoneName = cmd.Next(); if (zoneName == null) { CdZoneMark.PrintUsage(player); return; } Zone zone = player.WorldMap.Zones.Find(zoneName); if (zone == null) { player.MessageNoZone(zoneName); return; } player.SelectionResetMarks(); player.SelectionAddMark(zone.Bounds.MinVertex, false); player.SelectionAddMark(zone.Bounds.MaxVertex, true); } else { player.MessageNow("ZMark can only be used for 2-block selection."); } }
static void CopyCallback([NotNull] Player player, [NotNull] Vector3I[] marks, [NotNull] object tag) { int sx = Math.Min(marks[0].X, marks[1].X); int ex = Math.Max(marks[0].X, marks[1].X); int sy = Math.Min(marks[0].Y, marks[1].Y); int ey = Math.Max(marks[0].Y, marks[1].Y); int sz = Math.Min(marks[0].Z, marks[1].Z); int ez = Math.Max(marks[0].Z, marks[1].Z); BoundingBox bounds = new BoundingBox(sx, sy, sz, ex, ey, ez); int volume = bounds.Volume; if (!player.CanDraw(volume)) { player.MessageNow( "You are only allowed to run commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, volume); return; } // remember dimensions and orientation CopyState copyInfo = new CopyState(marks[0], marks[1]); Map map = player.WorldMap; World playerWorld = player.World; if (playerWorld == null) { PlayerOpException.ThrowNoWorld(player); } for (int x = sx; x <= ex; x++) { for (int y = sy; y <= ey; y++) { for (int z = sz; z <= ez; z++) { copyInfo.Blocks[x - sx, y - sy, z - sz] = map.GetBlock(x, y, z); } } } copyInfo.OriginWorld = playerWorld.Name; copyInfo.CopyTime = DateTime.UtcNow; player.SetCopyState(copyInfo); player.MessageNow("{0} blocks copied into slot #{1}, origin at {2} corner. You can now &H/Paste", volume, player.CopySlot + 1, copyInfo.OriginCorner); Logger.Log(LogType.UserActivity, "{0} copied {1} blocks from world {2} (between {3} and {4}).", player.Name, volume, playerWorld.Name, bounds.MinVertex, bounds.MaxVertex); }
static void ZoneMarkHandler([NotNull] Player player, [NotNull] CommandReader cmd) { switch (player.SelectionMarksExpected) { case 0: player.MessageNow("Cannot use ZMark - no selection in progress."); break; case 2: { string zoneName = cmd.Next(); if (zoneName == null) { CdZoneMark.PrintUsage(player); return; } Zone zone = player.WorldMap.Zones.Find(zoneName); if (zone == null) { player.MessageNoZone(zoneName); return; } player.SelectionResetMarks(); player.SelectionAddMark(zone.Bounds.MinVertex, false, false); player.SelectionAddMark(zone.Bounds.MaxVertex, false, true); } break; default: player.MessageNow("ZMark can only be used with 2-block/2-click selections."); break; } }
static void ListIgnoredPlayers(Player player) { PlayerInfo[] ignoreList = player.IgnoreList; if (ignoreList.Length > 0) { player.MessageNow("Ignored players: {0}", ignoreList.JoinToClassyString()); } else { player.MessageNow("You are not currently ignoring anyone."); } }
internal static void Unignore(Player player, Command cmd) { string name = cmd.Next(); if (name != null) { PlayerInfo targetInfo; if (!PlayerDB.FindPlayerInfo(name, out targetInfo)) { PlayerInfo[] infos = PlayerDB.FindPlayers(name); if (infos.Length == 1) { targetInfo = infos[0]; } else if (infos.Length > 1) { player.ManyMatchesMessage("player", infos); return; } else { player.NoPlayerMessage(name); return; } } else if (targetInfo == null) { player.NoPlayerMessage(name); return; } if (player.Unignore(targetInfo)) { player.MessageNow("You are no longer ignoring {0}", targetInfo.GetClassyName()); } else { player.MessageNow("You are not currently ignoring {0}", targetInfo.GetClassyName()); } } else { PlayerInfo[] ignoreList = player.GetIgnoreList(); if (ignoreList.Length > 0) { player.MessageNow("Ignored players: {0}", ignoreList.JoinToClassyString()); } else { player.MessageNow("You are not currently ignoring anyone."); } return; } }
internal static void Deafen(Player player, Command cmd) { if (!player.IsDeaf) { player.MessageNow("Deafened mode: ON"); player.MessageNow("You will not see any messages until you type &H/deafen&S again."); player.IsDeaf = true; } else { player.IsDeaf = false; player.MessageNow("Deafened mode: OFF"); } }
static void RedoHandler([NotNull] Player player, [NotNull] CommandReader cmd) { if (cmd.HasNext) { CdRedo.PrintUsage(player); return; } World playerWorld = player.World; if (playerWorld == null) { PlayerOpException.ThrowNoWorld(player); } UndoState redoState = player.RedoPop(); if (redoState == null) { player.MessageNow("There is currently nothing to redo."); return; } string msg = "Redo: "; if (redoState.Op != null && !redoState.Op.IsDone) { redoState.Op.Cancel(); msg += String.Format("Cancelled {0} (was {1}% done). ", redoState.Op.Description, redoState.Op.PercentDone); } // no need to set player.drawingInProgress here because this is done on the user thread Logger.Log(LogType.UserActivity, "Player {0} initiated /Redo affecting {1} blocks (on world {2})", player.Name, redoState.Buffer.Count, playerWorld.Name); msg += String.Format("Restoring {0} blocks. Type &H/Undo&S to reverse.", redoState.Buffer.Count); player.MessageNow(msg); var op = new UndoDrawOperation(player, redoState, true); op.Prepare(new Vector3I[0]); op.Begin(); }
static void MarkHandler([NotNull] Player player, [NotNull] CommandReader cmd) { Map map = player.WorldMap; int x, y, z; Vector3I coords; if (cmd.NextInt(out x) && cmd.NextInt(out y) && cmd.NextInt(out z)) { if (cmd.HasNext) { CdMark.PrintUsage(player); return; } coords = new Vector3I(x, y, z); } else { coords = player.Position.ToBlockCoords(); } coords.X = Math.Min(map.Width - 1, Math.Max(0, coords.X)); coords.Y = Math.Min(map.Length - 1, Math.Max(0, coords.Y)); coords.Z = Math.Min(map.Height - 1, Math.Max(0, coords.Z)); if (player.SelectionMarksExpected > 0) { player.SelectionAddMark(coords, true, true); } else { player.MessageNow("Cannot mark - no selection in progress."); } }
static void ListIgnoredPlayers([NotNull] Player player) { if (player == null) { throw new ArgumentNullException("player"); } PlayerInfo[] ignoreList = player.IgnoreList; if (ignoreList.Length > 0) { player.MessageNow("Ignored players: {0}", ignoreList.JoinToClassyString()); } else { player.MessageNow("You are not currently ignoring anyone."); } }
static void IgnoreHandler(Player player, CommandReader cmd) { string name = cmd.Next(); if (name != null) { if (cmd.HasNext) { CdIgnore.PrintUsage(player); return; } PlayerInfo targetInfo = PlayerDB.FindByPartialNameOrPrintMatches(player, name); if (targetInfo == null) { return; } if (targetInfo == player.Info) { player.MessageNow("You cannot ignore yourself."); return; } if (player.Ignore(targetInfo)) { player.MessageNow("You are now ignoring {0}", targetInfo.ClassyName); } else { player.MessageNow("You are already ignoring {0}", targetInfo.ClassyName); } } else { PlayerInfo[] ignoreList = player.IgnoreList; if (ignoreList.Length > 0) { player.MessageNow("Ignored players: {0}", ignoreList.JoinToClassyString()); } else { player.MessageNow("You are not currently ignoring anyone."); } } }
static void ReplyHandler([NotNull] Player player, [NotNull] CommandReader cmd) { string messageText = cmd.NextAll(); if (messageText.Length == 0) { player.Message("Reply: No message to send!"); return; } string targetName = player.LastPrivateMessageSender; if (targetName != null) { Player targetPlayer = Server.FindPlayerExact(player, targetName, SearchOptions.IncludeHidden); if (targetPlayer != null) { if (player.CanSee(targetPlayer)) { if (targetPlayer.IsDeaf) { player.Message("Cannot PM {0}&S: they are currently deaf.", targetPlayer.ClassyName); } else if (targetPlayer.IsIgnoring(player.Info)) { player.Message("&WCannot PM {0}&W: you are ignored.", targetPlayer.ClassyName); } else { Chat.SendPM(player, targetPlayer, messageText); player.MessageNow("&Pto {0}: {1}", targetPlayer.Name, messageText); } } else { player.Message("Reply: Cannot send message; player {0}&S is offline.", PlayerDB.FindExactClassyName(targetName)); if (targetPlayer.CanHear(player)) { Chat.SendPM(player, targetPlayer, messageText); player.Info.DecrementMessageWritten(); } } } else { player.Message("Reply: Cannot send message; player {0}&S is offline.", PlayerDB.FindExactClassyName(targetName)); } } else { player.Message("Reply: You have not sent any messages yet."); } }
static void CopyHandler([NotNull] Player player, [NotNull] CommandReader cmd) { if (cmd.HasNext) { CdCopy.PrintUsage(player); return; } player.SelectionStart(2, CopyCallback, null, CdCopy.Permissions); player.MessageNow("Copy: Click or &H/Mark&S 2 blocks."); }
static void UnignoreHandler(Player player, Command cmd) { string name = cmd.Next(); if (name != null) { if (cmd.HasNext) { CdUnignore.PrintUsage(player); return; } PlayerInfo targetInfo = PlayerDB.FindPlayerInfoOrPrintMatches(player, name); if (targetInfo == null) { return; } if (player.Unignore(targetInfo)) { player.MessageNow("You are no longer ignoring {0}", targetInfo.ClassyName); } else { player.MessageNow("You are not currently ignoring {0}", targetInfo.ClassyName); } } else { PlayerInfo[] ignoreList = player.IgnoreList; if (ignoreList.Length > 0) { player.MessageNow("Ignored players: {0}", ignoreList.JoinToClassyString()); } else { player.MessageNow("You are not currently ignoring anyone."); } return; } }
static void UnignoreHandler([NotNull] Player player, [NotNull] CommandReader cmd) { string name = cmd.Next(); if (name != null) { if (cmd.HasNext) { // too many parameters given CdUnignore.PrintUsage(player); return; } // A name was given -- let's find the target PlayerInfo targetInfo = PlayerDB.FindPlayerInfoOrPrintMatches(player, name, SearchOptions.ReturnSelfIfOnlyMatch); if (targetInfo == null) { return; } if (targetInfo == player.Info) { player.Message("You cannot &H/Ignore&S (or &H/Unignore&S) yourself."); return; } if (player.Unignore(targetInfo)) { player.MessageNow("You are no longer ignoring {0}", targetInfo.ClassyName); } else { player.MessageNow("You are not currently ignoring {0}", targetInfo.ClassyName); } } else { ListIgnoredPlayers(player); } }
private static void DeafenHandler(Player player, Command cmd) { if (cmd.HasNext) { CdDeafen.PrintUsage(player); return; } if (!player.IsDeaf) { for (int i = 0; i < LinesToClear; i++) { player.MessageNow(""); } player.MessageNow("&WDeafened mode is now on."); player.MessageNow("&SYou will not see any chat messages until you type &H/Deafen&S again."); player.IsDeaf = true; } else { player.IsDeaf = false; player.MessageNow("&WDeafened mode is now off."); } }
static void DeafenHandler([NotNull] Player player, [NotNull] CommandReader cmd) { if (cmd.HasNext) { CdDeafen.PrintUsage(player); return; } if (!player.IsDeaf) { for (int i = 0; i < LinesToClear; i++) { player.MessageNow(""); } player.MessageNow("Deafened mode: ON"); player.MessageNow("You will not see ANY messages until you type &H/Deafen&S again."); player.IsDeaf = true; } else { player.IsDeaf = false; player.MessageNow("Deafened mode: OFF"); } }
private static void OnCreate(Player p, Command cmd) { LifeHandler handler = new LifeHandler(); if (!handler.CheckAndGetLifeZone(p, cmd)) { return; } if (!handler.CheckWorldPermissions(p)) { return; } if (null != handler._life) { p.Message("&WLife with such name exists already, choose another"); return; } p.SelectionStart(2, handler.LifeCreateCallback, null, Permission.DrawAdvanced); p.MessageNow("Select life zone: place/remove a block or type /Mark to use your location."); }
static void ReplyHandler( Player player, CommandReader cmd ) { string messageText = cmd.NextAll(); if( messageText.Length == 0 ) { player.Message( "Reply: No message to send!" ); return; } string targetName = player.lastPrivateMessageSender; if( targetName != null ) { Player targetPlayer = Server.FindPlayerExact( player, targetName, SearchOptions.IncludeHidden ); if( targetPlayer != null ) { if( player.CanSee( targetPlayer ) ) { if( targetPlayer.IsDeaf ) { player.Message( "Cannot PM {0}&S: they are currently deaf.", targetPlayer.ClassyName ); } else if( targetPlayer.IsIgnoring( player.Info ) ) { player.Message( "&WCannot PM {0}&W: you are ignored.", targetPlayer.ClassyName ); } else { Chat.SendPM( player, targetPlayer, messageText ); player.MessageNow( "&Pto {0}: {1}", targetPlayer.Name, messageText ); } } else { player.Message( "Reply: Cannot send message; player {0}&S is offline.", PlayerDB.FindExactClassyName( targetName ) ); if( targetPlayer.CanHear( player ) ) { Chat.SendPM( player, targetPlayer, messageText ); player.Info.DecrementMessageWritten(); } } } else { player.Message( "Reply: Cannot send message; player {0}&S is offline.", PlayerDB.FindExactClassyName( targetName ) ); } } else { player.Message( "Reply: You have not sent any messages yet." ); } }
static void ReplaceHandlerInternal( IBrush factory, Player player, CommandReader cmd ) { CuboidDrawOperation op = new CuboidDrawOperation( player ); IBrushInstance brush = factory.MakeInstance( player, cmd, op ); if( brush == null ) return; op.Brush = brush; player.SelectionStart( 2, DrawOperationCallback, op, Permission.Draw ); player.MessageNow( "{0}: Click or &H/Mark&S 2 blocks.", op.Brush.InstanceDescription ); }
static void UndoAreaNotHandler( Player player, CommandReader cmd ) { BlockDBUndoArgs args = ParseBlockDBUndoParams( player, cmd, "UndoAreaNot", true ); if( args == null ) return; player.SelectionStart( 2, UndoAreaSelectionCallback, args, CdUndoAreaNot.Permissions ); player.MessageNow( "UndoAreaNot: Click or &H/Mark&S 2 blocks." ); }
static void MarkHandler( Player player, CommandReader cmd ) { Map map = player.WorldMap; int x, y, z; Vector3I coords; if( cmd.NextInt( out x ) && cmd.NextInt( out y ) && cmd.NextInt( out z ) ) { if( cmd.HasNext ) { CdMark.PrintUsage( player ); return; } coords = new Vector3I( x, y, z ); } else { coords = player.Position.ToBlockCoords(); } coords.X = Math.Min( map.Width - 1, Math.Max( 0, coords.X ) ); coords.Y = Math.Min( map.Length - 1, Math.Max( 0, coords.Y ) ); coords.Z = Math.Min( map.Height - 1, Math.Max( 0, coords.Z ) ); if( player.SelectionMarksExpected > 0 ) { player.SelectionAddMark( coords, true, true ); } else { player.MessageNow( "Cannot mark - no selection in progress." ); } }
static void RestoreHandler( Player player, CommandReader cmd ) { string fileName = cmd.Next(); if( fileName == null ) { CdRestore.PrintUsage( player ); return; } if( cmd.HasNext ) { CdRestore.PrintUsage( player ); return; } string fullFileName = WorldManager.FindMapFile( player, fileName ); if( fullFileName == null ) return; Map map; if( !MapUtility.TryLoad( fullFileName, true, out map ) ) { player.Message( "Could not load the given map file ({0})", fileName ); return; } Map playerMap = player.WorldMap; if( playerMap.Width != map.Width || playerMap.Length != map.Length || playerMap.Height != map.Height ) { player.Message( "Map file dimensions must match your current world's dimensions ({0}x{1}x{2})", playerMap.Width, playerMap.Length, playerMap.Height ); return; } map.Metadata["fCraft.Temp", "FileName"] = fullFileName; player.SelectionStart( 2, RestoreCallback, map, CdRestore.Permissions ); player.MessageNow( "Restore: Click or &H/Mark&S 2 blocks." ); }
static void RotateHandler( Player player, CommandReader cmd ) { CopyState originalInfo = player.GetCopyState(); if( originalInfo == null ) { player.MessageNow( "Nothing to rotate! Copy something first." ); return; } int degrees; if( !cmd.NextInt( out degrees ) || (degrees != 90 && degrees != -90 && degrees != 180 && degrees != 270) ) { CdRotate.PrintUsage( player ); return; } string axisName = cmd.Next(); Axis axis = Axis.Z; if( axisName != null ) { switch( axisName.ToLower() ) { case "x": axis = Axis.X; break; case "y": axis = Axis.Y; break; case "z": case "h": axis = Axis.Z; break; default: CdRotate.PrintUsage( player ); return; } } // allocate the new buffer Block[, ,] oldBuffer = originalInfo.Blocks; Block[, ,] newBuffer; if( degrees == 180 ) { newBuffer = new Block[oldBuffer.GetLength( 0 ), oldBuffer.GetLength( 1 ), oldBuffer.GetLength( 2 )]; } else if( axis == Axis.X ) { newBuffer = new Block[oldBuffer.GetLength( 0 ), oldBuffer.GetLength( 2 ), oldBuffer.GetLength( 1 )]; } else if( axis == Axis.Y ) { newBuffer = new Block[oldBuffer.GetLength( 2 ), oldBuffer.GetLength( 1 ), oldBuffer.GetLength( 0 )]; } else { // axis == Axis.Z newBuffer = new Block[oldBuffer.GetLength( 1 ), oldBuffer.GetLength( 0 ), oldBuffer.GetLength( 2 )]; } // clone to avoid messing up any paste-in-progress CopyState info = new CopyState( originalInfo, newBuffer ); // construct the rotation matrix int[,] matrix = { {1,0,0}, {0,1,0}, {0,0,1} }; int a, b; switch( axis ) { case Axis.X: a = 1; b = 2; break; case Axis.Y: a = 0; b = 2; break; default: a = 0; b = 1; break; } switch( degrees ) { case 90: matrix[a, a] = 0; matrix[b, b] = 0; matrix[a, b] = -1; matrix[b, a] = 1; break; case 180: matrix[a, a] = -1; matrix[b, b] = -1; break; case -90: case 270: matrix[a, a] = 0; matrix[b, b] = 0; matrix[a, b] = 1; matrix[b, a] = -1; break; } // apply the rotation matrix for( int x = oldBuffer.GetLength( 0 ) - 1; x >= 0; x-- ) { for( int y = oldBuffer.GetLength( 1 ) - 1; y >= 0; y-- ) { for( int z = oldBuffer.GetLength( 2 ) - 1; z >= 0; z-- ) { int nx = (matrix[0, 0] < 0 ? oldBuffer.GetLength( 0 ) - 1 - x : (matrix[0, 0] > 0 ? x : 0)) + (matrix[0, 1] < 0 ? oldBuffer.GetLength( 1 ) - 1 - y : (matrix[0, 1] > 0 ? y : 0)) + (matrix[0, 2] < 0 ? oldBuffer.GetLength( 2 ) - 1 - z : (matrix[0, 2] > 0 ? z : 0)); int ny = (matrix[1, 0] < 0 ? oldBuffer.GetLength( 0 ) - 1 - x : (matrix[1, 0] > 0 ? x : 0)) + (matrix[1, 1] < 0 ? oldBuffer.GetLength( 1 ) - 1 - y : (matrix[1, 1] > 0 ? y : 0)) + (matrix[1, 2] < 0 ? oldBuffer.GetLength( 2 ) - 1 - z : (matrix[1, 2] > 0 ? z : 0)); int nz = (matrix[2, 0] < 0 ? oldBuffer.GetLength( 0 ) - 1 - x : (matrix[2, 0] > 0 ? x : 0)) + (matrix[2, 1] < 0 ? oldBuffer.GetLength( 1 ) - 1 - y : (matrix[2, 1] > 0 ? y : 0)) + (matrix[2, 2] < 0 ? oldBuffer.GetLength( 2 ) - 1 - z : (matrix[2, 2] > 0 ? z : 0)); newBuffer[nx, ny, nz] = oldBuffer[x, y, z]; } } } player.Message( "Rotated copy (slot {0}) by {1} degrees around {2} axis.", info.Slot + 1, degrees, axis ); player.SetCopyState( info ); }
static void CopyHandler( Player player, Command cmd ) { if( cmd.HasNext ) { CdCopy.PrintUsage( player ); return; } player.SelectionStart( 2, CopyCallback, null, CdCopy.Permissions ); player.MessageNow( "Copy: Place a block or type /Mark to use your location." ); }
static void RotateHandler([NotNull] Player player, [NotNull] CommandReader cmd) { CopyState originalInfo = player.GetCopyState(); if (originalInfo == null) { player.MessageNow("Nothing to rotate! Copy something first."); return; } int degrees; if (!cmd.NextInt(out degrees) || (degrees != 90 && degrees != -90 && degrees != 180 && degrees != 270)) { CdRotate.PrintUsage(player); return; } string axisName = cmd.Next(); Axis axis = Axis.Z; if (axisName != null) { switch (axisName.ToLower()) { case "x": axis = Axis.X; break; case "y": axis = Axis.Y; break; case "z": case "h": axis = Axis.Z; break; default: CdRotate.PrintUsage(player); return; } } // allocate the new buffer Block[,,] oldBuffer = originalInfo.Blocks; Block[,,] newBuffer; if (degrees == 180) { newBuffer = new Block[oldBuffer.GetLength(0), oldBuffer.GetLength(1), oldBuffer.GetLength(2)]; } else if (axis == Axis.X) { newBuffer = new Block[oldBuffer.GetLength(0), oldBuffer.GetLength(2), oldBuffer.GetLength(1)]; } else if (axis == Axis.Y) { newBuffer = new Block[oldBuffer.GetLength(2), oldBuffer.GetLength(1), oldBuffer.GetLength(0)]; } else { // axis == Axis.Z newBuffer = new Block[oldBuffer.GetLength(1), oldBuffer.GetLength(0), oldBuffer.GetLength(2)]; } // clone to avoid messing up any paste-in-progress CopyState info = new CopyState(originalInfo, newBuffer); // construct the rotation matrix int[,] matrix = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }; int a, b; switch (axis) { case Axis.X: a = 1; b = 2; break; case Axis.Y: a = 0; b = 2; break; default: a = 0; b = 1; break; } switch (degrees) { case 90: matrix[a, a] = 0; matrix[b, b] = 0; matrix[a, b] = -1; matrix[b, a] = 1; break; case 180: matrix[a, a] = -1; matrix[b, b] = -1; break; case -90: case 270: matrix[a, a] = 0; matrix[b, b] = 0; matrix[a, b] = 1; matrix[b, a] = -1; break; } // apply the rotation matrix for (int x = oldBuffer.GetLength(0) - 1; x >= 0; x--) { for (int y = oldBuffer.GetLength(1) - 1; y >= 0; y--) { for (int z = oldBuffer.GetLength(2) - 1; z >= 0; z--) { int nx = (matrix[0, 0] < 0 ? oldBuffer.GetLength(0) - 1 - x : (matrix[0, 0] > 0 ? x : 0)) + (matrix[0, 1] < 0 ? oldBuffer.GetLength(1) - 1 - y : (matrix[0, 1] > 0 ? y : 0)) + (matrix[0, 2] < 0 ? oldBuffer.GetLength(2) - 1 - z : (matrix[0, 2] > 0 ? z : 0)); int ny = (matrix[1, 0] < 0 ? oldBuffer.GetLength(0) - 1 - x : (matrix[1, 0] > 0 ? x : 0)) + (matrix[1, 1] < 0 ? oldBuffer.GetLength(1) - 1 - y : (matrix[1, 1] > 0 ? y : 0)) + (matrix[1, 2] < 0 ? oldBuffer.GetLength(2) - 1 - z : (matrix[1, 2] > 0 ? z : 0)); int nz = (matrix[2, 0] < 0 ? oldBuffer.GetLength(0) - 1 - x : (matrix[2, 0] > 0 ? x : 0)) + (matrix[2, 1] < 0 ? oldBuffer.GetLength(1) - 1 - y : (matrix[2, 1] > 0 ? y : 0)) + (matrix[2, 2] < 0 ? oldBuffer.GetLength(2) - 1 - z : (matrix[2, 2] > 0 ? z : 0)); newBuffer[nx, ny, nz] = oldBuffer[x, y, z]; } } } player.Message("Rotated copy (slot {0}) by {1} degrees around {2} axis.", info.Slot + 1, degrees, axis); player.SetCopyState(info); }
static void WorldRenameHandler(Player player, Command cmd) { string oldName = cmd.Next(); string newName = cmd.Next(); if (oldName == null || newName == null) { CdWorldRename.PrintUsage(player); return; } World oldWorld = WorldManager.FindWorldOrPrintMatches(player, oldName); if (oldWorld == null) return; oldName = oldWorld.Name; if (!World.IsValidName(newName)) { player.MessageInvalidWorldName(newName); return; } World newWorld = WorldManager.FindWorldExact(newName); if (!cmd.IsConfirmed && newWorld != null && newWorld != oldWorld) { player.Confirm(cmd, "A world named {0}&S already exists. Replace it?", newWorld.ClassyName); return; } if (!cmd.IsConfirmed && File.Exists(Path.Combine(Paths.MapPath, newName + ".fcm"))) { player.Confirm(cmd, "Renaming this world will overwrite an existing map file \"{0}.fcm\".", newName); return; } try { WorldManager.RenameWorld(oldWorld, newName, true, true); } catch (WorldOpException ex) { switch (ex.ErrorCode) { case WorldOpExceptionCode.NoChangeNeeded: player.MessageNow("WRename: World is already named \"{0}\"", oldName); return; case WorldOpExceptionCode.DuplicateWorldName: player.MessageNow("WRename: Another world named \"{0}\" already exists.", newName); return; case WorldOpExceptionCode.InvalidWorldName: player.MessageNow("WRename: Invalid world name: \"{0}\"", newName); return; case WorldOpExceptionCode.MapMoveError: player.MessageNow("WRename: World \"{0}\" was renamed to \"{1}\", but the map file could not be moved due to an error: {2}", oldName, newName, ex.InnerException); return; default: player.MessageNow("&WWRename: Unexpected error renaming world \"{0}\": {1}", oldName, ex.Message); Logger.Log(LogType.Error, "WorldCommands.Rename: Unexpected error while renaming world {0} to {1}: {2}", oldWorld.Name, newName, ex); return; } } player.LastUsedWorldName = newName; WorldManager.SaveWorldList(); Logger.Log(LogType.UserActivity, "{0} renamed the world \"{1}\" to \"{2}\".", player.Name, oldName, newName); Server.Message("{0}&S renamed the world \"{1}\" to \"{2}\"", player.ClassyName, oldName, newName); }
static void DeafenHandler( Player player, Command cmd ) { if( cmd.HasNext ) { CdDeafen.PrintUsage( player ); return; } if( !player.IsDeaf ) { for( int i = 0; i < LinesToClear; i++ ) { player.MessageNow( "" ); } player.MessageNow( "Deafened mode: ON" ); player.MessageNow( "You will not see ANY messages until you type &H/Deafen&S again." ); player.IsDeaf = true; } else { player.IsDeaf = false; player.MessageNow( "Deafened mode: OFF" ); } }
static void UnignoreHandler( Player player, Command cmd ) { string name = cmd.Next(); if( name != null ) { if( cmd.HasNext ) { CdUnignore.PrintUsage( player ); return; } PlayerInfo targetInfo = PlayerDB.FindPlayerInfoOrPrintMatches( player, name ); if( targetInfo == null ) return; if( player.Unignore( targetInfo ) ) { player.MessageNow( "You are no longer ignoring {0}", targetInfo.ClassyName ); } else { player.MessageNow( "You are not currently ignoring {0}", targetInfo.ClassyName ); } } else { PlayerInfo[] ignoreList = player.IgnoreList; if( ignoreList.Length > 0 ) { player.MessageNow( "Ignored players: {0}", ignoreList.JoinToClassyString() ); } else { player.MessageNow( "You are not currently ignoring anyone." ); } return; } }
public static void RealmLoad(Player player, Command cmd, string fileName, string worldName, string buildRankName, string accessRankName) { if (worldName == null && player.World == null) { player.Message("When using /realm from console, you must specify the realm name."); return; } if (fileName == null) { // No params given at all return; } string fullFileName = WorldManager.FindMapFile(player, fileName); if (fullFileName == null) { return; } // Loading map into current realm if (worldName == null) { if (!cmd.IsConfirmed) { player.Confirm(cmd, "About to replace THIS REALM with \"{0}\".", fileName); return; } Map map; try { map = MapUtility.Load(fullFileName); } catch (Exception ex) { player.MessageNow("Could not load specified file: {0}: {1}", ex.GetType().Name, ex.Message); return; } World realm = player.World; // Loading to current realm realm.MapChangedBy = player.Name; realm.ChangeMap(map); realm.Players.Message(player, "{0}&S loaded a new map for this realm.", player.ClassyName); player.MessageNow("New map loaded for the realm {0}", realm.ClassyName); Logger.Log(LogType.UserActivity, "{0} loaded new map for realm \"{1}\" from {2}", player.Name, realm.Name, fileName); realm.IsHidden = false; realm.IsRealm = true; WorldManager.SaveWorldList(); } else { // Loading to some other (or new) realm if (!World.IsValidName(worldName)) { player.MessageInvalidWorldName(worldName); return; } Rank buildRank = RankManager.DefaultBuildRank; Rank accessRank = null; if (buildRankName != null) { buildRank = RankManager.FindRank(buildRankName); if (buildRank == null) { player.MessageNoRank(buildRankName); return; } if (accessRankName != null) { accessRank = RankManager.FindRank(accessRankName); if (accessRank == null) { player.MessageNoRank(accessRankName); return; } } } // Retype realm name, if needed if (worldName == "-") { if (player.LastUsedWorldName != null) { worldName = player.LastUsedWorldName; } else { player.Message("Cannot repeat realm name: you haven't used any names yet."); return; } } lock (WorldManager.SyncRoot) { World realm = WorldManager.FindWorldExact(worldName); if (realm != null) { player.LastUsedWorldName = realm.Name; // Replacing existing realm's map if (!cmd.IsConfirmed) { player.Confirm(cmd, "About to replace realm map for {0}&S with \"{1}\".", realm.ClassyName, fileName); return; } Map map; try { map = MapUtility.Load(fullFileName); realm.IsHidden = false; realm.IsRealm = true; WorldManager.SaveWorldList(); } catch (Exception ex) { player.MessageNow("Could not load specified file: {0}: {1}", ex.GetType().Name, ex.Message); return; } try { realm.MapChangedBy = player.Name; realm.ChangeMap(map); realm.IsHidden = false; realm.IsRealm = true; WorldManager.SaveWorldList(); } catch (WorldOpException ex) { Logger.Log(LogType.Error, "Could not complete RealmLoad operation: {0}", ex.Message); player.Message("&WRealmLoad: {0}", ex.Message); return; } realm.Players.Message(player, "{0}&S loaded a new map for the realm {1}", player.ClassyName, realm.ClassyName); player.MessageNow("New map for the realm {0}&S has been loaded.", realm.ClassyName); Logger.Log(LogType.UserActivity, "{0} loaded new map for realm \"{1}\" from {2}", player.Name, realm.Name, fullFileName); } else { // Adding a new realm string targetFullFileName = Path.Combine(Paths.MapPath, worldName + ".fcm"); if (!cmd.IsConfirmed && File.Exists(targetFullFileName) && // target file already exists !Paths.Compare(targetFullFileName, fullFileName)) { // and is different from sourceFile player.Confirm(cmd, "A map named \"{0}\" already exists, and will be overwritten with \"{1}\".", Path.GetFileName(targetFullFileName), Path.GetFileName(fullFileName)); return; } Map map; try { map = MapUtility.Load(fullFileName); //realm.IsHidden = false; //realm.IsRealm = true; //WorldManager.SaveWorldList(); } 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("RealmLoad: {0}", ex.Message); return; } player.LastUsedWorldName = worldName; newWorld.BuildSecurity.MinRank = buildRank; if (accessRank == null) { newWorld.AccessSecurity.ResetMinRank(); } else { newWorld.AccessSecurity.MinRank = accessRank; } newWorld.BlockDB.AutoToggleIfNeeded(); if (BlockDB.IsEnabledGlobally && newWorld.BlockDB.IsEnabled) { player.Message("BlockDB is now auto-enabled on realm {0}", newWorld.ClassyName); } newWorld.LoadedBy = player.Name; newWorld.LoadedOn = DateTime.UtcNow; Server.Message("{0}&S created a new realm named {1}", player.ClassyName, newWorld.ClassyName); Logger.Log(LogType.UserActivity, "{0} created a new realm named \"{1}\" (loaded from \"{2}\")", player.Name, worldName, fileName); newWorld.IsHidden = false; newWorld.IsRealm = true; WorldManager.SaveWorldList(); player.MessageNow("Access permission is {0}+&S, and build permission is {1}+", newWorld.AccessSecurity.MinRank.ClassyName, newWorld.BuildSecurity.MinRank.ClassyName); } } } Server.RequestGC(); }
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 RedoHandler( Player player, CommandReader cmd ) { if( cmd.HasNext ) { CdRedo.PrintUsage( player ); return; } World playerWorld = player.World; if( playerWorld == null ) PlayerOpException.ThrowNoWorld( player ); UndoState redoState = player.RedoPop(); if( redoState == null ) { player.MessageNow( "There is currently nothing to redo." ); return; } string msg = "Redo: "; if( redoState.Op != null && !redoState.Op.IsDone ) { redoState.Op.Cancel(); msg += String.Format( "Cancelled {0} (was {1}% done). ", redoState.Op.Description, redoState.Op.PercentDone ); } // no need to set player.drawingInProgress here because this is done on the user thread Logger.Log( LogType.UserActivity, "Player {0} initiated /Redo affecting {1} blocks (on world {2})", player.Name, redoState.Buffer.Count, playerWorld.Name ); msg += String.Format( "Restoring {0} blocks. Type &H/Undo&S to reverse.", redoState.Buffer.Count ); player.MessageNow( msg ); var op = new UndoDrawOperation( player, redoState, true ); op.Prepare( new Vector3I[0] ); op.Begin(); }
static void CopyCallback( Player player, Vector3I[] marks, object tag ) { int sx = Math.Min( marks[0].X, marks[1].X ); int ex = Math.Max( marks[0].X, marks[1].X ); int sy = Math.Min( marks[0].Y, marks[1].Y ); int ey = Math.Max( marks[0].Y, marks[1].Y ); int sz = Math.Min( marks[0].Z, marks[1].Z ); int ez = Math.Max( marks[0].Z, marks[1].Z ); BoundingBox bounds = new BoundingBox( sx, sy, sz, ex, ey, ez ); int volume = bounds.Volume; if( !player.CanDraw( volume ) ) { player.MessageNow( "You are only allowed to run commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, volume ); return; } // remember dimensions and orientation CopyState copyInfo = new CopyState( marks[0], marks[1] ); Map map = player.WorldMap; World playerWorld = player.World; if( playerWorld == null ) PlayerOpException.ThrowNoWorld( player ); for( int x = sx; x <= ex; x++ ) { for( int y = sy; y <= ey; y++ ) { for( int z = sz; z <= ez; z++ ) { copyInfo.Blocks[x - sx, y - sy, z - sz] = map.GetBlock( x, y, z ); } } } copyInfo.OriginWorld = playerWorld.Name; copyInfo.CopyTime = DateTime.UtcNow; player.SetCopyState( copyInfo ); player.MessageNow( "{0} blocks copied into slot #{1}, origin at {2} corner. You can now &H/Paste", volume, player.CopySlot + 1, copyInfo.OriginCorner ); Logger.Log( LogType.UserActivity, "{0} copied {1} blocks from world {2} (between {3} and {4}).", player.Name, volume, playerWorld.Name, bounds.MinVertex, bounds.MaxVertex ); }
static void WorldUnloadHandler(Player player, Command cmd) { string worldName = cmd.Next(); if (worldName == null) { CdWorldUnload.PrintUsage(player); return; } World world = WorldManager.FindWorldOrPrintMatches(player, worldName); if (world == null) return; try { WorldManager.RemoveWorld(world); } catch (WorldOpException ex) { switch (ex.ErrorCode) { case WorldOpExceptionCode.CannotDoThatToMainWorld: player.MessageNow("&WWorld {0}&W is set as the main world. " + "Assign a new main world before deleting this one.", world.ClassyName); return; case WorldOpExceptionCode.WorldNotFound: player.MessageNow("&WWorld {0}&W is already unloaded.", world.ClassyName); return; default: player.MessageNow("&WUnexpected error occured while unloading world {0}&W: {1}", world.ClassyName, ex.GetType().Name); Logger.Log(LogType.Error, "WorldCommands.WorldUnload: Unexpected error while unloading world {0}: {1}", world.Name, ex); return; } } WorldManager.SaveWorldList(); Server.Message(player, "{0}&S removed {1}&S from the world list.", player.ClassyName, world.ClassyName); player.Message("Removed {0}&S from the world list. You can now delete the map file ({1}.fcm) manually.", world.ClassyName, world.Name); Logger.Log(LogType.UserActivity, "{0} removed \"{1}\" from the world list.", player.Name, worldName); Server.RequestGC(); }
static void PruneDBHandler( Player player, Command cmd ) { if( !cmd.IsConfirmed ) { player.MessageNow( "PruneDB: Finding inactive players..." ); int inactivePlayers = PlayerDB.CountInactivePlayers(); if( inactivePlayers == 0 ) { player.Message( "PruneDB: No inactive players found." ); } else { player.Confirm( cmd, "PruneDB: Erase {0} records of inactive players?", inactivePlayers ); } } else { Scheduler.NewBackgroundTask( PruneDBTask, player ).RunOnce(); } }
static void UndoHandler([NotNull] Player player, [NotNull] CommandReader cmd) { World playerWorld = player.World; if (playerWorld == null) { PlayerOpException.ThrowNoWorld(player); } if (cmd.HasNext) { player.Message("Undo command takes no parameters. Did you mean to do &H/UndoPlayer&S or &H/UndoArea&S?"); return; } string msg = "Undo: "; UndoState undoState = player.UndoPop(); if (undoState == null) { player.MessageNow("There is currently nothing to undo."); return; } // Cancel the last DrawOp, if still in progress if (undoState.Op != null && !undoState.Op.IsDone && !undoState.Op.IsCancelled) { undoState.Op.Cancel(); msg += String.Format("Cancelled {0} (was {1}% done). ", undoState.Op.Description, undoState.Op.PercentDone); } // Check if command was too massive. if (undoState.IsTooLargeToUndo) { if (undoState.Op != null) { player.MessageNow("Cannot undo {0}: too massive.", undoState.Op.Description); } else { player.MessageNow("Cannot undo: too massive."); } return; } // no need to set player.drawingInProgress here because this is done on the user thread Logger.Log(LogType.UserActivity, "Player {0} initiated /Undo affecting {1} blocks (on world {2})", player.Name, undoState.Buffer.Count, playerWorld.Name); msg += String.Format("Restoring {0} blocks. Type &H/Redo&S to reverse.", undoState.Buffer.Count); player.MessageNow(msg); var op = new UndoDrawOperation(player, undoState, false); op.Prepare(new Vector3I[0]); op.Begin(); }
static void MirrorHandler([NotNull] Player player, [NotNull] CommandReader cmd) { CopyState originalInfo = player.GetCopyState(); if (originalInfo == null) { player.MessageNow("Nothing to flip! Copy something first."); return; } // clone to avoid messing up any paste-in-progress CopyState info = new CopyState(originalInfo); bool flipX = false, flipY = false, flipH = false; string axis; while ((axis = cmd.Next()) != null) { foreach (char c in axis.ToLower()) { if (c == 'x') { flipX = true; } if (c == 'y') { flipY = true; } if (c == 'z') { flipH = true; } } } if (!flipX && !flipY && !flipH) { CdMirror.PrintUsage(player); return; } Block block; if (flipX) { int left = 0; int right = info.Bounds.Width - 1; while (left < right) { for (int y = info.Bounds.Length - 1; y >= 0; y--) { for (int z = info.Bounds.Height - 1; z >= 0; z--) { block = info.Blocks[left, y, z]; info.Blocks[left, y, z] = info.Blocks[right, y, z]; info.Blocks[right, y, z] = block; } } left++; right--; } } if (flipY) { int left = 0; int right = info.Bounds.Length - 1; while (left < right) { for (int x = info.Bounds.Width - 1; x >= 0; x--) { for (int z = info.Bounds.Height - 1; z >= 0; z--) { block = info.Blocks[x, left, z]; info.Blocks[x, left, z] = info.Blocks[x, right, z]; info.Blocks[x, right, z] = block; } } left++; right--; } } if (flipH) { int left = 0; int right = info.Bounds.Height - 1; while (left < right) { for (int x = info.Bounds.Width - 1; x >= 0; x--) { for (int y = info.Bounds.Length - 1; y >= 0; y--) { block = info.Blocks[x, y, left]; info.Blocks[x, y, left] = info.Blocks[x, y, right]; info.Blocks[x, y, right] = block; } } left++; right--; } } if (flipX) { if (flipY) { if (flipH) { player.Message("Flipped copy along all axes."); } else { player.Message("Flipped copy along X (east/west) and Y (north/south) axes."); } } else { if (flipH) { player.Message("Flipped copy along X (east/west) and Z (vertical) axes."); } else { player.Message("Flipped copy along X (east/west) axis."); } } } else { if (flipY) { if (flipH) { player.Message("Flipped copy along Y (north/south) and Z (vertical) axes."); } else { player.Message("Flipped copy along Y (north/south) axis."); } } else { player.Message("Flipped copy along Z (vertical) axis."); } } player.SetCopyState(info); }
public void Draw(Bitmap img) { //guess how big the draw will be int Count = 0; for (int x = 0; x < img.Width; x++) { for (int z = 0; z < img.Height; z++) { if (img.GetPixel(x, z).ToArgb() != System.Drawing.Color.White.ToArgb()) { Count++; } } } //check if player can make the drawing if (!player.CanDraw(Count)) { player.MessageNow( String.Format( "You are only allowed to run commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, Count)); return; } //check direction and draw switch (direction) { case Direction.one: for (int x = 0; x < img.Width; x++) { for (int z = 0; z < img.Height; z++) { if (img.GetPixel(x, z).ToArgb() != System.Drawing.Color.White.ToArgb()) { DrawOneBlock(player, player.World.Map, PixelData.BlockColor, new Vector3I((PixelData.X + x), PixelData.Y, (PixelData.Z + z)), BlockChangeContext.Drawn, ref blocks, ref blocksDenied, undoState); blockCount++; } } } break; case Direction.two: for (int x = 0; x < img.Width; x++) { for (int z = 0; z < img.Height; z++) { if (img.GetPixel(x, z).ToArgb() != System.Drawing.Color.White.ToArgb()) { DrawOneBlock(player, player.World.Map, PixelData.BlockColor, new Vector3I((PixelData.X - x), PixelData.Y, (PixelData.Z + z)), BlockChangeContext.Drawn, ref blocks, ref blocksDenied, undoState); blockCount++; } } } break; case Direction.three: for (int y = 0; y < img.Width; y++) { for (int z = 0; z < img.Height; z++) { if (img.GetPixel(y, z).ToArgb() != System.Drawing.Color.White.ToArgb()) { DrawOneBlock(player, player.World.Map, PixelData.BlockColor, new Vector3I(PixelData.X, (PixelData.Y + y), (PixelData.Z + z)), BlockChangeContext.Drawn, ref blocks, ref blocksDenied, undoState); blockCount++; } } } break; case Direction.four: for (int y = 0; y < img.Width; y++) { for (int z = 0; z < img.Height; z++) { if (img.GetPixel(y, z).ToArgb() != System.Drawing.Color.White.ToArgb()) { DrawOneBlock(player, player.World.Map, PixelData.BlockColor, new Vector3I(PixelData.X, ((PixelData.Y) - y), (PixelData.Z + z)), BlockChangeContext.Drawn, ref blocks, ref blocksDenied, undoState); blockCount++; } } } break; default: break; //if blockcount = 0, message is shown and returned } }
static void PasteNotHandler( Player player, Command cmd ) { QuickPasteDrawOperation op = new QuickPasteDrawOperation( player, true ); if( !op.ReadParams( cmd ) ) return; player.SelectionStart( 1, DrawOperationCallback, op, Permission.Draw, Permission.CopyAndPaste ); player.MessageNow( "{0}: Click a block or use &H/Mark&S to begin pasting.", op.Description ); }
static void PasteOpHandler( Player player, CommandReader cmd, int expectedMarks, DrawOpWithBrush op ) { if( !op.ReadParams( cmd ) ) return; player.SelectionStart( expectedMarks, DrawOperationCallback, op, Permission.Draw, Permission.CopyAndPaste ); CopyState copyInfo = player.GetCopyState(); if( copyInfo != null ) { player.MessageNow( "{0}: Click or &H/Mark&S the {1} corner.", op.Description, copyInfo.OriginCorner ); } else { player.MessageNow( "{0}: Click or &H/Mark&S a block.", op.Description ); } }
static void PasteXHandler( Player player, Command cmd ) { PasteDrawOperation op = new PasteDrawOperation( player, false ); if( !op.ReadParams( cmd ) ) return; player.SelectionStart( 2, DrawOperationCallback, op, Permission.Draw, Permission.CopyAndPaste ); player.MessageNow( "{0}: Click 2 blocks or use &H/Mark&S to make a selection.", op.Description ); }
static void RestoreCallback( Player player, Vector3I[] marks, object tag ) { BoundingBox selection = new BoundingBox( marks[0], marks[1] ); Map map = (Map)tag; if( !player.CanDraw( selection.Volume ) ) { player.MessageNow( "You are only allowed to restore up to {0} blocks at a time. This would affect {1} blocks.", player.Info.Rank.DrawLimit, selection.Volume ); return; } int blocksDrawn = 0, blocksSkipped = 0; UndoState undoState = player.DrawBegin( null ); World playerWorld = player.World; if( playerWorld == null ) PlayerOpException.ThrowNoWorld( player ); Map playerMap = player.WorldMap; Vector3I coord = new Vector3I(); for( coord.X = selection.XMin; coord.X <= selection.XMax; coord.X++ ) { for( coord.Y = selection.YMin; coord.Y <= selection.YMax; coord.Y++ ) { for( coord.Z = selection.ZMin; coord.Z <= selection.ZMax; coord.Z++ ) { DrawOneBlock( player, playerMap, map.GetBlock( coord ), coord, RestoreContext, ref blocksDrawn, ref blocksSkipped, undoState ); } } } Logger.Log( LogType.UserActivity, "{0} restored {1} blocks on world {2} (@{3},{4},{5} - {6},{7},{8}) from file {9}.", player.Name, blocksDrawn, playerWorld.Name, selection.XMin, selection.YMin, selection.ZMin, selection.XMax, selection.YMax, selection.ZMax, map.Metadata["fCraft.Temp", "FileName"] ); DrawingFinished( player, "Restored", blocksDrawn, blocksSkipped ); }
static void TreeHandler(Player player, Command cmd) { string shapeName = cmd.Next(); int height; Forester.TreeShape shape; // that's one ugly if statement... does the job though. if (shapeName == null || !cmd.NextInt(out height) || !EnumUtil.TryParse(shapeName, out shape, true) || shape == Forester.TreeShape.Stickly || shape == Forester.TreeShape.Procedural) { CdTree.PrintUsage(player); player.Message("Available shapes: Normal, Bamboo, Palm, Cone, Round, Rainforest, Mangrove."); return; } if (height < 6 || height > 1024) { player.Message("Tree height must be 6 blocks or above"); return; } Map map = player.World.Map; ForesterArgs args = new ForesterArgs { Height = height - 1, Operation = Forester.ForesterOperation.Add, Map = map, Shape = shape, TreeCount = 1, RootButtresses = false, Roots = Forester.RootMode.None, Rand = new Random() }; player.SelectionStart(1, TreeCallback, args, CdTree.Permissions); player.MessageNow("Tree: Place a block or type /Mark to use your location."); }
static void UndoAreaHandler( Player player, CommandReader cmd ) { BlockDBUndoArgs args = ParseBlockDBUndoParams( player, cmd, "UndoArea", false ); if( args == null ) return; Permission permission; if( args.Targets.Length == 0 ) { permission = Permission.UndoAll; } else { permission = Permission.UndoOthersActions; } player.SelectionStart( 2, UndoAreaSelectionCallback, args, permission ); player.MessageNow( "UndoArea: Click or &H/Mark&S 2 blocks." ); }
static void UndoAreaHandler( Player player, Command cmd ) { if( !BlockDB.IsEnabledGlobally ) { player.Message( "&WBlockDB is disabled on this server." ); return; } World playerWorld = player.World; if( playerWorld == null ) PlayerOpException.ThrowNoWorld( player ); if( !playerWorld.BlockDB.IsEnabled ) { player.Message( "&WBlockDB is disabled in this world." ); return; } string name = cmd.Next(); string range = cmd.Next(); if( name == null || range == null ) { CdUndoArea.PrintUsage( player ); return; } if( cmd.HasNext ) { CdUndoArea.PrintUsage( player ); return; } PlayerInfo target = PlayerDB.FindPlayerInfoOrPrintMatches( player, name ); if( target == null ) return; if( player.Info != target && !player.Can( Permission.UndoOthersActions, target.Rank ) ) { player.Message( "You may only undo actions of players ranked {0}&S or lower.", player.Info.Rank.GetLimit( Permission.UndoOthersActions ).ClassyName ); player.Message( "Player {0}&S is ranked {1}", target.ClassyName, target.Rank.ClassyName ); return; } int count; TimeSpan span; if( Int32.TryParse( range, out count ) ) { UndoAreaCountArgs args = new UndoAreaCountArgs { Target = target, World = playerWorld, MaxBlocks = count }; player.SelectionStart( 2, UndoAreaCountSelectionCallback, args, Permission.UndoOthersActions ); } else if( range.TryParseMiniTimespan( out span ) ) { if( span > DateTimeUtil.MaxTimeSpan ) { player.MessageMaxTimeSpan(); return; } UndoAreaTimeArgs args = new UndoAreaTimeArgs { Target = target, Time = span, World = playerWorld }; player.SelectionStart( 2, UndoAreaTimeSelectionCallback, args, Permission.UndoOthersActions ); } else { CdUndoArea.PrintUsage( player ); return; } player.MessageNow( "UndoArea: Click 2 blocks or use &H/Mark&S to make a selection." ); }
static void DrawOperationCallback( Player player, Vector3I[] marks, object tag ) { DrawOperation op = (DrawOperation)tag; if( !op.Prepare( marks ) ) return; if( !player.CanDraw( op.BlocksTotalEstimate ) ) { player.MessageNow( "You are only allowed to run draw commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, op.Bounds.Volume ); op.Cancel(); return; } player.Message( "{0}: Processing ~{1} blocks.", op.Description, op.BlocksTotalEstimate ); op.Begin(); }
static void CancelHandler( Player player, Command cmd ) { if( cmd.HasNext ) { CdCancel.PrintUsage( player ); return; } if( player.IsMakingSelection ) { player.SelectionCancel(); player.MessageNow( "Selection cancelled." ); } else { player.MessageNow( "There is currently nothing to cancel." ); } }
static void UndoHandler( Player player, CommandReader cmd ) { World playerWorld = player.World; if( playerWorld == null ) PlayerOpException.ThrowNoWorld( player ); if( cmd.HasNext ) { player.Message( "Undo command takes no parameters. Did you mean to do &H/UndoPlayer&S or &H/UndoArea&S?" ); return; } string msg = "Undo: "; UndoState undoState = player.UndoPop(); if( undoState == null ) { player.MessageNow( "There is currently nothing to undo." ); return; } // Cancel the last DrawOp, if still in progress if( undoState.Op != null && !undoState.Op.IsDone && !undoState.Op.IsCancelled ) { undoState.Op.Cancel(); msg += String.Format( "Cancelled {0} (was {1}% done). ", undoState.Op.Description, undoState.Op.PercentDone ); } // Check if command was too massive. if( undoState.IsTooLargeToUndo ) { if( undoState.Op != null ) { player.MessageNow( "Cannot undo {0}: too massive.", undoState.Op.Description ); } else { player.MessageNow( "Cannot undo: too massive." ); } return; } // no need to set player.drawingInProgress here because this is done on the user thread Logger.Log( LogType.UserActivity, "Player {0} initiated /Undo affecting {1} blocks (on world {2})", player.Name, undoState.Buffer.Count, playerWorld.Name ); msg += String.Format( "Restoring {0} blocks. Type &H/Redo&S to reverse.", undoState.Buffer.Count ); player.MessageNow( msg ); var op = new UndoDrawOperation( player, undoState, false ); op.Prepare( new Vector3I[0] ); op.Begin(); }
static void CenterHandler( Player player, Command cmd ) { player.SelectionStart( 2, CenterCallback, null, CdCenter.Permissions ); player.MessageNow( "Center: Place a block or type /Mark to use your location." ); }
static void CopyHandler( Player player, CommandReader cmd ) { if( cmd.HasNext ) { CdCopy.PrintUsage( player ); return; } player.SelectionStart( 2, CopyCallback, null, CdCopy.Permissions ); player.MessageNow( "Copy: Click or &H/Mark&S 2 blocks." ); }
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 MirrorHandler( Player player, CommandReader cmd ) { CopyState originalInfo = player.GetCopyState(); if( originalInfo == null ) { player.MessageNow( "Nothing to flip! Copy something first." ); return; } // clone to avoid messing up any paste-in-progress CopyState info = new CopyState( originalInfo ); bool flipX = false, flipY = false, flipH = false; string axis; while( (axis = cmd.Next()) != null ) { foreach( char c in axis.ToLower() ) { if( c == 'x' ) flipX = true; if( c == 'y' ) flipY = true; if( c == 'z' ) flipH = true; } } if( !flipX && !flipY && !flipH ) { CdMirror.PrintUsage( player ); return; } Block block; if( flipX ) { int left = 0; int right = info.Bounds.Width - 1; while( left < right ) { for( int y = info.Bounds.Length - 1; y >= 0; y-- ) { for( int z = info.Bounds.Height - 1; z >= 0; z-- ) { block = info.Blocks[left, y, z]; info.Blocks[left, y, z] = info.Blocks[right, y, z]; info.Blocks[right, y, z] = block; } } left++; right--; } } if( flipY ) { int left = 0; int right = info.Bounds.Length - 1; while( left < right ) { for( int x = info.Bounds.Width - 1; x >= 0; x-- ) { for( int z = info.Bounds.Height - 1; z >= 0; z-- ) { block = info.Blocks[x, left, z]; info.Blocks[x, left, z] = info.Blocks[x, right, z]; info.Blocks[x, right, z] = block; } } left++; right--; } } if( flipH ) { int left = 0; int right = info.Bounds.Height - 1; while( left < right ) { for( int x = info.Bounds.Width - 1; x >= 0; x-- ) { for( int y = info.Bounds.Length - 1; y >= 0; y-- ) { block = info.Blocks[x, y, left]; info.Blocks[x, y, left] = info.Blocks[x, y, right]; info.Blocks[x, y, right] = block; } } left++; right--; } } if( flipX ) { if( flipY ) { if( flipH ) { player.Message( "Flipped copy along all axes." ); } else { player.Message( "Flipped copy along X (east/west) and Y (north/south) axes." ); } } else { if( flipH ) { player.Message( "Flipped copy along X (east/west) and Z (vertical) axes." ); } else { player.Message( "Flipped copy along X (east/west) axis." ); } } } else { if( flipY ) { if( flipH ) { player.Message( "Flipped copy along Y (north/south) and Z (vertical) axes." ); } else { player.Message( "Flipped copy along Y (north/south) axis." ); } } else { player.Message( "Flipped copy along Z (vertical) axis." ); } } player.SetCopyState( info ); }
static void ZoneMarkHandler( Player player, Command cmd ) { if( player.SelectionMarksExpected == 0 ) { player.MessageNow( "Cannot use ZMark - no selection in progress." ); } else if( player.SelectionMarksExpected == 2 ) { string zoneName = cmd.Next(); if( zoneName == null ) { CdZoneMark.PrintUsage( player ); return; } Zone zone = player.WorldMap.Zones.Find( zoneName ); if( zone == null ) { player.MessageNoZone( zoneName ); return; } player.SelectionResetMarks(); player.SelectionAddMark( zone.Bounds.MinVertex, false ); player.SelectionAddMark( zone.Bounds.MaxVertex, true ); } else { player.MessageNow( "ZMark can only be used for 2-block selection." ); } }
static void RestartHandler( Player player, Command cmd ) { string delayString = cmd.Next(); TimeSpan delayTime = DefaultShutdownTime; string reason = ""; if( delayString != null ) { if( delayString.Equals( "abort", StringComparison.OrdinalIgnoreCase ) ) { if( Server.CancelShutdown() ) { Logger.Log( LogType.UserActivity, "Restart aborted by {0}.", player.Name ); Server.Message( "&WRestart aborted by {0}", player.ClassyName ); } else { player.MessageNow( "Cannot abort restart - too late." ); } return; } else if( !delayString.TryParseMiniTimespan( out delayTime ) ) { CdShutdown.PrintUsage( player ); return; } reason = cmd.NextAll(); } if( delayTime.TotalMilliseconds > Int32.MaxValue - 1 ) { player.Message( "Restart: Delay is too long, maximum is {0}", TimeSpan.FromMilliseconds( Int32.MaxValue - 1 ).ToMiniString() ); return; } Server.Message( "&WServer restarting in {0}", delayTime.ToMiniString() ); if( String.IsNullOrEmpty( reason ) ) { Logger.Log( LogType.UserActivity, "{0} scheduled a restart ({1} delay).", player.Name, delayTime.ToCompactString() ); ShutdownParams sp = new ShutdownParams( ShutdownReason.Restarting, delayTime, true, true ); Server.Shutdown( sp, false ); } else { Server.Message( "&WRestart reason: {0}", reason ); Logger.Log( LogType.UserActivity, "{0} scheduled a restart ({1} delay). Reason: {2}", player.Name, delayTime.ToCompactString(), reason ); ShutdownParams sp = new ShutdownParams( ShutdownReason.Restarting, delayTime, true, true, reason, player ); Server.Shutdown( sp, false ); } }
static void RestartHandler(Player player, CommandReader cmd) { string delayString = cmd.Next(); TimeSpan delayTime = DefaultShutdownTime; string reason = ""; if (delayString != null) { if (delayString.Equals("abort", StringComparison.OrdinalIgnoreCase)) { if (Server.CancelShutdown()) { Logger.Log(LogType.UserActivity, "Restart aborted by {0}.", player.Name); Server.Message("&WRestart aborted by {0}", player.ClassyName); } else { player.MessageNow("Cannot abort restart - too late."); } return; } else if (!delayString.TryParseMiniTimespan(out delayTime)) { CdShutdown.PrintUsage(player); return; } if (delayTime > DateTimeUtil.MaxTimeSpan) { player.MessageMaxTimeSpan(); return; } reason = cmd.NextAll(); } if (delayTime.TotalMilliseconds > Int32.MaxValue - 1) { player.Message("Restart: Delay is too long, maximum is {0}", TimeSpan.FromMilliseconds(Int32.MaxValue - 1).ToMiniString()); return; } Server.Message("&WServer restarting in {0}", delayTime.ToMiniString()); if (String.IsNullOrEmpty(reason)) { Logger.Log(LogType.UserActivity, "{0} scheduled a restart ({1} delay).", player.Name, delayTime.ToCompactString()); ShutdownParams sp = new ShutdownParams(ShutdownReason.Restarting, delayTime, true, true); Server.Shutdown(sp, false); } else { Server.Message("&WRestart reason: {0}", reason); Logger.Log(LogType.UserActivity, "{0} scheduled a restart ({1} delay). Reason: {2}", player.Name, delayTime.ToCompactString(), reason); ShutdownParams sp = new ShutdownParams(ShutdownReason.Restarting, delayTime, true, true, reason, player); Server.Shutdown(sp, false); } }