| package protocolsupport.protocol.serializer; |
| |
| import java.text.MessageFormat; |
| import java.util.function.Supplier; |
| |
| 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.NetworkEntityMetadataObjectRegistry; |
| import protocolsupport.protocol.types.networkentity.metadata.ReadableNetworkEntityMetadataObject; |
| 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.NetworkEntityMetadataObjectNBTTagCompound; |
| 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 DataWatcherSerializer { |
| |
| //while meta indexes can be now up to 255, we actually use up to 31 |
| public static final int MAX_USED_META_INDEX = 31; |
| |
| @SuppressWarnings("unchecked") |
| protected static final Supplier<? extends ReadableNetworkEntityMetadataObject<?>>[] registry = new Supplier[256]; |
| static { |
| register(NetworkEntityMetadataObjectByte::new); |
| register(NetworkEntityMetadataObjectVarInt::new); |
| register(NetworkEntityMetadataObjectFloat::new); |
| register(NetworkEntityMetadataObjectString::new); |
| register(NetworkEntityMetadataObjectChat::new); |
| register(NetworkEntityMetadataObjectOptionalChat::new); |
| register(NetworkEntityMetadataObjectItemStack::new); |
| register(NetworkEntityMetadataObjectBoolean::new); |
| register(NetworkEntityMetadataObjectVector3f::new); |
| register(NetworkEntityMetadataObjectPosition::new); |
| register(NetworkEntityMetadataObjectOptionalPosition::new); |
| register(NetworkEntityMetadataObjectDirection::new); |
| register(NetworkEntityMetadataObjectOptionalUUID::new); |
| register(NetworkEntityMetadataObjectBlockData::new); |
| register(NetworkEntityMetadataObjectNBTTagCompound::new); |
| register(NetworkEntityMetadataObjectParticle::new); |
| register(NetworkEntityMetadataObjectVillagerData::new); |
| register(NetworkEntityMetadataObjectOptionalVarInt::new); |
| register(NetworkEntityMetadataObjectEntityPose::new); |
| } |
| |
| protected static void register(Supplier<? extends ReadableNetworkEntityMetadataObject<?>> supplier) { |
| registry[NetworkEntityMetadataObjectRegistry.getTypeId(supplier.get().getClass(), ProtocolVersionsHelper.LATEST_PC)] = supplier; |
| } |
| |
| public static void readDataTo(ByteBuf from, ArrayMap<NetworkEntityMetadataObject<?>> to) { |
| do { |
| int key = from.readUnsignedByte(); |
| if (key == 0xFF) { |
| break; |
| } |
| int type = from.readUnsignedByte(); |
| try { |
| ReadableNetworkEntityMetadataObject<?> object = registry[type].get(); |
| object.readFromStream(from); |
| to.put(key, object); |
| } 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, ArrayMap<NetworkEntityMetadataObject<?>> objects) { |
| boolean hadObject = false; |
| for (int key = objects.getMinKey(); key < objects.getMaxKey(); key++) { |
| NetworkEntityMetadataObject<?> object = objects.get(key); |
| if (object != null) { |
| hadObject = true; |
| to.writeByte(key); |
| to.writeByte(NetworkEntityMetadataObjectRegistry.getTypeId(object, version)); |
| object.writeToStream(to, version, locale); |
| } |
| } |
| if (!hadObject) { |
| to.writeByte(31); |
| to.writeByte(0); |
| to.writeByte(0); |
| } |
| to.writeByte(0xFF); |
| } |
| |
| public static void writeLegacyData(ByteBuf to, ProtocolVersion version, String locale, ArrayMap<NetworkEntityMetadataObject<?>> objects) { |
| boolean hadObject = false; |
| for (int key = objects.getMinKey(); key < objects.getMaxKey(); key++) { |
| NetworkEntityMetadataObject<?> object = objects.get(key); |
| if (object != null) { |
| hadObject = true; |
| int tk = ((NetworkEntityMetadataObjectRegistry.getTypeId(object, version) << 5) | (key & 0x1F)) & 0xFF; |
| to.writeByte(tk); |
| object.writeToStream(to, version, locale); |
| } |
| } |
| if (!hadObject) { |
| to.writeByte(31); |
| to.writeByte(0); |
| } |
| to.writeByte(127); |
| } |
| |
| } |