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