    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 var6)
    115            {
    116                CrashReport var4 = CrashReport.func_85055_a(var6, "Getting synched entity data");
    117                CrashReportCategory var5 = var4.func_85058_a("Synched entity data");
    118                var5.addCrashSection("Data ID", Integer.valueOf(par1));
    119                throw new ReportedException(var4);
    120            }
    121
    122            this.field_75694_d.readLock().unlock();
    123            return var2;
    124        }
    125
    126        /**
    127         * updates an already existing object
    128         */
    129        public void updateObject(int par1, Object par2Obj)
    130        {
    131            WatchableObject var3 = this.getWatchedObject(par1);
    132
    133            if (!par2Obj.equals(var3.getObject()))
    134            {
    135                var3.setObject(par2Obj);
    136                var3.setWatched(true);
    137                this.objectChanged = true;
    138            }
    139        }
    140
    141        public void func_82708_h(int par1)
    142        {
    143            WatchableObject.setWatchableObjectWatched(this.getWatchedObject(par1), true);
    144            this.objectChanged = true;
    145        }
    146
    147        public boolean hasChanges()
    148        {
    149            return this.objectChanged;
    150        }
    151
    152        /**
    153         * writes every object in passed list to dataoutputstream, terminated by 0x7F
    154         */
    155        public static void writeObjectsInListToStream(List par0List, DataOutputStream par1DataOutputStream) throws IOException
    156        {
    157            if (par0List != null)
    158            {
    159                Iterator var2 = par0List.iterator();
    160
    161                while (var2.hasNext())
    162                {
    163                    WatchableObject var3 = (WatchableObject)var2.next();
    164                    writeWatchableObject(par1DataOutputStream, var3);
    165                }
    166            }
    167
    168            par1DataOutputStream.writeByte(127);
    169        }
    170
    171        public List unwatchAndReturnAllWatched()
    172        {
    173            ArrayList var1 = null;
    174
    175            if (this.objectChanged)
    176            {
    177                this.field_75694_d.readLock().lock();
    178                Iterator var2 = this.watchedObjects.values().iterator();
    179
    180                while (var2.hasNext())
    181                {
    182                    WatchableObject var3 = (WatchableObject)var2.next();
    183
    184                    if (var3.isWatched())
    185                    {
    186                        var3.setWatched(false);
    187
    188                        if (var1 == null)
    189                        {
    190                            var1 = new ArrayList();
    191                        }
    192
    193                        var1.add(var3);
    194                    }
    195                }
    196
    197                this.field_75694_d.readLock().unlock();
    198            }
    199
    200            this.objectChanged = false;
    201            return var1;
    202        }
    203
    204        public void writeWatchableObjects(DataOutputStream par1DataOutputStream) throws IOException
    205        {
    206            this.field_75694_d.readLock().lock();
    207            Iterator var2 = this.watchedObjects.values().iterator();
    208
    209            while (var2.hasNext())
    210            {
    211                WatchableObject var3 = (WatchableObject)var2.next();
    212                writeWatchableObject(par1DataOutputStream, var3);
    213            }
    214
    215            this.field_75694_d.readLock().unlock();
    216            par1DataOutputStream.writeByte(127);
    217        }
    218
    219        public List func_75685_c()
    220        {
    221            ArrayList var1 = null;
    222            this.field_75694_d.readLock().lock();
    223            WatchableObject var3;
    224
    225            for (Iterator var2 = this.watchedObjects.values().iterator(); var2.hasNext(); var1.add(var3))
    226            {
    227                var3 = (WatchableObject)var2.next();
    228
    229                if (var1 == null)
    230                {
    231                    var1 = new ArrayList();
    232                }
    233            }
    234
    235            this.field_75694_d.readLock().unlock();
    236            return var1;
    237        }
    238
    239        private static void writeWatchableObject(DataOutputStream par0DataOutputStream, WatchableObject par1WatchableObject) throws IOException
    240        {
    241            int var2 = (par1WatchableObject.getObjectType() << 5 | par1WatchableObject.getDataValueId() & 31) & 255;
    242            par0DataOutputStream.writeByte(var2);
    243
    244            switch (par1WatchableObject.getObjectType())
    245            {
    246                case 0:
    247                    par0DataOutputStream.writeByte(((Byte)par1WatchableObject.getObject()).byteValue());
    248                    break;
    249                case 1:
    250                    par0DataOutputStream.writeShort(((Short)par1WatchableObject.getObject()).shortValue());
    251                    break;
    252                case 2:
    253                    par0DataOutputStream.writeInt(((Integer)par1WatchableObject.getObject()).intValue());
    254                    break;
    255                case 3:
    256                    par0DataOutputStream.writeFloat(((Float)par1WatchableObject.getObject()).floatValue());
    257                    break;
    258                case 4:
    259                    Packet.writeString((String)par1WatchableObject.getObject(), par0DataOutputStream);
    260                    break;
    261                case 5:
    262                    ItemStack var4 = (ItemStack)par1WatchableObject.getObject();
    263                    Packet.writeItemStack(var4, par0DataOutputStream);
    264                    break;
    265                case 6:
    266                    ChunkCoordinates var3 = (ChunkCoordinates)par1WatchableObject.getObject();
    267                    par0DataOutputStream.writeInt(var3.posX);
    268                    par0DataOutputStream.writeInt(var3.posY);
    269                    par0DataOutputStream.writeInt(var3.posZ);
    270            }
    271        }
    272
    273        public static List readWatchableObjects(DataInputStream par0DataInputStream) throws IOException
    274        {
    275            ArrayList var1 = null;
    276
    277            for (byte var2 = par0DataInputStream.readByte(); var2 != 127; var2 = par0DataInputStream.readByte())
    278            {
    279                if (var1 == null)
    280                {
    281                    var1 = new ArrayList();
    282                }
    283
    284                int var3 = (var2 & 224) >> 5;
    285                int var4 = var2 & 31;
    286                WatchableObject var5 = null;
    287
    288                switch (var3)
    289                {
    290                    case 0:
    291                        var5 = new WatchableObject(var3, var4, Byte.valueOf(par0DataInputStream.readByte()));
    292                        break;
    293                    case 1:
    294                        var5 = new WatchableObject(var3, var4, Short.valueOf(par0DataInputStream.readShort()));
    295                        break;
    296                    case 2:
    297                        var5 = new WatchableObject(var3, var4, Integer.valueOf(par0DataInputStream.readInt()));
    298                        break;
    299                    case 3:
    300                        var5 = new WatchableObject(var3, var4, Float.valueOf(par0DataInputStream.readFloat()));
    301                        break;
    302                    case 4:
    303                        var5 = new WatchableObject(var3, var4, Packet.readString(par0DataInputStream, 64));
    304                        break;
    305                    case 5:
    306                        var5 = new WatchableObject(var3, var4, Packet.readItemStack(par0DataInputStream));
    307                        break;
    308                    case 6:
    309                        int var6 = par0DataInputStream.readInt();
    310                        int var7 = par0DataInputStream.readInt();
    311                        int var8 = par0DataInputStream.readInt();
    312                        var5 = new WatchableObject(var3, var4, new ChunkCoordinates(var6, var7, var8));
    313                }
    314
    315                var1.add(var5);
    316            }
    317
    318            return var1;
    319        }
    320
    321        @SideOnly(Side.CLIENT)
    322        public void updateWatchedObjectsFromList(List par1List)
    323        {
    324            this.field_75694_d.writeLock().lock();
    325            Iterator var2 = par1List.iterator();
    326
    327            while (var2.hasNext())
    328            {
    329                WatchableObject var3 = (WatchableObject)var2.next();
    330                WatchableObject var4 = (WatchableObject)this.watchedObjects.get(Integer.valueOf(var3.getDataValueId()));
    331
    332                if (var4 != null)
    333                {
    334                    var4.setObject(var3.getObject());
    335                }
    336            }
    337
    338            this.field_75694_d.writeLock().unlock();
    339        }
    340
    341        static
    342        {
    343            dataTypes.put(Byte.class, Integer.valueOf(0));
    344            dataTypes.put(Short.class, Integer.valueOf(1));
    345            dataTypes.put(Integer.class, Integer.valueOf(2));
    346            dataTypes.put(Float.class, Integer.valueOf(3));
    347            dataTypes.put(String.class, Integer.valueOf(4));
    348            dataTypes.put(ItemStack.class, Integer.valueOf(5));
    349            dataTypes.put(ChunkCoordinates.class, Integer.valueOf(6));
    350        }
    351    }