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