@WorkInProgress public abstract class DynamicPacket<R extends GenericInterface<?>> extends BidirectionalEventPacket { private Class<R> packetClass; public DynamicPacket(FriendlyByteBuf buffer) { super(buffer); } public DynamicPacket(R generic, @Nullable PacketData<?>... sourceData) { super(null, -1, sourceData); this.packetClass = (Class<R>) generic.getClass(); InsightAPI.INTERFACE_REF.registerHandler(generic.getClass(), generic); } @Override public void decode(FriendlyByteBuf buffer) { try { this.packetClass = (Class<R>) Class.forName(buffer.readUtf()); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } int size = buffer.readInt(); this.readData = new Object[size]; if (size > 0) { SerializerFactory.BuiltInFactory factory = SerializerRegistry.getFactory(); for (int i = 0; i < size; i++) { boolean flag = buffer.readBoolean(); int serializerId = buffer.readInt(); if (serializerId != -1) { DataSerializer<?> serializer = null; if (flag) { for (Integer enumId : factory.getEnumSerializers().inverse().values()) { if (enumId == serializerId) { serializer = factory.getEnumSerializer(enumId); break; } } } else { serializer = factory.getSerializer(serializerId); } if (serializer != null) { Object fromBuffer = serializer.readFromBuffer(buffer); readData[i] = fromBuffer; } } } } } @Override public void encode(FriendlyByteBuf buffer) { buffer.writeUtf(packetClass.getName()); PacketData<?>[] sourceData = this.getSourceData(); if (sourceData == null) { buffer.writeInt(0); // Prevent for null objects } else { boolean enumFlag = false; SerializerFactory.BuiltInFactory builtInFactory = SerializerRegistry.getFactory(); buffer.writeInt(sourceData.length); for (PacketData<?> object : sourceData) { if (object != null) { DataSerializer<?> serializer = object.getSerializer(); int serializerId; if (EnumSerializer.class.isAssignableFrom(serializer.getClass())) { enumFlag = true; serializerId = builtInFactory.getEnumSerializerId(((EnumSerializer<?>) serializer)); } else { serializerId = builtInFactory.getSerializerId(serializer); } buffer.writeBoolean(enumFlag); buffer.writeInt(serializerId); object.encode(buffer); } else { buffer.writeInt(-1); } } } } public abstract void compile(Method method, Object... data); @Override protected void onHandle(Identifiable holderKey, Level level, Player player) { super.onHandle(holderKey, level, player); Method handler = InsightAPI.INTERFACE_REF.getHandler(packetClass); if (handler != null) { // Object invoke = handler.invoke(handler.getDeclaringClass().newInstance(), getReadData()); this.compile(handler, getReadData()); } else { throw new IllegalArgumentException("No handler found for packet: " + packetClass.getName()); } } }