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 }