Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.Objects;
import java.util.Optional;

import net.kyori.adventure.key.Key;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
Expand All @@ -23,6 +24,14 @@ public class IslandChunksCommand extends CompositeCommand {
/** Widest map that still fits comfortably in chat */
private static final int MAX_MAP_RADIUS = 7;

/**
* Minecraft's built-in fixed-width font. Chat's default font is proportional, so a
* grid built from mixed glyphs comes out ragged — a row's width depends on which
* chunks happen to be claimed. Only the map rows use it; the rest of the chat stays
* in the normal font.
*/
private static final Key MONOSPACE_FONT = Key.key("minecraft", "uniform");

private ChunkBlock addon;

public IslandChunksCommand(CompositeCommand islandCommand, String label, String[] aliases) {
Expand Down Expand Up @@ -97,7 +106,8 @@ private void showMap(User user, Island island, int unlocked, int max) {
row.append(here ? "&b◇" : "&7□");
}
}
user.sendMessage("chunkblock.chunks.map.row", "[row]", row.toString());
user.sendMessage(user.getTranslationAsComponent("chunkblock.chunks.map.row", "[row]", row.toString())
.font(MONOSPACE_FONT));
}
user.sendMessage("chunkblock.chunks.map.legend", "[cost]", String.valueOf(cm.getChunkCost()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
Expand All @@ -10,6 +13,10 @@
import java.util.List;
import java.util.Optional;

import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;

import org.bukkit.Location;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -72,6 +79,12 @@ public void setUp() throws Exception {
when(user.getWorld()).thenReturn(world);
when(im.getIslandAt(playerLocation)).thenReturn(Optional.of(island));

// Hand the row string straight back as a component so the test can read it out again
when(user.getTranslationAsComponent(anyString(), any(String[].class))).thenAnswer(invocation -> {
Object[] args = invocation.getArguments();
return Component.text((String) args[args.length - 1]);
});

command = new IslandChunksCommand(ac, "chunks", new String[] { "chunks" });
}

Expand Down Expand Up @@ -130,12 +143,20 @@ void testMapIsCappedAtTheWidestRowThatFitsChat() {
assertEquals(15, mapRows().size());
}

/** The rendered map rows, in order, as passed to the row locale key */
/**
* The rendered map rows, in order. Rows are sent as components so they can carry the
* monospace font, so they are read back out of the component rather than the arguments.
*/
private List<String> mapRows() {
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(user, org.mockito.Mockito.atLeastOnce()).sendMessage(org.mockito.ArgumentMatchers.eq(
"chunkblock.chunks.map.row"), org.mockito.ArgumentMatchers.eq("[row]"), captor.capture());
return new ArrayList<>(captor.getAllValues());
ArgumentCaptor<Component> captor = ArgumentCaptor.forClass(Component.class);
verify(user, atLeastOnce()).sendMessage(captor.capture());
List<String> rows = new ArrayList<>();
for (Component component : captor.getAllValues()) {
assertEquals(Key.key("minecraft", "uniform"), component.font(),
"map rows must be monospaced or the grid comes out ragged");
rows.add(((TextComponent) component).content());
}
return rows;
}

/** The glyph at the middle of a row, colour code included */
Expand Down
Loading