Quilted Fabric API (QFAPI) / Quilt Standard Libraries (QSL)

Quilted Fabric API (QFAPI) / Quilt Standard Libraries (QSL)

525k Downloads

QSL breaks the new multiconnect beta.

Earthcomputer opened this issue · 5 comments

commented

Steps to reproduce:

  • Download the latest multiconnect beta.
  • Run 1.18.2 with multiconnect alongside Quilted Fabric API.
  • Join a server, any server version between 1.13 and 1.18.1 (not 1.18.2) should work.
  • Observe stack trace in logs:
java.lang.ExceptionInInitializerError: null
	at net.earthcomputer.multiconnect.packets.latest.SPacketSynchronizeTags_Latest.doFixTags(SPacketSynchronizeTags_Latest.java:123) ~[multiconnect-1.6-beta.5.jar:?]
	at net.earthcomputer.multiconnect.packets.latest.SPacketSynchronizeTags_Latest$BlockGroup.fixTags(SPacketSynchronizeTags_Latest.java:64) ~[multiconnect-1.6-beta.5.jar:?]
	at net.earthcomputer.multiconnect.generated.Protocol_1_12_2.translateExplicitSPacketSynchronizeTags_1_13_2393(Protocol_1_12_2.java:26819) ~[multiconnect-1.6-beta.5-generated.jar-e9802889-1e90-4daa-b15e-76d47ce06062-nested.jar:?]
	at net.earthcomputer.multiconnect.generated.Protocol_1_12_2.translateSPacketGameJoin_1_12_2(Protocol_1_12_2.java:33775) ~[multiconnect-1.6-beta.5-generated.jar-e9802889-1e90-4daa-b15e-76d47ce06062-nested.jar:?]
	at net.earthcomputer.multiconnect.protocols.generic.MulticonnectClientboundTranslator.lambda$decode$0(MulticonnectClientboundTranslator.java:38) ~[multiconnect-1.6-beta.5.jar:?]
	at net.earthcomputer.multiconnect.impl.DebugUtils.wrapInErrorHandler(DebugUtils.java:206) ~[multiconnect-1.6-beta.5.jar:?]
	at net.earthcomputer.multiconnect.protocols.generic.MulticonnectClientboundTranslator.lambda$decode$1(MulticonnectClientboundTranslator.java:37) ~[multiconnect-1.6-beta.5.jar:?]
	at net.earthcomputer.multiconnect.impl.PacketSystem$Internals.submitTranslationTask(PacketSystem.java:249) ~[multiconnect-1.6-beta.5.jar:?]
	at net.earthcomputer.multiconnect.protocols.generic.MulticonnectClientboundTranslator.lambda$decode$3(MulticonnectClientboundTranslator.java:36) ~[multiconnect-1.6-beta.5.jar:?]
	at net.earthcomputer.multiconnect.impl.DebugUtils.wrapInErrorHandler(DebugUtils.java:206) ~[multiconnect-1.6-beta.5.jar:?]
	at net.earthcomputer.multiconnect.protocols.generic.MulticonnectClientboundTranslator.decode(MulticonnectClientboundTranslator.java:30) ~[multiconnect-1.6-beta.5.jar:?]
	at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:507) ~[netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:446) ~[netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:311) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:432) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:795) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:480) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) [netty-all-4.1.68.Final.jar:4.1.68.Final]
	at java.lang.Thread.run(Thread.java:833) [?:?]
Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 4 column 6 path $.values[0]
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:226) ~[gson-2.8.9.jar:?]
	at net.minecraft.class_3518.method_15267(class_3518.java:503) ~[client-intermediary.jar:?]
	at net.minecraft.class_3518.method_15276(class_3518.java:542) ~[client-intermediary.jar:?]
	at net.earthcomputer.multiconnect.protocols.generic.TagLoader.lambda$loadTags$2(TagLoader.java:69) ~[multiconnect-1.6-beta.5.jar:?]
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[?:?]
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625) ~[?:?]
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[?:?]
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[?:?]
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) ~[?:?]
	at java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) ~[?:?]
	at java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) ~[?:?]
	at java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) ~[?:?]
	at java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) ~[?:?]
	at net.earthcomputer.multiconnect.protocols.generic.TagLoader.loadTags(TagLoader.java:77) ~[multiconnect-1.6-beta.5.jar:?]
	at net.earthcomputer.multiconnect.protocols.generic.TagLoader.<clinit>(TagLoader.java:116) ~[multiconnect-1.6-beta.5.jar:?]
	... 43 more
Caused by: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 4 column 6 path $.values[0]
	at com.google.gson.stream.JsonReader.nextString(JsonReader.java:824) ~[gson-2.8.9.jar:?]
	at com.google.gson.internal.bind.TypeAdapters$15.read(TypeAdapters.java:380) ~[gson-2.8.9.jar:?]
	at com.google.gson.internal.bind.TypeAdapters$15.read(TypeAdapters.java:368) ~[gson-2.8.9.jar:?]
	at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41) ~[gson-2.8.9.jar:?]
	at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82) ~[gson-2.8.9.jar:?]
	at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61) ~[gson-2.8.9.jar:?]
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131) ~[gson-2.8.9.jar:?]
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222) ~[gson-2.8.9.jar:?]
	at net.minecraft.class_3518.method_15267(class_3518.java:503) ~[client-intermediary.jar:?]
	at net.minecraft.class_3518.method_15276(class_3518.java:542) ~[client-intermediary.jar:?]
	at net.earthcomputer.multiconnect.protocols.generic.TagLoader.lambda$loadTags$2(TagLoader.java:69) ~[multiconnect-1.6-beta.5.jar:?]
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[?:?]
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625) ~[?:?]
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[?:?]
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[?:?]
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) ~[?:?]
	at java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) ~[?:?]
	at java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) ~[?:?]
	at java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) ~[?:?]
	at java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) ~[?:?]
	at net.earthcomputer.multiconnect.protocols.generic.TagLoader.loadTags(TagLoader.java:77) ~[multiconnect-1.6-beta.5.jar:?]
	at net.earthcomputer.multiconnect.protocols.generic.TagLoader.<clinit>(TagLoader.java:116) ~[multiconnect-1.6-beta.5.jar:?]
	... 43 more

The relevant class in multiconnect is TagLoader.

Everything works fine with Fabric API. Multiconnect does not depend on either Quilted Fabric API or Fabric API, although it does JiJ Fabric Resource Loader.

commented

On Discord it was mentioned that only the vanilla resources are needed, a much more reliable method to only get those is to directly use the Vanilla resource pack (QM names):

new DefaultResourcePack(VanillaDataPackProvider.DEFAULT_PACK_METADATA, "minecraft");

Mods may modify PackRepositories however they want, and make any assumption whether they are Vanilla or not harder to achieve, while an instantiation of the Vanilla pack only is more reliable on ensuring that contract.

commented

This is not a Quilted Fabric API bug. This is just multiconnect not respecting the tag JSON specification.

Here's a tag multiconnect crashed on (c:tags/blocks/ores.json):

{
  "replace": false,
  "values": [
    {
      "id": "#minecraft:redstone_ores",
      "required": false
    },
    {
      "id": "#minecraft:copper_ores",
      "required": false
    },
    {
      "id": "#minecraft:gold_ores",
      "required": false
    },
    {
      "id": "#minecraft:iron_ores",
      "required": false
    },
    {
      "id": "#minecraft:coal_ores",
      "required": false
    },
    {
      "id": "#minecraft:emerald_ores",
      "required": false
    },
    {
      "id": "#minecraft:lapis_ores",
      "required": false
    },
    {
      "id": "#minecraft:diamond_ores",
      "required": false
    },
    {
      "id": "#c:quartz_ores",
      "required": false
    }
  ]
}

Here's Multiconnect's Gson call: TagJson tagJson = GsonHelper.fromJson(GSON, reader, TagJson.class);

Here's the prototype of TagJson:

    private static class TagJson {
        private List<String> values;
    }

Gson sees a list of strings, and expects a list of strings, BUT minecraft allows you to specify an object instead, which allow to prevent errors if the element is absent from resolution.

Wait, why doesn't it happen with Fabric?

The answer is this:

    private static final ResourceManager DATA_LOADER = Util.make(() -> {
        PackRepository packRepo = new PackRepository(PackType.SERVER_DATA, new ServerPacksSource());
        packRepo.reload();
        packRepo.setSelected(Collections.singletonList("vanilla"));
        return new MultiPackResourceManager(PackType.SERVER_DATA, packRepo.openAllSelected());
    });

Fabric does not have the modded packs provided in the same pack as the Vanilla pack, meaning ServerPacksSource doesn't provide the modded packs, while QSL does.

commented

@Earthcomputer so...
Will you take a look now?

commented

The incompatibility megathread on the forum points to this issue saying a fix is coming on Quilt's end, but this issue is closed as not planned. Which is correct?

commented

The fix must come from Multiconnect's side, because the issue is a case of it relying on something that only works due to Fabric storing mod resources in a separate pack while Quilt stores it on the default pack; This is an architectural difference that we can't reasonably solve

(oh, and yes, the forum post needs to be updated)