package game.entity; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import game.item.ItemStack; import game.network.PacketBuffer; import game.world.BlockPos; public class DataWatcher { private static final Map, Integer> dataTypes = Maps., Integer>newHashMap(); private final Entity owner; private final Map objects = Maps.newHashMap(); private final ReadWriteLock lock = new ReentrantReadWriteLock(); private boolean blank = true; private boolean changed; public DataWatcher(Entity owner) { this.owner = owner; } public void addObject(int id, T object) { Integer integer = (Integer)dataTypes.get(object.getClass()); if(integer == null) { throw new IllegalArgumentException("Unknown data type: " + object.getClass()); } else if(id > 31) { throw new IllegalArgumentException("Data value id is too big with " + id + "! (Max is " + 31 + ")"); } else if(this.objects.containsKey(Integer.valueOf(id))) { throw new IllegalArgumentException("Duplicate id value for " + id + "!"); } else { DataWatcher.WatchableObject datawatcher$watchableobject = new DataWatcher.WatchableObject(integer.intValue(), id, object); this.lock.writeLock().lock(); this.objects.put(Integer.valueOf(id), datawatcher$watchableobject); this.lock.writeLock().unlock(); this.blank = false; } } public void addObjectByDataType(int id, int type) { DataWatcher.WatchableObject datawatcher$watchableobject = new DataWatcher.WatchableObject(type, id, (Object)null); this.lock.writeLock().lock(); this.objects.put(Integer.valueOf(id), datawatcher$watchableobject); this.lock.writeLock().unlock(); this.blank = false; } public byte getWatchableObjectByte(int id) { return ((Byte)this.getWatchedObject(id).getObject()).byteValue(); } public short getWatchableObjectShort(int id) { return ((Short)this.getWatchedObject(id).getObject()).shortValue(); } public int getWatchableObjectInt(int id) { return ((Integer)this.getWatchedObject(id).getObject()).intValue(); } public float getWatchableObjectFloat(int id) { return ((Float)this.getWatchedObject(id).getObject()).floatValue(); } public String getWatchableObjectString(int id) { return (String)this.getWatchedObject(id).getObject(); } public ItemStack getWatchableObjectItemStack(int id) { return (ItemStack)this.getWatchedObject(id).getObject(); } private DataWatcher.WatchableObject getWatchedObject(int id) { this.lock.readLock().lock(); DataWatcher.WatchableObject datawatcher$watchableobject = (DataWatcher.WatchableObject)this.objects.get(Integer.valueOf(id)); this.lock.readLock().unlock(); return datawatcher$watchableobject; } // public Rotations getWatchableObjectRotations(int id) { // return (Rotations)this.getWatchedObject(id).getObject(); // } public void updateObject(int id, T newData) { DataWatcher.WatchableObject datawatcher$watchableobject = this.getWatchedObject(id); if(!(newData == datawatcher$watchableobject.getObject() || (newData != null && datawatcher$watchableobject.getObject() != null ? newData.equals(datawatcher$watchableobject.getObject()) : false))) { datawatcher$watchableobject.setObject(newData); this.owner.onDataWatcherUpdate(id); datawatcher$watchableobject.setWatched(true); this.changed = true; } } public void setObjectWatched(int id) { this.getWatchedObject(id).watched = true; this.changed = true; } public boolean hasObjectChanged() { return this.changed; } public static void writeWatchedListToPacketBuffer(List objectsList, PacketBuffer buffer) throws IOException { if(objectsList != null) { for(DataWatcher.WatchableObject datawatcher$watchableobject : objectsList) { writeWatchableObjectToPacketBuffer(buffer, datawatcher$watchableobject); } } buffer.writeByte(127); } public List getChanged() { List list = null; if(this.changed) { this.lock.readLock().lock(); for(DataWatcher.WatchableObject datawatcher$watchableobject : this.objects.values()) { if(datawatcher$watchableobject.isWatched()) { datawatcher$watchableobject.setWatched(false); if(list == null) { list = Lists.newArrayList(); } list.add(datawatcher$watchableobject); } } this.lock.readLock().unlock(); } this.changed = false; return list; } public void writeTo(PacketBuffer buffer) throws IOException { this.lock.readLock().lock(); for(DataWatcher.WatchableObject datawatcher$watchableobject : this.objects.values()) { writeWatchableObjectToPacketBuffer(buffer, datawatcher$watchableobject); } this.lock.readLock().unlock(); buffer.writeByte(127); } public List getAllWatched() { List list = null; this.lock.readLock().lock(); for(DataWatcher.WatchableObject datawatcher$watchableobject : this.objects.values()) { if(list == null) { list = Lists.newArrayList(); } list.add(datawatcher$watchableobject); } this.lock.readLock().unlock(); return list; } private static void writeWatchableObjectToPacketBuffer(PacketBuffer buffer, DataWatcher.WatchableObject object) throws IOException { int i = (object.getObjectType() << 5 | object.getDataValueId() & 31) & 255; buffer.writeByte(i); switch(object.getObjectType()) { case 0: buffer.writeByte(((Byte)object.getObject()).byteValue()); break; case 1: buffer.writeShort(((Short)object.getObject()).shortValue()); break; case 2: buffer.writeInt(((Integer)object.getObject()).intValue()); break; case 3: buffer.writeFloat(((Float)object.getObject()).floatValue()); break; case 4: buffer.writeString((String)object.getObject()); break; case 5: ItemStack itemstack = (ItemStack)object.getObject(); buffer.writeItemStackToBuffer(itemstack); break; case 6: BlockPos blockpos = (BlockPos)object.getObject(); buffer.writeInt(blockpos.getX()); buffer.writeInt(blockpos.getY()); buffer.writeInt(blockpos.getZ()); // break; // // case 7: // Rotations rotations = (Rotations)object.getObject(); // buffer.writeFloat(rotations.getX()); // buffer.writeFloat(rotations.getY()); // buffer.writeFloat(rotations.getZ()); } } public static List readWatchedListFromPacketBuffer(PacketBuffer buffer) throws IOException { List list = null; for(int i = buffer.readByte(); i != 127; i = buffer.readByte()) { if(list == null) { list = Lists.newArrayList(); } int j = (i & 224) >> 5; int k = i & 31; DataWatcher.WatchableObject datawatcher$watchableobject = null; switch(j) { case 0: datawatcher$watchableobject = new DataWatcher.WatchableObject(j, k, Byte.valueOf(buffer.readByte())); break; case 1: datawatcher$watchableobject = new DataWatcher.WatchableObject(j, k, Short.valueOf(buffer.readShort())); break; case 2: datawatcher$watchableobject = new DataWatcher.WatchableObject(j, k, Integer.valueOf(buffer.readInt())); break; case 3: datawatcher$watchableobject = new DataWatcher.WatchableObject(j, k, Float.valueOf(buffer.readFloat())); break; case 4: datawatcher$watchableobject = new DataWatcher.WatchableObject(j, k, buffer.readStringFromBuffer(32767)); break; case 5: datawatcher$watchableobject = new DataWatcher.WatchableObject(j, k, buffer.readItemStackFromBuffer()); break; case 6: int l = buffer.readInt(); int i1 = buffer.readInt(); int j1 = buffer.readInt(); datawatcher$watchableobject = new DataWatcher.WatchableObject(j, k, new BlockPos(l, i1, j1)); // break; // // case 7: // float f = buffer.readFloat(); // float f1 = buffer.readFloat(); // float f2 = buffer.readFloat(); // datawatcher$watchableobject = new DataWatcher.WatchableObject(j, k, new Rotations(f, f1, f2)); } list.add(datawatcher$watchableobject); } return list; } public void updateWatchedObjectsFromList(List p_75687_1_) { this.lock.writeLock().lock(); for(DataWatcher.WatchableObject datawatcher$watchableobject : p_75687_1_) { DataWatcher.WatchableObject datawatcher$watchableobject1 = (DataWatcher.WatchableObject)this.objects .get(Integer.valueOf(datawatcher$watchableobject.getDataValueId())); if(datawatcher$watchableobject1 != null) { datawatcher$watchableobject1.setObject(datawatcher$watchableobject.getObject()); this.owner.onDataWatcherUpdate(datawatcher$watchableobject.getDataValueId()); } } this.lock.writeLock().unlock(); this.changed = true; } public boolean isBlank() { return this.blank; } public void markUnchanged() { this.changed = 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(BlockPos.class, Integer.valueOf(6)); // dataTypes.put(Rotations.class, Integer.valueOf(7)); } public static class WatchableObject { private final int objectType; private final int dataValueId; private Object watchedObject; private boolean watched; public WatchableObject(int type, int id, Object object) { this.dataValueId = id; this.watchedObject = object; this.objectType = type; this.watched = true; } public int getDataValueId() { return this.dataValueId; } public void setObject(Object object) { this.watchedObject = object; } public Object getObject() { return this.watchedObject; } public int getObjectType() { return this.objectType; } public boolean isWatched() { return this.watched; } public void setWatched(boolean watched) { this.watched = watched; } } }