예제 #1
0
        public static void LogBroadcastChat(Channel channel, WorldObject sender, string message)
        {
            switch (channel)
            {
            case Channel.Abuse:
                if (!PropertyManager.GetBool("chat_log_abuse").Item)
                {
                    return;
                }
                break;

            case Channel.Admin:
                if (!PropertyManager.GetBool("chat_log_admin").Item)
                {
                    return;
                }
                break;

            case Channel.AllBroadcast:     // using this to sub in for a WorldBroadcast channel which isn't technically a channel
                if (!PropertyManager.GetBool("chat_log_global").Item)
                {
                    return;
                }
                break;

            case Channel.Audit:
                if (!PropertyManager.GetBool("chat_log_audit").Item)
                {
                    return;
                }
                break;

            case Channel.Advocate1:
            case Channel.Advocate2:
            case Channel.Advocate3:
                if (!PropertyManager.GetBool("chat_log_advocate").Item)
                {
                    return;
                }
                break;

            case Channel.Debug:
                if (!PropertyManager.GetBool("chat_log_debug").Item)
                {
                    return;
                }
                break;

            case Channel.Fellow:
            case Channel.FellowBroadcast:
                if (!PropertyManager.GetBool("chat_log_fellow").Item)
                {
                    return;
                }
                break;

            case Channel.Help:
                if (!PropertyManager.GetBool("chat_log_help").Item)
                {
                    return;
                }
                break;

            case Channel.Olthoi:
                if (!PropertyManager.GetBool("chat_log_olthoi").Item)
                {
                    return;
                }
                break;

            case Channel.QA1:
            case Channel.QA2:
                if (!PropertyManager.GetBool("chat_log_qa").Item)
                {
                    return;
                }
                break;

            case Channel.Sentinel:
                if (!PropertyManager.GetBool("chat_log_sentinel").Item)
                {
                    return;
                }
                break;

            case Channel.SocietyCelHanBroadcast:
            case Channel.SocietyEldWebBroadcast:
            case Channel.SocietyRadBloBroadcast:
                if (!PropertyManager.GetBool("chat_log_society").Item)
                {
                    return;
                }
                break;

            case Channel.AllegianceBroadcast:
            case Channel.CoVassals:
            case Channel.Monarch:
            case Channel.Patron:
            case Channel.Vassals:
                if (!PropertyManager.GetBool("chat_log_allegiance").Item)
                {
                    return;
                }
                break;

            case Channel.AlArqas:
            case Channel.Holtburg:
            case Channel.Lytelthorpe:
            case Channel.Nanto:
            case Channel.Rithwic:
            case Channel.Samsur:
            case Channel.Shoushi:
            case Channel.Yanshi:
            case Channel.Yaraq:
                if (!PropertyManager.GetBool("chat_log_townchans").Item)
                {
                    return;
                }
                break;

            default:
                return;
            }

            if (channel != Channel.AllBroadcast)
            {
                log.Info($"[CHAT][{channel.ToString().ToUpper()}] {(sender != null ? sender.Name : "[SYSTEM]")} says on the {channel} channel, \"{message}\"");
            }
            else
            {
                log.Info($"[CHAT][GLOBAL] {(sender != null ? sender.Name : "[SYSTEM]")} issued a world broadcast, \"{message}\"");
            }
        }
예제 #2
0
        public static void UpdatePKStatusForAllPlayers(string worldType, bool enabled)
        {
            switch (worldType)
            {
            case "pk_server":
                if (enabled)
                {
                    foreach (var player in GetAllOnline())
                    {
                        player.SetPlayerKillerStatus(PlayerKillerStatus.PK, true);
                    }

                    foreach (var player in GetAllOffline())
                    {
                        player.SetProperty(PropertyInt.PlayerKillerStatus, (int)PlayerKillerStatus.NPK);
                        player.SetProperty(PropertyFloat.MinimumTimeSincePk, 0);
                    }

                    var msg = $"This world has been changed to a Player Killer world. All players will become Player Killers in {PropertyManager.GetDouble("pk_respite_timer").Item} seconds.";
                    BroadcastToAll(new GameMessageSystemChat(msg, ChatMessageType.WorldBroadcast));
                    LogBroadcastChat(Channel.AllBroadcast, null, msg);
                }
                else
                {
                    foreach (var player in GetAllOnline())
                    {
                        player.SetPlayerKillerStatus(PlayerKillerStatus.NPK, true);
                    }

                    foreach (var player in GetAllOffline())
                    {
                        player.SetProperty(PropertyInt.PlayerKillerStatus, (int)PlayerKillerStatus.NPK);
                        player.SetProperty(PropertyFloat.MinimumTimeSincePk, 0);
                    }

                    var msg = "This world has been changed to a Non Player Killer world. All players are now Non-Player Killers.";
                    BroadcastToAll(new GameMessageSystemChat(msg, ChatMessageType.WorldBroadcast));
                    LogBroadcastChat(Channel.AllBroadcast, null, msg);
                }
                break;

            case "pkl_server":
                if (PropertyManager.GetBool("pk_server").Item)
                {
                    return;
                }
                if (enabled)
                {
                    foreach (var player in GetAllOnline())
                    {
                        player.SetPlayerKillerStatus(PlayerKillerStatus.PKLite, true);
                    }

                    foreach (var player in GetAllOffline())
                    {
                        player.SetProperty(PropertyInt.PlayerKillerStatus, (int)PlayerKillerStatus.NPK);
                        player.SetProperty(PropertyFloat.MinimumTimeSincePk, 0);
                    }

                    var msg = $"This world has been changed to a Player Killer Lite world. All players will become Player Killer Lites in {PropertyManager.GetDouble("pk_respite_timer").Item} seconds.";
                    BroadcastToAll(new GameMessageSystemChat(msg, ChatMessageType.WorldBroadcast));
                    LogBroadcastChat(Channel.AllBroadcast, null, msg);
                }
                else
                {
                    foreach (var player in GetAllOnline())
                    {
                        player.SetPlayerKillerStatus(PlayerKillerStatus.NPK, true);
                    }

                    foreach (var player in GetAllOffline())
                    {
                        player.SetProperty(PropertyInt.PlayerKillerStatus, (int)PlayerKillerStatus.NPK);
                        player.SetProperty(PropertyFloat.MinimumTimeSincePk, 0);
                    }

                    var msg = "This world has been changed to a Non Player Killer world. All players are now Non-Player Killers.";
                    BroadcastToAll(new GameMessageSystemChat(msg, ChatMessageType.WorldBroadcast));
                    LogBroadcastChat(Channel.AllBroadcast, null, msg);
                }
                break;
            }
        }
예제 #3
0
        private static void DoPlayerEnterWorld(Session session, Character character, Biota playerBiota, PossessedBiotas possessedBiotas)
        {
            Player player;

            Player.HandleNoLogLandblock(playerBiota);

            var stripAdminProperties  = false;
            var addAdminProperties    = false;
            var addSentinelProperties = false;

            if (ConfigManager.Config.Server.Accounts.OverrideCharacterPermissions)
            {
                if (session.AccessLevel <= AccessLevel.Advocate)                                                               // check for elevated characters
                {
                    if (playerBiota.WeenieType == (int)WeenieType.Admin || playerBiota.WeenieType == (int)WeenieType.Sentinel) // Downgrade weenie
                    {
                        character.IsPlussed    = false;
                        playerBiota.WeenieType = (int)WeenieType.Creature;
                        stripAdminProperties   = true;
                    }
                }
                else if (session.AccessLevel >= AccessLevel.Sentinel && session.AccessLevel <= AccessLevel.Envoy)
                {
                    if (playerBiota.WeenieType == (int)WeenieType.Creature || playerBiota.WeenieType == (int)WeenieType.Admin) // Up/downgrade weenie
                    {
                        character.IsPlussed    = true;
                        playerBiota.WeenieType = (int)WeenieType.Sentinel;
                        addSentinelProperties  = true;
                    }
                }
                else // Developers and Admins
                {
                    if (playerBiota.WeenieType == (int)WeenieType.Creature || playerBiota.WeenieType == (int)WeenieType.Sentinel) // Up/downgrade weenie
                    {
                        character.IsPlussed    = true;
                        playerBiota.WeenieType = (int)WeenieType.Admin;
                        addAdminProperties     = true;
                    }
                }
            }

            if (playerBiota.WeenieType == (int)WeenieType.Admin)
            {
                player = new Admin(playerBiota, possessedBiotas.Inventory, possessedBiotas.WieldedItems, character, session);
            }
            else if (playerBiota.WeenieType == (int)WeenieType.Sentinel)
            {
                player = new Sentinel(playerBiota, possessedBiotas.Inventory, possessedBiotas.WieldedItems, character, session);
            }
            else
            {
                player = new Player(playerBiota, possessedBiotas.Inventory, possessedBiotas.WieldedItems, character, session);
            }

            session.SetPlayer(player);

            if (stripAdminProperties) // continue stripping properties
            {
                player.CloakStatus = null;
                player.Attackable  = true;
                player.SetProperty(ACE.Entity.Enum.Properties.PropertyBool.DamagedByCollisions, true);
                player.AdvocateLevel   = null;
                player.ChannelsActive  = null;
                player.ChannelsAllowed = null;
                player.Invincible      = null;
                player.Cloaked         = null;


                player.ChangesDetected          = true;
                player.CharacterChangesDetected = true;
            }

            if (addSentinelProperties || addAdminProperties) // continue restoring properties to default
            {
                WorldObject weenie;

                if (addAdminProperties)
                {
                    weenie = Factories.WorldObjectFactory.CreateWorldObject(DatabaseManager.World.GetCachedWeenie("admin"), new ACE.Entity.ObjectGuid(ACE.Entity.ObjectGuid.Invalid.Full)) as Admin;
                }
                else
                {
                    weenie = Factories.WorldObjectFactory.CreateWorldObject(DatabaseManager.World.GetCachedWeenie("sentinel"), new ACE.Entity.ObjectGuid(ACE.Entity.ObjectGuid.Invalid.Full)) as Sentinel;
                }

                if (weenie != null)
                {
                    player.CloakStatus = CloakStatus.Off;
                    player.Attackable  = weenie.Attackable;
                    player.SetProperty(ACE.Entity.Enum.Properties.PropertyBool.DamagedByCollisions, false);
                    player.AdvocateLevel   = weenie.GetProperty(ACE.Entity.Enum.Properties.PropertyInt.AdvocateLevel);
                    player.ChannelsActive  = (Channel?)weenie.GetProperty(ACE.Entity.Enum.Properties.PropertyInt.ChannelsActive);
                    player.ChannelsAllowed = (Channel?)weenie.GetProperty(ACE.Entity.Enum.Properties.PropertyInt.ChannelsAllowed);
                    player.Invincible      = false;
                    player.Cloaked         = false;


                    player.ChangesDetected          = true;
                    player.CharacterChangesDetected = true;
                }
            }

            // If the client is missing a location, we start them off in the starter dungeon
            if (session.Player.Location == null)
            {
                if (session.Player.Instantiation != null)
                {
                    session.Player.Location = new Position(session.Player.Instantiation);
                }
                else
                {
                    session.Player.Location = new Position(2349072813, 12.3199f, -28.482f, 0.0049999995f, 0.0f, 0.0f, -0.9408059f, -0.3389459f);
                }
            }

            session.Player.PlayerEnterWorld();

            LandblockManager.AddObject(session.Player, true);

            var popup_header  = PropertyManager.GetString("popup_header").Item;
            var popup_motd    = PropertyManager.GetString("popup_motd").Item;
            var popup_welcome = PropertyManager.GetString("popup_welcome").Item;

            if (character.TotalLogins <= 1)
            {
                session.Network.EnqueueSend(new GameEventPopupString(session, AppendLines(popup_header, popup_motd, popup_welcome)));
            }
            else if (!string.IsNullOrEmpty(popup_motd))
            {
                session.Network.EnqueueSend(new GameEventPopupString(session, AppendLines(popup_header, popup_motd)));
            }

            var info = "Welcome to Asheron's Call\n  powered by ACEmulator\n\nFor more information on commands supported by this server, type @acehelp\n";

            session.Network.EnqueueSend(new GameMessageSystemChat(info, ChatMessageType.Broadcast));

            var server_motd = PropertyManager.GetString("server_motd").Item;

            if (!string.IsNullOrEmpty(server_motd))
            {
                session.Network.EnqueueSend(new GameMessageSystemChat($"{server_motd}\n", ChatMessageType.Broadcast));
            }
        }
예제 #4
0
        /// <summary>
        /// Returns the time remaining until the player can solve this quest again
        /// </summary>
        public TimeSpan GetNextSolveTime(string questFormat)
        {
            var questName = GetQuestName(questFormat);

            var quest = DatabaseManager.World.GetCachedQuest(questName);

            if (quest == null)
            {
                return(TimeSpan.MaxValue);   // world quest not found - cannot solve it
            }
            var playerQuest = GetQuest(questName);

            if (playerQuest == null)
            {
                return(TimeSpan.MinValue);   // player hasn't completed this quest yet - can solve immediately
            }
            if (quest.MaxSolves > -1 && playerQuest.NumTimesCompleted >= quest.MaxSolves)
            {
                return(TimeSpan.MaxValue);   // cannot solve this quest again - max solves reached / exceeded
            }
            var  currentTime = (uint)Time.GetUnixTime();
            uint nextSolveTime;

            if (CanScaleQuestMinDelta(quest))
            {
                nextSolveTime = playerQuest.LastTimeCompleted + (uint)(quest.MinDelta * PropertyManager.GetDouble("quest_mindelta_rate", 1).Item);
            }
            else
            {
                nextSolveTime = playerQuest.LastTimeCompleted + quest.MinDelta;
            }

            if (currentTime >= nextSolveTime)
            {
                return(TimeSpan.MinValue);   // can solve again now - next solve time expired
            }
            // return the time remaining on the player's quest timer
            return(TimeSpan.FromSeconds(nextSolveTime - currentTime));
        }
예제 #5
0
        private static void DoPlayerEnterWorld(Session session, Character character, Biota playerBiota, PossessedBiotas possessedBiotas)
        {
            Player player;

            Player.HandleNoLogLandblock(playerBiota);

            var stripAdminProperties  = false;
            var addAdminProperties    = false;
            var addSentinelProperties = false;

            if (ConfigManager.Config.Server.Accounts.OverrideCharacterPermissions)
            {
                if (session.AccessLevel <= AccessLevel.Advocate)                                                     // check for elevated characters
                {
                    if (playerBiota.WeenieType == WeenieType.Admin || playerBiota.WeenieType == WeenieType.Sentinel) // Downgrade weenie
                    {
                        character.IsPlussed    = false;
                        playerBiota.WeenieType = WeenieType.Creature;
                        stripAdminProperties   = true;
                    }
                }
                else if (session.AccessLevel >= AccessLevel.Sentinel && session.AccessLevel <= AccessLevel.Envoy)
                {
                    if (playerBiota.WeenieType == WeenieType.Creature || playerBiota.WeenieType == WeenieType.Admin) // Up/downgrade weenie
                    {
                        character.IsPlussed    = true;
                        playerBiota.WeenieType = WeenieType.Sentinel;
                        addSentinelProperties  = true;
                    }
                }
                else // Developers and Admins
                {
                    if (playerBiota.WeenieType == WeenieType.Creature || playerBiota.WeenieType == WeenieType.Sentinel) // Up/downgrade weenie
                    {
                        character.IsPlussed    = true;
                        playerBiota.WeenieType = WeenieType.Admin;
                        addAdminProperties     = true;
                    }
                }
            }

            if (playerBiota.WeenieType == WeenieType.Admin)
            {
                player = new Admin(playerBiota, possessedBiotas.Inventory, possessedBiotas.WieldedItems, character, session);
            }
            else if (playerBiota.WeenieType == WeenieType.Sentinel)
            {
                player = new Sentinel(playerBiota, possessedBiotas.Inventory, possessedBiotas.WieldedItems, character, session);
            }
            else
            {
                player = new Player(playerBiota, possessedBiotas.Inventory, possessedBiotas.WieldedItems, character, session);
            }

            session.SetPlayer(player);

            if (stripAdminProperties) // continue stripping properties
            {
                player.CloakStatus = CloakStatus.Undef;
                player.Attackable  = true;
                player.SetProperty(ACE.Entity.Enum.Properties.PropertyBool.DamagedByCollisions, true);
                player.AdvocateLevel            = null;
                player.ChannelsActive           = null;
                player.ChannelsAllowed          = null;
                player.Invincible               = false;
                player.Cloaked                  = null;
                player.IgnoreHouseBarriers      = false;
                player.IgnorePortalRestrictions = false;
                player.SafeSpellComponents      = false;


                player.ChangesDetected          = true;
                player.CharacterChangesDetected = true;
            }

            if (addSentinelProperties || addAdminProperties) // continue restoring properties to default
            {
                WorldObject weenie;

                if (addAdminProperties)
                {
                    weenie = Factories.WorldObjectFactory.CreateWorldObject(DatabaseManager.World.GetCachedWeenie("admin"), new ACE.Entity.ObjectGuid(ACE.Entity.ObjectGuid.Invalid.Full));
                }
                else
                {
                    weenie = Factories.WorldObjectFactory.CreateWorldObject(DatabaseManager.World.GetCachedWeenie("sentinel"), new ACE.Entity.ObjectGuid(ACE.Entity.ObjectGuid.Invalid.Full));
                }

                if (weenie != null)
                {
                    player.CloakStatus = CloakStatus.Off;
                    player.Attackable  = weenie.Attackable;
                    player.SetProperty(ACE.Entity.Enum.Properties.PropertyBool.DamagedByCollisions, false);
                    player.AdvocateLevel   = weenie.GetProperty(ACE.Entity.Enum.Properties.PropertyInt.AdvocateLevel);
                    player.ChannelsActive  = (Channel?)weenie.GetProperty(ACE.Entity.Enum.Properties.PropertyInt.ChannelsActive);
                    player.ChannelsAllowed = (Channel?)weenie.GetProperty(ACE.Entity.Enum.Properties.PropertyInt.ChannelsAllowed);
                    player.Invincible      = false;
                    player.Cloaked         = false;


                    player.ChangesDetected          = true;
                    player.CharacterChangesDetected = true;
                }
            }

            // If the client is missing a location, we start them off in the starter town they chose
            if (session.Player.Location == null)
            {
                if (session.Player.Instantiation != null)
                {
                    session.Player.Location = new Position(session.Player.Instantiation);
                }
                else
                {
                    session.Player.Location = new Position(0xA9B40019, 84, 7.1f, 94, 0, 0, -0.0784591f, 0.996917f);  // ultimate fallback
                }
            }

            session.Player.PlayerEnterWorld();

            var success = LandblockManager.AddObject(session.Player, true);

            if (!success)
            {
                // send to lifestone, or fallback location
                var fixLoc = session.Player.Sanctuary ?? new Position(0xA9B40019, 84, 7.1f, 94, 0, 0, -0.0784591f, 0.996917f);

                log.Error($"WorldManager.DoPlayerEnterWorld: failed to spawn {session.Player.Name}, relocating to {fixLoc.ToLOCString()}");

                session.Player.Location = new Position(fixLoc);
                LandblockManager.AddObject(session.Player, true);

                var actionChain = new ActionChain();
                actionChain.AddDelaySeconds(5.0f);
                actionChain.AddAction(session.Player, () =>
                {
                    if (session != null && session.Player != null)
                    {
                        session.Player.Teleport(fixLoc);
                    }
                });
                actionChain.EnqueueChain();
            }

            var popup_header  = PropertyManager.GetString("popup_header").Item;
            var popup_motd    = PropertyManager.GetString("popup_motd").Item;
            var popup_welcome = PropertyManager.GetString("popup_welcome").Item;

            if (character.TotalLogins <= 1)
            {
                session.Network.EnqueueSend(new GameEventPopupString(session, AppendLines(popup_header, popup_motd, popup_welcome)));
            }
            else if (!string.IsNullOrEmpty(popup_motd))
            {
                session.Network.EnqueueSend(new GameEventPopupString(session, AppendLines(popup_header, popup_motd)));
            }

            var info = "Welcome to Asheron's Call\n  powered by ACEmulator\n\nFor more information on commands supported by this server, type @acehelp\n";

            session.Network.EnqueueSend(new GameMessageSystemChat(info, ChatMessageType.Broadcast));

            var server_motd = PropertyManager.GetString("server_motd").Item;

            if (!string.IsNullOrEmpty(server_motd))
            {
                session.Network.EnqueueSend(new GameMessageSystemChat($"{server_motd}\n", ChatMessageType.Broadcast));
            }
        }
예제 #6
0
        /// <summary>
        /// Threaded task created when performing a server shutdown
        /// </summary>
        private static void ShutdownServer()
        {
            var shutdownTime = DateTime.UtcNow.AddSeconds(ShutdownInterval);

            ShutdownTime = shutdownTime;

            var lastNoticeTime = DateTime.UtcNow;

            // wait for shutdown interval to expire
            while (shutdownTime != DateTime.MinValue && shutdownTime >= DateTime.UtcNow)
            {
                // this allows the server shutdown to be canceled
                if (!ShutdownInitiated)
                {
                    // reset shutdown details
                    string shutdownText = $"The server has canceled the shutdown procedure @ {DateTime.UtcNow} UTC";
                    log.Info(shutdownText);

                    // special text
                    foreach (var player in PlayerManager.GetAllOnline())
                    {
                        player.Session.WorldBroadcast(shutdownText);
                    }

                    // break function
                    return;
                }

                lastNoticeTime = NotifyPlayersOfPendingShutdown(lastNoticeTime, shutdownTime.AddSeconds(1));

                Thread.Sleep(10);
            }

            ShutdownInProgress = true;

            PropertyManager.ResyncVariables();
            PropertyManager.StopUpdating();

            WorldManager.EnqueueAction(new ActionEventDelegate(() =>
            {
                log.Debug("Logging off all players...");

                // logout each player
                foreach (var player in PlayerManager.GetAllOnline())
                {
                    player.Session.LogOffPlayer(true);
                }
            }));

            // Wait for all players to log out
            var logUpdateTS = DateTime.MinValue;
            int playerCount;

            while ((playerCount = PlayerManager.GetOnlineCount()) > 0)
            {
                logUpdateTS = LogStatusUpdate(logUpdateTS, $"Waiting for {playerCount} player{(playerCount > 1 ? "s" : "")} to log off...");
                Thread.Sleep(10);
            }

            WorldManager.EnqueueAction(new ActionEventDelegate(() =>
            {
                log.Debug("Disconnecting all sessions...");

                // disconnect each session
                NetworkManager.DisconnectAllSessionsForShutdown();
            }));

            // Wait for all sessions to drop out
            logUpdateTS = DateTime.MinValue;
            int sessionCount;

            while ((sessionCount = NetworkManager.GetSessionCount()) > 0)
            {
                logUpdateTS = LogStatusUpdate(logUpdateTS, $"Waiting for {sessionCount} session{(sessionCount > 1 ? "s" : "")} to disconnect...");
                Thread.Sleep(10);
            }

            log.Debug("Adding all landblocks to destruction queue...");

            // Queue unloading of all the landblocks
            // The actual unloading will happen in WorldManager.UpdateGameWorld
            LandblockManager.AddAllActiveLandblocksToDestructionQueue();

            // Wait for all landblocks to unload
            logUpdateTS = DateTime.MinValue;
            int landblockCount;

            while ((landblockCount = LandblockManager.GetLoadedLandblocks().Count) > 0)
            {
                logUpdateTS = LogStatusUpdate(logUpdateTS, $"Waiting for {landblockCount} loaded landblock{(landblockCount > 1 ? "s" : "")} to unload...");
                Thread.Sleep(10);
            }

            log.Debug("Stopping world...");

            // Disabled thread update loop
            WorldManager.StopWorld();

            // Wait for world to end
            logUpdateTS = DateTime.MinValue;
            while (WorldManager.WorldActive)
            {
                logUpdateTS = LogStatusUpdate(logUpdateTS, "Waiting for world to stop...");
                Thread.Sleep(10);
            }

            log.Info("Saving OfflinePlayers that have unsaved changes...");
            PlayerManager.SaveOfflinePlayersWithChanges();

            // Wait for the database queue to empty
            logUpdateTS = DateTime.MinValue;
            int shardQueueCount;

            while ((shardQueueCount = DatabaseManager.Shard.QueueCount) > 0)
            {
                logUpdateTS = LogStatusUpdate(logUpdateTS, $"Waiting for database queue ({shardQueueCount}) to empty...");
                Thread.Sleep(10);
            }

            // Write exit to console/log
            log.Info($"Exiting at {DateTime.UtcNow}");

            // System exit
            Environment.Exit(Environment.ExitCode);
        }
예제 #7
0
        /// <summary>
        /// Handles the eviction process for a player house
        /// </summary>
        public static void HandleEviction(House house, uint playerGuid, bool multihouse = false)
        {
            // clear out slumlord inventory
            var slumlord = house.SlumLord;

            slumlord.ClearInventory(true);

            var player = PlayerManager.FindByGuid(playerGuid, out bool isOnline);

            if (!PropertyManager.GetBool("house_rent_enabled", true).Item&& !multihouse)
            {
                // rent disabled, push forward
                var purchaseTime = (uint)(player.HousePurchaseTimestamp ?? 0);
                var nextRentTime = house.GetRentDue(purchaseTime);
                player.HouseRentTimestamp = (int)nextRentTime;

                log.Info($"HouseManager.HandleRentPaid({player.Name}): house rent disabled via config");

                // re-add item to queue
                AddRentQueue(player, house);
                return;
            }

            // handle eviction
            house.HouseOwner     = null;
            house.MonarchId      = null;
            house.HouseOwnerName = null;

            house.ClearPermissions();

            house.SaveBiotaToDatabase();

            // relink
            house.UpdateLinks();

            // player slumlord 'off' animation
            var off = new Motion(MotionStance.Invalid, MotionCommand.Off);

            slumlord.CurrentMotionState = off;
            slumlord.EnqueueBroadcastMotion(off);

            // reset slumlord name
            var weenie = DatabaseManager.World.GetCachedWeenie(slumlord.WeenieClassId);
            var wo     = WorldObjectFactory.CreateWorldObject(weenie, ObjectGuid.Invalid);

            slumlord.Name = wo.Name;

            slumlord.EnqueueBroadcast(new GameMessagePublicUpdatePropertyString(slumlord, PropertyString.Name, wo.Name));
            slumlord.SaveBiotaToDatabase();

            // if evicting a multihouse owner's previous house,
            // no update for player properties
            if (player.HouseInstance == house.Guid.Full)
            {
                player.HouseId       = null;
                player.HouseInstance = null;
                //player.HousePurchaseTimestamp = null;
                player.HouseRentTimestamp = null;
            }
            else
            {
                log.Warn($"HouseManager.HandleRentEviction({house.Guid}, {player.Name}, {multihouse}): house guids don't match {player.HouseInstance}");
            }

            house.ClearRestrictions();

            log.Info($"HouseManager.HandleRentEviction({player.Name})");

            if (multihouse)
            {
                RemoveRentQueue(house.Guid.Full);

                player.SaveBiotaToDatabase();

                return;
            }

            if (!isOnline)
            {
                // inform player of eviction when they log in
                var offlinePlayer = PlayerManager.GetOfflinePlayer(playerGuid);
                if (offlinePlayer == null)
                {
                    log.Warn($"{player.Name}.HandleEviction(): couldn't find offline player");
                    return;
                }
                offlinePlayer.SetProperty(PropertyBool.HouseEvicted, true);
                offlinePlayer.SaveBiotaToDatabase();
                return;
            }

            var onlinePlayer = PlayerManager.GetOnlinePlayer(playerGuid);

            onlinePlayer.House = null;

            // send text message
            onlinePlayer.Session.Network.EnqueueSend(new GameMessageSystemChat("You abandon your house!", ChatMessageType.Broadcast));
            onlinePlayer.RemoveDeed();

            onlinePlayer.SaveBiotaToDatabase();

            // clear house panel for online player
            var actionChain = new ActionChain();

            actionChain.AddDelaySeconds(3.0f);  // wait for slumlord inventory biotas above to save
            actionChain.AddAction(onlinePlayer, onlinePlayer.HandleActionQueryHouse);
            actionChain.EnqueueChain();
        }
예제 #8
0
        /// <summary>
        /// Queries the status of multi-house owners on the server
        /// </summary>
        private static void QueryMultiHouse()
        {
            var slumlordBiotas = DatabaseManager.Shard.GetBiotasByType(WeenieType.SlumLord);

            var playerHouses  = new Dictionary <IPlayer, List <Biota> >();
            var accountHouses = new Dictionary <string, List <Biota> >();

            foreach (var slumlord in slumlordBiotas)
            {
                var biotaOwner = slumlord.BiotaPropertiesIID.FirstOrDefault(i => i.Type == (ushort)PropertyInstanceId.HouseOwner);
                if (biotaOwner == null)
                {
                    // this is fine. this is just a house that was purchased, and then later abandoned
                    //Console.WriteLine($"HouseManager.QueryMultiHouse(): couldn't find owner for house {slumlord.Id:X8}");
                    continue;
                }
                var owner = PlayerManager.FindByGuid(biotaOwner.Value);
                if (owner == null)
                {
                    Console.WriteLine($"HouseManager.QueryMultiHouse(): couldn't find owner {biotaOwner.Value:X8}");
                    continue;
                }

                if (!playerHouses.TryGetValue(owner, out var houses))
                {
                    houses = new List <Biota>();
                    playerHouses.Add(owner, houses);
                }
                houses.Add(slumlord);

                var accountName = owner.Account != null ? owner.Account.AccountName : "NULL";

                if (!accountHouses.TryGetValue(accountName, out var aHouses))
                {
                    aHouses = new List <Biota>();
                    accountHouses.Add(accountName, aHouses);
                }
                aHouses.Add(slumlord);
            }


            if (PropertyManager.GetBool("house_per_char").Item)
            {
                var results = playerHouses.Where(i => i.Value.Count() > 1).OrderByDescending(i => i.Value.Count());

                if (results.Count() > 0)
                {
                    Console.WriteLine("Multi-house owners:");
                }

                foreach (var playerHouse in results)
                {
                    Console.WriteLine($"{playerHouse.Key.Name}: {playerHouse.Value.Count}");

                    for (var i = 0; i < playerHouse.Value.Count; i++)
                    {
                        Console.WriteLine($"{i + 1}. {GetCoords(playerHouse.Value[i])}");
                    }
                }
            }
            else
            {
                var results = accountHouses.Where(i => i.Value.Count() > 1).OrderByDescending(i => i.Value.Count());

                if (results.Count() > 0)
                {
                    Console.WriteLine("Multi-house owners:");
                }

                foreach (var accountHouse in results)
                {
                    Console.WriteLine($"{accountHouse.Key}: {accountHouse.Value.Count}");

                    for (var i = 0; i < accountHouse.Value.Count; i++)
                    {
                        Console.WriteLine($"{i + 1}. {GetCoords(accountHouse.Value[i])}");
                    }
                }
            }
        }
예제 #9
0
        /// <summary>
        /// Handles the eviction process for a player house
        /// </summary>
        public static void HandleEviction(House house, uint playerGuid, bool multihouse = false, bool force = false)
        {
            // clear out slumlord inventory
            var slumlord = house.SlumLord;

            slumlord.ClearInventory(true);

            var player = PlayerManager.FindByGuid(playerGuid, out bool isOnline);

            if (!PropertyManager.GetBool("house_rent_enabled", true).Item&& !multihouse && !force)
            {
                // rent disabled, push forward
                var purchaseTime = (uint)(player.HousePurchaseTimestamp ?? 0);
                var nextRentTime = house.GetRentDue(purchaseTime);
                player.HouseRentTimestamp = (int)nextRentTime;

                log.Debug($"[HOUSE] HouseManager.HandleRentPaid({player.Name}): house rent disabled via config");

                // re-add item to queue
                AddRentQueue(player, house);
                return;
            }

            // handle eviction
            house.HouseOwner     = null;
            house.MonarchId      = null;
            house.HouseOwnerName = null;

            house.ClearPermissions();

            house.SaveBiotaToDatabase();

            // relink
            house.UpdateLinks();

            if (house.HasDungeon)
            {
                var dungeonHouse = house.GetDungeonHouse();
                if (dungeonHouse != null)
                {
                    dungeonHouse.UpdateLinks();
                }
            }

            // player slumlord 'off' animation
            slumlord.Off();

            // reset slumlord name
            slumlord.SetAndBroadcastName();

            slumlord.SaveBiotaToDatabase();

            // if evicting a multihouse owner's previous house,
            // no update for player properties
            if (player.HouseInstance == house.Guid.Full)
            {
                player.HouseId       = null;
                player.HouseInstance = null;
                //player.HousePurchaseTimestamp = null;
                player.HouseRentTimestamp = null;
            }
            else
            {
                log.Warn($"HouseManager.HandleRentEviction({house.Guid}, {player.Name}, {multihouse}): house guids don't match {player.HouseInstance}");
            }

            house.ClearRestrictions();

            log.Debug($"[HOUSE] HouseManager.HandleRentEviction({player.Name})");

            if (multihouse)
            {
                RemoveRentQueue(house.Guid.Full);

                player.SaveBiotaToDatabase();

                return;
            }

            if (!isOnline)
            {
                // inform player of eviction when they log in
                var offlinePlayer = PlayerManager.GetOfflinePlayer(playerGuid);
                if (offlinePlayer == null)
                {
                    log.Warn($"{player.Name}.HandleEviction(): couldn't find offline player");
                    return;
                }
                offlinePlayer.SetProperty(PropertyBool.HouseEvicted, true);
                offlinePlayer.SaveBiotaToDatabase();
                return;
            }

            var onlinePlayer = PlayerManager.GetOnlinePlayer(playerGuid);

            onlinePlayer.House = null;

            // send text message
            onlinePlayer.Session.Network.EnqueueSend(new GameMessageSystemChat("You've been evicted from your house!", ChatMessageType.Broadcast));
            onlinePlayer.RemoveDeed();

            onlinePlayer.SaveBiotaToDatabase();

            // clear house panel for online player
            var actionChain = new ActionChain();

            actionChain.AddDelaySeconds(3.0f);  // wait for slumlord inventory biotas above to save
            actionChain.AddAction(onlinePlayer, onlinePlayer.HandleActionQueryHouse);
            actionChain.EnqueueChain();
        }
예제 #10
0
        public static async void HandleEviction(PlayerHouse playerHouse)
        {
            // todo: copied from Player_House.HandleActionAbandonHouse, move to House.Abandon()
            // todo: get online copy of house
            var house = playerHouse.House;

            // clear out slumlord inventory
            // todo: get online copy of house
            var slumlord = house.SlumLord;

            slumlord.ClearInventory(true);

            var player = PlayerManager.FindByGuid(playerHouse.PlayerGuid, out bool isOnline);

            if (!PropertyManager.GetBool("house_rent_enabled", true).Item)
            {
                // rent disabled, push forward
                var purchaseTime = (uint)(player.HousePurchaseTimestamp ?? 0);
                var nextRentTime = house.GetRentDue(purchaseTime);
                player.HouseRentTimestamp = (int)nextRentTime;

                log.Info($"HouseManager.HandleRentPaid({playerHouse.PlayerName}): house rent disabled via config");

                BuildRentQueue();
                return;
            }

            house.HouseOwner     = null;
            house.MonarchId      = null;
            house.HouseOwnerName = null;

            house.ClearPermissions();

            house.SaveBiotaToDatabase();

            // relink
            house.UpdateLinks();

            // player slumlord 'off' animation
            var off = new Motion(MotionStance.Invalid, MotionCommand.Off);

            slumlord.CurrentMotionState = off;
            slumlord.EnqueueBroadcastMotion(off);

            // reset slumlord name
            var weenie = DatabaseManager.World.GetCachedWeenie(slumlord.WeenieClassId);
            var wo     = WorldObjectFactory.CreateWorldObject(weenie, ObjectGuid.Invalid);

            slumlord.Name = wo.Name;

            slumlord.EnqueueBroadcast(new GameMessagePublicUpdatePropertyString(slumlord, PropertyString.Name, wo.Name));
            slumlord.SaveBiotaToDatabase();

            player.HouseId       = null;
            player.HouseInstance = null;
            //player.HousePurchaseTimestamp = null;
            player.HouseRentTimestamp = null;

            house.ClearRestrictions();

            log.Info($"HouseManager.HandleRentEviction({playerHouse.PlayerName})");

            BuildRentQueue();

            if (!isOnline)
            {
                // inform player of eviction when they log in
                var offlinePlayer = PlayerManager.GetOfflinePlayer(playerHouse.PlayerGuid);
                if (offlinePlayer == null)
                {
                    log.Warn($"{playerHouse.PlayerName}.HandleEviction(): couldn't find offline player");
                    return;
                }
                offlinePlayer.SetProperty(PropertyBool.HouseEvicted, true);
                offlinePlayer.SaveBiotaToDatabase();
                return;
            }

            var onlinePlayer = PlayerManager.GetOnlinePlayer(playerHouse.PlayerGuid);

            onlinePlayer.House = null;

            // send text message
            onlinePlayer.Session.Network.EnqueueSend(new GameMessageSystemChat("You abandon your house!", ChatMessageType.Broadcast));
            onlinePlayer.RemoveDeed();

            await Task.Delay(3000);     // wait for slumlord inventory biotas above to save

            onlinePlayer.HandleActionQueryHouse();
        }
예제 #11
0
        /// <summary>
        /// Threaded task created when performing a server shutdown
        /// </summary>
        private static void ShutdownServer()
        {
            var shutdownTime = DateTime.UtcNow.AddSeconds(ShutdownInterval);

            ShutdownTime = shutdownTime;

            var lastNoticeTime = DateTime.UtcNow;

            // wait for shutdown interval to expire
            while (shutdownTime != DateTime.MinValue && shutdownTime >= DateTime.UtcNow)
            {
                // this allows the server shutdown to be canceled
                if (!ShutdownInitiated)
                {
                    // reset shutdown details
                    string shutdownText = $"The server has canceled the shutdown procedure @ {DateTime.UtcNow} UTC";
                    log.Info(shutdownText);

                    // special text
                    foreach (var player in PlayerManager.GetAllOnline())
                    {
                        player.Session.WorldBroadcast(shutdownText);
                    }

                    // break function
                    return;
                }

                lastNoticeTime = NotifyPlayersOfPendingShutdown(lastNoticeTime, shutdownTime.AddSeconds(1));

                Thread.Sleep(10);
            }

            PropertyManager.ResyncVariables();
            PropertyManager.StopUpdating();

            log.Debug("Logging off all players...");

            // logout each player
            foreach (var player in PlayerManager.GetAllOnline())
            {
                player.Session.LogOffPlayer();
            }

            log.Info("Waiting for all players to log off...");

            // wait 10 seconds for log-off
            while (PlayerManager.GetAllOnline().Count > 0)
            {
                Thread.Sleep(10);
            }

            log.Debug("Adding all landblocks to destruction queue...");

            // Queue unloading of all the landblocks
            // The actual unloading will happen in WorldManager.UpdateGameWorld
            LandblockManager.AddAllActiveLandblocksToDestructionQueue();

            log.Info("Waiting for all active landblocks to unload...");

            while (LandblockManager.GetLoadedLandblocks().Count > 0)
            {
                Thread.Sleep(10);
            }

            log.Debug("Stopping world...");

            // Disabled thread update loop
            WorldManager.StopWorld();

            log.Info("Waiting for world to stop...");

            // Wait for world to end
            while (WorldManager.WorldActive)
            {
                Thread.Sleep(10);
            }

            log.Info("Saving OfflinePlayers that have unsaved changes...");
            PlayerManager.SaveOfflinePlayersWithChanges();

            log.Info("Waiting for database queue to empty...");

            // Wait for the database queue to empty
            while (DatabaseManager.Shard.QueueCount > 0)
            {
                Thread.Sleep(10);
            }

            // Write exit to console/log
            log.Info($"Exiting at {DateTime.UtcNow}");

            // System exit
            Environment.Exit(Environment.ExitCode);
        }