    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}