blob: a4ed9dd51425227c53ee8fc23022649c8fdce05a [file] [log] [blame] [raw]
package protocolsupport.protocol.serializer;
import java.text.MessageFormat;
import java.util.Arrays;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.DecoderException;
import protocolsupport.api.ProtocolVersion;
import protocolsupport.protocol.types.networkentity.metadata.NetworkEntityMetadataObject;
import protocolsupport.protocol.types.networkentity.metadata.NetworkEntityMetadataObjectDeserializer;
import protocolsupport.protocol.types.networkentity.metadata.NetworkEntityMetadataObjectRegistry;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectBlockData;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectBoolean;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectByte;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectChat;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectDirection;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectEntityPose;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectFloat;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectItemStack;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectNBT;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectOptionalChat;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectOptionalPosition;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectOptionalUUID;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectOptionalVarInt;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectParticle;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectPosition;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectString;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectVarInt;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectVector3f;
import protocolsupport.protocol.types.networkentity.metadata.objects.NetworkEntityMetadataObjectVillagerData;
import protocolsupport.protocol.utils.ProtocolVersionsHelper;
import protocolsupport.utils.CollectionsUtils.ArrayMap;
public class NetworkEntityMetadataSerializer {
private NetworkEntityMetadataSerializer() {
}
@SuppressWarnings("unchecked")
private static final NetworkEntityMetadataObjectDeserializer<NetworkEntityMetadataObject<?>>[] registry = new NetworkEntityMetadataObjectDeserializer[256];
static {
register(NetworkEntityMetadataObjectByte.class, NetworkEntityMetadataObjectDeserializer.BYTE);
register(NetworkEntityMetadataObjectVarInt.class, NetworkEntityMetadataObjectDeserializer.VARINT);
register(NetworkEntityMetadataObjectFloat.class, NetworkEntityMetadataObjectDeserializer.FLOAT);
register(NetworkEntityMetadataObjectString.class, NetworkEntityMetadataObjectDeserializer.STRING);
register(NetworkEntityMetadataObjectChat.class, NetworkEntityMetadataObjectDeserializer.CHAT);
register(NetworkEntityMetadataObjectOptionalChat.class, NetworkEntityMetadataObjectDeserializer.OPT_CHAT);
register(NetworkEntityMetadataObjectItemStack.class, NetworkEntityMetadataObjectDeserializer.ITEMSTACK);
register(NetworkEntityMetadataObjectBoolean.class, NetworkEntityMetadataObjectDeserializer.BOOLEAN);
register(NetworkEntityMetadataObjectVector3f.class, NetworkEntityMetadataObjectDeserializer.VECTOR3F);
register(NetworkEntityMetadataObjectPosition.class, NetworkEntityMetadataObjectDeserializer.POSITION);
register(NetworkEntityMetadataObjectOptionalPosition.class, NetworkEntityMetadataObjectDeserializer.OPT_POSITION);
register(NetworkEntityMetadataObjectDirection.class, NetworkEntityMetadataObjectDeserializer.DIRECTION);
register(NetworkEntityMetadataObjectOptionalUUID.class, NetworkEntityMetadataObjectDeserializer.OPT_UUID);
register(NetworkEntityMetadataObjectBlockData.class, NetworkEntityMetadataObjectDeserializer.BLOCKDATA);
register(NetworkEntityMetadataObjectNBT.class, NetworkEntityMetadataObjectDeserializer.NBT);
register(NetworkEntityMetadataObjectParticle.class, NetworkEntityMetadataObjectDeserializer.PARTICLE);
register(NetworkEntityMetadataObjectVillagerData.class, NetworkEntityMetadataObjectDeserializer.VILLAGER_DATA);
register(NetworkEntityMetadataObjectOptionalVarInt.class, NetworkEntityMetadataObjectDeserializer.OPT_VARINT);
register(NetworkEntityMetadataObjectEntityPose.class, NetworkEntityMetadataObjectDeserializer.ENTITY_POSE);
}
@SuppressWarnings("unchecked")
private static <T extends NetworkEntityMetadataObject<?>> void register(Class<T> clazz, NetworkEntityMetadataObjectDeserializer<T> deserializer) {
registry[NetworkEntityMetadataObjectRegistry.getTypeId(clazz, ProtocolVersionsHelper.LATEST_PC)] = (NetworkEntityMetadataObjectDeserializer<NetworkEntityMetadataObject<?>>) deserializer;
}
public static void readDataTo(ByteBuf from, ArrayMap<NetworkEntityMetadataObject<?>> to) {
do {
int key = from.readUnsignedByte();
if (key == 0xFF) {
break;
}
int type = from.readUnsignedByte();
try {
to.put(key, registry[type].read(from));
} catch (Exception e) {
throw new DecoderException(MessageFormat.format("Unable to decode datawatcher object (type: {0}, index: {1})", type, key), e);
}
} while (true);
}
public static void writeData(ByteBuf to, ProtocolVersion version, String locale, NetworkEntityMetadataList objects) {
if (objects.getSize() > 0) {
for (int index = 0; index < objects.getSize(); index++) {
NetworkEntityMetadataList.Entry entry = objects.get(index);
NetworkEntityMetadataObject<?> object = entry.getObject();
to.writeByte(entry.getObjectIndex());
to.writeByte(NetworkEntityMetadataObjectRegistry.getTypeId(object, version));
object.writeToStream(to, version, locale);
}
} else {
to.writeByte(31);
to.writeByte(0);
to.writeByte(0);
}
to.writeByte(0xFF);
}
public static void writeLegacyData(ByteBuf to, ProtocolVersion version, String locale, NetworkEntityMetadataList objects) {
if (objects.getSize() > 0) {
for (int index = 0; index < objects.getSize(); index++) {
NetworkEntityMetadataList.Entry entry = objects.get(index);
NetworkEntityMetadataObject<?> object = entry.getObject();
int tk = ((NetworkEntityMetadataObjectRegistry.getTypeId(object, version) << 5) | (entry.getObjectIndex() & 0x1F)) & 0xFF;
to.writeByte(tk);
object.writeToStream(to, version, locale);
}
} else {
to.writeByte(31);
to.writeByte(0);
}
to.writeByte(127);
}
public static class NetworkEntityMetadataList {
public static final NetworkEntityMetadataList EMPTY = new NetworkEntityMetadataList() {
@Override
public int getSize() {
return 0;
}
@Override
public Entry get(int index) {
throw new IllegalArgumentException("Invalid index");
}
@Override
public void add(int index, NetworkEntityMetadataObject<?> object) {
}
@Override
public void clear() {
}
};
protected Entry[] array = new Entry[16];
protected int size;
public int getSize() {
return size;
}
public void clear() {
size = 0;
}
public Entry get(int index) {
if ((index >= 0) && (index < size)) {
return array[index];
}
throw new IllegalArgumentException("Invalid index");
}
public void add(int index, NetworkEntityMetadataObject<?> object) {
if (size >= array.length) {
array = Arrays.copyOfRange(array, 0, array.length * 2);
}
Entry entry = array[size];
if (entry != null) {
entry.set(index, object);
} else {
array[size] = new Entry(index, object);
}
size++;
}
public static class Entry {
protected int index;
protected NetworkEntityMetadataObject<?> object;
protected Entry(int index, NetworkEntityMetadataObject<?> object) {
set(index, object);
}
protected void set(int index, NetworkEntityMetadataObject<?> object) {
this.index = index;
this.object = object;
}
public int getObjectIndex() {
return index;
}
public NetworkEntityMetadataObject<?> getObject() {
return object;
}
}
}
}