Uploaded image for project: 'Minecraft Launcher'
  1. Minecraft Launcher
  2. MCL-8475

Launcher incorrectly serializes version data

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Won't Fix
    • None
    • 1.6.76 (java)
    • None
    • Confirmed

      The bug

      The Java launcher incorrectly serializes version data of the new format. This prevents playing versions which use the new version file format in offline mode.

      How to reproduce

      1. Start a Minecraft version higher than or equal to 17w43b
      2. Look in the Launcher Log tab of your launcher
        → The following error was logged
        [19:16:51 INFO]: Refreshing local version list...
        [19:16:51 ERROR]: Couldn't load local version .minecraft\versions\17w43b\17w43b.json
        java.lang.NullPointerException
        	at net.minecraft.launcher.updater.Argument$Serializer.deserialize(Argument.java:56) ~[launcher.jar:1.6.84-j]
        	at net.minecraft.launcher.updater.Argument$Serializer.deserialize(Argument.java:46) ~[launcher.jar:1.6.84-j]
        	at com.google.gson.TreeTypeAdapter.read(TreeTypeAdapter.java:58) ~[launcher.jar:1.6.84-j]
        	at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40) ~[launcher.jar:1.6.84-j]
        	at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:81) ~[launcher.jar:1.6.84-j]
        	at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60) ~[launcher.jar:1.6.84-j]
        	at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40) ~[launcher.jar:1.6.84-j]
        	at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:187) ~[launcher.jar:1.6.84-j]
        	at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145) ~[launcher.jar:1.6.84-j]
        	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93) ~[launcher.jar:1.6.84-j]
        	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172) ~[launcher.jar:1.6.84-j]
        	at com.google.gson.Gson.fromJson(Gson.java:803) ~[launcher.jar:1.6.84-j]
        	at com.google.gson.Gson.fromJson(Gson.java:768) ~[launcher.jar:1.6.84-j]
        	at com.google.gson.Gson.fromJson(Gson.java:717) ~[launcher.jar:1.6.84-j]
        	at com.google.gson.Gson.fromJson(Gson.java:689) ~[launcher.jar:1.6.84-j]
        	at net.minecraft.launcher.updater.LocalVersionList.refreshVersions(LocalVersionList.java:46) [launcher.jar:1.6.84-j]
        	at net.minecraft.launcher.updater.MinecraftVersionManager.refreshVersions(MinecraftVersionManager.java:60) [launcher.jar:1.6.84-j]
        	at net.minecraft.launcher.Launcher$3.run(Launcher.java:184) [launcher.jar:1.6.84-j]
        	at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_151]
        	at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_151]
        	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:1.8.0_151]
        	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:1.8.0_151]
        	at java.lang.Thread.run(Unknown Source) [?:1.8.0_151]
        

      Code analysis

      The problem is caused by the class net.minecraft.launcher.updater.Argument. This class is missing a proper serializer and therefore when called by net.minecraft.launcher.updater.VersionList.serializeVersion(CompleteVersion) all fields are serialized. This causes two problems:

      • Deserializing requires a key value, but the field is called values
      • For rules the key rules is expected, but the field is called compatibilityRules

      The following is rough implementation added to the class net.minecraft.launcher.updater.Argument.Serializer after having it implement com.google.gson.JsonSerializer<Argument> as well. Please verify that this works as expected and does not miss any corner case before implementing it.

      @Override
      public JsonElement serialize(Argument argument, Type type, JsonSerializationContext serializationContext) {
          if (argument.values.length == 0) {
              throw new IllegalStateException("Don't know how to serialize Argument with no values");
          }
          else if (argument.values.length == 1 && (argument.compatibilityRules == null || argument.compatibilityRules.isEmpty())) {
              return new JsonPrimitive(argument.values[0]);
          }
          else {
              JsonObject argumentObject = new JsonObject();
              
              if (argument.values.length == 1) {
                  argumentObject.addProperty("value", argument.values[0]);
              }
              else {
                  argumentObject.add("value", serializationContext.serialize(argument.values));
              }
              
              if (!(argument.compatibilityRules == null || argument.compatibilityRules.isEmpty())) {
                  argumentObject.add("rules", serializationContext.serialize(argument.compatibilityRules, new TypeToken<ArrayList<CompatibilityRule>>(){}.getType()));
              }
              
              return argumentObject;
          }
      }
      

      Affected versions

      Currently tracked here since selectable launcher versions here in Mojira are not always up to date

      • 1.6.84-j

            Unassigned Unassigned
            marcono1234 Marcono1234
            Votes:
            5 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved:
              CHK: