Пример #1
0
 private static bool CheckCondition(QueueItem item)
 {
     return(item.Condition != null && item.Condition.Invoke(item.Nodes));
 }
Пример #2
0
        /// <summary>
        /// Selects a composite to be run
        /// This is called every tick and returns a composite
        /// Which composite is returned changes based on the QueueItem currently being processed.
        /// </summary>
        private static Composite Next()
        {
            // 1. No active node
            if (_active == null)
            {
                // 1.1 Nothing in the Queue.
                if (!Q.Any())
                {
                    return(Continue);
                }

                // 1.2 Start the next QueueItem that has passed its condition
                var nextItem = Q.FirstOrDefault(n => n.ConditionPassed);
                if (nextItem != null)
                {
                    Logger.Verbose("Starting QueueItem");
                    if (Q.Remove(nextItem))
                    {
                        _active = nextItem;
                        if (_active.OnStart != null)
                        {
                            _active.OnStart.Invoke(_active);
                        }
                        return(Loop);
                    }
                    ;
                }

                // 1.3 Nothing has passed condition yet.
                return(Continue);
            }

            // 2. We're currently processing a QueueItem
            // But havent started processing its nodes.
            if (_active.ActiveNode == null)
            {
                // 2.1 Handle starting the first Node
                _active.ActiveNode = _active.Nodes.First();
                _active.ActiveNode.Run();
                if (_active.OnNodeStart != null)
                {
                    _active.OnNodeStart.Invoke(_active);
                }
                return(_active.ActiveNode.Behavior);
            }

            BotMain.StatusText = _active.ActiveNode.StatusText;

            // 3. We're currently processing a QueueItem
            // And the current node is Done
            if (_active.ActiveNode.IsDone)
            {
                // 3.1 Handle ActiveNode has finished
                _active.CompletedNodes++;
                _active.ActiveNode.OnDone();
                Logger.Verbose("[{0}] Complete {1}/{2} ({3})", _active.Name, _active.CompletedNodes, _active.Nodes.Count, _active.ActiveNode.GetType());
                if (_active.OnNodeDone != null)
                {
                    _active.OnNodeDone.Invoke(_active);
                }

                // 3.2 All nodes are finished, so the QueueItem is now Done.
                if (_active.IsComplete)
                {
                    // 3.2.1 Handle all nodes are finished
                    if (_active.OnDone != null)
                    {
                        _active.OnDone.Invoke(_active);
                    }
                    Logger.Verbose("[{1}] Completed {0}", _active.CompletedNodes, _active.Name);

                    // 3.2.2 Traverse Upwards
                    // If this QueueItem is a child, we need to continue with its parent
                    // Parent gets taken off the shelf (unpaused) and set as the new active Queueitem.
                    var parent = Shelf.FirstOrDefault(i => i.ParentOf == _active.Id);
                    Logger.Verbose("All Nodes Complete ParentId={0} ThisId={1}", parent != null ? parent.Id.ToString() : "Null", _active.Id);
                    if (parent != null)
                    {
                        _active = parent;
                        Shelf.Remove(parent);
                        Logger.Verbose("ShelfCount={0}", Shelf.Count);
                        return(Loop);
                    }

                    // 3.2.3 Shove it back at the bottom of the queue if it should be repeated
                    if (_active.Repeat)
                    {
                        var temp = _active;
                        _active.Reset();
                        _active = null;
                        Queue(temp);
                        return(Loop);
                    }

                    // 3.2.4 No parent, No Repeat, so just end the QueueItem
                    _active = null;
                    return(Loop);
                }

                // 3.3 Handle start of next node
                var currentPosition = _active.Nodes.IndexOf(_active.ActiveNode);
                _active.ActiveNode = _active.Nodes.ElementAt(currentPosition + 1);
                _active.ActiveNode.Run();
                if (_active.OnNodeStart != null)
                {
                    _active.OnNodeStart.Invoke(_active);
                }
                return(_active.ActiveNode.Behavior);
            }

            // 4.1 Traverse Downwards
            // We're currently processing a QueueItem
            // And the current node is NOT Done
            // And the current node has children
            Logger.Verbose("ShelfCount={0}", Shelf.Count);
            var children = _active.ActiveNode.GetChildren();

            if (children.Count > 0)
            {
                Logger.Log("Processing {0} Children of '{1}' ({2})", children.Count, _active.Name, _active.Id);

                // Copy QueueItem so we can resume it later.
                var queueItemToShelve = _active;

                // Wrap the children as a new QueueItem
                var childQueueItem = new QueueItem
                {
                    Name  = string.Format("Children of {0}", _active.Name),
                    Nodes = _active.ActiveNode.GetChildren()
                };

                // Store a references between parent and child
                queueItemToShelve.ParentOf = childQueueItem.Id;
                childQueueItem.ChildOf     = _active.Id;

                // Pause the active QueueItem by moving it to the shelf
                Shelf.Add(queueItemToShelve);

                // Start working on the children.
                _active = childQueueItem;
                return(Loop);
            }

            // Handle continuing an in-progress Node
            LogBehavior(_active);
            return(_active.ActiveNode.Behavior);
        }