示例#1
0
        public static void HandleAccountSetPassword(Session session, params string[] parameters)
        {
            string accountName = parameters[0].ToLower();

            var account = DatabaseManager.Authentication.GetAccountByName(accountName);

            if (account == null)
            {
                CommandHandlerHelper.WriteOutputInfo(session, "Account " + accountName + " does not exist.", ChatMessageType.Broadcast);
                return;
            }

            if (parameters.Length < 1)
            {
                CommandHandlerHelper.WriteOutputInfo(session, "You must specify a password for the account.", ChatMessageType.Broadcast);
                return;
            }

            account.SetPassword(parameters[1]);
            account.SetSaltForBCrypt();

            DatabaseManager.Authentication.UpdateAccount(account);

            CommandHandlerHelper.WriteOutputInfo(session, $"Account password for {accountName} successfully changed.", ChatMessageType.Broadcast);
        }
示例#2
0
        public static void HandleDatabaseShardCacheNPBRT(Session session, params string[] parameters)
        {
            if (!(DatabaseManager.Shard.BaseDatabase is ShardDatabaseWithCaching shardDatabaseWithCaching))
            {
                CommandHandlerHelper.WriteOutputInfo(session, "DatabaseManager is not using ShardDatabaseWithCaching");

                return;
            }

            if (parameters == null || parameters.Length == 0)
            {
                CommandHandlerHelper.WriteOutputInfo(session, $"Shard Database, Non-Player Biota Cache - Retention Time {shardDatabaseWithCaching.NonPlayerBiotaRetentionTime.TotalMinutes:N0} m");

                return;
            }

            if (!int.TryParse(parameters[0], out var value) || value < 0)
            {
                CommandHandlerHelper.WriteOutputInfo(session, "Unable to parse argument. Specify retention time in integer minutes.");

                return;
            }

            shardDatabaseWithCaching.NonPlayerBiotaRetentionTime = TimeSpan.FromMinutes(value);

            CommandHandlerHelper.WriteOutputInfo(session, $"Shard Database, Non-Player Biota Cache - Retention Time {shardDatabaseWithCaching.NonPlayerBiotaRetentionTime.TotalMinutes:N0} m");
        }
示例#3
0
        public static void HandleCharacterForcedDelete(Session session, params string[] parameters)
        {
            var characterName = string.Join(" ", parameters);

            var foundPlayer = PlayerManager.FindByName(characterName, out var isOnline);

            if (foundPlayer == null)
            {
                CommandHandlerHelper.WriteOutputInfo(session, $"There is no character named {characterName} in the database.", ChatMessageType.Broadcast);
                return;
            }

            if (isOnline && foundPlayer is Player player)
            {
                player.Character.DeleteTime     = (ulong)Time.GetUnixTime();
                player.Character.IsDeleted      = true;
                player.CharacterChangesDetected = true;
                player.Session.LogOffPlayer(true);
                PlayerManager.HandlePlayerDelete(player.Character.Id);
                PlayerManager.ProcessDeletedPlayer(player.Character.Id);
            }
            else
            {
                var character = DatabaseManager.Shard.GetCharacterByName(foundPlayer.Name);

                character.DeleteTime = (ulong)Time.GetUnixTime();
                character.IsDeleted  = true;
                DatabaseManager.Shard.SaveCharacter(character, new ReaderWriterLockSlim(), null);
                PlayerManager.HandlePlayerDelete(character.Id);
                PlayerManager.ProcessDeletedPlayer(character.Id);
            }


            CommandHandlerHelper.WriteOutputInfo(session, $"Successfully {(isOnline ? "booted and " : "")}deleted character {foundPlayer.Name} (0x{foundPlayer.Guid}).", ChatMessageType.Broadcast);
        }
示例#4
0
        public static void HandleSetShutdownInterval(Session session, params string[] parameters)
        {
            if (parameters?.Length > 0)
            {
                // delay server shutdown for up to x minutes
                // limit to uint length 65535
                string parseInt = parameters[0].Length > 5 ? parameters[0].Substring(0, 5) : parameters[0];
                if (uint.TryParse(parseInt, out var newShutdownInterval))
                {
                    // newShutdownInterval is represented as a time element
                    if (newShutdownInterval > uint.MaxValue)
                    {
                        newShutdownInterval = uint.MaxValue;
                    }

                    // set the interval
                    ServerManager.SetShutdownInterval(Convert.ToUInt32(newShutdownInterval));

                    // message the admin
                    CommandHandlerHelper.WriteOutputInfo(session, $"Shutdown Interval (seconds to shutdown server) has been set to {ServerManager.ShutdownInterval}.", ChatMessageType.Broadcast);
                    return;
                }
            }
            CommandHandlerHelper.WriteOutputInfo(session, "Usage: /set-shutdown-interval <00000>", ChatMessageType.Broadcast);
        }
示例#5
0
        public static void HandleUnBanAccount(Session session, params string[] parameters)
        {
            // usage: @unban acct
            // This command removes the ban from the specified account.The player will then be able to log into the game.
            // @unban - Unbans the specified player account.

            var accountName = parameters[0];

            var account = DatabaseManager.Authentication.GetAccountByName(accountName);

            if (account == null)
            {
                CommandHandlerHelper.WriteOutputInfo(session, $"Cannot unban \"{accountName}\" because that account cannot be found in database. Check spelling and try again.", ChatMessageType.Broadcast);
                return;
            }

            if (account.BanExpireTime == null)
            {
                CommandHandlerHelper.WriteOutputInfo(session, $"Cannon unban\"{accountName}\" because that account is not banned.", ChatMessageType.Broadcast);
                return;
            }

            account.UnBan();
            var banText = $"UnBanned account {accountName}.";

            CommandHandlerHelper.WriteOutputInfo(session, banText, ChatMessageType.Broadcast);
            PlayerManager.BroadcastToAuditChannel(session?.Player, banText);
        }
示例#6
0
        public static void HandleGCStatus(Session session, params string[] parameters)
        {
            var sb = new StringBuilder();

            sb.Append($"GC.GetTotalMemory: {(GC.GetTotalMemory(false) >> 20):N0} MB, GC.GetTotalAllocatedBytes: {(GC.GetTotalAllocatedBytes() >> 20):N0} MB{'\n'}");

            // https://docs.microsoft.com/en-us/dotnet/api/system.gcmemoryinfo?view=net-5.0
            var gcmi = GC.GetGCMemoryInfo();

            sb.Append($"GCMI Index: {gcmi.Index:N0}, Generation: {gcmi.Generation}, Compacted: {gcmi.Compacted}, Concurrent: {gcmi.Concurrent}, PauseTimePercentage: {gcmi.PauseTimePercentage}{'\n'}");
            for (int i = 0; i < gcmi.GenerationInfo.Length; i++)
            {
                sb.Append($"GCMI.GenerationInfo[{i}] FragmentationBeforeBytes: {(gcmi.GenerationInfo[i].FragmentationBeforeBytes >> 20):N0} MB, FragmentationAfterBytes: {(gcmi.GenerationInfo[i].FragmentationAfterBytes >> 20):N0} MB, SizeBeforeBytes: {(gcmi.GenerationInfo[i].SizeBeforeBytes >> 20):N0} MB, SizeAfterBytes: {(gcmi.GenerationInfo[i].SizeAfterBytes >> 20):N0} MB{'\n'}");
            }
            for (int i = 0; i < gcmi.PauseDurations.Length; i++)
            {
                sb.Append($"GCMI.PauseDurations[{i}]: {gcmi.PauseDurations[i].TotalMilliseconds:N0} ms{'\n'}");
            }
            sb.Append($"GCMI PinnedObjectsCount: {gcmi.PinnedObjectsCount}, FinalizationPendingCount: {gcmi.FinalizationPendingCount:N0}{'\n'}");

            sb.Append($"GCMI FragmentedBytes: {(gcmi.FragmentedBytes >> 20):N0} MB, PromotedBytes: {(gcmi.PromotedBytes >> 20):N0} MB, HeapSizeBytes: {(gcmi.HeapSizeBytes >> 20):N0} MB, TotalCommittedBytes: {(gcmi.TotalCommittedBytes >> 20):N0} MB{'\n'}");
            sb.Append($"GCMI MemoryLoadBytes: {(gcmi.MemoryLoadBytes >> 20):N0} MB, HighMemoryLoadThresholdBytes: {(gcmi.HighMemoryLoadThresholdBytes >> 20):N0} MB, TotalAvailableMemoryBytes: {(gcmi.TotalAvailableMemoryBytes >> 20):N0} MB{'\n'}");

            CommandHandlerHelper.WriteOutputInfo(session, sb.ToString());
        }
示例#7
0
        public static void HandleServerPerformance(Session session, params string[] parameters)
        {
            if (parameters != null && parameters.Length == 1)
            {
                if (parameters[0].ToLower() == "start")
                {
                    ServerPerformanceMonitor.Start();
                    CommandHandlerHelper.WriteOutputInfo(session, "Server Performance Monitor started");
                    return;
                }

                if (parameters[0].ToLower() == "stop")
                {
                    ServerPerformanceMonitor.Stop();
                    CommandHandlerHelper.WriteOutputInfo(session, "Server Performance Monitor stopped");
                    return;
                }

                if (parameters[0].ToLower() == "reset")
                {
                    ServerPerformanceMonitor.Reset();
                    CommandHandlerHelper.WriteOutputInfo(session, "Server Performance Monitor reset");
                    return;
                }
            }

            if (!ServerPerformanceMonitor.IsRunning)
            {
                CommandHandlerHelper.WriteOutputInfo(session, "Server Performance Monitor not running. To start use /serverperformance start");
                return;
            }

            CommandHandlerHelper.WriteOutputInfo(session, ServerPerformanceMonitor.ToString());
        }
        public static void HandleCharacterTokenization(Session session, params string[] parameters)
        {
            string characterName = parameters[0];

            AccessLevel accessLevel = AccessLevel.Player;

            if (parameters.Length > 1)
            {
                if (Enum.TryParse(parameters[1], true, out accessLevel))
                {
                    if (!Enum.IsDefined(typeof(AccessLevel), accessLevel))
                    {
                        accessLevel = AccessLevel.Player;
                    }
                }
            }

            DatabaseManager.Shard.SetCharacterAccessLevelByName(characterName.ToLower(), accessLevel, ((uint characterId) =>
            {
                if (characterId > 0)
                {
                    string articleAorAN = "a";
                    if (accessLevel == AccessLevel.Advocate || accessLevel == AccessLevel.Admin || accessLevel == AccessLevel.Envoy)
                    {
                        articleAorAN = "an";
                    }

                    CommandHandlerHelper.WriteOutputInfo(session, "Character " + characterName + " has been made " + articleAorAN + " " + Enum.GetName(typeof(AccessLevel), accessLevel) + ".", ChatMessageType.Broadcast);
                }
                else
                {
                    CommandHandlerHelper.WriteOutputInfo(session, "There is no character by the name of " + characterName + " found in the database. Has it been deleted?", ChatMessageType.Broadcast);
                }
            }));
        }
示例#9
0
        public static void HandleSetShutdownInterval(Session session, params string[] parameters)
        {
            if (parameters?.Length > 0)
            {
                // delay server shutdown for up to x minutes
                // limit to uint length 65535
                string parseInt = parameters[0].Length > 5 ? parameters[0].Substring(0, 5) : parameters[0];
                if (uint.TryParse(parseInt, out var newShutdownInterval))
                {
                    // newShutdownInterval is represented as a time element
                    if (newShutdownInterval > uint.MaxValue)
                    {
                        newShutdownInterval = uint.MaxValue;
                    }

                    var adminName = (session == null) ? "CONSOLE" : session.Player.Name;
                    var msg       = $"{adminName} has requested the shut down interval be changed from {ServerManager.ShutdownInterval} seconds to {newShutdownInterval} seconds.";
                    //log.Info(msg);
                    PlayerManager.BroadcastToAuditChannel(session?.Player, msg);

                    // set the interval
                    ServerManager.SetShutdownInterval(Convert.ToUInt32(newShutdownInterval));

                    // message the admin
                    CommandHandlerHelper.WriteOutputInfo(session, $"Shutdown Interval (seconds to shutdown server) has been set to {ServerManager.ShutdownInterval}.", ChatMessageType.Broadcast);
                    return;
                }
            }
            CommandHandlerHelper.WriteOutputInfo(session, "Usage: /set-shutdown-interval <00000>", ChatMessageType.Broadcast);
        }
示例#10
0
        public static void HandlePasswd(Session session, params string[] parameters)
        {
            if (session == null)
            {
                CommandHandlerHelper.WriteOutputInfo(session, "This command is run from ingame client only", ChatMessageType.Broadcast);
                return;
            }

            log.Debug($"{session.Player.Name} is changing their password");

            var currentTime = DateTime.UtcNow;

            if (currentTime - session.LastPassTime < PasswdInterval)
            {
                CommandHandlerHelper.WriteOutputInfo(session, $"This command may only be run once every {PasswdInterval.TotalSeconds} seconds.", ChatMessageType.Broadcast);
                return;
            }
            session.LastPassTime = currentTime;

            if (parameters.Length <= 0)
            {
                CommandHandlerHelper.WriteOutputInfo(session, "You must specify the current password for the account.", ChatMessageType.Broadcast);
                return;
            }

            if (parameters.Length < 1)
            {
                CommandHandlerHelper.WriteOutputInfo(session, "You must specify a new password for the account.", ChatMessageType.Broadcast);
                return;
            }

            var account = DatabaseManager.Authentication.GetAccountById(session.AccountId);

            if (account == null)
            {
                CommandHandlerHelper.WriteOutputInfo(session, $"Account {session.Account} ({session.AccountId}) wasn't found in the database! How are you in world without a valid account?", ChatMessageType.Broadcast);
                return;
            }

            var oldpassword = parameters[0];
            var newpassword = parameters[1];

            if (account.PasswordMatches(oldpassword))
            {
                account.SetPassword(newpassword);
                account.SetSaltForBCrypt();
            }
            else
            {
                CommandHandlerHelper.WriteOutputInfo(session, $"Unable to change password: Password provided in first parameter does not match current account password for this account!", ChatMessageType.Broadcast);
                return;
            }


            DatabaseManager.Authentication.UpdateAccount(account);

            CommandHandlerHelper.WriteOutputInfo(session, "Account password successfully changed.", ChatMessageType.Broadcast);
        }
示例#11
0
        public static void HandleAccountCreate(Session session, params string[] parameters)
        {
            AccessLevel defaultAccessLevel = (AccessLevel)Common.ConfigManager.Config.Server.Accounts.DefaultAccessLevel;

            if (!Enum.IsDefined(typeof(AccessLevel), defaultAccessLevel))
            {
                defaultAccessLevel = AccessLevel.Player;
            }

            var accessLevel = defaultAccessLevel;

            if (parameters.Length > 2)
            {
                if (Enum.TryParse(parameters[2], true, out accessLevel))
                {
                    if (!Enum.IsDefined(typeof(AccessLevel), accessLevel))
                    {
                        accessLevel = defaultAccessLevel;
                    }
                }
            }

            string articleAorAN = "a";

            if (accessLevel == AccessLevel.Advocate || accessLevel == AccessLevel.Admin || accessLevel == AccessLevel.Envoy)
            {
                articleAorAN = "an";
            }

            string message = "";

            var accountExists = DatabaseManager.Authentication.GetAccountByName(parameters[0]);

            if (accountExists != null)
            {
                message = "Account already exists. Try a new name.";
            }
            else
            {
                try
                {
                    var account = DatabaseManager.Authentication.CreateAccount(parameters[0].ToLower(), parameters[1], accessLevel, IPAddress.Parse("127.0.0.1"));

                    if (DatabaseManager.AutoPromoteNextAccountToAdmin && accessLevel == AccessLevel.Admin)
                    {
                        DatabaseManager.AutoPromoteNextAccountToAdmin = false;
                    }

                    message = ("Account successfully created for " + account.AccountName + " (" + account.AccountId + ") with access rights as " + articleAorAN + " " + Enum.GetName(typeof(AccessLevel), accessLevel) + ".");
                }
                catch
                {
                    message = "Account already exists. Try a new name.";
                }
            }

            CommandHandlerHelper.WriteOutputInfo(session, message, ChatMessageType.WorldBroadcast);
        }
示例#12
0
        public static void HandleLandblockPerformance(Session session, params string[] parameters)
        {
            var sb = new StringBuilder();

            var loadedLandblocks = LandblockManager.GetLoadedLandblocks();

            // Filter out landblocks that haven't recorded at least 1000 events
            var sortedByAverage = loadedLandblocks.Where(r => r.Monitor1h.TotalEvents >= 1000).OrderByDescending(r => r.Monitor1h.AverageEventDuration).Take(10);

            sb.Append($"Most Busy Landblock - By Average{'\n'}");
            sb.Append($"~1h Hits   Avg  Long  Last  Tot - Location   Players  Creatures{'\n'}");

            foreach (var entry in sortedByAverage)
            {
                int players = 0, creatures = 0;
                foreach (var worldObject in entry.GetAllWorldObjectsForDiagnostics())
                {
                    if (worldObject is Player)
                    {
                        players++;
                    }
                    else if (worldObject is Creature)
                    {
                        creatures++;
                    }
                }

                sb.Append($"{entry.Monitor1h.TotalEvents.ToString().PadLeft(7)} {entry.Monitor1h.AverageEventDuration:N4} {entry.Monitor1h.LongestEvent:N3} {entry.Monitor1h.LastEvent:N3} {((int)entry.Monitor1h.TotalSeconds).ToString().PadLeft(4)} - " +
                          $"0x{entry.Id.Raw:X8} {players.ToString().PadLeft(7)}  {creatures.ToString().PadLeft(9)}{'\n'}");
            }

            var sortedByLong = loadedLandblocks.Where(r => r.Monitor1h.TotalEvents >= 1000).OrderByDescending(r => r.Monitor1h.LongestEvent).Take(10);

            sb.Append($"Most Busy Landblock - By Longest{'\n'}");
            sb.Append($"~1h Hits   Avg  Long  Last  Tot - Location   Players  Creatures{'\n'}");

            foreach (var entry in sortedByLong)
            {
                int players = 0, creatures = 0;
                foreach (var worldObject in entry.GetAllWorldObjectsForDiagnostics())
                {
                    if (worldObject is Player)
                    {
                        players++;
                    }
                    else if (worldObject is Creature)
                    {
                        creatures++;
                    }
                }

                sb.Append($"{entry.Monitor1h.TotalEvents.ToString().PadLeft(7)} {entry.Monitor1h.AverageEventDuration:N4} {entry.Monitor1h.LongestEvent:N3} {entry.Monitor1h.LastEvent:N3} {((int)entry.Monitor1h.TotalSeconds).ToString().PadLeft(4)} - " +
                          $"0x{entry.Id.Raw:X8} {players.ToString().PadLeft(7)}  {creatures.ToString().PadLeft(9)}{'\n'}");
            }

            CommandHandlerHelper.WriteOutputInfo(session, sb.ToString());
        }
示例#13
0
        public static void HandleDatabaseQueueInfo(Session session, params string[] parameters)
        {
            CommandHandlerHelper.WriteOutputInfo(session, $"Current database queue count: {DatabaseManager.Shard.QueueCount}");

            DatabaseManager.Shard.GetCurrentQueueWaitTime(result =>
            {
                CommandHandlerHelper.WriteOutputInfo(session, $"Current database queue wait time: {result.TotalMilliseconds:N0} ms");
            });
        }
示例#14
0
        public static void HandleAccountUpdateAccessLevel(Session session, params string[] parameters)
        {
            string accountName = parameters[0].ToLower();

            var accountId = DatabaseManager.Authentication.GetAccountIdByName(accountName);

            if (accountId == 0)
            {
                CommandHandlerHelper.WriteOutputInfo(session, "Account " + accountName + " does not exist.", ChatMessageType.Broadcast);
                return;
            }

            AccessLevel accessLevel = AccessLevel.Player;

            if (parameters.Length > 1)
            {
                if (Enum.TryParse(parameters[1], true, out accessLevel))
                {
                    if (!Enum.IsDefined(typeof(AccessLevel), accessLevel))
                    {
                        accessLevel = AccessLevel.Player;
                    }
                }
            }

            string articleAorAN = "a";

            if (accessLevel == AccessLevel.Advocate || accessLevel == AccessLevel.Admin || accessLevel == AccessLevel.Envoy)
            {
                articleAorAN = "an";
            }

            if (accountId == 0)
            {
                CommandHandlerHelper.WriteOutputInfo(session, "Account " + accountName + " does not exist.", ChatMessageType.Broadcast);
                return;
            }

            DatabaseManager.Authentication.UpdateAccountAccessLevel(accountId, accessLevel);

            if (DatabaseManager.AutoPromoteNextAccountToAdmin && accessLevel == AccessLevel.Admin)
            {
                DatabaseManager.AutoPromoteNextAccountToAdmin = false;
            }

            CommandHandlerHelper.WriteOutputInfo(session, "Account " + accountName + " updated with access rights set as " + articleAorAN + " " + Enum.GetName(typeof(AccessLevel), accessLevel) + ".", ChatMessageType.Broadcast);
        }
示例#15
0
        public static void HandleBanlist(Session session, params string[] parameters)
        {
            // @banlist - Lists all banned accounts on this world.

            var bannedAccounts = DatabaseManager.Authentication.GetListofBannedAccounts();

            if (bannedAccounts.Count != 0)
            {
                var msg = "The following accounts are banned:\n";
                msg += "-------------------\n";
                foreach (var account in bannedAccounts)
                    msg += account + "\n";

                CommandHandlerHelper.WriteOutputInfo(session, msg, ChatMessageType.Broadcast);
            }
            else
                CommandHandlerHelper.WriteOutputInfo(session, $"There are no accounts currently banned.", ChatMessageType.Broadcast);
        }
示例#16
0
 public static void HandleModifyRiptideBoolProperty(Session session, params string[] paramters)
 {
     try
     {
         var boolVal = bool.Parse(paramters[1]);
         if (CustomPropertiesManager.ModifyBool(paramters[0], boolVal))
         {
             CommandHandlerHelper.WriteOutputInfo(session, "Bool property successfully updated!");
         }
         else
         {
             CommandHandlerHelper.WriteOutputInfo(session, "Unknown bool property was not updated. Type showprops for a list of properties.");
         }
     }
     catch (Exception)
     {
         CommandHandlerHelper.WriteOutputInfo(session, "Please input a valid bool", ChatMessageType.Help);
     }
 }
示例#17
0
 public static void HandleModifyRiptideFloatProperty(Session session, params string[] paramters)
 {
     try
     {
         var doubleVal = double.Parse(paramters[1]);
         if (CustomPropertiesManager.ModifyDouble(paramters[0], doubleVal))
         {
             CommandHandlerHelper.WriteOutputInfo(session, "Float property successfully updated!");
         }
         else
         {
             CommandHandlerHelper.WriteOutputInfo(session, "Unknown float property was not updated. Type rt-showprops for a list of properties.");
         }
     }
     catch (Exception)
     {
         CommandHandlerHelper.WriteOutputInfo(session, "Please input a valid float", ChatMessageType.Help);
     }
 }
示例#18
0
 public static void HandlePop(Session session, params string[] parameters)
 {
     CommandHandlerHelper.WriteOutputInfo(session, $"Current world population: {PlayerManager.GetOnlineCount():N0}", ChatMessageType.Broadcast);
 }
示例#19
0
        public static void HandleFixBiotaEmoteDelay(Session session, params string[] parameters)
        {
            if (parameters.Length == 0)
            {
                CommandHandlerHelper.WriteOutputInfo(session, "This command is intended to be run while the world is in offline mode, or there are 0 players connected.");
                CommandHandlerHelper.WriteOutputInfo(session, "To run this fix, type fix-biota-emote-delay fix");
                return;
            }

            var fix = parameters[0].Equals("fix", StringComparison.OrdinalIgnoreCase);

            CommandHandlerHelper.WriteOutputInfo(session, "Building weenie emote cache");

            var weenieEmoteCache = BuildWeenieEmoteCache();

            CommandHandlerHelper.WriteOutputInfo(session, $"Found {weenieEmoteCache.Count:N0} weenie templates w/ emote actions with delay 0");

            using (var ctx = new ShardDbContext())
            {
                CommandHandlerHelper.WriteOutputInfo(session, $"Finding biotas for these wcids");

                var biotas = ctx.Biota.Where(i => weenieEmoteCache.ContainsKey(i.WeenieClassId)).ToList();

                var distinct = biotas.Select(i => i.WeenieClassId).Distinct();
                var counts   = new Dictionary <uint, uint>();
                foreach (var biota in biotas)
                {
                    if (!counts.ContainsKey(biota.WeenieClassId))
                    {
                        counts[biota.WeenieClassId] = 1;
                    }
                    else
                    {
                        counts[biota.WeenieClassId]++;
                    }
                }

                CommandHandlerHelper.WriteOutputInfo(session, $"Found {biotas.Count} biotas matching {distinct.Count()} distinct wcids");

                foreach (var kvp in counts.OrderBy(i => i.Key))
                {
                    CommandHandlerHelper.WriteOutputInfo(session, $"{kvp.Key} - {(WeenieClassName)kvp.Key} ({kvp.Value})");
                }

                if (!fix)
                {
                    CommandHandlerHelper.WriteOutputInfo(session, $"Dry run completed");
                    return;
                }

                var totalUpdated = 0;

                foreach (var biota in biotas)
                {
                    bool updated = false;

                    var query = from emote in ctx.BiotaPropertiesEmote
                                join action in ctx.BiotaPropertiesEmoteAction on emote.Id equals action.EmoteId
                                where emote.ObjectId == biota.Id && action.Delay == 1.0f
                                select new
                    {
                        Emote  = emote,
                        Action = action
                    };

                    var emoteActions = query.ToList();

                    foreach (var emoteAction in emoteActions)
                    {
                        var emote  = emoteAction.Emote;
                        var action = emoteAction.Action;

                        // ensure this delay 1 should be delay 0
                        var hash         = CalculateEmoteHash(emote);
                        var weenieEmotes = weenieEmoteCache[biota.WeenieClassId];
                        if (!weenieEmotes.TryGetValue(hash, out var list))
                        {
                            //CommandHandlerHelper.WriteOutputInfo(session, $"Skipping emote for {biota.WeenieClassId} not found in hash list");
                            continue;
                        }
                        if (!list.Contains(action.Order))
                        {
                            //CommandHandlerHelper.WriteOutputInfo(session, $"Skipping emote for {biota.WeenieClassId} not found in action list");
                            continue;
                        }

                        // confirmed match, update delay 1 -> 0
                        action.Delay = 0.0f;
                        updated      = true;
                    }

                    if (updated)
                    {
                        CommandHandlerHelper.WriteOutputInfo(session, $"Fixed shard object {biota.Id:X8} of type {biota.WeenieClassId} - {(WeenieClassName)biota.WeenieClassId}");
                        totalUpdated++;
                    }
                }
                ctx.SaveChanges();

                CommandHandlerHelper.WriteOutputInfo(session, $"Completed successfully, fixed {totalUpdated} shard items");
            }
        }
示例#20
0
        public static void HandleHelp(Session session, params string[] parameters)
        {
            var open        = false;
            var close       = false;
            var bootPlayers = false;

            var message = $"World is currently {WorldManager.WorldStatus.ToString()}\nPlease specify state to change\n@world [open | close] <boot>\nIf closing world, using @world close boot will force players to logoff immediately";

            if (parameters.Length >= 1)
            {
                switch (parameters[0].ToLower())
                {
                case "open":
                    if (WorldManager.WorldStatus != WorldManager.WorldStatusState.Open)
                    {
                        message = "Opening world to players...";
                        open    = true;
                    }
                    else
                    {
                        message = "World is already open.";
                    }
                    break;

                case "close":
                    if (WorldManager.WorldStatus != WorldManager.WorldStatusState.Closed)
                    {
                        if (parameters.Length > 1)
                        {
                            if (parameters[1].ToLower() == "boot")
                            {
                                bootPlayers = true;
                            }
                        }
                        message = "Closing world";
                        if (bootPlayers)
                        {
                            message += ", and booting all online players.";
                        }
                        else
                        {
                            message += "...";
                        }

                        close = true;
                    }
                    else
                    {
                        message = "World is already closed.";
                    }
                    break;
                }
            }

            CommandHandlerHelper.WriteOutputInfo(session, message, ChatMessageType.WorldBroadcast);

            if (open)
            {
                WorldManager.Open(session == null ? null : session.Player);
            }
            else if (close)
            {
                WorldManager.Close(session == null ? null : session.Player, bootPlayers);
            }
        }
示例#21
0
        public static void HandleBanAccount(Session session, params string[] parameters)
        {
            // usage: @ban < acct > < days > < hours > < minutes >
            // This command bans the specified player account for the specified time.This player will not be able to enter the game with any character until the time expires.
            // @ban - Bans the specified player account.

            var accountName = parameters[0];
            var banDays     = parameters[1];
            var banHours    = parameters[2];
            var banMinutes  = parameters[3];

            var banReason = string.Empty;

            if (parameters.Length > 4)
            {
                var parametersAfterBanParams = "";
                for (var i = 4; i < parameters.Length; i++)
                {
                    parametersAfterBanParams += parameters[i] + " ";
                }
                parametersAfterBanParams = parametersAfterBanParams.Trim();
                banReason = parametersAfterBanParams;
            }

            var account = DatabaseManager.Authentication.GetAccountByName(accountName);

            if (account == null)
            {
                CommandHandlerHelper.WriteOutputInfo(session, $"Cannot ban \"{accountName}\" because that account cannot be found in database. Check syntax/spelling and try again.", ChatMessageType.Broadcast);
                return;
            }

            if (!double.TryParse(banDays, out var days) || days < 0)
            {
                CommandHandlerHelper.WriteOutputInfo(session, $"Days must not be less than 0.", ChatMessageType.Broadcast);
                return;
            }
            if (!double.TryParse(banHours, out var hours) || hours < 0)
            {
                CommandHandlerHelper.WriteOutputInfo(session, $"Hours must not be less than 0.", ChatMessageType.Broadcast);
                return;
            }
            if (!double.TryParse(banMinutes, out var minutes) || minutes < 0)
            {
                CommandHandlerHelper.WriteOutputInfo(session, $"Minutes must not be less than 0.", ChatMessageType.Broadcast);
                return;
            }

            var bannedOn   = DateTime.UtcNow;
            var banExpires = DateTime.UtcNow.AddDays(days).AddHours(hours).AddMinutes(minutes);

            var bannedBy = 0u;

            if (session != null)
            {
                bannedBy = session.AccountId;
            }

            account.BannedTime        = bannedOn;
            account.BanExpireTime     = banExpires;
            account.BannedByAccountId = bannedBy;
            if (!string.IsNullOrWhiteSpace(banReason))
            {
                account.BanReason = banReason;
            }

            DatabaseManager.Authentication.UpdateAccount(account);

            // Boot the player
            if (NetworkManager.Find(accountName) != null)
            {
                var bootArgs = new List <string> {
                    "account"
                };
                if (!string.IsNullOrWhiteSpace(banReason))
                {
                    bootArgs.Add($"{accountName},");
                    bootArgs.Add(banReason);
                }
                else
                {
                    bootArgs.Add(accountName);
                }
                HandleBoot(session, bootArgs.ToArray());
            }

            var banText = $"Banned account {accountName} for {days} days, {hours} hours and {minutes} minutes.{(!string.IsNullOrWhiteSpace(banReason) ? $" Reason: {banReason}" : "")}";

            CommandHandlerHelper.WriteOutputInfo(session, banText, ChatMessageType.Broadcast);
            PlayerManager.BroadcastToAuditChannel(session?.Player, banText);
        }
示例#22
0
        public static void HandleFetchRiptideFloatProperty(Session session, params string[] paramters)
        {
            var floatVal = CustomPropertiesManager.GetDouble(paramters[0]);

            CommandHandlerHelper.WriteOutputInfo(session, $"{paramters[0]} - {floatVal.Description ?? "No Description"}: {floatVal.Item}");
        }
示例#23
0
        public static void HandleBoot(Session session, params string[] parameters)
        {
            // usage: @boot { account,char, iid} who
            // This command boots the specified character out of the game.You can specify who to boot by account, character name, or player instance id.  'who' is the account / character / instance id to actually boot.
            // @boot - Boots the character out of the game.

            var    whomToBoot      = parameters[1];
            string specifiedReason = null;

            if (parameters.Length > 1)
            {
                var parametersAfterBootType = "";
                for (var i = 1; i < parameters.Length; i++)
                {
                    parametersAfterBootType += parameters[i] + " ";
                }
                parametersAfterBootType = parametersAfterBootType.Trim();
                var completeBootNamePlusCommaSeperatedReason = parametersAfterBootType.Split(",");
                whomToBoot = completeBootNamePlusCommaSeperatedReason[0].Trim();
                if (completeBootNamePlusCommaSeperatedReason.Length > 1)
                {
                    specifiedReason = parametersAfterBootType.Replace($"{whomToBoot},", "").Trim();
                }
            }

            string  whatToBoot    = null;
            Session sessionToBoot = null;

            switch (parameters[0].ToLower())
            {
            case "char":
                whatToBoot    = "character";
                sessionToBoot = PlayerManager.GetOnlinePlayer(whomToBoot)?.Session;
                break;

            case "account":
                whatToBoot    = "account";
                sessionToBoot = NetworkManager.Find(whomToBoot);
                break;

            case "iid":
                whatToBoot = "instance id";
                if (!whomToBoot.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
                {
                    CommandHandlerHelper.WriteOutputInfo(session, $"That is not a valid Instance ID (IID). IIDs must be between 0x{ObjectGuid.PlayerMin:X8} and 0x{ObjectGuid.PlayerMax:X8}", ChatMessageType.Broadcast);
                    return;
                }
                if (uint.TryParse(whomToBoot.Substring(2), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out var iid))
                {
                    sessionToBoot = PlayerManager.GetOnlinePlayer(iid)?.Session;
                }
                else
                {
                    CommandHandlerHelper.WriteOutputInfo(session, $"That is not a valid Instance ID (IID). IIDs must be between 0x{ObjectGuid.PlayerMin:X8} and 0x{ObjectGuid.PlayerMax:X8}", ChatMessageType.Broadcast);
                    return;
                }
                break;

            default:
                CommandHandlerHelper.WriteOutputInfo(session, "You must specify what you are booting with char, account, or iid as the first parameter.", ChatMessageType.Broadcast);
                return;
            }

            if (sessionToBoot == null)
            {
                CommandHandlerHelper.WriteOutputInfo(session, $"Cannot boot \"{whomToBoot}\" because that {whatToBoot} is not currently online or cannot be found. Check syntax/spelling and try again.", ChatMessageType.Broadcast);
                return;
            }

            // Boot the player
            var bootText = $"Booting {whatToBoot} {whomToBoot}.{(specifiedReason != null ? $" Reason: {specifiedReason}" : "")}";

            CommandHandlerHelper.WriteOutputInfo(session, bootText, ChatMessageType.Broadcast);
            sessionToBoot.Terminate(SessionTerminationReason.AccountBooted, new GameMessageBootAccount($"{(specifiedReason != null ? $" - {specifiedReason}" : null)}"), null, specifiedReason);
            //CommandHandlerHelper.WriteOutputInfo(session, $"...Result: Success!", ChatMessageType.Broadcast);

            PlayerManager.BroadcastToAuditChannel(session?.Player, bootText);
        }
示例#24
0
 public static void HandleRiptideShowProperties(Session session, params string[] paramters)
 {
     CommandHandlerHelper.WriteOutputInfo(session, CustomPropertiesManager.ListProperties());
 }
示例#25
0
        public static void HandleCloak(Session session, params string[] parameters)
        {
            // Please specify if you want cloaking on or off.usage: @cloak < on / off / player / creature >
            // This command sets your current cloaking state.
            // < on > You will be completely invisible to players.
            // < off > You will show up as a normal.
            // < player > You will appear as a player. (No + and a white radar dot.)
            // < creature > You will appear as a creature. (No + and an orange radar dot.)
            // @cloak - Sets your cloaking state.

            // TODO: investigate translucensy/visbility of other cloaked admins.

            switch (parameters?[0].ToLower())
            {
            case "off":
                session.Player.Cloaked  = false;
                session.Player.Ethereal = false;
                // session.Player.IgnoreCollisions = false;
                session.Player.NoDraw = false;
                // session.Player.ReportCollisions = true;
                session.Player.EnqueueBroadcastPhysicsState();
                session.Player.Translucency = null;
                session.Player.Visibility   = false;

                if (session.Player.CloakStatus > CloakStatus.On)
                {
                    CommandHandlerHelper.WriteOutputInfo(session, $"You will now appear as an admin. You must relog for this to take effect", ChatMessageType.Broadcast);
                }

                session.Player.SetProperty(ACE.Entity.Enum.Properties.PropertyInt.CloakStatus, (int)CloakStatus.Off);

                //session.Player.CurrentLandblock?.EnqueueBroadcast(session.Player.Location, new GameMessageRemoveObject(session.Player));
                //session.Player.CurrentLandblock?.RemoveWorldObject(session.Player.Guid, false);
                //session.Player.CurrentLandblock?.EnqueueBroadcast(session.Player.Location, new GameMessageCreateObject(session.Player));
                //session.Player.CurrentLandblock?.AddWorldObject(session.Player);
                break;

            case "on":
                session.Player.Cloaked  = true;
                session.Player.Ethereal = true;
                // session.Player.IgnoreCollisions = true;
                session.Player.NoDraw = true;
                // session.Player.ReportCollisions = false;
                session.Player.EnqueueBroadcastPhysicsState();
                session.Player.Visibility   = true;
                session.Player.Translucency = 0.5f;

                if (session.Player.CloakStatus > CloakStatus.On)
                {
                    CommandHandlerHelper.WriteOutputInfo(session, $"You will now appear as an admin. You must relog for this to take effect", ChatMessageType.Broadcast);
                }

                session.Player.SetProperty(ACE.Entity.Enum.Properties.PropertyInt.CloakStatus, (int)CloakStatus.On);

                //session.Player.CurrentLandblock?.EnqueueBroadcast(session.Player.Location, new GameMessageRemoveObject(session.Player));
                //session.Player.CurrentLandblock?.RemoveWorldObject(session.Player.Guid, false);
                //session.Player.CurrentLandblock?.EnqueueBroadcast(session.Player.Location, new GameMessageCreateObject(session.Player));
                //session.Network.EnqueueSend(new GameMessageCreateObject(session.Player));
                //session.Player.CurrentLandblock?.AddWorldObject(session.Player);

                break;

            case "player":
                if (session.AccessLevel > AccessLevel.Envoy)
                {
                    session.Player.Cloaked  = false;
                    session.Player.Ethereal = false;
                    // session.Player.IgnoreCollisions = false;
                    session.Player.NoDraw = false;
                    // session.Player.ReportCollisions = true;
                    session.Player.EnqueueBroadcastPhysicsState();
                    session.Player.Translucency = null;
                    session.Player.Visibility   = false;
                    session.Player.SetProperty(ACE.Entity.Enum.Properties.PropertyInt.CloakStatus, (int)CloakStatus.Player);

                    //session.Player.CurrentLandblock?.EnqueueBroadcast(session.Player.Location, new GameMessageRemoveObject(session.Player));
                    //session.Player.CurrentLandblock?.RemoveWorldObject(session.Player.Guid, false);
                    //session.Player.CurrentLandblock?.EnqueueBroadcast(session.Player.Location, new GameMessageCreateObject(session.Player));
                    //session.Player.CurrentLandblock?.AddWorldObject(session.Player);

                    CommandHandlerHelper.WriteOutputInfo(session, $"You will now appear as a player. You must relog for this to take effect", ChatMessageType.Broadcast);
                }
                else
                {
                    CommandHandlerHelper.WriteOutputInfo(session, $"You do not have permission to do that state", ChatMessageType.Broadcast);
                }
                break;

            case "creature":
                if (session.AccessLevel > AccessLevel.Envoy)
                {
                    session.Player.Cloaked  = false;
                    session.Player.Ethereal = false;
                    // session.Player.IgnoreCollisions = false;
                    session.Player.NoDraw = false;
                    // session.Player.ReportCollisions = true;
                    session.Player.EnqueueBroadcastPhysicsState();
                    session.Player.Translucency = null;
                    session.Player.Visibility   = false;
                    session.Player.SetProperty(ACE.Entity.Enum.Properties.PropertyInt.CloakStatus, (int)CloakStatus.Creature);

                    //session.Player.CurrentLandblock?.EnqueueBroadcast(session.Player.Location, new GameMessageRemoveObject(session.Player));
                    //session.Player.CurrentLandblock?.RemoveWorldObject(session.Player.Guid, false);
                    //session.Player.CurrentLandblock?.EnqueueBroadcast(session.Player.Location, new GameMessageCreateObject(session.Player));
                    //session.Player.CurrentLandblock?.AddWorldObject(session.Player);

                    CommandHandlerHelper.WriteOutputInfo(session, $"You will now appear as a creature. You must relog for this to take effect\nIn order to appear correctly, you must also set '@attackable on'\nUse @pk free to be allowed to attack all living things.", ChatMessageType.Broadcast);
                }
                else
                {
                    CommandHandlerHelper.WriteOutputInfo(session, $"You do not have permission to do that state", ChatMessageType.Broadcast);
                }
                break;

            default:
                session.Network.EnqueueSend(new GameMessageSystemChat("Please specify if you want cloaking on or off.", ChatMessageType.Broadcast));
                break;
            }
        }
示例#26
0
        public static void HandleLandblockPerformance(Session session, params string[] parameters)
        {
            var sb = new StringBuilder();

            var loadedLandblocks = LandblockManager.GetLoadedLandblocks();

            // Filter out landblocks that haven't recorded a certain amount of events
            var sortedBy5mAverage  = loadedLandblocks.Where(r => r.Monitor5m.EventHistory.TotalEvents >= 10).OrderByDescending(r => r.Monitor5m.EventHistory.AverageEventDuration).Take(10).ToList();
            var sortedBy1hrAverage = loadedLandblocks.Where(r => r.Monitor1h.EventHistory.TotalEvents >= 1000).OrderByDescending(r => r.Monitor1h.EventHistory.AverageEventDuration).Take(10).ToList();

            var combinedByAverage = sortedBy5mAverage.Concat(sortedBy1hrAverage).Distinct().OrderByDescending(r => Math.Max(r.Monitor5m.EventHistory.AverageEventDuration, r.Monitor1h.EventHistory.AverageEventDuration)).Take(10);

            sb.Append($"Most Busy Landblock - By Average{'\n'}");
            sb.Append($"~5m Hits   Avg  Long  Last - ~1h Hits   Avg  Long  Last - Location   Players  Creatures{'\n'}");

            foreach (var entry in combinedByAverage)
            {
                int players = 0, creatures = 0;
                foreach (var worldObject in entry.GetAllWorldObjectsForDiagnostics())
                {
                    if (worldObject is Player)
                    {
                        players++;
                    }
                    else if (worldObject is Creature)
                    {
                        creatures++;
                    }
                }

                sb.Append($"{entry.Monitor5m.EventHistory.TotalEvents.ToString().PadLeft(7)} {entry.Monitor5m.EventHistory.AverageEventDuration:N4} {entry.Monitor5m.EventHistory.LongestEvent:N3} {entry.Monitor5m.EventHistory.LastEvent:N3} - " +
                          $"{entry.Monitor1h.EventHistory.TotalEvents.ToString().PadLeft(7)} {entry.Monitor1h.EventHistory.AverageEventDuration:N4} {entry.Monitor1h.EventHistory.LongestEvent:N3} {entry.Monitor1h.EventHistory.LastEvent:N3} - " +
                          $"0x{entry.Id.Raw:X8} {players.ToString().PadLeft(7)}  {creatures.ToString().PadLeft(9)}{'\n'}");
            }

            var sortedBy5mLong  = loadedLandblocks.OrderByDescending(r => r.Monitor5m.EventHistory.LongestEvent).Take(10);
            var sortedBy1hrLong = loadedLandblocks.OrderByDescending(r => r.Monitor1h.EventHistory.LongestEvent).Take(10);

            var combinedByLong = sortedBy5mLong.Concat(sortedBy1hrLong).Distinct().OrderByDescending(r => Math.Max(r.Monitor5m.EventHistory.LongestEvent, r.Monitor1h.EventHistory.LongestEvent)).Take(10);

            sb.Append($"Most Busy Landblock - By Longest{'\n'}");
            sb.Append($"~5m Hits   Avg  Long  Last - ~1h Hits   Avg  Long  Last - Location   Players  Creatures{'\n'}");

            foreach (var entry in combinedByLong)
            {
                int players = 0, creatures = 0;
                foreach (var worldObject in entry.GetAllWorldObjectsForDiagnostics())
                {
                    if (worldObject is Player)
                    {
                        players++;
                    }
                    else if (worldObject is Creature)
                    {
                        creatures++;
                    }
                }

                sb.Append($"{entry.Monitor5m.EventHistory.TotalEvents.ToString().PadLeft(7)} {entry.Monitor5m.EventHistory.AverageEventDuration:N4} {entry.Monitor5m.EventHistory.LongestEvent:N3} {entry.Monitor5m.EventHistory.LastEvent:N3} - " +
                          $"{entry.Monitor1h.EventHistory.TotalEvents.ToString().PadLeft(7)} {entry.Monitor1h.EventHistory.AverageEventDuration:N4} {entry.Monitor1h.EventHistory.LongestEvent:N3} {entry.Monitor1h.EventHistory.LastEvent:N3} - " +
                          $"0x{entry.Id.Raw:X8} {players.ToString().PadLeft(7)}  {creatures.ToString().PadLeft(9)}{'\n'}");
            }

            CommandHandlerHelper.WriteOutputInfo(session, sb.ToString());
        }
示例#27
0
        public static void HandleCloak(Session session, params string[] parameters)
        {
            // Please specify if you want cloaking on or off.usage: @cloak < on / off / player / creature >
            // This command sets your current cloaking state.
            // < on > You will be completely invisible to players.
            // < off > You will show up as a normal.
            // < player > You will appear as a player. (No + and a white radar dot.)
            // < creature > You will appear as a creature. (No + and an orange radar dot.)
            // @cloak - Sets your cloaking state.

            // TODO: investigate translucensy/visbility of other cloaked admins.

            switch (parameters?[0].ToLower())
            {
            case "off":
                if (session.Player.CloakStatus == CloakStatus.Off)
                {
                    return;
                }

                session.Player.DeCloak();

                session.Player.SetProperty(PropertyInt.CloakStatus, (int)CloakStatus.Off);

                CommandHandlerHelper.WriteOutputInfo(session, $"You are no longer cloaked, can no longer pass through doors and will appear as an admin.", ChatMessageType.Broadcast);
                break;

            case "on":
                if (session.Player.CloakStatus == CloakStatus.On)
                {
                    return;
                }

                session.Player.HandleCloak();

                session.Player.SetProperty(PropertyInt.CloakStatus, (int)CloakStatus.On);

                CommandHandlerHelper.WriteOutputInfo(session, $"You are now cloaked.\nYou are now ethereal and can pass through doors.", ChatMessageType.Broadcast);
                break;

            case "player":
                if (session.AccessLevel > AccessLevel.Envoy)
                {
                    if (session.Player.CloakStatus == CloakStatus.Player)
                    {
                        return;
                    }

                    session.Player.SetProperty(PropertyInt.CloakStatus, (int)CloakStatus.Player);

                    session.Player.DeCloak();
                    CommandHandlerHelper.WriteOutputInfo(session, $"You will now appear as a player.", ChatMessageType.Broadcast);
                }
                else
                {
                    CommandHandlerHelper.WriteOutputInfo(session, $"You do not have permission to do that state", ChatMessageType.Broadcast);
                }
                break;

            case "creature":
                if (session.AccessLevel > AccessLevel.Envoy)
                {
                    if (session.Player.CloakStatus == CloakStatus.Creature)
                    {
                        return;
                    }

                    session.Player.SetProperty(PropertyInt.CloakStatus, (int)CloakStatus.Creature);
                    session.Player.Attackable = true;

                    session.Player.DeCloak();
                    CommandHandlerHelper.WriteOutputInfo(session, $"You will now appear as a creature.\nUse @pk free to be allowed to attack all living things.", ChatMessageType.Broadcast);
                }
                else
                {
                    CommandHandlerHelper.WriteOutputInfo(session, $"You do not have permission to do that state", ChatMessageType.Broadcast);
                }
                break;

            default:
                session.Network.EnqueueSend(new GameMessageSystemChat("Please specify if you want cloaking on or off.", ChatMessageType.Broadcast));
                break;
            }
        }
示例#28
0
        public static void HandleServerStatus(Session session, params string[] parameters)
        {
            // This is formatted very similarly to GDL.

            var sb = new StringBuilder();

            var proc = Process.GetCurrentProcess();

            sb.Append($"Server Status:{'\n'}");

            sb.Append($"Host Info: {Environment.OSVersion}, vCPU: {Environment.ProcessorCount}{'\n'}");

            var runTime = DateTime.Now - proc.StartTime;

            sb.Append($"Server Runtime: {(int)runTime.TotalHours}h {runTime.Minutes}m {runTime.Seconds}s{'\n'}");

            sb.Append($"Total CPU Time: {(int)proc.TotalProcessorTime.TotalHours}h {proc.TotalProcessorTime.Minutes}m {proc.TotalProcessorTime.Seconds}s, Threads: {proc.Threads.Count}{'\n'}");

            // todo, add actual system memory used/avail
            sb.Append($"{(proc.PrivateMemorySize64 >> 20):N0} MB used{'\n'}");  // sb.Append($"{(proc.PrivateMemorySize64 >> 20)} MB used, xxxx / yyyy MB physical mem free.{'\n'}");

            sb.Append($"{NetworkManager.GetSessionCount():N0} connections, {NetworkManager.GetUniqueSessionEndpointCount():N0} unique connections, {PlayerManager.GetAllOnline().Count:N0} players online{'\n'}");
            sb.Append($"Total Accounts Created: {DatabaseManager.Authentication.GetAccountCount():N0}, Total Characters Created: {(PlayerManager.GetAllOffline().Count + PlayerManager.GetAllOnline().Count):N0}{'\n'}");

            // 330 active objects, 1931 total objects(16777216 buckets.)

            // todo, expand this
            var loadedLandblocks = LandblockManager.GetLoadedLandblocks();
            int dormantLandblocks = 0, activeDungeonLandblocks = 0, dormantDungeonLandblocks = 0;
            int players = 0, creatures = 0, missiles = 0, other = 0, total = 0;

            foreach (var landblock in loadedLandblocks)
            {
                if (landblock.IsDormant)
                {
                    dormantLandblocks++;
                }

                if (landblock.IsDungeon)
                {
                    if (landblock.IsDormant)
                    {
                        dormantDungeonLandblocks++;
                    }
                    else
                    {
                        activeDungeonLandblocks++;
                    }
                }

                foreach (var worldObject in landblock.GetAllWorldObjectsForDiagnostics())
                {
                    if (worldObject is Player)
                    {
                        players++;
                    }
                    else if (worldObject is Creature)
                    {
                        creatures++;
                    }
                    else if (worldObject.Missile ?? false)
                    {
                        missiles++;
                    }
                    else
                    {
                        other++;
                    }

                    total++;
                }
            }
            sb.Append($"Landblocks: {(loadedLandblocks.Count - dormantLandblocks):N0} active ({activeDungeonLandblocks:N0} dungeons), {dormantLandblocks:N0} dormant ({dormantDungeonLandblocks:N0} dungeons) - Players: {players:N0}, Creatures: {creatures:N0}, Missiles: {missiles:N0}, Other: {other:N0}, Total: {total:N0}.{'\n'}"); // 11 total blocks loaded. 11 active. 0 pending dormancy. 0 dormant. 314 unloaded.
            // 11 total blocks loaded. 11 active. 0 pending dormancy. 0 dormant. 314 unloaded.

            if (ServerPerformanceMonitor.IsRunning)
            {
                sb.Append($"Server Performance Monitor - UpdateGameWorld ~5m {ServerPerformanceMonitor.GetEventHistory5m(ServerPerformanceMonitor.MonitorType.UpdateGameWorld_Entire).AverageEventDuration:N3}, ~1h {ServerPerformanceMonitor.GetEventHistory1h(ServerPerformanceMonitor.MonitorType.UpdateGameWorld_Entire).AverageEventDuration:N3} s{'\n'}");
            }
            else
            {
                sb.Append($"Server Performance Monitor - Not running. To start use /serverperformance start{'\n'}");
            }

            sb.Append($"Physics Cache Counts - BSPCache: {BSPCache.Count:N0}, GfxObjCache: {GfxObjCache.Count:N0}, PolygonCache: {PolygonCache.Count:N0}, VertexCache: {VertexCache.Count:N0}{'\n'}");

            sb.Append($"Total Server Objects: {ServerObjectManager.ServerObjects.Count:N0}{'\n'}");

            sb.Append($"World DB Cache Counts - Weenies: {DatabaseManager.World.GetWeenieCacheCount():N0}, LandblockInstances: {DatabaseManager.World.GetLandblockInstancesCacheCount():N0}, PointsOfInterest: {DatabaseManager.World.GetPointsOfInterestCacheCount():N0}, Cookbooks: {DatabaseManager.World.GetCookbookCacheCount():N0}, Spells: {DatabaseManager.World.GetSpellCacheCount():N0}, Encounters: {DatabaseManager.World.GetEncounterCacheCount():N0}, Events: {DatabaseManager.World.GetEventsCacheCount():N0}{'\n'}");
            sb.Append($"Shard DB Counts - Biotas: {DatabaseManager.Shard.GetBiotaCount():N0}{'\n'}");

            sb.Append(GuidManager.GetDynamicGuidDebugInfo() + '\n');

            sb.Append($"Portal.dat has {DatManager.PortalDat.FileCache.Count:N0} files cached of {DatManager.PortalDat.AllFiles.Count:N0} total{'\n'}");
            sb.Append($"Cell.dat has {DatManager.CellDat.FileCache.Count:N0} files cached of {DatManager.CellDat.AllFiles.Count:N0} total{'\n'}");

            CommandHandlerHelper.WriteOutputInfo(session, $"{sb}");
        }
示例#29
0
        public static void HandleCharacterForcedDelete(Session session, params string[] parameters)
        {
            var characterName = string.Join(" ", parameters);

            var foundPlayer = PlayerManager.FindByName(characterName, out var isOnline);

            if (foundPlayer == null)
            {
                CommandHandlerHelper.WriteOutputInfo(session, $"There is no character named {characterName} in the database.", ChatMessageType.Broadcast);
                return;
            }

            if (isOnline && foundPlayer is Player player)
            {
                player.Character.DeleteTime     = (ulong)Time.GetUnixTime();
                player.Character.IsDeleted      = true;
                player.CharacterChangesDetected = true;
                player.Session.LogOffPlayer(true);
                PlayerManager.HandlePlayerDelete(player.Character.Id);

                var success = PlayerManager.ProcessDeletedPlayer(player.Character.Id);
                if (success)
                {
                    CommandHandlerHelper.WriteOutputInfo(session, $"Successfully {(isOnline ? "booted and " : "")}deleted character {foundPlayer.Name} (0x{foundPlayer.Guid}).", ChatMessageType.Broadcast);
                }
                else
                {
                    CommandHandlerHelper.WriteOutputInfo(session, $"Unable to {(isOnline ? "boot and " : "")}delete character {foundPlayer.Name} (0x{foundPlayer.Guid}) due to PlayerManager failure.", ChatMessageType.Broadcast);
                }
            }
            else
            {
                var existingCharId = foundPlayer.Guid.Full; //DatabaseManager.Shard.BaseDatabase.GetCharacterStubByName(foundPlayer.Name).Id;

                DatabaseManager.Shard.GetCharacter(existingCharId, character =>
                {
                    if (character != null)
                    {
                        character.DeleteTime = (ulong)Time.GetUnixTime();
                        character.IsDeleted  = true;
                        DatabaseManager.Shard.SaveCharacter(character, new ReaderWriterLockSlim(), result =>
                        {
                            if (result)
                            {
                                var deleteOfflineChain = new ActionChain();
                                deleteOfflineChain.AddAction(WorldManager.ActionQueue, () => PlayerManager.HandlePlayerDelete(character.Id));
                                deleteOfflineChain.AddDelayForOneTick();
                                deleteOfflineChain.AddAction(WorldManager.ActionQueue, () =>
                                {
                                    var success = PlayerManager.ProcessDeletedPlayer(character.Id);
                                    if (success)
                                    {
                                        CommandHandlerHelper.WriteOutputInfo(session, $"Successfully {(isOnline ? "booted and " : "")}deleted character {foundPlayer.Name} (0x{foundPlayer.Guid}).", ChatMessageType.Broadcast);
                                    }
                                    else
                                    {
                                        CommandHandlerHelper.WriteOutputInfo(session, $"Unable to {(isOnline ? "boot and " : "")}delete character {foundPlayer.Name} (0x{foundPlayer.Guid}) due to PlayerManager failure.", ChatMessageType.Broadcast);
                                    }
                                });
                                deleteOfflineChain.EnqueueChain();
                            }
                            else
                            {
                                CommandHandlerHelper.WriteOutputInfo(session, $"Unable to {(isOnline ? "boot and " : "")}delete character {foundPlayer.Name} (0x{foundPlayer.Guid}) due to shard database SaveCharacter failure.", ChatMessageType.Broadcast);
                            }
                        });
                    }
                    else
                    {
                        CommandHandlerHelper.WriteOutputInfo(session, $"Unable to {(isOnline ? "boot and " : "")}delete character {foundPlayer.Name} (0x{foundPlayer.Guid}) due to shard database GetCharacter failure.", ChatMessageType.Broadcast);
                    }
                });
            }
        }