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 }