Ejemplo n.º 1
0
        /// <summary>Executes the command.</summary>
        /// <param name="actionInput">The full input specified for executing the command.</param>
        public override void Execute(ActionInput actionInput)
        {
            // Generate an item changed owner event.
            IController sender = actionInput.Controller;
            ContextualStringBuilder csb = new ContextualStringBuilder(sender.Thing, this.parent);
            csb.Append(@"$ActiveThing.Name drops $Thing.Name.", ContextualStringUsage.WhenNotBeingPassedToOriginator);
            csb.Append(@"You drop $Thing.Name.", ContextualStringUsage.OnlyWhenBeingPassedToOriginator);
            SensoryMessage message = new SensoryMessage(SensoryType.Sight, 100, csb);
            var changeOwnerEvent = new ChangeOwnerEvent(sender.Thing, message, sender.Thing, this.parent, this.thing);

            // Broadcast as a request and see if anything wants to prevent the event.
            this.parent.Eventing.OnMovementRequest(changeOwnerEvent, EventScope.ParentsDown);
            if (!changeOwnerEvent.IsCancelled)
            {
                // Always have to remove an item before adding it because of the event observer system.
                // @@@ TODO: Test, this may be broken now...
                this.thing.Parent.Remove(this.thing);
                this.parent.Add(this.thing);

                //// @@@ BUG: Saving currently throws a NotImplementedException. Disabled for now...
                this.thing.Save();
                this.parent.Save();

                // Broadcast the event.
                this.parent.Eventing.OnMovementEvent(changeOwnerEvent, EventScope.ParentsDown);
            }
        }
Ejemplo n.º 2
0
 /// <summary>Initializes a new instance of the SensoryMessage class.</summary>
 /// <param name="targetedSense">The sense this message is for.</param>
 /// <param name="messageStrength">The strength of the message.</param>
 /// <param name="message">The message contents.</param>
 /// <param name="context">The context for the view processor to use to render the message.</param>
 public SensoryMessage(SensoryType targetedSense, int messageStrength, ContextualStringBuilder message, Hashtable context)
 {
     TargetedSense   = targetedSense;
     MessageStrength = messageStrength;
     Message         = message;
     Context         = context;
 }
Ejemplo n.º 3
0
 /// <summary>
 /// Initializes a new instance of the SensoryMessage class.
 /// </summary>
 /// <param name="targetedSense">The sense this message is for.</param>
 /// <param name="messageStrength">The strength of the message.</param>
 /// <param name="message">The message contents.</param>
 /// <param name="context">The context for the view processor to use to render the message.</param>
 public SensoryMessage(SensoryType targetedSense, int messageStrength, ContextualStringBuilder message, Hashtable context)
 {
     this.TargetedSense = targetedSense;
     this.MessageStrength = messageStrength;
     this.Message = message;
     this.Context = context;
 }
Ejemplo n.º 4
0
        /// <summary>Try to log this player into the game.</summary>
        /// <param name="session">The session.</param>
        /// <returns>True if the player successfully logged in.</returns>
        public bool LogIn(Session session)
        {
            var player = Parent;

            // If the player isn't located anywhere yet, try to drop them in the default room.
            // (Expect that even new characters may gain a starting position via custom character generation
            // flows which let the user to select a starting spawn area.)
            var targetPlayerStartingPosition = player.Parent != null ? player.Parent : FindDefaultRoom();

            if (targetPlayerStartingPosition == null)
            {
                session.WriteLine("Could not place character in the game world. Please contact an administrator.");
                return(false);
            }

            // Prepare a login request and event.
            var csb = new ContextualStringBuilder(player, targetPlayerStartingPosition);

            csb.Append($"{session.Thing.Name} enters the world.", ContextualStringUsage.WhenNotBeingPassedToOriginator);
            csb.Append($"You enter the world.", ContextualStringUsage.OnlyWhenBeingPassedToOriginator);
            var message = new SensoryMessage(SensoryType.Sight, 100, csb);
            var e       = new PlayerLogInEvent(player, message);

            // Broadcast the login request to the player's current location (IE their parent room), if applicable.
            player.Eventing.OnMiscellaneousRequest(e, EventScope.ParentsDown);

            // Also broadcast the request to any registered global listeners.
            PlayerManager.Instance.OnPlayerLogInRequest(player, e);

            // If nothing canceled this event request, carry on with the login.
            if (!e.IsCancelled)
            {
                targetPlayerStartingPosition.Add(player);

                DateTime universalTime = DateTime.Now.ToUniversalTime();
                PlayerData.LastLogin     = universalTime.ToString("s", DateTimeFormatInfo.InvariantInfo) + "Z";
                PlayerData.LastIPAddress = session.Connection.CurrentIPAddress.ToString();

                session.Thing = player;
                session.User.LastLogInTime = DateTime.Now; // Should this occur when user was authenticated instead?

                // Broadcast that the player successfully logged in, to their login location.
                player.Eventing.OnMiscellaneousEvent(e, EventScope.ParentsDown);

                // TODO: Fix: Sending this before the player has registered as being in the PlayingState causes some problems,
                //       including the last character creation or password prompt from printing again as the user's prompt.
                //       Need to figure out if this can be straightened out in a clean way.
                //       See: https://github.com/DavidRieman/WheelMUD/issues/86#issuecomment-787057858
                PlayerManager.Instance.OnPlayerLogIn(player, e);

                return(true);
            }

            return(false);
        }
Ejemplo n.º 5
0
        /// <summary>Try to log this player into the game.</summary>
        /// <param name="session">The session.</param>
        /// <returns>True if the player successfully logged in.</returns>
        public bool LogIn(Session session)
        {
            var player = this.Parent;

            // If the player isn't located anywhere yet, try to drop them in the default room.
            // (Expect that even new characters may gain a starting position via custom character generation
            // flows which let the user to select a starting spawn area.)
            var targetPlayerStartingPosition = player.Parent != null ? player.Parent : FindDefaultRoom();

            if (targetPlayerStartingPosition == null)
            {
                session.Write("Could not place character in the game world. Please contact an administrator.");
                return(false);
            }

            // Prepare a login request and event.
            var csb = new ContextualStringBuilder(player, targetPlayerStartingPosition);

            csb.Append(@"$ActiveThing.Name enters the world.", ContextualStringUsage.WhenNotBeingPassedToOriginator);
            csb.Append(@"You enter the world.", ContextualStringUsage.OnlyWhenBeingPassedToOriginator);
            var message = new SensoryMessage(SensoryType.Sight, 100, csb);
            var e       = new PlayerLogInEvent(player, message);

            // Broadcast the login request to the player's current location (IE their parent room), if applicable.
            player.Eventing.OnMiscellaneousRequest(e, EventScope.ParentsDown);

            // Also broadcast the request to any registered global listeners.
            PlayerManager.OnPlayerLogInRequest(player, e);

            // If nothing canceled this event request, carry on with the login.
            if (!e.IsCancelled)
            {
                player.Parent = targetPlayerStartingPosition;

                DateTime universalTime = DateTime.Now.ToUniversalTime();
                this.PlayerData.LastLogin     = universalTime.ToString("s", DateTimeFormatInfo.InvariantInfo) + "Z";
                this.PlayerData.LastIPAddress = session.Connection.CurrentIPAddress.ToString();

                session.Thing = player;
                session.User.LastLogInTime = DateTime.Now; // Should this occur when user was authenticated instead?

                // Broadcast that the player successfully logged in, to their login location.
                player.Eventing.OnMiscellaneousEvent(e, EventScope.ParentsDown);

                PlayerManager.OnPlayerLogIn(player, e);

                return(true);
            }

            return(false);
        }
Ejemplo n.º 6
0
        /// <summary>Sets the value of the stat.</summary>
        /// <param name="value">The new value.</param>
        /// <param name="sender">The sender of the stat change.</param>
        /// <param name="message">The contextual message to broadcast with the change.</param>
        public virtual void SetValue(int value, Thing sender, ContextualStringBuilder message)
        {
            lock (lockObject)
            {
                int oldValue = currentValue;

                if (Host != null)
                {
                    // Check if the player is in the character creation state.
                    Thing hostThing = Host.Thing;
                    if (hostThing != null)
                    {
                        var e = new StatChangeEvent(
                            hostThing,
                            new SensoryMessage(SensoryType.Sight, 100, message),
                            this,
                            value - oldValue,
                            oldValue);

                        hostThing.Eventing.OnCombatRequest(e, EventScope.ParentsDown);

                        if (!e.IsCancelled)
                        {
                            if (value >= maxValue)
                            {
                                currentValue = maxValue;
                            }
                            else if (value <= minValue)
                            {
                                currentValue = minValue;
                            }
                            else
                            {
                                currentValue = value;
                            }

                            hostThing.Eventing.OnCombatEvent(e, EventScope.ParentsDown);
                        }
                    }
                    else
                    {
                        currentValue = value;
                    }
                }
                else
                {
                    currentValue = value;
                }
            }
        }
Ejemplo n.º 7
0
        /// <summary>Try to log this player out of the game.</summary>
        /// <returns>Indicates whether the logout was successful or not.</returns>
        public bool LogOut()
        {
            var player = this.Parent;

            // Prepare a logout request and event.
            var csb = new ContextualStringBuilder(player, player.Parent);

            csb.Append(@"$ActiveThing.Name exits the world.", ContextualStringUsage.WhenNotBeingPassedToOriginator);
            csb.Append(@"You exit the world.", ContextualStringUsage.OnlyWhenBeingPassedToOriginator);
            var message = new SensoryMessage(SensoryType.Sight, 100, csb);
            var e       = new PlayerLogOutEvent(player, message);

            // Broadcast the logout request to the player's current location (if applicable).
            player.Eventing.OnMiscellaneousRequest(e, EventScope.ParentsDown);

            // Also broadcast the request to any registered global listeners.
            PlayerManager.OnPlayerLogOutRequest(player, e);

            // If nothing canceled this event request, carry on with the logout.
            if (!e.IsCancelled)
            {
                DateTime universalTime = DateTime.Now.ToUniversalTime();
                this.PlayerData.LastLogout = universalTime.ToString("s", DateTimeFormatInfo.InvariantInfo) + "Z";

                player.Save();
                this.Dispose();
                player.Dispose();

                // Broadcast that the player successfully logged out, to their parent (IE room).
                player.Eventing.OnMiscellaneousEvent(e, EventScope.ParentsDown);
                PlayerManager.OnPlayerLogOut(player, e);

                return(true);
            }

            return(false);
        }
Ejemplo n.º 8
0
        /// <summary>Open or close this behavior's parent, via the specified actor.</summary>
        /// <param name="actor">The actor doing the opening or closing.</param>
        /// <param name="verb">Whether this is an "open" or "close" action.</param>
        /// <param name="newOpenedState">The new IsOpen state to be set, if the request is not cancelled.</param>
        private void OpenOrClose(Thing actor, string verb, bool newOpenedState)
        {
            // If we're already in the desired opened/closed state, we're already done with state changes.
            if (newOpenedState == this.IsOpen)
            {
                // @@@ TODO: Message to the actor that it is already open/closed.
                return;
            }

            // Prepare the Close/Open game event for sending as a request, and if not cancelled, again as an event.
            var csb = new ContextualStringBuilder(actor, this.Parent);

            csb.Append(@"You " + verb + " $TargetThing.Name.", ContextualStringUsage.OnlyWhenBeingPassedToOriginator);
            csb.Append(@"$ActiveThing.Name " + verb + "s you.", ContextualStringUsage.OnlyWhenBeingPassedToReceiver);
            csb.Append(@"$ActiveThing.Name " + verb + "s $TargetThing.Name.", ContextualStringUsage.WhenNotBeingPassedToReceiverOrOriginator);
            var message = new SensoryMessage(SensoryType.Sight, 100, csb);
            var e       = new OpenCloseEvent(this.Parent, newOpenedState, actor, message);

            // Broadcast the Open or Close Request and carry on if nothing cancelled it.
            // Use a temporary ref to our own parent to avoid race conditions like sudden parent removal.
            var thisThing = this.Parent;

            if (thisThing != null)
            {
                // Broadcast from the parents of the openable/closable thing (IE the rooms an openable exit is attached to).
                thisThing.Eventing.OnMiscellaneousRequest(e, EventScope.ParentsDown);
                if (!e.IsCancelled)
                {
                    // Open or Close the thing.
                    this.IsOpen = newOpenedState;

                    // Broadcast the Open or Close event.
                    thisThing.Eventing.OnMiscellaneousEvent(e, EventScope.ParentsDown);
                }
            }
        }
Ejemplo n.º 9
0
 /// <summary>Decreases the value of the stat.</summary>
 /// <param name="value">The amount to increase.</param>
 /// <param name="sender">The sender of the stat change.</param>
 /// <param name="message">The contextual message to broadcast with the change.</param>
 public void Decrease(int value, Thing sender, ContextualStringBuilder message)
 {
     SetValue(Value - value, sender, message);
 }
Ejemplo n.º 10
0
        /// <summary>Lock or unlock this behavior's parent, via the specified actor.</summary>
        /// <param name="actor">The actor doing the locking or unlocking.</param>
        /// <param name="verb">Whether this is an "lock" or "unlock" action.</param>
        /// <param name="newLockedState">The new IsLocked state to be set, if the request is not cancelled.</param>
        private void LockOrUnlock(Thing actor, string verb, bool newLockedState)
        {
            // If we're already in the desired locked/unlocked state, we're already done with state changes.
            if (newLockedState == this.IsLocked)
            {
                // @@@ TODO: Message to the actor that it is already locked/unlocked.
                return;
            }

            // Use a temporary ref to our own parent to avoid race conditions like sudden parent removal.
            var thisThing = this.Parent;

            if (newLockedState && thisThing != null)
            {
                // If we are attempting to lock an opened thing, cancel the lock attempt.
                var opensClosesBehavior = thisThing.Behaviors.FindFirst<OpensClosesBehavior>();
                if (opensClosesBehavior != null && opensClosesBehavior.IsOpen)
                {
                    // @@@ TODO: Message to the actor that they can't lock an open thing.
                    return;
                }
            }

            // Prepare the Lock/Unlock game event for sending as a request, and if not cancelled, again as an event.
            var csb = new ContextualStringBuilder(actor, this.Parent);
            csb.Append(@"You " + verb + " $TargetThing.Name.", ContextualStringUsage.OnlyWhenBeingPassedToOriginator);
            csb.Append(@"$ActiveThing.Name " + verb + "s you.", ContextualStringUsage.OnlyWhenBeingPassedToReceiver);
            csb.Append(@"$ActiveThing.Name " + verb + "s $TargetThing.Name.", ContextualStringUsage.WhenNotBeingPassedToReceiverOrOriginator);
            var message = new SensoryMessage(SensoryType.Sight, 100, csb);
            var e = new LockUnlockEvent(this.Parent, false, actor, message);

            // Broadcast the Lock or Unlock Request and carry on if nothing cancelled it.
            if (thisThing != null)
            {
                // Broadcast from the parents of the lockable/unlockable thing (IE a room or inventory where the lockable resides).
                thisThing.Eventing.OnMiscellaneousRequest(e, EventScope.ParentsDown);
                if (!e.IsCancelled)
                {
                    // Lock or Unlock the thing.
                    this.IsLocked = newLockedState;

                    // Broadcast the Lock or Unlock event.
                    thisThing.Eventing.OnMiscellaneousEvent(e, EventScope.ParentsDown);
                }
            }
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Open or close this behavior's parent, via the specified actor.
        /// </summary>
        /// <param name="actor">The actor doing the opening or closing.</param>
        /// <param name="verb">Whether this is an "open" or "close" action.</param>
        /// <param name="newOpenedState">The new IsOpen state to be set, if the request is not cancelled.</param>
        private void OpenOrClose(Thing actor, string verb, bool newOpenedState)
        {
            // If we're already in the desired opened/closed state, we're already done with state changes.
            if (newOpenedState == this.IsOpen)
            {
                // @@@ TODO: Message to the actor that it is already open/closed.
                return;
            }

            // Prepare the Close/Open game event for sending as a request, and if not cancelled, again as an event.
            var csb = new ContextualStringBuilder(actor, this.Parent);
            csb.Append(@"You " + verb + " $TargetThing.Name.", ContextualStringUsage.OnlyWhenBeingPassedToOriginator);
            csb.Append(@"$ActiveThing.Name " + verb + "s you.", ContextualStringUsage.OnlyWhenBeingPassedToReceiver);
            csb.Append(@"$ActiveThing.Name " + verb + "s $TargetThing.Name.", ContextualStringUsage.WhenNotBeingPassedToReceiverOrOriginator);
            var message = new SensoryMessage(SensoryType.Sight, 100, csb);
            var e = new OpenCloseEvent(this.Parent, newOpenedState, actor, message);

            // Broadcast the Open or Close Request and carry on if nothing cancelled it.
            // Use a temporary ref to our own parent to avoid race conditions like sudden parent removal.
            var thisThing = this.Parent;
            if (thisThing != null)
            {
                // Broadcast from the parents of the openable/closable thing (IE the rooms an openable exit is attached to).
                thisThing.Eventing.OnMiscellaneousRequest(e, EventScope.ParentsDown);
                if (!e.IsCancelled)
                {
                    // Open or Close the thing.
                    this.IsOpen = newOpenedState;

                    // Broadcast the Open or Close event.
                    thisThing.Eventing.OnMiscellaneousEvent(e, EventScope.ParentsDown);
                }
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Sets the value of the stat.
        /// </summary>
        /// <param name="value">The new value.</param>
        /// <param name="sender">The sender of the stat change.</param>
        /// <param name="message">The contextual message to broadcast with the change.</param>
        public virtual void SetValue(int value, Thing sender, ContextualStringBuilder message)
        {
            lock (this.lockObject)
            {
                int oldValue = this.currentValue;

                if (this.Host != null)
                {
                    // Check if the player is in the character creation state.
                    Thing hostThing = this.Host.Thing;
                    if (hostThing != null)
                    {
                        var e = new StatChangeEvent(
                            hostThing,
                            new SensoryMessage(SensoryType.Sight, 100, message),
                            this,
                            value - oldValue,
                            oldValue);

                        hostThing.Eventing.OnCombatRequest(e, EventScope.ParentsDown);

                        if (!e.IsCancelled)
                        {
                            if (value >= this.maxValue)
                            {
                                this.currentValue = this.maxValue;
                            }
                            else if (value <= this.minValue)
                            {
                                this.currentValue = this.minValue;
                            }
                            else
                            {
                                this.currentValue = value;
                            }

                            hostThing.Eventing.OnCombatEvent(e, EventScope.ParentsDown);
                        }
                    }
                    else
                    {
                        this.currentValue = value;
                    }
                }
                else
                {
                    this.currentValue = value;
                }
            }
        }
Ejemplo n.º 13
0
 /// <summary>
 /// Increases the value of the stat.
 /// </summary>
 /// <param name="value">The amount to increase.</param>
 /// <param name="sender">The sender of the stat change.</param>
 /// <param name="message">The contextual message to broadcast with the change.</param>
 public void Increase(int value, Thing sender, ContextualStringBuilder message)
 {
     this.SetValue(this.Value + value, sender, message);
 }
Ejemplo n.º 14
0
 /// <summary>
 /// Initializes a new instance of the SensoryMessage class.
 /// </summary>
 /// <param name="targetedSense">The sense this message is for.</param>
 /// <param name="messageStrength">The strength of the message.</param>
 /// <param name="message">The message contents.</param>
 public SensoryMessage(SensoryType targetedSense, int messageStrength, ContextualStringBuilder message)
     : this(targetedSense, messageStrength, message, new Hashtable())
 {
 }
Ejemplo n.º 15
0
 /// <summary>Initializes a new instance of the SensoryMessage class.</summary>
 /// <param name="targetedSense">The sense this message is for.</param>
 /// <param name="messageStrength">The strength of the message.</param>
 /// <param name="message">The message contents.</param>
 public SensoryMessage(SensoryType targetedSense, int messageStrength, ContextualStringBuilder message)
     : this(targetedSense, messageStrength, message, new Hashtable())
 {
 }
Ejemplo n.º 16
0
 /// <summary>Increases the value of the stat.</summary>
 /// <param name="value">The amount to increase.</param>
 /// <param name="sender">The sender of the stat change.</param>
 /// <param name="message">The contextual message to broadcast with the change.</param>
 public void Increase(int value, Thing sender, ContextualStringBuilder message)
 {
     this.SetValue(this.Value + value, sender, message);
 }
Ejemplo n.º 17
0
        /// <summary>
        /// Try to log this player out of the game.
        /// </summary>
        /// <returns>Indicates whether the logout was successful or not.</returns>
        public bool LogOut()
        {
            var player = this.Parent;

            // Prepare a logout request and event.
            var csb = new ContextualStringBuilder(player, player.Parent);
            csb.Append(@"$ActiveThing.Name exits the world.", ContextualStringUsage.WhenNotBeingPassedToOriginator);
            csb.Append(@"You exit the world.", ContextualStringUsage.OnlyWhenBeingPassedToOriginator);
            var message = new SensoryMessage(SensoryType.Sight, 100, csb);
            var e = new PlayerLogOutEvent(player, message);

            // Broadcast the logout request to the player's current location (if applicable).
            player.Eventing.OnMiscellaneousRequest(e, EventScope.ParentsDown);

            // Also broadcast the request to any registered global listeners.
            PlayerManager.OnPlayerLogOutRequest(player, e);

            // If nothing canceled this event request, carry on with the logout.
            if (!e.IsCancelled)
            {
                DateTime universalTime = DateTime.Now.ToUniversalTime();
                this.PlayerData.LastLogout = universalTime.ToString("s", DateTimeFormatInfo.InvariantInfo) + "Z";

                player.Save();
                this.Dispose();
                player.Dispose();

                // Broadcast that the player successfully logged out, to their parent (IE room).
                player.Eventing.OnMiscellaneousEvent(e, EventScope.ParentsDown);
                PlayerManager.OnPlayerLogOut(player, e);

                return true;
            }

            return false;
        }