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