From a15d24270ebfcbdb590c0fa2278d53c8bd313543 Mon Sep 17 00:00:00 2001 From: Frederik van der Els Date: Thu, 20 Mar 2025 18:27:15 +0100 Subject: [PATCH 1/3] Add some improvements to cwaypoint --- .../earthcomputer/clientcommands/Configs.java | 3 + .../command/WaypointCommand.java | 132 +++++++++++++++--- ...AddVisibilityAndColourIfNotPresentFix.java | 28 ++++ .../mixin/datafix/DataFixersMixin.java | 23 +++ .../assets/clientcommands/lang/en_us.json | 13 +- src/main/resources/mixins.clientcommands.json | 1 + .../test/WaypointLoadingTest.java | 36 ++++- 7 files changed, 210 insertions(+), 26 deletions(-) create mode 100644 src/main/java/net/earthcomputer/clientcommands/datafix/WaypointAddVisibilityAndColourIfNotPresentFix.java create mode 100644 src/main/java/net/earthcomputer/clientcommands/mixin/datafix/DataFixersMixin.java 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..929ab28f 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.invalidColour", 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("colour", color()) + .executes(ctx -> add(ctx.getSource(), getString(ctx, "name"), getBlockPos(ctx, "pos"), getDimension(ctx, "dimension"), getColor(ctx, "colour")))))))) .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("colour", color()) + .executes(ctx -> edit(ctx.getSource(), getString(ctx, "name"), getBlockPos(ctx, "pos"), getDimension(ctx, "dimension"), getColor(ctx, "colour")))))))) .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 colour) throws CommandSyntaxException { + if (colour == ChatFormatting.RESET) { + throw INVALID_COLOR_EXCEPTION.create(colour.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, colour.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(), colour.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.colour)); + + 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 colour) throws CommandSyntaxException { + if (colour == ChatFormatting.RESET) { + throw INVALID_COLOR_EXCEPTION.create(colour.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, colour.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(), colour.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("Colour", entry.getValue().colour()); 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 colour = waypoint.getInt("Colour"); + return new WaypointLocation(dimension, pos, visible, colour); }))); }); @@ -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 colour = waypoint.colour(); + ShapeRenderer.renderLineBox(stack, context.consumers().getBuffer(RenderQueue.NO_DEPTH_LAYER), box, ARGB.red(colour) / 255.0f, ARGB.green(colour) / 255.0f, ARGB.blue(colour) / 255.0f, ARGB.alpha(colour) / 255.0f); stack.translate(waypointLocation.getCenter().add(new Vec3(0, 1, 0))); stack.mulPose(context.camera().rotation()); @@ -421,7 +509,7 @@ private static void renderWaypointBoxes(WorldRenderContext context) { } @VisibleForTesting - public record WaypointLocation(ResourceKey dimension, BlockPos location) { + public record WaypointLocation(ResourceKey dimension, BlockPos location, boolean visible, int colour) { } record WaypointLabelLocation(Component label, int location) { diff --git a/src/main/java/net/earthcomputer/clientcommands/datafix/WaypointAddVisibilityAndColourIfNotPresentFix.java b/src/main/java/net/earthcomputer/clientcommands/datafix/WaypointAddVisibilityAndColourIfNotPresentFix.java new file mode 100644 index 00000000..c10aadb1 --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/datafix/WaypointAddVisibilityAndColourIfNotPresentFix.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 WaypointAddVisibilityAndColourIfNotPresentFix extends DataFix { + + private static final String VISIBILITY_KEY = "Visible"; + private static final String COLOUR_KEY = "Colour"; + + private final boolean visible; + private final int colour; + private final String name; + + public WaypointAddVisibilityAndColourIfNotPresentFix(Schema outputSchema, boolean visible, int colour) { + super(outputSchema, true); + this.visible = visible; + this.colour = colour; + this.name = "WaypointAddVisibilityIfNotPresentFix_" + VISIBILITY_KEY + "=" + this.visible + "_" + COLOUR_KEY + "=" + this.colour + " 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..dbe96b51 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 colour %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 colour %s", + "commands.cwaypoint.hidden": "hidden", + "commands.cwaypoint.hide.success": "Now hiding %s", + "commands.cwaypoint.invalidColour": "The colour %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.shown": "shown", + "commands.cwaypoint.show.success": "Now showing %s", "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..3c92effa 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 testWaypointLoadingWithoutVisibleAndColourKey() { 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.colour()); + } + + @Test + public void testWaypointLoading() { + CompoundTag waypointTag = parseSnbt(""" + { + DataVersion: 4189, + Waypoints: { + foo: { + testWaypoint: { + pos: [I; 1, 2, 3], + Dimension: "minecraft:overworld", + Visible: true, + Colour: 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.colour()); } } From 860408a2fe381b612f6930e0157a5c63ccfc6e28 Mon Sep 17 00:00:00 2001 From: Frederik van der Els Date: Thu, 20 Mar 2025 21:56:52 +0100 Subject: [PATCH 2/3] colour -> color --- .../command/WaypointCommand.java | 48 +++++++++---------- ...AddVisibilityAndColorIfNotPresentFix.java} | 12 ++--- .../assets/clientcommands/lang/en_us.json | 6 +-- .../test/WaypointLoadingTest.java | 8 ++-- 4 files changed, 37 insertions(+), 37 deletions(-) rename src/main/java/net/earthcomputer/clientcommands/datafix/{WaypointAddVisibilityAndColourIfNotPresentFix.java => WaypointAddVisibilityAndColorIfNotPresentFix.java} (56%) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/WaypointCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/WaypointCommand.java index 929ab28f..988f245a 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/WaypointCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/WaypointCommand.java @@ -82,7 +82,7 @@ public class WaypointCommand { 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.invalidColour", color)); + private static final DynamicCommandExceptionType INVALID_COLOR_EXCEPTION = new DynamicCommandExceptionType(color -> Component.translatableEscape("commands.cwaypoint.invalidColor", color)); static { try { @@ -100,8 +100,8 @@ public static void register(CommandDispatcher dispatc .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"))) - .then(argument("colour", color()) - .executes(ctx -> add(ctx.getSource(), getString(ctx, "name"), getBlockPos(ctx, "pos"), getDimension(ctx, "dimension"), getColor(ctx, "colour")))))))) + .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) -> { @@ -133,8 +133,8 @@ public static void register(CommandDispatcher dispatc .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"))) - .then(argument("colour", color()) - .executes(ctx -> edit(ctx.getSource(), getString(ctx, "name"), getBlockPos(ctx, "pos"), getDimension(ctx, "dimension"), getColor(ctx, "colour")))))))) + .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()) @@ -169,19 +169,19 @@ private static int add(FabricClientCommandSource source, String name, BlockPos p return add(source, name, pos, dimension, ChatFormatting.WHITE); } - private static int add(FabricClientCommandSource source, String name, BlockPos pos, ResourceKey dimension, ChatFormatting colour) throws CommandSyntaxException { - if (colour == ChatFormatting.RESET) { - throw INVALID_COLOR_EXCEPTION.create(colour.getName()); + 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<>()); //noinspection DataFlowIssue - if (worldWaypoints.putIfAbsent(name, new WaypointLocation(dimension, pos, true, colour.getColor())) != null) { + 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(), colour.getName())); + source.sendFeedback(Component.translatable("commands.cwaypoint.add.success", name, formatCoordinates(pos), dimension.location(), color.getName())); return Command.SINGLE_SUCCESS; } @@ -217,7 +217,7 @@ private static int toggleVisibility(FabricClientCommandSource source, String nam } else if (!waypoint.visible() && !visible) { throw ALREADY_HIDDEN_EXCEPTION.create(name); } - worldWaypoints.put(name, new WaypointLocation(waypoint.dimension, waypoint.location, visible, waypoint.colour)); + worldWaypoints.put(name, new WaypointLocation(waypoint.dimension, waypoint.location, visible, waypoint.color)); saveFile(); if (visible) { @@ -236,9 +236,9 @@ private static int edit(FabricClientCommandSource source, String name, BlockPos return edit(source, name, pos, dimension, ChatFormatting.WHITE); } - private static int edit(FabricClientCommandSource source, String name, BlockPos pos, ResourceKey dimension, ChatFormatting colour) throws CommandSyntaxException { - if (colour == ChatFormatting.RESET) { - throw INVALID_COLOR_EXCEPTION.create(colour.getName()); + 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); @@ -247,12 +247,12 @@ private static int edit(FabricClientCommandSource source, String name, BlockPos } //noinspection DataFlowIssue - if (worldWaypoints.computeIfPresent(name, (key, value) -> new WaypointLocation(dimension, pos, value.visible, colour.getColor())) == null) { + 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(), colour.getName())); + source.sendFeedback(Component.translatable("commands.cwaypoint.edit.success", name, formatCoordinates(pos), dimension.location(), color.getName())); return Command.SINGLE_SUCCESS; } @@ -306,7 +306,7 @@ private static void saveFile() throws CommandSyntaxException { String dimension = entry.getValue().dimension().location().toString(); waypoint.putString("Dimension", dimension); waypoint.putBoolean("Visible", entry.getValue().visible()); - waypoint.putInt("Colour", entry.getValue().colour()); + waypoint.putInt("Color", entry.getValue().color()); result.put(entry.getKey(), waypoint); }, CompoundTag::merge))); rootTag.put("Waypoints", compoundTag); @@ -343,8 +343,8 @@ public static Map> deserializeWaypoints(Co 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(); boolean visible = waypoint.getBoolean("Visible"); - int colour = waypoint.getInt("Colour"); - return new WaypointLocation(dimension, pos, visible, colour); + int color = waypoint.getInt("Color"); + return new WaypointLocation(dimension, pos, visible, color); }))); }); @@ -492,8 +492,8 @@ private static void renderWaypointBoxes(WorldRenderContext context) { AABB box = new AABB(waypointLocation); - int colour = waypoint.colour(); - ShapeRenderer.renderLineBox(stack, context.consumers().getBuffer(RenderQueue.NO_DEPTH_LAYER), box, ARGB.red(colour) / 255.0f, ARGB.green(colour) / 255.0f, ARGB.blue(colour) / 255.0f, ARGB.alpha(colour) / 255.0f); + 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()); @@ -501,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, boolean visible, int colour) { + 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/WaypointAddVisibilityAndColourIfNotPresentFix.java b/src/main/java/net/earthcomputer/clientcommands/datafix/WaypointAddVisibilityAndColorIfNotPresentFix.java similarity index 56% rename from src/main/java/net/earthcomputer/clientcommands/datafix/WaypointAddVisibilityAndColourIfNotPresentFix.java rename to src/main/java/net/earthcomputer/clientcommands/datafix/WaypointAddVisibilityAndColorIfNotPresentFix.java index c10aadb1..bf9860df 100644 --- a/src/main/java/net/earthcomputer/clientcommands/datafix/WaypointAddVisibilityAndColourIfNotPresentFix.java +++ b/src/main/java/net/earthcomputer/clientcommands/datafix/WaypointAddVisibilityAndColorIfNotPresentFix.java @@ -4,20 +4,20 @@ import com.mojang.datafixers.TypeRewriteRule; import com.mojang.datafixers.schemas.Schema; -public class WaypointAddVisibilityAndColourIfNotPresentFix extends DataFix { +public class WaypointAddVisibilityAndColorIfNotPresentFix extends DataFix { private static final String VISIBILITY_KEY = "Visible"; - private static final String COLOUR_KEY = "Colour"; + private static final String COLOR_KEY = "Color"; private final boolean visible; - private final int colour; + private final int color; private final String name; - public WaypointAddVisibilityAndColourIfNotPresentFix(Schema outputSchema, boolean visible, int colour) { + public WaypointAddVisibilityAndColorIfNotPresentFix(Schema outputSchema, boolean visible, int color) { super(outputSchema, true); this.visible = visible; - this.colour = colour; - this.name = "WaypointAddVisibilityIfNotPresentFix_" + VISIBILITY_KEY + "=" + this.visible + "_" + COLOUR_KEY + "=" + this.colour + " for " + outputSchema.getVersionKey(); + this.color = color; + this.name = "WaypointAddVisibilityIfNotPresentFix_" + VISIBILITY_KEY + "=" + this.visible + "_" + COLOR_KEY + "=" + this.color + " for " + outputSchema.getVersionKey(); } @Override diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index dbe96b51..8bf162d2 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -286,14 +286,14 @@ "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 with colour %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.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 colour %s", + "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.invalidColour": "The colour %s is invalid", + "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", diff --git a/src/test/java/net/earthcomputer/clientcommands/test/WaypointLoadingTest.java b/src/test/java/net/earthcomputer/clientcommands/test/WaypointLoadingTest.java index 3c92effa..51459df9 100644 --- a/src/test/java/net/earthcomputer/clientcommands/test/WaypointLoadingTest.java +++ b/src/test/java/net/earthcomputer/clientcommands/test/WaypointLoadingTest.java @@ -31,7 +31,7 @@ private static CompoundTag parseSnbt(String snbt) { } @Test - public void testWaypointLoadingWithoutVisibleAndColourKey() { + public void testWaypointLoadingWithoutVisibleAndColorKey() { CompoundTag waypointTag = parseSnbt(""" { DataVersion: 4189, @@ -56,7 +56,7 @@ public void testWaypointLoadingWithoutVisibleAndColourKey() { assertEquals(new BlockPos(1, 2, 3), waypoint.location()); assertEquals(Level.OVERWORLD, waypoint.dimension()); assertTrue(waypoint.visible()); - assertEquals(ChatFormatting.WHITE.getColor(), waypoint.colour()); + assertEquals(ChatFormatting.WHITE.getColor(), waypoint.color()); } @Test @@ -70,7 +70,7 @@ public void testWaypointLoading() { pos: [I; 1, 2, 3], Dimension: "minecraft:overworld", Visible: true, - Colour: 16733525 + Color: 16733525 } } } @@ -87,6 +87,6 @@ public void testWaypointLoading() { assertEquals(new BlockPos(1, 2, 3), waypoint.location()); assertEquals(Level.OVERWORLD, waypoint.dimension()); assertTrue(waypoint.visible()); - assertEquals(ChatFormatting.RED.getColor(), waypoint.colour()); + assertEquals(ChatFormatting.RED.getColor(), waypoint.color()); } } From 63ebdb1c01bc18e504eff9da09b827022641237b Mon Sep 17 00:00:00 2001 From: Frederik van der Els Date: Thu, 20 Mar 2025 22:02:15 +0100 Subject: [PATCH 3/3] Sort translation keys in "alphabetical" order --- src/main/resources/assets/clientcommands/lang/en_us.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 8bf162d2..5e6f129f 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -299,8 +299,8 @@ "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.shown": "shown", "commands.cwaypoint.show.success": "Now showing %s", + "commands.cwaypoint.shown": "shown", "commands.cwe.playerNotFound": "Player not found",