private void _decalEventsProxy_ChatBoxMessage(object sender, Decal.Adapter.ChatTextInterceptEventArgs e)
        {
            if (this._giveItemPending.WaitOne(0))
            {
                // Ex: You give Kreap Invitation Ithaenc Cathedral.
                // Ex: You give Kreap Velvet Baggy Pants.
                //         WorldObject Name will = Baggy Pants
                // Ex: You give Vassari 4 Quills of Infliction
                // Ex: You give Rockdown Guy 50 Silver Peas.
                if (e.IsYouGive())
                {
                    var worldObj = this._pendingGiveItemCapturedWorldObject;

                    var textMinusPrefix = e.Text.Substring(9);

                    var itemNameStartIndex = textMinusPrefix.IndexOf(worldObj.Name);

                    var targetName = textMinusPrefix.Substring(0, itemNameStartIndex).Trim();

                    // If the item we are giving has a material, it's going to be in the text and we need to trim it out
                    var materialValue = worldObj.Values(LongValueKey.Material);
                    if (materialValue > 0)
                    {
                        string materialName;
                        if(Mag.Shared.Constants.Dictionaries.MaterialInfo.TryGetValue(materialValue, out materialName))
                        {
                            targetName = targetName.Substring(0, targetName.Length - (materialName.Length + 1));
                        }
                    }

                    var stackCount = worldObj.Values(LongValueKey.StackCount);
                    if (stackCount > 1)
                    {
                        // When stack count > 0, what we will be looking at is :
                        //      targetName = Rockdown Guy 50 S
                        // The single character is left over from the item name being plural in the give message
                        var endingCharsToIgnore = 2 + (stackCount.ToString()).Length;
                        targetName = targetName.Substring(0, targetName.Length - endingCharsToIgnore).Trim();
                    }

                    var eventArgs = new EndGiveItemEventArgs(worldObj, targetName, GiveItemOutcome.Successful);
                    REPlugin.Instance.Debug.WriteObject(eventArgs);

                    if (this.EndGiveItem != null)
                    {
                        this.EndGiveItem(sender, eventArgs);
                    }

                    this._giveItemPending.Reset();
                    this._pendingGiveItemCapturedWorldObject = null;
                }
            }
        }
        private void FireEndNonZeroBusyState(object sender, EndNonZeroBusyStateEventArgs eventArgs)
        {
            try
            {
                this._nonZeroActionStatePending.Reset();

                REPlugin.Instance.Debug.WriteObject(eventArgs);

                // Check for busy states that we fire events for.
                switch (this._pendingBusyState)
                {
                    case BusyStateConstants.GivingItem:  // Give Object
                        // If the pending give event is still set at this point, that means we were not able to
                        // verify a successful (or failed) give.  Every Begin event needs a correspond End event,
                        // so since no one else took care of it, we should fire a failed End now
                        if (this._giveItemPending.WaitOne(0))
                        {
                            var tmpEventArgs = new EndGiveItemEventArgs(null, string.Empty, GiveItemOutcome.FailedUnknown);
                            REPlugin.Instance.Debug.WriteObject(eventArgs);
                            if (this.EndGiveItem != null)
                            {
                                this.EndGiveItem(sender, tmpEventArgs);
                            }

                            this._giveItemPending.Reset();
                        }

                        break;

                    case BusyStateConstants.EquipingItem:
                        // TODO : Investigate how to detect failed equips.  Once found, introduce a manual reset event
                        if (this.EndEquipItem != null)
                        {
                            this.EndEquipItem(sender, new ObjectIdEventArgs(this._pendingBusyStateId));
                        }
                        break;

                    case BusyStateConstants.UnequipingItem:
                        // TODO : Investigate how to detect failed equips.  Once found, introduce a manual reset event
                        if (this.EndUnequipItem != null)
                        {
                            this.EndUnequipItem(sender, new ObjectIdEventArgs(this._pendingBusyStateId));
                        }
                        break;
                }

                if (this.EndNonZeroBusyState != null)
                {
                    this.EndNonZeroBusyState(sender, eventArgs);
                }
            }
            finally
            {
                this._pendingBusyState = int.MaxValue;
                this._pendingBusyStateId = int.MaxValue;
            }
        }
        private void DecalEventsProxy_StatusTextIntercept(object sender, Data.Events.StatusTextInterceptEventArgs e)
        {
            // We can provide support for a couple of additional events based on this one.

            string objectName = string.Empty;

            // Using Object Text Example(s) :
            //  Hooks_StatusTextIntercept : Text = Using the Portal to Town Network
            //  Hooks_StatusTextIntercept : Text = Using the Ong-Hau Village Portal
            //  Hooks_StatusTextIntercept : Text = Using the Corpse of <Blah...blah>

            if (e.IsUsingObject(out objectName))
            {
                // Note (3/5/2015) : So far this seems reliable.  When this message comes in, you pretty much have to have
                // the item selected.  So grab the id from the current selection.
                var currentSelectionId = REPlugin.Instance.PluginHost.Actions.CurrentSelection;

                var eventArgs = new UsingObjectEventArgs(objectName, currentSelectionId);

                REPlugin.Instance.Debug.WriteObject(eventArgs);

                if (this.UsingObject != null)
                {
                    this.UsingObject(sender, eventArgs);
                }

                // Once we fire the generic event, check and see if there is a more specific event we can fire
                this.CheckForAndFireMoreSpecificUsingEvents(sender, objectName, currentSelectionId);

                return;
            }

            // Object Test Example(s) :
            //  Hooks_StatusTextIntercept : Text = Approaching Small Creepy Statue
            //  Hooks_StatusTextIntercept : Text = Approaching Hisham al-Evv
            //  Hooks_StatusTextIntercept : Text = Approaching Umbral Guard
            if (e.IsApproachingObject(out objectName))
            {
                // Note (3/5/2015) : So far this seems reliable.  When this message comes in, you pretty much have to have
                // the item selected.  So grab the id from the current selection.
                var currentSelectionId = REPlugin.Instance.PluginHost.Actions.CurrentSelection;

                var eventArgs = new ApproachingObjectEventArgs(objectName, currentSelectionId);

                REPlugin.Instance.Debug.WriteObject(eventArgs);
                if (this.ApproachingObject != null)
                {
                    this.ApproachingObject(sender, eventArgs);
                }

                return;
            }

            // Too Busy Example :
            //  Text = You're too busy!
            if (e.IsYoureTooBusy())
            {
                var eventArgs = new YourTooBusyEventArgs();

                REPlugin.Instance.Debug.WriteObject(eventArgs);

                if (this.YourTooBusy != null)
                {
                    this.YourTooBusy(sender, eventArgs);
                }
            }

            if (this._giveItemPending.WaitOne(0) && e.IsCantBeGiven())
            {
                if (string.IsNullOrEmpty(this._pendingGiveItemTargetName))
                {
                    throw new InvalidOperationException("Expected to have a target name at this point, but we do not.");
                }

                if (this._pendingGiveItemOutcome == GiveItemOutcome.Undefined)
                {
                    throw new InvalidOperationException("Expected to know the outcome of the give at this point");
                }

                var eventArgs = new EndGiveItemEventArgs(this._pendingBusyStateId.ToWorldObject().Capture(), this._pendingGiveItemTargetName, this._pendingGiveItemOutcome);

                REPlugin.Instance.Debug.WriteObject(eventArgs);

                if (this.EndGiveItem != null)
                {
                    this.EndGiveItem(sender, eventArgs);
                }

                this._giveItemPending.Reset();
                this._pendingGiveItemOutcome = GiveItemOutcome.Undefined;
            }
        }
        internal void WriteObject(EndGiveItemEventArgs obj)
        {
            if (ActiveSettings.Instance.DebugLevel == DebugLevel.None)
                return;

            lock (this._writeLock)
            {
                using (StreamWriter stream = new StreamWriter(this._currentPath, true))
                {
                    this.LogRawMessage(this.FormatWithPrefix("EndGiveItemEventArgs"), stream);
                    this.LogRawMessage(string.Format("  ItemGiven = {0}", obj.ItemGiven.ToShortSummary()), stream);
                    this.LogRawMessage(string.Format("  TargetName = {0}", obj.TargetName), stream);
                    this.LogRawMessage(string.Format("  Outcome = {0}", obj.Outcome), stream);

                    //this.WriteCurrentStateStuff(stream, false);

                    this.LogRawMessage("", stream);
                }
            }
        }