BuilderCodec class

Пакет: com.hypixel.hytale.codec.builder

Файл: com/hypixel/hytale/codec/builder/BuilderCodec.java

implements: Codec<T>, DirectDecodeCodec<T>, RawJsonCodec<T>, InheritCodec<T>, ValidatableCodec<T>

Поля (30)

МодификаторыТипИмя
final int UNSET_VERSION
return
int var10
int var11
var11
var11
var11
int var12
var12
int var13
var13
var13
var13
int var15
var15
boolean var2
Object var2
var2
var2
ValidationResults var3
Object var3
BsonDocument var3
var3
Object var3
BsonDocument var4
BuilderField var6
BuilderField var6
String var6
BuilderField var6
BuilderField var7

Методы (41)

МодификаторыВозвратСигнатура
abstract throw new CodecExceptionthrow new CodecException("This BuilderCodec is for an abstract or direct codec. To use this codec you must specify an existing object to decode into.")
public void afterDecodevoid afterDecode(T var1, ExtraInfo var2)
public void afterDecodeAndValidatevoid afterDecodeAndValidate(T var1, @Nonnull ExtraInfo var2)
private boolean declaresVersionFieldboolean declaresVersionField()
protected void decode0void decode0(@Nonnull BsonDocument var1, T var2, ExtraInfo var3)
private void decodeJson0void decodeJson0(@Nonnull RawJsonReader var1, T var2, ExtraInfo var3)
for for(BuilderField var6 : var4)
for for(BuilderField var8 : var16)
for for(BuilderField var9 : var18)
for for(BuilderCodec var1 = this; var1 != null; var1 = var1.parentCodec)
public BiConsumer<T, ExtraInfo> getAfterDecodeBiConsumer<T, ExtraInfo> getAfterDecode()
public int getCodecVersionint getCodecVersion()
public T getDefaultValueT getDefaultValue()
public T getDefaultValueT getDefaultValue(ExtraInfo var1)
public String getDocumentationString getDocumentation()
public Class<T> getInnerClassClass<T> getInnerClass()
public Supplier<T> getSupplierSupplier<T> getSupplier()
if if(var1.codecVersion != Integer.MIN_VALUE)
if if(var1.minCodecVersion != Integer.MAX_VALUE)
if if(var10 != Integer.MIN_VALUE)
if if(this.parentCodec != null)
if if(this.parentCodec != null)
if if(var6 != null)
if if(this.parentCodec != null)
if if(this.afterDecode != null)
if if(this.parentCodec != null)
if if(this.afterDecode != null)
if if(this.hasNonNullValidator)
if if(var6 != null)
if if(this.validator != null)
if if(this.supplier == null)
if if(this.versioned)
if if(this.codecVersion != 0)
if if(this.versioned)
if if(var7 != null)
if if(this.parentCodec != null)
if if(var6 != null)
if if(this.supplier == null)
if if(this.versioned)
public void inheritvoid inherit(T var1, @Nonnull T var2, @Nonnull ExtraInfo var3)
while while(true)

Исходный код

Показать/скрыть
class="kw">package com.hypixel.hytale.codec.builder;

class="kw">import com.hypixel.hytale.codec.Codec;
class="kw">import com.hypixel.hytale.codec.DirectDecodeCodec;
class="kw">import com.hypixel.hytale.codec.EmptyExtraInfo;
class="kw">import com.hypixel.hytale.codec.ExtraInfo;
class="kw">import com.hypixel.hytale.codec.InheritCodec;
class="kw">import com.hypixel.hytale.codec.KeyedCodec;
class="kw">import com.hypixel.hytale.codec.RawJsonCodec;
class="kw">import com.hypixel.hytale.codec.VersionedExtraInfo;
class="kw">import com.hypixel.hytale.codec.exception.CodecException;
class="kw">import com.hypixel.hytale.codec.schema.SchemaContext;
class="kw">import com.hypixel.hytale.codec.schema.config.NullSchema;
class="kw">import com.hypixel.hytale.codec.schema.config.ObjectSchema;
class="kw">import com.hypixel.hytale.codec.schema.config.Schema;
class="kw">import com.hypixel.hytale.codec.schema.metadata.Metadata;
class="kw">import com.hypixel.hytale.codec.schema.metadata.ui.UIDisplayMode;
class="kw">import com.hypixel.hytale.codec.util.RawJsonReader;
class="kw">import com.hypixel.hytale.codec.validation.ValidatableCodec;
class="kw">import com.hypixel.hytale.codec.validation.ValidationResults;
class="kw">import com.hypixel.hytale.function.consumer.TriConsumer;
class="kw">import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectArrayList;
class="kw">import java.io.IOException;
class="kw">import java.util.Collections;
class="kw">import java.util.Comparator;
class="kw">import java.util.List;
class="kw">import java.util.Map;
class="kw">import java.util.Objects;
class="kw">import java.util.Set;
class="kw">import java.util.Map.Entry;
class="kw">import java.util.function.BiConsumer;
class="kw">import java.util.function.BiFunction;
class="kw">import java.util.function.Consumer;
class="kw">import java.util.function.Function;
class="kw">import java.util.function.Supplier;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">import org.bson.BsonDocument;
class="kw">import org.bson.BsonValue;

class="kw">public class BuilderCodec<T> class="kw">implements Codec<T>, DirectDecodeCodec<T>, RawJsonCodec<T>, InheritCodec<T>, ValidatableCodec<T> {
   class="kw">public class="kw">static class="kw">final int UNSET_VERSION = Integer.MIN_VALUE;
   class="kw">public class="kw">static class="kw">final int UNSET_MAX_VERSION = Integer.MAX_VALUE;
   class="kw">public class="kw">static class="kw">final int INITIAL_VERSION = 0;
   class="kw">public class="kw">static class="kw">final BuilderCodec<?>[] EMPTY_ARRAY = new BuilderCodec[0];
   class="kw">private class="kw">static class="kw">final KeyedCodec<Integer> VERSION = new KeyedCodec<>("Version", INTEGER);
   class="kw">private class="kw">static class="kw">final Map<String, BuilderCodec.EntryType> BASE_IGNORED_KEYS = Map.ofEntries(
      Map.entry("$Title", BuilderCodec.EntryType.IGNORE),
      Map.entry("$Comment", BuilderCodec.EntryType.IGNORE),
      Map.entry("$TODO", BuilderCodec.EntryType.IGNORE),
      Map.entry("$Author", BuilderCodec.EntryType.IGNORE),
      Map.entry("$Position", BuilderCodec.EntryType.IGNORE),
      Map.entry("$FloatingFunctionNodes", BuilderCodec.EntryType.IGNORE),
      Map.entry("$Groups", BuilderCodec.EntryType.IGNORE),
      Map.entry("$WorkspaceID", BuilderCodec.EntryType.IGNORE),
      Map.entry("$NodeEditorMetadata", BuilderCodec.EntryType.IGNORE),
      Map.entry("$NodeId", BuilderCodec.EntryType.IGNORE),
      Map.entry("Parent", BuilderCodec.EntryType.IGNORE_IN_BASE_OBJECT)
   );
   class="kw">protected class="kw">final Class<T> tClass;
   class="kw">protected class="kw">final Supplier<T> supplier;
   @Nullable
   class="kw">protected class="kw">final BuilderCodec<? super T> parentCodec;
   @Nonnull
   class="kw">protected class="kw">final Map<String, List<BuilderField<T, ?>>> entries;
   @Nonnull
   class="kw">protected class="kw">final Map<String, List<BuilderField<T, ?>>> unmodifiableEntries;
   class="kw">protected class="kw">final BiConsumer<T, ValidationResults> validator;
   class="kw">protected class="kw">final BiConsumer<T, ExtraInfo> afterDecode;
   class="kw">protected class="kw">final boolean hasNonNullValidator;
   class="kw">protected class="kw">final String documentation;
   class="kw">protected class="kw">final List<Metadata> metadata;
   class="kw">protected class="kw">final int codecVersion;
   class="kw">protected class="kw">final int minCodecVersion;
   class="kw">protected class="kw">final boolean versioned;
   @Deprecated
   class="kw">protected class="kw">final boolean useLegacyVersion;
   @Nonnull
   class="kw">protected class="kw">final StringTreeMap<BuilderCodec.KeyEntry<T>> stringTreeMap;

   class="kw">protected BuilderCodec(@Nonnull BuilderCodec.BuilderBase<T, ?> var1) {
      this.tClass = var1.tClass;
      this.supplier = var1.supplier;
      this.parentCodec = var1.parentCodec;
      this.entries = Objects.requireNonNull(var1.entries, "entries parameter can't be null");
      this.unmodifiableEntries = Collections.unmodifiableMap(var1.entries);
      this.stringTreeMap = var1.stringTreeMap;
      this.validator = var1.validator;
      this.afterDecode = var1.afterDecode;
      this.documentation = var1.documentation;
      this.metadata = var1.metadata;
      boolean var2 = false;

      for (List var4 : this.entries.values()) {
         var4.sort(Comparator.comparingInt(BuilderField::getMinVersion));

         for (BuilderField var6 : var4) {
            var2 |= var6.hasNonNullValidator();
         }
      }

      this.hasNonNullValidator = var2;
      int var11;
      if (var1.codecVersion != Integer.MIN_VALUE) {
         var11 = var1.codecVersion;
      } else {
         int var12 = Integer.MIN_VALUE;

         for (List var16 : this.entries.values()) {
            for (BuilderField var8 : var16) {
               var12 = Math.max(var12, var8.getHighestSupportedVersion());
            }
         }

         var11 = var12;
      }

      int var13;
      if (var1.minCodecVersion != Integer.MAX_VALUE) {
         var13 = var1.minCodecVersion;
      } else {
         int var15 = Integer.MAX_VALUE;

         for (List var18 : this.entries.values()) {
            for (BuilderField var9 : var18) {
               int var10 = var9.getMinVersion();
               if (var10 != Integer.MIN_VALUE) {
                  var15 = Math.min(var15, var10);
               }
            }
         }

         var13 = var15;
      }

      if (this.parentCodec != null) {
         var11 = Math.max(var11, this.parentCodec.codecVersion);
         var13 = Math.min(var13, this.parentCodec.minCodecVersion);
         this.versioned = var1.versioned || this.parentCodec.versioned;
         this.useLegacyVersion = var1.useLegacyVersion || this.parentCodec.useLegacyVersion;
      } else {
         this.versioned = var1.versioned;
         this.useLegacyVersion = var1.useLegacyVersion;
      }

      this.codecVersion = var11;
      this.minCodecVersion = var13;
      if (this.versioned && !this.declaresVersionField()) {
         this.stringTreeMap.put(VERSION.getKey(), new BuilderCodec.KeyEntry<>(BuilderCodec.EntryType.IGNORE));
      }
   }

   class="kw">private boolean declaresVersionField() {
      for (BuilderCodec var1 = this; var1 != null; var1 = var1.parentCodec) {
         if (var1.entries.containsKey(VERSION.getKey())) {
            class="kw">return true;
         }
      }

      class="kw">return false;
   }

   class="kw">public Class<T> getInnerClass() {
      class="kw">return this.tClass;
   }

   class="kw">public Supplier<T> getSupplier() {
      class="kw">return this.supplier;
   }

   class="kw">public T getDefaultValue() {
      class="kw">return this.getDefaultValue(EmptyExtraInfo.EMPTY);
   }

   class="kw">public T getDefaultValue(ExtraInfo var1) {
      Object var2 = this.supplier.get();
      this.afterDecode(var2, var1);
      class="kw">return var2;
   }

   @Nonnull
   class="kw">public Map<String, List<BuilderField<T, ?>>> getEntries() {
      class="kw">return this.unmodifiableEntries;
   }

   class="kw">public BiConsumer<T, ExtraInfo> getAfterDecode() {
      class="kw">return this.afterDecode;
   }

   @Nullable
   class="kw">public BuilderCodec<? super T> getParent() {
      class="kw">return this.parentCodec;
   }

   class="kw">public String getDocumentation() {
      class="kw">return this.documentation;
   }

   class="kw">public int getCodecVersion() {
      class="kw">return this.codecVersion;
   }

   class="kw">public void inherit(T var1, @Nonnull T var2, @Nonnull ExtraInfo var3) {
      if (this.parentCodec != null) {
         this.parentCodec.inherit(var1, var2, var3);
      }

      if (this.getInnerClass().isAssignableFrom(var2.getClass())) {
         for (List var5 : this.entries.values()) {
            BuilderField var6 = findField(var5, var3);
            if (var6 != null) {
               var6.inherit(var1, var2, var3);
            }
         }
      }
   }

   class="kw">public void afterDecode(T var1, ExtraInfo var2) {
      if (this.parentCodec != null) {
         this.parentCodec.afterDecode(var1, var2);
      }

      if (this.afterDecode != null) {
         this.afterDecode.accept(var1, var2);
      }
   }

   class="kw">public void afterDecodeAndValidate(T var1, @Nonnull ExtraInfo var2) {
      if (this.parentCodec != null) {
         this.parentCodec.afterDecodeAndValidate(var1, var2);
      }

      if (this.afterDecode != null) {
         this.afterDecode.accept(var1, var2);
      }

      ValidationResults var3 = var2.getValidationResults();
      if (this.hasNonNullValidator) {
         for (List var5 : this.entries.values()) {
            BuilderField var6 = findField(var5, var2);
            if (var6 != null) {
               var2.pushKey(var6.codec.getKey());

               try {
                  var6.nullValidate(var1, var3, var2);
               } class="kw">finally {
                  var2.popKey();
               }
            }
         }

         if (this.validator != null) {
            this.validator.accept(var1, var3);
         }

         var3._processValidationResults();
      } else if (this.validator != null) {
         this.validator.accept(var1, var3);
         var3._processValidationResults();
      }
   }

   @Override
   class="kw">public T decode(@Nonnull BsonValue var1, @Nonnull ExtraInfo var2) {
      if (this.supplier == null) {
         throw new CodecException("This BuilderCodec is for an class="kw">abstract or direct codec. To use this codec you must specify an existing object to decode into.");
      }

      Object var3 = this.supplier.get();
      this.decode(var1.asDocument(), var3, var2);
      class="kw">return var3;
   }

   @Nonnull
   class="kw">public BsonDocument encode(T var1, @Nonnull ExtraInfo var2) {
      BsonDocument var3 = new BsonDocument();
      if (this.versioned) {
         if (this.codecVersion != 0) {
            VERSION.put(var3, this.codecVersion, var2);
         }

         var2 = new VersionedExtraInfo(this.codecVersion, var2);
      }

      class="kw">return this.encode0(var1, var3, var2);
   }

   @Override
   class="kw">public void decode(@Nonnull BsonValue var1, T var2, @Nonnull ExtraInfo var3) {
      BsonDocument var4 = var1.asDocument();
      if (this.versioned) {
         var3 = this.decodeVersion(var4, var3);
      }

      this.decode0(var4, var2, var3);
      this.afterDecodeAndValidate(var2, var3);
   }

   class="kw">protected void decode0(@Nonnull BsonDocument var1, T var2, ExtraInfo var3) {
      for (Entry var5 : var1.entrySet()) {
         String var6 = var5.getKey();
         BuilderField var7 = findEntry(this, var6, var3);
         if (var7 != null) {
            var7.decode(var1, var2, var3);
         } else if (!this.isIgnoredKey(var6, var3)) {
            var3.addUnknownKey(var6);
         }
      }
   }

   @Nonnull
   class="kw">protected BsonDocument encode0(T var1, @Nonnull BsonDocument var2, @Nonnull ExtraInfo var3) {
      if (this.parentCodec != null) {
         this.parentCodec.encode0(var1, var2, var3);
      }

      for (List var5 : this.entries.values()) {
         BuilderField var6 = findField(var5, var3);
         if (var6 != null) {
            var6.encode(var2, var1, var3);
         }
      }

      class="kw">return var2;
   }

   @Override
   class="kw">public T decodeJson(@Nonnull RawJsonReader var1, @Nonnull ExtraInfo var2) class="kw">throws IOException {
      if (this.supplier == null) {
         throw new CodecException("This BuilderCodec is for an class="kw">abstract or direct codec. To use this codec you must specify an existing object to decode into.");
      }

      Object var3 = this.supplier.get();
      if (this.versioned) {
         var2 = this.decodeVersion(var1, var2);
      }

      this.decodeJson0(var1, var3, var2);
      this.afterDecodeAndValidate(var3, var2);
      class="kw">return var3;
   }

   class="kw">private void decodeJson0(@Nonnull RawJsonReader var1, T var2, ExtraInfo var3) class="kw">throws IOException {
      var1.expect('{');
      var1.consumeWhiteSpace();
      if (!var1.tryConsume('}')) {
         while (true) {
            this.readEntry(var1, var2, var3);
            var1.consumeWhiteSpace();
            if (var1.tryConsumeOrExpect('}', ',')) {
               class="kw">return;
            }

            var1.consumeWhiteSpace();
         }
      }
   }

   class="kw">protected void readEntry(@Nonnull RawJsonReader var1, T var2, @Nonnull ExtraInfo var3) class="kw">throws IOException {
      var1.mark();
      StringTreeMap var4 = this.stringTreeMap.findEntry(var1);
      BuilderCodec.KeyEntry var5;
      if (var4 != null && (var5 = var4.getValue()) != null) {
         class="kw">switch (var5.getType()) {
            case FIELD:
               String var6 = var4.getKey();
               List var7 = var5.getFields();
               this.readField(var1, var2, var3, var6, var7);
               break;
            case IGNORE:
               var1.unmark();
               this.skipField(var1);
               break;
            case IGNORE_IN_BASE_OBJECT:
               if (var3.getKeysSize() == 0) {
                  var1.unmark();
                  this.skipField(var1);
               } else {
                  var1.reset();
                  this.readUnknownField(var1, var3);
               }
         }
      } else {
         var1.reset();
         this.readUnknownField(var1, var3);
      }
   }

   class="kw">private void skipField(@Nonnull RawJsonReader var1) class="kw">throws IOException {
      var1.consumeWhiteSpace();
      var1.expect(':');
      var1.consumeWhiteSpace();
      var1.skipValue();
   }

   class="kw">private void readField(@Nonnull RawJsonReader var1, T var2, @Nonnull ExtraInfo var3, String var4, @Nonnull List<BuilderField<T, ?>> var5) class="kw">throws IOException {
      BuilderField var6 = null;

      for (BuilderField var8 : var5) {
         if (var8.supportsVersion(var3.getVersion())) {
            var6 = var8;
            break;
         }
      }

      if (var6 == null) {
         var1.reset();
         this.readUnknownField(var1, var3);
      } else {
         var1.unmark();
         var1.consumeWhiteSpace();
         var1.expect(':');
         var1.consumeWhiteSpace();
         var3.pushKey(var4, var1);

         try {
            var6.decodeJson(var1, var2, var3);
         } catch (Exception var12) {
            throw new CodecException("Failed to decode", var1, var3, var12);
         } class="kw">finally {
            var3.popKey();
         }
      }
   }

   class="kw">private void readUnknownField(@Nonnull RawJsonReader var1, @Nonnull ExtraInfo var2) class="kw">throws IOException {
      var2.readUnknownKey(var1);
      var1.consumeWhiteSpace();
      var1.expect(':');
      var1.consumeWhiteSpace();
      var1.skipValue();
   }

   class="kw">public void decodeJson(@Nonnull RawJsonReader var1, T var2, @Nonnull ExtraInfo var3) class="kw">throws IOException {
      if (this.versioned) {
         var3 = this.decodeVersion(var1, var3);
      }

      this.decodeJson0(var1, var2, var3);
      this.afterDecodeAndValidate(var2, var3);
   }

   @Override
   class="kw">public T decodeAndInherit(@Nonnull BsonDocument var1, T var2, ExtraInfo var3) {
      Object var4 = this.supplier.get();
      this.decodeAndInherit(var1, var4, var2, var3);
      class="kw">return var4;
   }

   @Override
   class="kw">public void decodeAndInherit(@Nonnull BsonDocument var1, T var2, @Nullable T var3, ExtraInfo var4) {
      if (this.versioned) {
         var4 = this.decodeVersion(var1, var4);
      }

      if (var3 != null) {
         this.inherit(var2, var3, var4);
      }

      this.decodeAndInherit0(var1, var2, var3, var4);
      this.afterDecodeAndValidate(var2, var4);
   }

   class="kw">protected void decodeAndInherit0(@Nonnull BsonDocument var1, T var2, T var3, @Nonnull ExtraInfo var4) {
      for (Entry var6 : var1.entrySet()) {
         String var7 = var6.getKey();
         BuilderField var8 = findEntry(this, var7, var4);
         if (var8 != null) {
            if (var8.codec.getChildCodec() class="kw">instanceof BuilderCodec) {
               decodeAndInherit(var8, var1, var2, var3, var4);
            } else {
               var8.decodeAndInherit(var1, var2, var3, var4);
            }
         } else if (!this.isIgnoredKey(var7, var4)) {
            var4.addUnknownKey(var7);
         }
      }
   }

   class="kw">private class="kw">static <Type, FieldType> void decodeAndInherit(
      @Nonnull BuilderField<Type, FieldType> var0, @Nonnull BsonDocument var1, Type var2, @Nullable Type var3, @Nonnull ExtraInfo var4
   ) {
      KeyedCodec var5 = var0.codec;
      String var6 = var5.getKey();
      BsonValue var7 = var1.get(var6);
      if (Codec.isNullBsonValue(var7)) {
         if (var7 != null && var7.isNull()) {
            var0.setValue(var2, null, var4);
         }
      } else {
         var4.pushKey(var6);

         try {
            BuilderCodec var8 = (BuilderCodec<FieldType>)var5.getChildCodec();
            Object var9 = var8.getSupplier().get();
            Object var10 = var3 != null ? var0.getter.apply(var3, var4) : null;
            var8.decodeAndInherit(var7.asDocument(), var9, var10, var4);
            var0.setValue(var2, var9, var4);
         } catch (Exception var14) {
            throw new CodecException("Failed to decode", var7, var4, var14);
         } class="kw">finally {
            var4.popKey();
         }
      }
   }

   @Override
   class="kw">public T decodeAndInheritJson(@Nonnull RawJsonReader var1, T var2, ExtraInfo var3) class="kw">throws IOException {
      Object var4 = this.supplier.get();
      this.decodeAndInheritJson(var1, var4, var2, var3);
      class="kw">return var4;
   }

   @Override
   class="kw">public void decodeAndInheritJson(@Nonnull RawJsonReader var1, T var2, @Nullable T var3, ExtraInfo var4) class="kw">throws IOException {
      if (this.versioned) {
         var4 = this.decodeVersion(var1, var4);
      }

      if (var3 != null) {
         this.inherit(var2, var3, var4);
      }

      this.decodeAndInheritJson0(var1, var2, var3, var4);
      this.afterDecodeAndValidate(var2, var4);
   }

   class="kw">public void decodeAndInheritJson0(@Nonnull RawJsonReader var1, T var2, T var3, @Nonnull ExtraInfo var4) class="kw">throws IOException {
      var1.expect('{');
      var1.consumeWhiteSpace();
      if (!var1.tryConsume('}')) {
         while (true) {
            this.readAndInheritEntry(var1, var2, var3, var4);
            var1.consumeWhiteSpace();
            if (var1.tryConsumeOrExpect('}', ',')) {
               class="kw">return;
            }

            var1.consumeWhiteSpace();
         }
      }
   }

   class="kw">protected void readAndInheritEntry(@Nonnull RawJsonReader var1, T var2, T var3, @Nonnull ExtraInfo var4) class="kw">throws IOException {
      var1.mark();
      StringTreeMap var5 = this.stringTreeMap.findEntry(var1);
      BuilderCodec.KeyEntry var6;
      if (var5 != null && (var6 = var5.getValue()) != null) {
         class="kw">switch (var6.getType()) {
            case FIELD:
               String var7 = var5.getKey();
               List var8 = var6.getFields();
               this.readAndInheritField(var1, var2, var3, var4, var7, var8);
               break;
            case IGNORE:
               var1.unmark();
               this.skipField(var1);
               break;
            case IGNORE_IN_BASE_OBJECT:
               if (var4.getKeysSize() == 0) {
                  var1.unmark();
                  this.skipField(var1);
               } else {
                  var1.reset();
                  this.readUnknownField(var1, var4);
               }
         }
      } else {
         var1.reset();
         this.readUnknownField(var1, var4);
      }
   }

   class="kw">private void readAndInheritField(@Nonnull RawJsonReader var1, T var2, T var3, @Nonnull ExtraInfo var4, String var5, @Nonnull List<BuilderField<T, ?>> var6) class="kw">throws IOException {
      BuilderField var7 = null;

      for (BuilderField var9 : var6) {
         if (var9.supportsVersion(var4.getVersion())) {
            var7 = var9;
            break;
         }
      }

      if (var7 == null) {
         var1.reset();
         this.readUnknownField(var1, var4);
      } else {
         var1.unmark();
         var1.consumeWhiteSpace();
         var1.expect(':');
         var1.consumeWhiteSpace();
         var4.pushKey(var5, var1);

         try {
            if (var7.codec.getChildCodec() class="kw">instanceof BuilderCodec) {
               decodeAndInheritJson(var7, var1, var2, var3, var4);
            } else {
               var7.decodeAndInheritJson(var1, var2, var3, var4);
            }
         } catch (Exception var13) {
            throw new CodecException("Failed to decode", var1, var4, var13);
         } class="kw">finally {
            var4.popKey();
         }
      }
   }

   class="kw">private class="kw">static <Type, FieldType> void decodeAndInheritJson(
      @Nonnull BuilderField<Type, FieldType> var0, @Nonnull RawJsonReader var1, Type var2, @Nullable Type var3, @Nonnull ExtraInfo var4
   ) class="kw">throws IOException {
      int var5 = var1.peek();
      if (var5 == -1) {
         throw new IOException("Unexpected EOF!");
      }

      class="kw">switch (var5) {
         case 78:
         case 110:
            var1.readNullValue();
            var0.setValue(var2, null, var4);
            class="kw">return;
         class="kw">default:
            BuilderCodec var6 = (BuilderCodec<FieldType>)var0.codec.getChildCodec();
            Object var7 = var6.getSupplier().get();
            Object var8 = var3 != null ? var0.getter.apply(var3, var4) : null;
            var6.decodeAndInheritJson(var1, var7, var8, var4);
            var0.setValue(var2, var7, var4);
      }
   }

   class="kw">private boolean isIgnoredKey(@Nonnull String var1, @Nonnull ExtraInfo var2) {
      StringTreeMap var3 = this.stringTreeMap.findEntry(var1);
      if (var3 == null) {
         class="kw">return false;
      }

      BuilderCodec.KeyEntry var4 = var3.getValue();
      if (var4 == null) {
         class="kw">return false;
      }

      class="kw">return class="kw">switch (var4.getType()) {
         case FIELD -> false;
         case IGNORE -> true;
         case IGNORE_IN_BASE_OBJECT -> var2.getKeysSize() == 0;
      };
   }

   @Nonnull
   class="kw">protected ExtraInfo decodeVersion(BsonDocument var1, @Nonnull ExtraInfo var2) {
      if (this.useLegacyVersion && var2.getLegacyVersion() != Integer.MAX_VALUE) {
         class="kw">return new VersionedExtraInfo(var2.getLegacyVersion(), var2);
      } else {
         int var3 = VERSION.get(var1, var2).orElse(0);
         if (var3 > this.codecVersion) {
            throw new IllegalArgumentException("Version " + var3 + " is newer than expected version " + this.codecVersion);
         } else if (this.minCodecVersion != Integer.MAX_VALUE && var3 < this.minCodecVersion) {
            throw new IllegalArgumentException("Version " + var3 + " is older than min supported version " + this.minCodecVersion);
         } else {
            class="kw">return new VersionedExtraInfo(var3, var2);
         }
      }
   }

   @Nonnull
   class="kw">protected ExtraInfo decodeVersion(@Nonnull RawJsonReader var1, @Nonnull ExtraInfo var2) class="kw">throws IOException {
      if (this.useLegacyVersion && var2.getLegacyVersion() != Integer.MAX_VALUE) {
         class="kw">return new VersionedExtraInfo(var2.getLegacyVersion(), var2);
      }

      var1.mark();
      int var3 = 0;
      if (RawJsonReader.seekToKey(var1, VERSION.getKey())) {
         var3 = var1.readIntValue();
      }

      if (var3 > this.codecVersion) {
         throw new IllegalArgumentException("Version " + var3 + " is newer than expected version " + this.codecVersion);
      }

      if (this.minCodecVersion != Integer.MAX_VALUE && var3 < this.minCodecVersion) {
         throw new IllegalArgumentException("Version " + var3 + " is older than min supported version " + this.minCodecVersion);
      }

      var1.reset();
      class="kw">return new VersionedExtraInfo(var3, var2);
   }

   @Override
   class="kw">public void validate(T var1, @Nonnull ExtraInfo var2) {
      if (this.parentCodec != null) {
         this.parentCodec.validate(var1, var2);
      }

      for (List var4 : this.entries.values()) {
         BuilderField var5 = findField(var4, var2);
         if (var5 != null) {
            var2.pushKey(var5.codec.getKey());

            try {
               var5.validate(var1, var2);
            } class="kw">finally {
               var2.popKey();
            }
         }
      }
   }

   @Override
   class="kw">public void validateDefaults(@Nonnull ExtraInfo var1, @Nonnull Set<Codec<?>> var2) {
      if (var2.add(this)) {
         Object var3 = this.supplier.get();
         this.afterDecode(var3, var1);

         for (BuilderCodec var4 = this; var4 != null; var4 = (BuilderCodec<T>)var4.parentCodec) {
            for (List var6 : var4.entries.values()) {
               BuilderField var7 = findField(var6, var1);
               if (var7 != null) {
                  var1.pushKey(var7.codec.getKey());

                  try {
                     var7.validateDefaults(var3, var1, var2);
                  } class="kw">finally {
                     var1.popKey();
                  }
               }
            }
         }
      }
   }

   @Nonnull
   class="kw">public ObjectSchema toSchema(@Nonnull SchemaContext var1) {
      Object var2 = this.getDefaultValue();
      class="kw">return this.toSchema(var1, var2);
   }

   @Nonnull
   class="kw">public ObjectSchema toSchema(@Nonnull SchemaContext var1, @Nullable T var2) {
      ObjectSchema var3 = new ObjectSchema();
      var3.setAdditionalProperties(false);
      var3.setTitle(this.tClass.getSimpleName());
      var3.setMarkdownDescription(this.documentation);
      var3.getHytale().setMergesProperties(true);
      Map var4 = new Object2ObjectLinkedOpenHashMap();
      if (this.versioned) {
         var4.put(VERSION.getKey(), VERSION.getChildCodec().toSchema(var1));
      }

      Schema var5 = new Schema();
      var5.getHytale().setUiPropertyTitle("Comment");
      var5.setDoNotSuggest(true);
      var5.setDescription("Comments don't have any function other than allowing users to add certain internal comments or notes to an asset");
      UIDisplayMode.HIDDEN.modify(var5);
      var4.put("$Title", var5);
      var4.put("$Comment", var5);
      var4.put("$Author", var5);
      var4.put("$TODO", var5);
      var4.put("$Position", var5);
      var4.put("$FloatingFunctionNodes", var5);
      var4.put("$Groups", var5);
      var4.put("$WorkspaceID", var5);
      var4.put("$NodeId", var5);
      var4.put("$NodeEditorMetadata", var5);
      var3.setProperties(var4);
      createSchemaFields(var1, var2, this, var4);
      if (this.metadata != null) {
         for (int var6 = 0; var6 < this.metadata.size(); var6++) {
            Metadata var7 = this.metadata.get(var6);
            var7.modify(var3);
         }
      }

      class="kw">return var3;
   }

   class="kw">private class="kw">static <T> void createSchemaFields(@Nonnull SchemaContext var0, @Nullable T var1, @Nonnull BuilderCodec<T> var2, @Nonnull Map<String, Schema> var3) {
      if (var2.parentCodec != null) {
         createSchemaFields(var0, var1, var2.parentCodec, var3);
      }

      for (Entry var5 : var2.getEntries().entrySet()) {
         String var6 = var5.getKey();
         List var7 = var5.getValue();
         BuilderField var8 = var7.getLast();
         Codec var9 = var8.getCodec().getChildCodec();

         Object var10;
         try {
            var10 = var8.getter.apply(var1, EmptyExtraInfo.EMPTY);
         } catch (UnsupportedOperationException var14) {
            class="kw">continue;
         }

         Schema var11 = var0.refDefinition(var9, (T)var10);
         var8.updateSchema(var0, var11);
         Schema var12 = var11;
         String var13 = Schema.CODEC.getIdFor((Class<? class="kw">extends Schema>)var11.getClass());
         if (!var13.isEmpty()) {
            if (!var8.hasNonNullValidator() && !var8.isPrimitive) {
               var11.setTypes(new String[]{var13, "null"});
            }

            var3.put(var6, var11);
         } else if (var8.hasNonNullValidator()) {
            var3.put(var6, var11);
         } else {
            var3.put(var6, var12 = Schema.anyOf(var11, NullSchema.INSTANCE));
         }

         var12.setMarkdownDescription(var8.getDocumentation());
      }
   }

   @Nonnull
   @Override
   class="kw">public String toString() {
      class="kw">return "BuilderCodec{supplier="
         + this.supplier
         + ", parentCodec="
         + this.parentCodec
         + ", entries="
         + this.entries
         + ", afterDecode="
         + this.afterDecode
         + "}";
   }

   @Nullable
   class="kw">protected class="kw">static <T> BuilderField<? super T, ?> findEntry(@Nonnull BuilderCodec<? super T> var0, String var1, @Nonnull ExtraInfo var2) {
      List var3 = var0.entries.get(var1);
      if (var3 != null && var3.size() == 1) {
         BuilderField var4 = (BuilderField<? super T, ?>)var3.getFirst();
         if (var4.supportsVersion(var2.getVersion())) {
            class="kw">return var4;
         }
      }

      BuilderField var5 = null;

      while (var0 != null) {
         var5 = findField(var0.entries.get(var1), var2);
         if (var5 != null) {
            class="kw">return var5;
         }

         var0 = var0.parentCodec;
      }

      class="kw">return var5;
   }

   @Nullable
   class="kw">protected class="kw">static <T, F class="kw">extends BuilderField<T, ?>> F findField(@Nullable List<F> var0, @Nonnull ExtraInfo var1) {
      if (var0 == null) {
         class="kw">return null;
      }

      int var2 = 0;

      for (int var3 = var0.size(); var2 < var3; var2++) {
         BuilderField var4 = (F)var0.get(var2);
         if (var4.supportsVersion(var1.getVersion())) {
            class="kw">return var4;
         }
      }

      class="kw">return null;
   }

   @Nonnull
   class="kw">public class="kw">static <T> BuilderCodec.Builder<T> builder(Class<T> var0, Supplier<T> var1) {
      class="kw">return new BuilderCodec.Builder<>(var0, var1);
   }

   @Nonnull
   class="kw">public class="kw">static <T> BuilderCodec.Builder<T> builder(Class<T> var0, Supplier<T> var1, BuilderCodec<? super T> var2) {
      class="kw">return new BuilderCodec.Builder<>(var0, var1, var2);
   }

   @Nonnull
   class="kw">public class="kw">static <T> BuilderCodec.Builder<T> abstractBuilder(Class<T> var0) {
      class="kw">return new BuilderCodec.Builder<>(var0, null);
   }

   @Nonnull
   class="kw">public class="kw">static <T> BuilderCodec.Builder<T> abstractBuilder(Class<T> var0, BuilderCodec<? super T> var1) {
      class="kw">return new BuilderCodec.Builder<>(var0, null, var1);
   }

   class="kw">public class="kw">static class Builder<T> class="kw">extends BuilderCodec.BuilderBase<T, BuilderCodec.Builder<T>> {
      class="kw">protected Builder(Class<T> var1, Supplier<T> var2) {
         super(var1, var2);
      }

      class="kw">protected Builder(Class<T> var1, Supplier<T> var2, @Nullable BuilderCodec<? super T> var3) {
         super(var1, var2, var3);
      }
   }

   class="kw">public class="kw">abstract class="kw">static class BuilderBase<T, S class="kw">extends BuilderCodec.BuilderBase<T, S>> {
      class="kw">protected class="kw">final Class<T> tClass;
      class="kw">protected class="kw">final Supplier<T> supplier;
      @Nullable
      class="kw">protected class="kw">final BuilderCodec<? super T> parentCodec;
      class="kw">protected class="kw">final Map<String, List<BuilderField<T, ?>>> entries = new Object2ObjectLinkedOpenHashMap();
      @Nonnull
      class="kw">protected class="kw">final StringTreeMap<BuilderCodec.KeyEntry<T>> stringTreeMap;
      class="kw">protected BiConsumer<T, ValidationResults> validator;
      class="kw">protected BiConsumer<T, ExtraInfo> afterDecode;
      class="kw">protected String documentation;
      class="kw">protected List<Metadata> metadata;
      class="kw">protected int codecVersion = Integer.MIN_VALUE;
      class="kw">protected int minCodecVersion = Integer.MAX_VALUE;
      class="kw">protected boolean versioned = false;
      class="kw">protected boolean useLegacyVersion = false;

      class="kw">protected BuilderBase(Class<T> var1, Supplier<T> var2) {
         this(var1, var2, null);
      }

      class="kw">protected BuilderBase(Class<T> var1, Supplier<T> var2, @Nullable BuilderCodec<? super T> var3) {
         this.tClass = var1;
         this.supplier = var2;
         this.parentCodec = var3;
         if (var3 != null) {
            this.stringTreeMap = new StringTreeMap<>((StringTreeMap<BuilderCodec.KeyEntry<T>>)var3.stringTreeMap);
         } else {
            this.stringTreeMap = new StringTreeMap<>();
            BuilderCodec.BASE_IGNORED_KEYS.forEach((var1x, var2x) -> this.stringTreeMap.put(var1x, new BuilderCodec.KeyEntry<>(var2x)));
         }
      }

      class="kw">private S self() {
         class="kw">return (S)this;
      }

      @Nonnull
      class="kw">public S documentation(String var1) {
         this.documentation = var1;
         class="kw">return this.self();
      }

      @Nonnull
      class="kw">public S versioned() {
         this.versioned = true;
         class="kw">return this.self();
      }

      @Nonnull
      @Deprecated
      class="kw">public S legacyVersioned() {
         this.versioned = true;
         this.useLegacyVersion = true;
         class="kw">return this.self();
      }

      @Nonnull
      @Deprecated
      class="kw">public <FieldType> S addField(@Nonnull KeyedCodec<FieldType> var1, @Nonnull BiConsumer<T, FieldType> var2, @Nonnull Function<T, FieldType> var3) {
         class="kw">return this.addField(new BuilderField<>(var1, (var1x, var2x, var3x) -> var2.accept(var1x, var2x), (var1x, var2x) -> var3.apply(var1x), null));
      }

      @Nonnull
      class="kw">public <FieldType> BuilderField.FieldBuilder<T, FieldType, S> append(
         KeyedCodec<FieldType> var1, @Nonnull BiConsumer<T, FieldType> var2, @Nonnull Function<T, FieldType> var3
      ) {
         class="kw">return this.append(var1, (var1x, var2x, var3x) -> var2.accept(var1x, var2x), (var1x, var2x) -> var3.apply(var1x));
      }

      @Nonnull
      class="kw">public <FieldType> BuilderField.FieldBuilder<T, FieldType, S> append(
         KeyedCodec<FieldType> var1, TriConsumer<T, FieldType, ExtraInfo> var2, BiFunction<T, ExtraInfo, FieldType> var3
      ) {
         class="kw">return new BuilderField.FieldBuilder<>(this.self(), var1, var2, var3, null);
      }

      @Nonnull
      class="kw">public <FieldType> BuilderField.FieldBuilder<T, FieldType, S> appendInherited(
         KeyedCodec<FieldType> var1, @Nonnull BiConsumer<T, FieldType> var2, @Nonnull Function<T, FieldType> var3, @Nonnull BiConsumer<T, T> var4
      ) {
         class="kw">return this.appendInherited(
            var1, (var1x, var2x, var3x) -> var2.accept(var1x, var2x), (var1x, var2x) -> var3.apply(var1x), (var1x, var2x, var3x) -> var4.accept(var1x, var2x)
         );
      }

      @Nonnull
      class="kw">public <FieldType> BuilderField.FieldBuilder<T, FieldType, S> appendInherited(
         KeyedCodec<FieldType> var1, TriConsumer<T, FieldType, ExtraInfo> var2, BiFunction<T, ExtraInfo, FieldType> var3, TriConsumer<T, T, ExtraInfo> var4
      ) {
         class="kw">return new BuilderField.FieldBuilder<>(this.self(), var1, var2, var3, var4);
      }

      @Nonnull
      class="kw">public <FieldType> S addField(@Nonnull BuilderField<T, FieldType> var1) {
         if (var1.getMinVersion() > var1.getMaxVersion()) {
            throw new IllegalArgumentException("Min version must be less than the max version: " + var1);
         }

         List var2 = this.entries.computeIfAbsent(var1.getCodec().getKey(), var0 -> new ObjectArrayList());

         for (BuilderField var4 : var2) {
            if (var1.getMaxVersion() >= var4.getMinVersion() && var1.getMinVersion() <= var4.getMaxVersion()) {
               throw new IllegalArgumentException("Field already defined for this version range!");
            }
         }

         var2.add(var1);
         this.stringTreeMap.put(var1.getCodec().getKey(), new BuilderCodec.KeyEntry<>(var2));
         class="kw">return this.self();
      }

      @Nonnull
      class="kw">public S afterDecode(@Nonnull Consumer<T> var1) {
         Objects.requireNonNull(var1, "afterDecodeAndValidate can't be null!");
         class="kw">return this.afterDecode((var1x, var2) -> var1.accept(var1x));
      }

      @Nonnull
      class="kw">public S afterDecode(BiConsumer<T, ExtraInfo> var1) {
         this.afterDecode = Objects.requireNonNull(var1, "afterDecodeAndValidate can't be null!");
         class="kw">return this.self();
      }

      @Nonnull
      @Deprecated
      class="kw">public S validator(BiConsumer<T, ValidationResults> var1) {
         this.validator = Objects.requireNonNull(var1, "validator can't be null!");
         class="kw">return this.self();
      }

      @Nonnull
      class="kw">public S metadata(Metadata var1) {
         if (this.metadata == null) {
            this.metadata = new ObjectArrayList();
         }

         this.metadata.add(var1);
         class="kw">return this.self();
      }

      @Nonnull
      class="kw">public S codecVersion(int var1, int var2) {
         this.minCodecVersion = var1;
         this.codecVersion = var2;
         class="kw">return this.self();
      }

      @Nonnull
      class="kw">public S codecVersion(int var1) {
         this.minCodecVersion = 0;
         this.codecVersion = var1;
         class="kw">return this.self();
      }

      @Nonnull
      class="kw">public BuilderCodec<T> build() {
         class="kw">return new BuilderCodec<>(this);
      }
   }

   class="kw">protected enum EntryType {
      FIELD,
      IGNORE,
      IGNORE_IN_BASE_OBJECT;

      EntryType() {
      }
   }

   class="kw">protected class="kw">static class KeyEntry<T> {
      class="kw">private class="kw">final BuilderCodec.EntryType type;
      @Nullable
      class="kw">private class="kw">final List<BuilderField<T, ?>> fields;

      class="kw">public KeyEntry(BuilderCodec.EntryType var1) {
         this.type = var1;
         this.fields = null;
      }

      class="kw">public KeyEntry(List<BuilderField<T, ?>> var1) {
         this.type = BuilderCodec.EntryType.FIELD;
         this.fields = var1;
      }

      class="kw">public BuilderCodec.EntryType getType() {
         class="kw">return this.type;
      }

      @Nullable
      class="kw">public List<BuilderField<T, ?>> getFields() {
         class="kw">return this.fields;
      }
   }
}