package net.minecraft.entity;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.item.ItemStack;
import net.minecraft.network.packet.Packet;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.ReportedException;
public class DataWatcher
{
private boolean field_92035_a = true;
private static final HashMap dataTypes = new HashMap();
private final Map watchedObjects = new HashMap();
/** true if one or more object was changed */
private boolean objectChanged;
private ReadWriteLock field_75694_d = new ReentrantReadWriteLock();
/**
* adds a new object to dataWatcher to watch, to update an already existing object see updateObject. Arguments: data
* Value Id, Object to add
*/
public void addObject(int par1, Object par2Obj)
{
Integer var3 = (Integer)dataTypes.get(par2Obj.getClass());
if (var3 == null)
{
throw new IllegalArgumentException("Unknown data type: " + par2Obj.getClass());
}
else if (par1 > 31)
{
throw new IllegalArgumentException("Data value id is too big with " + par1 + "! (Max is " + 31 + ")");
}
else if (this.watchedObjects.containsKey(Integer.valueOf(par1)))
{
throw new IllegalArgumentException("Duplicate id value for " + par1 + "!");
}
else
{
WatchableObject var4 = new WatchableObject(var3.intValue(), par1, par2Obj);
this.field_75694_d.writeLock().lock();
this.watchedObjects.put(Integer.valueOf(par1), var4);
this.field_75694_d.writeLock().unlock();
this.field_92035_a = false;
}
}
/**
* Add a new object for the DataWatcher to watch, using the specified data type.
*/
public void addObjectByDataType(int par1, int par2)
{
WatchableObject var3 = new WatchableObject(par2, par1, (Object)null);
this.field_75694_d.writeLock().lock();
this.watchedObjects.put(Integer.valueOf(par1), var3);
this.field_75694_d.writeLock().unlock();
this.field_92035_a = false;
}
/**
* gets the bytevalue of a watchable object
*/
public byte getWatchableObjectByte(int par1)
{
return ((Byte)this.getWatchedObject(par1).getObject()).byteValue();
}
public short getWatchableObjectShort(int par1)
{
return ((Short)this.getWatchedObject(par1).getObject()).shortValue();
}
/**
* gets a watchable object and returns it as a Integer
*/
public int getWatchableObjectInt(int par1)
{
return ((Integer)this.getWatchedObject(par1).getObject()).intValue();
}
/**
* gets a watchable object and returns it as a String
*/
public String getWatchableObjectString(int par1)
{
return (String)this.getWatchedObject(par1).getObject();
}
/**
* Get a watchable object as an ItemStack.
*/
public ItemStack getWatchableObjectItemStack(int par1)
{
return (ItemStack)this.getWatchedObject(par1).getObject();
}
/**
* is threadsafe, unless it throws an exception, then
*/
private WatchableObject getWatchedObject(int par1)
{
this.field_75694_d.readLock().lock();
WatchableObject var2;
try
{
var2 = (WatchableObject)this.watchedObjects.get(Integer.valueOf(par1));
}
catch (Throwable var6)
{
CrashReport var4 = CrashReport.makeCrashReport(var6, "Getting synched entity data");
CrashReportCategory var5 = var4.makeCategory("Synched entity data");
var5.addCrashSection("Data ID", Integer.valueOf(par1));
throw new ReportedException(var4);
}
this.field_75694_d.readLock().unlock();
return var2;
}
/**
* updates an already existing object
*/
public void updateObject(int par1, Object par2Obj)
{
WatchableObject var3 = this.getWatchedObject(par1);
if (!par2Obj.equals(var3.getObject()))
{
var3.setObject(par2Obj);
var3.setWatched(true);
this.objectChanged = true;
}
}
public void func_82708_h(int par1)
{
WatchableObject.setWatchableObjectWatched(this.getWatchedObject(par1), true);
this.objectChanged = true;
}
public boolean hasChanges()
{
return this.objectChanged;
}
/**
* writes every object in passed list to dataoutputstream, terminated by 0x7F
*/
public static void writeObjectsInListToStream(List par0List, DataOutputStream par1DataOutputStream) throws IOException
{
if (par0List != null)
{
Iterator var2 = par0List.iterator();
while (var2.hasNext())
{
WatchableObject var3 = (WatchableObject)var2.next();
writeWatchableObject(par1DataOutputStream, var3);
}
}
par1DataOutputStream.writeByte(127);
}
public List unwatchAndReturnAllWatched()
{
ArrayList var1 = null;
if (this.objectChanged)
{
this.field_75694_d.readLock().lock();
Iterator var2 = this.watchedObjects.values().iterator();
while (var2.hasNext())
{
WatchableObject var3 = (WatchableObject)var2.next();
if (var3.isWatched())
{
var3.setWatched(false);
if (var1 == null)
{
var1 = new ArrayList();
}
var1.add(var3);
}
}
this.field_75694_d.readLock().unlock();
}
this.objectChanged = false;
return var1;
}
public void writeWatchableObjects(DataOutputStream par1DataOutputStream) throws IOException
{
this.field_75694_d.readLock().lock();
Iterator var2 = this.watchedObjects.values().iterator();
while (var2.hasNext())
{
WatchableObject var3 = (WatchableObject)var2.next();
writeWatchableObject(par1DataOutputStream, var3);
}
this.field_75694_d.readLock().unlock();
par1DataOutputStream.writeByte(127);
}
public List func_75685_c()
{
ArrayList var1 = null;
this.field_75694_d.readLock().lock();
WatchableObject var3;
for (Iterator var2 = this.watchedObjects.values().iterator(); var2.hasNext(); var1.add(var3))
{
var3 = (WatchableObject)var2.next();
if (var1 == null)
{
var1 = new ArrayList();
}
}
this.field_75694_d.readLock().unlock();
return var1;
}
private static void writeWatchableObject(DataOutputStream par0DataOutputStream, WatchableObject par1WatchableObject) throws IOException
{
int var2 = (par1WatchableObject.getObjectType() << 5 | par1WatchableObject.getDataValueId() & 31) & 255;
par0DataOutputStream.writeByte(var2);
switch (par1WatchableObject.getObjectType())
{
case 0:
par0DataOutputStream.writeByte(((Byte)par1WatchableObject.getObject()).byteValue());
break;
case 1:
par0DataOutputStream.writeShort(((Short)par1WatchableObject.getObject()).shortValue());
break;
case 2:
par0DataOutputStream.writeInt(((Integer)par1WatchableObject.getObject()).intValue());
break;
case 3:
par0DataOutputStream.writeFloat(((Float)par1WatchableObject.getObject()).floatValue());
break;
case 4:
Packet.writeString((String)par1WatchableObject.getObject(), par0DataOutputStream);
break;
case 5:
ItemStack var4 = (ItemStack)par1WatchableObject.getObject();
Packet.writeItemStack(var4, par0DataOutputStream);
break;
case 6:
ChunkCoordinates var3 = (ChunkCoordinates)par1WatchableObject.getObject();
par0DataOutputStream.writeInt(var3.posX);
par0DataOutputStream.writeInt(var3.posY);
par0DataOutputStream.writeInt(var3.posZ);
}
}
public static List readWatchableObjects(DataInputStream par0DataInputStream) throws IOException
{
ArrayList var1 = null;
for (byte var2 = par0DataInputStream.readByte(); var2 != 127; var2 = par0DataInputStream.readByte())
{
if (var1 == null)
{
var1 = new ArrayList();
}
int var3 = (var2 & 224) >> 5;
int var4 = var2 & 31;
WatchableObject var5 = null;
switch (var3)
{
case 0:
var5 = new WatchableObject(var3, var4, Byte.valueOf(par0DataInputStream.readByte()));
break;
case 1:
var5 = new WatchableObject(var3, var4, Short.valueOf(par0DataInputStream.readShort()));
break;
case 2:
var5 = new WatchableObject(var3, var4, Integer.valueOf(par0DataInputStream.readInt()));
break;
case 3:
var5 = new WatchableObject(var3, var4, Float.valueOf(par0DataInputStream.readFloat()));
break;
case 4:
var5 = new WatchableObject(var3, var4, Packet.readString(par0DataInputStream, 64));
break;
case 5:
var5 = new WatchableObject(var3, var4, Packet.readItemStack(par0DataInputStream));
break;
case 6:
int var6 = par0DataInputStream.readInt();
int var7 = par0DataInputStream.readInt();
int var8 = par0DataInputStream.readInt();
var5 = new WatchableObject(var3, var4, new ChunkCoordinates(var6, var7, var8));
}
var1.add(var5);
}
return var1;
}
@SideOnly(Side.CLIENT)
public void updateWatchedObjectsFromList(List par1List)
{
this.field_75694_d.writeLock().lock();
Iterator var2 = par1List.iterator();
while (var2.hasNext())
{
WatchableObject var3 = (WatchableObject)var2.next();
WatchableObject var4 = (WatchableObject)this.watchedObjects.get(Integer.valueOf(var3.getDataValueId()));
if (var4 != null)
{
var4.setObject(var3.getObject());
}
}
this.field_75694_d.writeLock().unlock();
}
public boolean func_92034_d()
{
return this.field_92035_a;
}
static
{
dataTypes.put(Byte.class, Integer.valueOf(0));
dataTypes.put(Short.class, Integer.valueOf(1));
dataTypes.put(Integer.class, Integer.valueOf(2));
dataTypes.put(Float.class, Integer.valueOf(3));
dataTypes.put(String.class, Integer.valueOf(4));
dataTypes.put(ItemStack.class, Integer.valueOf(5));
dataTypes.put(ChunkCoordinates.class, Integer.valueOf(6));
}
}