001 package net.minecraft.entity; 002 003 import cpw.mods.fml.relauncher.Side; 004 import cpw.mods.fml.relauncher.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 import net.minecraft.crash.CrashReport; 016 import net.minecraft.crash.CrashReportCategory; 017 import net.minecraft.item.ItemStack; 018 import net.minecraft.network.packet.Packet; 019 import net.minecraft.util.ChunkCoordinates; 020 import net.minecraft.util.ReportedException; 021 022 public class DataWatcher 023 { 024 private boolean field_92035_a = true; 025 private static final HashMap dataTypes = new HashMap(); 026 private final Map watchedObjects = new HashMap(); 027 028 /** true if one or more object was changed */ 029 private boolean objectChanged; 030 private ReadWriteLock field_75694_d = new ReentrantReadWriteLock(); 031 032 /** 033 * adds a new object to dataWatcher to watch, to update an already existing object see updateObject. Arguments: data 034 * Value Id, Object to add 035 */ 036 public void addObject(int par1, Object par2Obj) 037 { 038 Integer var3 = (Integer)dataTypes.get(par2Obj.getClass()); 039 040 if (var3 == null) 041 { 042 throw new IllegalArgumentException("Unknown data type: " + par2Obj.getClass()); 043 } 044 else if (par1 > 31) 045 { 046 throw new IllegalArgumentException("Data value id is too big with " + par1 + "! (Max is " + 31 + ")"); 047 } 048 else if (this.watchedObjects.containsKey(Integer.valueOf(par1))) 049 { 050 throw new IllegalArgumentException("Duplicate id value for " + par1 + "!"); 051 } 052 else 053 { 054 WatchableObject var4 = new WatchableObject(var3.intValue(), par1, par2Obj); 055 this.field_75694_d.writeLock().lock(); 056 this.watchedObjects.put(Integer.valueOf(par1), var4); 057 this.field_75694_d.writeLock().unlock(); 058 this.field_92035_a = false; 059 } 060 } 061 062 /** 063 * Add a new object for the DataWatcher to watch, using the specified data type. 064 */ 065 public void addObjectByDataType(int par1, int par2) 066 { 067 WatchableObject var3 = new WatchableObject(par2, par1, (Object)null); 068 this.field_75694_d.writeLock().lock(); 069 this.watchedObjects.put(Integer.valueOf(par1), var3); 070 this.field_75694_d.writeLock().unlock(); 071 this.field_92035_a = false; 072 } 073 074 /** 075 * gets the bytevalue of a watchable object 076 */ 077 public byte getWatchableObjectByte(int par1) 078 { 079 return ((Byte)this.getWatchedObject(par1).getObject()).byteValue(); 080 } 081 082 public short getWatchableObjectShort(int par1) 083 { 084 return ((Short)this.getWatchedObject(par1).getObject()).shortValue(); 085 } 086 087 /** 088 * gets a watchable object and returns it as a Integer 089 */ 090 public int getWatchableObjectInt(int par1) 091 { 092 return ((Integer)this.getWatchedObject(par1).getObject()).intValue(); 093 } 094 095 /** 096 * gets a watchable object and returns it as a String 097 */ 098 public String getWatchableObjectString(int par1) 099 { 100 return (String)this.getWatchedObject(par1).getObject(); 101 } 102 103 /** 104 * Get a watchable object as an ItemStack. 105 */ 106 public ItemStack getWatchableObjectItemStack(int par1) 107 { 108 return (ItemStack)this.getWatchedObject(par1).getObject(); 109 } 110 111 /** 112 * is threadsafe, unless it throws an exception, then 113 */ 114 private WatchableObject getWatchedObject(int par1) 115 { 116 this.field_75694_d.readLock().lock(); 117 WatchableObject var2; 118 119 try 120 { 121 var2 = (WatchableObject)this.watchedObjects.get(Integer.valueOf(par1)); 122 } 123 catch (Throwable var6) 124 { 125 CrashReport var4 = CrashReport.makeCrashReport(var6, "Getting synched entity data"); 126 CrashReportCategory var5 = var4.makeCategory("Synched entity data"); 127 var5.addCrashSection("Data ID", Integer.valueOf(par1)); 128 throw new ReportedException(var4); 129 } 130 131 this.field_75694_d.readLock().unlock(); 132 return var2; 133 } 134 135 /** 136 * updates an already existing object 137 */ 138 public void updateObject(int par1, Object par2Obj) 139 { 140 WatchableObject var3 = this.getWatchedObject(par1); 141 142 if (!par2Obj.equals(var3.getObject())) 143 { 144 var3.setObject(par2Obj); 145 var3.setWatched(true); 146 this.objectChanged = true; 147 } 148 } 149 150 public void func_82708_h(int par1) 151 { 152 WatchableObject.setWatchableObjectWatched(this.getWatchedObject(par1), true); 153 this.objectChanged = true; 154 } 155 156 public boolean hasChanges() 157 { 158 return this.objectChanged; 159 } 160 161 /** 162 * writes every object in passed list to dataoutputstream, terminated by 0x7F 163 */ 164 public static void writeObjectsInListToStream(List par0List, DataOutputStream par1DataOutputStream) throws IOException 165 { 166 if (par0List != null) 167 { 168 Iterator var2 = par0List.iterator(); 169 170 while (var2.hasNext()) 171 { 172 WatchableObject var3 = (WatchableObject)var2.next(); 173 writeWatchableObject(par1DataOutputStream, var3); 174 } 175 } 176 177 par1DataOutputStream.writeByte(127); 178 } 179 180 public List unwatchAndReturnAllWatched() 181 { 182 ArrayList var1 = null; 183 184 if (this.objectChanged) 185 { 186 this.field_75694_d.readLock().lock(); 187 Iterator var2 = this.watchedObjects.values().iterator(); 188 189 while (var2.hasNext()) 190 { 191 WatchableObject var3 = (WatchableObject)var2.next(); 192 193 if (var3.isWatched()) 194 { 195 var3.setWatched(false); 196 197 if (var1 == null) 198 { 199 var1 = new ArrayList(); 200 } 201 202 var1.add(var3); 203 } 204 } 205 206 this.field_75694_d.readLock().unlock(); 207 } 208 209 this.objectChanged = false; 210 return var1; 211 } 212 213 public void writeWatchableObjects(DataOutputStream par1DataOutputStream) throws IOException 214 { 215 this.field_75694_d.readLock().lock(); 216 Iterator var2 = this.watchedObjects.values().iterator(); 217 218 while (var2.hasNext()) 219 { 220 WatchableObject var3 = (WatchableObject)var2.next(); 221 writeWatchableObject(par1DataOutputStream, var3); 222 } 223 224 this.field_75694_d.readLock().unlock(); 225 par1DataOutputStream.writeByte(127); 226 } 227 228 public List func_75685_c() 229 { 230 ArrayList var1 = null; 231 this.field_75694_d.readLock().lock(); 232 WatchableObject var3; 233 234 for (Iterator var2 = this.watchedObjects.values().iterator(); var2.hasNext(); var1.add(var3)) 235 { 236 var3 = (WatchableObject)var2.next(); 237 238 if (var1 == null) 239 { 240 var1 = new ArrayList(); 241 } 242 } 243 244 this.field_75694_d.readLock().unlock(); 245 return var1; 246 } 247 248 private static void writeWatchableObject(DataOutputStream par0DataOutputStream, WatchableObject par1WatchableObject) throws IOException 249 { 250 int var2 = (par1WatchableObject.getObjectType() << 5 | par1WatchableObject.getDataValueId() & 31) & 255; 251 par0DataOutputStream.writeByte(var2); 252 253 switch (par1WatchableObject.getObjectType()) 254 { 255 case 0: 256 par0DataOutputStream.writeByte(((Byte)par1WatchableObject.getObject()).byteValue()); 257 break; 258 case 1: 259 par0DataOutputStream.writeShort(((Short)par1WatchableObject.getObject()).shortValue()); 260 break; 261 case 2: 262 par0DataOutputStream.writeInt(((Integer)par1WatchableObject.getObject()).intValue()); 263 break; 264 case 3: 265 par0DataOutputStream.writeFloat(((Float)par1WatchableObject.getObject()).floatValue()); 266 break; 267 case 4: 268 Packet.writeString((String)par1WatchableObject.getObject(), par0DataOutputStream); 269 break; 270 case 5: 271 ItemStack var4 = (ItemStack)par1WatchableObject.getObject(); 272 Packet.writeItemStack(var4, par0DataOutputStream); 273 break; 274 case 6: 275 ChunkCoordinates var3 = (ChunkCoordinates)par1WatchableObject.getObject(); 276 par0DataOutputStream.writeInt(var3.posX); 277 par0DataOutputStream.writeInt(var3.posY); 278 par0DataOutputStream.writeInt(var3.posZ); 279 } 280 } 281 282 public static List readWatchableObjects(DataInputStream par0DataInputStream) throws IOException 283 { 284 ArrayList var1 = null; 285 286 for (byte var2 = par0DataInputStream.readByte(); var2 != 127; var2 = par0DataInputStream.readByte()) 287 { 288 if (var1 == null) 289 { 290 var1 = new ArrayList(); 291 } 292 293 int var3 = (var2 & 224) >> 5; 294 int var4 = var2 & 31; 295 WatchableObject var5 = null; 296 297 switch (var3) 298 { 299 case 0: 300 var5 = new WatchableObject(var3, var4, Byte.valueOf(par0DataInputStream.readByte())); 301 break; 302 case 1: 303 var5 = new WatchableObject(var3, var4, Short.valueOf(par0DataInputStream.readShort())); 304 break; 305 case 2: 306 var5 = new WatchableObject(var3, var4, Integer.valueOf(par0DataInputStream.readInt())); 307 break; 308 case 3: 309 var5 = new WatchableObject(var3, var4, Float.valueOf(par0DataInputStream.readFloat())); 310 break; 311 case 4: 312 var5 = new WatchableObject(var3, var4, Packet.readString(par0DataInputStream, 64)); 313 break; 314 case 5: 315 var5 = new WatchableObject(var3, var4, Packet.readItemStack(par0DataInputStream)); 316 break; 317 case 6: 318 int var6 = par0DataInputStream.readInt(); 319 int var7 = par0DataInputStream.readInt(); 320 int var8 = par0DataInputStream.readInt(); 321 var5 = new WatchableObject(var3, var4, new ChunkCoordinates(var6, var7, var8)); 322 } 323 324 var1.add(var5); 325 } 326 327 return var1; 328 } 329 330 @SideOnly(Side.CLIENT) 331 public void updateWatchedObjectsFromList(List par1List) 332 { 333 this.field_75694_d.writeLock().lock(); 334 Iterator var2 = par1List.iterator(); 335 336 while (var2.hasNext()) 337 { 338 WatchableObject var3 = (WatchableObject)var2.next(); 339 WatchableObject var4 = (WatchableObject)this.watchedObjects.get(Integer.valueOf(var3.getDataValueId())); 340 341 if (var4 != null) 342 { 343 var4.setObject(var3.getObject()); 344 } 345 } 346 347 this.field_75694_d.writeLock().unlock(); 348 } 349 350 public boolean func_92034_d() 351 { 352 return this.field_92035_a; 353 } 354 355 static 356 { 357 dataTypes.put(Byte.class, Integer.valueOf(0)); 358 dataTypes.put(Short.class, Integer.valueOf(1)); 359 dataTypes.put(Integer.class, Integer.valueOf(2)); 360 dataTypes.put(Float.class, Integer.valueOf(3)); 361 dataTypes.put(String.class, Integer.valueOf(4)); 362 dataTypes.put(ItemStack.class, Integer.valueOf(5)); 363 dataTypes.put(ChunkCoordinates.class, Integer.valueOf(6)); 364 } 365 }