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