diff --git a/src/main/java/net/earthcomputer/clientcommands/Configs.java b/src/main/java/net/earthcomputer/clientcommands/Configs.java index c9387539..a82988a2 100644 --- a/src/main/java/net/earthcomputer/clientcommands/Configs.java +++ b/src/main/java/net/earthcomputer/clientcommands/Configs.java @@ -182,4 +182,7 @@ public enum PacketDumpMethod { public static void setMinimumReplyDelaySeconds(float minimumReplyDelaySeconds) { Configs.minimumReplyDelaySeconds = Math.clamp(minimumReplyDelaySeconds, 0.0f, ReplyCommand.MAXIMUM_REPLY_DELAY_SECONDS); } + + @Config(comment = "Distance after which to stop rendering waypoint labels; put a negative value to disable") + public static int waypointLabelRenderLimit = -1; } diff --git a/src/main/java/net/earthcomputer/clientcommands/command/WaypointCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/WaypointCommand.java index e44b249c..988f245a 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/WaypointCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/WaypointCommand.java @@ -10,11 +10,13 @@ import com.mojang.logging.LogUtils; import com.mojang.serialization.Dynamic; import net.earthcomputer.clientcommands.ClientCommands; +import net.earthcomputer.clientcommands.Configs; import net.earthcomputer.clientcommands.render.RenderQueue; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.fabricmc.fabric.api.util.BooleanFunction; import net.minecraft.ChatFormatting; import net.minecraft.SharedConstants; import net.minecraft.Util; @@ -27,7 +29,6 @@ import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.ShapeRenderer; -import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtIo; @@ -39,10 +40,12 @@ import net.minecraft.network.chat.ComponentUtils; import net.minecraft.network.chat.HoverEvent; import net.minecraft.resources.ResourceKey; +import net.minecraft.util.ARGB; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.VisibleForTesting; import org.joml.Vector2d; import org.slf4j.Logger; @@ -56,14 +59,17 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; import static com.mojang.brigadier.arguments.BoolArgumentType.*; import static com.mojang.brigadier.arguments.StringArgumentType.*; import static dev.xpple.clientarguments.arguments.CBlockPosArgument.*; +import static dev.xpple.clientarguments.arguments.CColorArgument.*; import static dev.xpple.clientarguments.arguments.CDimensionArgument.*; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*; +import static net.minecraft.commands.SharedSuggestionProvider.*; public class WaypointCommand { @@ -74,6 +80,9 @@ public class WaypointCommand { private static final SimpleCommandExceptionType SAVE_FAILED_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cwaypoint.saveFailed")); private static final DynamicCommandExceptionType ALREADY_EXISTS_EXCEPTION = new DynamicCommandExceptionType(name -> Component.translatable("commands.cwaypoint.alreadyExists", name)); private static final DynamicCommandExceptionType NOT_FOUND_EXCEPTION = new DynamicCommandExceptionType(name -> Component.translatable("commands.cwaypoint.notFound", name)); + private static final DynamicCommandExceptionType ALREADY_VISIBLE_EXCEPTION = new DynamicCommandExceptionType(name -> Component.translatable("commands.cwaypoint.alreadyVisible", name)); + private static final DynamicCommandExceptionType ALREADY_HIDDEN_EXCEPTION = new DynamicCommandExceptionType(name -> Component.translatable("commands.cwaypoint.alreadyHidden", name)); + private static final DynamicCommandExceptionType INVALID_COLOR_EXCEPTION = new DynamicCommandExceptionType(color -> Component.translatableEscape("commands.cwaypoint.invalidColor", color)); static { try { @@ -90,30 +99,57 @@ public static void register(CommandDispatcher dispatc .then(argument("pos", blockPos()) .executes(ctx -> add(ctx.getSource(), getString(ctx, "name"), getBlockPos(ctx, "pos"))) .then(argument("dimension", dimension()) - .executes(ctx -> add(ctx.getSource(), getString(ctx, "name"), getBlockPos(ctx, "pos"), getDimension(ctx, "dimension"))))))) + .executes(ctx -> add(ctx.getSource(), getString(ctx, "name"), getBlockPos(ctx, "pos"), getDimension(ctx, "dimension"))) + .then(argument("color", color()) + .executes(ctx -> add(ctx.getSource(), getString(ctx, "name"), getBlockPos(ctx, "pos"), getDimension(ctx, "dimension"), getColor(ctx, "color")))))))) .then(literal("remove") .then(argument("name", word()) .suggests((ctx, builder) -> { Map worldWaypoints = waypoints.get(getWorldIdentifier(ctx.getSource().getClient())); - return SharedSuggestionProvider.suggest(worldWaypoints != null ? worldWaypoints.keySet() : Collections.emptySet(), builder); + return suggest(worldWaypoints != null ? worldWaypoints.keySet() : Collections.emptySet(), builder); }) .executes(ctx -> remove(ctx.getSource(), getString(ctx, "name"))))) + .then(literal("show") + .then(argument("name", word()) + .suggests((ctx, builder) -> { + Map worldWaypoints = waypoints.get(getWorldIdentifier(ctx.getSource().getClient())); + return suggest(partitionWaypointsByVisibility(worldWaypoints).get(false), builder); + }) + .executes(ctx -> toggleVisibility(ctx.getSource(), getString(ctx, "name"), true)))) + .then(literal("hide") + .then(argument("name", word()) + .suggests((ctx, builder) -> { + Map worldWaypoints = waypoints.get(getWorldIdentifier(ctx.getSource().getClient())); + return suggest(partitionWaypointsByVisibility(worldWaypoints).get(true), builder); + }) + .executes(ctx -> toggleVisibility(ctx.getSource(), getString(ctx, "name"), false)))) .then(literal("edit") .then(argument("name", word()) .suggests((ctx, builder) -> { Map worldWaypoints = waypoints.get(getWorldIdentifier(ctx.getSource().getClient())); - return SharedSuggestionProvider.suggest(worldWaypoints != null ? worldWaypoints.keySet() : Collections.emptySet(), builder); + return suggest(worldWaypoints != null ? worldWaypoints.keySet() : Collections.emptySet(), builder); }) .then(argument("pos", blockPos()) .executes(ctx -> edit(ctx.getSource(), getString(ctx, "name"), getBlockPos(ctx, "pos"))) .then(argument("dimension", dimension()) - .executes(ctx -> edit(ctx.getSource(), getString(ctx, "name"), getBlockPos(ctx, "pos"), getDimension(ctx, "dimension"))))))) + .executes(ctx -> edit(ctx.getSource(), getString(ctx, "name"), getBlockPos(ctx, "pos"), getDimension(ctx, "dimension"))) + .then(argument("color", color()) + .executes(ctx -> edit(ctx.getSource(), getString(ctx, "name"), getBlockPos(ctx, "pos"), getDimension(ctx, "dimension"), getColor(ctx, "color")))))))) .then(literal("list") .executes(ctx -> list(ctx.getSource())) .then(argument("current", bool()) .executes(ctx -> list(ctx.getSource(), getBool(ctx, "current")))))); } + private static Map> partitionWaypointsByVisibility(@Nullable Map waypoints) { + if (waypoints == null) { + return Map.of(true, Collections.emptySet(), false, Collections.emptySet()); + } + // wanted to use Collectors#partitioningBy + return waypoints.entrySet().stream() + .collect(Collectors.partitioningBy(entry -> entry.getValue().visible(), Collectors.mapping(Map.Entry::getKey, Collectors.toSet()))); + } + private static String getWorldIdentifier(Minecraft minecraft) { String worldIdentifier; if (minecraft.hasSingleplayerServer()) { @@ -130,24 +166,28 @@ private static int add(FabricClientCommandSource source, String name, BlockPos p } private static int add(FabricClientCommandSource source, String name, BlockPos pos, ResourceKey dimension) throws CommandSyntaxException { - String worldIdentifier = getWorldIdentifier(source.getClient()); + return add(source, name, pos, dimension, ChatFormatting.WHITE); + } + private static int add(FabricClientCommandSource source, String name, BlockPos pos, ResourceKey dimension, ChatFormatting color) throws CommandSyntaxException { + if (color == ChatFormatting.RESET) { + throw INVALID_COLOR_EXCEPTION.create(color.getName()); + } + String worldIdentifier = getWorldIdentifier(source.getClient()); Map worldWaypoints = waypoints.computeIfAbsent(worldIdentifier, key -> new HashMap<>()); - - if (worldWaypoints.putIfAbsent(name, new WaypointLocation(dimension, pos)) != null) { + //noinspection DataFlowIssue + if (worldWaypoints.putIfAbsent(name, new WaypointLocation(dimension, pos, true, color.getColor())) != null) { throw ALREADY_EXISTS_EXCEPTION.create(name); } saveFile(); - source.sendFeedback(Component.translatable("commands.cwaypoint.add.success", name, formatCoordinates(pos), dimension.location())); + source.sendFeedback(Component.translatable("commands.cwaypoint.add.success", name, formatCoordinates(pos), dimension.location(), color.getName())); return Command.SINGLE_SUCCESS; } private static int remove(FabricClientCommandSource source, String name) throws CommandSyntaxException { String worldIdentifier = getWorldIdentifier(source.getClient()); - Map worldWaypoints = waypoints.get(worldIdentifier); - if (worldWaypoints == null) { throw NOT_FOUND_EXCEPTION.create(name); } @@ -161,25 +201,58 @@ private static int remove(FabricClientCommandSource source, String name) throws return Command.SINGLE_SUCCESS; } + private static int toggleVisibility(FabricClientCommandSource source, String name, boolean visible) throws CommandSyntaxException { + String worldIdentifier = getWorldIdentifier(source.getClient()); + Map worldWaypoints = waypoints.get(worldIdentifier); + if (worldWaypoints == null) { + throw NOT_FOUND_EXCEPTION.create(name); + } + + WaypointLocation waypoint = worldWaypoints.get(name); + if (waypoint == null) { + throw NOT_FOUND_EXCEPTION.create(name); + } + if (waypoint.visible() && visible) { + throw ALREADY_VISIBLE_EXCEPTION.create(name); + } else if (!waypoint.visible() && !visible) { + throw ALREADY_HIDDEN_EXCEPTION.create(name); + } + worldWaypoints.put(name, new WaypointLocation(waypoint.dimension, waypoint.location, visible, waypoint.color)); + + saveFile(); + if (visible) { + source.sendFeedback(Component.translatable("commands.cwaypoint.show.success", name)); + } else { + source.sendFeedback(Component.translatable("commands.cwaypoint.hide.success", name)); + } + return Command.SINGLE_SUCCESS; + } + private static int edit(FabricClientCommandSource source, String name, BlockPos pos) throws CommandSyntaxException { return edit(source, name, pos, source.getWorld().dimension()); } private static int edit(FabricClientCommandSource source, String name, BlockPos pos, ResourceKey dimension) throws CommandSyntaxException { - String worldIdentifier = getWorldIdentifier(source.getClient()); + return edit(source, name, pos, dimension, ChatFormatting.WHITE); + } + private static int edit(FabricClientCommandSource source, String name, BlockPos pos, ResourceKey dimension, ChatFormatting color) throws CommandSyntaxException { + if (color == ChatFormatting.RESET) { + throw INVALID_COLOR_EXCEPTION.create(color.getName()); + } + String worldIdentifier = getWorldIdentifier(source.getClient()); Map worldWaypoints = waypoints.get(worldIdentifier); - if (worldWaypoints == null) { throw NOT_FOUND_EXCEPTION.create(name); } - if (worldWaypoints.computeIfPresent(name, (key, value) -> new WaypointLocation(dimension, pos)) == null) { + //noinspection DataFlowIssue + if (worldWaypoints.computeIfPresent(name, (key, value) -> new WaypointLocation(dimension, pos, value.visible, color.getColor())) == null) { throw NOT_FOUND_EXCEPTION.create(name); } saveFile(); - source.sendFeedback(Component.translatable("commands.cwaypoint.edit.success", name, formatCoordinates(pos), dimension.location())); + source.sendFeedback(Component.translatable("commands.cwaypoint.edit.success", name, formatCoordinates(pos), dimension.location(), color.getName())); return Command.SINGLE_SUCCESS; } @@ -188,17 +261,16 @@ private static int list(FabricClientCommandSource source) { } private static int list(FabricClientCommandSource source, boolean current) { + BooleanFunction getVisibilityComponent = visible -> visible ? Component.translatable("commands.cwaypoint.shown") : Component.translatable("commands.cwaypoint.hidden"); if (current) { String worldIdentifier = getWorldIdentifier(source.getClient()); - Map worldWaypoints = waypoints.get(worldIdentifier); - if (worldWaypoints == null || worldWaypoints.isEmpty()) { source.sendFeedback(Component.translatable("commands.cwaypoint.list.empty")); return 0; } - worldWaypoints.forEach((name, waypoint) -> source.sendFeedback(Component.translatable("commands.cwaypoint.list", name, formatCoordinates(waypoint.location()), waypoint.dimension().location()))); + worldWaypoints.forEach((name, waypoint) -> source.sendFeedback(Component.translatable("commands.cwaypoint.list", name, formatCoordinates(waypoint.location()), waypoint.dimension().location(), getVisibilityComponent.apply(waypoint.visible())))); return worldWaypoints.size(); } @@ -216,7 +288,7 @@ private static int list(FabricClientCommandSource source, boolean current) { count[0] += worldWaypoints.size(); source.sendFeedback(Component.literal(worldIdentifier).append(":")); - worldWaypoints.forEach((name, waypoint) -> source.sendFeedback(Component.translatable("commands.cwaypoint.list", name, formatCoordinates(waypoint.location()), waypoint.dimension().location()))); + worldWaypoints.forEach((name, waypoint) -> source.sendFeedback(Component.translatable("commands.cwaypoint.list", name, formatCoordinates(waypoint.location()), waypoint.dimension().location(), getVisibilityComponent.apply(waypoint.visible())))); }); return count[0]; } @@ -233,6 +305,8 @@ private static void saveFile() throws CommandSyntaxException { waypoint.put("pos", pos); String dimension = entry.getValue().dimension().location().toString(); waypoint.putString("Dimension", dimension); + waypoint.putBoolean("Visible", entry.getValue().visible()); + waypoint.putInt("Color", entry.getValue().color()); result.put(entry.getKey(), waypoint); }, CompoundTag::merge))); rootTag.put("Waypoints", compoundTag); @@ -242,6 +316,7 @@ private static void saveFile() throws CommandSyntaxException { Path currentFile = ClientCommands.CONFIG_DIR.resolve("waypoints.dat"); Util.safeReplaceFile(currentFile, newFile, backupFile); } catch (IOException e) { + LOGGER.error("Could not save waypoints file", e); throw SAVE_FAILED_EXCEPTION.create(); } } @@ -267,7 +342,9 @@ public static Map> deserializeWaypoints(Co CompoundTag waypoint = worldWaypoints.getCompound(name); BlockPos pos = NbtUtils.readBlockPos(waypoint, "pos").orElseThrow(); ResourceKey dimension = Level.RESOURCE_KEY_CODEC.parse(new Dynamic<>(NbtOps.INSTANCE, waypoint.get("Dimension"))).resultOrPartial(LOGGER::error).orElseThrow(); - return new WaypointLocation(dimension, pos); + boolean visible = waypoint.getBoolean("Visible"); + int color = waypoint.getInt("Color"); + return new WaypointLocation(dimension, pos, visible, color); }))); }); @@ -310,12 +387,18 @@ private static void renderWaypointLabels(GuiGraphics guiGraphics, DeltaTracker d List xPositions = new ArrayList<>(); waypoints.forEach((waypointName, waypoint) -> { + if (!waypoint.visible()) { + return; + } if (!waypoint.dimension().location().equals(minecraft.level.dimension().location())) { return; } double distanceSquared = waypoint.location().distToCenterSqr(cameraEntity.position()); long distance = Math.round(Math.sqrt(distanceSquared)); + if (Configs.waypointLabelRenderLimit >= 0 && distance > Configs.waypointLabelRenderLimit) { + return; + } Component label = ComponentUtils.wrapInSquareBrackets(Component.literal(waypointName + ' ' + distance).withStyle(ChatFormatting.YELLOW)); Vector2d waypointLocation = new Vector2d(waypoint.location().getX(), waypoint.location().getZ()); @@ -387,6 +470,9 @@ private static void renderWaypointBoxes(WorldRenderContext context) { ClientChunkCache chunkSource = context.world().getChunkSource(); waypoints.forEach((waypointName, waypoint) -> { + if (!waypoint.visible()) { + return; + } if (!waypoint.dimension().location().equals(context.world().dimension().location())) { return; } @@ -405,7 +491,9 @@ private static void renderWaypointBoxes(WorldRenderContext context) { stack.translate(cameraPosition.scale(-1)); AABB box = new AABB(waypointLocation); - ShapeRenderer.renderLineBox(stack, context.consumers().getBuffer(RenderQueue.NO_DEPTH_LAYER), box, 1, 1, 1, 1); + + int color = waypoint.color(); + ShapeRenderer.renderLineBox(stack, context.consumers().getBuffer(RenderQueue.NO_DEPTH_LAYER), box, ARGB.red(color) / 255.0f, ARGB.green(color) / 255.0f, ARGB.blue(color) / 255.0f, ARGB.alpha(color) / 255.0f); stack.translate(waypointLocation.getCenter().add(new Vec3(0, 1, 0))); stack.mulPose(context.camera().rotation()); @@ -413,15 +501,15 @@ private static void renderWaypointBoxes(WorldRenderContext context) { Font font = Minecraft.getInstance().font; int width = font.width(waypointName) / 2; - int backgroundColour = (int) (Minecraft.getInstance().options.getBackgroundOpacity(0.25f) * 255.0f) << 24; - font.drawInBatch(waypointName, -width, 0, 0xFFFFFF, false, stack.last().pose(), context.consumers(), Font.DisplayMode.SEE_THROUGH, backgroundColour, LightTexture.FULL_SKY); + int backgroundColor = (int) (Minecraft.getInstance().options.getBackgroundOpacity(0.25f) * 255.0f) << 24; + font.drawInBatch(waypointName, -width, 0, 0xFFFFFF, false, stack.last().pose(), context.consumers(), Font.DisplayMode.SEE_THROUGH, backgroundColor, LightTexture.FULL_SKY); stack.popPose(); }); } @VisibleForTesting - public record WaypointLocation(ResourceKey dimension, BlockPos location) { + public record WaypointLocation(ResourceKey dimension, BlockPos location, boolean visible, int color) { } record WaypointLabelLocation(Component label, int location) { diff --git a/src/main/java/net/earthcomputer/clientcommands/datafix/WaypointAddVisibilityAndColorIfNotPresentFix.java b/src/main/java/net/earthcomputer/clientcommands/datafix/WaypointAddVisibilityAndColorIfNotPresentFix.java new file mode 100644 index 00000000..bf9860df --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/datafix/WaypointAddVisibilityAndColorIfNotPresentFix.java @@ -0,0 +1,28 @@ +package net.earthcomputer.clientcommands.datafix; + +import com.mojang.datafixers.DataFix; +import com.mojang.datafixers.TypeRewriteRule; +import com.mojang.datafixers.schemas.Schema; + +public class WaypointAddVisibilityAndColorIfNotPresentFix extends DataFix { + + private static final String VISIBILITY_KEY = "Visible"; + private static final String COLOR_KEY = "Color"; + + private final boolean visible; + private final int color; + private final String name; + + public WaypointAddVisibilityAndColorIfNotPresentFix(Schema outputSchema, boolean visible, int color) { + super(outputSchema, true); + this.visible = visible; + this.color = color; + this.name = "WaypointAddVisibilityIfNotPresentFix_" + VISIBILITY_KEY + "=" + this.visible + "_" + COLOR_KEY + "=" + this.color + " for " + outputSchema.getVersionKey(); + } + + @Override + protected TypeRewriteRule makeRule() { + // TODO + return null; + } +} diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/datafix/DataFixersMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/datafix/DataFixersMixin.java new file mode 100644 index 00000000..1154ba27 --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/datafix/DataFixersMixin.java @@ -0,0 +1,23 @@ +package net.earthcomputer.clientcommands.mixin.datafix; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.datafixers.DataFixerBuilder; +import com.mojang.datafixers.schemas.Schema; +import net.minecraft.util.datafix.DataFixers; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Slice; + +@Mixin(DataFixers.class) +public class DataFixersMixin { + @ModifyExpressionValue( + method = "addFixers", + slice = @Slice(from = @At(value = "CONSTANT", args = "intValue=4187")), + at = @At(value = "INVOKE", target = "Lcom/mojang/datafixers/DataFixerBuilder;addSchema(ILjava/util/function/BiFunction;)Lcom/mojang/datafixers/schemas/Schema;", ordinal = 0, remap = false)) + private static Schema addFixers(Schema original, @Local(argsOnly = true) DataFixerBuilder builder) { + // TODO + // builder.addFixer(new WaypointAddVisibilityIfNotPresentFix(original, true, ChatFormatting.WHITE.getColor())); + return original; + } +} diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index db2a95cc..5e6f129f 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -286,14 +286,21 @@ "commands.cvar.remove.success": "Successfully removed variable \"%s\"", "commands.cvar.saveFile.failed": "Could not save variables file", - "commands.cwaypoint.add.success": "Waypoint \"%s\" at %s in %s successfully added", + "commands.cwaypoint.add.success": "Waypoint \"%s\" at %s in %s with color %s successfully added", "commands.cwaypoint.alreadyExists": "A waypoint with the name \"%s\" already exists", - "commands.cwaypoint.edit.success": "Waypoint \"%s\" has successfully been changed to %s in %s", - "commands.cwaypoint.list": "- \"%s\" at %s in %s", + "commands.cwaypoint.alreadyHidden": "This waypoint is already hidden", + "commands.cwaypoint.alreadyVisible": "This waypoint is already visible", + "commands.cwaypoint.edit.success": "Waypoint \"%s\" has successfully been changed to %s in %s with color %s", + "commands.cwaypoint.hidden": "hidden", + "commands.cwaypoint.hide.success": "Now hiding %s", + "commands.cwaypoint.invalidColor": "The color %s is invalid", + "commands.cwaypoint.list": "- \"%s\" at %s in %s (%s)", "commands.cwaypoint.list.empty": "No available waypoints", "commands.cwaypoint.notFound": "No waypoint with the name \"%s\" could be found", "commands.cwaypoint.remove.success": "Waypoint \"%s\" successfully removed", "commands.cwaypoint.saveFailed": "Could not save waypoints file", + "commands.cwaypoint.show.success": "Now showing %s", + "commands.cwaypoint.shown": "shown", "commands.cwe.playerNotFound": "Player not found", diff --git a/src/main/resources/mixins.clientcommands.json b/src/main/resources/mixins.clientcommands.json index 3777cf45..348f9fdc 100644 --- a/src/main/resources/mixins.clientcommands.json +++ b/src/main/resources/mixins.clientcommands.json @@ -19,6 +19,7 @@ "commands.render.EntityRendererDispatcherMixin", "commands.time.ClientLevelDataMixin", "commands.weather.LevelMixin", + "datafix.DataFixersMixin", "debug.EntityMixin", "debug.ServerLevelMixin", "events.MinecraftMixin", diff --git a/src/test/java/net/earthcomputer/clientcommands/test/WaypointLoadingTest.java b/src/test/java/net/earthcomputer/clientcommands/test/WaypointLoadingTest.java index b2ce5f05..51459df9 100644 --- a/src/test/java/net/earthcomputer/clientcommands/test/WaypointLoadingTest.java +++ b/src/test/java/net/earthcomputer/clientcommands/test/WaypointLoadingTest.java @@ -3,6 +3,7 @@ import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.earthcomputer.clientcommands.command.WaypointCommand; +import net.minecraft.ChatFormatting; import net.minecraft.SharedConstants; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; @@ -30,7 +31,7 @@ private static CompoundTag parseSnbt(String snbt) { } @Test - public void testWaypointLoading() { + public void testWaypointLoadingWithoutVisibleAndColorKey() { CompoundTag waypointTag = parseSnbt(""" { DataVersion: 4189, @@ -54,5 +55,38 @@ public void testWaypointLoading() { var waypoint = worldWaypoints.get("testWaypoint"); assertEquals(new BlockPos(1, 2, 3), waypoint.location()); assertEquals(Level.OVERWORLD, waypoint.dimension()); + assertTrue(waypoint.visible()); + assertEquals(ChatFormatting.WHITE.getColor(), waypoint.color()); + } + + @Test + public void testWaypointLoading() { + CompoundTag waypointTag = parseSnbt(""" + { + DataVersion: 4189, + Waypoints: { + foo: { + testWaypoint: { + pos: [I; 1, 2, 3], + Dimension: "minecraft:overworld", + Visible: true, + Color: 16733525 + } + } + } + } + """); + + var waypoints = WaypointCommand.deserializeWaypoints(waypointTag); + assertEquals(1, waypoints.size()); + assertTrue(waypoints.containsKey("foo")); + var worldWaypoints = waypoints.get("foo"); + assertEquals(1, worldWaypoints.size()); + assertTrue(worldWaypoints.containsKey("testWaypoint")); + var waypoint = worldWaypoints.get("testWaypoint"); + assertEquals(new BlockPos(1, 2, 3), waypoint.location()); + assertEquals(Level.OVERWORLD, waypoint.dimension()); + assertTrue(waypoint.visible()); + assertEquals(ChatFormatting.RED.getColor(), waypoint.color()); } }