Skip to content

Commit

Permalink
Config version 1
Browse files Browse the repository at this point in the history
* Config fields are now optional, but not lenient, and they will reappear with default values when saving
* Include Pale Oak Leaves to default targets
* Added config versioning used in upgrading to important config changes

Previous config are considered version 0
* When upgrading, Pale Oak Leaves will be added to targets
  • Loading branch information
StartsMercury committed Feb 1, 2025
1 parent c16b03c commit 5e04c1d
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,9 @@ private boolean loadConfig() {
return false;
}

Config.CODEC
Config.LENIENT_CODEC
.decode(JsonOps.INSTANCE, json)
.ifSuccess(result -> this.setConfig(result.getFirst()))
.ifSuccess(result -> this.setConfig(result.getFirst().upgrade()))
.ifError(result -> this.logger
.warn("[{}] Unable to decode config: {}", VslConstants.NAME, result.message())
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@

import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.resources.ResourceLocation;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.function.Function;

import static io.github.startsmercury.visual_snowy_leaves.impl.client.config.Leaves.*;

public record Config(
int version,
RebuildInterval rebuildInterval,
SnowyMode snowyMode,
Set<ResourceLocation> targetBlockKeys,
Expand All @@ -33,33 +37,123 @@ public record Config(
}
);

public static final Codec<Config> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
RebuildInterval.CODEC.fieldOf("rebuildInterval").forGetter(Config::rebuildInterval),
SnowyMode.CODEC.fieldOf("snowyMode").forGetter(Config::snowyMode),
TARGET_BLOCK_KEYS_CODEC.fieldOf("targetBlockKeys").forGetter(Config::targetBlockKeys),
TransitionDuration.CODEC.fieldOf("transitionDuration").forGetter(Config::transitionDuration)
).apply(instance, Config::new));
public static final int MINIMUM_VERSION = 0;

public static final int CURRENT_VERSION = 1;

public static final RebuildInterval DEFAULT_REBUILD_INTERVAL = RebuildInterval.fromTicks(20);

public static final SnowyMode DEFAULT_SNOWY_MODE = SnowyMode.SNOWING;

public static final Set<ResourceLocation> DEFAULT_TARGET_BLOCK_KEYS = Stream.of(
"oak", "spruce", "birch", "jungle", "acacia", "dark_oak", "mangrove"
)
.map(base -> base + "_leaves")
.map(ResourceLocation::parse)
.collect(Collectors.toUnmodifiableSet());
public static final Set<ResourceLocation> DEFAULT_TARGET_BLOCK_KEYS = Set.of(
OAK, SPRUCE, BIRCH, JUNGLE, ACACIA, DARK_OAK, MANGROVE, PALE_OAK
);

@SuppressWarnings("deprecation")
public static final TransitionDuration DEFAULT_TRANSITION_DURATION =
TransitionDuration.fromTicksUnchecked(400);

@FunctionalInterface
private interface CodecFieldBuilder {
CodecFieldBuilder DEFAULT = CodecFieldBuilder::fieldOfImpl;
CodecFieldBuilder OPTIONAL = Codec::optionalFieldOf;

private static <A> MapCodec<A> fieldOfImpl(
final Codec<A> self,
final String name,
final A defaultValue
) {
return self.fieldOf(name);
}

<A> MapCodec<A> create(Codec<A> self, String name, A defaultValue);

default <O, A> RecordCodecBuilder<O, A> create(
final Codec<A> self,
final String name,
final A defaultValue,
final Function<O, A> getter
) {
return create(self, name, defaultValue).forGetter(getter);
}
}

private static Codec<Config> newCodec(final CodecFieldBuilder fieldBuilder) {
return RecordCodecBuilder.create(instance ->
instance.group(
fieldBuilder.create(
Codec.INT,
// Defaults may be partial, assume minimum version
"version",
MINIMUM_VERSION,
Config::version
),
fieldBuilder.create(
RebuildInterval.CODEC,
"rebuildInterval",
DEFAULT_REBUILD_INTERVAL,
Config::rebuildInterval
),
fieldBuilder.create(
SnowyMode.CODEC,
"snowyMode",
DEFAULT_SNOWY_MODE,
Config::snowyMode
),
fieldBuilder.create(
TARGET_BLOCK_KEYS_CODEC,
"targetBlockKeys",
DEFAULT_TARGET_BLOCK_KEYS,
Config::targetBlockKeys
),
fieldBuilder.create(
TransitionDuration.CODEC,
"transitionDuration",
DEFAULT_TRANSITION_DURATION,
Config::transitionDuration
)
).apply(instance, Config::new));
}

public static final Codec<Config> LENIENT_CODEC = newCodec(CodecFieldBuilder.OPTIONAL);

public static final Codec<Config> CODEC = newCodec(CodecFieldBuilder.DEFAULT);

public static final Config DEFAULT = new Config(
CURRENT_VERSION,
DEFAULT_REBUILD_INTERVAL,
DEFAULT_SNOWY_MODE,
DEFAULT_TARGET_BLOCK_KEYS,
DEFAULT_TRANSITION_DURATION
);

public Config upgrade() {
if (version >= CURRENT_VERSION) {
return this;
}

final var version = Math.max(this.version, MINIMUM_VERSION);
var rebuildInterval = this.rebuildInterval;
var snowyMode = this.snowyMode;
var targetBlockKeys = new HashSet<>(this.targetBlockKeys);
var transitionDuration = this.transitionDuration;

switch (version) {
case 0 -> targetBlockKeys.add(PALE_OAK);
default -> {
final var message = "Upgrade is not yet implemented for config version "
+ version
+ ". Immediately report this issue";
throw new InternalError(message);
}
}

return new Config(
CURRENT_VERSION,
rebuildInterval,
snowyMode,
Set.copyOf(targetBlockKeys),
transitionDuration
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.github.startsmercury.visual_snowy_leaves.impl.client.config;

import net.minecraft.resources.ResourceLocation;

final class Leaves {
private static ResourceLocation getLeaves(final String baseName) {
return ResourceLocation.parse(baseName + "_leaves");
}

// Version 0
public static final ResourceLocation OAK = getLeaves("oak");
public static final ResourceLocation SPRUCE = getLeaves("spruce");
public static final ResourceLocation BIRCH = getLeaves("birch");
public static final ResourceLocation ACACIA = getLeaves("acacia");
public static final ResourceLocation JUNGLE = getLeaves("jungle");
public static final ResourceLocation DARK_OAK = getLeaves("dark_oak");
public static final ResourceLocation MANGROVE = getLeaves("mangrove");

// Version 1
public static final ResourceLocation PALE_OAK = getLeaves("pale_oak");

private Leaves() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import net.minecraft.SharedConstants;

import java.time.Duration;
import java.util.Objects;

import static io.github.startsmercury.visual_snowy_leaves.impl.client.VslConstants.Duration.ONE_TICK;

Expand Down

0 comments on commit 5e04c1d

Please sign in to comment.