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