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 }