Exemplo n.º 1
0
        /// <summary>Checks against the guards for the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        /// <returns>A string with the error message for the user upon guard failure, else null.</returns>
        public override string Guards(ActionInput actionInput)
        {
            IController sender = actionInput.Controller;
            string commonFailure = VerifyCommonGuards(actionInput, ActionGuards);
            if (commonFailure != null)
            {
                return commonFailure;
            }

            // The comon guards already guarantees the sender is a player, hence no null checks here.
            this.player = sender.Thing;
            this.playerBehavior = sender.Thing.Behaviors.FindFirst<PlayerBehavior>();

            // Rule: The new pretitle must be empty or meet the length requirements.
            this.oldPretitle = this.player.SingularPrefix;

            if (!string.IsNullOrEmpty(actionInput.Tail)) {
                this.newPretitle = actionInput.Tail;

                if (this.newPretitle.Length < 2 || this.newPretitle.Length > 15)
                {
                    return "The pretitle may not be less than 2 nor more than 15 characters long.";
                }
            }

            //// One could implement 'no color' or 'no swearing' or 'no non-alpha character' rules here, etc.

            return null;
        }
Exemplo n.º 2
0
        /// <summary>Checks against the guards for the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        /// <returns>A string with the error message for the user upon guard failure, else null.</returns>
        public override string Guards(ActionInput actionInput)
        {
            IController sender = actionInput.Controller;
            string commonFailure = VerifyCommonGuards(actionInput, ActionGuards);
            if (commonFailure != null)
            {
                return commonFailure;
            }

            // This initiator is already guaranteed by VerifyCommonGuards to be a player, hence no null check.
            this.playerBehavior = sender.Thing.Behaviors.FindFirst<PlayerBehavior>();

            return null;
        }
Exemplo n.º 3
0
        /// <summary>Called upon authentication of a session.</summary>
        /// <param name="session">The authenticated session.</param>
        public void OnSessionAuthenticated(Session session)
        {
            // If there was already a connected player for this new, authentic user session,
            // kick the old one (as it may have been a prior disconnect or whatnot).
            PlayerBehavior previousPlayer = this.FindLoggedInPlayer(session.UserName);

            if (previousPlayer != null)
            {
                var msg = "Duplicate player match, kicking session id " + previousPlayer.SessionId;
                this.SystemHost.UpdateSystemHost(this, msg);

                var existingUserControlledBehavior = previousPlayer.Parent.Behaviors.FindFirst <UserControlledBehavior>();
                if (existingUserControlledBehavior != null)
                {
                    existingUserControlledBehavior.Controller.Write("Another connection has logged in as you; closing this connection.");
                }

                // @@@ TEST: Ensure this closes the connection correctly, etc; used to be rigged
                //     dangerously directly through the ServerManager.
                previousPlayer.LogOut();
                this.RemovePlayer(previousPlayer.Parent);
            }

            bool wasPlayerMissingDocument = false;

            // If this session doesn't have a player thing attached yet, load it up.  Note that
            // for situations like character creation, we might already have our Thing, so we
            // don't want to load a duplicate version of the just-created player Thing.
            if (session.Thing == null)
            {
                var playerBehavior = new PlayerBehavior();
                playerBehavior.Load(session.UserName);

                var player = new Thing(null)
                {
                    Name = playerBehavior.PlayerData.DisplayName
                };

                // Make sure that the playerBehavior has a parent set.
                playerBehavior.Parent = player;

                // Load game data from disk (RavenDb/NoSQL)
                PlayerDocument pd = this.LoadPlayerDocument(playerBehavior.PlayerData.ID);
                if (pd == null)
                {
                    // If we are here, this means that the player that we are trying to
                    // load does not have a corresponding player document in the NoSQL
                    // (RavenDb) store. Let's go and create a player document with default
                    // values.
                    player                = PrepareBaseCharacter(session);
                    player.Name           = playerBehavior.PlayerData.DisplayName;
                    playerBehavior.Parent = player;
                    playerBehavior.CreateMissingPlayerDocument();

                    var sb = new StringBuilder();

                    sb.AppendLine("This character is missing gaming data.");
                    sb.AppendFormat("The MUD engine is creating a default game settings for {0}.", playerBehavior.PlayerData.DisplayName);
                    sb.Append(Environment.NewLine);
                    sb.AppendLine("The system will now log you out. Please login again, to continue playing.");

                    session.Write(sb.ToString());

                    playerBehavior.LogOut();
                }

                // Get SensesBehavior and UserControlledBehavior from the PlayerDocument.
                var sensesBehavior         = pd.Behaviors.OfType <SensesBehavior>().FirstOrDefault();
                var userControlledBehavior = pd.Behaviors.OfType <UserControlledBehavior>().FirstOrDefault();

                // Setup the controlled behavior controller.
                userControlledBehavior.Controller = session;

                // Initialize the player behavior event processor.
                playerBehavior.InitEventProcessor(sensesBehavior, userControlledBehavior);

                // Get the player behavior with the game data
                var persistedPlayerBehavior = pd.Behaviors.OfType <PlayerBehavior>().FirstOrDefault();

                // Get data from the persisted player behavior and merge it into the manually created one
                playerBehavior.Gender    = persistedPlayerBehavior.Gender;
                playerBehavior.Race      = persistedPlayerBehavior.Race;
                playerBehavior.SessionId = session.ID;
                playerBehavior.Name      = session.UserName;
                playerBehavior.Prompt    = pd.PlayerPrompt;
                playerBehavior.RoleData  = persistedPlayerBehavior.RoleData;
                playerBehavior.ID        = persistedPlayerBehavior.ID;

                // We don't need the persisted player behavior anymore, so remove it
                pd.Behaviors.Remove(persistedPlayerBehavior);

                if (!wasPlayerMissingDocument)
                {
                    // Put all the persisted game data onto the right objects.
                    this.TranslateFromPlayerDocument(ref player, pd);

                    // Make sure to add the player behavior to the player Thing object.
                    playerBehavior.Parent = player;
                    player.Behaviors.Add(playerBehavior);
                    player.ID = "player/" + playerBehavior.ID;
                }

                if (playerBehavior.LogIn(session))
                {
                    lock (this.lockObject)
                    {
                        if (!this.playersList.Contains(playerBehavior))
                        {
                            this.playersList.Add(playerBehavior);
                        }
                    }

                    // Determine the screen buffer size.
                    if (session.Connection != null)
                    {
                        if (userControlledBehavior.PagingRowLimit >= 0)
                        {
                            session.Connection.PagingRowLimit = userControlledBehavior.PagingRowLimit;
                        }
                        else
                        {
                            int terminalHeight = session.Terminal.Height;

                            // If a broken client doesn't provide a valid terminal height, who knows
                            // what it might contain. In that case, default to 0 (no paging).
                            // 100 is an arbitrary realistic number. If this changes, the "buffer"
                            // command should also be changed for consistency. Or define the
                            // max/min as constants somewhere.
                            if (terminalHeight >= 0 && terminalHeight <= 100)
                            {
                                session.Connection.PagingRowLimit = session.Terminal.Height;
                            }
                            else
                            {
                                session.Connection.PagingRowLimit = 0;
                            }
                        }
                    }

                    session.Thing = player;

                    // @@@ HACK: Add player to Krondor's first room
                    PlacesManager.Instance.World.Children[0].Children[0].Add(player);

                    // Finally give the player some initial sensory feedback by having them look.
                    CommandManager.Instance.EnqueueAction(new ActionInput("look", userControlledBehavior.Controller));
                }
                else
                {
                    // @@@ TODO: Login denied? Back out of the session, disconnect, etc.
                    throw new NotImplementedException("Cancellation of login event is not yet supported.");
                }
            }

            // Finally, if the newly-logged in character replaced an old connection, notify the new
            // user of the problem.  We could also vary behavior/logging based on whether the IP
            // addresses match; same IP is safer to assume as replaced connection instead of breach.
            if (previousPlayer != null)
            {
                // @@@ TODO: Implement
            }
        }
Exemplo n.º 4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PlayerEventProcessor"/> class.
 /// </summary>
 /// <param name="playerBehavior">The player behavior.</param>
 /// <param name="sensesBehavior">The senses behavior.</param>
 /// <param name="userControlledBehavior">The user controlled behavior.</param>
 public PlayerEventProcessor(PlayerBehavior playerBehavior, SensesBehavior sensesBehavior, UserControlledBehavior userControlledBehavior)
 {
     this.playerBehavior         = playerBehavior;
     this.sensesBehavior         = sensesBehavior;
     this.userControlledBehavior = userControlledBehavior;
 }
Exemplo n.º 5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PlayerEventProcessor"/> class.
 /// </summary>
 /// <param name="playerBehavior">The player behavior.</param>
 /// <param name="sensesBehavior">The senses behavior.</param>
 /// <param name="userControlledBehavior">The user controlled behavior.</param>
 public PlayerEventProcessor(PlayerBehavior playerBehavior, SensesBehavior sensesBehavior, UserControlledBehavior userControlledBehavior)
 {
     this.playerBehavior = playerBehavior;
     this.sensesBehavior = sensesBehavior;
     this.userControlledBehavior = userControlledBehavior;
 }
Exemplo n.º 6
0
        /// <summary>Checks against the guards for the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        /// <returns>A string with the error message for the user upon guard failure, else null.</returns>
        public override string Guards(ActionInput actionInput)
        {
            string commonFailure = VerifyCommonGuards(actionInput, ActionGuards);
            if (commonFailure != null)
            {
                return commonFailure;
            }

            // The comon guards already guarantees the sender is a player, hence no null checks here.
            this.player = actionInput.Controller.Thing;
            this.playerBehavior = this.player.Behaviors.FindFirst<PlayerBehavior>();

            return null;
        }
Exemplo n.º 7
0
 public void Init()
 {
     this.playerBehavior = new PlayerBehavior();
 }
Exemplo n.º 8
0
        /// <summary>Checks against the guards for the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        /// <returns>A string with the error message for the user upon guard failure, else null.</returns>
        public override string Guards(ActionInput actionInput)
        {
            string commonFailure = VerifyCommonGuards(actionInput, ActionGuards);
            if (commonFailure != null)
            {
                return commonFailure;
            }

            this.playerBehavior = actionInput.Controller.Thing.Behaviors.FindFirst<PlayerBehavior>();

            return null;
        }
Exemplo n.º 9
0
        /// <summary>Called upon authentication of a session.</summary>
        /// <param name="session">The authenticated session.</param>
        public void OnSessionAuthenticated(Session session)
        {
            // If there was already a connected player for this new, authentic user session,
            // kick the old one (as it may have been a prior disconnect or whatnot).
            PlayerBehavior previousPlayer = this.FindLoggedInPlayer(session.UserName);
            if (previousPlayer != null)
            {
                var msg = "Duplicate player match, kicking session id " + previousPlayer.SessionId;
                this.SystemHost.UpdateSystemHost(this, msg);

                var existingUserControlledBehavior = previousPlayer.Parent.Behaviors.FindFirst<UserControlledBehavior>();
                if (existingUserControlledBehavior != null)
                {
                    existingUserControlledBehavior.Controller.Write("Another connection has logged in as you; closing this connection.");
                }

                // @@@ TEST: Ensure this closes the connection correctly, etc; used to be rigged
                //     dangerously directly through the ServerManager.
                previousPlayer.LogOut();
                this.RemovePlayer(previousPlayer.Parent);
            }

            bool wasPlayerMissingDocument = false;

            // If this session doesn't have a player thing attached yet, load it up.  Note that
            // for situations like character creation, we might already have our Thing, so we
            // don't want to load a duplicate version of the just-created player Thing.
            if (session.Thing == null)
            {
                var playerBehavior = new PlayerBehavior();
                playerBehavior.Load(session.UserName);

                var player = new Thing(null)
                {
                    Name = playerBehavior.PlayerData.DisplayName
                };

                // Make sure that the playerBehavior has a parent set.
                playerBehavior.Parent = player;

                // Load game data from disk (RavenDb/NoSQL)
                PlayerDocument pd = this.LoadPlayerDocument(playerBehavior.PlayerData.ID);
                if (pd == null)
                {
                    // If we are here, this means that the player that we are trying to
                    // load does not have a corresponding player document in the NoSQL
                    // (RavenDb) store. Let's go and create a player document with default
                    // values.
                    player = PrepareBaseCharacter(session);
                    player.Name = playerBehavior.PlayerData.DisplayName;
                    playerBehavior.Parent = player;
                    playerBehavior.CreateMissingPlayerDocument();

                    var sb = new StringBuilder();

                    sb.AppendLine("This character is missing gaming data.");
                    sb.AppendFormat("The MUD engine is creating a default game settings for {0}.", playerBehavior.PlayerData.DisplayName);
                    sb.Append(Environment.NewLine);
                    sb.AppendLine("The system will now log you out. Please login again, to continue playing.");

                    session.Write(sb.ToString());

                    playerBehavior.LogOut();
                }

                // Get SensesBehavior and UserControlledBehavior from the PlayerDocument.
                var sensesBehavior = pd.Behaviors.OfType<SensesBehavior>().FirstOrDefault();
                var userControlledBehavior = pd.Behaviors.OfType<UserControlledBehavior>().FirstOrDefault();

                // Setup the controlled behavior controller.
                userControlledBehavior.Controller = session;

                // Initialize the player behavior event processor.
                playerBehavior.InitEventProcessor(sensesBehavior, userControlledBehavior);

                // Get the player behavior with the game data
                var persistedPlayerBehavior = pd.Behaviors.OfType<PlayerBehavior>().FirstOrDefault();

                // Get data from the persisted player behavior and merge it into the manually created one
                playerBehavior.Gender = persistedPlayerBehavior.Gender;
                playerBehavior.Race = persistedPlayerBehavior.Race;
                playerBehavior.SessionId = session.ID;
                playerBehavior.Name = session.UserName;
                playerBehavior.Prompt = pd.PlayerPrompt;
                playerBehavior.RoleData = persistedPlayerBehavior.RoleData;
                playerBehavior.ID = persistedPlayerBehavior.ID;

                // We don't need the persisted player behavior anymore, so remove it
                pd.Behaviors.Remove(persistedPlayerBehavior);

                if (!wasPlayerMissingDocument)
                {
                    // Put all the persisted game data onto the right objects.
                    this.TranslateFromPlayerDocument(ref player, pd);

                    // Make sure to add the player behavior to the player Thing object.
                    playerBehavior.Parent = player;
                    player.Behaviors.Add(playerBehavior);
                    player.ID = "player/" + playerBehavior.ID;
                }

                if (playerBehavior.LogIn(session))
                {
                    lock (this.lockObject)
                    {
                        if (!this.playersList.Contains(playerBehavior))
                        {
                            this.playersList.Add(playerBehavior);
                        }
                    }

                    // Determine the screen buffer size.
                    if (session.Connection != null)
                    {
                        if (userControlledBehavior.PagingRowLimit >= 0)
                        {
                            session.Connection.PagingRowLimit = userControlledBehavior.PagingRowLimit;
                        }
                        else
                        {
                            int terminalHeight = session.Terminal.Height;

                            // If a broken client doesn't provide a valid terminal height, who knows
                            // what it might contain. In that case, default to 0 (no paging).
                            // 100 is an arbitrary realistic number. If this changes, the "buffer"
                            // command should also be changed for consistency. Or define the
                            // max/min as constants somewhere.
                            if (terminalHeight >= 0 && terminalHeight <= 100)
                            {
                                session.Connection.PagingRowLimit = session.Terminal.Height;
                            }
                            else
                            {
                                session.Connection.PagingRowLimit = 0;
                            }
                        }
                    }

                    session.Thing = player;

                    // @@@ HACK: Add player to Krondor's first room
                    PlacesManager.Instance.World.Children[0].Children[0].Add(player);

                    // Finally give the player some initial sensory feedback by having them look.
                    CommandManager.Instance.EnqueueAction(new ActionInput("look", userControlledBehavior.Controller));
                }
                else
                {
                    // @@@ TODO: Login denied? Back out of the session, disconnect, etc.
                    throw new NotImplementedException("Cancellation of login event is not yet supported.");
                }
            }

            // Finally, if the newly-logged in character replaced an old connection, notify the new
            // user of the problem.  We could also vary behavior/logging based on whether the IP
            // addresses match; same IP is safer to assume as replaced connection instead of breach.
            if (previousPlayer != null)
            {
                // @@@ TODO: Implement
            }
        }
Exemplo n.º 10
0
        /// <summary>Prepares the base character.</summary>
        /// <param name="session">The session.</param>
        /// <returns>Filled out base character.</returns>
        public static Thing PrepareBaseCharacter(Session session)
        {
            var movableBehavior = new MovableBehavior();
            var livingBehavior = new LivingBehavior();
            var sensesBehavior = new SensesBehavior();
            var userControlledBehavior = new UserControlledBehavior()
            {
                Controller = session,
            };
            var playerBehavior = new PlayerBehavior(sensesBehavior, userControlledBehavior)
            {
                SessionId = session.ID,
            };

            var player = new Thing(livingBehavior, sensesBehavior, userControlledBehavior, playerBehavior, movableBehavior);

            var game = GameSystemController.Instance;

            // Load the default stats for the current gaming system
            foreach (var gameStat in game.GameStats)
            {
                var currStat = new GameStat(session, gameStat.Name, gameStat.Abbreviation, gameStat.Formula, gameStat.Value, gameStat.MinValue, gameStat.MaxValue, gameStat.Visible);
                player.Stats.Add(currStat.Abbreviation, currStat);
            }

            // Load the secondary stats\attributes for the current gaming system
            foreach (var attribute in game.GameAttributes)
            {
                var newAttribute = new GameAttribute(session, attribute.Name, attribute.Abbreviation, attribute.Formula, attribute.Value, attribute.MinValue, attribute.MaxValue, attribute.Visible);
                player.Attributes.Add(newAttribute.Abbreviation, newAttribute);
            }

            return player;
        }