diff --git a/src/main/java/com/technicjelle/bluemapsignextractor/common/BlockEntity.java b/src/main/java/com/technicjelle/bluemapsignextractor/common/BlockEntity.java index 49e014d..ffefd73 100644 --- a/src/main/java/com/technicjelle/bluemapsignextractor/common/BlockEntity.java +++ b/src/main/java/com/technicjelle/bluemapsignextractor/common/BlockEntity.java @@ -22,7 +22,11 @@ public Vector3d getPosition() { return new Vector3d(x + 0.5, y + 0.5, z + 0.5); // center of the block } - //TODO: Replace with formatIntoHTML(). So that each sign is responsible for generating HTML from/for itself, to put into the BlueMap marker. - // This should also remove the need for so many getters everywhere. - public abstract String getAllSignMessages(); + public String getKey() { + return "sign@" + getPosition().toString(); + } + + public abstract String getFormattedHTML(); + + public abstract String getLabel(); } diff --git a/src/main/java/com/technicjelle/bluemapsignextractor/common/Core.java b/src/main/java/com/technicjelle/bluemapsignextractor/common/Core.java index 712d0a3..76fb909 100644 --- a/src/main/java/com/technicjelle/bluemapsignextractor/common/Core.java +++ b/src/main/java/com/technicjelle/bluemapsignextractor/common/Core.java @@ -8,7 +8,6 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Random; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Stream; @@ -33,28 +32,22 @@ public static void loadMarkers(Logger logger, BlueMapAPI api) { private static void processMCA(Logger logger, BlueMapMap map, Path regionFile) { logger.info("Processing region " + regionFile.getFileName().toString()); - Random random = new Random(); - MCA mca = new MCA(regionFile); try { for (BlockEntity blockEntity : mca.getBlockEntities()) { if (blockEntity.isInvalidSign()) continue; - String allMessages = blockEntity.getAllSignMessages(); - logger.info("Sign:\n" + allMessages); HtmlMarker htmlMarker = HtmlMarker.builder() - .label(allMessages.split("\n")[0]) + .label(blockEntity.getLabel()) .position(blockEntity.getPosition()) - .html(allMessages.replace("\n", "
")) + .html(blockEntity.getFormattedHTML()) .styleClasses("sign") .maxDistance(16) .build(); MarkerSet markerSet = map.getMarkerSets().computeIfAbsent("signs", id -> MarkerSet.builder().label("Signs").toggleable(true).defaultHidden(false).build()); - //nice and random key... probably good enough to prevent duplicates - String key = allMessages.replace("\n", "") + random.nextInt(); - markerSet.put(key, htmlMarker); + markerSet.put(blockEntity.getKey(), htmlMarker); } } catch (IOException e) { logger.log(Level.SEVERE, "Error reading region file", e); diff --git a/src/main/java/com/technicjelle/bluemapsignextractor/common/HTMLUtils.java b/src/main/java/com/technicjelle/bluemapsignextractor/common/HTMLUtils.java new file mode 100644 index 0000000..695a310 --- /dev/null +++ b/src/main/java/com/technicjelle/bluemapsignextractor/common/HTMLUtils.java @@ -0,0 +1,86 @@ +package com.technicjelle.bluemapsignextractor.common; + + +import java.util.Map; + +public class HTMLUtils { + private static final Map mc2css = Map.ofEntries( + Map.entry("white", "#646464"), + Map.entry("orange", "#64280c"), + Map.entry("magenta", "#640064"), + Map.entry("light_blue", "#3c4b51"), + Map.entry("yellow", "#646400"), + Map.entry("lime", "#4b6400"), + Map.entry("pink", "#642947"), + Map.entry("gray", "#323232"), + Map.entry("light_gray", "#535353"), + Map.entry("cyan", "#006464"), + Map.entry("purple", "#3f0c5e"), + Map.entry("blue", "#000064"), + Map.entry("brown", "#361b07"), + Map.entry("green", "#006400"), + Map.entry("red", "#640000"), + Map.entry("black", "#000000") + ); + + private static final Map glowCenter2css = Map.ofEntries( + Map.entry("white", "#ffffff"), + Map.entry("orange", "#fc671f"), + Map.entry("magenta", "#fc00fc"), + Map.entry("light_blue", "#98becb"), + Map.entry("yellow", "#fcfc00"), + Map.entry("lime", "#bdfc00"), + Map.entry("pink", "#fc68b2"), + Map.entry("gray", "#7e7e7e"), + Map.entry("light_gray", "#d0d0d0"), + Map.entry("cyan", "#00fcfc"), + Map.entry("purple", "#9e20ed"), + Map.entry("blue", "#0000fc"), + Map.entry("brown", "#894413"), + Map.entry("green", "#00fc00"), + Map.entry("red", "#fc0000"), + Map.entry("black", "#000000") + ); + + private static final Map glowOutline2css = Map.ofEntries( + Map.entry("white", "#656565"), + Map.entry("orange", "#65280c"), + Map.entry("magenta", "#650065"), + Map.entry("light_blue", "#3c4b51"), + Map.entry("yellow", "#656500"), + Map.entry("lime", "#4b6500"), + Map.entry("pink", "#652947"), + Map.entry("gray", "#323232"), + Map.entry("light_gray", "#535353"), + Map.entry("cyan", "#006565"), + Map.entry("purple", "#3f0c5f"), + Map.entry("blue", "#000065"), + Map.entry("brown", "#361b07"), + Map.entry("green", "#006500"), + Map.entry("red", "#650000"), + Map.entry("black", "#ede8ca") + ); + + public static String minecraftColourToCSSColour(String minecraftColour) { + return mc2css.get(minecraftColour); + } + + public static String minecraftColourToGlowCenterCSSColour(String minecraftColour) { + return glowCenter2css.get(minecraftColour); + } + + private static String minecraftColourToGlowOutlineCSSColour(String minecraftColour) { + return glowOutline2css.get(minecraftColour); + } + + public static String formatSignLineToHTML(String text, String minecraftColour, boolean isGlowing) { + if (isGlowing) { + final String centerColour = minecraftColourToGlowCenterCSSColour(minecraftColour); + final String outlineColour = minecraftColourToGlowOutlineCSSColour(minecraftColour); + return "" + text + ""; + } else { + final String textColour = minecraftColourToCSSColour(minecraftColour); + return "" + text + ""; + } + } +} diff --git a/src/main/java/com/technicjelle/bluemapsignextractor/versions/MC_1_13_2/MC_1_13_2_Sign.java b/src/main/java/com/technicjelle/bluemapsignextractor/versions/MC_1_13_2/MC_1_13_2_Sign.java index 0e94c54..2237308 100644 --- a/src/main/java/com/technicjelle/bluemapsignextractor/versions/MC_1_13_2/MC_1_13_2_Sign.java +++ b/src/main/java/com/technicjelle/bluemapsignextractor/versions/MC_1_13_2/MC_1_13_2_Sign.java @@ -2,30 +2,51 @@ import com.google.gson.Gson; import com.technicjelle.bluemapsignextractor.common.BlockEntity; +import com.technicjelle.bluemapsignextractor.common.HTMLUtils; import de.bluecolored.bluenbt.NBTName; public class MC_1_13_2_Sign extends BlockEntity { private static class SignTextLine { @NBTName("text") - public String text; + private String text; } @NBTName("Text1") - private String text1; + protected String text1; @NBTName("Text2") - private String text2; + protected String text2; @NBTName("Text3") - private String text3; + protected String text3; @NBTName("Text4") - private String text4; + protected String text4; - private String getText(String text) { - SignTextLine signTextLine = new Gson().fromJson(text, SignTextLine.class); + protected String unJSON(String text) { + final SignTextLine signTextLine = new Gson().fromJson(text, SignTextLine.class); return signTextLine.text; } @Override - public String getAllSignMessages() { - return getText(text1) + "\n" + getText(text2) + "\n" + getText(text3) + "\n" + getText(text4); + public String getFormattedHTML() { + return HTMLUtils.formatSignLineToHTML(unJSON(text1), "black", false) + "\n" + + HTMLUtils.formatSignLineToHTML(unJSON(text2), "black", false) + "\n" + + HTMLUtils.formatSignLineToHTML(unJSON(text3), "black", false) + "\n" + + HTMLUtils.formatSignLineToHTML(unJSON(text4), "black", false); + } + + @Override + public String getLabel() { + final String t1 = unJSON(text1); + if (!t1.isBlank()) return t1; + + final String t2 = unJSON(text2); + if (!t2.isBlank()) return t2; + + final String t3 = unJSON(text3); + if (!t3.isBlank()) return t3; + + final String t4 = unJSON(text4); + if (!t4.isBlank()) return t4; + + return "Blank sign at " + getPosition().toString(); } } diff --git a/src/main/java/com/technicjelle/bluemapsignextractor/versions/MC_1_14_4/MC_1_14_4_Sign.java b/src/main/java/com/technicjelle/bluemapsignextractor/versions/MC_1_14_4/MC_1_14_4_Sign.java index 06fbb1f..646d31f 100644 --- a/src/main/java/com/technicjelle/bluemapsignextractor/versions/MC_1_14_4/MC_1_14_4_Sign.java +++ b/src/main/java/com/technicjelle/bluemapsignextractor/versions/MC_1_14_4/MC_1_14_4_Sign.java @@ -1,13 +1,18 @@ package com.technicjelle.bluemapsignextractor.versions.MC_1_14_4; +import com.technicjelle.bluemapsignextractor.common.HTMLUtils; import com.technicjelle.bluemapsignextractor.versions.MC_1_13_2.MC_1_13_2_Sign; import de.bluecolored.bluenbt.NBTName; public class MC_1_14_4_Sign extends MC_1_13_2_Sign { @NBTName("Color") - String colour; + protected String colour; - public String getColour() { - return colour; + @Override + public String getFormattedHTML() { + return HTMLUtils.formatSignLineToHTML(unJSON(text1), colour, false) + "\n" + + HTMLUtils.formatSignLineToHTML(unJSON(text2), colour, false) + "\n" + + HTMLUtils.formatSignLineToHTML(unJSON(text3), colour, false) + "\n" + + HTMLUtils.formatSignLineToHTML(unJSON(text4), colour, false); } } diff --git a/src/main/java/com/technicjelle/bluemapsignextractor/versions/MC_1_17_1/MC_1_17_1_Sign.java b/src/main/java/com/technicjelle/bluemapsignextractor/versions/MC_1_17_1/MC_1_17_1_Sign.java index 1e5c5d6..5e9cf9b 100644 --- a/src/main/java/com/technicjelle/bluemapsignextractor/versions/MC_1_17_1/MC_1_17_1_Sign.java +++ b/src/main/java/com/technicjelle/bluemapsignextractor/versions/MC_1_17_1/MC_1_17_1_Sign.java @@ -1,13 +1,18 @@ package com.technicjelle.bluemapsignextractor.versions.MC_1_17_1; +import com.technicjelle.bluemapsignextractor.common.HTMLUtils; import com.technicjelle.bluemapsignextractor.versions.MC_1_14_4.MC_1_14_4_Sign; import de.bluecolored.bluenbt.NBTName; public class MC_1_17_1_Sign extends MC_1_14_4_Sign { @NBTName("GlowingText") - private boolean glowingText; + private boolean isGlowing; - public boolean isGlowing() { - return glowingText; + @Override + public String getFormattedHTML() { + return HTMLUtils.formatSignLineToHTML(unJSON(text1), colour, isGlowing) + "\n" + + HTMLUtils.formatSignLineToHTML(unJSON(text2), colour, isGlowing) + "\n" + + HTMLUtils.formatSignLineToHTML(unJSON(text3), colour, isGlowing) + "\n" + + HTMLUtils.formatSignLineToHTML(unJSON(text4), colour, isGlowing); } } diff --git a/src/main/java/com/technicjelle/bluemapsignextractor/versions/MC_1_20_4/MC_1_20_4_Sign.java b/src/main/java/com/technicjelle/bluemapsignextractor/versions/MC_1_20_4/MC_1_20_4_Sign.java index f6452d0..00f50c3 100644 --- a/src/main/java/com/technicjelle/bluemapsignextractor/versions/MC_1_20_4/MC_1_20_4_Sign.java +++ b/src/main/java/com/technicjelle/bluemapsignextractor/versions/MC_1_20_4/MC_1_20_4_Sign.java @@ -3,7 +3,10 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.technicjelle.bluemapsignextractor.common.BlockEntity; +import com.technicjelle.bluemapsignextractor.common.HTMLUtils; import de.bluecolored.bluenbt.NBTName; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class MC_1_20_4_Sign extends BlockEntity { private static class Side { @@ -14,19 +17,42 @@ private static class Side { private String colour; @NBTName("has_glowing_text") - private boolean hasGlowingText; + private boolean isGlowing; - public String[] getMessages() { - final String key = "\"text\""; - JsonParser parser = new JsonParser(); + public static String unJSON(String text) { + final String key = "text"; + final JsonParser parser = new JsonParser(); - String[] cleanMessages = messages.clone(); - for (int i = 0; i < cleanMessages.length; i++) { - JsonObject o = parser.parse("{" + key + ":" + cleanMessages[i] + "}").getAsJsonObject(); - cleanMessages[i] = o.get("text").getAsString(); + final JsonObject o = parser.parse("{\"" + key + "\":" + text + "}").getAsJsonObject(); + return o.get(key).getAsString(); + } + + public boolean isWrittenOn() { + for (String message : messages) { + if (!unJSON(message).isBlank()) { + return true; + } + } + return false; + } + + public String getFormattedHTML() { + final StringBuilder sb = new StringBuilder(); + for (String message : messages) { + sb.append(HTMLUtils.formatSignLineToHTML(unJSON(message), colour, isGlowing)).append("\n"); + } + return sb.toString(); + } + + public @Nullable String getLabel() { + for (String message : messages) { + final String unJSON = unJSON(message); + if (!unJSON.isBlank()) { + return unJSON; + } } - return cleanMessages; + return null; } } @@ -37,7 +63,27 @@ public String[] getMessages() { private Side front; @Override - public String getAllSignMessages() { - return String.join("\n", front.getMessages()) + "\n---\n" + String.join("\n", back.getMessages()); + public String getFormattedHTML() { + final StringBuilder sb = new StringBuilder(); + if (front.isWrittenOn()) { + sb.append(front.getFormattedHTML()); + } + if (back.isWrittenOn()) { + sb.append(back.getFormattedHTML()); + } + return sb.toString().stripTrailing(); + } + + @Override + public @NotNull String getLabel() { + if (front.isWrittenOn()) { + final String frontLabel = front.getLabel(); + if (frontLabel != null) return frontLabel; + } + if (back.isWrittenOn()) { + final String backLabel = back.getLabel(); + if (backLabel != null) return backLabel; + } + return "Blank sign at " + getPosition().toString(); } } diff --git a/src/main/resources/style.css b/src/main/resources/style.css index 36b209e..0606be2 100644 --- a/src/main/resources/style.css +++ b/src/main/resources/style.css @@ -32,7 +32,20 @@ transform: translate(-50%, -50%); } -.sign p { +.sign > * { margin: 0; padding: 0; + color: black; + min-height: 1em; +} + +.glowing { + text-shadow: -0.1em -0.1em 0 var(--sign-glow-colour, white), + 0 -0.1em 0 var(--sign-glow-colour, white), + 0.1em -0.1em 0 var(--sign-glow-colour, white), + 0.1em 0 0 var(--sign-glow-colour, white), + 0.1em 0.1em 0 var(--sign-glow-colour, white), + 0 0.1em 0 var(--sign-glow-colour, white), + -0.1em 0.1em 0 var(--sign-glow-colour, white), + -0.1em 0 0 var(--sign-glow-colour, white); } diff --git a/src/test/java/LoadRegionsTest.java b/src/test/java/LoadRegionsTest.java index c740bbb..5c6ec6d 100644 --- a/src/test/java/LoadRegionsTest.java +++ b/src/test/java/LoadRegionsTest.java @@ -1,9 +1,5 @@ import com.technicjelle.bluemapsignextractor.common.BlockEntity; import com.technicjelle.bluemapsignextractor.common.MCA; -import com.technicjelle.bluemapsignextractor.versions.MC_1_13_2.MC_1_13_2_Sign; -import com.technicjelle.bluemapsignextractor.versions.MC_1_14_4.MC_1_14_4_Sign; -import com.technicjelle.bluemapsignextractor.versions.MC_1_17_1.MC_1_17_1_Sign; -import com.technicjelle.bluemapsignextractor.versions.MC_1_20_4.MC_1_20_4_Sign; import org.junit.Test; import java.io.IOException; @@ -60,7 +56,7 @@ public void test_MC_1_19_4() throws IOException { @Test public void test_MC_1_20_4() throws IOException { //Chunk [1, 5] in world at (1, 5) - testMCAFile("/MC_1_20_4/r.0.0.mca", 6); + testMCAFile("/MC_1_20_4/r.0.0.mca", 38); } private void testMCAFile(String resourcePath, int amountOfSignsToExpect) throws IOException { @@ -77,19 +73,12 @@ private void testMCAFile(String resourcePath, int amountOfSignsToExpect) throws signsFound++; - if (blockEntity instanceof MC_1_20_4_Sign) { - MC_1_20_4_Sign sign = (MC_1_20_4_Sign) blockEntity; - System.out.println("1.20.4 Sign:\nPosition:" + sign.getPosition() + "\n" + sign.getAllSignMessages()); - } else if (blockEntity instanceof MC_1_17_1_Sign) { - MC_1_17_1_Sign sign = (MC_1_17_1_Sign) blockEntity; - System.out.println("1.17.1 Sign:\nPosition: " + sign.getPosition() + "\nColour: " + sign.getColour() + "\nGlowing: " + sign.isGlowing() + "\n---\n" + sign.getAllSignMessages() + "\n==="); - } else if (blockEntity instanceof MC_1_14_4_Sign) { - MC_1_14_4_Sign sign = (MC_1_14_4_Sign) blockEntity; - System.out.println("1.14.4 Sign:\nPosition: " + sign.getPosition() + "\nColour: " + sign.getColour() + "\n---\n" + sign.getAllSignMessages() + "\n==="); - } else if (blockEntity instanceof MC_1_13_2_Sign) { - MC_1_13_2_Sign sign = (MC_1_13_2_Sign) blockEntity; - System.out.println("1.13.2 Sign:\nPosition: " + sign.getPosition() + "\n---\n" + sign.getAllSignMessages() + "\n==="); - } + System.out.println(blockEntity.getClass().getSimpleName() + ":\n" + + "Key: " + blockEntity.getKey() + "\n" + + "Label: " + blockEntity.getLabel() + "\n" + + "Position: " + blockEntity.getPosition() + "\n" + + blockEntity.getFormattedHTML() + + "\n\n"); } assertEquals(amountOfSignsToExpect, signsFound); diff --git a/src/test/resources/MC_1_20_4/r.0.0.mca b/src/test/resources/MC_1_20_4/r.0.0.mca index 16b9acb..37cb96d 100644 Binary files a/src/test/resources/MC_1_20_4/r.0.0.mca and b/src/test/resources/MC_1_20_4/r.0.0.mca differ