001package net.minecraft.entity.ai;
002
003import java.util.ArrayList;
004import java.util.Iterator;
005import java.util.List;
006import net.minecraft.profiler.Profiler;
007
008public class EntityAITasks
009{
010    /** A list of EntityAITaskEntrys in EntityAITasks. */
011    public List taskEntries = new ArrayList();
012
013    /** A list of EntityAITaskEntrys that are currently being executed. */
014    private List executingTaskEntries = new ArrayList();
015
016    /** Instance of Profiler. */
017    private final Profiler theProfiler;
018    private int field_75778_d = 0;
019    private int field_75779_e = 3;
020
021    public EntityAITasks(Profiler par1Profiler)
022    {
023        this.theProfiler = par1Profiler;
024    }
025
026    public void addTask(int par1, EntityAIBase par2EntityAIBase)
027    {
028        this.taskEntries.add(new EntityAITaskEntry(this, par1, par2EntityAIBase));
029    }
030
031    /**
032     * removes the indicated task from the entity's AI tasks.
033     */
034    public void removeTask(EntityAIBase par1EntityAIBase)
035    {
036        Iterator iterator = this.taskEntries.iterator();
037
038        while (iterator.hasNext())
039        {
040            EntityAITaskEntry entityaitaskentry = (EntityAITaskEntry)iterator.next();
041            EntityAIBase entityaibase1 = entityaitaskentry.action;
042
043            if (entityaibase1 == par1EntityAIBase)
044            {
045                if (this.executingTaskEntries.contains(entityaitaskentry))
046                {
047                    entityaibase1.resetTask();
048                    this.executingTaskEntries.remove(entityaitaskentry);
049                }
050
051                iterator.remove();
052            }
053        }
054    }
055
056    public void onUpdateTasks()
057    {
058        ArrayList arraylist = new ArrayList();
059        Iterator iterator;
060        EntityAITaskEntry entityaitaskentry;
061
062        if (this.field_75778_d++ % this.field_75779_e == 0)
063        {
064            iterator = this.taskEntries.iterator();
065
066            while (iterator.hasNext())
067            {
068                entityaitaskentry = (EntityAITaskEntry)iterator.next();
069                boolean flag = this.executingTaskEntries.contains(entityaitaskentry);
070
071                if (flag)
072                {
073                    if (this.canUse(entityaitaskentry) && this.canContinue(entityaitaskentry))
074                    {
075                        continue;
076                    }
077
078                    entityaitaskentry.action.resetTask();
079                    this.executingTaskEntries.remove(entityaitaskentry);
080                }
081
082                if (this.canUse(entityaitaskentry) && entityaitaskentry.action.shouldExecute())
083                {
084                    arraylist.add(entityaitaskentry);
085                    this.executingTaskEntries.add(entityaitaskentry);
086                }
087            }
088        }
089        else
090        {
091            iterator = this.executingTaskEntries.iterator();
092
093            while (iterator.hasNext())
094            {
095                entityaitaskentry = (EntityAITaskEntry)iterator.next();
096
097                if (!entityaitaskentry.action.continueExecuting())
098                {
099                    entityaitaskentry.action.resetTask();
100                    iterator.remove();
101                }
102            }
103        }
104
105        this.theProfiler.startSection("goalStart");
106        iterator = arraylist.iterator();
107
108        while (iterator.hasNext())
109        {
110            entityaitaskentry = (EntityAITaskEntry)iterator.next();
111            this.theProfiler.startSection(entityaitaskentry.action.getClass().getSimpleName());
112            entityaitaskentry.action.startExecuting();
113            this.theProfiler.endSection();
114        }
115
116        this.theProfiler.endSection();
117        this.theProfiler.startSection("goalTick");
118        iterator = this.executingTaskEntries.iterator();
119
120        while (iterator.hasNext())
121        {
122            entityaitaskentry = (EntityAITaskEntry)iterator.next();
123            entityaitaskentry.action.updateTask();
124        }
125
126        this.theProfiler.endSection();
127    }
128
129    /**
130     * Determine if a specific AI Task should continue being executed.
131     */
132    private boolean canContinue(EntityAITaskEntry par1EntityAITaskEntry)
133    {
134        this.theProfiler.startSection("canContinue");
135        boolean flag = par1EntityAITaskEntry.action.continueExecuting();
136        this.theProfiler.endSection();
137        return flag;
138    }
139
140    /**
141     * Determine if a specific AI Task can be executed, which means that all running higher (= lower int value) priority
142     * tasks are compatible with it or all lower priority tasks can be interrupted.
143     */
144    private boolean canUse(EntityAITaskEntry par1EntityAITaskEntry)
145    {
146        this.theProfiler.startSection("canUse");
147        Iterator iterator = this.taskEntries.iterator();
148
149        while (iterator.hasNext())
150        {
151            EntityAITaskEntry entityaitaskentry1 = (EntityAITaskEntry)iterator.next();
152
153            if (entityaitaskentry1 != par1EntityAITaskEntry)
154            {
155                if (par1EntityAITaskEntry.priority >= entityaitaskentry1.priority)
156                {
157                    if (this.executingTaskEntries.contains(entityaitaskentry1) && !this.areTasksCompatible(par1EntityAITaskEntry, entityaitaskentry1))
158                    {
159                        this.theProfiler.endSection();
160                        return false;
161                    }
162                }
163                else if (this.executingTaskEntries.contains(entityaitaskentry1) && !entityaitaskentry1.action.isInterruptible())
164                {
165                    this.theProfiler.endSection();
166                    return false;
167                }
168            }
169        }
170
171        this.theProfiler.endSection();
172        return true;
173    }
174
175    /**
176     * Returns whether two EntityAITaskEntries can be executed concurrently
177     */
178    private boolean areTasksCompatible(EntityAITaskEntry par1EntityAITaskEntry, EntityAITaskEntry par2EntityAITaskEntry)
179    {
180        return (par1EntityAITaskEntry.action.getMutexBits() & par2EntityAITaskEntry.action.getMutexBits()) == 0;
181    }
182}