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 }