    001    package net.minecraft.entity;
    002
    003    import cpw.mods.fml.relauncher.Side;
    004    import cpw.mods.fml.relauncher.SideOnly;
    005    import java.io.DataInputStream;
    006    import java.io.DataOutputStream;
    007    import java.io.IOException;
    008    import java.util.ArrayList;
    009    import java.util.HashMap;
    010    import java.util.Iterator;
    011    import java.util.List;
    012    import java.util.Map;
    013    import java.util.concurrent.locks.ReadWriteLock;
    014    import java.util.concurrent.locks.ReentrantReadWriteLock;
    015    import net.minecraft.crash.CrashReport;
    016    import net.minecraft.crash.CrashReportCategory;
    017    import net.minecraft.item.ItemStack;
    018    import net.minecraft.network.packet.Packet;
    019    import net.minecraft.util.ChunkCoordinates;
    020    import net.minecraft.util.ReportedException;
    021
    022    public class DataWatcher
    023    {
    024        private boolean field_92035_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 field_75694_d = 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.field_75694_d.writeLock().lock();
    056                this.watchedObjects.put(Integer.valueOf(par1), var4);
    057                this.field_75694_d.writeLock().unlock();
    058                this.field_92035_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.field_75694_d.writeLock().lock();
    069            this.watchedObjects.put(Integer.valueOf(par1), var3);
    070            this.field_75694_d.writeLock().unlock();
    071            this.field_92035_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.field_75694_d.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.field_75694_d.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.field_75694_d.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.field_75694_d.readLock().unlock();
    207            }
    208
    209            this.objectChanged = false;
    210            return var1;
    211        }
    212
    213        public void writeWatchableObjects(DataOutputStream par1DataOutputStream) throws IOException
    214        {
    215            this.field_75694_d.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.field_75694_d.readLock().unlock();
    225            par1DataOutputStream.writeByte(127);
    226        }
    227
    228        public List func_75685_c()
    229        {
    230            ArrayList var1 = null;
    231            this.field_75694_d.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.field_75694_d.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.field_75694_d.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.field_75694_d.writeLock().unlock();
    348        }
    349
    350        public boolean func_92034_d()
    351        {
    352            return this.field_92035_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    }