Skip to content

Commit

Permalink
Add unit test for loading waypoint file
Browse files Browse the repository at this point in the history
  • Loading branch information
Earthcomputer committed Jan 17, 2025
1 parent 8d83538 commit 0ab199e
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 29 deletions.
41 changes: 22 additions & 19 deletions src/main/java/net/earthcomputer/clientcommands/ClientCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.commands.CommandBuildContext;
import org.slf4j.Logger;
Expand All @@ -37,25 +36,11 @@

public class ClientCommands implements ClientModInitializer {
private static final Logger LOGGER = LogUtils.getLogger();
public static Path configDir;
public static final Path CONFIG_DIR = FabricLoader.getInstance().getConfigDir().resolve("clientcommands");
private static final Set<String> clientcommandsCommands = new HashSet<>();
private static final Set<String> COMMANDS_TO_NOT_SEND_TO_SERVER = Set.of("cwe", "cnote"); // could contain private information

public static final boolean SCRAMBLE_WINDOW_TITLE = Util.make(() -> {
String playerUUID = String.valueOf(Minecraft.getInstance().getUser().getProfileId());

Set<String> victims = Set.of(
"fa68270b-1071-46c6-ac5c-6c4a0b777a96", // Earthcomputer
"d4557649-e553-413e-a019-56d14548df96", // Azteched
"8dc3d945-cf90-47c1-a122-a576319d05a7", // samnrad
"c5d72740-cabc-42d1-b789-27859041d553", // allocator
"e4093360-a200-4f99-aa13-be420b8d9a79", // Rybot666
"083fb87e-c9e4-4489-8fb7-a45b06bfca90", // Kerbaras
"973e8f6e-2f51-4307-97dc-56fdc71d194f" // KatieTheQt
);

return victims.contains(playerUUID) || Boolean.getBoolean("clientcommands.scrambleWindowTitle");
});
public static boolean scrambleWindowTitle = false;

private static final Set<String> CHAT_COMMAND_USERS = Set.of(
"b793c3b9-425f-4dd8-a056-9dec4d835e24", // wsb
Expand All @@ -65,10 +50,11 @@ public class ClientCommands implements ClientModInitializer {

@Override
public void onInitializeClient() {
setupScrambleWindowTitle();

// Config
configDir = FabricLoader.getInstance().getConfigDir().resolve("clientcommands");
try {
Files.createDirectories(configDir);
Files.createDirectories(CONFIG_DIR);
} catch (IOException e) {
LOGGER.error("Failed to create config dir", e);
}
Expand All @@ -94,6 +80,23 @@ public void onInitializeClient() {
WaypointCommand.registerEvents();
}

private static void setupScrambleWindowTitle() {
// can't set this up during class initializer, because Minecraft.getInstance() is null during automated tests
String playerUUID = String.valueOf(Minecraft.getInstance().getUser().getProfileId());

Set<String> victims = Set.of(
"fa68270b-1071-46c6-ac5c-6c4a0b777a96", // Earthcomputer
"d4557649-e553-413e-a019-56d14548df96", // Azteched
"8dc3d945-cf90-47c1-a122-a576319d05a7", // samnrad
"c5d72740-cabc-42d1-b789-27859041d553", // allocator
"e4093360-a200-4f99-aa13-be420b8d9a79", // Rybot666
"083fb87e-c9e4-4489-8fb7-a45b06bfca90", // Kerbaras
"973e8f6e-2f51-4307-97dc-56fdc71d194f" // KatieTheQt
);

scrambleWindowTitle = victims.contains(playerUUID) || Boolean.getBoolean("clientcommands.scrambleWindowTitle");
}

private static Set<String> getCommands(CommandDispatcher<?> dispatcher) {
return dispatcher.getRoot().getChildren().stream().flatMap(node -> node instanceof LiteralCommandNode<?> literal ? Stream.of(literal.getLiteral()) : Stream.empty()).collect(Collectors.toSet());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.VisibleForTesting;
import org.joml.Vector2d;
import org.slf4j.Logger;

Expand Down Expand Up @@ -235,10 +236,10 @@ private static void saveFile() throws CommandSyntaxException {
result.put(entry.getKey(), waypoint);
}, CompoundTag::merge)));
rootTag.put("Waypoints", compoundTag);
Path newFile = Files.createTempFile(ClientCommands.configDir, "waypoints", ".dat");
Path newFile = Files.createTempFile(ClientCommands.CONFIG_DIR, "waypoints", ".dat");
NbtIo.write(rootTag, newFile);
Path backupFile = ClientCommands.configDir.resolve("waypoints.dat_old");
Path currentFile = ClientCommands.configDir.resolve("waypoints.dat");
Path backupFile = ClientCommands.CONFIG_DIR.resolve("waypoints.dat_old");
Path currentFile = ClientCommands.CONFIG_DIR.resolve("waypoints.dat");
Util.safeReplaceFile(currentFile, newFile, backupFile);
} catch (IOException e) {
throw SAVE_FAILED_EXCEPTION.create();
Expand All @@ -247,11 +248,17 @@ private static void saveFile() throws CommandSyntaxException {

private static void loadFile() throws Exception {
waypoints.clear();
CompoundTag rootTag = NbtIo.read(ClientCommands.configDir.resolve("waypoints.dat"));
CompoundTag rootTag = NbtIo.read(ClientCommands.CONFIG_DIR.resolve("waypoints.dat"));
if (rootTag == null) {
return;
}
// TODO: update-sensitive: apply custom data fixes when it becomes necessary
waypoints.putAll(deserializeWaypoints(rootTag));
}

@VisibleForTesting
public static Map<String, Map<String, WaypointLocation>> deserializeWaypoints(CompoundTag rootTag) {
Map<String, Map<String, WaypointLocation>> waypoints = new HashMap<>();

CompoundTag compoundTag = rootTag.getCompound("Waypoints");
compoundTag.getAllKeys().forEach(worldIdentifier -> {
CompoundTag worldWaypoints = compoundTag.getCompound(worldIdentifier);
Expand All @@ -263,6 +270,8 @@ private static void loadFile() throws Exception {
return new WaypointLocation(dimension, pos);
})));
});

return waypoints;
}

private static Component formatCoordinates(BlockPos waypoint) {
Expand Down Expand Up @@ -411,7 +420,8 @@ private static void renderWaypointBoxes(WorldRenderContext context) {
});
}

record WaypointLocation(ResourceKey<Level> dimension, BlockPos location) {
@VisibleForTesting
public record WaypointLocation(ResourceKey<Level> dimension, BlockPos location) {
}

record WaypointLabelLocation(Component label, int location) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
public class ClientCommandFunctions {
private static final Logger LOGGER = LogUtils.getLogger();

private static final Path FUNCTION_DIR = ClientCommands.configDir.resolve("functions");
private static final Path FUNCTION_DIR = ClientCommands.CONFIG_DIR.resolve("functions");

private static final DynamicCommandExceptionType NO_SUCH_FUNCTION_EXCEPTION = new DynamicCommandExceptionType(id -> Component.translatable("arguments.function.unknown", id));
private static final DynamicCommandExceptionType COMMAND_LIMIT_REACHED_EXCEPTION = new DynamicCommandExceptionType(limit -> Component.translatable("commands.cfunction.limitReached", limit));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class MinecraftMixin {
// Earth annoying his friends <3 nothing to see here
@Inject(method = "createTitle", at = @At("RETURN"), cancellable = true)
private void modifyWindowTitle(CallbackInfoReturnable<String> ci) {
if (ClientCommands.SCRAMBLE_WINDOW_TITLE) {
if (ClientCommands.scrambleWindowTitle) {
List<Character> chars = ci.getReturnValue().chars().mapToObj(c -> (char) c).collect(Collectors.toCollection(ArrayList::new));
Collections.shuffle(chars);
ci.setReturnValue(chars.stream().map(String::valueOf).collect(Collectors.joining()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ private void handleStackTrace(int stackTrace) {
public void writeToFile() {
try {
this.nbtStream.close();
Path debugDir = ClientCommands.configDir.resolve("debug");
Path debugDir = ClientCommands.CONFIG_DIR.resolve("debug");
Files.createDirectories(debugDir);
try (DataOutputStream dataOutput = new DataOutputStream(new GZIPOutputStream(Files.newOutputStream(debugDir.resolve(this.entity.getStringUUID() + ".dat"))))) {
dataOutput.writeInt(stackTraceById.size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public static void load() {

private static final Logger LOGGER = LogUtils.getLogger();

private static final Path MAPPINGS_DIR = ClientCommands.configDir.resolve("mappings");
private static final Path MAPPINGS_DIR = ClientCommands.CONFIG_DIR.resolve("mappings");

private static final boolean IS_DEV_ENV = FabricLoader.getInstance().isDevelopmentEnvironment();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package net.earthcomputer.clientcommands.test;

import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.earthcomputer.clientcommands.command.WaypointCommand;
import net.minecraft.SharedConstants;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.TagParser;
import net.minecraft.server.Bootstrap;
import net.minecraft.world.level.Level;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

public final class WaypointLoadingTest {
@BeforeAll
public static void setup() {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
}

private static CompoundTag parseSnbt(String snbt) {
try {
return new TagParser(new StringReader(snbt)).readStruct();
} catch (CommandSyntaxException e) {
throw new AssertionError(e);
}
}

@Test
public void testWaypointLoading() {
CompoundTag waypointTag = parseSnbt("""
{
DataVersion: 4189,
Waypoints: {
foo: {
testWaypoint: {
pos: [I; 1, 2, 3],
Dimension: "minecraft:overworld"
}
}
}
}
""");

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());
}
}

0 comments on commit 0ab199e

Please sign in to comment.