aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorKevin <92656833+kevinthegreat1@users.noreply.github.com>2025-05-07 18:07:49 -0400
committerGitHub <noreply@github.com>2025-05-07 18:07:49 -0400
commit89031b39097f896782a2f97d3280acf66b25ed96 (patch)
tree19adf0bba3d09223015def6ec428aa939ce14d35 /src/main/java
parentabbd59bdd32635363ea80fc7393b6611910e8321 (diff)
downloadSkyblocker-89031b39097f896782a2f97d3280acf66b25ed96.tar.gz
Skyblocker-89031b39097f896782a2f97d3280acf66b25ed96.tar.bz2
Skyblocker-89031b39097f896782a2f97d3280acf66b25ed96.zip
Remove Legacy Ordered Waypoints (#1242)
* Add OrderedWaypointsTest * Migrate legacy ordered waypoints parsing * Migrate import to new codecs * Migrate loading to new codecs
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/waypoint/OrderedWaypoints.java150
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/waypoint/Waypoints.java40
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsShareScreen.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/InstancedUtils.java14
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/waypoint/NamedWaypoint.java6
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/waypoint/WaypointGroup.java8
6 files changed, 57 insertions, 163 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/OrderedWaypoints.java b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/OrderedWaypoints.java
deleted file mode 100644
index 5c82cf7b..00000000
--- a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/OrderedWaypoints.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package de.hysky.skyblocker.skyblock.waypoint;
-
-import com.google.common.primitives.Floats;
-import com.google.gson.JsonParser;
-import com.mojang.brigadier.Command;
-import com.mojang.brigadier.CommandDispatcher;
-import com.mojang.logging.LogUtils;
-import com.mojang.serialization.Codec;
-import com.mojang.serialization.JsonOps;
-import com.mojang.serialization.codecs.RecordCodecBuilder;
-import de.hysky.skyblocker.SkyblockerMod;
-import de.hysky.skyblocker.annotations.Init;
-import de.hysky.skyblocker.config.SkyblockerConfigManager;
-import de.hysky.skyblocker.utils.Constants;
-import de.hysky.skyblocker.utils.Location;
-import de.hysky.skyblocker.utils.waypoint.OrderedNamedWaypoint;
-import de.hysky.skyblocker.utils.waypoint.Waypoint;
-import de.hysky.skyblocker.utils.waypoint.WaypointGroup;
-import it.unimi.dsi.fastutil.floats.FloatArrayList;
-import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
-import it.unimi.dsi.fastutil.objects.ObjectArrayList;
-import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
-import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
-import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.command.CommandRegistryAccess;
-import net.minecraft.text.Text;
-import net.minecraft.util.math.BlockPos;
-import org.slf4j.Logger;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.nio.file.Files;
-import java.nio.file.NoSuchFileException;
-import java.nio.file.Path;
-import java.util.Base64;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import java.util.zip.GZIPInputStream;
-
-import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
-
-/**
- * @deprecated Use {@link Waypoints} instead.
- */
-@Deprecated
-public class OrderedWaypoints {
- private static final Logger LOGGER = LogUtils.getLogger();
- private static final Codec<Map<String, OrderedWaypointGroup>> SERIALIZATION_CODEC = Codec.unboundedMap(Codec.STRING, OrderedWaypointGroup.CODEC).xmap(Object2ObjectOpenHashMap::new, Object2ObjectOpenHashMap::new);
- private static final String PREFIX = "[Skyblocker::OrderedWaypoints::v1]";
- public static final Path PATH = SkyblockerMod.CONFIG_DIR.resolve("ordered_waypoints.json");
-
- @Init
- public static void init() {
- ClientLifecycleEvents.CLIENT_STARTED.register(_client -> load());
- ClientCommandRegistrationCallback.EVENT.register(OrderedWaypoints::registerCommands);
- }
-
- private static void registerCommands(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) {
- dispatcher.register(literal(SkyblockerMod.NAMESPACE)
- .then(literal("waypoints")
- .then(literal("ordered")
- .then(literal("import")
- .then(literal("skyblocker")
- .executes(context -> fromSkyblockerFormat(context.getSource())))))));
- }
-
- /**
- * Loads and migrates the ordered waypoints to waypoints.
- * @deprecated Use {@link Waypoints} instead.
- */
- @Deprecated
- private static void load() {
- try (BufferedReader reader = Files.newBufferedReader(PATH)) {
- Map<String, OrderedWaypointGroup> orderedWaypoints = SERIALIZATION_CODEC.parse(JsonOps.INSTANCE, JsonParser.parseReader(reader)).getOrThrow();
- migrateOrderedWaypoints(orderedWaypoints);
- Files.move(PATH, SkyblockerMod.CONFIG_DIR.resolve("legacy_ordered_waypoints.json"));
- LOGGER.info("[Skyblocker Ordered Waypoints] Successfully migrated {} ordered waypoints from {} groups to waypoints!", orderedWaypoints.values().stream().map(OrderedWaypointGroup::waypoints).mapToInt(List::size).sum(), orderedWaypoints.size());
- } catch (NoSuchFileException ignored) {
- } catch (Exception e) {
- LOGGER.error("[Skyblocker Ordered Waypoints] Failed to load the waypoints! :(", e);
- }
- }
-
- /**
- * @deprecated Use {@link Waypoints} instead.
- */
- @Deprecated
- private static int fromSkyblockerFormat(FabricClientCommandSource source) {
- try {
- String importCode = MinecraftClient.getInstance().keyboard.getClipboard();
-
- if (importCode.startsWith(PREFIX)) {
- String encoded = importCode.replace(PREFIX, "");
- byte[] decoded = Base64.getDecoder().decode(encoded);
-
- String json = new String(new GZIPInputStream(new ByteArrayInputStream(decoded)).readAllBytes());
- Map<String, OrderedWaypointGroup> importedWaypoints = SERIALIZATION_CODEC.parse(JsonOps.INSTANCE, JsonParser.parseString(json)).getOrThrow();
-
- migrateOrderedWaypoints(importedWaypoints);
- source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.waypoints.ordered.import.skyblocker.success")));
- } else {
- source.sendError(Constants.PREFIX.get().append(Text.translatable("skyblocker.waypoints.ordered.import.skyblocker.unknownFormatHeader")));
- }
- } catch (Exception e) {
- LOGGER.error("[Skyblocker Ordered Waypoints] Failed to import waypoints!", e);
- source.sendError(Constants.PREFIX.get().append(Text.translatable("skyblocker.waypoints.ordered.import.skyblocker.fail")));
- }
-
- return Command.SINGLE_SUCCESS;
- }
-
- /**
- * Migrates the given ordered waypoints to waypoints.
- */
- private static void migrateOrderedWaypoints(Map<String, OrderedWaypointGroup> orderedWaypoints) {
- for (OrderedWaypointGroup legacyGroup : orderedWaypoints.values()) {
- // Migrate waypoints to both the dwarven mines and the crystal hollows
- Waypoints.putWaypointGroup(new WaypointGroup(legacyGroup.name, Location.DWARVEN_MINES, legacyGroup.waypoints.stream().map(waypoint -> new OrderedNamedWaypoint(waypoint.pos, "", new float[]{0, 1, 0})).collect(Collectors.toList()), true));
- Waypoints.putWaypointGroup(new WaypointGroup(legacyGroup.name, Location.CRYSTAL_HOLLOWS, legacyGroup.waypoints.stream().map(waypoint -> new OrderedNamedWaypoint(waypoint.pos, "", new float[]{0, 1, 0})).collect(Collectors.toList()), true));
- }
- }
-
- @Deprecated
- private record OrderedWaypointGroup(String name, boolean enabled, ObjectArrayList<OrderedWaypoint> waypoints) {
- static final Codec<OrderedWaypointGroup> CODEC = RecordCodecBuilder.create(instance -> instance.group(
- Codec.STRING.fieldOf("name").forGetter(OrderedWaypointGroup::name),
- Codec.BOOL.fieldOf("enabled").forGetter(OrderedWaypointGroup::enabled),
- OrderedWaypoint.LIST_CODEC.fieldOf("waypoints").xmap(ObjectArrayList::new, ObjectArrayList::new).forGetter(OrderedWaypointGroup::waypoints)
- ).apply(instance, OrderedWaypointGroup::new));
- }
-
- @Deprecated
- private static class OrderedWaypoint extends Waypoint {
- static final Codec<OrderedWaypoint> CODEC = RecordCodecBuilder.create(instance -> instance.group(
- BlockPos.CODEC.fieldOf("pos").forGetter(OrderedWaypoint::getPos),
- Codec.floatRange(0, 1).listOf().xmap(Floats::toArray, FloatArrayList::new).optionalFieldOf("colorComponents", new float[0]).forGetter(inst -> inst.colorComponents.length == 3 ? inst.colorComponents : new float[0]))
- .apply(instance, OrderedWaypoint::new));
- static final Codec<List<OrderedWaypoint>> LIST_CODEC = CODEC.listOf();
-
- OrderedWaypoint(BlockPos pos, float[] colorComponents) {
- super(pos, () -> SkyblockerConfigManager.get().uiAndVisuals.waypoints.waypointType, colorComponents);
- }
-
- private BlockPos getPos() {
- return this.pos;
- }
- }
-}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/Waypoints.java b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/Waypoints.java
index 588c9a9c..acefbca3 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/Waypoints.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/Waypoints.java
@@ -24,7 +24,6 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
-import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.toast.SystemToast;
import net.minecraft.command.CommandRegistryAccess;
@@ -41,6 +40,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Function;
+import java.util.stream.Collectors;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
@@ -51,10 +51,13 @@ public class Waypoints {
public static final Logger LOGGER = LoggerFactory.getLogger(Waypoints.class);
private static final Codec<List<WaypointGroup>> CODEC = WaypointGroup.CODEC.listOf();
private static final Codec<List<WaypointGroup>> SKYTILS_CODEC = WaypointGroup.SKYTILS_CODEC.listOf();
+ private static final Codec<Collection<WaypointGroup>> SKYBLOCKER_LEGACY_ORDERED_CODEC = Codec.unboundedMap(Codec.STRING, WaypointGroup.SKYBLOCKER_LEGACY_ORDERED_CODEC).xmap(Map::values, groups -> groups.stream().collect(Collectors.toMap(WaypointGroup::name, Function.identity())));
private static final String PREFIX = "[Skyblocker-Waypoint-Data-V1]";
+ private static final String SKYBLOCKER_LEGACY_ORDERED = "[Skyblocker::OrderedWaypoints::v1]";
protected static final SystemToast.Type WAYPOINTS_TOAST_TYPE = new SystemToast.Type();
- private static final Path waypointsFile = FabricLoader.getInstance().getConfigDir().resolve(SkyblockerMod.NAMESPACE).resolve("waypoints.json");
+ private static final Path WAYPOINTS_FILE = SkyblockerMod.CONFIG_DIR.resolve("waypoints.json");
+ private static final Path SKYBLOCKER_LEGACY_ORDERED_FILE = SkyblockerMod.CONFIG_DIR.resolve("ordered_waypoints.json");
private static final Multimap<Location, WaypointGroup> waypoints = MultimapBuilder.enumKeys(Location.class).arrayListValues().build();
@Init
@@ -95,16 +98,27 @@ public class Waypoints {
public static void loadWaypoints() {
waypoints.clear();
- try (BufferedReader reader = Files.newBufferedReader(waypointsFile)) {
+ try (BufferedReader reader = Files.newBufferedReader(WAYPOINTS_FILE)) {
List<WaypointGroup> waypointGroups = CODEC.parse(JsonOps.INSTANCE, SkyblockerMod.GSON.fromJson(reader, JsonArray.class)).resultOrPartial(LOGGER::error).orElseThrow();
waypointGroups.forEach(Waypoints::putWaypointGroup);
} catch (Exception e) {
LOGGER.error("[Skyblocker Waypoints] Encountered exception while loading waypoints", e);
}
- }
+ try (BufferedReader reader = Files.newBufferedReader(SKYBLOCKER_LEGACY_ORDERED_FILE)) {
+ Collection<WaypointGroup> waypointGroups = SKYBLOCKER_LEGACY_ORDERED_CODEC.parse(JsonOps.INSTANCE, SkyblockerMod.GSON.fromJson(reader, JsonObject.class)).resultOrPartial(LOGGER::error).orElseThrow();
+ for (WaypointGroup group : waypointGroups) {
+ Waypoints.putWaypointGroup(group.withIsland(Location.DWARVEN_MINES).deepCopy());
+ Waypoints.putWaypointGroup(group.withIsland(Location.DWARVEN_MINES).deepCopy());
+ }
+ Files.move(SKYBLOCKER_LEGACY_ORDERED_FILE, SkyblockerMod.CONFIG_DIR.resolve("legacy_ordered_waypoints.json"));
+ LOGGER.info("[Skyblocker Waypoints] Successfully migrated {} ordered waypoints from {} groups to waypoints!", waypointGroups.stream().map(WaypointGroup::waypoints).mapToInt(List::size).sum(), waypointGroups.size());
+ } catch (IOException e) {
+ LOGGER.error("[Skyblocker Waypoints] Encountered exception while loading legacy ordered waypoints", e);
+ }
+ }
public static void saveWaypoints(MinecraftClient client) {
- try (BufferedWriter writer = Files.newBufferedWriter(waypointsFile)) {
+ try (BufferedWriter writer = Files.newBufferedWriter(WAYPOINTS_FILE)) {
JsonElement waypointsJson = CODEC.encodeStart(JsonOps.INSTANCE, List.copyOf(waypoints.values())).resultOrPartial(LOGGER::error).orElseThrow();
SkyblockerMod.GSON.toJson(waypointsJson, writer);
LOGGER.info("[Skyblocker Waypoints] Saved waypoints");
@@ -113,14 +127,20 @@ public class Waypoints {
}
}
- public static List<WaypointGroup> fromSkyblocker(String waypointsString) {
+ public static List<WaypointGroup> fromSkyblocker(String waypointsString, Location defaultIsland) {
if (waypointsString.startsWith(PREFIX)) {
try (GZIPInputStream reader = new GZIPInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(waypointsString.replace(PREFIX, ""))))) {
return CODEC.parse(JsonOps.INSTANCE, SkyblockerMod.GSON.fromJson(new String(reader.readAllBytes()), JsonArray.class)).resultOrPartial(LOGGER::error).orElseThrow();
} catch (IOException e) {
LOGGER.error("[Skyblocker Waypoints] Encountered exception while parsing Skyblocker waypoint data", e);
}
- }
+ } else if (waypointsString.startsWith(SKYBLOCKER_LEGACY_ORDERED)) {
+ try (GZIPInputStream reader = new GZIPInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(waypointsString.replace(SKYBLOCKER_LEGACY_ORDERED, ""))))) {
+ return applyDefaultLocation(SKYBLOCKER_LEGACY_ORDERED_CODEC.parse(JsonOps.INSTANCE, SkyblockerMod.GSON.fromJson(new String(reader.readAllBytes()), JsonObject.class)).resultOrPartial(LOGGER::error).orElseThrow(), defaultIsland);
+ } catch (IOException e) {
+ LOGGER.error("[Skyblocker Waypoints] Encountered exception while parsing Skyblocker legacy ordered waypoint data", e);
+ }
+ }
return Collections.emptyList();
}
@@ -170,7 +190,7 @@ public class Waypoints {
waypointGroupsJson.add(waypointGroupJson);
}
List<WaypointGroup> waypointGroups = SKYTILS_CODEC.parse(JsonOps.INSTANCE, waypointGroupsJson).resultOrPartial(LOGGER::error).orElseThrow();
- return waypointGroups.stream().map(waypointGroup -> waypointGroup.island() == Location.UNKNOWN ? waypointGroup.withIsland(defaultIsland) : waypointGroup).toList();
+ return applyDefaultLocation(waypointGroups, defaultIsland);
}
public static String toSkytilsBase64(List<WaypointGroup> waypointGroups) {
@@ -187,6 +207,10 @@ public class Waypoints {
return WaypointGroup.COLEWEIGHT_CODEC.parse(JsonOps.INSTANCE, JsonParser.parseString(waypointsJson)).resultOrPartial(LOGGER::error).orElseThrow().withIsland(defaultIsland);
}
+ public static List<WaypointGroup> applyDefaultLocation(Collection<WaypointGroup> waypointGroups, Location defaultIsland) {
+ return waypointGroups.stream().map(waypointGroup -> waypointGroup.island() == Location.UNKNOWN ? waypointGroup.withIsland(defaultIsland) : waypointGroup).toList();
+ }
+
/**
* Gets the waypoint groups for the specified island.
*/
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsShareScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsShareScreen.java
index bc9102ca..7773c9c9 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsShareScreen.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/WaypointsShareScreen.java
@@ -32,7 +32,7 @@ public class WaypointsShareScreen extends AbstractWaypointsScreen<WaypointsScree
GridWidget.Adder adder = gridWidget.createAdder(2);
adder.add(ButtonWidget.builder(Text.translatable("skyblocker.waypoints.importWaypointsSkyblocker"), buttonImport -> {
try {
- List<WaypointGroup> waypointGroups = Waypoints.fromSkyblocker(client.keyboard.getClipboard());
+ List<WaypointGroup> waypointGroups = Waypoints.fromSkyblocker(client.keyboard.getClipboard(), island);
for (WaypointGroup waypointGroup : waypointGroups) {
selectedWaypoints.addAll(waypointGroup.waypoints());
waypoints.put(waypointGroup.island(), waypointGroup);
diff --git a/src/main/java/de/hysky/skyblocker/utils/InstancedUtils.java b/src/main/java/de/hysky/skyblocker/utils/InstancedUtils.java
index 063240b9..c356f322 100644
--- a/src/main/java/de/hysky/skyblocker/utils/InstancedUtils.java
+++ b/src/main/java/de/hysky/skyblocker/utils/InstancedUtils.java
@@ -14,7 +14,8 @@ import org.slf4j.Logger;
import com.mojang.logging.LogUtils;
-import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
+import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
+import it.unimi.dsi.fastutil.objects.ObjectSet;
/**
* @implNote If implementing any of these onto a class, ensure that all subclasses have an implementation of the methods too.
@@ -71,7 +72,7 @@ public class InstancedUtils {
try {
Field[] fields = getClassFields(type);
MethodHandle[] getters = getFieldGetters(fields);
- String fieldNames = String.join(";", Arrays.stream(fields).map(Field::getName).toArray(String[]::new));
+ String fieldNames = String.join(";", Arrays.stream(fields).filter(InstancedUtils::nonStatic).map(Field::getName).toArray(String[]::new));
MethodHandle toStringHandle = (MethodHandle) ObjectMethods.bootstrap(MethodHandles.lookup(), "toString", MethodHandle.class, type, fieldNames, getters);
@@ -90,10 +91,11 @@ public class InstancedUtils {
}
private static MethodHandle[] getFieldGetters(Field[] fields) throws Throwable {
- ObjectOpenHashSet<MethodHandle> handles = new ObjectOpenHashSet<>();
+ // Keep insertion order to make sure getters and field names match
+ ObjectSet<MethodHandle> handles = new ObjectLinkedOpenHashSet<>();
for (Field field : fields) {
- if ((field.getModifiers() & Modifier.STATIC) != 0) continue;
+ if (!nonStatic(field)) continue;
field.setAccessible(true);
@@ -104,4 +106,8 @@ public class InstancedUtils {
return handles.toArray(MethodHandle[]::new);
}
+
+ private static boolean nonStatic(Field field) {
+ return (field.getModifiers() & Modifier.STATIC) == 0;
+ }
}
diff --git a/src/main/java/de/hysky/skyblocker/utils/waypoint/NamedWaypoint.java b/src/main/java/de/hysky/skyblocker/utils/waypoint/NamedWaypoint.java
index ee3a098b..8387be4d 100644
--- a/src/main/java/de/hysky/skyblocker/utils/waypoint/NamedWaypoint.java
+++ b/src/main/java/de/hysky/skyblocker/utils/waypoint/NamedWaypoint.java
@@ -9,6 +9,7 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.utils.CodecUtils;
import de.hysky.skyblocker.utils.ColorUtils;
import de.hysky.skyblocker.utils.render.RenderHelper;
+import it.unimi.dsi.fastutil.floats.FloatArrayList;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
import net.minecraft.text.Text;
import net.minecraft.text.TextCodecs;
@@ -50,6 +51,11 @@ public class NamedWaypoint extends Waypoint {
CodecUtils.optionalDouble(Codec.DOUBLE.optionalFieldOf("b")).forGetter(waypoint -> OptionalDouble.of(waypoint.colorComponents[2])),
ColeweightOptions.CODEC.optionalFieldOf("options").forGetter(waypoint -> Optional.of(new ColeweightOptions(Optional.of(waypoint.name.getString()))))
).apply(instance, NamedWaypoint::fromColeweight));
+ static final Codec<NamedWaypoint> SKYBLOCKER_LEGACY_ORDERED_CODEC = RecordCodecBuilder.create(instance -> instance.group(
+ BlockPos.CODEC.fieldOf("pos").forGetter(waypoint -> waypoint.pos),
+ Codec.floatRange(0, 1).listOf().xmap(Floats::toArray, FloatArrayList::new).optionalFieldOf("colorComponents", new float[0]).forGetter(waypoint -> waypoint.colorComponents)
+ ).apply(instance, (pos, colorComponents) -> new OrderedNamedWaypoint(pos, "", new float[]{0, 1, 0})));
+
public final Text name;
public final Vec3d centerPos;
diff --git a/src/main/java/de/hysky/skyblocker/utils/waypoint/WaypointGroup.java b/src/main/java/de/hysky/skyblocker/utils/waypoint/WaypointGroup.java
index 978c75c4..200b4eaa 100644
--- a/src/main/java/de/hysky/skyblocker/utils/waypoint/WaypointGroup.java
+++ b/src/main/java/de/hysky/skyblocker/utils/waypoint/WaypointGroup.java
@@ -25,6 +25,14 @@ public class WaypointGroup {
NamedWaypoint.SKYTILS_CODEC.listOf().fieldOf("waypoints").forGetter(WaypointGroup::waypoints)
).apply(instance, WaypointGroup::new));
public static final Codec<WaypointGroup> COLEWEIGHT_CODEC = NamedWaypoint.COLEWEIGHT_CODEC.listOf().xmap(coleWeightWaypoints -> new WaypointGroup("Coleweight", Location.UNKNOWN, coleWeightWaypoints, true), WaypointGroup::waypoints);
+ public static final Codec<WaypointGroup> SKYBLOCKER_LEGACY_ORDERED_CODEC = RecordCodecBuilder.create(instance -> instance.group(
+ Codec.STRING.fieldOf("name").forGetter(WaypointGroup::name),
+ Codec.BOOL.fieldOf("enabled").forGetter(group -> !group.waypoints().isEmpty() && group.waypoints().stream().allMatch(Waypoint::isEnabled)),
+ NamedWaypoint.SKYBLOCKER_LEGACY_ORDERED_CODEC.listOf().fieldOf("waypoints").forGetter(WaypointGroup::waypoints)
+ ).apply(instance, (name, enabled, waypoints) -> {
+ waypoints.forEach(enabled ? Waypoint::setMissing : Waypoint::setFound);
+ return new WaypointGroup(name, Location.UNKNOWN, waypoints, true);
+ }));
public static final int WAYPOINT_ACTIVATION_RADIUS = 2;
private final String name;