    001package net.minecraft.entity;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import java.io.DataInputStream;
    006import java.io.DataOutputStream;
    007import java.io.IOException;
    008import java.util.ArrayList;
    009import java.util.HashMap;
    010import java.util.Iterator;
    011import java.util.List;
    012import java.util.Map;
    013import java.util.concurrent.locks.ReadWriteLock;
    014import java.util.concurrent.locks.ReentrantReadWriteLock;
    015import net.minecraft.crash.CrashReport;
    016import net.minecraft.crash.CrashReportCategory;
    017import net.minecraft.item.ItemStack;
    018import net.minecraft.network.packet.Packet;
    019import net.minecraft.util.ChunkCoordinates;
    020import net.minecraft.util.ReportedException;
    021
    022public class DataWatcher
    023{
    024    private boolean field_92086_a = true;
    025    private static final HashMap dataTypes = new HashMap();
    026    private final Map watchedObjects = new HashMap();
    027
    028    /** true if one or more object was changed */
    029    private boolean objectChanged;
    030    private ReadWriteLock lock = new ReentrantReadWriteLock();
    031
    032    /**
    033     * adds a new object to dataWatcher to watch, to update an already existing object see updateObject. Arguments: data
    034     * Value Id, Object to add
    035     */
    036    public void addObject(int par1, Object par2Obj)
    037    {
    038        Integer var3 = (Integer)dataTypes.get(par2Obj.getClass());
    039
    040        if (var3 == null)
    041        {
    042            throw new IllegalArgumentException("Unknown data type: " + par2Obj.getClass());
    043        }
    044        else if (par1 > 31)
    045        {
    046            throw new IllegalArgumentException("Data value id is too big with " + par1 + "! (Max is " + 31 + ")");
    047        }
    048        else if (this.watchedObjects.containsKey(Integer.valueOf(par1)))
    049        {
    050            throw new IllegalArgumentException("Duplicate id value for " + par1 + "!");
    051        }
    052        else
    053        {
    054            WatchableObject var4 = new WatchableObject(var3.intValue(), par1, par2Obj);
    055            this.lock.writeLock().lock();
    056            this.watchedObjects.put(Integer.valueOf(par1), var4);
    057            this.lock.writeLock().unlock();
    058            this.field_92086_a = false;
    059        }
    060    }
    061
    062    /**
    063     * Add a new object for the DataWatcher to watch, using the specified data type.
    064     */
    065    public void addObjectByDataType(int par1, int par2)
    066    {
    067        WatchableObject var3 = new WatchableObject(par2, par1, (Object)null);
    068        this.lock.writeLock().lock();
    069        this.watchedObjects.put(Integer.valueOf(par1), var3);
    070        this.lock.writeLock().unlock();
    071        this.field_92086_a = false;
    072    }
    073
    074    /**
    075     * gets the bytevalue of a watchable object
    076     */
    077    public byte getWatchableObjectByte(int par1)
    078    {
    079        return ((Byte)this.getWatchedObject(par1).getObject()).byteValue();
    080    }
    081
    082    public short getWatchableObjectShort(int par1)
    083    {
    084        return ((Short)this.getWatchedObject(par1).getObject()).shortValue();
    085    }
    086
    087    /**
    088     * gets a watchable object and returns it as a Integer
    089     */
    090    public int getWatchableObjectInt(int par1)
    091    {
    092        return ((Integer)this.getWatchedObject(par1).getObject()).intValue();
    093    }
    094
    095    /**
    096     * gets a watchable object and returns it as a String
    097     */
    098    public String getWatchableObjectString(int par1)
    099    {
    100        return (String)this.getWatchedObject(par1).getObject();
    101    }
    102
    103    /**
    104     * Get a watchable object as an ItemStack.
    105     */
    106    public ItemStack getWatchableObjectItemStack(int par1)
    107    {
    108        return (ItemStack)this.getWatchedObject(par1).getObject();
    109    }
    110
    111    /**
    112     * is threadsafe, unless it throws an exception, then
    113     */
    114    private WatchableObject getWatchedObject(int par1)
    115    {
    116        this.lock.readLock().lock();
    117        WatchableObject var2;
    118
    119        try
    120        {
    121            var2 = (WatchableObject)this.watchedObjects.get(Integer.valueOf(par1));
    122        }
    123        catch (Throwable var6)
    124        {
    125            CrashReport var4 = CrashReport.makeCrashReport(var6, "Getting synched entity data");
    126            CrashReportCategory var5 = var4.makeCategory("Synched entity data");
    127            var5.addCrashSection("Data ID", Integer.valueOf(par1));
    128            throw new ReportedException(var4);
    129        }
    130
    131        this.lock.readLock().unlock();
    132        return var2;
    133    }
    134
    135    /**
    136     * updates an already existing object
    137     */
    138    public void updateObject(int par1, Object par2Obj)
    139    {
    140        WatchableObject var3 = this.getWatchedObject(par1);
    141
    142        if (!par2Obj.equals(var3.getObject()))
    143        {
    144            var3.setObject(par2Obj);
    145            var3.setWatched(true);
    146            this.objectChanged = true;
    147        }
    148    }
    149
    150    public void func_82708_h(int par1)
    151    {
    152        WatchableObject.setWatchableObjectWatched(this.getWatchedObject(par1), true);
    153        this.objectChanged = true;
    154    }
    155
    156    public boolean hasChanges()
    157    {
    158        return this.objectChanged;
    159    }
    160
    161    /**
    162     * writes every object in passed list to dataoutputstream, terminated by 0x7F
    163     */
    164    public static void writeObjectsInListToStream(List par0List, DataOutputStream par1DataOutputStream) throws IOException
    165    {
    166        if (par0List != null)
    167        {
    168            Iterator var2 = par0List.iterator();
    169
    170            while (var2.hasNext())
    171            {
    172                WatchableObject var3 = (WatchableObject)var2.next();
    173                writeWatchableObject(par1DataOutputStream, var3);
    174            }
    175        }
    176
    177        par1DataOutputStream.writeByte(127);
    178    }
    179
    180    public List unwatchAndReturnAllWatched()
    181    {
    182        ArrayList var1 = null;
    183
    184        if (this.objectChanged)
    185        {
    186            this.lock.readLock().lock();
    187            Iterator var2 = this.watchedObjects.values().iterator();
    188
    189            while (var2.hasNext())
    190            {
    191                WatchableObject var3 = (WatchableObject)var2.next();
    192
    193                if (var3.isWatched())
    194                {
    195                    var3.setWatched(false);
    196
    197                    if (var1 == null)
    198                    {
    199                        var1 = new ArrayList();
    200                    }
    201
    202                    var1.add(var3);
    203                }
    204            }
    205
    206            this.lock.readLock().unlock();
    207        }
    208
    209        this.objectChanged = false;
    210        return var1;
    211    }
    212
    213    public void writeWatchableObjects(DataOutputStream par1DataOutputStream) throws IOException
    214    {
    215        this.lock.readLock().lock();
    216        Iterator var2 = this.watchedObjects.values().iterator();
    217
    218        while (var2.hasNext())
    219        {
    220            WatchableObject var3 = (WatchableObject)var2.next();
    221            writeWatchableObject(par1DataOutputStream, var3);
    222        }
    223
    224        this.lock.readLock().unlock();
    225        par1DataOutputStream.writeByte(127);
    226    }
    227
    228    public List func_75685_c()
    229    {
    230        ArrayList var1 = null;
    231        this.lock.readLock().lock();
    232        WatchableObject var3;
    233
    234        for (Iterator var2 = this.watchedObjects.values().iterator(); var2.hasNext(); var1.add(var3))
    235        {
    236            var3 = (WatchableObject)var2.next();
    237
    238            if (var1 == null)
    239            {
    240                var1 = new ArrayList();
    241            }
    242        }
    243
    244        this.lock.readLock().unlock();
    245        return var1;
    246    }
    247
    248    private static void writeWatchableObject(DataOutputStream par0DataOutputStream, WatchableObject par1WatchableObject) throws IOException
    249    {
    250        int var2 = (par1WatchableObject.getObjectType() << 5 | par1WatchableObject.getDataValueId() & 31) & 255;
    251        par0DataOutputStream.writeByte(var2);
    252
    253        switch (par1WatchableObject.getObjectType())
    254        {
    255            case 0:
    256                par0DataOutputStream.writeByte(((Byte)par1WatchableObject.getObject()).byteValue());
    257                break;
    258            case 1:
    259                par0DataOutputStream.writeShort(((Short)par1WatchableObject.getObject()).shortValue());
    260                break;
    261            case 2:
    262                par0DataOutputStream.writeInt(((Integer)par1WatchableObject.getObject()).intValue());
    263                break;
    264            case 3:
    265                par0DataOutputStream.writeFloat(((Float)par1WatchableObject.getObject()).floatValue());
    266                break;
    267            case 4:
    268                Packet.writeString((String)par1WatchableObject.getObject(), par0DataOutputStream);
    269                break;
    270            case 5:
    271                ItemStack var4 = (ItemStack)par1WatchableObject.getObject();
    272                Packet.writeItemStack(var4, par0DataOutputStream);
    273                break;
    274            case 6:
    275                ChunkCoordinates var3 = (ChunkCoordinates)par1WatchableObject.getObject();
    276                par0DataOutputStream.writeInt(var3.posX);
    277                par0DataOutputStream.writeInt(var3.posY);
    278                par0DataOutputStream.writeInt(var3.posZ);
    279        }
    280    }
    281
    282    public static List readWatchableObjects(DataInputStream par0DataInputStream) throws IOException
    283    {
    284        ArrayList var1 = null;
    285
    286        for (byte var2 = par0DataInputStream.readByte(); var2 != 127; var2 = par0DataInputStream.readByte())
    287        {
    288            if (var1 == null)
    289            {
    290                var1 = new ArrayList();
    291            }
    292
    293            int var3 = (var2 & 224) >> 5;
    294            int var4 = var2 & 31;
    295            WatchableObject var5 = null;
    296
    297            switch (var3)
    298            {
    299                case 0:
    300                    var5 = new WatchableObject(var3, var4, Byte.valueOf(par0DataInputStream.readByte()));
    301                    break;
    302                case 1:
    303                    var5 = new WatchableObject(var3, var4, Short.valueOf(par0DataInputStream.readShort()));
    304                    break;
    305                case 2:
    306                    var5 = new WatchableObject(var3, var4, Integer.valueOf(par0DataInputStream.readInt()));
    307                    break;
    308                case 3:
    309                    var5 = new WatchableObject(var3, var4, Float.valueOf(par0DataInputStream.readFloat()));
    310                    break;
    311                case 4:
    312                    var5 = new WatchableObject(var3, var4, Packet.readString(par0DataInputStream, 64));
    313                    break;
    314                case 5:
    315                    var5 = new WatchableObject(var3, var4, Packet.readItemStack(par0DataInputStream));
    316                    break;
    317                case 6:
    318                    int var6 = par0DataInputStream.readInt();
    319                    int var7 = par0DataInputStream.readInt();
    320                    int var8 = par0DataInputStream.readInt();
    321                    var5 = new WatchableObject(var3, var4, new ChunkCoordinates(var6, var7, var8));
    322            }
    323
    324            var1.add(var5);
    325        }
    326
    327        return var1;
    328    }
    329
    330    @SideOnly(Side.CLIENT)
    331    public void updateWatchedObjectsFromList(List par1List)
    332    {
    333        this.lock.writeLock().lock();
    334        Iterator var2 = par1List.iterator();
    335
    336        while (var2.hasNext())
    337        {
    338            WatchableObject var3 = (WatchableObject)var2.next();
    339            WatchableObject var4 = (WatchableObject)this.watchedObjects.get(Integer.valueOf(var3.getDataValueId()));
    340
    341            if (var4 != null)
    342            {
    343                var4.setObject(var3.getObject());
    344            }
    345        }
    346
    347        this.lock.writeLock().unlock();
    348    }
    349
    350    public boolean func_92085_d()
    351    {
    352        return this.field_92086_a;
    353    }
    354
    355    static
    356    {
    357        dataTypes.put(Byte.class, Integer.valueOf(0));
    358        dataTypes.put(Short.class, Integer.valueOf(1));
    359        dataTypes.put(Integer.class, Integer.valueOf(2));
    360        dataTypes.put(Float.class, Integer.valueOf(3));
    361        dataTypes.put(String.class, Integer.valueOf(4));
    362        dataTypes.put(ItemStack.class, Integer.valueOf(5));
    363        dataTypes.put(ChunkCoordinates.class, Integer.valueOf(6));
    364    }
    365}