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 }