package net.minecraft.entity; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; 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.PacketBuffer; import net.minecraft.util.ChunkCoordinates; import net.minecraft.util.ReportedException; import org.apache.commons.lang3.ObjectUtils; public class DataWatcher { private final Entity field_151511_a; /** When isBlank is true the DataWatcher is not watching any objects */ private boolean isBlank = 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 lock = new ReentrantReadWriteLock(); private static final String __OBFID = "CL_00001559"; public DataWatcher(Entity p_i45313_1_) { this.field_151511_a = p_i45313_1_; } /** * 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 p_75682_1_, Object p_75682_2_) { Integer integer = (Integer)dataTypes.get(p_75682_2_.getClass()); if (integer == null) { throw new IllegalArgumentException("Unknown data type: " + p_75682_2_.getClass()); } else if (p_75682_1_ > 31) { throw new IllegalArgumentException("Data value id is too big with " + p_75682_1_ + "! (Max is " + 31 + ")"); } else if (this.watchedObjects.containsKey(Integer.valueOf(p_75682_1_))) { throw new IllegalArgumentException("Duplicate id value for " + p_75682_1_ + "!"); } else { DataWatcher.WatchableObject watchableobject = new DataWatcher.WatchableObject(integer.intValue(), p_75682_1_, p_75682_2_); this.lock.writeLock().lock(); this.watchedObjects.put(Integer.valueOf(p_75682_1_), watchableobject); this.lock.writeLock().unlock(); this.isBlank = false; } } /** * Add a new object for the DataWatcher to watch, using the specified data type. */ public void addObjectByDataType(int p_82709_1_, int p_82709_2_) { DataWatcher.WatchableObject watchableobject = new DataWatcher.WatchableObject(p_82709_2_, p_82709_1_, (Object)null); this.lock.writeLock().lock(); this.watchedObjects.put(Integer.valueOf(p_82709_1_), watchableobject); this.lock.writeLock().unlock(); this.isBlank = false; } /** * gets the bytevalue of a watchable object */ public byte getWatchableObjectByte(int p_75683_1_) { return ((Byte)this.getWatchedObject(p_75683_1_).getObject()).byteValue(); } public short getWatchableObjectShort(int p_75693_1_) { return ((Short)this.getWatchedObject(p_75693_1_).getObject()).shortValue(); } /** * gets a watchable object and returns it as a Integer */ public int getWatchableObjectInt(int p_75679_1_) { return ((Integer)this.getWatchedObject(p_75679_1_).getObject()).intValue(); } public float getWatchableObjectFloat(int p_111145_1_) { return ((Float)this.getWatchedObject(p_111145_1_).getObject()).floatValue(); } /** * gets a watchable object and returns it as a String */ public String getWatchableObjectString(int p_75681_1_) { return (String)this.getWatchedObject(p_75681_1_).getObject(); } /** * Get a watchable object as an ItemStack. */ public ItemStack getWatchableObjectItemStack(int p_82710_1_) { return (ItemStack)this.getWatchedObject(p_82710_1_).getObject(); } /** * is threadsafe, unless it throws an exception, then */ private DataWatcher.WatchableObject getWatchedObject(int p_75691_1_) { this.lock.readLock().lock(); DataWatcher.WatchableObject watchableobject; try { watchableobject = (DataWatcher.WatchableObject)this.watchedObjects.get(Integer.valueOf(p_75691_1_)); } catch (Throwable throwable) { CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Getting synched entity data"); CrashReportCategory crashreportcategory = crashreport.makeCategory("Synched entity data"); crashreportcategory.addCrashSection("Data ID", Integer.valueOf(p_75691_1_)); throw new ReportedException(crashreport); } this.lock.readLock().unlock(); return watchableobject; } /** * updates an already existing object */ public void updateObject(int p_75692_1_, Object p_75692_2_) { DataWatcher.WatchableObject watchableobject = this.getWatchedObject(p_75692_1_); if (ObjectUtils.notEqual(p_75692_2_, watchableobject.getObject())) { watchableobject.setObject(p_75692_2_); this.field_151511_a.func_145781_i(p_75692_1_); watchableobject.setWatched(true); this.objectChanged = true; } } public void setObjectWatched(int p_82708_1_) { this.getWatchedObject(p_82708_1_).watched = true; this.objectChanged = true; } /** * true if one or more object was changed */ public boolean hasObjectChanged() { return this.objectChanged; } /** * Writes the list of watched objects (entity attribute of type {byte, short, int, float, string, ItemStack, * ChunkCoordinates}) to the specified PacketBuffer */ public static void writeWatchedListToPacketBuffer(List p_151507_0_, PacketBuffer p_151507_1_) throws IOException { if (p_151507_0_ != null) { Iterator iterator = p_151507_0_.iterator(); while (iterator.hasNext()) { DataWatcher.WatchableObject watchableobject = (DataWatcher.WatchableObject)iterator.next(); writeWatchableObjectToPacketBuffer(p_151507_1_, watchableobject); } } p_151507_1_.writeByte(127); } public List getChanged() { ArrayList arraylist = null; if (this.objectChanged) { this.lock.readLock().lock(); Iterator iterator = this.watchedObjects.values().iterator(); while (iterator.hasNext()) { DataWatcher.WatchableObject watchableobject = (DataWatcher.WatchableObject)iterator.next(); if (watchableobject.isWatched()) { watchableobject.setWatched(false); if (arraylist == null) { arraylist = new ArrayList(); } arraylist.add(watchableobject); } } this.lock.readLock().unlock(); } this.objectChanged = false; return arraylist; } public void func_151509_a(PacketBuffer p_151509_1_) throws IOException { this.lock.readLock().lock(); Iterator iterator = this.watchedObjects.values().iterator(); while (iterator.hasNext()) { DataWatcher.WatchableObject watchableobject = (DataWatcher.WatchableObject)iterator.next(); writeWatchableObjectToPacketBuffer(p_151509_1_, watchableobject); } this.lock.readLock().unlock(); p_151509_1_.writeByte(127); } public List getAllWatched() { ArrayList arraylist = null; this.lock.readLock().lock(); DataWatcher.WatchableObject watchableobject; for (Iterator iterator = this.watchedObjects.values().iterator(); iterator.hasNext(); arraylist.add(watchableobject)) { watchableobject = (DataWatcher.WatchableObject)iterator.next(); if (arraylist == null) { arraylist = new ArrayList(); } } this.lock.readLock().unlock(); return arraylist; } /** * Writes a watchable object (entity attribute of type {byte, short, int, float, string, ItemStack, * ChunkCoordinates}) to the specified PacketBuffer */ private static void writeWatchableObjectToPacketBuffer(PacketBuffer p_151510_0_, DataWatcher.WatchableObject p_151510_1_) throws IOException { int i = (p_151510_1_.getObjectType() << 5 | p_151510_1_.getDataValueId() & 31) & 255; p_151510_0_.writeByte(i); switch (p_151510_1_.getObjectType()) { case 0: p_151510_0_.writeByte(((Byte)p_151510_1_.getObject()).byteValue()); break; case 1: p_151510_0_.writeShort(((Short)p_151510_1_.getObject()).shortValue()); break; case 2: p_151510_0_.writeInt(((Integer)p_151510_1_.getObject()).intValue()); break; case 3: p_151510_0_.writeFloat(((Float)p_151510_1_.getObject()).floatValue()); break; case 4: p_151510_0_.writeStringToBuffer((String)p_151510_1_.getObject()); break; case 5: ItemStack itemstack = (ItemStack)p_151510_1_.getObject(); p_151510_0_.writeItemStackToBuffer(itemstack); break; case 6: ChunkCoordinates chunkcoordinates = (ChunkCoordinates)p_151510_1_.getObject(); p_151510_0_.writeInt(chunkcoordinates.posX); p_151510_0_.writeInt(chunkcoordinates.posY); p_151510_0_.writeInt(chunkcoordinates.posZ); } } /** * Reads a list of watched objects (entity attribute of type {byte, short, int, float, string, ItemStack, * ChunkCoordinates}) from the supplied PacketBuffer */ public static List readWatchedListFromPacketBuffer(PacketBuffer p_151508_0_) throws IOException { ArrayList arraylist = null; for (byte b0 = p_151508_0_.readByte(); b0 != 127; b0 = p_151508_0_.readByte()) { if (arraylist == null) { arraylist = new ArrayList(); } int i = (b0 & 224) >> 5; int j = b0 & 31; DataWatcher.WatchableObject watchableobject = null; switch (i) { case 0: watchableobject = new DataWatcher.WatchableObject(i, j, Byte.valueOf(p_151508_0_.readByte())); break; case 1: watchableobject = new DataWatcher.WatchableObject(i, j, Short.valueOf(p_151508_0_.readShort())); break; case 2: watchableobject = new DataWatcher.WatchableObject(i, j, Integer.valueOf(p_151508_0_.readInt())); break; case 3: watchableobject = new DataWatcher.WatchableObject(i, j, Float.valueOf(p_151508_0_.readFloat())); break; case 4: watchableobject = new DataWatcher.WatchableObject(i, j, p_151508_0_.readStringFromBuffer(32767)); break; case 5: watchableobject = new DataWatcher.WatchableObject(i, j, p_151508_0_.readItemStackFromBuffer()); break; case 6: int k = p_151508_0_.readInt(); int l = p_151508_0_.readInt(); int i1 = p_151508_0_.readInt(); watchableobject = new DataWatcher.WatchableObject(i, j, new ChunkCoordinates(k, l, i1)); } arraylist.add(watchableobject); } return arraylist; } @SideOnly(Side.CLIENT) public void updateWatchedObjectsFromList(List p_75687_1_) { this.lock.writeLock().lock(); Iterator iterator = p_75687_1_.iterator(); while (iterator.hasNext()) { DataWatcher.WatchableObject watchableobject = (DataWatcher.WatchableObject)iterator.next(); DataWatcher.WatchableObject watchableobject1 = (DataWatcher.WatchableObject)this.watchedObjects.get(Integer.valueOf(watchableobject.getDataValueId())); if (watchableobject1 != null) { watchableobject1.setObject(watchableobject.getObject()); this.field_151511_a.func_145781_i(watchableobject.getDataValueId()); } } this.lock.writeLock().unlock(); this.objectChanged = true; } public boolean getIsBlank() { return this.isBlank; } public void func_111144_e() { this.objectChanged = false; } 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)); } public static class WatchableObject { private final int objectType; /** id of max 31 */ private final int dataValueId; private Object watchedObject; private boolean watched; private static final String __OBFID = "CL_00001560"; public WatchableObject(int p_i1603_1_, int p_i1603_2_, Object p_i1603_3_) { this.dataValueId = p_i1603_2_; this.watchedObject = p_i1603_3_; this.objectType = p_i1603_1_; this.watched = true; } public int getDataValueId() { return this.dataValueId; } public void setObject(Object p_75673_1_) { this.watchedObject = p_75673_1_; } public Object getObject() { return this.watchedObject; } public int getObjectType() { return this.objectType; } public boolean isWatched() { return this.watched; } public void setWatched(boolean p_75671_1_) { this.watched = p_75671_1_; } } }