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 }