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