Ejemplo n.º 1
0
        /// <summary>Perform removal of the specified thing from our Children.</summary>
        /// <param name="thingToRemove">The thing to remove from our Children.</param>
        /// <param name="removalEvent">The removal event to work with; must have previously been sent as the request.</param>
        /// <param name="multipleParentsBehavior">The multipleParentsBehavior, if applicable.</param>
        /// <returns>True if the thing has been successfully removed, else false.</returns>
        private bool PerformRemoval(Thing thingToRemove, RemoveChildEvent removalEvent, MultipleParentsBehavior multipleParentsBehavior)
        {
            if (removalEvent.IsCancelled)
            {
                return(false);
            }

            // Send the removal event.
            this.Eventing.OnMovementEvent(removalEvent, EventScope.SelfDown);

            // If the thing to remove was in our Children collection, remove it.
            if (this.Children.Contains(thingToRemove))
            {
                this.Children.Remove(thingToRemove);
            }

            // If we don't have a MultipleParentsBehavior, directly remove the one-allowed
            // parent ourselves, else use the behavior's logic for adjusting the parents.
            if (multipleParentsBehavior == null)
            {
                thingToRemove.Parent = null;
            }
            else
            {
                multipleParentsBehavior.RemoveParent(this);
            }

            return(true);
        }
Ejemplo n.º 2
0
        private RemoveChildEvent RequestRemoval(Thing thingToRemove)
        {
            // Create and raise a removal event request.
            var removeChildEvent = new RemoveChildEvent(thingToRemove);

            this.Eventing.OnMovementRequest(removeChildEvent, EventScope.SelfDown);
            return(removeChildEvent);
        }
Ejemplo n.º 3
0
        // TODO: All things (world, room, item, mob, etc), should all potentially have sub-things
        //       but it should be up to the code which moves things about to do so intelligently
        //       (IE should not allow adding an Area inside a Room, etc.)  These can be prevented
        //       either explicitly here, or preferably via event request cancellation.
        public bool Add(Thing thing)
        {
            // No two threads may add/remove any combination of the parent/sub-thing at the same time,
            // in order to prevent race conditions resulting in thing-disconnection/duplication/etc.
            // TODO: May need to pick a consistent order to apply the locks (like locking the lowest
            //       alphabetical thing ID's lock first) to prevent possible deadlocks.
            // TODO: The whole MultipleParentsBehavior may be too complicated for our actual use cases,
            //       and we should consider a lighter approach that doesn't track multiple parents, but
            //       simply lets the thing be a child of multiple locations.
            lock (lockObject)
            {
                lock (thing.lockObject)
                {
                    // If the thing already has a parent, ensure we have permission to continue.
                    // Presence of MultipleParentsBehavior means we can always add more parents, but
                    // if it's not present, we have to see if removal would be accepted first.
                    var multipleParentsBehavior     = thing.Behaviors.FindFirst <MultipleParentsBehavior>();
                    RemoveChildEvent removalRequest = null;

                    var oldParent = thing.Parent;
                    if (oldParent != null && multipleParentsBehavior == null)
                    {
                        removalRequest = oldParent.RequestRemoval(thing);
                        if (removalRequest.IsCancelled)
                        {
                            return(false);
                        }
                    }

                    var addRequest = RequestAdd(thing);
                    if (addRequest.IsCancelled)
                    {
                        return(false);
                    }

                    // If we got this far, both removal (if needed) and add requests were accepted, so
                    // perform both now and send the confirmation events for any listeners.  Removal is
                    // first, since we don't want to risk accidentally removing from the new parent, etc.
                    if (removalRequest != null)
                    {
                        oldParent.PerformRemoval(thing, removalRequest, multipleParentsBehavior);
                    }

                    PerformAdd(thing, addRequest, multipleParentsBehavior);
                }

                return(true);
            }
        }
Ejemplo n.º 4
0
        // @@@ All things (world, room, item, mob, etc), should all potentially have sub-things
        //     but it should be up to the code which moves things about to do so intelligently
        //     (IE should not allow adding an Area inside a Room, etc.)  These can be prevented
        //     either explicitly here, or preferably via event request cancellation.
        public bool Add(Thing thing)
        {
            // No two threads may add/remove any combination of the parent/sub-thing at the same time,
            // in order to prevent race conditions resulting in thing-disconnection/duplication/etc.
            lock (this.lockObject)
            {
                lock (thing.lockObject)
                {
                    // If the thing already has a parent, ensure we have permission to continue.
                    // Presence of MultipleParentsBehavior means we can always add more parents, but
                    // if it's not present, we have to see if removal would be accepted first.
                    var multipleParentsBehavior     = thing.Behaviors.FindFirst <MultipleParentsBehavior>();
                    RemoveChildEvent removalRequest = null;

                    var oldParent = thing.Parent;
                    if (oldParent != null && multipleParentsBehavior == null)
                    {
                        removalRequest = oldParent.RequestRemoval(thing);
                        if (removalRequest.IsCancelled)
                        {
                            return(false);
                        }
                    }

                    var addRequest = this.RequestAdd(thing);
                    if (addRequest.IsCancelled)
                    {
                        return(false);
                    }

                    // If we got this far, both removal (if needed) and add requests were accepted, so
                    // perform both now and send the confirmation events for any listeners.  Removal is
                    // first, since we don't want to risk accidentally removing from the new parent, etc.
                    if (removalRequest != null)
                    {
                        oldParent.PerformRemoval(thing, removalRequest, multipleParentsBehavior);
                    }

                    this.PerformAdd(thing, addRequest, multipleParentsBehavior);
                }

                return(true);
            }
        }