package dev.isxander.yacl3.config.v3; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.*; import org.jetbrains.annotations.ApiStatus; import java.util.ArrayList; import java.util.List; @ApiStatus.Experimental public abstract class CodecConfig> implements EntryAddable, Codec { private final List> entries = new ArrayList<>(); public CodecConfig() { // cast here to throw immediately on construction var ignored = (S) this; } @Override public ConfigEntry register(String fieldName, T defaultValue, Codec codec) { ConfigEntry entry = new CodecConfigEntryImpl<>(fieldName, defaultValue, codec); entries.add(entry); return entry; } @Override public > ReadonlyConfigEntry register(String fieldName, T configInstance) { ReadonlyConfigEntry entry = new ChildConfigEntryImpl<>(fieldName, configInstance); entries.add(entry); return entry; } protected void onFinishedDecode(boolean successful) { } @Override public DataResult encode(S input, DynamicOps ops, R prefix) { if (input != null && input != this) { throw new IllegalArgumentException("`input` is ignored. It must be null or equal to `this`."); } return this.encode(ops, prefix); } @Override public DataResult> decode(DynamicOps ops, R input) { this.decode(input, ops); return DataResult.success(Pair.of((S) this, input)); } public final DataResult encode(DynamicOps ops, R prefix) { RecordBuilder builder = ops.mapBuilder(); for (ReadonlyConfigEntry entry : entries) { builder = entry.encode(ops, builder); } return builder.build(prefix); } public final DataResult encodeStart(DynamicOps ops) { return this.encode(ops, ops.empty()); } /** * @return true if decoding of all entries was successful */ public final boolean decode(R encoded, DynamicOps ops) { boolean success = true; for (ReadonlyConfigEntry entry : entries) { success &= entry.decode(encoded, ops); } onFinishedDecode(success); return success; } }