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