From 475a8c26b49348690dc4e24d582c016056eba4fb Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sat, 5 Dec 2020 20:28:38 -0700 Subject: [PATCH 01/79] branch --- .../stickyapi/common/ServerVersion.java | 2 ++ .../common/util/{TextUtil.java => BookUtil.java} | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) rename src/main/java/com/dumbdogdiner/stickyapi/common/util/{TextUtil.java => BookUtil.java} (85%) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java b/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java index 1453dcb5..d5eaf1cf 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java @@ -32,6 +32,8 @@ public static ServerType getServerType() { } return ServerType.BUNGEE; + + } /** diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java similarity index 85% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java rename to src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index e6b38b15..67fd62ad 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -6,9 +6,15 @@ import java.util.HashMap; + import org.jetbrains.annotations.NotNull; -public class TextUtil { +public class BookUtil { + public static final int PIXELS_PER_LINE = 113; + public static final int LINES_PER_PAGE = 14; + public static final int PAGES_PER_BOOK = 50; + + // TODO: Test efficiency of this vs switch/case static HashMap characterWidths = new HashMap<>(); static { characterWidths.put('!', 1); @@ -19,7 +25,6 @@ public class TextUtil { characterWidths.put(';', 1); characterWidths.put('i', 1); characterWidths.put('|', 1); - characterWidths.put('!', 1); characterWidths.put('`', 2); characterWidths.put('l', 2); @@ -45,7 +50,7 @@ public class TextUtil { } // Uses info from: https://minecraft.gamepedia.com/Language#Font - public static int getCharacterWidth(@NotNull char c) { + public static int getCharacterWidth(char c) { if (c < 32 || c > 126) { // Not presently implemented, would require rendering TTF return -1; @@ -55,4 +60,6 @@ public static int getCharacterWidth(@NotNull char c) { } return 5; } + + } From 5fc3c16eac77f559491ae504dfa89d0707145b9f Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sat, 5 Dec 2020 20:31:25 -0700 Subject: [PATCH 02/79] Markdown color parsing --- build.gradle | 2 + .../stickyapi/bukkit/item/RuleBook.java | 29 +++++++ .../bukkit/item/generator/BookGenerator.java | 80 +++++++++++++++++++ .../MCColorFormatBlock.java | 14 ++++ .../MCColorFormatBlockParser.java | 66 +++++++++++++++ .../MCColorFormatExtension.java | 17 ++++ 6 files changed, 208 insertions(+) create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatBlock.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatBlockParser.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatExtension.java diff --git a/build.gradle b/build.gradle index e700542a..a2cd91b1 100644 --- a/build.gradle +++ b/build.gradle @@ -37,6 +37,8 @@ repositories { dependencies { compileOnly 'org.projectlombok:lombok:1.18.16' annotationProcessor 'org.projectlombok:lombok:1.18.16' + compileOnly 'io.github.waterfallmc:waterfall-api:1.16-R0.4-SNAPSHOT' + implementation 'com.atlassian.commonmark:commonmark:0.15.2' compileOnly 'com.destroystokyo.paper:paper-api:1.16.4-R0.1-SNAPSHOT' compileOnly 'net.md-5:bungeecord-api:1.16-R0.4-SNAPSHOT' diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java new file mode 100644 index 00000000..02187b5a --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2020 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.bukkit.item; + +import com.dumbdogdiner.stickyapi.common.util.commonmarkextensions.MCColorFormatExtension; +import org.commonmark.node.Node; +import org.commonmark.parser.Parser; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Collections; + +public class RuleBook { + //TODO MOVE TO CONST + private static final String RULEBOOK_PATH = "plugin name i guess? /rulebook.md"; + public static void generateDefault() throws IOException { + Parser cmparser = Parser.builder() + .extensions(Collections.singletonList(MCColorFormatExtension.create())) + .build(); + File file = new File(RULEBOOK_PATH); + Node bookRoot = cmparser.parseReader(new InputStreamReader(new FileInputStream(new File(RULEBOOK_PATH)))); + //TODO: Traverse all subnodes and build the relevant json, convert to nbt, create a bookmeta, create an itemstack, and return it + + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java new file mode 100644 index 00000000..80c14923 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2020 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.bukkit.item.generator; + +import com.dumbdogdiner.stickyapi.common.util.BookUtil; +import com.google.gson.Gson; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BookMeta.Generation; +import org.bukkit.inventory.meta.BookMeta; +import lombok.Getter; +import lombok.Setter; + +public class BookGenerator { + private static final int MAX_PAGES = 50; + private static final int MAX_LINES_PER_PAGE = 14; + private static final float MAX_PIXELS_PER_LINE = 113; + + + private Generation generation = Generation.ORIGINAL; + + @Setter + @Getter + private String title; + + public BookGenerator(){} + /* +/give @p written_book{pages:['["",{"text":"Dumb Dog Diner MC\\nSurvival Handbook","bold":true,"italic":true,"color":"dark_purple"},{"text":"\\n\\n","color":"reset"},{"text":"Table of Contents:","bold":true,"italic":true,"underlined":true,"color":"dark_red"},{"text":"\\n","color":"reset"},{"text":"Page 2: ","color":"red"},{"text":"Rules\\n","color":"reset"},{"text":"Pg. 3: ","color":"red"},{"text":"Gameplay\\n","color":"reset"},{"text":"Pg. 5: ","color":"red"},{"text":"Trading\\n","color":"reset"},{"text":"Pg. 7: ","color":"red"},{"text":"Commands\\n","color":"reset"},{"text":"Pg. 9: ","color":"red"},{"text":"Trading\\nCommands\\n","color":"reset"},{"text":"Pg. 11: ","color":"red"},{"text":"Misc Commands\\n","color":"reset"},{"text":"Pg. 12: ","color":"red"},{"text":"Getting Help\\n","color":"reset"},{"text":"Pg. 14: ","color":"red"},{"text":"Credits","color":"reset"}]','["",{"text":"The Rules:","bold":true,"italic":true,"underlined":true,"color":"red"},{"text":"\\n1. Absolutely no\\ngriefing, theft, or\\nintentional distress!\\n2. No cheating/hacking\\nallowed. Optifine and\\nsimilar are okay.\\n3. No floating trees.\\n4. No fully-automatic\\nredstone farms.\\n5. No harassment,\\nbullying, or abuse.\\n6. No AFK fishing.","color":"reset"}]','["",{"text":"Gameplay:","bold":true,"italic":true,"underlined":true,"color":"dark_green"},{"text":"\\nThe world border for all worlds is 8,000\\nblocks from the\\ncenter. Because of\\nnow ","color":"reset"},{"text":"Nether Portal","color":"dark_red"},{"text":"\\ntravel works, you will\\nnot be able to light\\nthem past 1,000 blocks\\nfrom the center.\\nYou may build wherever you like! Try ","color":"reset"},{"text":"/rtp","color":"blue"},{"text":" to help find a spot!","color":"reset"}]','["",{"text":"This server uses a "},{"text":"Death Chest ","color":"red"},{"text":"system. Upon death, a campfire with your items will spawn at your death location. It will last\\nfor 10 minutes before\\nyour items drop on \\nthe ground!\\n\\nYou can have up to 3\\n","color":"reset"},{"text":"Death Chests","color":"red"},{"text":" at a time.","color":"reset"}]','["",{"text":"Trading:","bold":true,"italic":true,"underlined":true,"color":"dark_aqua"},{"text":"\\nWe use chest chops\\nfor player to trade\\ngood for ","color":"reset"},{"text":"Coins","color":"gold"},{"text":".\\n\\nCoins may be earned through selling goods\\nto other players,\\npaying/receiving\\nmoney for a service,\\nor by selling goods to\\nthe server itself.","color":"reset"}]','{"text":"Chest shops can buy\\nor sell items!\\n\\nTo make a shop, place a chest and\\nshift-click with the\\nitem you want to sell\\nor buy.\\n\\nRegular users may have up to 6 shops\\nat a time."}','["",{"text":"Commands:","bold":true,"italic":true,"underlined":true,"color":"red"},{"text":"\\nTab-complete is set\\nup to only show commands you have access to. Here are some useful ones:\\n\\n","color":"reset"},{"text":"/help ","color":"blue"},{"text":"- Opens the\\nhelp menu\\n","color":"reset"},{"text":"/servers ","color":"blue"},{"text":"- Opens the\\nserver menu\\n","color":"reset"},{"text":"/rules","color":"blue"},{"text":" - Grants this\\nbook","color":"reset"}]','["",{"text":"/options ","color":"blue"},{"text":"- Opens the player options menu\\n","color":"reset"},{"text":"/tpa ","color":"blue"},{"text":"- Sends a\\nteleport request to another player\\n","color":"reset"},{"text":"/rtp ","color":"blue"},{"text":"- Start a\\nrandom teleport\\n","color":"reset"},{"text":"/pw ","color":"blue"},{"text":"- Opens the playerwarps personal\\nhome menu\\n","color":"reset"},{"text":"/helpme ","color":"blue"},{"text":"- Pings an online staff member\\nfor assistance","color":"reset"}]','["",{"text":"Trading Commands:","bold":true,"italic":true,"underlined":true,"color":"dark_purple"},{"text":"\\n","color":"reset"},{"text":"/bal ","color":"blue"},{"text":"- Check your\\nbalance\\n","color":"reset"},{"text":"/pay ","color":"blue"},{"text":"- Pay another player\\n","color":"reset"},{"text":"/sell ","color":"blue"},{"text":"- Sell the item in your hand to the server\\n","color":"reset"},{"text":"/worth ","color":"blue"},{"text":"- Shows the\\nitem price when selling\\nto the server","color":"reset"}]','["",{"text":"/value","color":"blue"},{"text":" - Shows the\\naverage selling price\\nfor an item in\\nplayer shops","color":"reset"}]','["",{"text":"Extra Commands:","bold":true,"italic":true,"underlined":true,"color":"dark_aqua"},{"text":"\\n","color":"reset"},{"text":"/donate, /vip ","color":"blue"},{"text":"- Gives link to the server Patreon page\\n","color":"reset"},{"text":"/discord ","color":"blue"},{"text":"- Gives link to the server Discord\\n","color":"reset"},{"text":"/twitter, /twitch ","color":"blue"},{"text":"- Gives social media links\\n","color":"reset"},{"text":"/merch ","color":"blue"},{"text":"- Gives merch link\\n","color":"reset"},{"text":"/afk ","color":"blue"},{"text":"- Set your status to AFK","color":"reset"}]','["",{"text":"Getting Help:","bold":true,"italic":true,"underlined":true,"color":"light_purple"},{"text":"\\nIf you ever need help\\ngetting your way\\naround the server,\\nplease ask any staff!\\n","color":"reset"},{"text":"/helpme","color":"blue"},{"text":"\\n\\nPlease join the\\nDiscord server to get\\ntechnical help!\\n","color":"reset"},{"text":"/discord","color":"blue"}]','["",{"text":"Please report any\\nbugs, griefing, etc.\\nthat you come across\\nor are a victim of. A\\nstaff member will be\\nhappy to assist you.\\n\\nThe help menu has shortcuts that make getting help easy!\\n"},{"text":"/help","color":"blue"}]','["",{"text":"Credits:","bold":true,"italic":true,"underlined":true,"color":"gold"},{"text":"\\n","color":"reset"},{"text":"dddMC ","bold":true,"color":"dark_purple"},{"text":"is fully funded\\nthrough player donations. Please consider helping support us on Patreon!\\n","color":"reset"},{"text":"/donate /patreon","color":"blue"},{"text":"\\n\\nPatrons will receive a\\nVIP rank. More ranks\\nwill be added in the\\nfuture.","color":"reset"}]','["",{"text":"We hope you enjoy\\nyour time playing\\non the server!\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n- Stixil, "},{"text":"dddMC 2020","bold":true,"color":"dark_purple"}]'],title:"&ddddMC Survival Handbook",author:Stixil} + + */ + + /** + * Escape characters for colors, etc... + * I guess we can just.... use the &-* codes or something, we can use chatcolors somehow + * Beyond that, we can use markdown??? + */ + + public BookGenerator setGeneration(BookMeta.Generation generation){ + this.generation = generation; + return this; + } + + Generation g = BookMeta.Generation.ORIGINAL; + public ItemStack toItemStack(){ + ItemStack book = new ItemStack(Material.WRITTEN_BOOK); + BookMeta meta = null; + return null; + } + + private class TextWrapper{ + public String Text; + public boolean bold; + public boolean italic; + public boolean underlined; + public boolean strikethrough; + public boolean obfuscated; + public String color; + } + + public String generateText(TextWrapper [] wrappers){ + Gson g = new Gson(); + return g.toJson(wrappers); + } + + public float percentFull(){ + return 0.0f; + } + + //TODO STUB + public boolean isFull(){ + return false; + } + + public BookGenerator(String sth){ + BookUtil.getCharacterWidth('a'); + } + +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatBlock.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatBlock.java new file mode 100644 index 00000000..8ce128c2 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatBlock.java @@ -0,0 +1,14 @@ +package com.dumbdogdiner.stickyapi.common.util.commonmarkextensions; + +import lombok.Getter; +import org.bukkit.ChatColor; +import org.commonmark.node.CustomBlock; + +public class MCColorFormatBlock extends CustomBlock { + @Getter + private ChatColor type; + + public MCColorFormatBlock(ChatColor type) { + this.type = type; + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatBlockParser.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatBlockParser.java new file mode 100644 index 00000000..eb608d3a --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatBlockParser.java @@ -0,0 +1,66 @@ +package com.dumbdogdiner.stickyapi.common.util.commonmarkextensions; + +import lombok.Getter; +import org.bukkit.ChatColor; +import org.commonmark.node.Block; +import org.commonmark.parser.block.*; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class MCColorFormatBlockParser extends AbstractBlockParser { + private ChatColor color; + + + @Getter + private Block block; + + + private static final Pattern MATCHME = Pattern.compile("\\s*&([0-9a-fk-o])\\s(.*)&&"); + + public MCColorFormatBlockParser(ChatColor color) { + this.color = color; + this.block = new MCColorFormatBlock(color); + } + + @Override + public boolean canContain(Block block) { + return block != null && !MCColorFormatBlock.class.isAssignableFrom(block.getClass()); + } + + @Override + public boolean isContainer() { + return true; + } + + @Override + public BlockContinue tryContinue(ParserState state) { + CharSequence fullLine = state.getLine(); + CharSequence currentLine = fullLine.subSequence(state.getColumn() + state.getIndent(), fullLine.length()); + + Matcher matcher = MATCHME.matcher(currentLine); + if (matcher.matches()) { + if (color.equals(ChatColor.getByChar(matcher.group(1)))) { + return BlockContinue.atColumn(state.getColumn() + state.getIndent() + matcher.start(2)); + } + } + + return BlockContinue.none(); + } + + public static class Factory extends AbstractBlockParserFactory { + + @Override + public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockParser) { + CharSequence fullLine = state.getLine(); + CharSequence line = fullLine.subSequence(state.getColumn(), fullLine.length()); + Matcher matcher = MATCHME.matcher(line); + if (matcher.matches()) { + return BlockStart + .of(new MCColorFormatBlockParser(ChatColor.getByChar(matcher.group(1)))) + .atColumn(state.getColumn() + state.getIndent() + matcher.start(2)); + } + return BlockStart.none(); + } + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatExtension.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatExtension.java new file mode 100644 index 00000000..0258432f --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatExtension.java @@ -0,0 +1,17 @@ +package com.dumbdogdiner.stickyapi.common.util.commonmarkextensions; + +import org.commonmark.Extension; +import org.commonmark.parser.Parser; + +public class MCColorFormatExtension implements Parser.ParserExtension { + private MCColorFormatExtension(){} + + public static Extension create(){ + return new MCColorFormatExtension(); + } + + @Override + public void extend(Parser.Builder parserBuilder) { + parserBuilder.customBlockParserFactory(new MCColorFormatBlockParser.Factory()); + } +} From 9d9ea1f6a38acc16dc6d6d30ca2ab31d62093144 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Fri, 27 Nov 2020 18:43:07 -0700 Subject: [PATCH 03/79] Start Json Renderer --- .../stickyapi/bukkit/item/RuleBook.java | 9 +- .../MCColorFormatDelimiterProcessor.java | 59 ++++++++++ .../commonmarkextensions/MCColorNode.java | 17 +++ .../MarkdownJsonRenderer.java | 107 ++++++++++++++++++ 4 files changed, 187 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatDelimiterProcessor.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorNode.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MarkdownJsonRenderer.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java index 02187b5a..a56c464f 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java @@ -1,10 +1,10 @@ /** - * Copyright (c) 2020 DumbDogDiner . All rights reserved. + * Copyright (c) 2020 DumbDogDiner <dumbdogdiner.com>. All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ package com.dumbdogdiner.stickyapi.bukkit.item; -import com.dumbdogdiner.stickyapi.common.util.commonmarkextensions.MCColorFormatExtension; +import com.dumbdogdiner.stickyapi.common.util.commonmarkextensions.MCColorFormatDelimiterProcessor; import org.commonmark.node.Node; import org.commonmark.parser.Parser; @@ -12,18 +12,17 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; -import java.util.Collections; public class RuleBook { //TODO MOVE TO CONST private static final String RULEBOOK_PATH = "plugin name i guess? /rulebook.md"; public static void generateDefault() throws IOException { Parser cmparser = Parser.builder() - .extensions(Collections.singletonList(MCColorFormatExtension.create())) + .customDelimiterProcessor(new MCColorFormatDelimiterProcessor()) .build(); File file = new File(RULEBOOK_PATH); Node bookRoot = cmparser.parseReader(new InputStreamReader(new FileInputStream(new File(RULEBOOK_PATH)))); //TODO: Traverse all subnodes and build the relevant json, convert to nbt, create a bookmeta, create an itemstack, and return it - + } } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatDelimiterProcessor.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatDelimiterProcessor.java new file mode 100644 index 00000000..99e3431b --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatDelimiterProcessor.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2020 DumbDogDiner <dumbdogdiner.com>. All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.util.commonmarkextensions; + +import org.commonmark.node.Node; +import org.commonmark.node.Text; +import org.commonmark.parser.delimiter.DelimiterProcessor; +import org.commonmark.parser.delimiter.DelimiterRun; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class MCColorFormatDelimiterProcessor implements DelimiterProcessor { + private static final Pattern COLOR_PATTERN = Pattern.compile("^(black|dark_blue|dark_green|dark_aqua|dark_red|dark_purple|gold|gray|dark_gray|blue|green|aqua|red|light_purple|yellow|white|reset|#[0-9A-Fa-f]{6})\\s*(?:\\s([\\S\\s]+))?$"); + + @Override + public char getOpeningCharacter() { + return '$'; + } + + @Override + public char getClosingCharacter() { + return '$'; + } + + @Override + public int getMinLength() { + return 1; + } + + @Override + public int getDelimiterUse(DelimiterRun opener, DelimiterRun closer) { + if (opener.length() >= 1 && closer.length() >= 1) { + return 1; + } else { + return 0; + } + } + + @Override + public void process(Text opener, Text closer, int delimiterUse) { + Node firstNext = opener.getNext(); + if (firstNext instanceof Text) { + String literal = ((Text) firstNext).getLiteral(); + Matcher match = COLOR_PATTERN.matcher(literal); + // only create the color node if a color was specified + if (match.matches()) { + ((Text) firstNext).setLiteral(match.group(2)); + MCColorNode color = new MCColorNode(match.group(1)); + for (Node n = opener.getNext(); n != null && n != closer; n = n.getNext()) { + color.appendChild(n); + } + opener.insertAfter(color); + } + } + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorNode.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorNode.java new file mode 100644 index 00000000..e386261b --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorNode.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2020 DumbDogDiner <dumbdogdiner.com>. All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.util.commonmarkextensions; + +import lombok.Getter; +import org.commonmark.node.CustomNode; + +public class MCColorNode extends CustomNode { + @Getter + private final String colorName; + + public MCColorNode(String colorName) { + this.colorName = colorName; + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MarkdownJsonRenderer.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MarkdownJsonRenderer.java new file mode 100644 index 00000000..5db76c2d --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MarkdownJsonRenderer.java @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2020 DumbDogDiner <dumbdogdiner.com>. All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.util.commonmarkextensions; + +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.commonmark.node.*; + +import java.util.ArrayList; +import java.util.List; + +public class MarkdownJsonRenderer { + private MarkdownJsonRenderer() {} + + public static BaseComponent render(Node node) { + BaseComponent component = new MarkdownJsonRenderer().render0(node); + BaseComponent current = component; + // find last element and try to remove trailing newlines + while (!current.getExtra().isEmpty()) { + current = current.getExtra().get(current.getExtra().size() - 1); + } + if (current instanceof TextComponent) { + ((TextComponent) current).setText(((TextComponent) current).getText().stripTrailing()); + } + return component; + } + + private BaseComponent render0(Node node) { + TextComponent component = new TextComponent(); + addProperties(node, component); + component.setExtra(renderChildren(node)); + addExtra(node, component); + return optimize(component); + } + + private void addProperties(Node node, TextComponent component) { + if (node instanceof Text) { + component.setText(((Text) node).getLiteral()); + } else if (node instanceof Heading) { + component.setBold(true); + } else if (node instanceof MCColorNode) { + component.setColor(ChatColor.of(((MCColorNode) node).getColorName())); + } else if (node instanceof Delimited) { + switch (((Delimited) node).getOpeningDelimiter()) { + case "*": case "_": + component.setItalic(true); + break; + case "**": + component.setBold(true); + break; + case "__": + component.setUnderlined(true); + break; + // no official formatters are mapped to strikethrough or obfuscated + } + } else if (node instanceof Link) { + component.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, ((Link) node).getDestination())); + String title = ((Link) node).getTitle(); + if (title != null) { + component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new net.md_5.bungee.api.chat.hover.content.Text(title))); + } + } + } + + private void addExtra(Node node, TextComponent component) { + if (node instanceof SoftLineBreak) { + component.addExtra(" "); + } else if (node instanceof HardLineBreak) { + component.addExtra("\n"); + } else if (node instanceof Block) { + if (!( + node instanceof ListItem || + node instanceof ListBlock + )) { + component.addExtra("\n"); + } + } + } + + private List renderChildren(Node node) { + List extra = new ArrayList<>(); + for (Node child = node.getFirstChild(); child != null; child = child.getNext()) { + extra.add(render0(child)); + } + return extra; + } + + private BaseComponent optimize(TextComponent component) { + if (component.getText().equals("") && + component.getExtra().size() == 1 && + (component.isBoldRaw() == Boolean.FALSE) && + (component.isItalicRaw() == Boolean.FALSE) && + (component.isObfuscatedRaw() == Boolean.FALSE) && + (component.isStrikethroughRaw() == Boolean.FALSE) && + (component.isUnderlinedRaw() == Boolean.FALSE) + ) { + return component.getExtra().get(0); + } else { + return component; + } + } +} From 2b822c607f319d61edc85ea79fbdcba9a338d112 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sat, 5 Dec 2020 21:51:03 -0700 Subject: [PATCH 04/79] Add some notes and fix a lot of little bits --- build.gradle | 16 ++++- .../stickyapi/bukkit/item/RuleBook.java | 4 +- .../bukkit/item/generator/BookGenerator.java | 28 ++++++-- .../MCColorFormatDelimiterProcessor.java | 4 +- .../commonmarkextensions/MCColorNode.java | 4 +- .../MCFormatExtension.java | 22 +++++++ .../MarkdownJsonRenderer.java | 5 +- .../stickyapi/common/book/package-info.java | 5 ++ .../stickyapi/common/util/BookUtil.java | 3 +- .../MCColorFormatBlock.java | 14 ---- .../MCColorFormatBlockParser.java | 66 ------------------- .../MCColorFormatExtension.java | 17 ----- 12 files changed, 73 insertions(+), 115 deletions(-) rename src/main/java/com/dumbdogdiner/stickyapi/common/{util => book}/commonmarkextensions/MCColorFormatDelimiterProcessor.java (91%) rename src/main/java/com/dumbdogdiner/stickyapi/common/{util => book}/commonmarkextensions/MCColorNode.java (65%) create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java rename src/main/java/com/dumbdogdiner/stickyapi/common/{util => book}/commonmarkextensions/MarkdownJsonRenderer.java (95%) create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/book/package-info.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatBlock.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatBlockParser.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatExtension.java diff --git a/build.gradle b/build.gradle index a2cd91b1..c003dd3a 100644 --- a/build.gradle +++ b/build.gradle @@ -32,16 +32,26 @@ repositories { maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } maven { url 'https://papermc.io/repo/repository/maven-public/' } + + + // FULL paper/spigot/bukkit/craftbukkit + maven { + credentials { + username "$ghUser" + password "$ghPass" + } + url = "https://maven.pkg.github.com/DumbDogDiner/buildtoolspackages/" } } dependencies { compileOnly 'org.projectlombok:lombok:1.18.16' annotationProcessor 'org.projectlombok:lombok:1.18.16' - compileOnly 'io.github.waterfallmc:waterfall-api:1.16-R0.4-SNAPSHOT' implementation 'com.atlassian.commonmark:commonmark:0.15.2' - compileOnly 'com.destroystokyo.paper:paper-api:1.16.4-R0.1-SNAPSHOT' - compileOnly 'net.md-5:bungeecord-api:1.16-R0.4-SNAPSHOT' + + compileOnly 'com.dumbdogdiner.buildtools:paper:1.16.4-298-SNAPSHOT' + compileOnly 'io.github.waterfallmc:waterfall-api:1.16-R0.4-SNAPSHOT' + implementation 'org.jetbrains:annotations:20.1.0' implementation 'com.google.code.gson:gson:2.8.6' implementation 'io.github.classgraph:classgraph:4.8.92' diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java index a56c464f..5cadc802 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java @@ -1,10 +1,10 @@ /** - * Copyright (c) 2020 DumbDogDiner <dumbdogdiner.com>. All rights reserved. + * Copyright (c) 2020 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ package com.dumbdogdiner.stickyapi.bukkit.item; -import com.dumbdogdiner.stickyapi.common.util.commonmarkextensions.MCColorFormatDelimiterProcessor; +import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.MCColorFormatDelimiterProcessor; import org.commonmark.node.Node; import org.commonmark.parser.Parser; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java index 80c14923..284452a8 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java @@ -6,7 +6,10 @@ import com.dumbdogdiner.stickyapi.common.util.BookUtil; import com.google.gson.Gson; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftMetaBook; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta.Generation; import org.bukkit.inventory.meta.BookMeta; @@ -18,14 +21,21 @@ public class BookGenerator { private static final int MAX_LINES_PER_PAGE = 14; private static final float MAX_PIXELS_PER_LINE = 113; + BookMeta meta; + @Getter private Generation generation = Generation.ORIGINAL; - - @Setter + Material mat; + @Getter private String title; - public BookGenerator(){} + public BookGenerator(Material material){ + if(material != Material.WRITABLE_BOOK && material != Material.WRITTEN_BOOK){ + throw new IllegalArgumentException("Material must be WRITABLE_BOOK or WRITTEN_BOOK"); + } + meta = (BookMeta) new ItemStack(material).getItemMeta(); + } /* /give @p written_book{pages:['["",{"text":"Dumb Dog Diner MC\\nSurvival Handbook","bold":true,"italic":true,"color":"dark_purple"},{"text":"\\n\\n","color":"reset"},{"text":"Table of Contents:","bold":true,"italic":true,"underlined":true,"color":"dark_red"},{"text":"\\n","color":"reset"},{"text":"Page 2: ","color":"red"},{"text":"Rules\\n","color":"reset"},{"text":"Pg. 3: ","color":"red"},{"text":"Gameplay\\n","color":"reset"},{"text":"Pg. 5: ","color":"red"},{"text":"Trading\\n","color":"reset"},{"text":"Pg. 7: ","color":"red"},{"text":"Commands\\n","color":"reset"},{"text":"Pg. 9: ","color":"red"},{"text":"Trading\\nCommands\\n","color":"reset"},{"text":"Pg. 11: ","color":"red"},{"text":"Misc Commands\\n","color":"reset"},{"text":"Pg. 12: ","color":"red"},{"text":"Getting Help\\n","color":"reset"},{"text":"Pg. 14: ","color":"red"},{"text":"Credits","color":"reset"}]','["",{"text":"The Rules:","bold":true,"italic":true,"underlined":true,"color":"red"},{"text":"\\n1. Absolutely no\\ngriefing, theft, or\\nintentional distress!\\n2. No cheating/hacking\\nallowed. Optifine and\\nsimilar are okay.\\n3. No floating trees.\\n4. No fully-automatic\\nredstone farms.\\n5. No harassment,\\nbullying, or abuse.\\n6. No AFK fishing.","color":"reset"}]','["",{"text":"Gameplay:","bold":true,"italic":true,"underlined":true,"color":"dark_green"},{"text":"\\nThe world border for all worlds is 8,000\\nblocks from the\\ncenter. Because of\\nnow ","color":"reset"},{"text":"Nether Portal","color":"dark_red"},{"text":"\\ntravel works, you will\\nnot be able to light\\nthem past 1,000 blocks\\nfrom the center.\\nYou may build wherever you like! Try ","color":"reset"},{"text":"/rtp","color":"blue"},{"text":" to help find a spot!","color":"reset"}]','["",{"text":"This server uses a "},{"text":"Death Chest ","color":"red"},{"text":"system. Upon death, a campfire with your items will spawn at your death location. It will last\\nfor 10 minutes before\\nyour items drop on \\nthe ground!\\n\\nYou can have up to 3\\n","color":"reset"},{"text":"Death Chests","color":"red"},{"text":" at a time.","color":"reset"}]','["",{"text":"Trading:","bold":true,"italic":true,"underlined":true,"color":"dark_aqua"},{"text":"\\nWe use chest chops\\nfor player to trade\\ngood for ","color":"reset"},{"text":"Coins","color":"gold"},{"text":".\\n\\nCoins may be earned through selling goods\\nto other players,\\npaying/receiving\\nmoney for a service,\\nor by selling goods to\\nthe server itself.","color":"reset"}]','{"text":"Chest shops can buy\\nor sell items!\\n\\nTo make a shop, place a chest and\\nshift-click with the\\nitem you want to sell\\nor buy.\\n\\nRegular users may have up to 6 shops\\nat a time."}','["",{"text":"Commands:","bold":true,"italic":true,"underlined":true,"color":"red"},{"text":"\\nTab-complete is set\\nup to only show commands you have access to. Here are some useful ones:\\n\\n","color":"reset"},{"text":"/help ","color":"blue"},{"text":"- Opens the\\nhelp menu\\n","color":"reset"},{"text":"/servers ","color":"blue"},{"text":"- Opens the\\nserver menu\\n","color":"reset"},{"text":"/rules","color":"blue"},{"text":" - Grants this\\nbook","color":"reset"}]','["",{"text":"/options ","color":"blue"},{"text":"- Opens the player options menu\\n","color":"reset"},{"text":"/tpa ","color":"blue"},{"text":"- Sends a\\nteleport request to another player\\n","color":"reset"},{"text":"/rtp ","color":"blue"},{"text":"- Start a\\nrandom teleport\\n","color":"reset"},{"text":"/pw ","color":"blue"},{"text":"- Opens the playerwarps personal\\nhome menu\\n","color":"reset"},{"text":"/helpme ","color":"blue"},{"text":"- Pings an online staff member\\nfor assistance","color":"reset"}]','["",{"text":"Trading Commands:","bold":true,"italic":true,"underlined":true,"color":"dark_purple"},{"text":"\\n","color":"reset"},{"text":"/bal ","color":"blue"},{"text":"- Check your\\nbalance\\n","color":"reset"},{"text":"/pay ","color":"blue"},{"text":"- Pay another player\\n","color":"reset"},{"text":"/sell ","color":"blue"},{"text":"- Sell the item in your hand to the server\\n","color":"reset"},{"text":"/worth ","color":"blue"},{"text":"- Shows the\\nitem price when selling\\nto the server","color":"reset"}]','["",{"text":"/value","color":"blue"},{"text":" - Shows the\\naverage selling price\\nfor an item in\\nplayer shops","color":"reset"}]','["",{"text":"Extra Commands:","bold":true,"italic":true,"underlined":true,"color":"dark_aqua"},{"text":"\\n","color":"reset"},{"text":"/donate, /vip ","color":"blue"},{"text":"- Gives link to the server Patreon page\\n","color":"reset"},{"text":"/discord ","color":"blue"},{"text":"- Gives link to the server Discord\\n","color":"reset"},{"text":"/twitter, /twitch ","color":"blue"},{"text":"- Gives social media links\\n","color":"reset"},{"text":"/merch ","color":"blue"},{"text":"- Gives merch link\\n","color":"reset"},{"text":"/afk ","color":"blue"},{"text":"- Set your status to AFK","color":"reset"}]','["",{"text":"Getting Help:","bold":true,"italic":true,"underlined":true,"color":"light_purple"},{"text":"\\nIf you ever need help\\ngetting your way\\naround the server,\\nplease ask any staff!\\n","color":"reset"},{"text":"/helpme","color":"blue"},{"text":"\\n\\nPlease join the\\nDiscord server to get\\ntechnical help!\\n","color":"reset"},{"text":"/discord","color":"blue"}]','["",{"text":"Please report any\\nbugs, griefing, etc.\\nthat you come across\\nor are a victim of. A\\nstaff member will be\\nhappy to assist you.\\n\\nThe help menu has shortcuts that make getting help easy!\\n"},{"text":"/help","color":"blue"}]','["",{"text":"Credits:","bold":true,"italic":true,"underlined":true,"color":"gold"},{"text":"\\n","color":"reset"},{"text":"dddMC ","bold":true,"color":"dark_purple"},{"text":"is fully funded\\nthrough player donations. Please consider helping support us on Patreon!\\n","color":"reset"},{"text":"/donate /patreon","color":"blue"},{"text":"\\n\\nPatrons will receive a\\nVIP rank. More ranks\\nwill be added in the\\nfuture.","color":"reset"}]','["",{"text":"We hope you enjoy\\nyour time playing\\non the server!\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n- Stixil, "},{"text":"dddMC 2020","bold":true,"color":"dark_purple"}]'],title:"&ddddMC Survival Handbook",author:Stixil} @@ -49,6 +59,11 @@ public ItemStack toItemStack(){ return null; } + public BookGenerator setTitle(String title){ + this.title = title; + return this; + } + private class TextWrapper{ public String Text; public boolean bold; @@ -59,7 +74,10 @@ private class TextWrapper{ public String color; } - public String generateText(TextWrapper [] wrappers){ + public String generateText(TextComponent [] wrappers){ + TextComponent t = wrappers[0]; + + Gson g = new Gson(); return g.toJson(wrappers); } @@ -74,7 +92,7 @@ public boolean isFull(){ } public BookGenerator(String sth){ - BookUtil.getCharacterWidth('a'); + int x = BookUtil.getCharacterWidth('a'); } } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatDelimiterProcessor.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java similarity index 91% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatDelimiterProcessor.java rename to src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java index 99e3431b..bb4d8ca0 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatDelimiterProcessor.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java @@ -1,8 +1,8 @@ /** - * Copyright (c) 2020 DumbDogDiner <dumbdogdiner.com>. All rights reserved. + * Copyright (c) 2020 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ -package com.dumbdogdiner.stickyapi.common.util.commonmarkextensions; +package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; import org.commonmark.node.Node; import org.commonmark.node.Text; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorNode.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java similarity index 65% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorNode.java rename to src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java index e386261b..226c2104 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorNode.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java @@ -1,8 +1,8 @@ /** - * Copyright (c) 2020 DumbDogDiner <dumbdogdiner.com>. All rights reserved. + * Copyright (c) 2020 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ -package com.dumbdogdiner.stickyapi.common.util.commonmarkextensions; +package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; import lombok.Getter; import org.commonmark.node.CustomNode; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java new file mode 100644 index 00000000..efb49bba --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2020 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; + +import org.commonmark.Extension; +import org.commonmark.parser.Parser; + +public class MCFormatExtension implements Parser.ParserExtension { + private MCFormatExtension(){} + + public static Extension create(){ + return new MCFormatExtension(); + } + + @Override + public void extend(Parser.Builder parserBuilder) { + parserBuilder.customDelimiterProcessor(new MCColorFormatDelimiterProcessor()); + // TODO add a parser here that does the line splitting + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MarkdownJsonRenderer.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java similarity index 95% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MarkdownJsonRenderer.java rename to src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java index 5db76c2d..a9820a62 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MarkdownJsonRenderer.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java @@ -1,8 +1,8 @@ /** - * Copyright (c) 2020 DumbDogDiner <dumbdogdiner.com>. All rights reserved. + * Copyright (c) 2020 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ -package com.dumbdogdiner.stickyapi.common.util.commonmarkextensions; +package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; @@ -14,6 +14,7 @@ import java.util.ArrayList; import java.util.List; +//TODO Implement NodeRenderer or Renderer public class MarkdownJsonRenderer { private MarkdownJsonRenderer() {} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/package-info.java new file mode 100644 index 00000000..d68bef74 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/package-info.java @@ -0,0 +1,5 @@ +/** + * Copyright (c) 2020 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.book; \ No newline at end of file diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index 67fd62ad..385e7585 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -7,6 +7,7 @@ import java.util.HashMap; +import net.md_5.bungee.api.chat.BaseComponent; import org.jetbrains.annotations.NotNull; public class BookUtil { @@ -60,6 +61,4 @@ public static int getCharacterWidth(char c) { } return 5; } - - } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatBlock.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatBlock.java deleted file mode 100644 index 8ce128c2..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatBlock.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dumbdogdiner.stickyapi.common.util.commonmarkextensions; - -import lombok.Getter; -import org.bukkit.ChatColor; -import org.commonmark.node.CustomBlock; - -public class MCColorFormatBlock extends CustomBlock { - @Getter - private ChatColor type; - - public MCColorFormatBlock(ChatColor type) { - this.type = type; - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatBlockParser.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatBlockParser.java deleted file mode 100644 index eb608d3a..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatBlockParser.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.dumbdogdiner.stickyapi.common.util.commonmarkextensions; - -import lombok.Getter; -import org.bukkit.ChatColor; -import org.commonmark.node.Block; -import org.commonmark.parser.block.*; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class MCColorFormatBlockParser extends AbstractBlockParser { - private ChatColor color; - - - @Getter - private Block block; - - - private static final Pattern MATCHME = Pattern.compile("\\s*&([0-9a-fk-o])\\s(.*)&&"); - - public MCColorFormatBlockParser(ChatColor color) { - this.color = color; - this.block = new MCColorFormatBlock(color); - } - - @Override - public boolean canContain(Block block) { - return block != null && !MCColorFormatBlock.class.isAssignableFrom(block.getClass()); - } - - @Override - public boolean isContainer() { - return true; - } - - @Override - public BlockContinue tryContinue(ParserState state) { - CharSequence fullLine = state.getLine(); - CharSequence currentLine = fullLine.subSequence(state.getColumn() + state.getIndent(), fullLine.length()); - - Matcher matcher = MATCHME.matcher(currentLine); - if (matcher.matches()) { - if (color.equals(ChatColor.getByChar(matcher.group(1)))) { - return BlockContinue.atColumn(state.getColumn() + state.getIndent() + matcher.start(2)); - } - } - - return BlockContinue.none(); - } - - public static class Factory extends AbstractBlockParserFactory { - - @Override - public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockParser) { - CharSequence fullLine = state.getLine(); - CharSequence line = fullLine.subSequence(state.getColumn(), fullLine.length()); - Matcher matcher = MATCHME.matcher(line); - if (matcher.matches()) { - return BlockStart - .of(new MCColorFormatBlockParser(ChatColor.getByChar(matcher.group(1)))) - .atColumn(state.getColumn() + state.getIndent() + matcher.start(2)); - } - return BlockStart.none(); - } - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatExtension.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatExtension.java deleted file mode 100644 index 0258432f..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/commonmarkextensions/MCColorFormatExtension.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dumbdogdiner.stickyapi.common.util.commonmarkextensions; - -import org.commonmark.Extension; -import org.commonmark.parser.Parser; - -public class MCColorFormatExtension implements Parser.ParserExtension { - private MCColorFormatExtension(){} - - public static Extension create(){ - return new MCColorFormatExtension(); - } - - @Override - public void extend(Parser.Builder parserBuilder) { - parserBuilder.customBlockParserFactory(new MCColorFormatBlockParser.Factory()); - } -} From 8b3453dc65b823b3d6df2af48b1cabe2ad23126b Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sun, 6 Dec 2020 10:47:35 -0700 Subject: [PATCH 05/79] Update gradle --- build.gradle | 45 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index e700542a..49783cda 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ plugins { id 'java' id 'maven-publish' id 'jacoco' - id "io.freefair.lombok" version "5.3.0" + //id "io.freefair.lombok" version "5.3.0" id "com.github.hierynomus.license" version "0.15.0" } @@ -13,7 +13,8 @@ jacoco { group = 'com.dumbdogdiner' -version = '2.0.0' +// Suffix with -pre while in development +version = '2.0.0-pre' // License Plugin Options license { header = file('LICENSE_HEADER') } @@ -30,21 +31,50 @@ repositories { mavenCentral() jcenter() + maven { url 'https://jitpack.io' } maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } maven { url 'https://papermc.io/repo/repository/maven-public/' } + maven { url = "https://repo.extendedclip.com/content/repositories/placeholderapi/" } + maven { url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/' } + maven { + credentials { + username "$ghUser" + password "$ghPass" + } + url = "https://maven.pkg.github.com/DumbDogDiner/buildtoolspackages/" } + + maven { + credentials { + username "$ghUser" + password "$ghPass" + } + url = "https://maven.pkg.github.com/DumbDogDiner/closedsource-package-mirror/" } } dependencies { compileOnly 'org.projectlombok:lombok:1.18.16' annotationProcessor 'org.projectlombok:lombok:1.18.16' - compileOnly 'com.destroystokyo.paper:paper-api:1.16.4-R0.1-SNAPSHOT' - compileOnly 'net.md-5:bungeecord-api:1.16-R0.4-SNAPSHOT' + compileOnly 'com.dumbdogdiner.buildtools:paper:1.16.4-318-SNAPSHOT' + compileOnly 'io.github.waterfallmc:waterfall-api:1.16-R0.4-SNAPSHOT' + implementation 'org.jetbrains:annotations:20.1.0' implementation 'com.google.code.gson:gson:2.8.6' + implementation 'com.atlassian.commonmark:commonmark:0.15.2' implementation 'io.github.classgraph:classgraph:4.8.92' implementation 'com.github.seancfoley:ipaddress:5.3.3' - + implementation 'org.apache.httpcomponents:httpclient:4.5' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + + //Softdepend Plugins (not all are used yet) + compileOnly 'net.luckperms:api:5.2' + compileOnly 'com.github.MilkBowl:VaultAPI:1.7' + compileOnly 'me.clip:placeholderapi:2.10.6' + compileOnly 'com.dumbdogdiner.closedsource-package-mirror:stafffacilities:4.8.5' + compileOnly 'com.dumbdogdiner.closedsource-package-mirror:plotsquared-bukkit-premium:5.13.8' + compileOnly 'com.dumbdogdiner.closedsource-package-mirror:spartan:377.1' + compileOnly 'com.dumbdogdiner.closedsource-package-mirror:warpsystem:4.2.12' + // JUnit 5 Testing testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.0") @@ -80,12 +110,13 @@ task sources(type: Jar, dependsOn: classes) { from sourceSets.main.allSource } +tasks.withType(JavaCompile) { + options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" << "-XDignore.symbol.file" +} tasks.publish.dependsOn build, sources - - publishing { repositories { maven { From aa2dbe17f1ca74b8de8126ef73add01cf9eb5f6c Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sun, 6 Dec 2020 10:47:53 -0700 Subject: [PATCH 06/79] fixup ci --- .github/workflows/ci.yml | 8 ++++++++ .github/workflows/docs.yml | 8 ++++++++ .github/workflows/publish.yml | 8 ++++++++ 3 files changed, 24 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca653bbe..672f16d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,14 @@ jobs: - uses: actions/checkout@v2 - name: Grant execute permission for gradlew run: chmod +x gradlew + - name: Setup gradle.properties + run: | + mkdir -p ~/.gradle/ + echo "GRADLE_USER_HOME=$HOME/.gradle" >> $GITHUB_ENV + echo "ghUser=${GITHUB_ACTOR}" >> ~/.gradle/gradle.properties + echo "ghPass=${GITHUB_TOKEN}" >> ~/.gradle/gradle.properties + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Build with Gradle run: ./gradlew build - name: Install dependencies for coverage reporter (java 11 only) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 0f57403b..b0324af0 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -22,6 +22,14 @@ jobs: persist-credentials: false - name: Echo branch name run: echo ${GITHUB_REF##*/} + - name: Setup gradle.properties + run: | + mkdir -p ~/.gradle/ + echo "GRADLE_USER_HOME=$HOME/.gradle" >> $GITHUB_ENV + echo "ghUser=${GITHUB_ACTOR}" >> ~/.gradle/gradle.properties + echo "ghPass=${GITHUB_TOKEN}" >> ~/.gradle/gradle.properties + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Build docs run: | ./gradlew javadoc diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a5724fbe..12df168c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -16,6 +16,14 @@ jobs: run: echo ${GITHUB_REF##*/} - name: Grant execute permission for gradlew run: chmod +x gradlew + - name: Setup gradle.properties + run: | + mkdir -p ~/.gradle/ + echo "GRADLE_USER_HOME=$HOME/.gradle" >> $GITHUB_ENV + echo "ghUser=${GITHUB_ACTOR}" >> ~/.gradle/gradle.properties + echo "ghPass=${GITHUB_TOKEN}" >> ~/.gradle/gradle.properties + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Publish with Gradle run: ./gradlew -Pversion=${GITHUB_REF##*/} publish env: From ba3100d85c3982d7ed73e48c908a3f10be9c5c22 Mon Sep 17 00:00:00 2001 From: Matt <25674682+spazzylemons@users.noreply.github.com> Date: Sun, 6 Dec 2020 12:47:54 -0500 Subject: [PATCH 07/79] Implement NodeRenderer, various improvements to MarkdownJsonRenderer --- .../MarkdownJsonRenderer.java | 219 +++++++++++------- .../TextComponentWriter.java | 96 ++++++++ 2 files changed, 228 insertions(+), 87 deletions(-) create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/TextComponentWriter.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java index a9820a62..78b1f066 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java @@ -4,105 +4,150 @@ */ package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; +import lombok.Getter; import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.ClickEvent; -import net.md_5.bungee.api.chat.HoverEvent; -import net.md_5.bungee.api.chat.TextComponent; import org.commonmark.node.*; +import org.commonmark.renderer.NodeRenderer; -import java.util.ArrayList; -import java.util.List; +import java.util.*; -//TODO Implement NodeRenderer or Renderer -public class MarkdownJsonRenderer { - private MarkdownJsonRenderer() {} +public class MarkdownJsonRenderer extends AbstractVisitor implements NodeRenderer { + private static final Set> nodeTypes = new HashSet<>(Arrays.asList( + Text.class, + Heading.class, + MCColorNode.class, + Emphasis.class, + StrongEmphasis.class, + Link.class, + SoftLineBreak.class, + HardLineBreak.class, + ListItem.class, + OrderedList.class, + BulletList.class, + Block.class + )); - public static BaseComponent render(Node node) { - BaseComponent component = new MarkdownJsonRenderer().render0(node); - BaseComponent current = component; - // find last element and try to remove trailing newlines - while (!current.getExtra().isEmpty()) { - current = current.getExtra().get(current.getExtra().size() - 1); - } - if (current instanceof TextComponent) { - ((TextComponent) current).setText(((TextComponent) current).getText().stripTrailing()); - } - return component; - } - - private BaseComponent render0(Node node) { - TextComponent component = new TextComponent(); - addProperties(node, component); - component.setExtra(renderChildren(node)); - addExtra(node, component); - return optimize(component); - } - - private void addProperties(Node node, TextComponent component) { - if (node instanceof Text) { - component.setText(((Text) node).getLiteral()); - } else if (node instanceof Heading) { - component.setBold(true); - } else if (node instanceof MCColorNode) { - component.setColor(ChatColor.of(((MCColorNode) node).getColorName())); - } else if (node instanceof Delimited) { - switch (((Delimited) node).getOpeningDelimiter()) { - case "*": case "_": - component.setItalic(true); - break; - case "**": - component.setBold(true); - break; - case "__": - component.setUnderlined(true); - break; - // no official formatters are mapped to strikethrough or obfuscated - } - } else if (node instanceof Link) { - component.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, ((Link) node).getDestination())); - String title = ((Link) node).getTitle(); - if (title != null) { - component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new net.md_5.bungee.api.chat.hover.content.Text(title))); - } - } + private final TextComponentWriter writer; + private int listIndex = 0; + + public MarkdownJsonRenderer(TextComponentWriter writer) { + this.writer = writer; + } + + // lombok auto getter is static which doesn't match the override + @Override + public Set> getNodeTypes() { + return nodeTypes; + } + + @Override + public void visit(Text text) { + writer.addText(text.getLiteral()); + visitChildren(text); + } + + @Override + public void visit(Heading heading) { + writer.setBold(); + visitChildren(heading); + writer.addLine(); + } + + @Override + public void visit(Emphasis node) { + writer.setItalic(); + visitChildren(node); } - private void addExtra(Node node, TextComponent component) { - if (node instanceof SoftLineBreak) { - component.addExtra(" "); - } else if (node instanceof HardLineBreak) { - component.addExtra("\n"); - } else if (node instanceof Block) { - if (!( - node instanceof ListItem || - node instanceof ListBlock - )) { - component.addExtra("\n"); - } + @Override + public void visit(StrongEmphasis node) { + switch (node.getOpeningDelimiter()) { + case "**": + writer.setBold(); + break; + case "__": + writer.setUnderlined(); + break; } + visitChildren(node); + } + + @Override + public void visit(Link link) { + writer.setHyperlink(link.getDestination()); + writer.setMouseoverText(link.getTitle()); + } + + @Override + public void visit(SoftLineBreak lineBreak) { + writer.addText(" "); + } + + @Override + public void visit(HardLineBreak lineBreak) { + writer.addLine(); } - private List renderChildren(Node node) { - List extra = new ArrayList<>(); - for (Node child = node.getFirstChild(); child != null; child = child.getNext()) { - extra.add(render0(child)); + @Override + public void visit(Paragraph paragraph) { + visitChildren(paragraph); + writer.addLine(); + } + + @Override + public void visit(OrderedList list) { + visitList(list, 1); + } + + @Override + public void visit(BulletList list) { + visitList(list, 0); + } + + private void visitList(ListBlock list, int initialIndex) { + writer.indent(); + int oldIndex = listIndex; + listIndex = initialIndex; + visitChildren(list); + listIndex = oldIndex; + writer.dedent(); + } + + @Override + public void visit(ListItem item) { + if (listIndex == 0) { + writer.addText("• "); + } else { + writer.addText((listIndex++) + ". "); } - return extra; - } - - private BaseComponent optimize(TextComponent component) { - if (component.getText().equals("") && - component.getExtra().size() == 1 && - (component.isBoldRaw() == Boolean.FALSE) && - (component.isItalicRaw() == Boolean.FALSE) && - (component.isObfuscatedRaw() == Boolean.FALSE) && - (component.isStrikethroughRaw() == Boolean.FALSE) && - (component.isUnderlinedRaw() == Boolean.FALSE) - ) { - return component.getExtra().get(0); + visitChildren(item); + } + + @Override + public void visit(CustomNode node) { + if (node instanceof MCColorNode) { + visit((MCColorNode) node); } else { - return component; + visitChildren(node); } } + + public void visit(MCColorNode color) { + writer.setColor(ChatColor.of(color.getColorName())); + visitChildren(color); + } + + @Override + protected void visitChildren(Node parent) { + for (Node child = parent.getFirstChild(); child != null; child = child.getNext()) { + render(child); + } + } + + @Override + public void render(Node node) { + writer.enterLevel(); + node.accept(this); + writer.exitLevel(); + } } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/TextComponentWriter.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/TextComponentWriter.java new file mode 100644 index 00000000..1348e966 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/TextComponentWriter.java @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2020 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; + +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.api.chat.hover.content.Text; + +import java.util.Stack; + +public class TextComponentWriter { + private final Stack levels = new Stack<>(); + private TextComponent current; + private boolean renderNewLine = false; + private boolean renderIndent = true; + private int indent = 0; + + public TextComponentWriter(TextComponent component) { + this.current = component; + } + + public void enterLevel() { + levels.push(current); + current = new TextComponent(); + } + + public void exitLevel() { + TextComponent top = levels.pop(); + top.addExtra(current); + current = top; + } + + public void indent() { + ++indent; + } + + public void dedent() { + indent = Math.max(indent - 1, 0); + } + + public void addText(String text) { + if (text.isEmpty()) return; + enterLevel(); + if (renderNewLine) { + renderNewLine = false; + current.setText(current.getText() + "\n"); + renderIndent = true; + } + if (renderIndent) { + renderIndent = false; + current.setText(current.getText() + " ".repeat(indent)); + } + current.setText(current.getText() + text); + exitLevel(); + } + + public void addLine() { + renderNewLine = true; + } + + public void setBold() { + current.setBold(true); + } + + public void setItalic() { + current.setItalic(true); + } + + public void setUnderlined() { + current.setUnderlined(true); + } + + public void setColor(ChatColor color) { + current.setColor(color); + } + + public void setHyperlink(String url) { + if (url == null) { + current.setClickEvent(null); + } else { + current.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url)); + } + } + + public void setMouseoverText(String text) { + if (text == null) { + current.setHoverEvent(null); + } else { + current.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(text))); + } + } +} From c81e69cec5d3267b31edc8fc2d915d0d9171c9c0 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sun, 6 Dec 2020 10:48:02 -0700 Subject: [PATCH 08/79] unbrick javadoc --- .../dumbdogdiner/stickyapi/bukkit/util/SoundUtil.java | 2 +- .../bungeecord/packet/PacketRegistration.java | 2 +- .../stickyapi/bungeecord/util/SoundUtil.java | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/SoundUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/SoundUtil.java index 4c842be7..e7296247 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/SoundUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/SoundUtil.java @@ -94,7 +94,7 @@ public static void sendSuccess(@NotNull Player player) { * the sound was played. * * @param sender {@link org.bukkit.command.CommandSender} The sender - * @param type {@link com.dumbdogdiner.stickyapi.bukkit.util.NotificationType} + * @param type {@link NotificationType} * The type of sound * @return {@link java.lang.Boolean} */ diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/packet/PacketRegistration.java b/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/packet/PacketRegistration.java index 0fd861c1..8835356d 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/packet/PacketRegistration.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/packet/PacketRegistration.java @@ -38,7 +38,7 @@ private static void processReflection() { /** * Register a packet with BungeeCord * - * @param clazz that extends {@link DefinedPacket} + * @param clazz that extends {@link net.md_5.bungee.protocol.DefinedPacket} * @param id the protocol ID for the packet (see: https://wiki.vg/Protocol) */ public static void registerPacket(Class clazz, Integer id) { diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/SoundUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/SoundUtil.java index cc7b2629..468bf470 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/SoundUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/SoundUtil.java @@ -54,7 +54,7 @@ public static void queueSound(@NotNull ProxiedPlayer player, @NotNull Sound soun /** * Send an info notification to the target player. * - * @param player {@link org.bukkit.entity.ProxiedPlayer} The target player + * @param player {@link ProxiedPlayer} The target player */ public static void sendInfo(@NotNull ProxiedPlayer player) { queueSound(player, Sound.BLOCK_NOTE_BLOCK_PLING, 1f, 1f, 0L); // note pling @@ -64,7 +64,7 @@ public static void sendInfo(@NotNull ProxiedPlayer player) { /** * Send a quiet notification to the target player. * - * @param player {@link org.bukkit.entity.ProxiedPlayer} The target player + * @param player {@link ProxiedPlayer} The target player */ public static void sendQuiet(@NotNull ProxiedPlayer player) { queueSound(player, Sound.BLOCK_NOTE_BLOCK_PLING, 1f, 1f, 0L); // note harp @@ -75,7 +75,7 @@ public static void sendQuiet(@NotNull ProxiedPlayer player) { /** * Send an error notification to the target player. * - * @param player {@link org.bukkit.entity.ProxiedPlayer} The target player + * @param player {@link ProxiedPlayer} The target player */ public static void sendError(@NotNull ProxiedPlayer player) { queueSound(player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 0.944f, 0L); @@ -86,7 +86,7 @@ public static void sendError(@NotNull ProxiedPlayer player) { /** * Send a success notification to the target player. * - * @param player {@link org.bukkit.entity.ProxiedPlayer} The target player + * @param player {@link ProxiedPlayer} The target player */ public static void sendSuccess(@NotNull ProxiedPlayer player) { queueSound(player, Sound.ENTITY_PLAYER_LEVELUP, 1f, 2f, 0L); @@ -98,7 +98,7 @@ public static void sendSuccess(@NotNull ProxiedPlayer player) { * the sound was played. * * @param sender {@link org.bukkit.command.CommandSender} The sender - * @param type {@link com.dumbdogdiner.stickyapi.bukkit.util.NotificationType} + * @param type {@link NotificationType} * The type of sound * @return {@link java.lang.Boolean} */ From 8fdc82b8a75986d27f0245f983dccd10d3f3169c Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sun, 6 Dec 2020 10:56:56 -0700 Subject: [PATCH 09/79] re-add lombok --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 49783cda..e47675a0 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ plugins { id 'java' id 'maven-publish' id 'jacoco' - //id "io.freefair.lombok" version "5.3.0" + id "io.freefair.lombok" version "5.3.0" id "com.github.hierynomus.license" version "0.15.0" } From a34ba4ce2195a82ec9673781480448bc228d1250 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sun, 6 Dec 2020 10:58:23 -0700 Subject: [PATCH 10/79] fix escape in javadoc --- .../stickyapi/bukkit/item/generator/BookGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java index 284452a8..5d6ca674 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java @@ -43,7 +43,7 @@ public BookGenerator(Material material){ /** * Escape characters for colors, etc... - * I guess we can just.... use the &-* codes or something, we can use chatcolors somehow + * I guess we can just.... use the &-* codes or something, we can use chatcolors somehow * Beyond that, we can use markdown??? */ From d2ced9479e8508e5a0935373c248bfc233a40683 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sun, 6 Dec 2020 13:07:40 -0700 Subject: [PATCH 11/79] Allow converting json to pages (doesnt check json validity!) --- .../bukkit/item/generator/BookGenerator.java | 119 +++++++++++++----- 1 file changed, 91 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java index 5d6ca674..0188f241 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java @@ -5,28 +5,74 @@ package com.dumbdogdiner.stickyapi.bukkit.item.generator; import com.dumbdogdiner.stickyapi.common.util.BookUtil; +import com.dumbdogdiner.stickyapi.common.util.ReflectionUtil; import com.google.gson.Gson; -import net.md_5.bungee.api.chat.BaseComponent; + +import com.google.gson.JsonObject; +import lombok.Setter; +import lombok.experimental.Accessors; import net.md_5.bungee.api.chat.TextComponent; + +import net.minecraft.server.v1_16_R3.NBTTagCompound; +import net.minecraft.server.v1_16_R3.NBTTagList; +import net.minecraft.server.v1_16_R3.NBTTagString; import org.bukkit.Material; -import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftMetaBook; + +import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta.Generation; import org.bukkit.inventory.meta.BookMeta; import lombok.Getter; -import lombok.Setter; +import org.bukkit.inventory.meta.ItemMeta; + +import java.awt.print.Book; +import java.lang.reflect.Constructor; +@SuppressWarnings({"UnusedReturnValue", "unused"}) +@Accessors(chain = true) public class BookGenerator { - private static final int MAX_PAGES = 50; - private static final int MAX_LINES_PER_PAGE = 14; - private static final float MAX_PIXELS_PER_LINE = 113; + public enum Generation{ + ORIGINAL(0), + COPY_OF_ORIGINAL(1), + COPY_OF_COPY(2), + TATTERED(3); + + private Generation(int g){ + genInt = g; + } + private final int genInt; + public int asInt(){ + return genInt; + } + } + + private NBTTagList pages = new NBTTagList(); - BookMeta meta; + + @Setter @Getter private Generation generation = Generation.ORIGINAL; - Material mat; + @Getter + Material bookType; + + @Getter + @Setter + private String author; + + /** + * Title of the book + * -- SETTER -- + * Sets the name of the book, this may have ChatColors + * + * @param title The new value. + * -- GETTER -- + * Returns the book title + * @return String The book's title + */ + @SuppressWarnings("JavaDoc") + @Setter @Getter private String title; @@ -34,7 +80,11 @@ public BookGenerator(Material material){ if(material != Material.WRITABLE_BOOK && material != Material.WRITTEN_BOOK){ throw new IllegalArgumentException("Material must be WRITABLE_BOOK or WRITTEN_BOOK"); } - meta = (BookMeta) new ItemStack(material).getItemMeta(); + + this.bookType = material; + + + } /* /give @p written_book{pages:['["",{"text":"Dumb Dog Diner MC\\nSurvival Handbook","bold":true,"italic":true,"color":"dark_purple"},{"text":"\\n\\n","color":"reset"},{"text":"Table of Contents:","bold":true,"italic":true,"underlined":true,"color":"dark_red"},{"text":"\\n","color":"reset"},{"text":"Page 2: ","color":"red"},{"text":"Rules\\n","color":"reset"},{"text":"Pg. 3: ","color":"red"},{"text":"Gameplay\\n","color":"reset"},{"text":"Pg. 5: ","color":"red"},{"text":"Trading\\n","color":"reset"},{"text":"Pg. 7: ","color":"red"},{"text":"Commands\\n","color":"reset"},{"text":"Pg. 9: ","color":"red"},{"text":"Trading\\nCommands\\n","color":"reset"},{"text":"Pg. 11: ","color":"red"},{"text":"Misc Commands\\n","color":"reset"},{"text":"Pg. 12: ","color":"red"},{"text":"Getting Help\\n","color":"reset"},{"text":"Pg. 14: ","color":"red"},{"text":"Credits","color":"reset"}]','["",{"text":"The Rules:","bold":true,"italic":true,"underlined":true,"color":"red"},{"text":"\\n1. Absolutely no\\ngriefing, theft, or\\nintentional distress!\\n2. No cheating/hacking\\nallowed. Optifine and\\nsimilar are okay.\\n3. No floating trees.\\n4. No fully-automatic\\nredstone farms.\\n5. No harassment,\\nbullying, or abuse.\\n6. No AFK fishing.","color":"reset"}]','["",{"text":"Gameplay:","bold":true,"italic":true,"underlined":true,"color":"dark_green"},{"text":"\\nThe world border for all worlds is 8,000\\nblocks from the\\ncenter. Because of\\nnow ","color":"reset"},{"text":"Nether Portal","color":"dark_red"},{"text":"\\ntravel works, you will\\nnot be able to light\\nthem past 1,000 blocks\\nfrom the center.\\nYou may build wherever you like! Try ","color":"reset"},{"text":"/rtp","color":"blue"},{"text":" to help find a spot!","color":"reset"}]','["",{"text":"This server uses a "},{"text":"Death Chest ","color":"red"},{"text":"system. Upon death, a campfire with your items will spawn at your death location. It will last\\nfor 10 minutes before\\nyour items drop on \\nthe ground!\\n\\nYou can have up to 3\\n","color":"reset"},{"text":"Death Chests","color":"red"},{"text":" at a time.","color":"reset"}]','["",{"text":"Trading:","bold":true,"italic":true,"underlined":true,"color":"dark_aqua"},{"text":"\\nWe use chest chops\\nfor player to trade\\ngood for ","color":"reset"},{"text":"Coins","color":"gold"},{"text":".\\n\\nCoins may be earned through selling goods\\nto other players,\\npaying/receiving\\nmoney for a service,\\nor by selling goods to\\nthe server itself.","color":"reset"}]','{"text":"Chest shops can buy\\nor sell items!\\n\\nTo make a shop, place a chest and\\nshift-click with the\\nitem you want to sell\\nor buy.\\n\\nRegular users may have up to 6 shops\\nat a time."}','["",{"text":"Commands:","bold":true,"italic":true,"underlined":true,"color":"red"},{"text":"\\nTab-complete is set\\nup to only show commands you have access to. Here are some useful ones:\\n\\n","color":"reset"},{"text":"/help ","color":"blue"},{"text":"- Opens the\\nhelp menu\\n","color":"reset"},{"text":"/servers ","color":"blue"},{"text":"- Opens the\\nserver menu\\n","color":"reset"},{"text":"/rules","color":"blue"},{"text":" - Grants this\\nbook","color":"reset"}]','["",{"text":"/options ","color":"blue"},{"text":"- Opens the player options menu\\n","color":"reset"},{"text":"/tpa ","color":"blue"},{"text":"- Sends a\\nteleport request to another player\\n","color":"reset"},{"text":"/rtp ","color":"blue"},{"text":"- Start a\\nrandom teleport\\n","color":"reset"},{"text":"/pw ","color":"blue"},{"text":"- Opens the playerwarps personal\\nhome menu\\n","color":"reset"},{"text":"/helpme ","color":"blue"},{"text":"- Pings an online staff member\\nfor assistance","color":"reset"}]','["",{"text":"Trading Commands:","bold":true,"italic":true,"underlined":true,"color":"dark_purple"},{"text":"\\n","color":"reset"},{"text":"/bal ","color":"blue"},{"text":"- Check your\\nbalance\\n","color":"reset"},{"text":"/pay ","color":"blue"},{"text":"- Pay another player\\n","color":"reset"},{"text":"/sell ","color":"blue"},{"text":"- Sell the item in your hand to the server\\n","color":"reset"},{"text":"/worth ","color":"blue"},{"text":"- Shows the\\nitem price when selling\\nto the server","color":"reset"}]','["",{"text":"/value","color":"blue"},{"text":" - Shows the\\naverage selling price\\nfor an item in\\nplayer shops","color":"reset"}]','["",{"text":"Extra Commands:","bold":true,"italic":true,"underlined":true,"color":"dark_aqua"},{"text":"\\n","color":"reset"},{"text":"/donate, /vip ","color":"blue"},{"text":"- Gives link to the server Patreon page\\n","color":"reset"},{"text":"/discord ","color":"blue"},{"text":"- Gives link to the server Discord\\n","color":"reset"},{"text":"/twitter, /twitch ","color":"blue"},{"text":"- Gives social media links\\n","color":"reset"},{"text":"/merch ","color":"blue"},{"text":"- Gives merch link\\n","color":"reset"},{"text":"/afk ","color":"blue"},{"text":"- Set your status to AFK","color":"reset"}]','["",{"text":"Getting Help:","bold":true,"italic":true,"underlined":true,"color":"light_purple"},{"text":"\\nIf you ever need help\\ngetting your way\\naround the server,\\nplease ask any staff!\\n","color":"reset"},{"text":"/helpme","color":"blue"},{"text":"\\n\\nPlease join the\\nDiscord server to get\\ntechnical help!\\n","color":"reset"},{"text":"/discord","color":"blue"}]','["",{"text":"Please report any\\nbugs, griefing, etc.\\nthat you come across\\nor are a victim of. A\\nstaff member will be\\nhappy to assist you.\\n\\nThe help menu has shortcuts that make getting help easy!\\n"},{"text":"/help","color":"blue"}]','["",{"text":"Credits:","bold":true,"italic":true,"underlined":true,"color":"gold"},{"text":"\\n","color":"reset"},{"text":"dddMC ","bold":true,"color":"dark_purple"},{"text":"is fully funded\\nthrough player donations. Please consider helping support us on Patreon!\\n","color":"reset"},{"text":"/donate /patreon","color":"blue"},{"text":"\\n\\nPatrons will receive a\\nVIP rank. More ranks\\nwill be added in the\\nfuture.","color":"reset"}]','["",{"text":"We hope you enjoy\\nyour time playing\\non the server!\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n- Stixil, "},{"text":"dddMC 2020","bold":true,"color":"dark_purple"}]'],title:"&ddddMC Survival Handbook",author:Stixil} @@ -47,31 +97,43 @@ public BookGenerator(Material material){ * Beyond that, we can use markdown??? */ - public BookGenerator setGeneration(BookMeta.Generation generation){ - this.generation = generation; + public BookGenerator addPages(JsonObject ... pages){ + for (JsonObject page: pages) { + addPage(page); + } return this; } - - Generation g = BookMeta.Generation.ORIGINAL; - public ItemStack toItemStack(){ - ItemStack book = new ItemStack(Material.WRITTEN_BOOK); - BookMeta meta = null; - return null; + public BookGenerator addPage(JsonObject page){ + pages.add(NBTTagString.create(page.toString())); + return this; } - public BookGenerator setTitle(String title){ - this.title = title; - return this; + + + public ItemStack toItemStack(int qty){ + NBTTagCompound root = new NBTTagCompound(); + if(bookType == Material.WRITTEN_BOOK) { + root.setString("title", title); + root.setString("author", author); + root.setInt("generation", generation.asInt()); + } + root.set("pages", pages); + + net.minecraft.server.v1_16_R3.ItemStack nmsBook= CraftItemStack.asNMSCopy(new ItemStack(bookType,qty)); + nmsBook.setTag(root); + return CraftItemStack.asBukkitCopy(nmsBook); } - private class TextWrapper{ - public String Text; - public boolean bold; - public boolean italic; - public boolean underlined; - public boolean strikethrough; - public boolean obfuscated; - public String color; + + + private NBTTagCompound generateRootNBT(NBTTagCompound base){ + + NBTTagList modifiers = new NBTTagList(); + + modifiers.add(base); + NBTTagCompound root = new NBTTagCompound(); + root.set("AttributeModifiers", modifiers); + return root; } public String generateText(TextComponent [] wrappers){ @@ -95,4 +157,5 @@ public BookGenerator(String sth){ int x = BookUtil.getCharacterWidth('a'); } + } From 0b7b3ced123cc2d6ca83a2e96ca17be95e13a3ff Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sun, 6 Dec 2020 13:15:12 -0700 Subject: [PATCH 12/79] clean imports, clean some code --- .../bukkit/item/generator/BookGenerator.java | 86 +++++++------------ 1 file changed, 29 insertions(+), 57 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java index 0188f241..9f5ed23c 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java @@ -5,43 +5,35 @@ package com.dumbdogdiner.stickyapi.bukkit.item.generator; import com.dumbdogdiner.stickyapi.common.util.BookUtil; -import com.dumbdogdiner.stickyapi.common.util.ReflectionUtil; import com.google.gson.Gson; - import com.google.gson.JsonObject; +import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; import net.md_5.bungee.api.chat.TextComponent; - import net.minecraft.server.v1_16_R3.NBTTagCompound; import net.minecraft.server.v1_16_R3.NBTTagList; import net.minecraft.server.v1_16_R3.NBTTagString; import org.bukkit.Material; - import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.BookMeta.Generation; -import org.bukkit.inventory.meta.BookMeta; -import lombok.Getter; -import org.bukkit.inventory.meta.ItemMeta; - -import java.awt.print.Book; -import java.lang.reflect.Constructor; @SuppressWarnings({"UnusedReturnValue", "unused"}) @Accessors(chain = true) public class BookGenerator { - public enum Generation{ + public enum Generation { ORIGINAL(0), COPY_OF_ORIGINAL(1), COPY_OF_COPY(2), TATTERED(3); - private Generation(int g){ + private Generation(int g) { genInt = g; } + private final int genInt; - public int asInt(){ + + public int asInt() { return genInt; } } @@ -49,7 +41,6 @@ public int asInt(){ private NBTTagList pages = new NBTTagList(); - @Setter @Getter private Generation generation = Generation.ORIGINAL; @@ -76,85 +67,66 @@ public int asInt(){ @Getter private String title; - public BookGenerator(Material material){ - if(material != Material.WRITABLE_BOOK && material != Material.WRITTEN_BOOK){ + public BookGenerator(Material material) { + if (material != Material.WRITABLE_BOOK && material != Material.WRITTEN_BOOK) { throw new IllegalArgumentException("Material must be WRITABLE_BOOK or WRITTEN_BOOK"); } this.bookType = material; - } /* /give @p written_book{pages:['["",{"text":"Dumb Dog Diner MC\\nSurvival Handbook","bold":true,"italic":true,"color":"dark_purple"},{"text":"\\n\\n","color":"reset"},{"text":"Table of Contents:","bold":true,"italic":true,"underlined":true,"color":"dark_red"},{"text":"\\n","color":"reset"},{"text":"Page 2: ","color":"red"},{"text":"Rules\\n","color":"reset"},{"text":"Pg. 3: ","color":"red"},{"text":"Gameplay\\n","color":"reset"},{"text":"Pg. 5: ","color":"red"},{"text":"Trading\\n","color":"reset"},{"text":"Pg. 7: ","color":"red"},{"text":"Commands\\n","color":"reset"},{"text":"Pg. 9: ","color":"red"},{"text":"Trading\\nCommands\\n","color":"reset"},{"text":"Pg. 11: ","color":"red"},{"text":"Misc Commands\\n","color":"reset"},{"text":"Pg. 12: ","color":"red"},{"text":"Getting Help\\n","color":"reset"},{"text":"Pg. 14: ","color":"red"},{"text":"Credits","color":"reset"}]','["",{"text":"The Rules:","bold":true,"italic":true,"underlined":true,"color":"red"},{"text":"\\n1. Absolutely no\\ngriefing, theft, or\\nintentional distress!\\n2. No cheating/hacking\\nallowed. Optifine and\\nsimilar are okay.\\n3. No floating trees.\\n4. No fully-automatic\\nredstone farms.\\n5. No harassment,\\nbullying, or abuse.\\n6. No AFK fishing.","color":"reset"}]','["",{"text":"Gameplay:","bold":true,"italic":true,"underlined":true,"color":"dark_green"},{"text":"\\nThe world border for all worlds is 8,000\\nblocks from the\\ncenter. Because of\\nnow ","color":"reset"},{"text":"Nether Portal","color":"dark_red"},{"text":"\\ntravel works, you will\\nnot be able to light\\nthem past 1,000 blocks\\nfrom the center.\\nYou may build wherever you like! Try ","color":"reset"},{"text":"/rtp","color":"blue"},{"text":" to help find a spot!","color":"reset"}]','["",{"text":"This server uses a "},{"text":"Death Chest ","color":"red"},{"text":"system. Upon death, a campfire with your items will spawn at your death location. It will last\\nfor 10 minutes before\\nyour items drop on \\nthe ground!\\n\\nYou can have up to 3\\n","color":"reset"},{"text":"Death Chests","color":"red"},{"text":" at a time.","color":"reset"}]','["",{"text":"Trading:","bold":true,"italic":true,"underlined":true,"color":"dark_aqua"},{"text":"\\nWe use chest chops\\nfor player to trade\\ngood for ","color":"reset"},{"text":"Coins","color":"gold"},{"text":".\\n\\nCoins may be earned through selling goods\\nto other players,\\npaying/receiving\\nmoney for a service,\\nor by selling goods to\\nthe server itself.","color":"reset"}]','{"text":"Chest shops can buy\\nor sell items!\\n\\nTo make a shop, place a chest and\\nshift-click with the\\nitem you want to sell\\nor buy.\\n\\nRegular users may have up to 6 shops\\nat a time."}','["",{"text":"Commands:","bold":true,"italic":true,"underlined":true,"color":"red"},{"text":"\\nTab-complete is set\\nup to only show commands you have access to. Here are some useful ones:\\n\\n","color":"reset"},{"text":"/help ","color":"blue"},{"text":"- Opens the\\nhelp menu\\n","color":"reset"},{"text":"/servers ","color":"blue"},{"text":"- Opens the\\nserver menu\\n","color":"reset"},{"text":"/rules","color":"blue"},{"text":" - Grants this\\nbook","color":"reset"}]','["",{"text":"/options ","color":"blue"},{"text":"- Opens the player options menu\\n","color":"reset"},{"text":"/tpa ","color":"blue"},{"text":"- Sends a\\nteleport request to another player\\n","color":"reset"},{"text":"/rtp ","color":"blue"},{"text":"- Start a\\nrandom teleport\\n","color":"reset"},{"text":"/pw ","color":"blue"},{"text":"- Opens the playerwarps personal\\nhome menu\\n","color":"reset"},{"text":"/helpme ","color":"blue"},{"text":"- Pings an online staff member\\nfor assistance","color":"reset"}]','["",{"text":"Trading Commands:","bold":true,"italic":true,"underlined":true,"color":"dark_purple"},{"text":"\\n","color":"reset"},{"text":"/bal ","color":"blue"},{"text":"- Check your\\nbalance\\n","color":"reset"},{"text":"/pay ","color":"blue"},{"text":"- Pay another player\\n","color":"reset"},{"text":"/sell ","color":"blue"},{"text":"- Sell the item in your hand to the server\\n","color":"reset"},{"text":"/worth ","color":"blue"},{"text":"- Shows the\\nitem price when selling\\nto the server","color":"reset"}]','["",{"text":"/value","color":"blue"},{"text":" - Shows the\\naverage selling price\\nfor an item in\\nplayer shops","color":"reset"}]','["",{"text":"Extra Commands:","bold":true,"italic":true,"underlined":true,"color":"dark_aqua"},{"text":"\\n","color":"reset"},{"text":"/donate, /vip ","color":"blue"},{"text":"- Gives link to the server Patreon page\\n","color":"reset"},{"text":"/discord ","color":"blue"},{"text":"- Gives link to the server Discord\\n","color":"reset"},{"text":"/twitter, /twitch ","color":"blue"},{"text":"- Gives social media links\\n","color":"reset"},{"text":"/merch ","color":"blue"},{"text":"- Gives merch link\\n","color":"reset"},{"text":"/afk ","color":"blue"},{"text":"- Set your status to AFK","color":"reset"}]','["",{"text":"Getting Help:","bold":true,"italic":true,"underlined":true,"color":"light_purple"},{"text":"\\nIf you ever need help\\ngetting your way\\naround the server,\\nplease ask any staff!\\n","color":"reset"},{"text":"/helpme","color":"blue"},{"text":"\\n\\nPlease join the\\nDiscord server to get\\ntechnical help!\\n","color":"reset"},{"text":"/discord","color":"blue"}]','["",{"text":"Please report any\\nbugs, griefing, etc.\\nthat you come across\\nor are a victim of. A\\nstaff member will be\\nhappy to assist you.\\n\\nThe help menu has shortcuts that make getting help easy!\\n"},{"text":"/help","color":"blue"}]','["",{"text":"Credits:","bold":true,"italic":true,"underlined":true,"color":"gold"},{"text":"\\n","color":"reset"},{"text":"dddMC ","bold":true,"color":"dark_purple"},{"text":"is fully funded\\nthrough player donations. Please consider helping support us on Patreon!\\n","color":"reset"},{"text":"/donate /patreon","color":"blue"},{"text":"\\n\\nPatrons will receive a\\nVIP rank. More ranks\\nwill be added in the\\nfuture.","color":"reset"}]','["",{"text":"We hope you enjoy\\nyour time playing\\non the server!\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n- Stixil, "},{"text":"dddMC 2020","bold":true,"color":"dark_purple"}]'],title:"&ddddMC Survival Handbook",author:Stixil} */ - /** - * Escape characters for colors, etc... - * I guess we can just.... use the &-* codes or something, we can use chatcolors somehow - * Beyond that, we can use markdown??? - */ + /** + * Escape characters for colors, etc... + * I guess we can just.... use the &-* codes or something, we can use chatcolors somehow + * Beyond that, we can use markdown??? + */ - public BookGenerator addPages(JsonObject ... pages){ - for (JsonObject page: pages) { + public BookGenerator addPages(JsonObject... pages) { + for (JsonObject page : pages) { addPage(page); } return this; } - public BookGenerator addPage(JsonObject page){ - pages.add(NBTTagString.create(page.toString())); + + public BookGenerator addPage(JsonObject page) { + if(!isFull()){ + pages.add(NBTTagString.create(page.toString())); + } else { + throw new IllegalStateException("Book is overfilled"); + } return this; } - public ItemStack toItemStack(int qty){ + public ItemStack toItemStack(int qty) { NBTTagCompound root = new NBTTagCompound(); - if(bookType == Material.WRITTEN_BOOK) { + if (bookType == Material.WRITTEN_BOOK) { root.setString("title", title); root.setString("author", author); root.setInt("generation", generation.asInt()); } root.set("pages", pages); - net.minecraft.server.v1_16_R3.ItemStack nmsBook= CraftItemStack.asNMSCopy(new ItemStack(bookType,qty)); + net.minecraft.server.v1_16_R3.ItemStack nmsBook = CraftItemStack.asNMSCopy(new ItemStack(bookType, qty)); nmsBook.setTag(root); return CraftItemStack.asBukkitCopy(nmsBook); } - - private NBTTagCompound generateRootNBT(NBTTagCompound base){ - - NBTTagList modifiers = new NBTTagList(); - - modifiers.add(base); - NBTTagCompound root = new NBTTagCompound(); - root.set("AttributeModifiers", modifiers); - return root; - } - - public String generateText(TextComponent [] wrappers){ - TextComponent t = wrappers[0]; - - - Gson g = new Gson(); - return g.toJson(wrappers); + public float percentFull() { + return (float)pages.size() / (float)BookUtil.PAGES_PER_BOOK; } - public float percentFull(){ - return 0.0f; - } - - //TODO STUB - public boolean isFull(){ - return false; - } - public BookGenerator(String sth){ - int x = BookUtil.getCharacterWidth('a'); + public boolean isFull() { + return percentFull() >= 1.0f; } From a822e67a6fdd752454944f764ae89ab6d45faed7 Mon Sep 17 00:00:00 2001 From: Matt <25674682+spazzylemons@users.noreply.github.com> Date: Sun, 6 Dec 2020 17:48:51 -0500 Subject: [PATCH 13/79] More BookUtils, create JsonComponent, more fixes to renderer --- .../commonmarkextensions/JsonComponent.java | 139 ++++++++++++++++++ ...ntWriter.java => JsonComponentWriter.java} | 36 ++--- .../MCColorFormatDelimiterProcessor.java | 8 +- .../MarkdownJsonRenderer.java | 9 +- .../stickyapi/common/util/BookUtil.java | 139 +++++++++++++++++- 5 files changed, 297 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponent.java rename src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/{TextComponentWriter.java => JsonComponentWriter.java} (60%) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponent.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponent.java new file mode 100644 index 00000000..f0283c03 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponent.java @@ -0,0 +1,139 @@ +/** + * Copyright (c) 2020 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import lombok.Getter; +import lombok.NonNull; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * A text component that can be converted to JSON. Differs slightly from BaseComponent. + */ +public class JsonComponent { + @Getter @Setter + private @NonNull String text = ""; + // for now, the attributes are only what are needed for the renderer, might expand later + @Getter @Setter + private boolean isBold = false; + @Getter @Setter + private boolean isItalic = false; + @Getter @Setter + private boolean isUnderlined = false; + @Getter @Setter + private String color = null; + @Getter @Setter + private String url = null; + @Getter @Setter + private String hoverText = null; + @Getter + private final List children = new ArrayList<>(); + + public JsonComponent() {} + + public JsonComponent(@NonNull String text) { + this.text = text; + } + + /** + * Converts the component into JSON. + * @return {@link com.google.gson.JsonObject} + */ + public JsonObject toJson() { + JsonObject object = new JsonObject(); + object.addProperty("text", text); + if (isBold) object.addProperty("bold", true); + if (isItalic) object.addProperty("italic", true); + if (isUnderlined) object.addProperty("underline", true); + if (color != null) { + object.addProperty("color", color); + } + if (url != null) { + JsonObject clickEvent = new JsonObject(); + clickEvent.addProperty("action", "open_url"); + clickEvent.addProperty("value", url); + object.add("clickEvent", clickEvent); + } + if (hoverText != null) { + JsonObject hoverEvent = new JsonObject(); + hoverEvent.addProperty("action", "show_text"); + hoverEvent.addProperty("contents", hoverText); + object.add("hoverEvent", hoverEvent); + } + if (!children.isEmpty()) { + JsonArray extra = new JsonArray(); + for (JsonComponent component : children) { + extra.add(component.toJson()); + } + object.add("extra", extra); + } + return object; + } + + /** + * Flatten a JsonComponent into an array of JsonComponents with no children. + * @return {@link java.util.List} + */ + public List flatten() { + return flattenWithParents(new ArrayList<>()); + } + + private List flattenWithParents(List parents) { + List components = new ArrayList<>(); + if (!text.equals("")) { + JsonComponent flatComponent = new JsonComponent(text); + flatComponent.setBold(isBold || parents.stream().anyMatch(c -> c.isBold)); + flatComponent.setItalic(isItalic || parents.stream().anyMatch(c -> c.isItalic)); + flatComponent.setUnderlined(isUnderlined || parents.stream().anyMatch(c -> c.isUnderlined)); + if (color == null) { + flatComponent.setColor(findFromList(parents, JsonComponent::getColor)); + } else { + flatComponent.setColor(color); + } + if (url == null) { + flatComponent.setUrl(findFromList(parents, JsonComponent::getUrl)); + } else { + flatComponent.setUrl(url); + } + if (hoverText == null) { + flatComponent.setHoverText(findFromList(parents, JsonComponent::getHoverText)); + } else { + flatComponent.setHoverText(hoverText); + } + components.add(flatComponent); + } + List newParents = Stream.concat(Stream.of(this), parents.stream()).collect(Collectors.toList()); + for (JsonComponent child : children) { + components.addAll(child.flattenWithParents(newParents)); + } + return components; + } + + private T findFromList(List components, Function getter) { + return components.stream().map(getter).filter(Objects::nonNull).findFirst().orElse(null); + } + + public JsonComponent duplicate() { + JsonComponent clone = new JsonComponent(text); + clone.isBold = isBold; + clone.isItalic = isItalic; + clone.isUnderlined = isUnderlined; + clone.color = color; + clone.url = url; + clone.hoverText = hoverText; + for (JsonComponent child : children) { + clone.children.add(child.duplicate()); + } + return clone; + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/TextComponentWriter.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponentWriter.java similarity index 60% rename from src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/TextComponentWriter.java rename to src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponentWriter.java index 1348e966..9be6ec2a 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/TextComponentWriter.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponentWriter.java @@ -4,33 +4,27 @@ */ package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.ClickEvent; -import net.md_5.bungee.api.chat.HoverEvent; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.chat.hover.content.Text; - import java.util.Stack; -public class TextComponentWriter { - private final Stack levels = new Stack<>(); - private TextComponent current; +public class JsonComponentWriter { + private final Stack levels = new Stack<>(); + private JsonComponent current; private boolean renderNewLine = false; private boolean renderIndent = true; private int indent = 0; - public TextComponentWriter(TextComponent component) { + public JsonComponentWriter(JsonComponent component) { this.current = component; } public void enterLevel() { levels.push(current); - current = new TextComponent(); + current = new JsonComponent(); } public void exitLevel() { - TextComponent top = levels.pop(); - top.addExtra(current); + JsonComponent top = levels.pop(); + top.getChildren().add(current); current = top; } @@ -47,7 +41,7 @@ public void addText(String text) { enterLevel(); if (renderNewLine) { renderNewLine = false; - current.setText(current.getText() + "\n"); + current.setText(current.getText() + "\n\n"); renderIndent = true; } if (renderIndent) { @@ -74,23 +68,15 @@ public void setUnderlined() { current.setUnderlined(true); } - public void setColor(ChatColor color) { + public void setColor(String color) { current.setColor(color); } public void setHyperlink(String url) { - if (url == null) { - current.setClickEvent(null); - } else { - current.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url)); - } + current.setUrl(url); } public void setMouseoverText(String text) { - if (text == null) { - current.setHoverEvent(null); - } else { - current.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(text))); - } + current.setHoverText(text); } } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java index bb4d8ca0..9bab1cc6 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java @@ -13,7 +13,7 @@ import java.util.regex.Pattern; public class MCColorFormatDelimiterProcessor implements DelimiterProcessor { - private static final Pattern COLOR_PATTERN = Pattern.compile("^(black|dark_blue|dark_green|dark_aqua|dark_red|dark_purple|gold|gray|dark_gray|blue|green|aqua|red|light_purple|yellow|white|reset|#[0-9A-Fa-f]{6})\\s*(?:\\s([\\S\\s]+))?$"); + private static final Pattern COLOR_PATTERN = Pattern.compile("^(black|dark_blue|dark_green|dark_aqua|dark_red|dark_purple|gold|gray|dark_gray|blue|green|aqua|red|light_purple|yellow|white|reset|#[0-9A-Fa-f]{6})(\\s*(?:\\s[\\S\\s]+)?)$"); @Override public char getOpeningCharacter() { @@ -47,9 +47,11 @@ public void process(Text opener, Text closer, int delimiterUse) { Matcher match = COLOR_PATTERN.matcher(literal); // only create the color node if a color was specified if (match.matches()) { - ((Text) firstNext).setLiteral(match.group(2)); + ((Text) firstNext).setLiteral(match.group(2).stripLeading()); MCColorNode color = new MCColorNode(match.group(1)); - for (Node n = opener.getNext(); n != null && n != closer; n = n.getNext()) { + Node next; + for (Node n = opener.getNext(); n != null && n != closer; n = next) { + next = n.getNext(); color.appendChild(n); } opener.insertAfter(color); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java index 78b1f066..390b4df1 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java @@ -4,8 +4,6 @@ */ package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; -import lombok.Getter; -import net.md_5.bungee.api.ChatColor; import org.commonmark.node.*; import org.commonmark.renderer.NodeRenderer; @@ -27,10 +25,10 @@ public class MarkdownJsonRenderer extends AbstractVisitor implements NodeRendere Block.class )); - private final TextComponentWriter writer; + private final JsonComponentWriter writer; private int listIndex = 0; - public MarkdownJsonRenderer(TextComponentWriter writer) { + public MarkdownJsonRenderer(JsonComponentWriter writer) { this.writer = writer; } @@ -76,6 +74,7 @@ public void visit(StrongEmphasis node) { public void visit(Link link) { writer.setHyperlink(link.getDestination()); writer.setMouseoverText(link.getTitle()); + visitChildren(link); } @Override @@ -133,7 +132,7 @@ public void visit(CustomNode node) { } public void visit(MCColorNode color) { - writer.setColor(ChatColor.of(color.getColorName())); + writer.setColor(color.getColorName()); visitChildren(color); } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index 385e7585..48b7d5ca 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -4,10 +4,17 @@ */ package com.dumbdogdiner.stickyapi.common.util; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; +import java.util.regex.Pattern; -import net.md_5.bungee.api.chat.BaseComponent; +import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.JsonComponent; +import lombok.NonNull; +import org.commonmark.node.Document; +import org.commonmark.node.Heading; +import org.commonmark.node.Node; import org.jetbrains.annotations.NotNull; public class BookUtil { @@ -15,6 +22,8 @@ public class BookUtil { public static final int LINES_PER_PAGE = 14; public static final int PAGES_PER_BOOK = 50; + private static final Pattern SPLIT_PATTERN = Pattern.compile("(?<=[ \n])|(?=[ \n])"); + // TODO: Test efficiency of this vs switch/case static HashMap characterWidths = new HashMap<>(); static { @@ -61,4 +70,132 @@ public static int getCharacterWidth(char c) { } return 5; } + + /** + * Split a JsonComponent into pages for use in a book. + * @param origComponent The component to split into pages + * @return A list of JsonComponents, one for each page + */ + public static List splitBookPages(@NonNull JsonComponent origComponent) { + List lines = wrapLines(origComponent, PIXELS_PER_LINE); + List pages = new ArrayList<>(); + JsonComponent currentPage = new JsonComponent(); + int i = 0; + boolean trimNewLines = true; + for (JsonComponent line : lines) { + if (i++ % LINES_PER_PAGE == 0) { + trimNewLines = true; + pages.add(currentPage); + currentPage = new JsonComponent(); + } + if (trimNewLines) { + if (line.getText().equals("\n")) { + line.setText(""); + } else { + trimNewLines = false; + } + } + currentPage.getChildren().add(line); + } + pages.add(currentPage); + return pages.subList(1, pages.size()); + } + + /** + * Wrap a JsonComponent into lines. + * @param origComponent The JsonComponent to wrap. + * @param pixels The width of the JsonComponent in pixels. + * @return A list of JsonComponents, one for each line + */ + public static List wrapLines(@NonNull JsonComponent origComponent, int pixels) { + List components = origComponent.flatten(); + if (components.isEmpty()) return new ArrayList<>(); + List lineComponents = new ArrayList<>(); + JsonComponent currentLine = new JsonComponent(); + int xPosition = 0; + for (JsonComponent component : components) { + String[] words = SPLIT_PATTERN.split(component.getText()); + for (String word : words) { + if (word.isEmpty()) continue; + if (word.charAt(0) == '\n') { + int l = word.length(); + for (int i = 0; i < l; ++i) { + lineComponents.add(currentLine); + currentLine = new JsonComponent("\n"); + } + xPosition = 0; + } else { + JsonComponent wordComponent = component.duplicate(); + wordComponent.setText(word); + int width = getStringWidth(word) + 1; + if (component.isBold()) width += word.length() + 1; + if (xPosition + width >= pixels) { + lineComponents.add(currentLine); + currentLine = new JsonComponent(); + xPosition = width; + } else { + xPosition += width; + } + currentLine.getChildren().add(wordComponent); + } + } + } + if (!currentLine.getChildren().isEmpty()) { + lineComponents.add(currentLine); + } + return lineComponents; + } + + /** + * Split a document into multiple documents, delimited by headings. Destroys the original document. + * @param document The original document + * @param maxHeadingSize The smallest size of heading to split on. + * @return A list of each document. + */ + public static List splitDocumentByHeadings(@NonNull Document document, int maxHeadingSize) { + List docs = new ArrayList<>(); + Document currentDocument = new Document(); + Node next; + for (Node n = document.getFirstChild(); n != null; n = next) { + next = n.getNext(); + if (n instanceof Heading && ((Heading) n).getLevel() <= maxHeadingSize) { + docs.add(currentDocument); + currentDocument = new Document(); + } + currentDocument.appendChild(n); + } + docs.add(currentDocument); + return docs; + } + + /** + * Measure the width of text in a BaseComponent in pixels. + * @param component The component to measure + * @return The width of the text, in pixels + */ + public static int getComponentWidth(@NotNull JsonComponent component) { + String text = component.getText(); + int width = getStringWidth(text); + if (component.isBold()) width += text.length(); + for (JsonComponent child : component.getChildren()) { + width += getComponentWidth(child); + } + return width; + } + + /** + * Measure the width of a string, assuming it is unformatted and in the default Minecraft font. + * @param text The string to measure + * @return The width of the string, in pixels + */ + public static int getStringWidth(@NotNull String text) { + if (text.isEmpty()) return 0; + int width = 0; + int textLength = text.length(); + for (int i = 0; i < textLength; ++i) { + width += BookUtil.getCharacterWidth(text.charAt(i)); + } + width += textLength - 1; + return width; + } } From 8c79712b233ed85eaca66d9692273419fc2b9059 Mon Sep 17 00:00:00 2001 From: Matt <25674682+spazzylemons@users.noreply.github.com> Date: Sun, 6 Dec 2020 22:04:58 -0500 Subject: [PATCH 14/79] make RuleBook generate rulebooks --- .../stickyapi/bukkit/item/RuleBook.java | 50 +++++++++++++++---- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java index 5cadc802..7da0bd7f 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java @@ -4,25 +4,53 @@ */ package com.dumbdogdiner.stickyapi.bukkit.item; +import com.dumbdogdiner.stickyapi.bukkit.item.generator.BookGenerator; +import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.JsonComponent; +import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.JsonComponentWriter; import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.MCColorFormatDelimiterProcessor; -import org.commonmark.node.Node; +import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.MarkdownJsonRenderer; +import com.dumbdogdiner.stickyapi.common.util.BookUtil; +import org.bukkit.Bukkit; +import org.bukkit.inventory.ItemStack; +import org.bukkit.Material; +import org.commonmark.node.Document; import org.commonmark.parser.Parser; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; +import java.io.*; +import java.util.List; public class RuleBook { //TODO MOVE TO CONST private static final String RULEBOOK_PATH = "plugin name i guess? /rulebook.md"; - public static void generateDefault() throws IOException { - Parser cmparser = Parser.builder() + + // TODO where should we expect to find rulebook.md? using server root directory for now + private static File getRulebookPath() { + return new File(Bukkit.getWorldContainer(), "rulebook.md"); + } + + public static ItemStack generateDefault() throws IOException { + try (var reader = new InputStreamReader(new FileInputStream(getRulebookPath()))) { + return generate(reader, "§ddddMCSurvival Handbook", "Stixil"); + } + } + + public static ItemStack generate(Reader reader, String title, String author) throws IOException { + var cmparser = Parser.builder() .customDelimiterProcessor(new MCColorFormatDelimiterProcessor()) .build(); - File file = new File(RULEBOOK_PATH); - Node bookRoot = cmparser.parseReader(new InputStreamReader(new FileInputStream(new File(RULEBOOK_PATH)))); - //TODO: Traverse all subnodes and build the relevant json, convert to nbt, create a bookmeta, create an itemstack, and return it - + var bookRoot = (Document) cmparser.parseReader(reader); + var bookGenerator = new BookGenerator(Material.WRITTEN_BOOK); + BookUtil.splitDocumentByHeadings(bookRoot, 2) + .stream().map(document -> { + var component = new JsonComponent(); + var writer = new JsonComponentWriter(component); + new MarkdownJsonRenderer(writer).render(document); + return component; + }).map(BookUtil::splitBookPages).flatMap(List::stream).forEach(page -> { + bookGenerator.addPage(page.toJson()); + }); + bookGenerator.setTitle(title); + bookGenerator.setAuthor(author); + return bookGenerator.toItemStack(1); } } From 92c810464828c1ef0b3776e0f12ad2dc5f3d38bf Mon Sep 17 00:00:00 2001 From: Matt <25674682+spazzylemons@users.noreply.github.com> Date: Mon, 7 Dec 2020 08:39:06 -0500 Subject: [PATCH 15/79] Fix a NoSuchMethodError in BookGenerator --- .../stickyapi/bukkit/item/generator/BookGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java index 9f5ed23c..47282a12 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java @@ -96,7 +96,7 @@ public BookGenerator addPages(JsonObject... pages) { public BookGenerator addPage(JsonObject page) { if(!isFull()){ - pages.add(NBTTagString.create(page.toString())); + pages.add(NBTTagString.a(page.toString())); } else { throw new IllegalStateException("Book is overfilled"); } From de2a517d2c7bb17287ae80b869467b5783df07ca Mon Sep 17 00:00:00 2001 From: Matt <25674682+spazzylemons@users.noreply.github.com> Date: Mon, 7 Dec 2020 09:22:32 -0500 Subject: [PATCH 16/79] Choose NBTTagString method based on server type --- .../bukkit/item/generator/BookGenerator.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java index 47282a12..dd53e768 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java @@ -4,6 +4,8 @@ */ package com.dumbdogdiner.stickyapi.bukkit.item.generator; +import com.dumbdogdiner.stickyapi.StickyAPI; +import com.dumbdogdiner.stickyapi.common.ServerVersion; import com.dumbdogdiner.stickyapi.common.util.BookUtil; import com.google.gson.Gson; import com.google.gson.JsonObject; @@ -96,7 +98,15 @@ public BookGenerator addPages(JsonObject... pages) { public BookGenerator addPage(JsonObject page) { if(!isFull()){ - pages.add(NBTTagString.a(page.toString())); + String jsonString = page.toString(); + NBTTagString tag; + // .create just calls .a, so both branches are identical except .create is added by Paper + if (ServerVersion.isPaper()) { + tag = NBTTagString.create(jsonString); + } else { + tag = NBTTagString.a(jsonString); + } + pages.add(tag); } else { throw new IllegalStateException("Book is overfilled"); } From 8753fe5e704a53aa2bdec13021118f275d3149fb Mon Sep 17 00:00:00 2001 From: Matt <25674682+spazzylemons@users.noreply.github.com> Date: Mon, 7 Dec 2020 12:37:22 -0500 Subject: [PATCH 17/79] Expand JsonComponent, change section splitting method to use breaks --- .../stickyapi/bukkit/item/RuleBook.java | 27 ++-- .../common/book/chat/ClickEvent.java | 151 ++++++++++++++++++ .../common/book/chat/ComponentColor.java | 68 ++++++++ .../common/book/chat/HoverEvent.java | 109 +++++++++++++ .../JsonComponent.java | 90 +++++------ .../JsonComponentWriter.java | 35 ++-- .../MCColorFormatDelimiterProcessor.java | 19 ++- .../commonmarkextensions/MCColorNode.java | 7 +- .../MarkdownJsonRenderer.java | 17 +- .../stickyapi/common/util/BookUtil.java | 29 +++- 10 files changed, 462 insertions(+), 90 deletions(-) create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java rename src/main/java/com/dumbdogdiner/stickyapi/common/book/{commonmarkextensions => chat}/JsonComponent.java (51%) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java index 7da0bd7f..1569b9ea 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java @@ -5,7 +5,7 @@ package com.dumbdogdiner.stickyapi.bukkit.item; import com.dumbdogdiner.stickyapi.bukkit.item.generator.BookGenerator; -import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.JsonComponent; +import com.dumbdogdiner.stickyapi.common.book.chat.JsonComponent; import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.JsonComponentWriter; import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.MCColorFormatDelimiterProcessor; import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.MarkdownJsonRenderer; @@ -30,7 +30,7 @@ private static File getRulebookPath() { public static ItemStack generateDefault() throws IOException { try (var reader = new InputStreamReader(new FileInputStream(getRulebookPath()))) { - return generate(reader, "§ddddMCSurvival Handbook", "Stixil"); + return generate(reader, "§ddddMC Survival Handbook", "Stixil"); } } @@ -38,19 +38,22 @@ public static ItemStack generate(Reader reader, String title, String author) thr var cmparser = Parser.builder() .customDelimiterProcessor(new MCColorFormatDelimiterProcessor()) .build(); - var bookRoot = (Document) cmparser.parseReader(reader); var bookGenerator = new BookGenerator(Material.WRITTEN_BOOK); - BookUtil.splitDocumentByHeadings(bookRoot, 2) - .stream().map(document -> { - var component = new JsonComponent(); - var writer = new JsonComponentWriter(component); - new MarkdownJsonRenderer(writer).render(document); - return component; - }).map(BookUtil::splitBookPages).flatMap(List::stream).forEach(page -> { - bookGenerator.addPage(page.toJson()); - }); + var sections = BookUtil.splitDocumentByBreaks((Document) cmparser.parseReader(reader)); + sections.stream() + .map(section -> BookUtil.splitBookPages(renderDocument(section))) + .flatMap(List::stream) + .forEach(page -> bookGenerator.addPage(page.toJson())); bookGenerator.setTitle(title); bookGenerator.setAuthor(author); + return bookGenerator.toItemStack(1); } + + private static JsonComponent renderDocument(Document document) { + var component = new JsonComponent(); + var writer = new JsonComponentWriter(component); + new MarkdownJsonRenderer(writer).render(document); + return component; + } } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java new file mode 100644 index 00000000..68b3d2ba --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java @@ -0,0 +1,151 @@ +/** + * Copyright (c) 2020 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.book.chat; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import lombok.Getter; +import lombok.NonNull; + +public abstract class ClickEvent { + private ClickEvent() { } + + public abstract JsonElement toJson(); + + public abstract ClickEvent duplicate(); + + public final static class OpenUrl extends ClickEvent { + @Getter + private final @NonNull String url; + + public OpenUrl(@NonNull String url) { + this.url = url; + } + + @Override + public JsonElement toJson() { + JsonObject object = new JsonObject(); + object.addProperty("action", "open_url"); + object.addProperty("value", url); + return object; + } + + @Override + public OpenUrl duplicate() { + return new OpenUrl(url); + } + } + + // shouldn't work but included for completeness + public final static class OpenFile extends ClickEvent { + @Getter + private final @NonNull String path; + + public OpenFile(@NonNull String path) { + this.path = path; + } + + @Override + public JsonElement toJson() { + JsonObject object = new JsonObject(); + object.addProperty("action", "open_file"); + object.addProperty("value", path); + return object; + } + + @Override + public OpenFile duplicate() { + return new OpenFile(path); + } + } + + public final static class RunCommand extends ClickEvent { + @Getter + private final @NonNull String command; + + public RunCommand(@NonNull String command) { + this.command = command; + } + + @Override + public JsonElement toJson() { + JsonObject object = new JsonObject(); + object.addProperty("action", "run_command"); + object.addProperty("value", command); + return object; + } + + @Override + public RunCommand duplicate() { + return new RunCommand(command); + } + } + + public final static class SuggestCommand extends ClickEvent { + @Getter + private final @NonNull String command; + + public SuggestCommand(@NonNull String command) { + this.command = command; + } + + @Override + public JsonElement toJson() { + JsonObject object = new JsonObject(); + object.addProperty("action", "suggest_command"); + object.addProperty("value", command); + return object; + } + + @Override + public SuggestCommand duplicate() { + return new SuggestCommand(command); + } + } + + public final static class ChangePage extends ClickEvent { + @Getter + private final int page; + + public ChangePage(int page) { + this.page = page; + } + + @Override + public JsonElement toJson() { + JsonObject object = new JsonObject(); + object.addProperty("action", "change_page"); + object.addProperty("value", page); + return object; + } + + @Override + public ChangePage duplicate() { + return new ChangePage(page); + } + } + + public final static class CopyToClipboard extends ClickEvent { + @Getter + private final @NonNull String text; + + public CopyToClipboard(@NonNull String text) { + this.text = text; + } + + @Override + public JsonElement toJson() { + JsonObject object = new JsonObject(); + object.addProperty("action", "copy_to_clipboard"); + object.addProperty("value", text); + return object; + } + + @Override + public CopyToClipboard duplicate() { + return new CopyToClipboard(text); + } + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java new file mode 100644 index 00000000..ddb7b7d5 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2020 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.book.chat; + +import lombok.Getter; +import lombok.NonNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Pattern; + +public class ComponentColor { + private static final Set VALID_NAMED_COLORS = new HashSet<>(); + + public static final ComponentColor RESET = registerValid("reset"); + public static final ComponentColor BLACK = registerValid("black"); + public static final ComponentColor DARK_BLUE = registerValid("dark_blue"); + public static final ComponentColor DARK_GREEN = registerValid("dark_green"); + public static final ComponentColor DARK_AQUA = registerValid("dark_aqua"); + public static final ComponentColor DARK_RED = registerValid("dark_red"); + public static final ComponentColor DARK_PURPLE = registerValid("dark_purple"); + public static final ComponentColor GOLD = registerValid("gold"); + public static final ComponentColor GRAY = registerValid("gray"); + public static final ComponentColor DARK_GRAY = registerValid("dark_gray"); + public static final ComponentColor BLUE = registerValid("blue"); + public static final ComponentColor GREEN = registerValid("green"); + public static final ComponentColor AQUA = registerValid("aqua"); + public static final ComponentColor RED = registerValid("red"); + public static final ComponentColor LIGHT_PURPLE = registerValid("light_purple"); + public static final ComponentColor YELLOW = registerValid("yellow"); + public static final ComponentColor WHITE = registerValid("white"); + + private static final Pattern HEX_PATTERN = Pattern.compile("^#[0-9A-Fa-f]{6}$"); + + @Getter + private final String text; + + private ComponentColor(String text) { + this.text = text; + } + + private ComponentColor(Color color) { + this.text = String.format("#%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue()); + } + + private static ComponentColor registerValid(String text) { + VALID_NAMED_COLORS.add(text); + return new ComponentColor(text); + } + + public static @Nullable ComponentColor fromText(String text) { + if (HEX_PATTERN.matcher(text).matches()) { + return new ComponentColor(text); + } else if (VALID_NAMED_COLORS.contains(text)) { + return new ComponentColor(text); + } else { + return null; + } + } + + public static @NonNull ComponentColor fromColor(Color color) { + return new ComponentColor(color); + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java new file mode 100644 index 00000000..c6244be5 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2020 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.book.chat; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import lombok.Getter; +import lombok.NonNull; +import net.minecraft.server.v1_16_R3.EntityTypes; +import net.minecraft.server.v1_16_R3.IRegistry; +import net.minecraft.server.v1_16_R3.ItemStack; +import net.minecraft.server.v1_16_R3.NBTTagCompound; + +import java.util.UUID; + +public abstract class HoverEvent { + private HoverEvent() {} + + public abstract JsonElement toJson(); + + public abstract HoverEvent duplicate(); + + public final static class ShowText extends HoverEvent { + @Getter + private final @NonNull JsonComponent component; + + public ShowText(@NonNull JsonComponent component) { + this.component = component; + } + + @Override + public JsonElement toJson() { + JsonObject object = new JsonObject(); + object.addProperty("action", "show_text"); + object.add("contents", component.toJson()); + return object; + } + + @Override + public ShowText duplicate() { + return new ShowText(component); + } + } + + public final static class ShowItem extends HoverEvent { + @Getter + private final @NonNull ItemStack stack; + + public ShowItem(@NonNull ItemStack stack) { + this.stack = stack; + } + + @Override + public JsonElement toJson() { + JsonObject object = new JsonObject(); + object.addProperty("action", "show_item"); + JsonObject contents = new JsonObject(); + contents.addProperty("id", IRegistry.ITEM.getKey(stack.getItem()).toString()); + contents.addProperty("count", stack.getCount()); + NBTTagCompound tag = stack.getTag(); + if (tag != null) { + contents.addProperty("tag", tag.toString()); + } + object.add("contents", contents); + return object; + } + + @Override + public ShowItem duplicate() { + return new ShowItem(stack); + } + } + + public final static class ShowEntity extends HoverEvent { + @Getter + private final JsonComponent name; + @Getter + private final @NonNull EntityTypes entityType; + @Getter + private final @NonNull UUID entityId; + + public ShowEntity(JsonComponent name, @NonNull EntityTypes entityType, @NonNull UUID entityId) { + this.name = name; + this.entityType = entityType; + this.entityId = entityId; + } + + @Override + public JsonElement toJson() { + JsonObject object = new JsonObject(); + object.addProperty("action", "show_entity"); + JsonObject contents = new JsonObject(); + if (name != null) { + contents.add("name", name.toJson()); + } + contents.addProperty("type", IRegistry.ENTITY_TYPE.getKey(entityType).toString()); + contents.addProperty("id", entityId.toString()); + object.add("contents", contents); + return object; + } + + @Override + public ShowEntity duplicate() { + return new ShowEntity(name, entityType, entityId); + } + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponent.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java similarity index 51% rename from src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponent.java rename to src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java index f0283c03..0fdf9d0f 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponent.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java @@ -2,13 +2,14 @@ * Copyright (c) 2020 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ -package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; +package com.dumbdogdiner.stickyapi.common.book.chat; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.Getter; import lombok.NonNull; import lombok.Setter; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -25,17 +26,21 @@ public class JsonComponent { private @NonNull String text = ""; // for now, the attributes are only what are needed for the renderer, might expand later @Getter @Setter - private boolean isBold = false; + private @Nullable Boolean bold = null; @Getter @Setter - private boolean isItalic = false; + private @Nullable Boolean italic = null; @Getter @Setter - private boolean isUnderlined = false; + private @Nullable Boolean underlined = null; @Getter @Setter - private String color = null; + private @Nullable Boolean strikethrough = null; @Getter @Setter - private String url = null; + private @Nullable Boolean obfuscated = null; @Getter @Setter - private String hoverText = null; + private @Nullable ComponentColor color = null; + @Getter @Setter + private @Nullable ClickEvent clickEvent = null; + @Getter @Setter + private @Nullable HoverEvent hoverEvent = null; @Getter private final List children = new ArrayList<>(); @@ -52,23 +57,19 @@ public JsonComponent(@NonNull String text) { public JsonObject toJson() { JsonObject object = new JsonObject(); object.addProperty("text", text); - if (isBold) object.addProperty("bold", true); - if (isItalic) object.addProperty("italic", true); - if (isUnderlined) object.addProperty("underline", true); + if (bold != null) object.addProperty("bold", bold); + if (italic != null) object.addProperty("italic", italic); + if (underlined != null) object.addProperty("underlined", underlined); + if (strikethrough != null) object.addProperty("strikethrough", strikethrough); + if (obfuscated != null) object.addProperty("obfuscated", obfuscated); if (color != null) { - object.addProperty("color", color); + object.addProperty("color", color.getText()); } - if (url != null) { - JsonObject clickEvent = new JsonObject(); - clickEvent.addProperty("action", "open_url"); - clickEvent.addProperty("value", url); - object.add("clickEvent", clickEvent); + if (clickEvent != null) { + object.add("clickEvent", clickEvent.toJson()); } - if (hoverText != null) { - JsonObject hoverEvent = new JsonObject(); - hoverEvent.addProperty("action", "show_text"); - hoverEvent.addProperty("contents", hoverText); - object.add("hoverEvent", hoverEvent); + if (hoverEvent != null) { + object.add("hoverEvent", hoverEvent.toJson()); } if (!children.isEmpty()) { JsonArray extra = new JsonArray(); @@ -92,24 +93,14 @@ private List flattenWithParents(List parents) { List components = new ArrayList<>(); if (!text.equals("")) { JsonComponent flatComponent = new JsonComponent(text); - flatComponent.setBold(isBold || parents.stream().anyMatch(c -> c.isBold)); - flatComponent.setItalic(isItalic || parents.stream().anyMatch(c -> c.isItalic)); - flatComponent.setUnderlined(isUnderlined || parents.stream().anyMatch(c -> c.isUnderlined)); - if (color == null) { - flatComponent.setColor(findFromList(parents, JsonComponent::getColor)); - } else { - flatComponent.setColor(color); - } - if (url == null) { - flatComponent.setUrl(findFromList(parents, JsonComponent::getUrl)); - } else { - flatComponent.setUrl(url); - } - if (hoverText == null) { - flatComponent.setHoverText(findFromList(parents, JsonComponent::getHoverText)); - } else { - flatComponent.setHoverText(hoverText); - } + flatComponent.setBold(orFromList(bold, parents, JsonComponent::getBold)); + flatComponent.setItalic(orFromList(italic, parents, JsonComponent::getItalic)); + flatComponent.setUnderlined(orFromList(underlined, parents, JsonComponent::getUnderlined)); + flatComponent.setStrikethrough(orFromList(strikethrough, parents, JsonComponent::getStrikethrough)); + flatComponent.setObfuscated(orFromList(obfuscated, parents, JsonComponent::getObfuscated)); + flatComponent.setColor(orFromList(color, parents, JsonComponent::getColor)); + flatComponent.setClickEvent(orFromList(clickEvent, parents, JsonComponent::getClickEvent)); + flatComponent.setHoverEvent(orFromList(hoverEvent, parents, JsonComponent::getHoverEvent)); components.add(flatComponent); } List newParents = Stream.concat(Stream.of(this), parents.stream()).collect(Collectors.toList()); @@ -119,21 +110,28 @@ private List flattenWithParents(List parents) { return components; } - private T findFromList(List components, Function getter) { - return components.stream().map(getter).filter(Objects::nonNull).findFirst().orElse(null); + private T orFromList(T t, List components, Function getter) { + if (t == null) { + return components.stream().map(getter).filter(Objects::nonNull).findFirst().orElse(null); + } else { + return t; + } } public JsonComponent duplicate() { JsonComponent clone = new JsonComponent(text); - clone.isBold = isBold; - clone.isItalic = isItalic; - clone.isUnderlined = isUnderlined; + clone.bold = bold; + clone.italic = italic; + clone.underlined = underlined; + clone.strikethrough = strikethrough; + clone.obfuscated = obfuscated; clone.color = color; - clone.url = url; - clone.hoverText = hoverText; + if (clickEvent != null) clone.clickEvent = clickEvent.duplicate(); + if (hoverEvent != null) clone.hoverEvent = hoverEvent.duplicate(); for (JsonComponent child : children) { clone.children.add(child.duplicate()); } return clone; } + } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponentWriter.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponentWriter.java index 9be6ec2a..561b1966 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponentWriter.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponentWriter.java @@ -4,6 +4,11 @@ */ package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; +import com.dumbdogdiner.stickyapi.common.book.chat.ClickEvent; +import com.dumbdogdiner.stickyapi.common.book.chat.ComponentColor; +import com.dumbdogdiner.stickyapi.common.book.chat.HoverEvent; +import com.dumbdogdiner.stickyapi.common.book.chat.JsonComponent; + import java.util.Stack; public class JsonComponentWriter { @@ -56,27 +61,35 @@ public void addLine() { renderNewLine = true; } - public void setBold() { - current.setBold(true); + public void setBold(Boolean bold) { + current.setBold(bold); + } + + public void setItalic(Boolean italic) { + current.setItalic(italic); + } + + public void setUnderlined(Boolean underlined) { + current.setUnderlined(underlined); } - public void setItalic() { - current.setItalic(true); + public void setStrikethrough(Boolean strikethrough) { + current.setStrikethrough(strikethrough); } - public void setUnderlined() { - current.setUnderlined(true); + public void setObfuscated(Boolean obfuscated) { + current.setObfuscated(obfuscated); } - public void setColor(String color) { + public void setColor(ComponentColor color) { current.setColor(color); } - public void setHyperlink(String url) { - current.setUrl(url); + public void setClickEvent(ClickEvent event) { + current.setClickEvent(event); } - public void setMouseoverText(String text) { - current.setHoverText(text); + public void setHoverEvent(HoverEvent event) { + current.setHoverEvent(event); } } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java index 9bab1cc6..27cec3ca 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java @@ -4,6 +4,7 @@ */ package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; +import com.dumbdogdiner.stickyapi.common.book.chat.ComponentColor; import org.commonmark.node.Node; import org.commonmark.node.Text; import org.commonmark.parser.delimiter.DelimiterProcessor; @@ -13,7 +14,7 @@ import java.util.regex.Pattern; public class MCColorFormatDelimiterProcessor implements DelimiterProcessor { - private static final Pattern COLOR_PATTERN = Pattern.compile("^(black|dark_blue|dark_green|dark_aqua|dark_red|dark_purple|gold|gray|dark_gray|blue|green|aqua|red|light_purple|yellow|white|reset|#[0-9A-Fa-f]{6})(\\s*(?:\\s[\\S\\s]+)?)$"); + private static final Pattern COLOR_PATTERN = Pattern.compile("^([a-z_]+|#[0-9A-Fa-f]{6})(\\s*(?:\\s[\\S\\s]+)?)$"); @Override public char getOpeningCharacter() { @@ -45,16 +46,18 @@ public void process(Text opener, Text closer, int delimiterUse) { if (firstNext instanceof Text) { String literal = ((Text) firstNext).getLiteral(); Matcher match = COLOR_PATTERN.matcher(literal); - // only create the color node if a color was specified if (match.matches()) { ((Text) firstNext).setLiteral(match.group(2).stripLeading()); - MCColorNode color = new MCColorNode(match.group(1)); - Node next; - for (Node n = opener.getNext(); n != null && n != closer; n = next) { - next = n.getNext(); - color.appendChild(n); + ComponentColor color = ComponentColor.fromText(match.group(1)); + if (color != null) { + MCColorNode colorNode = new MCColorNode(color); + Node next; + for (Node n = opener.getNext(); n != null && n != closer; n = next) { + next = n.getNext(); + colorNode.appendChild(n); + } + opener.insertAfter(colorNode); } - opener.insertAfter(color); } } } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java index 226c2104..433e46dd 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java @@ -4,14 +4,15 @@ */ package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; +import com.dumbdogdiner.stickyapi.common.book.chat.ComponentColor; import lombok.Getter; import org.commonmark.node.CustomNode; public class MCColorNode extends CustomNode { @Getter - private final String colorName; + private final ComponentColor color; - public MCColorNode(String colorName) { - this.colorName = colorName; + public MCColorNode(ComponentColor color) { + this.color = color; } } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java index 390b4df1..9f1de325 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java @@ -4,6 +4,9 @@ */ package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; +import com.dumbdogdiner.stickyapi.common.book.chat.ClickEvent; +import com.dumbdogdiner.stickyapi.common.book.chat.HoverEvent; +import com.dumbdogdiner.stickyapi.common.book.chat.JsonComponent; import org.commonmark.node.*; import org.commonmark.renderer.NodeRenderer; @@ -46,14 +49,14 @@ public void visit(Text text) { @Override public void visit(Heading heading) { - writer.setBold(); + writer.setBold(true); visitChildren(heading); writer.addLine(); } @Override public void visit(Emphasis node) { - writer.setItalic(); + writer.setItalic(true); visitChildren(node); } @@ -61,10 +64,10 @@ public void visit(Emphasis node) { public void visit(StrongEmphasis node) { switch (node.getOpeningDelimiter()) { case "**": - writer.setBold(); + writer.setBold(true); break; case "__": - writer.setUnderlined(); + writer.setUnderlined(true); break; } visitChildren(node); @@ -72,8 +75,8 @@ public void visit(StrongEmphasis node) { @Override public void visit(Link link) { - writer.setHyperlink(link.getDestination()); - writer.setMouseoverText(link.getTitle()); + writer.setClickEvent(new ClickEvent.OpenUrl(link.getDestination())); + writer.setHoverEvent(new HoverEvent.ShowText(new JsonComponent(link.getTitle()))); visitChildren(link); } @@ -132,7 +135,7 @@ public void visit(CustomNode node) { } public void visit(MCColorNode color) { - writer.setColor(color.getColorName()); + writer.setColor(color.getColor()); visitChildren(color); } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index 48b7d5ca..0efa5db6 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -10,11 +10,12 @@ import java.util.regex.Pattern; -import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.JsonComponent; +import com.dumbdogdiner.stickyapi.common.book.chat.JsonComponent; import lombok.NonNull; import org.commonmark.node.Document; import org.commonmark.node.Heading; import org.commonmark.node.Node; +import org.commonmark.node.ThematicBreak; import org.jetbrains.annotations.NotNull; public class BookUtil { @@ -128,7 +129,7 @@ public static List wrapLines(@NonNull JsonComponent origComponent JsonComponent wordComponent = component.duplicate(); wordComponent.setText(word); int width = getStringWidth(word) + 1; - if (component.isBold()) width += word.length() + 1; + if (component.getBold() == Boolean.TRUE) width += word.length() + 1; if (xPosition + width >= pixels) { lineComponents.add(currentLine); currentLine = new JsonComponent(); @@ -168,6 +169,28 @@ public static List splitDocumentByHeadings(@NonNull Document document, return docs; } + /** + * Split a document into multiple documents, delimited by thematic breaks. Destroys the original document. + * @param document The original document + * @return A list of each document. + */ + public static List splitDocumentByBreaks(@NonNull Document document) { + List docs = new ArrayList<>(); + Document currentDocument = new Document(); + Node next; + for (Node n = document.getFirstChild(); n != null; n = next) { + next = n.getNext(); + if (n instanceof ThematicBreak) { + docs.add(currentDocument); + currentDocument = new Document(); + } else { + currentDocument.appendChild(n); + } + } + docs.add(currentDocument); + return docs; + } + /** * Measure the width of text in a BaseComponent in pixels. * @param component The component to measure @@ -176,7 +199,7 @@ public static List splitDocumentByHeadings(@NonNull Document document, public static int getComponentWidth(@NotNull JsonComponent component) { String text = component.getText(); int width = getStringWidth(text); - if (component.isBold()) width += text.length(); + if (component.getBold() == Boolean.TRUE) width += text.length(); for (JsonComponent child : component.getChildren()) { width += getComponentWidth(child); } From c4b4f559f3a38f82a3b5e5cedfac099bbe08fb87 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Tue, 8 Dec 2020 15:02:38 -0500 Subject: [PATCH 18/79] Add comment --- .../java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java index 1569b9ea..cf1c7707 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java @@ -50,6 +50,7 @@ public static ItemStack generate(Reader reader, String title, String author) thr return bookGenerator.toItemStack(1); } + //TODO: make a class that extends the renderer or NodeRenderer thingy private static JsonComponent renderDocument(Document document) { var component = new JsonComponent(); var writer = new JsonComponentWriter(component); From 894944e503d2bb66c9341a12677b2ec6e445b4f8 Mon Sep 17 00:00:00 2001 From: Matt <25674682+spazzylemons@users.noreply.github.com> Date: Wed, 9 Dec 2020 13:15:07 -0500 Subject: [PATCH 19/79] Remove NMS and CraftBukkit --- build.gradle | 2 +- .../stickyapi/bukkit/item/RuleBook.java | 5 +- .../bukkit/item/generator/BookGenerator.java | 58 +++++-------------- .../common/book/chat/HoverEvent.java | 44 ++++++++------ 4 files changed, 41 insertions(+), 68 deletions(-) diff --git a/build.gradle b/build.gradle index 1eb48137..4e941c62 100644 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,7 @@ dependencies { annotationProcessor 'org.projectlombok:lombok:1.18.16' implementation 'com.atlassian.commonmark:commonmark:0.15.2' - compileOnly 'com.dumbdogdiner.buildtools:paper:1.16.4-318-SNAPSHOT' + compileOnly 'com.destroystokyo.paper:paper-api:1.16.4-R0.1-SNAPSHOT' compileOnly 'io.github.waterfallmc:waterfall-api:1.16-R0.4-SNAPSHOT' implementation 'org.jetbrains:annotations:20.1.0' diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java index cf1c7707..c0cd0271 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java @@ -44,10 +44,7 @@ public static ItemStack generate(Reader reader, String title, String author) thr .map(section -> BookUtil.splitBookPages(renderDocument(section))) .flatMap(List::stream) .forEach(page -> bookGenerator.addPage(page.toJson())); - bookGenerator.setTitle(title); - bookGenerator.setAuthor(author); - - return bookGenerator.toItemStack(1); + return bookGenerator.setTitle(title).setAuthor(author).toItemStack(1); } //TODO: make a class that extends the renderer or NodeRenderer thingy diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java index dd53e768..37a237d7 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java @@ -4,48 +4,26 @@ */ package com.dumbdogdiner.stickyapi.bukkit.item.generator; -import com.dumbdogdiner.stickyapi.StickyAPI; -import com.dumbdogdiner.stickyapi.common.ServerVersion; import com.dumbdogdiner.stickyapi.common.util.BookUtil; -import com.google.gson.Gson; +import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; -import net.md_5.bungee.api.chat.TextComponent; -import net.minecraft.server.v1_16_R3.NBTTagCompound; -import net.minecraft.server.v1_16_R3.NBTTagList; -import net.minecraft.server.v1_16_R3.NBTTagString; +import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BookMeta; @SuppressWarnings({"UnusedReturnValue", "unused"}) @Accessors(chain = true) public class BookGenerator { - public enum Generation { - ORIGINAL(0), - COPY_OF_ORIGINAL(1), - COPY_OF_COPY(2), - TATTERED(3); - - private Generation(int g) { - genInt = g; - } - - private final int genInt; - - public int asInt() { - return genInt; - } - } - - private NBTTagList pages = new NBTTagList(); + private final JsonArray pages = new JsonArray(); @Setter @Getter - private Generation generation = Generation.ORIGINAL; + private BookMeta.Generation generation = BookMeta.Generation.ORIGINAL; @Getter Material bookType; @@ -98,15 +76,7 @@ public BookGenerator addPages(JsonObject... pages) { public BookGenerator addPage(JsonObject page) { if(!isFull()){ - String jsonString = page.toString(); - NBTTagString tag; - // .create just calls .a, so both branches are identical except .create is added by Paper - if (ServerVersion.isPaper()) { - tag = NBTTagString.create(jsonString); - } else { - tag = NBTTagString.a(jsonString); - } - pages.add(tag); + pages.add(page.toString()); } else { throw new IllegalStateException("Book is overfilled"); } @@ -116,17 +86,17 @@ public BookGenerator addPage(JsonObject page) { public ItemStack toItemStack(int qty) { - NBTTagCompound root = new NBTTagCompound(); + ItemStack stack = Bukkit.getUnsafe().modifyItemStack(new ItemStack(bookType), "{pages: " + pages.toString() + "}"); + if (bookType == Material.WRITTEN_BOOK) { - root.setString("title", title); - root.setString("author", author); - root.setInt("generation", generation.asInt()); + BookMeta meta = (BookMeta) stack.getItemMeta(); + meta.setTitle(title); + meta.setAuthor(author); + meta.setGeneration(generation); + stack.setItemMeta(meta); } - root.set("pages", pages); - net.minecraft.server.v1_16_R3.ItemStack nmsBook = CraftItemStack.asNMSCopy(new ItemStack(bookType, qty)); - nmsBook.setTag(root); - return CraftItemStack.asBukkitCopy(nmsBook); + return stack; } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java index c6244be5..4ea1f4af 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java @@ -8,10 +8,7 @@ import com.google.gson.JsonObject; import lombok.Getter; import lombok.NonNull; -import net.minecraft.server.v1_16_R3.EntityTypes; -import net.minecraft.server.v1_16_R3.IRegistry; -import net.minecraft.server.v1_16_R3.ItemStack; -import net.minecraft.server.v1_16_R3.NBTTagCompound; +import org.jetbrains.annotations.Nullable; import java.util.UUID; @@ -46,10 +43,16 @@ public ShowText duplicate() { public final static class ShowItem extends HoverEvent { @Getter - private final @NonNull ItemStack stack; + private final @NonNull String itemId; + @Getter + private final @Nullable Integer count; + @Getter + private final @Nullable String nbt; - public ShowItem(@NonNull ItemStack stack) { - this.stack = stack; + public ShowItem(@NonNull String itemId, @Nullable Integer count, @Nullable String nbt) { + this.itemId = itemId; + this.count = count; + this.nbt = nbt; } @Override @@ -57,11 +60,14 @@ public JsonElement toJson() { JsonObject object = new JsonObject(); object.addProperty("action", "show_item"); JsonObject contents = new JsonObject(); - contents.addProperty("id", IRegistry.ITEM.getKey(stack.getItem()).toString()); - contents.addProperty("count", stack.getCount()); - NBTTagCompound tag = stack.getTag(); - if (tag != null) { - contents.addProperty("tag", tag.toString()); + if (itemId != null) { + contents.addProperty("id", itemId); + } + if (count != null) { + contents.addProperty("count", count); + } + if (nbt != null) { + contents.addProperty("tag", nbt); } object.add("contents", contents); return object; @@ -69,21 +75,21 @@ public JsonElement toJson() { @Override public ShowItem duplicate() { - return new ShowItem(stack); + return new ShowItem(itemId, count, nbt); } } public final static class ShowEntity extends HoverEvent { @Getter - private final JsonComponent name; + private final @Nullable JsonComponent name; @Getter - private final @NonNull EntityTypes entityType; + private final @NonNull String entityKey; @Getter private final @NonNull UUID entityId; - public ShowEntity(JsonComponent name, @NonNull EntityTypes entityType, @NonNull UUID entityId) { + public ShowEntity(@Nullable JsonComponent name, @NonNull String entityKey, @NonNull UUID entityId) { this.name = name; - this.entityType = entityType; + this.entityKey = entityKey; this.entityId = entityId; } @@ -95,7 +101,7 @@ public JsonElement toJson() { if (name != null) { contents.add("name", name.toJson()); } - contents.addProperty("type", IRegistry.ENTITY_TYPE.getKey(entityType).toString()); + contents.addProperty("type", entityKey); contents.addProperty("id", entityId.toString()); object.add("contents", contents); return object; @@ -103,7 +109,7 @@ public JsonElement toJson() { @Override public ShowEntity duplicate() { - return new ShowEntity(name, entityType, entityId); + return new ShowEntity(name, entityKey, entityId); } } } From 6edb87a10af9596b3127afc524b1cfa0424f602a Mon Sep 17 00:00:00 2001 From: Matt <25674682+spazzylemons@users.noreply.github.com> Date: Wed, 9 Dec 2020 17:18:32 -0500 Subject: [PATCH 20/79] Add Javadocs to book stuff --- .../stickyapi/bukkit/item/RuleBook.java | 8 +- .../bukkit/item/generator/BookGenerator.java | 70 +++++++--------- .../common/book/chat/ClickEvent.java | 52 ++++++++++-- .../common/book/chat/ComponentColor.java | 32 ++++++-- .../common/book/chat/HoverEvent.java | 82 +++++++++++++------ .../common/book/chat/JsonComponent.java | 5 +- .../JsonComponentWriter.java | 48 +++++++++++ .../MCColorFormatDelimiterProcessor.java | 3 + .../commonmarkextensions/MCColorNode.java | 3 + .../MCFormatExtension.java | 2 +- .../MarkdownJsonRenderer.java | 3 + .../stickyapi/common/util/BookUtil.java | 38 +++------ 12 files changed, 230 insertions(+), 116 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java index c0cd0271..58957c6a 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java @@ -8,6 +8,7 @@ import com.dumbdogdiner.stickyapi.common.book.chat.JsonComponent; import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.JsonComponentWriter; import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.MCColorFormatDelimiterProcessor; +import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.MCFormatExtension; import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.MarkdownJsonRenderer; import com.dumbdogdiner.stickyapi.common.util.BookUtil; import org.bukkit.Bukkit; @@ -35,9 +36,9 @@ public static ItemStack generateDefault() throws IOException { } public static ItemStack generate(Reader reader, String title, String author) throws IOException { - var cmparser = Parser.builder() - .customDelimiterProcessor(new MCColorFormatDelimiterProcessor()) - .build(); + var builder = Parser.builder(); + MCFormatExtension.create().extend(builder); + var cmparser = builder.build(); var bookGenerator = new BookGenerator(Material.WRITTEN_BOOK); var sections = BookUtil.splitDocumentByBreaks((Document) cmparser.parseReader(reader)); sections.stream() @@ -47,7 +48,6 @@ public static ItemStack generate(Reader reader, String title, String author) thr return bookGenerator.setTitle(title).setAuthor(author).toItemStack(1); } - //TODO: make a class that extends the renderer or NodeRenderer thingy private static JsonComponent renderDocument(Document document) { var component = new JsonComponent(); var writer = new JsonComponentWriter(component); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java index 37a237d7..50d553ce 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java @@ -8,43 +8,30 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.Getter; +import lombok.NonNull; import lombok.Setter; import lombok.experimental.Accessors; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta; +import org.jetbrains.annotations.Nullable; @SuppressWarnings({"UnusedReturnValue", "unused"}) @Accessors(chain = true) public class BookGenerator { private final JsonArray pages = new JsonArray(); - - - @Setter - @Getter - private BookMeta.Generation generation = BookMeta.Generation.ORIGINAL; - - @Getter - Material bookType; - - @Getter - @Setter - private String author; - - /** - * Title of the book - * -- SETTER -- - * Sets the name of the book, this may have ChatColors - * - * @param title The new value. - * -- GETTER -- - * Returns the book title - * @return String The book's title - */ - @SuppressWarnings("JavaDoc") - @Setter + /** The generation of the book. */ + @Getter @Setter + private @NonNull BookMeta.Generation generation = BookMeta.Generation.ORIGINAL; + /** The material of the book. */ @Getter + private final Material bookType; + /** The author of the book. Must not be null if the book is written. */ + @Getter @Setter + private @Nullable String author; + /** The title of the book, can be formatted using color codes. */ + @Getter @Setter private String title; public BookGenerator(Material material) { @@ -53,20 +40,13 @@ public BookGenerator(Material material) { } this.bookType = material; - - } - /* -/give @p written_book{pages:['["",{"text":"Dumb Dog Diner MC\\nSurvival Handbook","bold":true,"italic":true,"color":"dark_purple"},{"text":"\\n\\n","color":"reset"},{"text":"Table of Contents:","bold":true,"italic":true,"underlined":true,"color":"dark_red"},{"text":"\\n","color":"reset"},{"text":"Page 2: ","color":"red"},{"text":"Rules\\n","color":"reset"},{"text":"Pg. 3: ","color":"red"},{"text":"Gameplay\\n","color":"reset"},{"text":"Pg. 5: ","color":"red"},{"text":"Trading\\n","color":"reset"},{"text":"Pg. 7: ","color":"red"},{"text":"Commands\\n","color":"reset"},{"text":"Pg. 9: ","color":"red"},{"text":"Trading\\nCommands\\n","color":"reset"},{"text":"Pg. 11: ","color":"red"},{"text":"Misc Commands\\n","color":"reset"},{"text":"Pg. 12: ","color":"red"},{"text":"Getting Help\\n","color":"reset"},{"text":"Pg. 14: ","color":"red"},{"text":"Credits","color":"reset"}]','["",{"text":"The Rules:","bold":true,"italic":true,"underlined":true,"color":"red"},{"text":"\\n1. Absolutely no\\ngriefing, theft, or\\nintentional distress!\\n2. No cheating/hacking\\nallowed. Optifine and\\nsimilar are okay.\\n3. No floating trees.\\n4. No fully-automatic\\nredstone farms.\\n5. No harassment,\\nbullying, or abuse.\\n6. No AFK fishing.","color":"reset"}]','["",{"text":"Gameplay:","bold":true,"italic":true,"underlined":true,"color":"dark_green"},{"text":"\\nThe world border for all worlds is 8,000\\nblocks from the\\ncenter. Because of\\nnow ","color":"reset"},{"text":"Nether Portal","color":"dark_red"},{"text":"\\ntravel works, you will\\nnot be able to light\\nthem past 1,000 blocks\\nfrom the center.\\nYou may build wherever you like! Try ","color":"reset"},{"text":"/rtp","color":"blue"},{"text":" to help find a spot!","color":"reset"}]','["",{"text":"This server uses a "},{"text":"Death Chest ","color":"red"},{"text":"system. Upon death, a campfire with your items will spawn at your death location. It will last\\nfor 10 minutes before\\nyour items drop on \\nthe ground!\\n\\nYou can have up to 3\\n","color":"reset"},{"text":"Death Chests","color":"red"},{"text":" at a time.","color":"reset"}]','["",{"text":"Trading:","bold":true,"italic":true,"underlined":true,"color":"dark_aqua"},{"text":"\\nWe use chest chops\\nfor player to trade\\ngood for ","color":"reset"},{"text":"Coins","color":"gold"},{"text":".\\n\\nCoins may be earned through selling goods\\nto other players,\\npaying/receiving\\nmoney for a service,\\nor by selling goods to\\nthe server itself.","color":"reset"}]','{"text":"Chest shops can buy\\nor sell items!\\n\\nTo make a shop, place a chest and\\nshift-click with the\\nitem you want to sell\\nor buy.\\n\\nRegular users may have up to 6 shops\\nat a time."}','["",{"text":"Commands:","bold":true,"italic":true,"underlined":true,"color":"red"},{"text":"\\nTab-complete is set\\nup to only show commands you have access to. Here are some useful ones:\\n\\n","color":"reset"},{"text":"/help ","color":"blue"},{"text":"- Opens the\\nhelp menu\\n","color":"reset"},{"text":"/servers ","color":"blue"},{"text":"- Opens the\\nserver menu\\n","color":"reset"},{"text":"/rules","color":"blue"},{"text":" - Grants this\\nbook","color":"reset"}]','["",{"text":"/options ","color":"blue"},{"text":"- Opens the player options menu\\n","color":"reset"},{"text":"/tpa ","color":"blue"},{"text":"- Sends a\\nteleport request to another player\\n","color":"reset"},{"text":"/rtp ","color":"blue"},{"text":"- Start a\\nrandom teleport\\n","color":"reset"},{"text":"/pw ","color":"blue"},{"text":"- Opens the playerwarps personal\\nhome menu\\n","color":"reset"},{"text":"/helpme ","color":"blue"},{"text":"- Pings an online staff member\\nfor assistance","color":"reset"}]','["",{"text":"Trading Commands:","bold":true,"italic":true,"underlined":true,"color":"dark_purple"},{"text":"\\n","color":"reset"},{"text":"/bal ","color":"blue"},{"text":"- Check your\\nbalance\\n","color":"reset"},{"text":"/pay ","color":"blue"},{"text":"- Pay another player\\n","color":"reset"},{"text":"/sell ","color":"blue"},{"text":"- Sell the item in your hand to the server\\n","color":"reset"},{"text":"/worth ","color":"blue"},{"text":"- Shows the\\nitem price when selling\\nto the server","color":"reset"}]','["",{"text":"/value","color":"blue"},{"text":" - Shows the\\naverage selling price\\nfor an item in\\nplayer shops","color":"reset"}]','["",{"text":"Extra Commands:","bold":true,"italic":true,"underlined":true,"color":"dark_aqua"},{"text":"\\n","color":"reset"},{"text":"/donate, /vip ","color":"blue"},{"text":"- Gives link to the server Patreon page\\n","color":"reset"},{"text":"/discord ","color":"blue"},{"text":"- Gives link to the server Discord\\n","color":"reset"},{"text":"/twitter, /twitch ","color":"blue"},{"text":"- Gives social media links\\n","color":"reset"},{"text":"/merch ","color":"blue"},{"text":"- Gives merch link\\n","color":"reset"},{"text":"/afk ","color":"blue"},{"text":"- Set your status to AFK","color":"reset"}]','["",{"text":"Getting Help:","bold":true,"italic":true,"underlined":true,"color":"light_purple"},{"text":"\\nIf you ever need help\\ngetting your way\\naround the server,\\nplease ask any staff!\\n","color":"reset"},{"text":"/helpme","color":"blue"},{"text":"\\n\\nPlease join the\\nDiscord server to get\\ntechnical help!\\n","color":"reset"},{"text":"/discord","color":"blue"}]','["",{"text":"Please report any\\nbugs, griefing, etc.\\nthat you come across\\nor are a victim of. A\\nstaff member will be\\nhappy to assist you.\\n\\nThe help menu has shortcuts that make getting help easy!\\n"},{"text":"/help","color":"blue"}]','["",{"text":"Credits:","bold":true,"italic":true,"underlined":true,"color":"gold"},{"text":"\\n","color":"reset"},{"text":"dddMC ","bold":true,"color":"dark_purple"},{"text":"is fully funded\\nthrough player donations. Please consider helping support us on Patreon!\\n","color":"reset"},{"text":"/donate /patreon","color":"blue"},{"text":"\\n\\nPatrons will receive a\\nVIP rank. More ranks\\nwill be added in the\\nfuture.","color":"reset"}]','["",{"text":"We hope you enjoy\\nyour time playing\\non the server!\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n- Stixil, "},{"text":"dddMC 2020","bold":true,"color":"dark_purple"}]'],title:"&ddddMC Survival Handbook",author:Stixil} - - */ /** - * Escape characters for colors, etc... - * I guess we can just.... use the &-* codes or something, we can use chatcolors somehow - * Beyond that, we can use markdown??? + * Add some pages to the book. May fail with {@link IllegalStateException} if the book is full or fills up. + * @param pages Pages to add + * @return This object, for chaining */ - public BookGenerator addPages(JsonObject... pages) { for (JsonObject page : pages) { addPage(page); @@ -74,6 +54,11 @@ public BookGenerator addPages(JsonObject... pages) { return this; } + /** + * Add a page to the book. May fail with {@link IllegalStateException} if the book is full. + * @param page The page to add + * @return This object, for chaining + */ public BookGenerator addPage(JsonObject page) { if(!isFull()){ pages.add(page.toString()); @@ -83,8 +68,11 @@ public BookGenerator addPage(JsonObject page) { return this; } - - + /** + * Build a book from this generator. + * @param qty Quantity of the item stack. + * @return {@link ItemStack} + */ public ItemStack toItemStack(int qty) { ItemStack stack = Bukkit.getUnsafe().modifyItemStack(new ItemStack(bookType), "{pages: " + pages.toString() + "}"); @@ -99,12 +87,16 @@ public ItemStack toItemStack(int qty) { return stack; } - + /** + * @return The percentage of pages allowed that are used by this book. + */ public float percentFull() { return (float)pages.size() / (float)BookUtil.PAGES_PER_BOOK; } - + /** + * @return True if the book is full. + */ public boolean isFull() { return percentFull() >= 1.0f; } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java index 68b3d2ba..688b60fd 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java @@ -9,14 +9,29 @@ import lombok.Getter; import lombok.NonNull; +/** + * An event that is fired when text associated with this event is clicked. + */ public abstract class ClickEvent { - private ClickEvent() { } - - public abstract JsonElement toJson(); - - public abstract ClickEvent duplicate(); - + private ClickEvent() {} // seal this class + + /** + * Convert the ClickEvent into JSON representation used in-game. + * @return {@link JsonElement} + */ + public abstract @NonNull JsonElement toJson(); + + /** + * Create a copy of this ClickEvent. + * @return {@link ClickEvent} + */ + public abstract @NonNull ClickEvent duplicate(); + + /** + * When clicked, displays a prompt to open a URL in the player's browser. + */ public final static class OpenUrl extends ClickEvent { + /** The URL to open. */ @Getter private final @NonNull String url; @@ -38,8 +53,12 @@ public OpenUrl duplicate() { } } - // shouldn't work but included for completeness + /** + * When clicked, opens a file on the player's computer. This event can only be used by messages generated by the + * game, and will not function otherwise. + */ public final static class OpenFile extends ClickEvent { + /** The path to open. */ @Getter private final @NonNull String path; @@ -61,7 +80,13 @@ public OpenFile duplicate() { } } + /** + * When clicked, executes the command as if the player said it in chat, either sending a message or executing a + * command. This can also be used to execute commands on signs, but only on the root component, with the slash + * omitted, and run by the server with @s set to the player. + */ public final static class RunCommand extends ClickEvent { + /** The command or message to run. */ @Getter private final @NonNull String command; @@ -83,7 +108,12 @@ public RunCommand duplicate() { } } + /** + * Behaves similarly to {@link RunCommand}, but does not actually execute the command, instead opening the chat box + * and pasting the command there. + */ public final static class SuggestCommand extends ClickEvent { + /** The command to suggest. */ @Getter private final @NonNull String command; @@ -105,7 +135,11 @@ public SuggestCommand duplicate() { } } + /** + * When clicked, jumps to a given page. Obviously only works in books. + */ public final static class ChangePage extends ClickEvent { + /** The page to go to. */ @Getter private final int page; @@ -127,7 +161,11 @@ public ChangePage duplicate() { } } + /** + * When clicked, text is copied to the clipboard. + */ public final static class CopyToClipboard extends ClickEvent { + /** The text to copy. */ @Getter private final @NonNull String text; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java index ddb7b7d5..ec16b145 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java @@ -9,12 +9,16 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; +import java.util.HashMap; import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; +/** + * A color used in text components. + */ public class ComponentColor { - private static final Set VALID_NAMED_COLORS = new HashSet<>(); + private static final HashMap VALID_NAMED_COLORS = new HashMap<>(); public static final ComponentColor RESET = registerValid("reset"); public static final ComponentColor BLACK = registerValid("black"); @@ -36,8 +40,9 @@ public class ComponentColor { private static final Pattern HEX_PATTERN = Pattern.compile("^#[0-9A-Fa-f]{6}$"); + /** The text representation used for the color. */ @Getter - private final String text; + private final @NonNull String text; private ComponentColor(String text) { this.text = text; @@ -48,21 +53,30 @@ private ComponentColor(Color color) { } private static ComponentColor registerValid(String text) { - VALID_NAMED_COLORS.add(text); - return new ComponentColor(text); + ComponentColor x = new ComponentColor(text); + VALID_NAMED_COLORS.put(text, x); + return x; } - public static @Nullable ComponentColor fromText(String text) { + /** + * Get or create a color from the given string, or null if the string is not valid. + * @param text The text for the color. Can be a 6-digit hex color, one of the sixteen named colors, or "reset". + * @return {@link ComponentColor} + */ + public static @Nullable ComponentColor fromText(@NonNull String text) { if (HEX_PATTERN.matcher(text).matches()) { return new ComponentColor(text); - } else if (VALID_NAMED_COLORS.contains(text)) { - return new ComponentColor(text); } else { - return null; + return VALID_NAMED_COLORS.get(text); } } - public static @NonNull ComponentColor fromColor(Color color) { + /** + * Create a color from the given Color object. + * @param color The color object to generate the color from. + * @return {@link ComponentColor} + */ + public static @NonNull ComponentColor fromColor(@NonNull Color color) { return new ComponentColor(color); } } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java index 4ea1f4af..f59cb286 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java @@ -8,18 +8,40 @@ import com.google.gson.JsonObject; import lombok.Getter; import lombok.NonNull; +import org.bukkit.Bukkit; +import org.bukkit.entity.EntityType; +import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Nullable; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.UUID; +/** + * An event that is fired when text associated with this event is hovered over. + */ public abstract class HoverEvent { - private HoverEvent() {} - - public abstract JsonElement toJson(); - - public abstract HoverEvent duplicate(); - + private HoverEvent() {} // seal this class + + /** + * Convert the HoverEvent into JSON representation used in-game. + * @return {@link JsonElement} + */ + public abstract @NonNull JsonElement toJson(); + + /** + * Create a copy of this HoverEvent. + * @return {@link HoverEvent} + */ + public abstract @NonNull HoverEvent duplicate(); + + /** + * When hovered over, show some text. + */ public final static class ShowText extends HoverEvent { + /** The text to show when the associated component is hovered over. */ @Getter private final @NonNull JsonComponent component; @@ -41,18 +63,20 @@ public ShowText duplicate() { } } + /** + * When hovered over, show the tooltip of an item. + */ public final static class ShowItem extends HoverEvent { + /** The item to reference for the tooltip. */ @Getter - private final @NonNull String itemId; - @Getter - private final @Nullable Integer count; + private final @NonNull ItemStack item; + /** Extra NBT to apply to this item stack. */ @Getter - private final @Nullable String nbt; + private final @Nullable String extraNBT; // might be possible to get this from the item but would need lots of nms - public ShowItem(@NonNull String itemId, @Nullable Integer count, @Nullable String nbt) { - this.itemId = itemId; - this.count = count; - this.nbt = nbt; + public ShowItem(@NonNull ItemStack item, @Nullable String extraNBT) { + this.item = item; + this.extraNBT = extraNBT; } @Override @@ -60,14 +84,12 @@ public JsonElement toJson() { JsonObject object = new JsonObject(); object.addProperty("action", "show_item"); JsonObject contents = new JsonObject(); - if (itemId != null) { - contents.addProperty("id", itemId); - } - if (count != null) { - contents.addProperty("count", count); + contents.addProperty("id", item.getType().getKey().toString()); + if (item.getAmount() != 1) { + contents.addProperty("count", item.getAmount()); } - if (nbt != null) { - contents.addProperty("tag", nbt); + if (extraNBT != null) { + contents.addProperty("tag", extraNBT); } object.add("contents", contents); return object; @@ -75,21 +97,27 @@ public JsonElement toJson() { @Override public ShowItem duplicate() { - return new ShowItem(itemId, count, nbt); + return new ShowItem(item, extraNBT); } } + /** + * When hovered over, show data about an entity. + */ public final static class ShowEntity extends HoverEvent { + /** Text to display as the name of the entity. */ @Getter private final @Nullable JsonComponent name; + /** The type of the entity. */ @Getter - private final @NonNull String entityKey; + private final @NonNull EntityType entityType; + /** The ID of the entity. */ @Getter private final @NonNull UUID entityId; - public ShowEntity(@Nullable JsonComponent name, @NonNull String entityKey, @NonNull UUID entityId) { + public ShowEntity(@Nullable JsonComponent name, @NonNull EntityType entityType, @NonNull UUID entityId) { this.name = name; - this.entityKey = entityKey; + this.entityType = entityType; this.entityId = entityId; } @@ -101,7 +129,7 @@ public JsonElement toJson() { if (name != null) { contents.add("name", name.toJson()); } - contents.addProperty("type", entityKey); + contents.addProperty("type", entityType.getKey().toString()); contents.addProperty("id", entityId.toString()); object.add("contents", contents); return object; @@ -109,7 +137,7 @@ public JsonElement toJson() { @Override public ShowEntity duplicate() { - return new ShowEntity(name, entityKey, entityId); + return new ShowEntity(name, entityType, entityId); } } } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java index 0fdf9d0f..a3ccea99 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java @@ -24,7 +24,6 @@ public class JsonComponent { @Getter @Setter private @NonNull String text = ""; - // for now, the attributes are only what are needed for the renderer, might expand later @Getter @Setter private @Nullable Boolean bold = null; @Getter @Setter @@ -118,6 +117,10 @@ private T orFromList(T t, List components, Function levels = new Stack<>(); private JsonComponent current; private boolean renderNewLine = false; private boolean renderIndent = true; + @Getter private int indent = 0; public JsonComponentWriter(JsonComponent component) { this.current = component; } + /** + * Enter a deeper level in the tree. + */ public void enterLevel() { levels.push(current); current = new JsonComponent(); } + /** + * Exit the current level. + */ public void exitLevel() { JsonComponent top = levels.pop(); top.getChildren().add(current); current = top; } + /** + * Increase the indentation of the next line. + */ public void indent() { ++indent; } + /** + * Decrease the indentation of the next line. + */ public void dedent() { indent = Math.max(indent - 1, 0); } + /** + * Add some text to the JsonComponent tree. + * @param text The text to add + */ public void addText(String text) { if (text.isEmpty()) return; enterLevel(); @@ -57,38 +78,65 @@ public void addText(String text) { exitLevel(); } + /** + * Add a line break. + */ public void addLine() { renderNewLine = true; } + /** + * Set if the text in the current level of the tree is bold. + */ public void setBold(Boolean bold) { current.setBold(bold); } + /** + * Set if the text in the current level of the tree is italic. + */ public void setItalic(Boolean italic) { current.setItalic(italic); } + /** + * Set if the text in the current level of the tree is underlined. + */ public void setUnderlined(Boolean underlined) { current.setUnderlined(underlined); } + /** + * Set if the text in the current level of the tree is strikethrough. + */ public void setStrikethrough(Boolean strikethrough) { current.setStrikethrough(strikethrough); } + /** + * Set if the text in the current level of the tree is obfuscated. + */ public void setObfuscated(Boolean obfuscated) { current.setObfuscated(obfuscated); } + /** + * Set the color of the text in the current level of the tree. + */ public void setColor(ComponentColor color) { current.setColor(color); } + /** + * Set the {@link ClickEvent} in the current level of the tree. + */ public void setClickEvent(ClickEvent event) { current.setClickEvent(event); } + /** + * Set the {@link HoverEvent} in the current level of the tree. + */ public void setHoverEvent(HoverEvent event) { current.setHoverEvent(event); } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java index 27cec3ca..99db423f 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java @@ -13,6 +13,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +/** + * A delimiter processor for custom name nbt. + */ public class MCColorFormatDelimiterProcessor implements DelimiterProcessor { private static final Pattern COLOR_PATTERN = Pattern.compile("^([a-z_]+|#[0-9A-Fa-f]{6})(\\s*(?:\\s[\\S\\s]+)?)$"); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java index 433e46dd..8e1f9eb5 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java @@ -8,6 +8,9 @@ import lombok.Getter; import org.commonmark.node.CustomNode; +/** + * A custom node that represents a {@link ComponentColor}. + */ public class MCColorNode extends CustomNode { @Getter private final ComponentColor color; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java index efb49bba..0791dee0 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java @@ -10,7 +10,7 @@ public class MCFormatExtension implements Parser.ParserExtension { private MCFormatExtension(){} - public static Extension create(){ + public static MCFormatExtension create() { return new MCFormatExtension(); } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java index 9f1de325..3909c969 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java @@ -12,6 +12,9 @@ import java.util.*; +/** + * An implementation of {@link NodeRenderer} that writes to a {@link JsonComponent} + */ public class MarkdownJsonRenderer extends AbstractVisitor implements NodeRenderer { private static final Set> nodeTypes = new HashSet<>(Arrays.asList( Text.class, diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index 0efa5db6..1a63af9f 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -9,15 +9,15 @@ import java.util.List; import java.util.regex.Pattern; - import com.dumbdogdiner.stickyapi.common.book.chat.JsonComponent; import lombok.NonNull; import org.commonmark.node.Document; -import org.commonmark.node.Heading; import org.commonmark.node.Node; import org.commonmark.node.ThematicBreak; -import org.jetbrains.annotations.NotNull; +/** + * Utilities for text and books. + */ public class BookUtil { public static final int PIXELS_PER_LINE = 113; public static final int LINES_PER_PAGE = 14; @@ -60,7 +60,11 @@ public class BookUtil { characterWidths.put('~', 6); } - // Uses info from: https://minecraft.gamepedia.com/Language#Font + /** + * Uses info from https://minecraft.gamepedia.com/Language#Font" + * @param c The character to measure + * @return The width of the character in pixels + */ public static int getCharacterWidth(char c) { if (c < 32 || c > 126) { // Not presently implemented, would require rendering TTF @@ -147,28 +151,6 @@ public static List wrapLines(@NonNull JsonComponent origComponent return lineComponents; } - /** - * Split a document into multiple documents, delimited by headings. Destroys the original document. - * @param document The original document - * @param maxHeadingSize The smallest size of heading to split on. - * @return A list of each document. - */ - public static List splitDocumentByHeadings(@NonNull Document document, int maxHeadingSize) { - List docs = new ArrayList<>(); - Document currentDocument = new Document(); - Node next; - for (Node n = document.getFirstChild(); n != null; n = next) { - next = n.getNext(); - if (n instanceof Heading && ((Heading) n).getLevel() <= maxHeadingSize) { - docs.add(currentDocument); - currentDocument = new Document(); - } - currentDocument.appendChild(n); - } - docs.add(currentDocument); - return docs; - } - /** * Split a document into multiple documents, delimited by thematic breaks. Destroys the original document. * @param document The original document @@ -196,7 +178,7 @@ public static List splitDocumentByBreaks(@NonNull Document document) { * @param component The component to measure * @return The width of the text, in pixels */ - public static int getComponentWidth(@NotNull JsonComponent component) { + public static int getComponentWidth(@NonNull JsonComponent component) { String text = component.getText(); int width = getStringWidth(text); if (component.getBold() == Boolean.TRUE) width += text.length(); @@ -211,7 +193,7 @@ public static int getComponentWidth(@NotNull JsonComponent component) { * @param text The string to measure * @return The width of the string, in pixels */ - public static int getStringWidth(@NotNull String text) { + public static int getStringWidth(@NonNull String text) { if (text.isEmpty()) return 0; int width = 0; int textLength = text.length(); From 59d85cd7e8290d391c09f93c12bdd449e94b76ee Mon Sep 17 00:00:00 2001 From: Matt <25674682+spazzylemons@users.noreply.github.com> Date: Thu, 10 Dec 2020 10:35:04 -0500 Subject: [PATCH 21/79] Remove RuleBook --- .../stickyapi/bukkit/item/RuleBook.java | 57 ------------------- 1 file changed, 57 deletions(-) delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java deleted file mode 100644 index 58957c6a..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/RuleBook.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (c) 2020 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.bukkit.item; - -import com.dumbdogdiner.stickyapi.bukkit.item.generator.BookGenerator; -import com.dumbdogdiner.stickyapi.common.book.chat.JsonComponent; -import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.JsonComponentWriter; -import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.MCColorFormatDelimiterProcessor; -import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.MCFormatExtension; -import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.MarkdownJsonRenderer; -import com.dumbdogdiner.stickyapi.common.util.BookUtil; -import org.bukkit.Bukkit; -import org.bukkit.inventory.ItemStack; -import org.bukkit.Material; -import org.commonmark.node.Document; -import org.commonmark.parser.Parser; - -import java.io.*; -import java.util.List; - -public class RuleBook { - //TODO MOVE TO CONST - private static final String RULEBOOK_PATH = "plugin name i guess? /rulebook.md"; - - // TODO where should we expect to find rulebook.md? using server root directory for now - private static File getRulebookPath() { - return new File(Bukkit.getWorldContainer(), "rulebook.md"); - } - - public static ItemStack generateDefault() throws IOException { - try (var reader = new InputStreamReader(new FileInputStream(getRulebookPath()))) { - return generate(reader, "§ddddMC Survival Handbook", "Stixil"); - } - } - - public static ItemStack generate(Reader reader, String title, String author) throws IOException { - var builder = Parser.builder(); - MCFormatExtension.create().extend(builder); - var cmparser = builder.build(); - var bookGenerator = new BookGenerator(Material.WRITTEN_BOOK); - var sections = BookUtil.splitDocumentByBreaks((Document) cmparser.parseReader(reader)); - sections.stream() - .map(section -> BookUtil.splitBookPages(renderDocument(section))) - .flatMap(List::stream) - .forEach(page -> bookGenerator.addPage(page.toJson())); - return bookGenerator.setTitle(title).setAuthor(author).toItemStack(1); - } - - private static JsonComponent renderDocument(Document document) { - var component = new JsonComponent(); - var writer = new JsonComponentWriter(component); - new MarkdownJsonRenderer(writer).render(document); - return component; - } -} From 6fcf8225ec443f7aa245dd3bbe55efc27ba46591 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 17 Jan 2021 08:34:42 +0000 Subject: [PATCH 22/79] Revert changes that are no longer needed --- .github/workflows/ci.yml | 8 -------- .github/workflows/docs.yml | 8 -------- .github/workflows/publish.yml | 8 -------- .../com/dumbdogdiner/stickyapi/common/ServerVersion.java | 2 -- 4 files changed, 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2eadd71..a3487780 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,14 +14,6 @@ jobs: - uses: actions/checkout@v2 - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Setup gradle.properties - run: | - mkdir -p ~/.gradle/ - echo "GRADLE_USER_HOME=$HOME/.gradle" >> $GITHUB_ENV - echo "ghUser=${GITHUB_ACTOR}" >> ~/.gradle/gradle.properties - echo "ghPass=${GITHUB_TOKEN}" >> ~/.gradle/gradle.properties - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Build with Gradle run: ./gradlew build - name: Install dependencies for coverage reporter (java 11 only) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index b0324af0..0f57403b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -22,14 +22,6 @@ jobs: persist-credentials: false - name: Echo branch name run: echo ${GITHUB_REF##*/} - - name: Setup gradle.properties - run: | - mkdir -p ~/.gradle/ - echo "GRADLE_USER_HOME=$HOME/.gradle" >> $GITHUB_ENV - echo "ghUser=${GITHUB_ACTOR}" >> ~/.gradle/gradle.properties - echo "ghPass=${GITHUB_TOKEN}" >> ~/.gradle/gradle.properties - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Build docs run: | ./gradlew javadoc diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 12df168c..a5724fbe 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -16,14 +16,6 @@ jobs: run: echo ${GITHUB_REF##*/} - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Setup gradle.properties - run: | - mkdir -p ~/.gradle/ - echo "GRADLE_USER_HOME=$HOME/.gradle" >> $GITHUB_ENV - echo "ghUser=${GITHUB_ACTOR}" >> ~/.gradle/gradle.properties - echo "ghPass=${GITHUB_TOKEN}" >> ~/.gradle/gradle.properties - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Publish with Gradle run: ./gradlew -Pversion=${GITHUB_REF##*/} publish env: diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java b/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java index d6a94012..a2ab1c97 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java @@ -33,8 +33,6 @@ public static ServerType getServerType() { } return ServerType.BUNGEE; - - } /** From 4b3ab4af4dc86b37a4ff4063287ab9ef55e300db Mon Sep 17 00:00:00 2001 From: James Date: Sun, 17 Jan 2021 09:19:49 +0000 Subject: [PATCH 23/79] Re-add CommonMark to dependencies --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index a1b795ab..ae8b4a23 100644 --- a/build.gradle +++ b/build.gradle @@ -52,6 +52,9 @@ dependencies { implementation 'com.google.code.gson:gson:2.8.6' implementation 'io.github.classgraph:classgraph:4.8.98' implementation 'com.github.seancfoley:ipaddress:5.3.3' + + // CommonMark for Book Text Utils + implementation 'com.atlassian.commonmark:commonmark:0.15.2' // Tests - JUnit 5 testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0") From cffd7d7b391abb12532ffb4c82ee7e5fabc598d0 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 17 Jan 2021 09:21:16 +0000 Subject: [PATCH 24/79] Run license formatter --- .../stickyapi/bukkit/item/generator/BookGenerator.java | 4 ++-- .../dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java | 4 ++-- .../stickyapi/common/book/chat/ComponentColor.java | 4 ++-- .../dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java | 4 ++-- .../stickyapi/common/book/chat/JsonComponent.java | 4 ++-- .../common/book/commonmarkextensions/JsonComponentWriter.java | 4 ++-- .../commonmarkextensions/MCColorFormatDelimiterProcessor.java | 4 ++-- .../common/book/commonmarkextensions/MCColorNode.java | 4 ++-- .../common/book/commonmarkextensions/MCFormatExtension.java | 4 ++-- .../book/commonmarkextensions/MarkdownJsonRenderer.java | 4 ++-- .../com/dumbdogdiner/stickyapi/common/book/package-info.java | 4 ++-- .../java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java | 4 ++-- 12 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java index 50d553ce..4663447a 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2020 DumbDogDiner . All rights reserved. +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ package com.dumbdogdiner.stickyapi.bukkit.item.generator; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java index 688b60fd..9b3ff05d 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2020 DumbDogDiner . All rights reserved. +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ package com.dumbdogdiner.stickyapi.common.book.chat; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java index ec16b145..7c2ca932 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2020 DumbDogDiner . All rights reserved. +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ package com.dumbdogdiner.stickyapi.common.book.chat; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java index f59cb286..d4d69ba2 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2020 DumbDogDiner . All rights reserved. +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ package com.dumbdogdiner.stickyapi.common.book.chat; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java index a3ccea99..85954c4f 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2020 DumbDogDiner . All rights reserved. +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ package com.dumbdogdiner.stickyapi.common.book.chat; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponentWriter.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponentWriter.java index 8f2d85a6..ce3e02f3 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponentWriter.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponentWriter.java @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2020 DumbDogDiner . All rights reserved. +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java index 99db423f..19287751 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2020 DumbDogDiner . All rights reserved. +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java index 8e1f9eb5..3f63b3fc 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2020 DumbDogDiner . All rights reserved. +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java index 0791dee0..5e5d9e57 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2020 DumbDogDiner . All rights reserved. +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java index 3909c969..af7c4594 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2020 DumbDogDiner . All rights reserved. +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/package-info.java index d68bef74..fad7c999 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/package-info.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/package-info.java @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2020 DumbDogDiner . All rights reserved. +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ package com.dumbdogdiner.stickyapi.common.book; \ No newline at end of file diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index 1a63af9f..c3aa2714 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2020 DumbDogDiner . All rights reserved. +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ package com.dumbdogdiner.stickyapi.common.util; From eae7442227d0af265d00c85462016da840c893a9 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 17 Jan 2021 09:23:26 +0000 Subject: [PATCH 25/79] Remove unused imports --- .../dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java | 6 ------ .../common/book/commonmarkextensions/MCFormatExtension.java | 1 - 2 files changed, 7 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java index d4d69ba2..dbc12c96 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java @@ -8,15 +8,9 @@ import com.google.gson.JsonObject; import lombok.Getter; import lombok.NonNull; -import org.bukkit.Bukkit; import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Nullable; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.UUID; /** diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java index 5e5d9e57..cea94cc5 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java @@ -4,7 +4,6 @@ */ package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; -import org.commonmark.Extension; import org.commonmark.parser.Parser; public class MCFormatExtension implements Parser.ParserExtension { From 8ca95ead44d956446f88aceafeecf6d8e42b5874 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sat, 23 Jan 2021 12:26:10 -0700 Subject: [PATCH 26/79] Ignore vscode workspaces --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5459b6f0..a729b3b3 100644 --- a/.gitignore +++ b/.gitignore @@ -48,4 +48,5 @@ bin .settings .classpath .project -.idea \ No newline at end of file +.idea +*.code-workspace \ No newline at end of file From cd306cdf07ab1cf9216f29d93963cb89da13b7fa Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sat, 23 Jan 2021 15:21:07 -0700 Subject: [PATCH 27/79] Fix a bunch of broken-ness and start tests --- .../bukkit/command/BukkitCommandBuilder.java | 2 +- .../bukkit/item/generator/BookGenerator.java | 56 +++++++---- .../common/book/chat/ClickEvent.java | 15 +-- .../common/book/chat/ComponentColor.java | 7 +- .../common/book/chat/JsonComponent.java | 2 +- .../stickyapi/common/book/BookTests.java | 71 ++++++++++++++ src/test/resources/rulebook.md | 97 +++++++++++++++++++ 7 files changed, 219 insertions(+), 31 deletions(-) create mode 100644 src/test/java/com/dumbdogdiner/stickyapi/common/book/BookTests.java create mode 100644 src/test/resources/rulebook.md diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/BukkitCommandBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/BukkitCommandBuilder.java index fdfa9524..3265f080 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/BukkitCommandBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/BukkitCommandBuilder.java @@ -62,7 +62,7 @@ public interface ErrorHandler { } /** - * Create a new [@link BukkitCommandBuilder} instance + * Create a new {@link BukkitCommandBuilder} instance *

* Used to build and register Bukkit commands * diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java index 4663447a..0695c941 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java @@ -5,8 +5,9 @@ package com.dumbdogdiner.stickyapi.bukkit.item.generator; import com.dumbdogdiner.stickyapi.common.util.BookUtil; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; +import com.google.common.base.Preconditions; +import com.google.gson.*; +import com.google.gson.reflect.TypeToken; import lombok.Getter; import lombok.NonNull; import lombok.Setter; @@ -17,6 +18,12 @@ import org.bukkit.inventory.meta.BookMeta; import org.jetbrains.annotations.Nullable; +import java.awt.print.Book; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; + @SuppressWarnings({"UnusedReturnValue", "unused"}) @Accessors(chain = true) public class BookGenerator { @@ -34,6 +41,11 @@ public class BookGenerator { @Getter @Setter private String title; + /** A basic blank meta for cloning */ + private static final BookMeta BASE_META = (BookMeta) new ItemStack(Material.WRITTEN_BOOK).getItemMeta(); + + private static final Gson G = new GsonBuilder().create(); + public BookGenerator(Material material) { if (material != Material.WRITABLE_BOOK && material != Material.WRITTEN_BOOK) { throw new IllegalArgumentException("Material must be WRITABLE_BOOK or WRITTEN_BOOK"); @@ -60,41 +72,51 @@ public BookGenerator addPages(JsonObject... pages) { * @return This object, for chaining */ public BookGenerator addPage(JsonObject page) { - if(!isFull()){ - pages.add(page.toString()); - } else { - throw new IllegalStateException("Book is overfilled"); - } + Preconditions.checkState(isFull(), "Cannot add page, the book is overfilled!"); + pages.add(page); return this; } /** - * Build a book from this generator. - * @param qty Quantity of the item stack. - * @return {@link ItemStack} + * Builds a {@link BookMeta} with the data provided to the generator */ - public ItemStack toItemStack(int qty) { - ItemStack stack = Bukkit.getUnsafe().modifyItemStack(new ItemStack(bookType), "{pages: " + pages.toString() + "}"); - + public BookMeta toBookMeta() { + Preconditions.checkState(pages.size() > 0, "Cannot generate BookMeta with no pages"); + Preconditions.checkState(pages.size() > BookUtil.PAGES_PER_BOOK, "Cannot generate BookMeta with an invalid number of pages"); + BookMeta meta = BASE_META.clone(); if (bookType == Material.WRITTEN_BOOK) { - BookMeta meta = (BookMeta) stack.getItemMeta(); - meta.setTitle(title); - meta.setAuthor(author); + meta.setTitle(title != null ? title : ""); + meta.setAuthor(author != null ? author : ""); meta.setGeneration(generation); - stack.setItemMeta(meta); } + pages.forEach(page -> meta.addPage(G.toJson(page))); + return meta; + } + + /** + * Build a book from this generator. + * @param qty Quantity of the item stack. + * @return an {@link ItemStack} of the book, with pages and all other data + */ + public ItemStack toItemStack(int qty) { + Preconditions.checkArgument(qty > 0 && qty <= 16, "Invalid quantity specified, qty should be greater than 0 and less than or equal to 16, but was " + qty); + ItemStack stack = new ItemStack(bookType, qty); + + stack.setItemMeta(toBookMeta()); return stack; } /** * @return The percentage of pages allowed that are used by this book. + * TODO: Does not account for characters per page or packet size at this time. */ public float percentFull() { return (float)pages.size() / (float)BookUtil.PAGES_PER_BOOK; } /** + * TODO: Does not account for characters per page or packet size at this time. * @return True if the book is full. */ public boolean isFull() { diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java index 9b3ff05d..b6366553 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java @@ -25,7 +25,8 @@ private ClickEvent() {} // seal this class * Create a copy of this ClickEvent. * @return {@link ClickEvent} */ - public abstract @NonNull ClickEvent duplicate(); + @Override + public abstract @NonNull ClickEvent clone(); /** * When clicked, displays a prompt to open a URL in the player's browser. @@ -48,7 +49,7 @@ public JsonElement toJson() { } @Override - public OpenUrl duplicate() { + public OpenUrl clone() { return new OpenUrl(url); } } @@ -75,7 +76,7 @@ public JsonElement toJson() { } @Override - public OpenFile duplicate() { + public OpenFile clone() { return new OpenFile(path); } } @@ -103,7 +104,7 @@ public JsonElement toJson() { } @Override - public RunCommand duplicate() { + public RunCommand clone() { return new RunCommand(command); } } @@ -130,7 +131,7 @@ public JsonElement toJson() { } @Override - public SuggestCommand duplicate() { + public SuggestCommand clone() { return new SuggestCommand(command); } } @@ -156,7 +157,7 @@ public JsonElement toJson() { } @Override - public ChangePage duplicate() { + public ChangePage clone() { return new ChangePage(page); } } @@ -182,7 +183,7 @@ public JsonElement toJson() { } @Override - public CopyToClipboard duplicate() { + public CopyToClipboard clone() { return new CopyToClipboard(text); } } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java index 7c2ca932..f7b626af 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java @@ -16,6 +16,7 @@ /** * A color used in text components. + * TODO: make this a lot nicer and less hacky */ public class ComponentColor { private static final HashMap VALID_NAMED_COLORS = new HashMap<>(); @@ -64,11 +65,7 @@ private static ComponentColor registerValid(String text) { * @return {@link ComponentColor} */ public static @Nullable ComponentColor fromText(@NonNull String text) { - if (HEX_PATTERN.matcher(text).matches()) { - return new ComponentColor(text); - } else { - return VALID_NAMED_COLORS.get(text); - } + return HEX_PATTERN.matcher(text).matches() ? new ComponentColor(text) : VALID_NAMED_COLORS.get(text); } /** diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java index 85954c4f..8d63995e 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java @@ -129,7 +129,7 @@ public JsonComponent duplicate() { clone.strikethrough = strikethrough; clone.obfuscated = obfuscated; clone.color = color; - if (clickEvent != null) clone.clickEvent = clickEvent.duplicate(); + if (clickEvent != null) clone.clickEvent = clickEvent.clone(); if (hoverEvent != null) clone.hoverEvent = hoverEvent.duplicate(); for (JsonComponent child : children) { clone.children.add(child.duplicate()); diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/book/BookTests.java b/src/test/java/com/dumbdogdiner/stickyapi/common/book/BookTests.java new file mode 100644 index 00000000..adbd2c52 --- /dev/null +++ b/src/test/java/com/dumbdogdiner/stickyapi/common/book/BookTests.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.book; + +import com.dumbdogdiner.stickyapi.common.book.chat.JsonComponent; +import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.JsonComponentWriter; +import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.MCFormatExtension; +import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.MarkdownJsonRenderer; +import com.dumbdogdiner.stickyapi.common.util.BookUtil; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import lombok.SneakyThrows; +import org.commonmark.node.Document; +import org.commonmark.parser.Parser; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; + +public class BookTests { + private static final String BOOK_FILENAME = "/rulebook.md"; + private static Reader bookReader; + private static Gson G; + @BeforeAll + static void setUp(){ + bookReader = new InputStreamReader(BookTests.class.getResourceAsStream(BOOK_FILENAME)); + G = new GsonBuilder()/*.setPrettyPrinting()*/.create(); + } + + + @AfterAll + static void tearDown() throws IOException { + bookReader.close(); + G = null; + System.gc(); + } + + @SneakyThrows + @Test + public void testParser() { + Parser.Builder parserBuilder = Parser.builder(); + MCFormatExtension.create().extend(parserBuilder); + Parser cmParser = parserBuilder.build(); + List sections = BookUtil.splitDocumentByBreaks((Document)cmParser.parseReader(bookReader)); + JsonArray pages = new JsonArray(); + sections.stream() + .map(section -> BookUtil.splitBookPages(renderDocument(section))) + .flatMap(List::stream) + .forEach(page -> pages.add(page.toJson())); + + System.out.println(G.toJson(pages)); + } + + + private JsonComponent renderDocument(Document section) { + JsonComponent component = new JsonComponent(); + JsonComponentWriter writer = new JsonComponentWriter(component); + new MarkdownJsonRenderer(writer).render(section); + return component; + } + +} diff --git a/src/test/resources/rulebook.md b/src/test/resources/rulebook.md new file mode 100644 index 00000000..dc56fdb1 --- /dev/null +++ b/src/test/resources/rulebook.md @@ -0,0 +1,97 @@ +# Dumb Dog Diner MC Survival Handbook + +## $red The Rules$ + +1. Absolutely no griefing, theft, or intentional distress! +2. No cheating/hacking allowed. Optifine and similar are okay. +3. No floating trees. +4. No fully-automatic redstone farms. +5. No harassment, bullying, or abuse. +6. No AFK fishing. + +--- + +## $dark_green Gameplay$ + +The world border for all worlds is 8,000 blocks from the center. Because of how +$dark_red Nether Portal$ travel works, you will not be able to light them past 1,000 blocks +from the center. You may build wherever you like! Try /rtp to help find a spot! + +This server uses a $red Death Chest$ system. Upon death, a campfire with your items +will spawn at your death location. It will last for 10 minutes before your items +drop on the ground! You can have up to 3 $red Death Chests$ at a time. + +--- + +## $dark_aqua Trading$ + +We use chest chops for player to trade good for $gold Coins$. Coins may be +earned through selling goods to other players, paying/receiving money for a +service, or by selling goods to the server itself. + +Chest shops can buy or sell items! To make a shop, place a chest and shift-click +with the item you want to sell or buy. Regular users may have up to 6 shops at a +time. + +--- + +## $red Commands$ + +Tab-complete is set up to only show commands you have access to. Here are some +useful ones: + +- $blue /help$ - Opens the help menu +- $blue /servers$ - Opens the server menu +- $blue /rules$ - Grants this book +- $blue /options$ - Opens the player options menu +- $blue /tpa$ - Sends a teleport request to another player +- $blue /rtp$ - Start a random teleport +- $blue /pw$ - Opens the playerwarps personal home menu +- $blue /helpme$ - Pings an online staff member for assistance + +--- + +## $dark_purple Trading Commands$ + +- $blue /bal$ - Check your balance +- $blue /pay$ - Pay another player +- $blue /sell$ - Sell the item in your hand to the server +- $blue /worth$ - Shows the item price when selling to the server +- $blue /value$ - Shows the average selling price for an item in player shops + +--- + +## $dark_aqua Extra Commands$ + +- $blue /donate, /vip$ - Gives link to the server Patreon page +- $blue /discord$ - Gives link to the server Discord +- $blue /twitter, /twitch$ - Gives social media links +- $blue /merch$ - Gives merch link +- $blue /afk$ - Set your status to AFK + +--- + +## $light_purple Getting Help$ + +If you ever need help getting your way around the server, please ask any staff! +**$blue /helpme$** + +Please join the Discord server to get technical help! **$blue /discord$** + +Please report any bugs, griefing, etc. that you come across or are a victim of. +A staff member will be happy to assist you. The help menu has shortcuts that +make getting help easy! **$blue /help$** + +--- + +## $gold Credits$ + +$dark_purple **dddMC**$ is fully funded through player donations. Please consider helping +support us on Patreon! $blue **/donate /patreon**$ + +Patrons will receive a VIP rank. More +ranks will be added in the future. + +We hope you enjoy your time playing on the server! + +\- Stixil, $dark_purple **dddMC 2020**$ From c5a3fa8d3be25f75af0d129ef7f9e788897a082e Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sat, 23 Jan 2021 18:46:25 -0700 Subject: [PATCH 28/79] Change to switch case --- .../common/book/chat/JsonComponent.java | 11 ++- .../stickyapi/common/util/BookUtil.java | 91 ++++++++++--------- 2 files changed, 56 insertions(+), 46 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java index 8d63995e..3dc524f5 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java @@ -5,10 +5,12 @@ package com.dumbdogdiner.stickyapi.common.book.chat; import com.google.gson.JsonArray; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import lombok.Getter; import lombok.NonNull; import lombok.Setter; +import net.md_5.bungee.api.chat.BaseComponent; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -19,7 +21,7 @@ import java.util.stream.Stream; /** - * A text component that can be converted to JSON. Differs slightly from BaseComponent. + * A text component that can be converted to JSON. Differs slightly from BaseComponent, and is not part of the UML */ public class JsonComponent { @Getter @Setter @@ -43,8 +45,11 @@ public class JsonComponent { @Getter private final List children = new ArrayList<>(); - public JsonComponent() {} - + @SuppressWarnings("deprecation") + public JsonComponent(){ + // Need to find out why this is used and stuffs + } + @SuppressWarnings("deprecation") public JsonComponent(@NonNull String text) { this.text = text; } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index c3aa2714..2e2d66f7 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -14,6 +14,8 @@ import org.commonmark.node.Document; import org.commonmark.node.Node; import org.commonmark.node.ThematicBreak; +import java.awt.Font; + /** * Utilities for text and books. @@ -25,59 +27,58 @@ public class BookUtil { private static final Pattern SPLIT_PATTERN = Pattern.compile("(?<=[ \n])|(?=[ \n])"); - // TODO: Test efficiency of this vs switch/case - static HashMap characterWidths = new HashMap<>(); - static { - characterWidths.put('!', 1); - characterWidths.put(',', 1); - characterWidths.put('\'', 1); - characterWidths.put('.', 1); - characterWidths.put(':', 1); - characterWidths.put(';', 1); - characterWidths.put('i', 1); - characterWidths.put('|', 1); - - characterWidths.put('`', 2); - characterWidths.put('l', 2); - - characterWidths.put(' ', 3); - characterWidths.put('(', 3); - characterWidths.put(')', 3); - characterWidths.put('*', 3); - characterWidths.put('I', 3); - characterWidths.put('[', 3); - characterWidths.put(']', 3); - characterWidths.put('t', 3); - characterWidths.put('{', 3); - characterWidths.put('}', 3); - - characterWidths.put('<', 4); - characterWidths.put('>', 4); - characterWidths.put('f', 4); - characterWidths.put('k', 4); - - characterWidths.put('@', 6); - characterWidths.put('~', 6); - } - /** * Uses info from https://minecraft.gamepedia.com/Language#Font" + * * @param c The character to measure * @return The width of the character in pixels + * @throws IllegalArgumentException if the character is out of range */ public static int getCharacterWidth(char c) { - if (c < 32 || c > 126) { - // Not presently implemented, would require rendering TTF - return -1; - } - if (characterWidths.containsKey(c)) { - return characterWidths.get(c); + if (c >= 32 && c <= 126) { + switch (c) { + case '!': + case ',': + case '\'': + case '.': + case ':': + case ';': + case 'i': + case '|': + return 1; + case '`': + case 'l': + return 2; + case ' ': + case '(': + case ')': + case '*': + case 'I': + case '[': + case ']': + case 't': + case '{': + case '}': + return 3; + case '<': + case '>': + case 'f': + case 'k': + return 4; + case '@': + case '~': + return 6; + default: + return 5; + } } - return 5; + + throw new IllegalArgumentException("Unsupported character"); } /** * Split a JsonComponent into pages for use in a book. + * * @param origComponent The component to split into pages * @return A list of JsonComponents, one for each page */ @@ -108,8 +109,9 @@ public static List splitBookPages(@NonNull JsonComponent origComp /** * Wrap a JsonComponent into lines. + * * @param origComponent The JsonComponent to wrap. - * @param pixels The width of the JsonComponent in pixels. + * @param pixels The width of the JsonComponent in pixels. * @return A list of JsonComponents, one for each line */ public static List wrapLines(@NonNull JsonComponent origComponent, int pixels) { @@ -153,6 +155,7 @@ public static List wrapLines(@NonNull JsonComponent origComponent /** * Split a document into multiple documents, delimited by thematic breaks. Destroys the original document. + * * @param document The original document * @return A list of each document. */ @@ -175,6 +178,7 @@ public static List splitDocumentByBreaks(@NonNull Document document) { /** * Measure the width of text in a BaseComponent in pixels. + * * @param component The component to measure * @return The width of the text, in pixels */ @@ -190,6 +194,7 @@ public static int getComponentWidth(@NonNull JsonComponent component) { /** * Measure the width of a string, assuming it is unformatted and in the default Minecraft font. + * * @param text The string to measure * @return The width of the string, in pixels */ From 52d16702c0c78bc6f840a47f6eb675d80a65a31d Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sat, 23 Jan 2021 18:57:21 -0700 Subject: [PATCH 29/79] Added some characters manually --- .../stickyapi/common/util/BookUtil.java | 76 ++++++++++--------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index 2e2d66f7..3078f67c 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -14,6 +14,7 @@ import org.commonmark.node.Document; import org.commonmark.node.Node; import org.commonmark.node.ThematicBreak; + import java.awt.Font; @@ -35,45 +36,48 @@ public class BookUtil { * @throws IllegalArgumentException if the character is out of range */ public static int getCharacterWidth(char c) { + + switch (c) { + case '!': + case ',': + case '\'': + case '.': + case ':': + case ';': + case 'i': + case '|': + return 1; + case '`': + case 'l': + return 2; + case ' ': + case '(': + case ')': + case '*': + case 'I': + case '[': + case ']': + case 't': + case '{': + case '}': + case '\u2022': + return 3; + case '<': + case '>': + case 'f': + case 'k': + case '\u00b7': + return 4; + case '@': + case '~': + return 6; + } if (c >= 32 && c <= 126) { - switch (c) { - case '!': - case ',': - case '\'': - case '.': - case ':': - case ';': - case 'i': - case '|': - return 1; - case '`': - case 'l': - return 2; - case ' ': - case '(': - case ')': - case '*': - case 'I': - case '[': - case ']': - case 't': - case '{': - case '}': - return 3; - case '<': - case '>': - case 'f': - case 'k': - return 4; - case '@': - case '~': - return 6; - default: - return 5; - } + return 5; } - throw new IllegalArgumentException("Unsupported character"); + + throw new IllegalArgumentException("Unsupported character: " + c + " code: " + String.format("%04x", (int) c)); } /** From ce6f63b3b40213d8aa2c6dcc0a4e03599e7075e2 Mon Sep 17 00:00:00 2001 From: Matt <25674682+spazzylemons@users.noreply.github.com> Date: Sat, 23 Jan 2021 21:26:31 -0500 Subject: [PATCH 30/79] Use HashMap for characters, remove obsolete TextUtil class --- .../stickyapi/common/util/BookUtil.java | 79 +++++++++---------- .../stickyapi/common/util/TextUtil.java | 66 ---------------- 2 files changed, 39 insertions(+), 106 deletions(-) delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index 3078f67c..0ffc9ab3 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -28,6 +28,42 @@ public class BookUtil { private static final Pattern SPLIT_PATTERN = Pattern.compile("(?<=[ \n])|(?=[ \n])"); + private static final HashMap widths = new HashMap<>(); + + static { + for (char c = 32; c <= 126; ++c) { + widths.put(c, 5); + } + widths.put('!', 1); + widths.put(',', 1); + widths.put('\'', 1); + widths.put('.', 1); + widths.put(':', 1); + widths.put(';', 1); + widths.put('i', 1); + widths.put('|', 1); + widths.put('`', 2); + widths.put('l', 2); + widths.put(' ', 3); + widths.put('(', 3); + widths.put(')', 3); + widths.put('*', 3); + widths.put('I', 3); + widths.put('[', 3); + widths.put(']', 3); + widths.put('t', 3); + widths.put('{', 3); + widths.put('}', 3); + widths.put('\u2022', 3); + widths.put('<', 4); + widths.put('>', 4); + widths.put('f', 4); + widths.put('k', 4); + widths.put('\u00b7', 4); + widths.put('@', 6); + widths.put('~', 6); + } + /** * Uses info from https://minecraft.gamepedia.com/Language#Font" * @@ -36,47 +72,10 @@ public class BookUtil { * @throws IllegalArgumentException if the character is out of range */ public static int getCharacterWidth(char c) { - - switch (c) { - case '!': - case ',': - case '\'': - case '.': - case ':': - case ';': - case 'i': - case '|': - return 1; - case '`': - case 'l': - return 2; - case ' ': - case '(': - case ')': - case '*': - case 'I': - case '[': - case ']': - case 't': - case '{': - case '}': - case '\u2022': - return 3; - case '<': - case '>': - case 'f': - case 'k': - case '\u00b7': - return 4; - case '@': - case '~': - return 6; - } - if (c >= 32 && c <= 126) { - return 5; + Integer width = widths.get(c); + if (width != null) { + return width; } - - throw new IllegalArgumentException("Unsupported character: " + c + " code: " + String.format("%04x", (int) c)); } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java deleted file mode 100644 index 9bdee829..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.util; - -import java.util.HashMap; - -import org.jetbrains.annotations.NotNull; - -public class TextUtil { - static HashMap characterWidths = new HashMap<>() { - { - put('!', 1); - put(',', 1); - put('\'', 1); - put('.', 1); - put(':', 1); - put(';', 1); - put('i', 1); - put('|', 1); - put('!', 1); - - put('`', 2); - put('l', 2); - - put(' ', 3); - put('(', 3); - put(')', 3); - put('*', 3); - put('I', 3); - put('[', 3); - put(']', 3); - put('t', 3); - put('{', 3); - put('}', 3); - - put('<', 4); - put('>', 4); - put('f', 4); - put('k', 4); - - put('@', 6); - put('~', 6); - } - }; - - // Uses info from: - /** - * Get the width of a character (https://minecraft.gamepedia.com/Language#Font) - * - * @param c - * @return - */ - public static int getCharacterWidth(@NotNull char c) { - if (c < 32 || c > 126) { - // Not presently implemented, would require rendering TTF - return -1; - } - - if (characterWidths.containsKey(c)) { - return characterWidths.get(c); - } - return 5; - } -} From 01ae2906de6592dea939d9487b01c19bd64b525a Mon Sep 17 00:00:00 2001 From: James Date: Sun, 24 Jan 2021 18:32:48 +0000 Subject: [PATCH 31/79] Add mojangles font width data as buildtime dep --- .gitignore | 5 ++++- build.gradle | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index a729b3b3..6c66882e 100644 --- a/.gitignore +++ b/.gitignore @@ -49,4 +49,7 @@ bin .classpath .project .idea -*.code-workspace \ No newline at end of file +*.code-workspace + +# Font Width Data +src/main/resources/mojangles_width_data.json \ No newline at end of file diff --git a/build.gradle b/build.gradle index dc026c40..97d7f01d 100644 --- a/build.gradle +++ b/build.gradle @@ -22,13 +22,12 @@ license { header = project.file('LICENSE_HEADER') ext.year = Calendar.getInstance().get(Calendar.YEAR) mapping("java", "SLASHSTAR_STYLE") + exclude "**/*.json" // Exclude JSON to keep the font width data valid } tasks.withType(JavaCompile) { options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" << "-XDignore.symbol.file" } -// Run the license formatter before compiling the source code. -tasks.compileJava.dependsOn licenseFormatMain, licenseFormatTest configurations { jaxDoclet @@ -42,9 +41,24 @@ repositories { maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } maven { url 'https://papermc.io/repo/repository/maven-public/' } + + // Define a Ivy repo for the font width data (that way we don't need another plugin! + def ddd_mc_font = ivy { + url 'https://dumbdogdiner.github.io/' + patternLayout { artifact '/[module]/[revision]/[classifier].[ext]'} + metadataSources { artifact() } + } + // Only use the Ivy repo for font width data - speeds up dependency resolution + exclusiveContent { + forRepositories(ddd_mc_font) + filter { includeGroup("dumbdogdiner") } + } } dependencies { + // Font width data (see above) + compile 'dumbdogdiner:mc-font-extractor:main:mojangles_width_data@json' + compileOnly 'org.projectlombok:lombok:1.18.16' annotationProcessor 'org.projectlombok:lombok:1.18.16' @@ -132,6 +146,21 @@ task processSourceTokens(type: Sync) { compileJava.source = processSourceTokens.outputs +// Font Width Info +task copyMCFontExtractor(type: Copy) { + def path = project.configurations.compile.find {it.name.startsWith("mc-font-extractor") } + println path + from file(path) + //into file("src/main/resources") + destinationDir file("src/main/resources/") + rename 'mc-font-extractor-main-mojangles_width_data.json', 'mojangles_width_data.json' +} + + +// Run the license formatter and font data copier before compiling the source code. +tasks.compileJava.dependsOn licenseFormatMain, licenseFormatTest, copyMCFontExtractor + + tasks.publish.dependsOn build, sources From 3e4e10d6dc74c7c5886e13de96de03b919d5d51f Mon Sep 17 00:00:00 2001 From: Matt <25674682+spazzylemons@users.noreply.github.com> Date: Sun, 24 Jan 2021 14:53:25 -0500 Subject: [PATCH 32/79] Update BookUtils to use JSON resource, change pixel measurements --- .../stickyapi/common/util/BookUtil.java | 100 +++++++++--------- 1 file changed, 48 insertions(+), 52 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index 0ffc9ab3..189cc05f 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -4,25 +4,25 @@ */ package com.dumbdogdiner.stickyapi.common.util; +import java.io.InputStream; +import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.regex.Pattern; import com.dumbdogdiner.stickyapi.common.book.chat.JsonComponent; +import com.google.gson.Gson; import lombok.NonNull; import org.commonmark.node.Document; import org.commonmark.node.Node; import org.commonmark.node.ThematicBreak; -import java.awt.Font; - - /** * Utilities for text and books. */ public class BookUtil { - public static final int PIXELS_PER_LINE = 113; + public static final int HALF_PIXELS_PER_LINE = 226; public static final int LINES_PER_PAGE = 14; public static final int PAGES_PER_BOOK = 50; @@ -30,45 +30,39 @@ public class BookUtil { private static final HashMap widths = new HashMap<>(); + private static class WidthEntry { + String uid; + Integer id; + String val; + int width; + } + static { - for (char c = 32; c <= 126; ++c) { - widths.put(c, 5); + Gson gson = new Gson(); + try (InputStream input = ClassLoader.getSystemResource("mojangles_width_data.json").openStream()) { + WidthEntry[] entries = gson.fromJson(new InputStreamReader(input), WidthEntry[].class); + for (WidthEntry entry : entries) { + if (entry.id == null) entry.id = 0; + widths.put((char) (int) entry.id, entry.width); + } + } catch (Exception e) { + e.printStackTrace(); + // fallback to a minimal , in case anything fails + for (char c = 32; c <= 126; ++c) { + widths.put(c, 12); + } + "\0 ".chars().forEach(c -> widths.put((char) c, 2)); + "!',.:;i|".chars().forEach(c -> widths.put((char) c, 4)); + "`l".chars().forEach(c -> widths.put((char) c, 6)); + "\"()*I[]t{}\u2022".chars().forEach(c -> widths.put((char) c, 8)); + "<>fk\u00b7".chars().forEach(c -> widths.put((char) c, 10)); + "@~".chars().forEach(c -> widths.put((char) c, 14)); } - widths.put('!', 1); - widths.put(',', 1); - widths.put('\'', 1); - widths.put('.', 1); - widths.put(':', 1); - widths.put(';', 1); - widths.put('i', 1); - widths.put('|', 1); - widths.put('`', 2); - widths.put('l', 2); - widths.put(' ', 3); - widths.put('(', 3); - widths.put(')', 3); - widths.put('*', 3); - widths.put('I', 3); - widths.put('[', 3); - widths.put(']', 3); - widths.put('t', 3); - widths.put('{', 3); - widths.put('}', 3); - widths.put('\u2022', 3); - widths.put('<', 4); - widths.put('>', 4); - widths.put('f', 4); - widths.put('k', 4); - widths.put('\u00b7', 4); - widths.put('@', 6); - widths.put('~', 6); } /** - * Uses info from https://minecraft.gamepedia.com/Language#Font" - * * @param c The character to measure - * @return The width of the character in pixels + * @return The width of the character in half-pixels * @throws IllegalArgumentException if the character is out of range */ public static int getCharacterWidth(char c) { @@ -86,7 +80,7 @@ public static int getCharacterWidth(char c) { * @return A list of JsonComponents, one for each page */ public static List splitBookPages(@NonNull JsonComponent origComponent) { - List lines = wrapLines(origComponent, PIXELS_PER_LINE); + List lines = wrapLines(origComponent, HALF_PIXELS_PER_LINE); List pages = new ArrayList<>(); JsonComponent currentPage = new JsonComponent(); int i = 0; @@ -114,10 +108,10 @@ public static List splitBookPages(@NonNull JsonComponent origComp * Wrap a JsonComponent into lines. * * @param origComponent The JsonComponent to wrap. - * @param pixels The width of the JsonComponent in pixels. + * @param halfPixels The width of the available space in half-pixels. * @return A list of JsonComponents, one for each line */ - public static List wrapLines(@NonNull JsonComponent origComponent, int pixels) { + public static List wrapLines(@NonNull JsonComponent origComponent, int halfPixels) { List components = origComponent.flatten(); if (components.isEmpty()) return new ArrayList<>(); List lineComponents = new ArrayList<>(); @@ -137,9 +131,8 @@ public static List wrapLines(@NonNull JsonComponent origComponent } else { JsonComponent wordComponent = component.duplicate(); wordComponent.setText(word); - int width = getStringWidth(word) + 1; - if (component.getBold() == Boolean.TRUE) width += word.length() + 1; - if (xPosition + width >= pixels) { + int width = getStringWidth(word, component.getBold() == Boolean.TRUE); + if (xPosition + width >= halfPixels) { lineComponents.add(currentLine); currentLine = new JsonComponent(); xPosition = width; @@ -180,15 +173,14 @@ public static List splitDocumentByBreaks(@NonNull Document document) { } /** - * Measure the width of text in a BaseComponent in pixels. + * Measure the width of text in a BaseComponent in half-pixels. * * @param component The component to measure - * @return The width of the text, in pixels + * @return The width of the text, in half-pixels */ public static int getComponentWidth(@NonNull JsonComponent component) { String text = component.getText(); - int width = getStringWidth(text); - if (component.getBold() == Boolean.TRUE) width += text.length(); + int width = getStringWidth(text, component.getBold() == Boolean.TRUE); for (JsonComponent child : component.getChildren()) { width += getComponentWidth(child); } @@ -196,19 +188,23 @@ public static int getComponentWidth(@NonNull JsonComponent component) { } /** - * Measure the width of a string, assuming it is unformatted and in the default Minecraft font. + * Measure the width of a string, assuming it is in the default Minecraft font. * * @param text The string to measure - * @return The width of the string, in pixels + * @param isBold If the string is bold + * @return The width of the string, in half-pixels */ - public static int getStringWidth(@NonNull String text) { - if (text.isEmpty()) return 0; + public static int getStringWidth(@NonNull String text, boolean isBold) { int width = 0; int textLength = text.length(); for (int i = 0; i < textLength; ++i) { width += BookUtil.getCharacterWidth(text.charAt(i)); } - width += textLength - 1; + if (isBold) width += 2 * textLength; return width; } + + public static int getStringWidth(@NonNull String text) { + return getStringWidth(text, false); + } } From c364e4ccbf715c51fc8b77c5c13fa145cdccd611 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Mon, 25 Jan 2021 13:14:02 -0700 Subject: [PATCH 33/79] Fix book item generation nbt (hopefully) --- .../bukkit/item/generator/BookGenerator.java | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java index 0695c941..7956cbdf 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.StringJoiner; import java.util.function.Consumer; @SuppressWarnings({"UnusedReturnValue", "unused"}) @@ -72,28 +73,11 @@ public BookGenerator addPages(JsonObject... pages) { * @return This object, for chaining */ public BookGenerator addPage(JsonObject page) { - Preconditions.checkState(isFull(), "Cannot add page, the book is overfilled!"); + Preconditions.checkState(!isFull(), "Cannot add page, the book is overfilled!"); pages.add(page); return this; } - /** - * Builds a {@link BookMeta} with the data provided to the generator - */ - public BookMeta toBookMeta() { - Preconditions.checkState(pages.size() > 0, "Cannot generate BookMeta with no pages"); - Preconditions.checkState(pages.size() > BookUtil.PAGES_PER_BOOK, "Cannot generate BookMeta with an invalid number of pages"); - BookMeta meta = BASE_META.clone(); - if (bookType == Material.WRITTEN_BOOK) { - meta.setTitle(title != null ? title : ""); - meta.setAuthor(author != null ? author : ""); - meta.setGeneration(generation); - } - - pages.forEach(page -> meta.addPage(G.toJson(page))); - return meta; - } - /** * Build a book from this generator. * @param qty Quantity of the item stack. @@ -101,9 +85,21 @@ public BookMeta toBookMeta() { */ public ItemStack toItemStack(int qty) { Preconditions.checkArgument(qty > 0 && qty <= 16, "Invalid quantity specified, qty should be greater than 0 and less than or equal to 16, but was " + qty); + Preconditions.checkState(pages.size() > 0, "Cannot generate book with no pages"); + Preconditions.checkState(pages.size() < BookUtil.PAGES_PER_BOOK, "Cannot generate book with an invalid number of pages (must be less than " + BookUtil.PAGES_PER_BOOK + ")"); ItemStack stack = new ItemStack(bookType, qty); - stack.setItemMeta(toBookMeta()); + BookMeta meta = (BookMeta) stack.getItemMeta(); + + if (bookType == Material.WRITTEN_BOOK) { + meta.setTitle(title != null ? title : ""); + meta.setAuthor(author != null ? author : ""); + meta.setGeneration(generation); + } + + stack = Bukkit.getUnsafe().modifyItemStack(stack, generateNbtString()); + + stack.setItemMeta(meta); return stack; } @@ -124,4 +120,15 @@ public boolean isFull() { } + /** + * Uses a {@link StringJoiner} to convert pages JsonArray to the weird NBT list + * @return {@link String} with NBT of the pages + */ + private String generateNbtString() { + StringJoiner NBT = new StringJoiner("','", "{pages:['", "']}"); + pages.forEach(jsonElement -> NBT.add(G.toJson(jsonElement))); + return NBT.toString().replace("\\n","\n").replace("\n","\\n");//TODO fix the new lines where they are originally + } + + } From e7fc447277983a88c1ad6cf73cd4dcf4b57b7d6f Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Wed, 27 Jan 2021 13:32:42 -0700 Subject: [PATCH 34/79] Add some notes and fixes --- .../bukkit/item/generator/BookGenerator.java | 10 +++++----- .../item/generator/MarkdownBookGenerator.java | 8 ++++++++ .../stickyapi/common/util/BookUtil.java | 2 ++ .../stickyapi/common/book/BookTests.java | 20 +++++++++++++------ 4 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/MarkdownBookGenerator.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java index 7956cbdf..794e993e 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java @@ -17,6 +17,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.VisibleForTesting; import java.awt.print.Book; import java.util.ArrayList; @@ -42,8 +43,6 @@ public class BookGenerator { @Getter @Setter private String title; - /** A basic blank meta for cloning */ - private static final BookMeta BASE_META = (BookMeta) new ItemStack(Material.WRITTEN_BOOK).getItemMeta(); private static final Gson G = new GsonBuilder().create(); @@ -124,10 +123,11 @@ public boolean isFull() { * Uses a {@link StringJoiner} to convert pages JsonArray to the weird NBT list * @return {@link String} with NBT of the pages */ - private String generateNbtString() { + @VisibleForTesting + public String generateNbtString() { StringJoiner NBT = new StringJoiner("','", "{pages:['", "']}"); - pages.forEach(jsonElement -> NBT.add(G.toJson(jsonElement))); - return NBT.toString().replace("\\n","\n").replace("\n","\\n");//TODO fix the new lines where they are originally + pages.forEach(jsonElement -> NBT.add(G.toJson(jsonElement)/*.replace("'", "\\\"")*/)); + return NBT.toString().replace("\\n","\n").replace("\n","\\\\n");//TODO fix the new lines where they are originally } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/MarkdownBookGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/MarkdownBookGenerator.java new file mode 100644 index 00000000..f9291d3a --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/MarkdownBookGenerator.java @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.bukkit.item.generator; + +public class MarkdownBookGenerator { +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index 189cc05f..f62e4d88 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -105,6 +105,7 @@ public static List splitBookPages(@NonNull JsonComponent origComp } /** + * TODO move this into the commonmark parser thing instead, because it will make life like 1000 times better! * Wrap a JsonComponent into lines. * * @param origComponent The JsonComponent to wrap. @@ -117,6 +118,7 @@ public static List wrapLines(@NonNull JsonComponent origComponent List lineComponents = new ArrayList<>(); JsonComponent currentLine = new JsonComponent(); int xPosition = 0; + //TODO make this make better json plz its real crap for (JsonComponent component : components) { String[] words = SPLIT_PATTERN.split(component.getText()); for (String word : words) { diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/book/BookTests.java b/src/test/java/com/dumbdogdiner/stickyapi/common/book/BookTests.java index adbd2c52..5694041f 100644 --- a/src/test/java/com/dumbdogdiner/stickyapi/common/book/BookTests.java +++ b/src/test/java/com/dumbdogdiner/stickyapi/common/book/BookTests.java @@ -4,6 +4,7 @@ */ package com.dumbdogdiner.stickyapi.common.book; +import com.dumbdogdiner.stickyapi.bukkit.item.generator.BookGenerator; import com.dumbdogdiner.stickyapi.common.book.chat.JsonComponent; import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.JsonComponentWriter; import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.MCFormatExtension; @@ -14,6 +15,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.SneakyThrows; +import org.bukkit.Material; import org.commonmark.node.Document; import org.commonmark.parser.Parser; import org.junit.jupiter.api.AfterAll; @@ -26,10 +28,12 @@ import java.util.ArrayList; import java.util.List; -public class BookTests { +public class BookTests{ private static final String BOOK_FILENAME = "/rulebook.md"; private static Reader bookReader; private static Gson G; + + @BeforeAll static void setUp(){ bookReader = new InputStreamReader(BookTests.class.getResourceAsStream(BOOK_FILENAME)); @@ -50,14 +54,18 @@ public void testParser() { Parser.Builder parserBuilder = Parser.builder(); MCFormatExtension.create().extend(parserBuilder); Parser cmParser = parserBuilder.build(); - List sections = BookUtil.splitDocumentByBreaks((Document)cmParser.parseReader(bookReader)); - JsonArray pages = new JsonArray(); + List sections = BookUtil.splitDocumentByBreaks( + (Document)cmParser + .parseReader(bookReader)); + BookGenerator bg = new BookGenerator(Material.WRITTEN_BOOK); sections.stream() - .map(section -> BookUtil.splitBookPages(renderDocument(section))) + .map(section -> BookUtil + .splitBookPages( + renderDocument(section))) .flatMap(List::stream) - .forEach(page -> pages.add(page.toJson())); + .forEach(page -> bg.addPage(page.toJson())); - System.out.println(G.toJson(pages)); + System.out.println(bg.generateNbtString()); } From 572e74e91e5faf8336d104b662d6294da3fbddad Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Wed, 27 Jan 2021 14:44:16 -0700 Subject: [PATCH 35/79] fix const --- .../dumbdogdiner/stickyapi/common/util/BookUtil.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index f62e4d88..54e9f3cf 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -22,7 +22,15 @@ * Utilities for text and books. */ public class BookUtil { - public static final int HALF_PIXELS_PER_LINE = 226; + /** + * Offset for bold (in each direction) + */ + public static final float BOLD_OFFSET = 0.5f; + public static final float SHADOW_OFFSET = 0.5f; + + public static final int PIXELS_PER_LINE = 113; + public static final int HALF_PIXELS_PER_LINE = PIXELS_PER_LINE * 2; + public static final int LINES_PER_PAGE = 14; public static final int PAGES_PER_BOOK = 50; From d4c5c809f40f2fd093fe004858b170941d8f364e Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Fri, 29 Jan 2021 14:34:40 -0700 Subject: [PATCH 36/79] Finish books, requires in-game testing --- build.gradle | 3 +- .../stickyapi/annotation/OnHold.java | 15 +++ .../stickyapi/annotation/Untested.java | 3 + .../book/chat/ClickEvent.java | 3 +- .../book/chat/ComponentColor.java | 4 +- .../book/chat/HoverEvent.java | 2 +- .../book/chat/JsonComponent.java | 4 +- .../stickyapi/bukkit/book/chat/Style.java | 17 ++++ .../JsonComponentWriter.java | 10 +- .../commonmarkextensions/MCBlockParser.java | 22 +++++ .../MCColorFormatDelimiterProcessor.java | 95 +++++++++++++++++++ .../commonmarkextensions/MCColorNode.java | 4 +- .../MCFormatExtension.java | 8 +- .../MarkdownJsonRenderer.java | 8 +- .../stickyapi/bukkit/book/package-info.java | 13 +++ .../bukkit/item/generator/BookGenerator.java | 40 +++++++- .../item/generator/MarkdownBookGenerator.java | 8 -- .../MCColorFormatDelimiterProcessor.java | 67 ------------- .../stickyapi/common/book/package-info.java | 5 - .../stickyapi/common/util/BookUtil.java | 2 +- .../bukkit/book/BookGeneratorTest.java | 26 +++++ .../{common => bukkit}/book/BookTests.java | 17 ++-- src/test/resources/rulebook.json | 25 +++++ src/test/resources/rulebook.md | 6 +- 24 files changed, 292 insertions(+), 115 deletions(-) create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/annotation/OnHold.java rename src/main/java/com/dumbdogdiner/stickyapi/{common => bukkit}/book/chat/ClickEvent.java (98%) rename src/main/java/com/dumbdogdiner/stickyapi/{common => bukkit}/book/chat/ComponentColor.java (96%) rename src/main/java/com/dumbdogdiner/stickyapi/{common => bukkit}/book/chat/HoverEvent.java (98%) rename src/main/java/com/dumbdogdiner/stickyapi/{common => bukkit}/book/chat/JsonComponent.java (97%) create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/Style.java rename src/main/java/com/dumbdogdiner/stickyapi/{common => bukkit}/book/commonmarkextensions/JsonComponentWriter.java (91%) create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCBlockParser.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java rename src/main/java/com/dumbdogdiner/stickyapi/{common => bukkit}/book/commonmarkextensions/MCColorNode.java (78%) rename src/main/java/com/dumbdogdiner/stickyapi/{common => bukkit}/book/commonmarkextensions/MCFormatExtension.java (65%) rename src/main/java/com/dumbdogdiner/stickyapi/{common => bukkit}/book/commonmarkextensions/MarkdownJsonRenderer.java (93%) create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/package-info.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/MarkdownBookGenerator.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/book/package-info.java create mode 100644 src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookGeneratorTest.java rename src/test/java/com/dumbdogdiner/stickyapi/{common => bukkit}/book/BookTests.java (85%) create mode 100644 src/test/resources/rulebook.json diff --git a/build.gradle b/build.gradle index 97d7f01d..db043adb 100644 --- a/build.gradle +++ b/build.gradle @@ -70,7 +70,8 @@ dependencies { implementation 'com.github.seancfoley:ipaddress:5.3.3' // CommonMark for Book Text Utils - implementation 'com.atlassian.commonmark:commonmark:0.15.2' + implementation 'org.commonmark:commonmark:0.17.0' + implementation 'org.commonmark:commonmark-ext-gfm-strikethrough:0.17.0' // Tests - JUnit 5 testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0") diff --git a/src/main/java/com/dumbdogdiner/stickyapi/annotation/OnHold.java b/src/main/java/com/dumbdogdiner/stickyapi/annotation/OnHold.java new file mode 100644 index 00000000..27e4c383 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/annotation/OnHold.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.annotation; + +import java.lang.annotation.Documented; + +/** + * Denotes a feature or class that is in-progress but has had development halted + */ +@Documented +public @interface OnHold { + +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/annotation/Untested.java b/src/main/java/com/dumbdogdiner/stickyapi/annotation/Untested.java index 590e1862..5bd7d1b3 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/annotation/Untested.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/annotation/Untested.java @@ -6,6 +6,9 @@ import java.lang.annotation.Documented; +/** + * Denotes beta features that are not officially stable/tested + */ @Documented public @interface Untested { } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/ClickEvent.java similarity index 98% rename from src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java rename to src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/ClickEvent.java index b6366553..1fdbbe35 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ClickEvent.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/ClickEvent.java @@ -2,12 +2,13 @@ * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ -package com.dumbdogdiner.stickyapi.common.book.chat; +package com.dumbdogdiner.stickyapi.bukkit.book.chat; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import lombok.Getter; import lombok.NonNull; +import lombok.experimental.UtilityClass; /** * An event that is fired when text associated with this event is clicked. diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/ComponentColor.java similarity index 96% rename from src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java rename to src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/ComponentColor.java index f7b626af..92a7124c 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/ComponentColor.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/ComponentColor.java @@ -2,7 +2,7 @@ * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ -package com.dumbdogdiner.stickyapi.common.book.chat; +package com.dumbdogdiner.stickyapi.bukkit.book.chat; import lombok.Getter; import lombok.NonNull; @@ -10,8 +10,6 @@ import java.awt.*; import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; import java.util.regex.Pattern; /** diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/HoverEvent.java similarity index 98% rename from src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java rename to src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/HoverEvent.java index dbc12c96..f8b840ad 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/HoverEvent.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/HoverEvent.java @@ -2,7 +2,7 @@ * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ -package com.dumbdogdiner.stickyapi.common.book.chat; +package com.dumbdogdiner.stickyapi.bukkit.book.chat; import com.google.gson.JsonElement; import com.google.gson.JsonObject; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/JsonComponent.java similarity index 97% rename from src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java rename to src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/JsonComponent.java index 3dc524f5..b83fceb4 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/chat/JsonComponent.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/JsonComponent.java @@ -2,15 +2,13 @@ * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ -package com.dumbdogdiner.stickyapi.common.book.chat; +package com.dumbdogdiner.stickyapi.bukkit.book.chat; import com.google.gson.JsonArray; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import lombok.Getter; import lombok.NonNull; import lombok.Setter; -import net.md_5.bungee.api.chat.BaseComponent; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/Style.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/Style.java new file mode 100644 index 00000000..69b06030 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/Style.java @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.bukkit.book.chat; + +import lombok.Data; +import org.bukkit.ChatColor; + +@Data +public class Style { + boolean obfuscated; + boolean bold; + boolean italic; + boolean underline; + boolean strikethrough; +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponentWriter.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/JsonComponentWriter.java similarity index 91% rename from src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponentWriter.java rename to src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/JsonComponentWriter.java index ce3e02f3..bf489ba6 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/JsonComponentWriter.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/JsonComponentWriter.java @@ -2,12 +2,12 @@ * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ -package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; +package com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions; -import com.dumbdogdiner.stickyapi.common.book.chat.ClickEvent; -import com.dumbdogdiner.stickyapi.common.book.chat.ComponentColor; -import com.dumbdogdiner.stickyapi.common.book.chat.HoverEvent; -import com.dumbdogdiner.stickyapi.common.book.chat.JsonComponent; +import com.dumbdogdiner.stickyapi.bukkit.book.chat.ClickEvent; +import com.dumbdogdiner.stickyapi.bukkit.book.chat.ComponentColor; +import com.dumbdogdiner.stickyapi.bukkit.book.chat.HoverEvent; +import com.dumbdogdiner.stickyapi.bukkit.book.chat.JsonComponent; import lombok.Getter; import java.util.Stack; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCBlockParser.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCBlockParser.java new file mode 100644 index 00000000..bcd4ea8e --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCBlockParser.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions; + +import org.commonmark.node.Block; +import org.commonmark.parser.block.AbstractBlockParser; +import org.commonmark.parser.block.BlockContinue; +import org.commonmark.parser.block.ParserState; + +public class MCBlockParser extends AbstractBlockParser { + @Override + public Block getBlock() { + return null; + } + + @Override + public BlockContinue tryContinue(ParserState parserState) { + return null; + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java new file mode 100644 index 00000000..06ba1654 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions; + +import com.dumbdogdiner.stickyapi.bukkit.book.chat.ComponentColor; +import org.bukkit.ChatColor; +import org.commonmark.node.*; +import org.commonmark.parser.delimiter.DelimiterProcessor; +import org.commonmark.parser.delimiter.DelimiterRun; + +import java.util.Iterator; +import java.util.Locale; +import java.util.concurrent.atomic.AtomicReference; +import java.util.regex.Pattern; + +/** + * A delimiter processor for custom name nbt. + */ +public class MCColorFormatDelimiterProcessor implements DelimiterProcessor { + private static final Pattern COLOR_PATTERN = Pattern.compile("^([a-z_]+|#[0-9A-Fa-f]{6})(\\s*(?:\\s[\\S\\s]+)?)$"); + + @Override + public char getOpeningCharacter() { + return '$'; + } + + @Override + public char getClosingCharacter() { + return '$'; + } + + @Override + public int getMinLength() { + return 1; + } + + @Override + public int process(DelimiterRun opener, DelimiterRun closing) { + if(opener.length() >= 1 && closing.length() == 1) { + SourceSpans s = new SourceSpans(); + s.addAllFrom(opener.getOpeners(opener.length())); + + ComponentColor cc = ComponentColor.GOLD; + Node n = opener.getOpener().getNext(); + //for (Node n : Nodes.between(opener.getOpener(), closing.getCloser())) { + if (n instanceof Text) { + String literal = ((Text) n).getLiteral(); + if (literal.charAt(0) == '#' && literal.length() == 7) { + cc = ComponentColor.fromText(literal.substring(1)); + //break; + } else { + System.out.println(literal); + if(ChatColor.getByChar(literal.toLowerCase().charAt(0)) == null) + return 0; + System.out.println(literal); + cc = ComponentColor.fromColor(ChatColor.getByChar(literal.toLowerCase().charAt(0)).asBungee().getColor()); + } + s.addAll(n.getSourceSpans()); + } + + MCColorNode mcn = new MCColorNode(cc); + mcn.setSourceSpans(s.getSourceSpans()); + opener.getOpener().insertAfter(mcn); + + //} + +/* + SourceSpans sourceSpans = new SourceSpans(); + + + Node firstNext = opener.getNext(); + if (firstNext instanceof Text) { + String literal = ((Text) firstNext).getLiteral(); + Matcher match = COLOR_PATTERN.matcher(literal); + if (match.matches()) { + ((Text) firstNext).setLiteral(match.group(2).stripLeading()); + ComponentColor color = ComponentColor.fromText(match.group(1)); + if (color != null) { + MCColorNode colorNode = new MCColorNode(color); + Node next; + for (Node n = opener.getNext(); n != null && n != closer; n = next) { + next = n.getNext(); + colorNode.appendChild(n); + } + opener.insertAfter(colorNode); + } + } + }*/ + return 1; + } else + return 0; + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCColorNode.java similarity index 78% rename from src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java rename to src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCColorNode.java index 3f63b3fc..964c46cd 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorNode.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCColorNode.java @@ -2,9 +2,9 @@ * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ -package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; +package com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions; -import com.dumbdogdiner.stickyapi.common.book.chat.ComponentColor; +import com.dumbdogdiner.stickyapi.bukkit.book.chat.ComponentColor; import lombok.Getter; import org.commonmark.node.CustomNode; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCFormatExtension.java similarity index 65% rename from src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java rename to src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCFormatExtension.java index cea94cc5..e20ce27f 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCFormatExtension.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCFormatExtension.java @@ -2,10 +2,13 @@ * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ -package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; +package com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions; +import org.commonmark.ext.gfm.strikethrough.internal.StrikethroughDelimiterProcessor; import org.commonmark.parser.Parser; + + public class MCFormatExtension implements Parser.ParserExtension { private MCFormatExtension(){} @@ -16,6 +19,9 @@ public static MCFormatExtension create() { @Override public void extend(Parser.Builder parserBuilder) { parserBuilder.customDelimiterProcessor(new MCColorFormatDelimiterProcessor()); + //parserBuilder.customDelimiterProcessor(new StrikethroughDelimiterProcessor()); + /*parserBuilder.postProcessor(null); + parserBuilder.postProcessor(null);*/ // TODO add a parser here that does the line splitting } } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MarkdownJsonRenderer.java similarity index 93% rename from src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java rename to src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MarkdownJsonRenderer.java index af7c4594..d4d80e85 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MarkdownJsonRenderer.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MarkdownJsonRenderer.java @@ -2,11 +2,11 @@ * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ -package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; +package com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions; -import com.dumbdogdiner.stickyapi.common.book.chat.ClickEvent; -import com.dumbdogdiner.stickyapi.common.book.chat.HoverEvent; -import com.dumbdogdiner.stickyapi.common.book.chat.JsonComponent; +import com.dumbdogdiner.stickyapi.bukkit.book.chat.ClickEvent; +import com.dumbdogdiner.stickyapi.bukkit.book.chat.HoverEvent; +import com.dumbdogdiner.stickyapi.bukkit.book.chat.JsonComponent; import org.commonmark.node.*; import org.commonmark.renderer.NodeRenderer; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/package-info.java new file mode 100644 index 00000000..7bba833c --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/package-info.java @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ + +/** + * The code in this package is for book parsing of/with markdown, and is unfinished. For now, it shall be ignored. + * It will be finished or removed in a future update. + */ +@OnHold +package com.dumbdogdiner.stickyapi.bukkit.book; + +import com.dumbdogdiner.stickyapi.annotation.OnHold; \ No newline at end of file diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java index 794e993e..c2a232a7 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java @@ -29,7 +29,7 @@ @SuppressWarnings({"UnusedReturnValue", "unused"}) @Accessors(chain = true) public class BookGenerator { - private final JsonArray pages = new JsonArray(); + private JsonArray pages = new JsonArray(); /** The generation of the book. */ @Getter @Setter private @NonNull BookMeta.Generation generation = BookMeta.Generation.ORIGINAL; @@ -54,6 +54,42 @@ public BookGenerator(Material material) { this.bookType = material; } + + /** + * Creates a new BookGenerator from a given JsonObject, representing a book, which can + * be obtained in whatever way you want. + * @param bookObject A JSON object containing a JsonArray of valid Pages; If a {@link Material#WRITTEN_BOOK} is desired, it must contain a title, author, and optionally, a Generation (an integer with the value of 0, 1, 2, or 3, with 0 being the default) + * @return a {@link BookGenerator} with the specified pages; if a title and author are both specified, it will be a {@link Material#WRITTEN_BOOK}, otherwise it will be a {@link Material#WRITABLE_BOOK} + */ + public static BookGenerator fromJson(JsonObject bookObject) { + BookGenerator b; + + if(bookObject.has("author") && bookObject.has("title")) { + b = new BookGenerator(Material.WRITTEN_BOOK); + b.author = bookObject.get("author").getAsString(); + b.title = bookObject.get("title").getAsString(); + if(bookObject.has("generation")) + switch (bookObject.get("generation").getAsInt()){ + case 1: + b.generation = BookMeta.Generation.COPY_OF_ORIGINAL; + break; + case 2: + b.generation = BookMeta.Generation.COPY_OF_COPY; + break; + case 3: + b.generation = BookMeta.Generation.TATTERED; + break; + case 0: + default: + b.generation = BookMeta.Generation.ORIGINAL; + } + } else { + b = new BookGenerator(Material.WRITABLE_BOOK); + } + b.pages = bookObject.get("pages").getAsJsonArray(); + return b; + } + /** * Add some pages to the book. May fail with {@link IllegalStateException} if the book is full or fills up. * @param pages Pages to add @@ -107,7 +143,7 @@ public ItemStack toItemStack(int qty) { * TODO: Does not account for characters per page or packet size at this time. */ public float percentFull() { - return (float)pages.size() / (float)BookUtil.PAGES_PER_BOOK; + return (float)pages.size() / (float) BookUtil.PAGES_PER_BOOK; } /** diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/MarkdownBookGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/MarkdownBookGenerator.java deleted file mode 100644 index f9291d3a..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/MarkdownBookGenerator.java +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.bukkit.item.generator; - -public class MarkdownBookGenerator { -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java deleted file mode 100644 index 19287751..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.book.commonmarkextensions; - -import com.dumbdogdiner.stickyapi.common.book.chat.ComponentColor; -import org.commonmark.node.Node; -import org.commonmark.node.Text; -import org.commonmark.parser.delimiter.DelimiterProcessor; -import org.commonmark.parser.delimiter.DelimiterRun; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * A delimiter processor for custom name nbt. - */ -public class MCColorFormatDelimiterProcessor implements DelimiterProcessor { - private static final Pattern COLOR_PATTERN = Pattern.compile("^([a-z_]+|#[0-9A-Fa-f]{6})(\\s*(?:\\s[\\S\\s]+)?)$"); - - @Override - public char getOpeningCharacter() { - return '$'; - } - - @Override - public char getClosingCharacter() { - return '$'; - } - - @Override - public int getMinLength() { - return 1; - } - - @Override - public int getDelimiterUse(DelimiterRun opener, DelimiterRun closer) { - if (opener.length() >= 1 && closer.length() >= 1) { - return 1; - } else { - return 0; - } - } - - @Override - public void process(Text opener, Text closer, int delimiterUse) { - Node firstNext = opener.getNext(); - if (firstNext instanceof Text) { - String literal = ((Text) firstNext).getLiteral(); - Matcher match = COLOR_PATTERN.matcher(literal); - if (match.matches()) { - ((Text) firstNext).setLiteral(match.group(2).stripLeading()); - ComponentColor color = ComponentColor.fromText(match.group(1)); - if (color != null) { - MCColorNode colorNode = new MCColorNode(color); - Node next; - for (Node n = opener.getNext(); n != null && n != closer; n = next) { - next = n.getNext(); - colorNode.appendChild(n); - } - opener.insertAfter(colorNode); - } - } - } - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/book/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/common/book/package-info.java deleted file mode 100644 index fad7c999..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/book/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.book; \ No newline at end of file diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index 54e9f3cf..b0743937 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -11,7 +11,7 @@ import java.util.List; import java.util.regex.Pattern; -import com.dumbdogdiner.stickyapi.common.book.chat.JsonComponent; +import com.dumbdogdiner.stickyapi.bukkit.book.chat.JsonComponent; import com.google.gson.Gson; import lombok.NonNull; import org.commonmark.node.Document; diff --git a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookGeneratorTest.java b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookGeneratorTest.java new file mode 100644 index 00000000..8dafba4c --- /dev/null +++ b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookGeneratorTest.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.bukkit.book; + +import com.dumbdogdiner.stickyapi.bukkit.item.generator.BookGenerator; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.junit.jupiter.api.Test; + +import java.awt.print.Book; +import java.io.InputStream; +import java.io.InputStreamReader; + +public class BookGeneratorTest { + @Test + public void testJsonBuild(){ + InputStream rulebookStream = BookGeneratorTest.class.getResourceAsStream("/rulebook.json"); + JsonObject jso = (JsonObject) JsonParser.parseReader(new InputStreamReader(rulebookStream)); + System.out.println(jso.toString()); + BookGenerator bg = BookGenerator.fromJson(jso); + System.out.println(bg.generateNbtString()); + } +} diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/book/BookTests.java b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookTests.java similarity index 85% rename from src/test/java/com/dumbdogdiner/stickyapi/common/book/BookTests.java rename to src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookTests.java index 5694041f..f6b65fdd 100644 --- a/src/test/java/com/dumbdogdiner/stickyapi/common/book/BookTests.java +++ b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookTests.java @@ -2,32 +2,31 @@ * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ -package com.dumbdogdiner.stickyapi.common.book; +package com.dumbdogdiner.stickyapi.bukkit.book; import com.dumbdogdiner.stickyapi.bukkit.item.generator.BookGenerator; -import com.dumbdogdiner.stickyapi.common.book.chat.JsonComponent; -import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.JsonComponentWriter; -import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.MCFormatExtension; -import com.dumbdogdiner.stickyapi.common.book.commonmarkextensions.MarkdownJsonRenderer; +import com.dumbdogdiner.stickyapi.bukkit.book.chat.JsonComponent; +import com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions.JsonComponentWriter; +import com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions.MCFormatExtension; +import com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions.MarkdownJsonRenderer; import com.dumbdogdiner.stickyapi.common.util.BookUtil; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; import lombok.SneakyThrows; import org.bukkit.Material; import org.commonmark.node.Document; import org.commonmark.parser.Parser; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; -import java.util.ArrayList; import java.util.List; +@Disabled public class BookTests{ private static final String BOOK_FILENAME = "/rulebook.md"; private static Reader bookReader; @@ -48,6 +47,8 @@ static void tearDown() throws IOException { System.gc(); } + + @Disabled @SneakyThrows @Test public void testParser() { diff --git a/src/test/resources/rulebook.json b/src/test/resources/rulebook.json new file mode 100644 index 00000000..041a6359 --- /dev/null +++ b/src/test/resources/rulebook.json @@ -0,0 +1,25 @@ +{ + "pages": [ + [ + { + "text": "Page 1\\nI'm text in " + }, + { + "text": "bold", + "bold": true + }, + { + "text": " owo", + "color": "reset" + } + ], + [ + { + "text": "red text in page 2", + "color": "dark_red" + } + ] + ], + "title": "a booky book", + "author": "rodwuffy" +} \ No newline at end of file diff --git a/src/test/resources/rulebook.md b/src/test/resources/rulebook.md index dc56fdb1..16354a8b 100644 --- a/src/test/resources/rulebook.md +++ b/src/test/resources/rulebook.md @@ -1,6 +1,6 @@ # Dumb Dog Diner MC Survival Handbook -## $red The Rules$ +## $c The Rules$ 1. Absolutely no griefing, theft, or intentional distress! 2. No cheating/hacking allowed. Optifine and similar are okay. @@ -11,7 +11,7 @@ --- -## $dark_green Gameplay$ +## $2 Gameplay$ The world border for all worlds is 8,000 blocks from the center. Because of how $dark_red Nether Portal$ travel works, you will not be able to light them past 1,000 blocks @@ -23,7 +23,7 @@ drop on the ground! You can have up to 3 $red Death Chests$ at a time. --- -## $dark_aqua Trading$ +## $3 Trading$ We use chest chops for player to trade good for $gold Coins$. Coins may be earned through selling goods to other players, paying/receiving money for a From 2123e7d0a3df2514ad15698b5e61eb06968b8746 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sun, 31 Jan 2021 12:14:59 -0700 Subject: [PATCH 37/79] Requested edits --- ...ava => ColorFormatDelimiterProcessor.java} | 2 +- .../commonmarkextensions/MCBlockParser.java | 22 ------------------- ...ension.java => ParserFormatExtension.java} | 11 +++++----- .../stickyapi/common/util/BookUtil.java | 11 +++++----- .../stickyapi/bukkit/book/BookTests.java | 4 ++-- 5 files changed, 14 insertions(+), 36 deletions(-) rename src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/{MCColorFormatDelimiterProcessor.java => ColorFormatDelimiterProcessor.java} (97%) delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCBlockParser.java rename src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/{MCFormatExtension.java => ParserFormatExtension.java} (62%) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/ColorFormatDelimiterProcessor.java similarity index 97% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java rename to src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/ColorFormatDelimiterProcessor.java index 06ba1654..7087f601 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCColorFormatDelimiterProcessor.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/ColorFormatDelimiterProcessor.java @@ -18,7 +18,7 @@ /** * A delimiter processor for custom name nbt. */ -public class MCColorFormatDelimiterProcessor implements DelimiterProcessor { +public class ColorFormatDelimiterProcessor implements DelimiterProcessor { private static final Pattern COLOR_PATTERN = Pattern.compile("^([a-z_]+|#[0-9A-Fa-f]{6})(\\s*(?:\\s[\\S\\s]+)?)$"); @Override diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCBlockParser.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCBlockParser.java deleted file mode 100644 index bcd4ea8e..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCBlockParser.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions; - -import org.commonmark.node.Block; -import org.commonmark.parser.block.AbstractBlockParser; -import org.commonmark.parser.block.BlockContinue; -import org.commonmark.parser.block.ParserState; - -public class MCBlockParser extends AbstractBlockParser { - @Override - public Block getBlock() { - return null; - } - - @Override - public BlockContinue tryContinue(ParserState parserState) { - return null; - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCFormatExtension.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/ParserFormatExtension.java similarity index 62% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCFormatExtension.java rename to src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/ParserFormatExtension.java index e20ce27f..ed3e4514 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCFormatExtension.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/ParserFormatExtension.java @@ -4,21 +4,20 @@ */ package com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions; -import org.commonmark.ext.gfm.strikethrough.internal.StrikethroughDelimiterProcessor; import org.commonmark.parser.Parser; -public class MCFormatExtension implements Parser.ParserExtension { - private MCFormatExtension(){} +public class ParserFormatExtension implements Parser.ParserExtension { + private ParserFormatExtension(){} - public static MCFormatExtension create() { - return new MCFormatExtension(); + public static ParserFormatExtension create() { + return new ParserFormatExtension(); } @Override public void extend(Parser.Builder parserBuilder) { - parserBuilder.customDelimiterProcessor(new MCColorFormatDelimiterProcessor()); + parserBuilder.customDelimiterProcessor(new ColorFormatDelimiterProcessor()); //parserBuilder.customDelimiterProcessor(new StrikethroughDelimiterProcessor()); /*parserBuilder.postProcessor(null); parserBuilder.postProcessor(null);*/ diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index b0743937..77cc0993 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -12,6 +12,7 @@ import java.util.regex.Pattern; import com.dumbdogdiner.stickyapi.bukkit.book.chat.JsonComponent; +import com.google.common.base.Preconditions; import com.google.gson.Gson; import lombok.NonNull; import org.commonmark.node.Document; @@ -74,11 +75,9 @@ private static class WidthEntry { * @throws IllegalArgumentException if the character is out of range */ public static int getCharacterWidth(char c) { - Integer width = widths.get(c); - if (width != null) { - return width; - } - throw new IllegalArgumentException("Unsupported character: " + c + " code: " + String.format("%04x", (int) c)); + Preconditions.checkArgument(widths.containsKey(c), "Unsupported character: " + c + " code: " + String.format("%04x", (int) c)); + + return widths.get(c); } /** @@ -86,6 +85,8 @@ public static int getCharacterWidth(char c) { * * @param origComponent The component to split into pages * @return A list of JsonComponents, one for each page + * + * TODO There's definately a better way to do this */ public static List splitBookPages(@NonNull JsonComponent origComponent) { List lines = wrapLines(origComponent, HALF_PIXELS_PER_LINE); diff --git a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookTests.java b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookTests.java index f6b65fdd..1a7c2228 100644 --- a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookTests.java +++ b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookTests.java @@ -7,7 +7,7 @@ import com.dumbdogdiner.stickyapi.bukkit.item.generator.BookGenerator; import com.dumbdogdiner.stickyapi.bukkit.book.chat.JsonComponent; import com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions.JsonComponentWriter; -import com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions.MCFormatExtension; +import com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions.ParserFormatExtension; import com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions.MarkdownJsonRenderer; import com.dumbdogdiner.stickyapi.common.util.BookUtil; import com.google.gson.Gson; @@ -53,7 +53,7 @@ static void tearDown() throws IOException { @Test public void testParser() { Parser.Builder parserBuilder = Parser.builder(); - MCFormatExtension.create().extend(parserBuilder); + ParserFormatExtension.create().extend(parserBuilder); Parser cmParser = parserBuilder.build(); List sections = BookUtil.splitDocumentByBreaks( (Document)cmParser From 39f446db82395d9de4be5642ada890919c413827 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sun, 31 Jan 2021 12:15:49 -0700 Subject: [PATCH 38/79] Bump version --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index db043adb..036173f2 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ jacoco { group = 'com.dumbdogdiner' -version = '2.1.0' +version = '2.2.0' // License Plugin Options license { From 2a4685d1989e8bd479500dcc30b08faf390cb0d7 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sun, 31 Jan 2021 22:22:19 -0700 Subject: [PATCH 39/79] Finish JSON format, update build.gradle, remove commonmark from branch --- build.gradle | 20 +- .../bukkit/book/chat/ClickEvent.java | 191 ---------------- .../bukkit/book/chat/ComponentColor.java | 77 ------- .../bukkit/book/chat/HoverEvent.java | 137 ------------ .../bukkit/book/chat/JsonComponent.java | 143 ------------ .../stickyapi/bukkit/book/chat/Style.java | 17 -- .../ColorFormatDelimiterProcessor.java | 95 -------- .../JsonComponentWriter.java | 143 ------------ .../commonmarkextensions/MCColorNode.java | 21 -- .../MarkdownJsonRenderer.java | 158 -------------- .../ParserFormatExtension.java | 26 --- .../stickyapi/bukkit/book/package-info.java | 13 -- .../bukkit/item/BookAndQuillBuilder.java | 145 +++++++++++++ .../bukkit/item/WrittenBookBuilder.java | 204 ++++++++++++++++++ .../bukkit/item/generator/BookGenerator.java | 170 --------------- .../stickyapi/common/util/BookUtil.java | 132 +----------- .../stickyapi/common/util/NumberUtil.java | 1 + .../stickyapi/common/util/StringUtil.java | 46 +++- .../bukkit/book/BookGeneratorTest.java | 26 --- .../stickyapi/bukkit/book/BookTests.java | 80 ------- .../bukkit/item/BookBuilderTest.java | 21 ++ .../bukkit/item/WrittenBookBuilderTest.java | 78 +++++++ src/test/resources/book1.json | 25 +++ src/test/resources/rulebook.json | 26 +-- 24 files changed, 533 insertions(+), 1462 deletions(-) delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/ClickEvent.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/ComponentColor.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/HoverEvent.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/JsonComponent.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/Style.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/ColorFormatDelimiterProcessor.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/JsonComponentWriter.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCColorNode.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MarkdownJsonRenderer.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/ParserFormatExtension.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/package-info.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/generator/BookGenerator.java delete mode 100644 src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookGeneratorTest.java delete mode 100644 src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookTests.java create mode 100644 src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/BookBuilderTest.java create mode 100644 src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilderTest.java create mode 100644 src/test/resources/book1.json diff --git a/build.gradle b/build.gradle index 036173f2..4f2ce808 100644 --- a/build.gradle +++ b/build.gradle @@ -68,10 +68,6 @@ dependencies { implementation 'com.google.code.gson:gson:2.8.6' implementation 'io.github.classgraph:classgraph:4.8.98' implementation 'com.github.seancfoley:ipaddress:5.3.3' - - // CommonMark for Book Text Utils - implementation 'org.commonmark:commonmark:0.17.0' - implementation 'org.commonmark:commonmark-ext-gfm-strikethrough:0.17.0' // Tests - JUnit 5 testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0") @@ -79,6 +75,10 @@ dependencies { // Tests - Mocking Suite (eg. mocking Bukkit for tests) testImplementation("org.mockito:mockito-core:3.7.7") +// +// // Mocked bukkit +// testImplementation 'com.github.seeseemelk:MockBukkit-v1.16:0.5.0' +// testImplementation group: 'it.unimi.dsi', name: 'fastutil', version: '8.2.1' } test { @@ -109,7 +109,6 @@ task sources(type: Jar, dependsOn: classes) { // Some environments (such as the builder image) do not use UTF-8 as the default encoding! // This sets UTF-8 as the encoding for the following tasks: delombok, compileJava, compileTestJava and javadoc. delombok.encoding = "UTF-8" - compileJava.options.encoding = "UTF-8" compileTestJava.options.encoding = "UTF-8" javadoc.options.encoding = "UTF-8" @@ -160,12 +159,13 @@ task copyMCFontExtractor(type: Copy) { // Run the license formatter and font data copier before compiling the source code. tasks.compileJava.dependsOn licenseFormatMain, licenseFormatTest, copyMCFontExtractor +tasks.build.dependsOn sources +tasks.publish.dependsOn build - -tasks.publish.dependsOn build, sources - - - +task rebuild{ + dependsOn clean + finalizedBy build +} publishing { repositories { diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/ClickEvent.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/ClickEvent.java deleted file mode 100644 index 1fdbbe35..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/ClickEvent.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.bukkit.book.chat; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import lombok.Getter; -import lombok.NonNull; -import lombok.experimental.UtilityClass; - -/** - * An event that is fired when text associated with this event is clicked. - */ -public abstract class ClickEvent { - private ClickEvent() {} // seal this class - - /** - * Convert the ClickEvent into JSON representation used in-game. - * @return {@link JsonElement} - */ - public abstract @NonNull JsonElement toJson(); - - /** - * Create a copy of this ClickEvent. - * @return {@link ClickEvent} - */ - @Override - public abstract @NonNull ClickEvent clone(); - - /** - * When clicked, displays a prompt to open a URL in the player's browser. - */ - public final static class OpenUrl extends ClickEvent { - /** The URL to open. */ - @Getter - private final @NonNull String url; - - public OpenUrl(@NonNull String url) { - this.url = url; - } - - @Override - public JsonElement toJson() { - JsonObject object = new JsonObject(); - object.addProperty("action", "open_url"); - object.addProperty("value", url); - return object; - } - - @Override - public OpenUrl clone() { - return new OpenUrl(url); - } - } - - /** - * When clicked, opens a file on the player's computer. This event can only be used by messages generated by the - * game, and will not function otherwise. - */ - public final static class OpenFile extends ClickEvent { - /** The path to open. */ - @Getter - private final @NonNull String path; - - public OpenFile(@NonNull String path) { - this.path = path; - } - - @Override - public JsonElement toJson() { - JsonObject object = new JsonObject(); - object.addProperty("action", "open_file"); - object.addProperty("value", path); - return object; - } - - @Override - public OpenFile clone() { - return new OpenFile(path); - } - } - - /** - * When clicked, executes the command as if the player said it in chat, either sending a message or executing a - * command. This can also be used to execute commands on signs, but only on the root component, with the slash - * omitted, and run by the server with @s set to the player. - */ - public final static class RunCommand extends ClickEvent { - /** The command or message to run. */ - @Getter - private final @NonNull String command; - - public RunCommand(@NonNull String command) { - this.command = command; - } - - @Override - public JsonElement toJson() { - JsonObject object = new JsonObject(); - object.addProperty("action", "run_command"); - object.addProperty("value", command); - return object; - } - - @Override - public RunCommand clone() { - return new RunCommand(command); - } - } - - /** - * Behaves similarly to {@link RunCommand}, but does not actually execute the command, instead opening the chat box - * and pasting the command there. - */ - public final static class SuggestCommand extends ClickEvent { - /** The command to suggest. */ - @Getter - private final @NonNull String command; - - public SuggestCommand(@NonNull String command) { - this.command = command; - } - - @Override - public JsonElement toJson() { - JsonObject object = new JsonObject(); - object.addProperty("action", "suggest_command"); - object.addProperty("value", command); - return object; - } - - @Override - public SuggestCommand clone() { - return new SuggestCommand(command); - } - } - - /** - * When clicked, jumps to a given page. Obviously only works in books. - */ - public final static class ChangePage extends ClickEvent { - /** The page to go to. */ - @Getter - private final int page; - - public ChangePage(int page) { - this.page = page; - } - - @Override - public JsonElement toJson() { - JsonObject object = new JsonObject(); - object.addProperty("action", "change_page"); - object.addProperty("value", page); - return object; - } - - @Override - public ChangePage clone() { - return new ChangePage(page); - } - } - - /** - * When clicked, text is copied to the clipboard. - */ - public final static class CopyToClipboard extends ClickEvent { - /** The text to copy. */ - @Getter - private final @NonNull String text; - - public CopyToClipboard(@NonNull String text) { - this.text = text; - } - - @Override - public JsonElement toJson() { - JsonObject object = new JsonObject(); - object.addProperty("action", "copy_to_clipboard"); - object.addProperty("value", text); - return object; - } - - @Override - public CopyToClipboard clone() { - return new CopyToClipboard(text); - } - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/ComponentColor.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/ComponentColor.java deleted file mode 100644 index 92a7124c..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/ComponentColor.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.bukkit.book.chat; - -import lombok.Getter; -import lombok.NonNull; -import org.jetbrains.annotations.Nullable; - -import java.awt.*; -import java.util.HashMap; -import java.util.regex.Pattern; - -/** - * A color used in text components. - * TODO: make this a lot nicer and less hacky - */ -public class ComponentColor { - private static final HashMap VALID_NAMED_COLORS = new HashMap<>(); - - public static final ComponentColor RESET = registerValid("reset"); - public static final ComponentColor BLACK = registerValid("black"); - public static final ComponentColor DARK_BLUE = registerValid("dark_blue"); - public static final ComponentColor DARK_GREEN = registerValid("dark_green"); - public static final ComponentColor DARK_AQUA = registerValid("dark_aqua"); - public static final ComponentColor DARK_RED = registerValid("dark_red"); - public static final ComponentColor DARK_PURPLE = registerValid("dark_purple"); - public static final ComponentColor GOLD = registerValid("gold"); - public static final ComponentColor GRAY = registerValid("gray"); - public static final ComponentColor DARK_GRAY = registerValid("dark_gray"); - public static final ComponentColor BLUE = registerValid("blue"); - public static final ComponentColor GREEN = registerValid("green"); - public static final ComponentColor AQUA = registerValid("aqua"); - public static final ComponentColor RED = registerValid("red"); - public static final ComponentColor LIGHT_PURPLE = registerValid("light_purple"); - public static final ComponentColor YELLOW = registerValid("yellow"); - public static final ComponentColor WHITE = registerValid("white"); - - private static final Pattern HEX_PATTERN = Pattern.compile("^#[0-9A-Fa-f]{6}$"); - - /** The text representation used for the color. */ - @Getter - private final @NonNull String text; - - private ComponentColor(String text) { - this.text = text; - } - - private ComponentColor(Color color) { - this.text = String.format("#%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue()); - } - - private static ComponentColor registerValid(String text) { - ComponentColor x = new ComponentColor(text); - VALID_NAMED_COLORS.put(text, x); - return x; - } - - /** - * Get or create a color from the given string, or null if the string is not valid. - * @param text The text for the color. Can be a 6-digit hex color, one of the sixteen named colors, or "reset". - * @return {@link ComponentColor} - */ - public static @Nullable ComponentColor fromText(@NonNull String text) { - return HEX_PATTERN.matcher(text).matches() ? new ComponentColor(text) : VALID_NAMED_COLORS.get(text); - } - - /** - * Create a color from the given Color object. - * @param color The color object to generate the color from. - * @return {@link ComponentColor} - */ - public static @NonNull ComponentColor fromColor(@NonNull Color color) { - return new ComponentColor(color); - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/HoverEvent.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/HoverEvent.java deleted file mode 100644 index f8b840ad..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/HoverEvent.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.bukkit.book.chat; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import lombok.Getter; -import lombok.NonNull; -import org.bukkit.entity.EntityType; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Nullable; -import java.util.UUID; - -/** - * An event that is fired when text associated with this event is hovered over. - */ -public abstract class HoverEvent { - private HoverEvent() {} // seal this class - - /** - * Convert the HoverEvent into JSON representation used in-game. - * @return {@link JsonElement} - */ - public abstract @NonNull JsonElement toJson(); - - /** - * Create a copy of this HoverEvent. - * @return {@link HoverEvent} - */ - public abstract @NonNull HoverEvent duplicate(); - - /** - * When hovered over, show some text. - */ - public final static class ShowText extends HoverEvent { - /** The text to show when the associated component is hovered over. */ - @Getter - private final @NonNull JsonComponent component; - - public ShowText(@NonNull JsonComponent component) { - this.component = component; - } - - @Override - public JsonElement toJson() { - JsonObject object = new JsonObject(); - object.addProperty("action", "show_text"); - object.add("contents", component.toJson()); - return object; - } - - @Override - public ShowText duplicate() { - return new ShowText(component); - } - } - - /** - * When hovered over, show the tooltip of an item. - */ - public final static class ShowItem extends HoverEvent { - /** The item to reference for the tooltip. */ - @Getter - private final @NonNull ItemStack item; - /** Extra NBT to apply to this item stack. */ - @Getter - private final @Nullable String extraNBT; // might be possible to get this from the item but would need lots of nms - - public ShowItem(@NonNull ItemStack item, @Nullable String extraNBT) { - this.item = item; - this.extraNBT = extraNBT; - } - - @Override - public JsonElement toJson() { - JsonObject object = new JsonObject(); - object.addProperty("action", "show_item"); - JsonObject contents = new JsonObject(); - contents.addProperty("id", item.getType().getKey().toString()); - if (item.getAmount() != 1) { - contents.addProperty("count", item.getAmount()); - } - if (extraNBT != null) { - contents.addProperty("tag", extraNBT); - } - object.add("contents", contents); - return object; - } - - @Override - public ShowItem duplicate() { - return new ShowItem(item, extraNBT); - } - } - - /** - * When hovered over, show data about an entity. - */ - public final static class ShowEntity extends HoverEvent { - /** Text to display as the name of the entity. */ - @Getter - private final @Nullable JsonComponent name; - /** The type of the entity. */ - @Getter - private final @NonNull EntityType entityType; - /** The ID of the entity. */ - @Getter - private final @NonNull UUID entityId; - - public ShowEntity(@Nullable JsonComponent name, @NonNull EntityType entityType, @NonNull UUID entityId) { - this.name = name; - this.entityType = entityType; - this.entityId = entityId; - } - - @Override - public JsonElement toJson() { - JsonObject object = new JsonObject(); - object.addProperty("action", "show_entity"); - JsonObject contents = new JsonObject(); - if (name != null) { - contents.add("name", name.toJson()); - } - contents.addProperty("type", entityType.getKey().toString()); - contents.addProperty("id", entityId.toString()); - object.add("contents", contents); - return object; - } - - @Override - public ShowEntity duplicate() { - return new ShowEntity(name, entityType, entityId); - } - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/JsonComponent.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/JsonComponent.java deleted file mode 100644 index b83fceb4..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/JsonComponent.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.bukkit.book.chat; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import lombok.Getter; -import lombok.NonNull; -import lombok.Setter; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * A text component that can be converted to JSON. Differs slightly from BaseComponent, and is not part of the UML - */ -public class JsonComponent { - @Getter @Setter - private @NonNull String text = ""; - @Getter @Setter - private @Nullable Boolean bold = null; - @Getter @Setter - private @Nullable Boolean italic = null; - @Getter @Setter - private @Nullable Boolean underlined = null; - @Getter @Setter - private @Nullable Boolean strikethrough = null; - @Getter @Setter - private @Nullable Boolean obfuscated = null; - @Getter @Setter - private @Nullable ComponentColor color = null; - @Getter @Setter - private @Nullable ClickEvent clickEvent = null; - @Getter @Setter - private @Nullable HoverEvent hoverEvent = null; - @Getter - private final List children = new ArrayList<>(); - - @SuppressWarnings("deprecation") - public JsonComponent(){ - // Need to find out why this is used and stuffs - } - @SuppressWarnings("deprecation") - public JsonComponent(@NonNull String text) { - this.text = text; - } - - /** - * Converts the component into JSON. - * @return {@link com.google.gson.JsonObject} - */ - public JsonObject toJson() { - JsonObject object = new JsonObject(); - object.addProperty("text", text); - if (bold != null) object.addProperty("bold", bold); - if (italic != null) object.addProperty("italic", italic); - if (underlined != null) object.addProperty("underlined", underlined); - if (strikethrough != null) object.addProperty("strikethrough", strikethrough); - if (obfuscated != null) object.addProperty("obfuscated", obfuscated); - if (color != null) { - object.addProperty("color", color.getText()); - } - if (clickEvent != null) { - object.add("clickEvent", clickEvent.toJson()); - } - if (hoverEvent != null) { - object.add("hoverEvent", hoverEvent.toJson()); - } - if (!children.isEmpty()) { - JsonArray extra = new JsonArray(); - for (JsonComponent component : children) { - extra.add(component.toJson()); - } - object.add("extra", extra); - } - return object; - } - - /** - * Flatten a JsonComponent into an array of JsonComponents with no children. - * @return {@link java.util.List} - */ - public List flatten() { - return flattenWithParents(new ArrayList<>()); - } - - private List flattenWithParents(List parents) { - List components = new ArrayList<>(); - if (!text.equals("")) { - JsonComponent flatComponent = new JsonComponent(text); - flatComponent.setBold(orFromList(bold, parents, JsonComponent::getBold)); - flatComponent.setItalic(orFromList(italic, parents, JsonComponent::getItalic)); - flatComponent.setUnderlined(orFromList(underlined, parents, JsonComponent::getUnderlined)); - flatComponent.setStrikethrough(orFromList(strikethrough, parents, JsonComponent::getStrikethrough)); - flatComponent.setObfuscated(orFromList(obfuscated, parents, JsonComponent::getObfuscated)); - flatComponent.setColor(orFromList(color, parents, JsonComponent::getColor)); - flatComponent.setClickEvent(orFromList(clickEvent, parents, JsonComponent::getClickEvent)); - flatComponent.setHoverEvent(orFromList(hoverEvent, parents, JsonComponent::getHoverEvent)); - components.add(flatComponent); - } - List newParents = Stream.concat(Stream.of(this), parents.stream()).collect(Collectors.toList()); - for (JsonComponent child : children) { - components.addAll(child.flattenWithParents(newParents)); - } - return components; - } - - private T orFromList(T t, List components, Function getter) { - if (t == null) { - return components.stream().map(getter).filter(Objects::nonNull).findFirst().orElse(null); - } else { - return t; - } - } - - /** - * Clone this component - * @return A clone of this component - */ - public JsonComponent duplicate() { - JsonComponent clone = new JsonComponent(text); - clone.bold = bold; - clone.italic = italic; - clone.underlined = underlined; - clone.strikethrough = strikethrough; - clone.obfuscated = obfuscated; - clone.color = color; - if (clickEvent != null) clone.clickEvent = clickEvent.clone(); - if (hoverEvent != null) clone.hoverEvent = hoverEvent.duplicate(); - for (JsonComponent child : children) { - clone.children.add(child.duplicate()); - } - return clone; - } - -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/Style.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/Style.java deleted file mode 100644 index 69b06030..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/chat/Style.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.bukkit.book.chat; - -import lombok.Data; -import org.bukkit.ChatColor; - -@Data -public class Style { - boolean obfuscated; - boolean bold; - boolean italic; - boolean underline; - boolean strikethrough; -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/ColorFormatDelimiterProcessor.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/ColorFormatDelimiterProcessor.java deleted file mode 100644 index 7087f601..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/ColorFormatDelimiterProcessor.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions; - -import com.dumbdogdiner.stickyapi.bukkit.book.chat.ComponentColor; -import org.bukkit.ChatColor; -import org.commonmark.node.*; -import org.commonmark.parser.delimiter.DelimiterProcessor; -import org.commonmark.parser.delimiter.DelimiterRun; - -import java.util.Iterator; -import java.util.Locale; -import java.util.concurrent.atomic.AtomicReference; -import java.util.regex.Pattern; - -/** - * A delimiter processor for custom name nbt. - */ -public class ColorFormatDelimiterProcessor implements DelimiterProcessor { - private static final Pattern COLOR_PATTERN = Pattern.compile("^([a-z_]+|#[0-9A-Fa-f]{6})(\\s*(?:\\s[\\S\\s]+)?)$"); - - @Override - public char getOpeningCharacter() { - return '$'; - } - - @Override - public char getClosingCharacter() { - return '$'; - } - - @Override - public int getMinLength() { - return 1; - } - - @Override - public int process(DelimiterRun opener, DelimiterRun closing) { - if(opener.length() >= 1 && closing.length() == 1) { - SourceSpans s = new SourceSpans(); - s.addAllFrom(opener.getOpeners(opener.length())); - - ComponentColor cc = ComponentColor.GOLD; - Node n = opener.getOpener().getNext(); - //for (Node n : Nodes.between(opener.getOpener(), closing.getCloser())) { - if (n instanceof Text) { - String literal = ((Text) n).getLiteral(); - if (literal.charAt(0) == '#' && literal.length() == 7) { - cc = ComponentColor.fromText(literal.substring(1)); - //break; - } else { - System.out.println(literal); - if(ChatColor.getByChar(literal.toLowerCase().charAt(0)) == null) - return 0; - System.out.println(literal); - cc = ComponentColor.fromColor(ChatColor.getByChar(literal.toLowerCase().charAt(0)).asBungee().getColor()); - } - s.addAll(n.getSourceSpans()); - } - - MCColorNode mcn = new MCColorNode(cc); - mcn.setSourceSpans(s.getSourceSpans()); - opener.getOpener().insertAfter(mcn); - - //} - -/* - SourceSpans sourceSpans = new SourceSpans(); - - - Node firstNext = opener.getNext(); - if (firstNext instanceof Text) { - String literal = ((Text) firstNext).getLiteral(); - Matcher match = COLOR_PATTERN.matcher(literal); - if (match.matches()) { - ((Text) firstNext).setLiteral(match.group(2).stripLeading()); - ComponentColor color = ComponentColor.fromText(match.group(1)); - if (color != null) { - MCColorNode colorNode = new MCColorNode(color); - Node next; - for (Node n = opener.getNext(); n != null && n != closer; n = next) { - next = n.getNext(); - colorNode.appendChild(n); - } - opener.insertAfter(colorNode); - } - } - }*/ - return 1; - } else - return 0; - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/JsonComponentWriter.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/JsonComponentWriter.java deleted file mode 100644 index bf489ba6..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/JsonComponentWriter.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions; - -import com.dumbdogdiner.stickyapi.bukkit.book.chat.ClickEvent; -import com.dumbdogdiner.stickyapi.bukkit.book.chat.ComponentColor; -import com.dumbdogdiner.stickyapi.bukkit.book.chat.HoverEvent; -import com.dumbdogdiner.stickyapi.bukkit.book.chat.JsonComponent; -import lombok.Getter; - -import java.util.Stack; - -/** - * A class for easily writing to a tree of {@link JsonComponent}s. - */ -public class JsonComponentWriter { - private final Stack levels = new Stack<>(); - private JsonComponent current; - private boolean renderNewLine = false; - private boolean renderIndent = true; - @Getter - private int indent = 0; - - public JsonComponentWriter(JsonComponent component) { - this.current = component; - } - - /** - * Enter a deeper level in the tree. - */ - public void enterLevel() { - levels.push(current); - current = new JsonComponent(); - } - - /** - * Exit the current level. - */ - public void exitLevel() { - JsonComponent top = levels.pop(); - top.getChildren().add(current); - current = top; - } - - /** - * Increase the indentation of the next line. - */ - public void indent() { - ++indent; - } - - /** - * Decrease the indentation of the next line. - */ - public void dedent() { - indent = Math.max(indent - 1, 0); - } - - /** - * Add some text to the JsonComponent tree. - * @param text The text to add - */ - public void addText(String text) { - if (text.isEmpty()) return; - enterLevel(); - if (renderNewLine) { - renderNewLine = false; - current.setText(current.getText() + "\n\n"); - renderIndent = true; - } - if (renderIndent) { - renderIndent = false; - current.setText(current.getText() + " ".repeat(indent)); - } - current.setText(current.getText() + text); - exitLevel(); - } - - /** - * Add a line break. - */ - public void addLine() { - renderNewLine = true; - } - - /** - * Set if the text in the current level of the tree is bold. - */ - public void setBold(Boolean bold) { - current.setBold(bold); - } - - /** - * Set if the text in the current level of the tree is italic. - */ - public void setItalic(Boolean italic) { - current.setItalic(italic); - } - - /** - * Set if the text in the current level of the tree is underlined. - */ - public void setUnderlined(Boolean underlined) { - current.setUnderlined(underlined); - } - - /** - * Set if the text in the current level of the tree is strikethrough. - */ - public void setStrikethrough(Boolean strikethrough) { - current.setStrikethrough(strikethrough); - } - - /** - * Set if the text in the current level of the tree is obfuscated. - */ - public void setObfuscated(Boolean obfuscated) { - current.setObfuscated(obfuscated); - } - - /** - * Set the color of the text in the current level of the tree. - */ - public void setColor(ComponentColor color) { - current.setColor(color); - } - - /** - * Set the {@link ClickEvent} in the current level of the tree. - */ - public void setClickEvent(ClickEvent event) { - current.setClickEvent(event); - } - - /** - * Set the {@link HoverEvent} in the current level of the tree. - */ - public void setHoverEvent(HoverEvent event) { - current.setHoverEvent(event); - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCColorNode.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCColorNode.java deleted file mode 100644 index 964c46cd..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MCColorNode.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions; - -import com.dumbdogdiner.stickyapi.bukkit.book.chat.ComponentColor; -import lombok.Getter; -import org.commonmark.node.CustomNode; - -/** - * A custom node that represents a {@link ComponentColor}. - */ -public class MCColorNode extends CustomNode { - @Getter - private final ComponentColor color; - - public MCColorNode(ComponentColor color) { - this.color = color; - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MarkdownJsonRenderer.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MarkdownJsonRenderer.java deleted file mode 100644 index d4d80e85..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/MarkdownJsonRenderer.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions; - -import com.dumbdogdiner.stickyapi.bukkit.book.chat.ClickEvent; -import com.dumbdogdiner.stickyapi.bukkit.book.chat.HoverEvent; -import com.dumbdogdiner.stickyapi.bukkit.book.chat.JsonComponent; -import org.commonmark.node.*; -import org.commonmark.renderer.NodeRenderer; - -import java.util.*; - -/** - * An implementation of {@link NodeRenderer} that writes to a {@link JsonComponent} - */ -public class MarkdownJsonRenderer extends AbstractVisitor implements NodeRenderer { - private static final Set> nodeTypes = new HashSet<>(Arrays.asList( - Text.class, - Heading.class, - MCColorNode.class, - Emphasis.class, - StrongEmphasis.class, - Link.class, - SoftLineBreak.class, - HardLineBreak.class, - ListItem.class, - OrderedList.class, - BulletList.class, - Block.class - )); - - private final JsonComponentWriter writer; - private int listIndex = 0; - - public MarkdownJsonRenderer(JsonComponentWriter writer) { - this.writer = writer; - } - - // lombok auto getter is static which doesn't match the override - @Override - public Set> getNodeTypes() { - return nodeTypes; - } - - @Override - public void visit(Text text) { - writer.addText(text.getLiteral()); - visitChildren(text); - } - - @Override - public void visit(Heading heading) { - writer.setBold(true); - visitChildren(heading); - writer.addLine(); - } - - @Override - public void visit(Emphasis node) { - writer.setItalic(true); - visitChildren(node); - } - - @Override - public void visit(StrongEmphasis node) { - switch (node.getOpeningDelimiter()) { - case "**": - writer.setBold(true); - break; - case "__": - writer.setUnderlined(true); - break; - } - visitChildren(node); - } - - @Override - public void visit(Link link) { - writer.setClickEvent(new ClickEvent.OpenUrl(link.getDestination())); - writer.setHoverEvent(new HoverEvent.ShowText(new JsonComponent(link.getTitle()))); - visitChildren(link); - } - - @Override - public void visit(SoftLineBreak lineBreak) { - writer.addText(" "); - } - - @Override - public void visit(HardLineBreak lineBreak) { - writer.addLine(); - } - - @Override - public void visit(Paragraph paragraph) { - visitChildren(paragraph); - writer.addLine(); - } - - @Override - public void visit(OrderedList list) { - visitList(list, 1); - } - - @Override - public void visit(BulletList list) { - visitList(list, 0); - } - - private void visitList(ListBlock list, int initialIndex) { - writer.indent(); - int oldIndex = listIndex; - listIndex = initialIndex; - visitChildren(list); - listIndex = oldIndex; - writer.dedent(); - } - - @Override - public void visit(ListItem item) { - if (listIndex == 0) { - writer.addText("• "); - } else { - writer.addText((listIndex++) + ". "); - } - visitChildren(item); - } - - @Override - public void visit(CustomNode node) { - if (node instanceof MCColorNode) { - visit((MCColorNode) node); - } else { - visitChildren(node); - } - } - - public void visit(MCColorNode color) { - writer.setColor(color.getColor()); - visitChildren(color); - } - - @Override - protected void visitChildren(Node parent) { - for (Node child = parent.getFirstChild(); child != null; child = child.getNext()) { - render(child); - } - } - - @Override - public void render(Node node) { - writer.enterLevel(); - node.accept(this); - writer.exitLevel(); - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/ParserFormatExtension.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/ParserFormatExtension.java deleted file mode 100644 index ed3e4514..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/commonmarkextensions/ParserFormatExtension.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions; - -import org.commonmark.parser.Parser; - - - -public class ParserFormatExtension implements Parser.ParserExtension { - private ParserFormatExtension(){} - - public static ParserFormatExtension create() { - return new ParserFormatExtension(); - } - - @Override - public void extend(Parser.Builder parserBuilder) { - parserBuilder.customDelimiterProcessor(new ColorFormatDelimiterProcessor()); - //parserBuilder.customDelimiterProcessor(new StrikethroughDelimiterProcessor()); - /*parserBuilder.postProcessor(null); - parserBuilder.postProcessor(null);*/ - // TODO add a parser here that does the line splitting - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/package-info.java deleted file mode 100644 index 7bba833c..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/book/package-info.java +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ - -/** - * The code in this package is for book parsing of/with markdown, and is unfinished. For now, it shall be ignored. - * It will be finished or removed in a future update. - */ -@OnHold -package com.dumbdogdiner.stickyapi.bukkit.book; - -import com.dumbdogdiner.stickyapi.annotation.OnHold; \ No newline at end of file diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java new file mode 100644 index 00000000..c6d9da47 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.bukkit.item; + +import com.dumbdogdiner.stickyapi.common.util.BookUtil; +import com.dumbdogdiner.stickyapi.common.util.StringUtil; +import com.google.common.base.Preconditions; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.VisibleForTesting; + +import java.util.Collections; +import java.util.StringJoiner; + +@SuppressWarnings({"UnusedReturnValue", "unused"}) +@Accessors(chain = true) +public class BookAndQuillBuilder { + private JsonArray pages = new JsonArray(); + private static final Gson G = new GsonBuilder().create(); + + @Setter + @Getter + private @Nullable String displayName; + + @Setter + @Getter + private @Nullable String lore; + + public BookAndQuillBuilder() { + + } + + + /** + * Creates a new BookGenerator from a given JsonObject, representing a book, which can + * be obtained in whatever way you want. + * + * @param bookObject A JSON object containing a JsonArray of valid Pages; If a {@link Material#WRITTEN_BOOK} is desired, it must contain a title, author, and optionally, a Generation (an integer with the value of 0, 1, 2, or 3, with 0 being the default) + * @return a {@link BookAndQuillBuilder} with the specified pages; if a title and author are both specified, it will be a {@link Material#WRITTEN_BOOK}, otherwise it will be a {@link Material#WRITABLE_BOOK} + */ + public static @NotNull BookAndQuillBuilder fromJson(@NotNull JsonObject bookObject) { + BookAndQuillBuilder b = new BookAndQuillBuilder(); + b.pages = bookObject.get("pages").getAsJsonArray(); + return b; + } + + /** + * Add some pages to the book. May fail with {@link IllegalStateException} if the book is full or fills up. + * + * @param pages Pages to add + * @return This object, for chaining + */ + public @NotNull BookAndQuillBuilder addPages(String @NotNull ... pages) { + for (String page : pages) { + addPage(page); + } + return this; + } + + /** + * Add a page to the book. May fail with {@link IllegalStateException} if the book is full. + * + * @param page The page to add + * @return This object, for chaining + */ + public @NotNull BookAndQuillBuilder addPage(@NotNull String page) { + Preconditions.checkState(!isFull(), "Cannot add page, the book is overfilled!"); + pages.add(page); + return this; + } + + /** + * Build a book from this generator. + * + * @param qty Quantity of the item stack. + * @return an {@link ItemStack} of the book, with pages and all other data + */ + @SuppressWarnings("deprecation") + public @NotNull ItemStack toItemStack(int qty) { + Preconditions.checkArgument(qty > 0 && qty <= 16, "Invalid quantity specified, qty should be greater than 0 and less than or equal to 16, but was " + qty); + Preconditions.checkState(pages.size() > 0, "Cannot generate book with no pages"); + Preconditions.checkState(pages.size() < BookUtil.PAGES_PER_BOOK, "Cannot generate book with an invalid number of pages (must be less than " + BookUtil.PAGES_PER_BOOK + ")"); + ItemStack stack = new ItemStack(Material.WRITABLE_BOOK, qty); + + stack = Bukkit.getUnsafe().modifyItemStack(stack, generatePagesNBT()); + + ItemMeta im = stack.getItemMeta(); + if (displayName != null) + im.setDisplayName(StringUtil.formatChatCodes(displayName)); + + if (lore != null) + im.setLore(Collections.singletonList(lore)); + stack.setItemMeta(im); + + return stack; + } + + /** + * @return The percentage of pages allowed that are used by this book. + * TODO: Does not account for characters per page or packet size at this time. + */ + public float percentFull() { + return (float) pages.size() / (float) BookUtil.PAGES_PER_BOOK; + } + + /** + * TODO: Does not account for characters per page or packet size at this time. + * + * @return True if the book is full. + */ + public boolean isFull() { + return percentFull() >= 1.0f; + } + + /** + * Uses a {@link StringJoiner} to convert pages JsonArray to the weird NBT list + * + * @return {@link String} with NBT of the pages + */ + @VisibleForTesting + public @NotNull String generatePagesNBT() { + StringJoiner NBT = new StringJoiner(",", "{pages:[", "]}"); + pages.forEach(jsonElement -> + NBT.add(G.toJson(jsonElement) + // Because minecraft json is a hack on a hack..... + .replace("\n", "\\n") + .replace("\\", "\\\\")) + + ); + return NBT.toString(); + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java new file mode 100644 index 00000000..860e89cc --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.bukkit.item; + +import com.dumbdogdiner.stickyapi.common.util.BookUtil; +import com.dumbdogdiner.stickyapi.common.util.StringUtil; +import com.google.common.base.Preconditions; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import lombok.Getter; +import lombok.NonNull; +import lombok.Setter; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BookMeta; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.VisibleForTesting; + +import java.util.Collections; +import java.util.StringJoiner; + +@SuppressWarnings({"UnusedReturnValue", "unused"}) +@Accessors(chain = true) +public class WrittenBookBuilder { + private @NotNull JsonArray pages = new JsonArray(); + /** + * The generation of the book. + */ + @Getter + @Setter + private @NonNull BookMeta.@NotNull Generation generation = BookMeta.Generation.ORIGINAL; + + /** + * The author of the book. Must not be null if the book is written. + */ + @Getter + @Setter + private @NotNull String author = StringUtil.randomObfuscatedString(1, 17); + /** + * The title of the book, can be formatted using color codes. + */ + @Getter + @Setter + private @NotNull String title = StringUtil.randomObfuscatedString(1, 17); + /** + * Lore/hover text for the item + */ + @Getter + @Setter + private @Nullable String lore; + + private static final Gson G = new GsonBuilder() + // Make sure things aren't weirdly escaped, may need to turn this back on + .disableHtmlEscaping() + .create(); + + public WrittenBookBuilder() { + + } + + + /** + * Creates a new BookGenerator from a given JsonObject, representing a book, which can + * be obtained in whatever way you want. + * + * @param bookObject A JSON object containing a JsonArray of valid Pages; If a {@link Material#WRITTEN_BOOK} is desired, it must contain a title, author, and optionally, a Generation (an integer with the value of 0, 1, 2, or 3, with 0 being the default) + * @return a {@link WrittenBookBuilder} with the specified pages; if a title and author are both specified, it will be a {@link Material#WRITTEN_BOOK}, otherwise it will be a {@link Material#WRITABLE_BOOK} + */ + public static @NotNull WrittenBookBuilder fromJson(@NotNull JsonObject bookObject) { + Preconditions.checkArgument(bookObject.has("pages") && bookObject.get("pages").isJsonArray(), "The provided JSON object must have a pages array!"); + WrittenBookBuilder b = new WrittenBookBuilder(); + if (bookObject.has("author")) + b.author = bookObject.get("author").getAsString(); + if (bookObject.has("title")) + b.title = bookObject.get("title").getAsString(); + if (bookObject.has("generation")) + switch (bookObject.get("generation").getAsInt()) { + case 1: + b.generation = BookMeta.Generation.COPY_OF_ORIGINAL; + break; + case 2: + b.generation = BookMeta.Generation.COPY_OF_COPY; + break; + case 3: + b.generation = BookMeta.Generation.TATTERED; + break; + case 0: + default: + b.generation = BookMeta.Generation.ORIGINAL; + } + + b.pages = bookObject.get("pages").getAsJsonArray(); + return b; + } + + /** + * Add some pages to the book. May fail with {@link IllegalStateException} if the book is full or fills up. + * + * @param pages Pages to add + * @return This object, for chaining + */ + public @NotNull WrittenBookBuilder addPages(JsonObject @NotNull ... pages) { + for (JsonObject page : pages) { + addPage(page); + } + return this; + } + + /** + * Add a page to the book. May fail with {@link IllegalStateException} if the book is full. + * + * @param page The page to add + * @return This object, for chaining + */ + public @NotNull WrittenBookBuilder addPage(@NotNull JsonObject page) { + Preconditions.checkState(!isFull(), "Cannot add page, the book is overfilled!"); + pages.add(page); + return this; + } + + /** + * Build a book from this generator. + * + * @param qty Quantity of the item stack. + * @return an {@link ItemStack} of the book, with pages and all other data + */ + @SuppressWarnings("deprecation") + public @NotNull ItemStack toItemStack(int qty) { + Preconditions.checkArgument(qty > 0 && qty <= 16, "Invalid quantity specified, qty should be greater than 0 and less than or equal to 16, but was " + qty); + Preconditions.checkState(pages.size() > 0, "Cannot generate book with no pages"); + Preconditions.checkState(pages.size() < BookUtil.PAGES_PER_BOOK, "Cannot generate book with an invalid number of pages (must be less than " + BookUtil.PAGES_PER_BOOK + ")"); + ItemStack stack = new ItemStack(Material.WRITTEN_BOOK, qty); + + stack = Bukkit.getUnsafe().modifyItemStack(stack, generatePagesNBT()); + + BookMeta meta = (BookMeta) stack.getItemMeta(); + //noinspection ConstantConditions + meta.setTitle(title != null ? StringUtil.formatChatCodes(title) : ""); + //noinspection ConstantConditions + meta.setAuthor(author != null ? StringUtil.formatChatCodes(author) : ""); + meta.setGeneration(generation); + if (lore != null) + meta.setLore(Collections.singletonList(StringUtil.formatChatCodes(lore))); + stack.setItemMeta(meta); + + return stack; + } + + /** + * @return The percentage of pages allowed that are used by this book. + * TODO: Does not account for characters per page or packet size at this time. + */ + public float percentFull() { + return (float) pages.size() / (float) BookUtil.PAGES_PER_BOOK; + } + + /** + * TODO: Does not account for characters per page or packet size at this time. + * + * @return True if the book is full. + */ + public boolean isFull() { + return percentFull() >= 1.0f; + } + + + /** + * Uses a {@link StringJoiner} to convert pages JsonArray to the weird NBT list + * + * @return {@link String} with NBT of the pages + */ + @VisibleForTesting + public @NotNull String generatePagesNBT() { + StringJoiner NBT = new StringJoiner(",", "{pages:[", "]}"); + pages.forEach(jsonElement -> { + if (jsonElement instanceof JsonArray) { + JsonArray newArr = new JsonArray(); + newArr.add(""); + newArr.addAll(jsonElement.getAsJsonArray()); + jsonElement = newArr; + } + NBT.add("'" + + G.toJson(jsonElement) + // Because minecraft json is a hack on a hack..... + + .replaceAll("(?. All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.bukkit.item.generator; - -import com.dumbdogdiner.stickyapi.common.util.BookUtil; -import com.google.common.base.Preconditions; -import com.google.gson.*; -import com.google.gson.reflect.TypeToken; -import lombok.Getter; -import lombok.NonNull; -import lombok.Setter; -import lombok.experimental.Accessors; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.BookMeta; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.VisibleForTesting; - -import java.awt.print.Book; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.StringJoiner; -import java.util.function.Consumer; - -@SuppressWarnings({"UnusedReturnValue", "unused"}) -@Accessors(chain = true) -public class BookGenerator { - private JsonArray pages = new JsonArray(); - /** The generation of the book. */ - @Getter @Setter - private @NonNull BookMeta.Generation generation = BookMeta.Generation.ORIGINAL; - /** The material of the book. */ - @Getter - private final Material bookType; - /** The author of the book. Must not be null if the book is written. */ - @Getter @Setter - private @Nullable String author; - /** The title of the book, can be formatted using color codes. */ - @Getter @Setter - private String title; - - - private static final Gson G = new GsonBuilder().create(); - - public BookGenerator(Material material) { - if (material != Material.WRITABLE_BOOK && material != Material.WRITTEN_BOOK) { - throw new IllegalArgumentException("Material must be WRITABLE_BOOK or WRITTEN_BOOK"); - } - - this.bookType = material; - } - - - /** - * Creates a new BookGenerator from a given JsonObject, representing a book, which can - * be obtained in whatever way you want. - * @param bookObject A JSON object containing a JsonArray of valid Pages; If a {@link Material#WRITTEN_BOOK} is desired, it must contain a title, author, and optionally, a Generation (an integer with the value of 0, 1, 2, or 3, with 0 being the default) - * @return a {@link BookGenerator} with the specified pages; if a title and author are both specified, it will be a {@link Material#WRITTEN_BOOK}, otherwise it will be a {@link Material#WRITABLE_BOOK} - */ - public static BookGenerator fromJson(JsonObject bookObject) { - BookGenerator b; - - if(bookObject.has("author") && bookObject.has("title")) { - b = new BookGenerator(Material.WRITTEN_BOOK); - b.author = bookObject.get("author").getAsString(); - b.title = bookObject.get("title").getAsString(); - if(bookObject.has("generation")) - switch (bookObject.get("generation").getAsInt()){ - case 1: - b.generation = BookMeta.Generation.COPY_OF_ORIGINAL; - break; - case 2: - b.generation = BookMeta.Generation.COPY_OF_COPY; - break; - case 3: - b.generation = BookMeta.Generation.TATTERED; - break; - case 0: - default: - b.generation = BookMeta.Generation.ORIGINAL; - } - } else { - b = new BookGenerator(Material.WRITABLE_BOOK); - } - b.pages = bookObject.get("pages").getAsJsonArray(); - return b; - } - - /** - * Add some pages to the book. May fail with {@link IllegalStateException} if the book is full or fills up. - * @param pages Pages to add - * @return This object, for chaining - */ - public BookGenerator addPages(JsonObject... pages) { - for (JsonObject page : pages) { - addPage(page); - } - return this; - } - - /** - * Add a page to the book. May fail with {@link IllegalStateException} if the book is full. - * @param page The page to add - * @return This object, for chaining - */ - public BookGenerator addPage(JsonObject page) { - Preconditions.checkState(!isFull(), "Cannot add page, the book is overfilled!"); - pages.add(page); - return this; - } - - /** - * Build a book from this generator. - * @param qty Quantity of the item stack. - * @return an {@link ItemStack} of the book, with pages and all other data - */ - public ItemStack toItemStack(int qty) { - Preconditions.checkArgument(qty > 0 && qty <= 16, "Invalid quantity specified, qty should be greater than 0 and less than or equal to 16, but was " + qty); - Preconditions.checkState(pages.size() > 0, "Cannot generate book with no pages"); - Preconditions.checkState(pages.size() < BookUtil.PAGES_PER_BOOK, "Cannot generate book with an invalid number of pages (must be less than " + BookUtil.PAGES_PER_BOOK + ")"); - ItemStack stack = new ItemStack(bookType, qty); - - BookMeta meta = (BookMeta) stack.getItemMeta(); - - if (bookType == Material.WRITTEN_BOOK) { - meta.setTitle(title != null ? title : ""); - meta.setAuthor(author != null ? author : ""); - meta.setGeneration(generation); - } - - stack = Bukkit.getUnsafe().modifyItemStack(stack, generateNbtString()); - - stack.setItemMeta(meta); - return stack; - } - - /** - * @return The percentage of pages allowed that are used by this book. - * TODO: Does not account for characters per page or packet size at this time. - */ - public float percentFull() { - return (float)pages.size() / (float) BookUtil.PAGES_PER_BOOK; - } - - /** - * TODO: Does not account for characters per page or packet size at this time. - * @return True if the book is full. - */ - public boolean isFull() { - return percentFull() >= 1.0f; - } - - - /** - * Uses a {@link StringJoiner} to convert pages JsonArray to the weird NBT list - * @return {@link String} with NBT of the pages - */ - @VisibleForTesting - public String generateNbtString() { - StringJoiner NBT = new StringJoiner("','", "{pages:['", "']}"); - pages.forEach(jsonElement -> NBT.add(G.toJson(jsonElement)/*.replace("'", "\\\"")*/)); - return NBT.toString().replace("\\n","\n").replace("\n","\\\\n");//TODO fix the new lines where they are originally - } - - -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index 77cc0993..cde2b6e9 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -4,21 +4,15 @@ */ package com.dumbdogdiner.stickyapi.common.util; +import com.google.common.base.Preconditions; +import com.google.gson.Gson; +import lombok.NonNull; + import java.io.InputStream; import java.io.InputStreamReader; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.regex.Pattern; -import com.dumbdogdiner.stickyapi.bukkit.book.chat.JsonComponent; -import com.google.common.base.Preconditions; -import com.google.gson.Gson; -import lombok.NonNull; -import org.commonmark.node.Document; -import org.commonmark.node.Node; -import org.commonmark.node.ThematicBreak; - /** * Utilities for text and books. */ @@ -80,124 +74,6 @@ public static int getCharacterWidth(char c) { return widths.get(c); } - /** - * Split a JsonComponent into pages for use in a book. - * - * @param origComponent The component to split into pages - * @return A list of JsonComponents, one for each page - * - * TODO There's definately a better way to do this - */ - public static List splitBookPages(@NonNull JsonComponent origComponent) { - List lines = wrapLines(origComponent, HALF_PIXELS_PER_LINE); - List pages = new ArrayList<>(); - JsonComponent currentPage = new JsonComponent(); - int i = 0; - boolean trimNewLines = true; - for (JsonComponent line : lines) { - if (i++ % LINES_PER_PAGE == 0) { - trimNewLines = true; - pages.add(currentPage); - currentPage = new JsonComponent(); - } - if (trimNewLines) { - if (line.getText().equals("\n")) { - line.setText(""); - } else { - trimNewLines = false; - } - } - currentPage.getChildren().add(line); - } - pages.add(currentPage); - return pages.subList(1, pages.size()); - } - - /** - * TODO move this into the commonmark parser thing instead, because it will make life like 1000 times better! - * Wrap a JsonComponent into lines. - * - * @param origComponent The JsonComponent to wrap. - * @param halfPixels The width of the available space in half-pixels. - * @return A list of JsonComponents, one for each line - */ - public static List wrapLines(@NonNull JsonComponent origComponent, int halfPixels) { - List components = origComponent.flatten(); - if (components.isEmpty()) return new ArrayList<>(); - List lineComponents = new ArrayList<>(); - JsonComponent currentLine = new JsonComponent(); - int xPosition = 0; - //TODO make this make better json plz its real crap - for (JsonComponent component : components) { - String[] words = SPLIT_PATTERN.split(component.getText()); - for (String word : words) { - if (word.isEmpty()) continue; - if (word.charAt(0) == '\n') { - int l = word.length(); - for (int i = 0; i < l; ++i) { - lineComponents.add(currentLine); - currentLine = new JsonComponent("\n"); - } - xPosition = 0; - } else { - JsonComponent wordComponent = component.duplicate(); - wordComponent.setText(word); - int width = getStringWidth(word, component.getBold() == Boolean.TRUE); - if (xPosition + width >= halfPixels) { - lineComponents.add(currentLine); - currentLine = new JsonComponent(); - xPosition = width; - } else { - xPosition += width; - } - currentLine.getChildren().add(wordComponent); - } - } - } - if (!currentLine.getChildren().isEmpty()) { - lineComponents.add(currentLine); - } - return lineComponents; - } - - /** - * Split a document into multiple documents, delimited by thematic breaks. Destroys the original document. - * - * @param document The original document - * @return A list of each document. - */ - public static List splitDocumentByBreaks(@NonNull Document document) { - List docs = new ArrayList<>(); - Document currentDocument = new Document(); - Node next; - for (Node n = document.getFirstChild(); n != null; n = next) { - next = n.getNext(); - if (n instanceof ThematicBreak) { - docs.add(currentDocument); - currentDocument = new Document(); - } else { - currentDocument.appendChild(n); - } - } - docs.add(currentDocument); - return docs; - } - - /** - * Measure the width of text in a BaseComponent in half-pixels. - * - * @param component The component to measure - * @return The width of the text, in half-pixels - */ - public static int getComponentWidth(@NonNull JsonComponent component) { - String text = component.getText(); - int width = getStringWidth(text, component.getBold() == Boolean.TRUE); - for (JsonComponent child : component.getChildren()) { - width += getComponentWidth(child); - } - return width; - } - /** * Measure the width of a string, assuming it is in the default Minecraft font. * diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java index 9f64139f..1515543e 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java @@ -106,6 +106,7 @@ public static String getPercentageString(@NotNull int x, @NotNull int total) { * @return {@link Integer} * @throws IllegalArgumentException when min is greater than max */ + @Deprecated public static int getRandomNumber(@NotNull int min, @NotNull int max) { if (min >= max) throw new IllegalArgumentException("Min may not be greater than max!"); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java index 516852d0..bf4329c8 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java @@ -7,16 +7,18 @@ import java.text.DecimalFormat; import java.util.HashMap; import java.util.Map; +import java.util.Random; import java.util.UUID; +import lombok.experimental.UtilityClass; +import net.md_5.bungee.api.ChatColor; import org.jetbrains.annotations.NotNull; /** * Operations on {@link java.lang.String} */ +@UtilityClass public final class StringUtil { - private StringUtil() { - } private static HashMap leetReplace = new HashMap<>(); @@ -287,4 +289,44 @@ public static UUID hyphenateUUID(@NotNull String uuid) { return UUID.fromString(uuid); } } + + + + + /** + * Creates a random string of "magic" characters of characters + * @param min the minimum length of the string (inclusive) + * @param max the maximum length of the string (exclusive) + * @return A string of random characters, where the length + */ + public static String randomObfuscatedString(int min, int max) { + // Placeholder chars by width + char [] choices = new char[] { + ' ', // 1 px + 'i', // 2 px + 'l', // 3 px + 't', // 4 px + 'f', // 5 px + 'a', // 6 px + '@' // 7 px + }; + StringBuilder obfuscated = new StringBuilder(); + obfuscated.append(ChatColor.COLOR_CHAR).append(ChatColor.MAGIC); + int len = MathUtil.randomInt(max) - min; + for(int i = 0; i < max; i++){ + obfuscated.append(choices[MathUtil.randomInt(choices.length)]); + } + obfuscated.append(ChatColor.COLOR_CHAR).append(ChatColor.RESET); + return obfuscated.toString(); + } + + /** + * Replaces & followed by any valid minecraft format code (matching the regex

(?=([a-f]|[0-9]|[klmnor]))
with § + * @param input The input string + * @return A string where the relevant ampersands are replaced with section symbols + */ + public static String formatChatCodes(String input){ + return input.replaceAll("&(?=([a-f]|[0-9]|[klmnor]))", Character.toString(ChatColor.COLOR_CHAR)); + } + } diff --git a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookGeneratorTest.java b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookGeneratorTest.java deleted file mode 100644 index 8dafba4c..00000000 --- a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookGeneratorTest.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.bukkit.book; - -import com.dumbdogdiner.stickyapi.bukkit.item.generator.BookGenerator; -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import org.junit.jupiter.api.Test; - -import java.awt.print.Book; -import java.io.InputStream; -import java.io.InputStreamReader; - -public class BookGeneratorTest { - @Test - public void testJsonBuild(){ - InputStream rulebookStream = BookGeneratorTest.class.getResourceAsStream("/rulebook.json"); - JsonObject jso = (JsonObject) JsonParser.parseReader(new InputStreamReader(rulebookStream)); - System.out.println(jso.toString()); - BookGenerator bg = BookGenerator.fromJson(jso); - System.out.println(bg.generateNbtString()); - } -} diff --git a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookTests.java b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookTests.java deleted file mode 100644 index 1a7c2228..00000000 --- a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/book/BookTests.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.bukkit.book; - -import com.dumbdogdiner.stickyapi.bukkit.item.generator.BookGenerator; -import com.dumbdogdiner.stickyapi.bukkit.book.chat.JsonComponent; -import com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions.JsonComponentWriter; -import com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions.ParserFormatExtension; -import com.dumbdogdiner.stickyapi.bukkit.book.commonmarkextensions.MarkdownJsonRenderer; -import com.dumbdogdiner.stickyapi.common.util.BookUtil; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import lombok.SneakyThrows; -import org.bukkit.Material; -import org.commonmark.node.Document; -import org.commonmark.parser.Parser; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.util.List; - -@Disabled -public class BookTests{ - private static final String BOOK_FILENAME = "/rulebook.md"; - private static Reader bookReader; - private static Gson G; - - - @BeforeAll - static void setUp(){ - bookReader = new InputStreamReader(BookTests.class.getResourceAsStream(BOOK_FILENAME)); - G = new GsonBuilder()/*.setPrettyPrinting()*/.create(); - } - - - @AfterAll - static void tearDown() throws IOException { - bookReader.close(); - G = null; - System.gc(); - } - - - @Disabled - @SneakyThrows - @Test - public void testParser() { - Parser.Builder parserBuilder = Parser.builder(); - ParserFormatExtension.create().extend(parserBuilder); - Parser cmParser = parserBuilder.build(); - List sections = BookUtil.splitDocumentByBreaks( - (Document)cmParser - .parseReader(bookReader)); - BookGenerator bg = new BookGenerator(Material.WRITTEN_BOOK); - sections.stream() - .map(section -> BookUtil - .splitBookPages( - renderDocument(section))) - .flatMap(List::stream) - .forEach(page -> bg.addPage(page.toJson())); - - System.out.println(bg.generateNbtString()); - } - - - private JsonComponent renderDocument(Document section) { - JsonComponent component = new JsonComponent(); - JsonComponentWriter writer = new JsonComponentWriter(component); - new MarkdownJsonRenderer(writer).render(section); - return component; - } - -} diff --git a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/BookBuilderTest.java b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/BookBuilderTest.java new file mode 100644 index 00000000..b24fcd51 --- /dev/null +++ b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/BookBuilderTest.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.bukkit.item; + +import org.junit.jupiter.api.Test; + +public class BookBuilderTest { + @Test + public void testJsonBuild(){ + BookAndQuillBuilder bb = new BookAndQuillBuilder(); + bb.addPage("Page1 is just a page\\n"); + bb.addPages("And another page", "and yet another"); + //noinspection RedundantArrayCreation + bb.addPages(new String [] {"yet more", "and more still"}); + + System.out.println("Pages NBT:"); + System.out.println(bb.generatePagesNBT()); + } +} diff --git a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilderTest.java b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilderTest.java new file mode 100644 index 00000000..f49a32eb --- /dev/null +++ b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilderTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.bukkit.item; + +import com.dumbdogdiner.stickyapi.common.util.StringUtil; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import com.google.gson.stream.JsonReader; +import org.junit.jupiter.api.*; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.text.MessageFormat; + +public class WrittenBookBuilderTest { + private static Reader bookReader; + + private static Gson G; + + + @BeforeAll + static void setUp(){ + G = new GsonBuilder().create(); + } + + + @AfterEach + void tearDown() throws IOException { + bookReader.close(); + System.gc(); + } + + @AfterAll + static void tearDownEnd() { + G = null; + System.gc(); + } + + + @Test + public void testSimple() { + testJSON("/book1.json"); + } + + @Test + public void testProdRulebook() { + testJSON("/rulebook.json"); + } + + public void testJSON(String filename) { + bookReader = new InputStreamReader(WrittenBookBuilderTest.class.getResourceAsStream(filename)); + JsonObject bookObject = JsonParser.parseReader(bookReader).getAsJsonObject(); + WrittenBookBuilder bb = WrittenBookBuilder.fromJson(bookObject); + System.out.println("Testing BookBuilder, please make sure the following NBT string is valid (It does not yet contain the title or author):"); + System.out.println(bb.generatePagesNBT()); + + System.out.println("Please paste the following line into a command block, and activate it"); + System.out.println("give @p minecraft:written_book" + makeValidWrittenBookNBT(bb)); + } + + /** + * Fix the command so it actually is valid, in a hacky way + * @param bookBuilder Original bookbuilder + * @return NBT that has the title forcibly put in + */ + private String makeValidWrittenBookNBT(WrittenBookBuilder bookBuilder) { + StringBuilder sb = new StringBuilder(); + sb.append(bookBuilder.generatePagesNBT()); + sb.insert(sb.length() - 1, StringUtil.formatChatCodes(MessageFormat.format(",title:\"{0}\",author:\"{1}\"", bookBuilder.getTitle(), bookBuilder.getAuthor()))); + return sb.toString(); + } +} diff --git a/src/test/resources/book1.json b/src/test/resources/book1.json new file mode 100644 index 00000000..041a6359 --- /dev/null +++ b/src/test/resources/book1.json @@ -0,0 +1,25 @@ +{ + "pages": [ + [ + { + "text": "Page 1\\nI'm text in " + }, + { + "text": "bold", + "bold": true + }, + { + "text": " owo", + "color": "reset" + } + ], + [ + { + "text": "red text in page 2", + "color": "dark_red" + } + ] + ], + "title": "a booky book", + "author": "rodwuffy" +} \ No newline at end of file diff --git a/src/test/resources/rulebook.json b/src/test/resources/rulebook.json index 041a6359..f66bf977 100644 --- a/src/test/resources/rulebook.json +++ b/src/test/resources/rulebook.json @@ -1,25 +1 @@ -{ - "pages": [ - [ - { - "text": "Page 1\\nI'm text in " - }, - { - "text": "bold", - "bold": true - }, - { - "text": " owo", - "color": "reset" - } - ], - [ - { - "text": "red text in page 2", - "color": "dark_red" - } - ] - ], - "title": "a booky book", - "author": "rodwuffy" -} \ No newline at end of file +{"pages":[[{"text":"Dumb Dog Diner MC\\nSurvival Handbook","bold":true,"italic":true,"color":"dark_purple"},{"text":"\\n\\n","color":"reset"},{"text":"Table of Contents:","bold":true,"italic":true,"underlined":true,"color":"dark_red"},{"text":"\\n","color":"reset"},{"text":"Page 2: ","color":"red"},{"text":"Rules\\n","color":"reset"},{"text":"Pg. 3: ","color":"red"},{"text":"Gameplay\\n","color":"reset"},{"text":"Pg. 5: ","color":"red"},{"text":"Trading\\n","color":"reset"},{"text":"Pg. 7: ","color":"red"},{"text":"Commands\\n","color":"reset"},{"text":"Pg. 9: ","color":"red"},{"text":"Trading\\nCommands\\n","color":"reset"},{"text":"Pg. 11: ","color":"red"},{"text":"Extras\\n","color":"reset"},{"text":"Pg. 12: ","color":"red"},{"text":"Getting Help\\n","color":"reset"},{"text":"Pg. 14: ","color":"red"},{"text":"Credits","color":"reset"}],[{"text":"The Rules:","bold":true,"italic":true,"underlined":true,"color":"red"},{"text":"\\n1. Absolutely no\\ngriefing, theft, or\\nintentional distress!\\n2. No cheating/hacking\\nallowed. No exploits.\\n3. No floating trees.\\n4. No fully-automatic\\nredstone farms.\\n5. No harassment,\\nbullying, or abuse.\\n6. No AFK fishing.","color":"reset"}],[{"text":"Gameplay:","bold":true,"italic":true,"underlined":true,"color":"dark_green"},{"text":"\\nThe world border for all worlds is 8,000\\nblocks from the\\ncenter. Because of\\nnow ","color":"reset"},{"text":"Nether Portal","color":"dark_red"},{"text":"\\ntravel works, you will\\nnot be able to light\\nthem past 1,000 blocks\\nfrom the center.\\nYou may build wherever you like! Try ","color":"reset"},{"text":"/rtp","color":"blue"},{"text":" to help find a spot!","color":"reset"}],[{"text":"This server uses a "},{"text":"Death Chest ","color":"red"},{"text":"system. Upon death, a campfire with your items will spawn at your death location. It will last\\nfor 10 minutes before\\nyour items drop on \\nthe ground!\\n\\nYou can have up to 3\\n","color":"reset"},{"text":"Death Chests","color":"red"},{"text":" at a time.","color":"reset"}],[{"text":"Trading:","bold":true,"italic":true,"underlined":true,"color":"dark_aqua"},{"text":"\\nWe use chest chops\\nfor player to trade\\ngood for ","color":"reset"},{"text":"Coins","color":"gold"},{"text":".\\n\\nCoins may be earned through selling goods\\nto other players,\\npaying/receiving\\nmoney for a service,\\nor by selling goods to\\nthe server itself.","color":"reset"}],{"text":"Chest shops can buy\\nor sell items!\\n\\nTo make a shop, place a chest and\\nshift-click with the\\nitem you want to sell\\nor buy.\\n\\nRegular users may have up to 6 shops\\nat a time."},[{"text":"Commands:","bold":true,"italic":true,"underlined":true,"color":"red"},{"text":"\\nTab-complete is set\\nup to only show commands you have access to. Here are some useful ones:\\n\\n","color":"reset"},{"text":"/helpmenu ","color":"blue"},{"text":"- Opens the\\nhelp menu\\n","color":"reset"},{"text":"/servers ","color":"blue"},{"text":"- Opens the\\nservers menu\\n","color":"reset"},{"text":"/rules","color":"blue"},{"text":" - Grants this\\nbook","color":"reset"}],[{"text":"/options ","color":"blue"},{"text":"- Opens the player options menu\\n","color":"reset"},{"text":"/tpa ","color":"blue"},{"text":"- Sends a\\nteleport request to another player\\n","color":"reset"},{"text":"/rtp ","color":"blue"},{"text":"- Start a\\nrandom teleport\\n","color":"reset"},{"text":"/pw ","color":"blue"},{"text":"- Opens the playerwarps personal\\nhome menu\\n","color":"reset"},{"text":"/helpme ","color":"blue"},{"text":"- Pings an online staff member\\nfor assistance","color":"reset"}],[{"text":"Trading Commands:","bold":true,"italic":true,"underlined":true,"color":"dark_purple"},{"text":"\\n","color":"reset"},{"text":"/bal ","color":"blue"},{"text":"- Check your\\nbalance\\n","color":"reset"},{"text":"/pay ","color":"blue"},{"text":"- Pay another player\\n","color":"reset"},{"text":"/sell ","color":"blue"},{"text":"- Sell the item in your hand to the server\\n","color":"reset"},{"text":"/worth ","color":"blue"},{"text":"- Shows the\\nitem price when selling\\nto the server","color":"reset"}],[{"text":"/value","color":"blue"},{"text":" - Shows the\\naverage selling price\\nfor an item in\\nplayer shops","color":"reset"}],[{"text":"Extras:","bold":true,"italic":true,"underlined":true,"color":"dark_aqua"},{"text":"\\n","color":"reset"},{"text":"/donate, /vip ","color":"blue"},{"text":"- Gives link to the server Patreon page\\n","color":"reset"},{"text":"/twitter, /twitch, /discord, /merch ","color":"blue"},{"text":"\\n- Gives various social media links\\n","color":"reset"},{"text":"/afk ","color":"blue"},{"text":"- Set your status to AFK\\n","color":"reset"},{"text":"/tamer tool ","color":"blue"},{"text":"- Gives\\ntool to protect pets\\n ","color":"reset"}],[{"text":"Getting Help:","bold":true,"italic":true,"underlined":true,"color":"light_purple"},{"text":"\\nIf you ever need help\\ngetting your way\\naround the server,\\nplease ask any staff!\\n","color":"reset"},{"text":"/helpme","color":"blue"},{"text":"\\n\\nPlease join the\\nDiscord server to get\\ntechnical help!\\n","color":"reset"},{"text":"/discord","color":"blue"}],[{"text":"Please report any\\nbugs, griefing, etc.\\nthat you come across\\nor are a victim of!","bold":true,"underlined":true},{"text":"\\n\\nUse ","color":"reset"},{"text":"/report \u003cplayer\u003e","color":"blue"},{"text":"\\nto report another\\nplayer to staff!\\n\\nThe help menu has shortcuts that make getting help easy!\\n","color":"reset"},{"text":"/help","color":"blue"}],[{"text":"Credits:","bold":true,"italic":true,"underlined":true,"color":"gold"},{"text":"\\n","color":"reset"},{"text":"dddMC ","bold":true,"color":"dark_purple"},{"text":"is fully funded\\nthrough player donations. Please consider helping support us on Patreon!\\n","color":"reset"},{"text":"/donate /patreon","color":"blue"},{"text":"\\n\\nPatrons will receive a\\nVIP rank. More ranks\\nwill be added in the\\nfuture.","color":"reset"}],[{"text":"We hope you enjoy\\nyour time playing\\non the server!\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n- Stixil, "},{"text":"dddMC 2020","bold":true,"color":"dark_purple"}]],"title":"\u0026ddddMC Survival Handbook v1.0","author":"Stixil"} \ No newline at end of file From ba707bee7b299867b95d8adb7fff0199e5519f0e Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sun, 31 Jan 2021 23:23:34 -0700 Subject: [PATCH 40/79] Spruced up javadoc, annotated utility classes --- build.gradle | 19 +++++++++ .../com/dumbdogdiner/stickyapi/StickyAPI.java | 9 ++++ .../bukkit/generator/VoidGenerator.java | 2 +- .../bukkit/item/BookAndQuillBuilder.java | 7 ++++ .../bukkit/item/WrittenBookBuilder.java | 6 +++ .../stickyapi/bukkit/item/package-info.java | 9 ++++ .../stickyapi/common/ServerVersion.java | 3 ++ .../stickyapi/common/util/BookUtil.java | 2 + .../stickyapi/common/util/IPUtil.java | 5 +-- .../stickyapi/common/util/MathUtil.java | 3 ++ .../stickyapi/common/util/MemoryUtil.java | 5 +-- .../stickyapi/common/util/NumberUtil.java | 5 +-- .../stickyapi/common/util/ShortID.java | 5 ++- .../stickyapi/common/util/TimeUtil.java | 5 +-- .../common/util/reflection/package-info.java | 8 ++++ .../stickyapi/common/util/url/URLUtil.java | 2 + .../common/util/url/package-info.java | 8 ++++ .../dumbdogdiner/stickyapi/package-info.java | 18 ++++++++ src/main/overview.html | 42 +++++++++++++++++++ 19 files changed, 148 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/package-info.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/package-info.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/util/url/package-info.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/package-info.java create mode 100644 src/main/overview.html diff --git a/build.gradle b/build.gradle index 4f2ce808..22eb36f7 100644 --- a/build.gradle +++ b/build.gradle @@ -167,6 +167,25 @@ task rebuild{ finalizedBy build } +javadoc { + options.addBooleanOption('XDignore.symbol.file', true) + options.addBooleanOption('-frames', true) + options.addBooleanOption('private', true) + options.addBooleanOption("-allow-script-in-comments",true) + options.overview('src/main/overview.html') + //TODO replace frames with JANITOR to get around removal of -frames in jdk15 + //options.footer("") + test.ignoreFailures true; + dependsOn delombok +} + +task browseJavadoc { + dependsOn javadoc + doLast { + java.awt.Desktop.desktop.browse new URI(("file:///" << System.getProperty("user.dir").replace('\\','/') << "/build/docs/javadoc/index.html").toString()) + } +} + publishing { repositories { maven { diff --git a/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java b/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java index 2f246a8b..e02df751 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java @@ -13,13 +13,22 @@ import lombok.Getter; import lombok.Setter; +import lombok.experimental.UtilityClass; /** *

StickyAPI

Utility methods, classes and potentially * code-dupe-annihilating code for DDD plugins. * * @author DumbDogDiner (dumbdogdiner.com) + * @author aakatz3 + * @author SkyezerFox + * @author JCX + * @author NotZachery + * @author vladfrangu + * @author spazzylemons + * @author kokumaji */ +@UtilityClass public class StickyAPI { @Getter public static Logger logger = Logger.getLogger("StickyAPI"); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java index 8403386a..69588027 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java @@ -16,7 +16,7 @@ public class VoidGenerator extends ChunkGenerator { @Override - public ChunkData generateChunkData(@NotNull World world, Random random, int x, int z, BiomeGrid biome) { + public @NotNull ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome) { return createChunkData(world); } } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java index c6d9da47..1f58d1b1 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java @@ -25,6 +25,13 @@ import java.util.Collections; import java.util.StringJoiner; +/** + * This class allows for easy construction of a writable book, which is unfortunately much + * simpler than a written/signed book, either manually in code, or by loading a JSON object + * + * @since 2.1.0 + */ + @SuppressWarnings({"UnusedReturnValue", "unused"}) @Accessors(chain = true) public class BookAndQuillBuilder { diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java index 860e89cc..f2880d97 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java @@ -27,6 +27,12 @@ import java.util.Collections; import java.util.StringJoiner; +/** + * This class allows for easy construction of a Written Book, whether through JSON objects and manual + * creation, or by loading a full JSON object from a file or other source + * + * @since 2.1.0 + */ @SuppressWarnings({"UnusedReturnValue", "unused"}) @Accessors(chain = true) public class WrittenBookBuilder { diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/package-info.java new file mode 100644 index 00000000..b9040982 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/package-info.java @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +/** + * Classes related to item generation or manipulation + */ + +package com.dumbdogdiner.stickyapi.bukkit.item; \ No newline at end of file diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java b/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java index a2ab1c97..da6f8d57 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java @@ -4,9 +4,12 @@ */ package com.dumbdogdiner.stickyapi.common; +import lombok.experimental.UtilityClass; + /** * Utility class for fetching version data. */ +@UtilityClass public final class ServerVersion { public enum ServerType { BUKKIT, SPIGOT, PAPER, BUNGEE, WATERFALL diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index cde2b6e9..748752ef 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -7,6 +7,7 @@ import com.google.common.base.Preconditions; import com.google.gson.Gson; import lombok.NonNull; +import lombok.experimental.UtilityClass; import java.io.InputStream; import java.io.InputStreamReader; @@ -16,6 +17,7 @@ /** * Utilities for text and books. */ +@UtilityClass public class BookUtil { /** * Offset for bold (in each direction) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/IPUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/IPUtil.java index d1e0f45b..257a1d22 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/IPUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/IPUtil.java @@ -4,6 +4,7 @@ */ package com.dumbdogdiner.stickyapi.common.util; +import lombok.experimental.UtilityClass; import org.jetbrains.annotations.NotNull; import inet.ipaddr.IPAddress; @@ -12,10 +13,8 @@ /** * Utility class for IP Addresses */ +@UtilityClass public final class IPUtil { - private IPUtil() { - } - /** * Check if an IP Address is within a CIDR range *

diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java index c5c66f72..d33a6740 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java @@ -4,6 +4,8 @@ */ package com.dumbdogdiner.stickyapi.common.util; +import lombok.experimental.UtilityClass; + import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.List; @@ -14,6 +16,7 @@ * Util class for commonly used math operations. *

*/ +@UtilityClass public class MathUtil { private static final Random random = new Random(); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MemoryUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/MemoryUtil.java index 33379947..3725a382 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MemoryUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/MemoryUtil.java @@ -8,6 +8,7 @@ import java.lang.reflect.Modifier; import com.dumbdogdiner.stickyapi.common.util.reflection.ReflectionUtil; +import lombok.experimental.UtilityClass; /** * Provides a very crude method of measuring the memory consumption of Java @@ -15,10 +16,8 @@ * with each new object, but can be useful to measure the estimated size of an * object. */ +@UtilityClass public final class MemoryUtil { - private MemoryUtil() { - } - public enum Unit { BITS, BYTES, KILOBYTES, MEGABYTES } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java index 1515543e..1b9e1360 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java @@ -4,6 +4,7 @@ */ package com.dumbdogdiner.stickyapi.common.util; +import lombok.experimental.UtilityClass; import org.jetbrains.annotations.NotNull; /** @@ -11,10 +12,8 @@ * Provides extra functionality for Java Number classes. *

*/ +@UtilityClass public final class NumberUtil { - private NumberUtil() { - } - /** *

* Checks if the String contains only unicode digits. A decimal point is not a diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/ShortID.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/ShortID.java index 154a130f..231b9333 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/ShortID.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/ShortID.java @@ -8,12 +8,13 @@ import java.util.UUID; import java.util.zip.CRC32; +import lombok.experimental.UtilityClass; import org.apache.commons.lang.Validate; import org.jetbrains.annotations.NotNull; +// TODO this is in the apache validation used in another PR +@UtilityClass final class Luhn { - private Luhn() { - } /** * Checks if the card is valid diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java index b729daa8..62dbf3ec 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java @@ -14,15 +14,14 @@ import javax.annotation.Nullable; +import lombok.experimental.UtilityClass; import org.jetbrains.annotations.NotNull; /** * Utility methods for dealing with time and duration parsing. */ +@UtilityClass public final class TimeUtil { - private TimeUtil() { - } - private static final SimpleDateFormat sdf = new SimpleDateFormat("EEE, MMM d yyyy HH:mm:ss"); private static final HashMap DURATION_CHARS = new HashMap<>(); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/package-info.java new file mode 100644 index 00000000..06f86531 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/package-info.java @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +/** + * Classes that make reflection a tad easier + */ +package com.dumbdogdiner.stickyapi.common.util.reflection; \ No newline at end of file diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java index b5adde7b..daaed5dd 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java @@ -7,6 +7,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import lombok.experimental.UtilityClass; import net.md_5.bungee.api.chat.HoverEvent; import net.md_5.bungee.api.chat.hover.content.Text; import org.jetbrains.annotations.NotNull; @@ -14,6 +15,7 @@ import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.TextComponent; +@UtilityClass public class URLUtil { private static final Pattern urlPattern = Pattern.compile( diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/package-info.java new file mode 100644 index 00000000..9fedfbd3 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/package-info.java @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +/** + * Utility classes for URLs + */ +package com.dumbdogdiner.stickyapi.common.util.url; \ No newline at end of file diff --git a/src/main/java/com/dumbdogdiner/stickyapi/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/package-info.java new file mode 100644 index 00000000..7bde2e12 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/package-info.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +/** + *

StickyAPI

Utility methods, classes and potentially + * code-dupe-annihilating code for DDD plugins. + * + * @author DumbDogDiner (dumbdogdiner.com) + * @author aakatz3 + * @author SkyezerFox + * @author JCX + * @author NotZachery + * @author vladfrangu + * @author spazzylemons + * @author kokumaji + */ +package com.dumbdogdiner.stickyapi; \ No newline at end of file diff --git a/src/main/overview.html b/src/main/overview.html new file mode 100644 index 00000000..72b6de5e --- /dev/null +++ b/src/main/overview.html @@ -0,0 +1,42 @@ + + + + + + Overview + + +

StickyAPI

+stixilDoggers +

Utility methods, classes and potentially code-dupe-annihilating code for DDD plugins.

+ +

+ Copyright © 2020- + DumbDogDiner <dumbdogdiner.com>. All rights reserved.
+ Licensed under the MIT license, see LICENSE for more + information... + +
+

+ Developed by +

+ +

This code is stored at https://github.com/DumbDogDiner/StickyAPI + + + \ No newline at end of file From 86226d82d8c44e0e3275f19c40e7a29a87e4fbe4 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Mon, 1 Feb 2021 13:54:32 -0700 Subject: [PATCH 41/79] requested fixes --- .gitignore | 4 ++-- build.gradle | 4 ++-- .../java/com/dumbdogdiner/stickyapi/StickyAPI.java | 10 +++------- .../dumbdogdiner/stickyapi/common/util/BookUtil.java | 2 +- .../java/com/dumbdogdiner/stickyapi/package-info.java | 2 +- src/main/overview.html | 4 ++-- 6 files changed, 11 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 6c66882e..42255ec6 100644 --- a/.gitignore +++ b/.gitignore @@ -51,5 +51,5 @@ bin .idea *.code-workspace -# Font Width Data -src/main/resources/mojangles_width_data.json \ No newline at end of file +# Generated resources +src/main/resources/generated/* \ No newline at end of file diff --git a/build.gradle b/build.gradle index 2cae852a..2cb1c20f 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,7 @@ repositories { maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } maven { url 'https://papermc.io/repo/repository/maven-public/' } - // Define a Ivy repo for the font width data (that way we don't need another plugin! + // Define a Ivy repo for the font width data (that way we don't need another plugin!) def ddd_mc_font = ivy { url 'https://dumbdogdiner.github.io/' patternLayout { artifact '/[module]/[revision]/[classifier].[ext]'} @@ -152,7 +152,7 @@ task copyMCFontExtractor(type: Copy) { println path from file(path) //into file("src/main/resources") - destinationDir file("src/main/resources/") + destinationDir file("src/main/resources/generated/") rename 'mc-font-extractor-main-mojangles_width_data.json', 'mojangles_width_data.json' } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java b/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java index fbd8646f..9b034354 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java @@ -23,16 +23,13 @@ * @author aakatz3 * @author SkyezerFox * @author JCX - * @author NotZachery + * @author ZachyFoxx * @author vladfrangu * @author spazzylemons * @author kokumaji */ @UtilityClass public class StickyAPI { - private StickyAPI() { - } - @Getter public static Logger logger = Logger.getLogger("StickyAPI"); @@ -47,7 +44,6 @@ private StickyAPI() { * * @since TBA * @return {@link String} version - * */ @Getter private static final String version = "@BUILDINFO_VERSION"; @@ -89,8 +85,7 @@ private StickyAPI() { public static Date getTimestamp() { SimpleDateFormat formatter = new SimpleDateFormat(dateFormat); try { - Date date = formatter.parse(timestamp); - return date; + return formatter.parse(timestamp); } catch (ParseException e) { e.printStackTrace(); return null; @@ -115,6 +110,7 @@ public static String getSha() { * @since TBA * @return {@link Boolean} isDirty */ + @SuppressWarnings("ConstantConditions") public static Boolean getIsDirty() { return Boolean.parseBoolean(isDirty); } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index 748752ef..e02b9868 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -44,7 +44,7 @@ private static class WidthEntry { static { Gson gson = new Gson(); - try (InputStream input = ClassLoader.getSystemResource("mojangles_width_data.json").openStream()) { + try (InputStream input = ClassLoader.getSystemResource("generated/mojangles_width_data.json").openStream()) { WidthEntry[] entries = gson.fromJson(new InputStreamReader(input), WidthEntry[].class); for (WidthEntry entry : entries) { if (entry.id == null) entry.id = 0; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/package-info.java index 7bde2e12..928b71fa 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/package-info.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/package-info.java @@ -10,7 +10,7 @@ * @author aakatz3 * @author SkyezerFox * @author JCX - * @author NotZachery + * @author ZachyFoxx * @author vladfrangu * @author spazzylemons * @author kokumaji diff --git a/src/main/overview.html b/src/main/overview.html index 72b6de5e..3062bc89 100644 --- a/src/main/overview.html +++ b/src/main/overview.html @@ -24,13 +24,13 @@

StickyAPI


- Developed by + Developed by:  

  • DumbDogDiner (dumbdogdiner.com)
  • aakatz3
  • SkyezerFox
  • JCX
  • -
  • NotZachery
  • +
  • ZachyFoxx
  • vladfrangu
  • spazzylemons
  • kokumaji
  • From a6d3a9b7e39db5b60e35029c5577010c1275821e Mon Sep 17 00:00:00 2001 From: James Date: Mon, 1 Feb 2021 21:19:40 +0000 Subject: [PATCH 42/79] Fix build by removing private constructors where utilityclass is used --- .../java/com/dumbdogdiner/stickyapi/common/ServerVersion.java | 3 --- .../com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java b/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java index 331f8c65..da6f8d57 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java @@ -11,9 +11,6 @@ */ @UtilityClass public final class ServerVersion { - private ServerVersion() { - } - public enum ServerType { BUKKIT, SPIGOT, PAPER, BUNGEE, WATERFALL } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java index d1c7e126..4b65fb33 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java @@ -17,9 +17,6 @@ @UtilityClass public class URLUtil { - private URLUtil() { - } - private static final Pattern urlPattern = Pattern.compile( "(https:\\/\\/|http:\\/\\/)((?:[-;:&=\\+\\$,\\w]+@)?[A-Za-z0-9.-]+|(www.|[-;:&=\\+\\$,\\w]+@)[A-Za-z0-9.-]+)((?:\\/[\\+~%\\/.\\w-_]*)?\\??(?:[-\\+=&;%@.\\w_]*)#?(?:[\\w]*))?"); From 0260b3bb6ee182ee122a1fd3be578f706e73592b Mon Sep 17 00:00:00 2001 From: James Date: Mon, 1 Feb 2021 21:22:12 +0000 Subject: [PATCH 43/79] Add BookUtil#isCharacterSupported and some tests --- .../stickyapi/common/util/BookUtil.java | 10 +++++ .../stickyapi/common/util/BookUtilTest.java | 37 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 src/test/java/com/dumbdogdiner/stickyapi/common/util/BookUtilTest.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java index e02b9868..a1364e9c 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java @@ -65,6 +65,16 @@ private static class WidthEntry { } } + /** + * Check if the given character is supported in-game. + * + * @param c The character to check + * @return A boolean representing if the character is supported or not + */ + public static boolean isCharacterSupported(char c) { + return widths.containsKey(c); + } + /** * @param c The character to measure * @return The width of the character in half-pixels diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/BookUtilTest.java b/src/test/java/com/dumbdogdiner/stickyapi/common/util/BookUtilTest.java new file mode 100644 index 00000000..7be4923b --- /dev/null +++ b/src/test/java/com/dumbdogdiner/stickyapi/common/util/BookUtilTest.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.util; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class BookUtilTest { + @Test + public void testIsCharacterSupportedTrueBasicPlaneUtf16() { + assertTrue(BookUtil.isCharacterSupported((char) 0x0041)); + } + + @Test + public void testIsCharacterSupportedTrueBasicPlaneDecimal() { + assertEquals((char) 0x0041, (char) 65); // Sanity check assertation + assertTrue(BookUtil.isCharacterSupported((char) 65)); + } + + @Test + public void testIsCharacterSupportedTrueEmojiUtf16() { + // 0x1F5E1 | "Dagger Knife" Emoji + assertTrue(BookUtil.isCharacterSupported((char) 0x1F5E1)); + } + + @Test + public void testIsCharacterSupportedFalseEmojiUtf16() { + // 0x1F98A | "Fox Face" Emoji + assertFalse(BookUtil.isCharacterSupported((char) 0x1F98A)); + } + +} From 10729b000ee1f6d9387d4fb0398b54613aff9c88 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Tue, 2 Feb 2021 12:24:34 -0700 Subject: [PATCH 44/79] Add a couple other tests --- .../bukkit/item/BookAndQuillBuilder.java | 6 +- .../bukkit/item/WrittenBookBuilder.java | 13 ++-- .../util/{BookUtil.java => TextUtil.java} | 73 ++++++++++++++----- .../stickyapi/common/util/BookUtilTest.java | 37 ---------- .../stickyapi/common/util/TextUtilTest.java | 65 +++++++++++++++++ 5 files changed, 128 insertions(+), 66 deletions(-) rename src/main/java/com/dumbdogdiner/stickyapi/common/util/{BookUtil.java => TextUtil.java} (61%) delete mode 100644 src/test/java/com/dumbdogdiner/stickyapi/common/util/BookUtilTest.java create mode 100644 src/test/java/com/dumbdogdiner/stickyapi/common/util/TextUtilTest.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java index 1f58d1b1..446b38eb 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java @@ -4,7 +4,7 @@ */ package com.dumbdogdiner.stickyapi.bukkit.item; -import com.dumbdogdiner.stickyapi.common.util.BookUtil; +import com.dumbdogdiner.stickyapi.common.util.TextUtil; import com.dumbdogdiner.stickyapi.common.util.StringUtil; import com.google.common.base.Preconditions; import com.google.gson.Gson; @@ -99,7 +99,7 @@ public BookAndQuillBuilder() { public @NotNull ItemStack toItemStack(int qty) { Preconditions.checkArgument(qty > 0 && qty <= 16, "Invalid quantity specified, qty should be greater than 0 and less than or equal to 16, but was " + qty); Preconditions.checkState(pages.size() > 0, "Cannot generate book with no pages"); - Preconditions.checkState(pages.size() < BookUtil.PAGES_PER_BOOK, "Cannot generate book with an invalid number of pages (must be less than " + BookUtil.PAGES_PER_BOOK + ")"); + Preconditions.checkState(pages.size() < TextUtil.PAGES_PER_BOOK, "Cannot generate book with an invalid number of pages (must be less than " + TextUtil.PAGES_PER_BOOK + ")"); ItemStack stack = new ItemStack(Material.WRITABLE_BOOK, qty); stack = Bukkit.getUnsafe().modifyItemStack(stack, generatePagesNBT()); @@ -120,7 +120,7 @@ public BookAndQuillBuilder() { * TODO: Does not account for characters per page or packet size at this time. */ public float percentFull() { - return (float) pages.size() / (float) BookUtil.PAGES_PER_BOOK; + return (float) pages.size() / (float) TextUtil.PAGES_PER_BOOK; } /** diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java index f2880d97..c826df8e 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java @@ -4,7 +4,7 @@ */ package com.dumbdogdiner.stickyapi.bukkit.item; -import com.dumbdogdiner.stickyapi.common.util.BookUtil; +import com.dumbdogdiner.stickyapi.common.util.TextUtil; import com.dumbdogdiner.stickyapi.common.util.StringUtil; import com.google.common.base.Preconditions; import com.google.gson.Gson; @@ -15,7 +15,6 @@ import lombok.NonNull; import lombok.Setter; import lombok.experimental.Accessors; -import net.md_5.bungee.api.ChatColor; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; @@ -50,12 +49,14 @@ public class WrittenBookBuilder { @Getter @Setter private @NotNull String author = StringUtil.randomObfuscatedString(1, 17); + /** * The title of the book, can be formatted using color codes. */ @Getter @Setter private @NotNull String title = StringUtil.randomObfuscatedString(1, 17); + /** * Lore/hover text for the item */ @@ -72,7 +73,6 @@ public WrittenBookBuilder() { } - /** * Creates a new BookGenerator from a given JsonObject, representing a book, which can * be obtained in whatever way you want. @@ -142,7 +142,7 @@ public WrittenBookBuilder() { public @NotNull ItemStack toItemStack(int qty) { Preconditions.checkArgument(qty > 0 && qty <= 16, "Invalid quantity specified, qty should be greater than 0 and less than or equal to 16, but was " + qty); Preconditions.checkState(pages.size() > 0, "Cannot generate book with no pages"); - Preconditions.checkState(pages.size() < BookUtil.PAGES_PER_BOOK, "Cannot generate book with an invalid number of pages (must be less than " + BookUtil.PAGES_PER_BOOK + ")"); + Preconditions.checkState(pages.size() < TextUtil.PAGES_PER_BOOK, "Cannot generate book with an invalid number of pages (must be less than " + TextUtil.PAGES_PER_BOOK + ")"); ItemStack stack = new ItemStack(Material.WRITTEN_BOOK, qty); stack = Bukkit.getUnsafe().modifyItemStack(stack, generatePagesNBT()); @@ -165,7 +165,7 @@ public WrittenBookBuilder() { * TODO: Does not account for characters per page or packet size at this time. */ public float percentFull() { - return (float) pages.size() / (float) BookUtil.PAGES_PER_BOOK; + return (float) pages.size() / (float) TextUtil.PAGES_PER_BOOK; } /** @@ -177,7 +177,6 @@ public boolean isFull() { return percentFull() >= 1.0f; } - /** * Uses a {@link StringJoiner} to convert pages JsonArray to the weird NBT list * @@ -205,6 +204,4 @@ public boolean isFull() { }); return NBT.toString(); } - - } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java similarity index 61% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java rename to src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java index a1364e9c..6d0d2096 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/BookUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java @@ -4,42 +4,61 @@ */ package com.dumbdogdiner.stickyapi.common.util; +import com.dumbdogdiner.stickyapi.StickyAPI; import com.google.common.base.Preconditions; import com.google.gson.Gson; +import lombok.Data; import lombok.NonNull; import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.InputStream; import java.io.InputStreamReader; import java.util.HashMap; +import java.util.Set; import java.util.regex.Pattern; /** * Utilities for text and books. */ @UtilityClass -public class BookUtil { - /** - * Offset for bold (in each direction) - */ +public class TextUtil { + /** Offset for bold (in each direction) */ public static final float BOLD_OFFSET = 0.5f; + /** Offset for shadows (in each direction) */ public static final float SHADOW_OFFSET = 0.5f; - public static final int PIXELS_PER_LINE = 113; - public static final int HALF_PIXELS_PER_LINE = PIXELS_PER_LINE * 2; + /** Number of pixels per line of a book */ + public static final int PIXELS_PER_BOOK_LINE = 113; + /** Number of half-pixels per book line */ + public static final int HALF_PIXELS_PER_BOOK_LINE = PIXELS_PER_BOOK_LINE * 2; + /** Number of lines in a page of a book */ public static final int LINES_PER_PAGE = 14; + /** Number of pages in a book */ public static final int PAGES_PER_BOOK = 50; + /** Number of pixels per line of a sign */ + // TODO verify via minecraft source code + public static final int PIXELS_PER_SIGN_LINE = 96; + /** Number of lines per sign */ + public static final int LINES_PER_SIGN = 4; + + private static final Pattern SPLIT_PATTERN = Pattern.compile("(?<=[ \n])|(?=[ \n])"); private static final HashMap widths = new HashMap<>(); + /** + * Internal class to parse the width data json file + */ + @Data private static class WidthEntry { - String uid; - Integer id; - String val; - int width; + private @NotNull String uid; + private @Nullable Integer id; + private @NotNull String val; + private int width; } static { @@ -47,11 +66,11 @@ private static class WidthEntry { try (InputStream input = ClassLoader.getSystemResource("generated/mojangles_width_data.json").openStream()) { WidthEntry[] entries = gson.fromJson(new InputStreamReader(input), WidthEntry[].class); for (WidthEntry entry : entries) { - if (entry.id == null) entry.id = 0; - widths.put((char) (int) entry.id, entry.width); + if (entry.getId() == null) entry.setId(0); + widths.put((char) (entry.getId() != null ? entry.getId() : '\0'), entry.width); } } catch (Exception e) { - e.printStackTrace(); + StickyAPI.getLogger().severe(e.getMessage()); // fallback to a minimal , in case anything fails for (char c = 32; c <= 126; ++c) { widths.put(c, 12); @@ -75,12 +94,20 @@ public static boolean isCharacterSupported(char c) { return widths.containsKey(c); } + + /** + * Returns a {@link Set} of the supported characters + */ + public static Set getSupportedCharacters() { + return widths.keySet(); + } + /** * @param c The character to measure * @return The width of the character in half-pixels * @throws IllegalArgumentException if the character is out of range */ - public static int getCharacterWidth(char c) { + public static int getCharacterWidth(char c) throws IllegalArgumentException{ Preconditions.checkArgument(widths.containsKey(c), "Unsupported character: " + c + " code: " + String.format("%04x", (int) c)); return widths.get(c); @@ -95,14 +122,24 @@ public static int getCharacterWidth(char c) { */ public static int getStringWidth(@NonNull String text, boolean isBold) { int width = 0; - int textLength = text.length(); - for (int i = 0; i < textLength; ++i) { - width += BookUtil.getCharacterWidth(text.charAt(i)); + + for (char c : text.toCharArray()) { + width += TextUtil.getCharacterWidth(c); } - if (isBold) width += 2 * textLength; + + if (isBold) + width += 2 * text.length(); + return width; } + /** + Measure the width of a string, assuming it is in the default Minecraft font. + * + * @param text The string to measure + * @return The width of the string, in half-pixels + * @see #getStringWidth(String, boolean) + */ public static int getStringWidth(@NonNull String text) { return getStringWidth(text, false); } diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/BookUtilTest.java b/src/test/java/com/dumbdogdiner/stickyapi/common/util/BookUtilTest.java deleted file mode 100644 index 7be4923b..00000000 --- a/src/test/java/com/dumbdogdiner/stickyapi/common/util/BookUtilTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.util; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class BookUtilTest { - @Test - public void testIsCharacterSupportedTrueBasicPlaneUtf16() { - assertTrue(BookUtil.isCharacterSupported((char) 0x0041)); - } - - @Test - public void testIsCharacterSupportedTrueBasicPlaneDecimal() { - assertEquals((char) 0x0041, (char) 65); // Sanity check assertation - assertTrue(BookUtil.isCharacterSupported((char) 65)); - } - - @Test - public void testIsCharacterSupportedTrueEmojiUtf16() { - // 0x1F5E1 | "Dagger Knife" Emoji - assertTrue(BookUtil.isCharacterSupported((char) 0x1F5E1)); - } - - @Test - public void testIsCharacterSupportedFalseEmojiUtf16() { - // 0x1F98A | "Fox Face" Emoji - assertFalse(BookUtil.isCharacterSupported((char) 0x1F98A)); - } - -} diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/TextUtilTest.java b/src/test/java/com/dumbdogdiner/stickyapi/common/util/TextUtilTest.java new file mode 100644 index 00000000..09bd8dce --- /dev/null +++ b/src/test/java/com/dumbdogdiner/stickyapi/common/util/TextUtilTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.util; + +import com.google.common.io.CharStreams; +import org.junit.jupiter.api.Test; + +import java.text.MessageFormat; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +public class TextUtilTest { + @Test + public void testIsCharacterSupportedTrueBasicPlaneUtf16() { + assertTrue(TextUtil.isCharacterSupported((char) 0x0041)); + } + + @Test + public void testIsCharacterSupportedTrueBasicPlaneDecimal() { + assertTrue(TextUtil.isCharacterSupported((char) 65)); + } + + @Test + public void testIsCharacterSupportedTrueEmojiUtf16() { + // 0x1F5E1 | "Dagger Knife" Emoji 🗡️ + assertTrue(TextUtil.isCharacterSupported((char) 0x1F5E1)); + } + + @Test + public void testIsCharacterSupportedFalseEmojiUtf16() { + // 0x1F98A | "Fox Face" Emoji 🦊 + assertFalse(TextUtil.isCharacterSupported((char) 0x1F98A)); + } + + @Test + public void testAllSupportedCharsAreSupported() { + for(char c : TextUtil.getSupportedCharacters()){ + assertTrue(TextUtil.isCharacterSupported(c)); + } + } + + @Test + public void testUnsupportedCharsNotSupported() { + Set unsupported = IntStream.range(Character.MIN_VALUE, Character.MAX_VALUE) + .boxed() + .map(i -> (char) (int) i) + .collect(Collectors.toSet()); + unsupported.removeAll(TextUtil.getSupportedCharacters()); + for (Character c : unsupported) { + try { + int x = TextUtil.getCharacterWidth(c); + fail(MessageFormat.format("Should have failed, instead got a width of {0} for char {1}", x, c)); + } catch (IllegalArgumentException e) { + // expected + assertFalse(TextUtil.isCharacterSupported(c)); + } + } + } +} From 439faac53ba7be53562df5d5f05dc7748ccf3c81 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sat, 6 Feb 2021 12:02:15 -0700 Subject: [PATCH 45/79] Fixes --- .gitignore | 2 +- build.gradle | 3 + .../com/dumbdogdiner/stickyapi/StickyAPI.java | 2 +- .../stickyapi/bukkit/item/package-info.java | 2 +- .../stickyapi/common/util/TextUtil.java | 2 +- .../common/util/reflection/package-info.java | 2 +- .../common/util/url/package-info.java | 2 +- .../dumbdogdiner/stickyapi/package-info.java | 2 +- src/main/overview.html | 52 +- src/test/resources/book1.json | 2 +- src/test/resources/rulebook.json | 448 +++++++++++++++++- 11 files changed, 488 insertions(+), 31 deletions(-) diff --git a/.gitignore b/.gitignore index 42255ec6..0290202d 100644 --- a/.gitignore +++ b/.gitignore @@ -52,4 +52,4 @@ bin *.code-workspace # Generated resources -src/main/resources/generated/* \ No newline at end of file +src/main/resources/generated/* diff --git a/build.gradle b/build.gradle index 2cb1c20f..c0f9d9b3 100644 --- a/build.gradle +++ b/build.gradle @@ -145,6 +145,7 @@ task processSourceTokens(type: Sync) { // Use the filter task as the input for compileJava compileJava.source = processSourceTokens.outputs +// TODO: Make task to minify resources (json) on compile // Font Width Info task copyMCFontExtractor(type: Copy) { @@ -173,6 +174,8 @@ javadoc { options.addBooleanOption('private', true) options.addBooleanOption("-allow-script-in-comments",true) options.overview('src/main/overview.html') + outputs.upToDateWhen { false } + //TODO replace frames with JANITOR to get around removal of -frames in jdk15 //options.footer("") test.ignoreFailures true; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java b/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java index 9b034354..f2270dda 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java @@ -46,7 +46,7 @@ public class StickyAPI { * @return {@link String} version */ @Getter - private static final String version = "@BUILDINFO_VERSION"; + private static final String version = "@BUILDINFO_VERSION@"; // Getter not required private static final String dateFormat = "@BUILDINFO_DATEFORMAT@"; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/package-info.java index b9040982..1f5149b8 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/package-info.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/package-info.java @@ -6,4 +6,4 @@ * Classes related to item generation or manipulation */ -package com.dumbdogdiner.stickyapi.bukkit.item; \ No newline at end of file +package com.dumbdogdiner.stickyapi.bukkit.item; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java index 6d0d2096..a0df7adb 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java @@ -96,7 +96,7 @@ public static boolean isCharacterSupported(char c) { /** - * Returns a {@link Set} of the supported characters + * Returns a {@link Set} of {@link Character}of the supported characters */ public static Set getSupportedCharacters() { return widths.keySet(); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/package-info.java index 06f86531..5b9b0d6f 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/package-info.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/package-info.java @@ -5,4 +5,4 @@ /** * Classes that make reflection a tad easier */ -package com.dumbdogdiner.stickyapi.common.util.reflection; \ No newline at end of file +package com.dumbdogdiner.stickyapi.common.util.reflection; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/package-info.java index 9fedfbd3..5cab60b2 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/package-info.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/package-info.java @@ -5,4 +5,4 @@ /** * Utility classes for URLs */ -package com.dumbdogdiner.stickyapi.common.util.url; \ No newline at end of file +package com.dumbdogdiner.stickyapi.common.util.url; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/package-info.java index 928b71fa..3081ee9c 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/package-info.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/package-info.java @@ -15,4 +15,4 @@ * @author spazzylemons * @author kokumaji */ -package com.dumbdogdiner.stickyapi; \ No newline at end of file +package com.dumbdogdiner.stickyapi; diff --git a/src/main/overview.html b/src/main/overview.html index 3062bc89..83e2b4b7 100644 --- a/src/main/overview.html +++ b/src/main/overview.html @@ -11,32 +11,40 @@ Overview -

    StickyAPI

    -stixilDoggers +

    + stixilDoggers + StickyAPI + stixilDoggers +

    Utility methods, classes and potentially code-dupe-annihilating code for DDD plugins.

    -

    - Copyright © 2020- - DumbDogDiner <dumbdogdiner.com>. All rights reserved.
    - Licensed under the MIT license, see LICENSE for more - information... -
    -

    +

    +

    + Copyright © 2020-CURRENT_YEAR DumbDogDiner <dumbdogdiner.com>. All rights reserved.
    + Licensed under the MIT license, see LICENSE for more information... +

    +
    + +

    Developed by:   -

    +

    +

    This code is stored at https://github.com/DumbDogDiner/StickyAPI - + + - \ No newline at end of file + diff --git a/src/test/resources/book1.json b/src/test/resources/book1.json index 041a6359..68e28d2f 100644 --- a/src/test/resources/book1.json +++ b/src/test/resources/book1.json @@ -22,4 +22,4 @@ ], "title": "a booky book", "author": "rodwuffy" -} \ No newline at end of file +} diff --git a/src/test/resources/rulebook.json b/src/test/resources/rulebook.json index f66bf977..5b361ee2 100644 --- a/src/test/resources/rulebook.json +++ b/src/test/resources/rulebook.json @@ -1 +1,447 @@ -{"pages":[[{"text":"Dumb Dog Diner MC\\nSurvival Handbook","bold":true,"italic":true,"color":"dark_purple"},{"text":"\\n\\n","color":"reset"},{"text":"Table of Contents:","bold":true,"italic":true,"underlined":true,"color":"dark_red"},{"text":"\\n","color":"reset"},{"text":"Page 2: ","color":"red"},{"text":"Rules\\n","color":"reset"},{"text":"Pg. 3: ","color":"red"},{"text":"Gameplay\\n","color":"reset"},{"text":"Pg. 5: ","color":"red"},{"text":"Trading\\n","color":"reset"},{"text":"Pg. 7: ","color":"red"},{"text":"Commands\\n","color":"reset"},{"text":"Pg. 9: ","color":"red"},{"text":"Trading\\nCommands\\n","color":"reset"},{"text":"Pg. 11: ","color":"red"},{"text":"Extras\\n","color":"reset"},{"text":"Pg. 12: ","color":"red"},{"text":"Getting Help\\n","color":"reset"},{"text":"Pg. 14: ","color":"red"},{"text":"Credits","color":"reset"}],[{"text":"The Rules:","bold":true,"italic":true,"underlined":true,"color":"red"},{"text":"\\n1. Absolutely no\\ngriefing, theft, or\\nintentional distress!\\n2. No cheating/hacking\\nallowed. No exploits.\\n3. No floating trees.\\n4. No fully-automatic\\nredstone farms.\\n5. No harassment,\\nbullying, or abuse.\\n6. No AFK fishing.","color":"reset"}],[{"text":"Gameplay:","bold":true,"italic":true,"underlined":true,"color":"dark_green"},{"text":"\\nThe world border for all worlds is 8,000\\nblocks from the\\ncenter. Because of\\nnow ","color":"reset"},{"text":"Nether Portal","color":"dark_red"},{"text":"\\ntravel works, you will\\nnot be able to light\\nthem past 1,000 blocks\\nfrom the center.\\nYou may build wherever you like! Try ","color":"reset"},{"text":"/rtp","color":"blue"},{"text":" to help find a spot!","color":"reset"}],[{"text":"This server uses a "},{"text":"Death Chest ","color":"red"},{"text":"system. Upon death, a campfire with your items will spawn at your death location. It will last\\nfor 10 minutes before\\nyour items drop on \\nthe ground!\\n\\nYou can have up to 3\\n","color":"reset"},{"text":"Death Chests","color":"red"},{"text":" at a time.","color":"reset"}],[{"text":"Trading:","bold":true,"italic":true,"underlined":true,"color":"dark_aqua"},{"text":"\\nWe use chest chops\\nfor player to trade\\ngood for ","color":"reset"},{"text":"Coins","color":"gold"},{"text":".\\n\\nCoins may be earned through selling goods\\nto other players,\\npaying/receiving\\nmoney for a service,\\nor by selling goods to\\nthe server itself.","color":"reset"}],{"text":"Chest shops can buy\\nor sell items!\\n\\nTo make a shop, place a chest and\\nshift-click with the\\nitem you want to sell\\nor buy.\\n\\nRegular users may have up to 6 shops\\nat a time."},[{"text":"Commands:","bold":true,"italic":true,"underlined":true,"color":"red"},{"text":"\\nTab-complete is set\\nup to only show commands you have access to. Here are some useful ones:\\n\\n","color":"reset"},{"text":"/helpmenu ","color":"blue"},{"text":"- Opens the\\nhelp menu\\n","color":"reset"},{"text":"/servers ","color":"blue"},{"text":"- Opens the\\nservers menu\\n","color":"reset"},{"text":"/rules","color":"blue"},{"text":" - Grants this\\nbook","color":"reset"}],[{"text":"/options ","color":"blue"},{"text":"- Opens the player options menu\\n","color":"reset"},{"text":"/tpa ","color":"blue"},{"text":"- Sends a\\nteleport request to another player\\n","color":"reset"},{"text":"/rtp ","color":"blue"},{"text":"- Start a\\nrandom teleport\\n","color":"reset"},{"text":"/pw ","color":"blue"},{"text":"- Opens the playerwarps personal\\nhome menu\\n","color":"reset"},{"text":"/helpme ","color":"blue"},{"text":"- Pings an online staff member\\nfor assistance","color":"reset"}],[{"text":"Trading Commands:","bold":true,"italic":true,"underlined":true,"color":"dark_purple"},{"text":"\\n","color":"reset"},{"text":"/bal ","color":"blue"},{"text":"- Check your\\nbalance\\n","color":"reset"},{"text":"/pay ","color":"blue"},{"text":"- Pay another player\\n","color":"reset"},{"text":"/sell ","color":"blue"},{"text":"- Sell the item in your hand to the server\\n","color":"reset"},{"text":"/worth ","color":"blue"},{"text":"- Shows the\\nitem price when selling\\nto the server","color":"reset"}],[{"text":"/value","color":"blue"},{"text":" - Shows the\\naverage selling price\\nfor an item in\\nplayer shops","color":"reset"}],[{"text":"Extras:","bold":true,"italic":true,"underlined":true,"color":"dark_aqua"},{"text":"\\n","color":"reset"},{"text":"/donate, /vip ","color":"blue"},{"text":"- Gives link to the server Patreon page\\n","color":"reset"},{"text":"/twitter, /twitch, /discord, /merch ","color":"blue"},{"text":"\\n- Gives various social media links\\n","color":"reset"},{"text":"/afk ","color":"blue"},{"text":"- Set your status to AFK\\n","color":"reset"},{"text":"/tamer tool ","color":"blue"},{"text":"- Gives\\ntool to protect pets\\n ","color":"reset"}],[{"text":"Getting Help:","bold":true,"italic":true,"underlined":true,"color":"light_purple"},{"text":"\\nIf you ever need help\\ngetting your way\\naround the server,\\nplease ask any staff!\\n","color":"reset"},{"text":"/helpme","color":"blue"},{"text":"\\n\\nPlease join the\\nDiscord server to get\\ntechnical help!\\n","color":"reset"},{"text":"/discord","color":"blue"}],[{"text":"Please report any\\nbugs, griefing, etc.\\nthat you come across\\nor are a victim of!","bold":true,"underlined":true},{"text":"\\n\\nUse ","color":"reset"},{"text":"/report \u003cplayer\u003e","color":"blue"},{"text":"\\nto report another\\nplayer to staff!\\n\\nThe help menu has shortcuts that make getting help easy!\\n","color":"reset"},{"text":"/help","color":"blue"}],[{"text":"Credits:","bold":true,"italic":true,"underlined":true,"color":"gold"},{"text":"\\n","color":"reset"},{"text":"dddMC ","bold":true,"color":"dark_purple"},{"text":"is fully funded\\nthrough player donations. Please consider helping support us on Patreon!\\n","color":"reset"},{"text":"/donate /patreon","color":"blue"},{"text":"\\n\\nPatrons will receive a\\nVIP rank. More ranks\\nwill be added in the\\nfuture.","color":"reset"}],[{"text":"We hope you enjoy\\nyour time playing\\non the server!\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n- Stixil, "},{"text":"dddMC 2020","bold":true,"color":"dark_purple"}]],"title":"\u0026ddddMC Survival Handbook v1.0","author":"Stixil"} \ No newline at end of file +{ + "pages": [ + [ + { + "text": "Dumb Dog Diner MC\\nSurvival Handbook", + "bold": true, + "italic": true, + "color": "dark_purple" + }, + { + "text": "\\n\\n", + "color": "reset" + }, + { + "text": "Table of Contents:", + "bold": true, + "italic": true, + "underlined": true, + "color": "dark_red" + }, + { + "text": "\\n", + "color": "reset" + }, + { + "text": "Page 2: ", + "color": "red" + }, + { + "text": "Rules\\n", + "color": "reset" + }, + { + "text": "Pg. 3: ", + "color": "red" + }, + { + "text": "Gameplay\\n", + "color": "reset" + }, + { + "text": "Pg. 5: ", + "color": "red" + }, + { + "text": "Trading\\n", + "color": "reset" + }, + { + "text": "Pg. 7: ", + "color": "red" + }, + { + "text": "Commands\\n", + "color": "reset" + }, + { + "text": "Pg. 9: ", + "color": "red" + }, + { + "text": "Trading\\nCommands\\n", + "color": "reset" + }, + { + "text": "Pg. 11: ", + "color": "red" + }, + { + "text": "Extras\\n", + "color": "reset" + }, + { + "text": "Pg. 12: ", + "color": "red" + }, + { + "text": "Getting Help\\n", + "color": "reset" + }, + { + "text": "Pg. 14: ", + "color": "red" + }, + { + "text": "Credits", + "color": "reset" + } + ], + [ + { + "text": "The Rules:", + "bold": true, + "italic": true, + "underlined": true, + "color": "red" + }, + { + "text": "\\n1. Absolutely no\\ngriefing, theft, or\\nintentional distress!\\n2. No cheating/hacking\\nallowed. No exploits.\\n3. No floating trees.\\n4. No fully-automatic\\nredstone farms.\\n5. No harassment,\\nbullying, or abuse.\\n6. No AFK fishing.", + "color": "reset" + } + ], + [ + { + "text": "Gameplay:", + "bold": true, + "italic": true, + "underlined": true, + "color": "dark_green" + }, + { + "text": "\\nThe world border for all worlds is 8,000\\nblocks from the\\ncenter. Because of\\nnow ", + "color": "reset" + }, + { + "text": "Nether Portal", + "color": "dark_red" + }, + { + "text": "\\ntravel works, you will\\nnot be able to light\\nthem past 1,000 blocks\\nfrom the center.\\nYou may build wherever you like! Try ", + "color": "reset" + }, + { + "text": "/rtp", + "color": "blue" + }, + { + "text": " to help find a spot!", + "color": "reset" + } + ], + [ + { + "text": "This server uses a " + }, + { + "text": "Death Chest ", + "color": "red" + }, + { + "text": "system. Upon death, a campfire with your items will spawn at your death location. It will last\\nfor 10 minutes before\\nyour items drop on \\nthe ground!\\n\\nYou can have up to 3\\n", + "color": "reset" + }, + { + "text": "Death Chests", + "color": "red" + }, + { + "text": " at a time.", + "color": "reset" + } + ], + [ + { + "text": "Trading:", + "bold": true, + "italic": true, + "underlined": true, + "color": "dark_aqua" + }, + { + "text": "\\nWe use chest chops\\nfor player to trade\\ngood for ", + "color": "reset" + }, + { + "text": "Coins", + "color": "gold" + }, + { + "text": ".\\n\\nCoins may be earned through selling goods\\nto other players,\\npaying/receiving\\nmoney for a service,\\nor by selling goods to\\nthe server itself.", + "color": "reset" + } + ], + { + "text": "Chest shops can buy\\nor sell items!\\n\\nTo make a shop, place a chest and\\nshift-click with the\\nitem you want to sell\\nor buy.\\n\\nRegular users may have up to 6 shops\\nat a time." + }, + [ + { + "text": "Commands:", + "bold": true, + "italic": true, + "underlined": true, + "color": "red" + }, + { + "text": "\\nTab-complete is set\\nup to only show commands you have access to. Here are some useful ones:\\n\\n", + "color": "reset" + }, + { + "text": "/helpmenu ", + "color": "blue" + }, + { + "text": "- Opens the\\nhelp menu\\n", + "color": "reset" + }, + { + "text": "/servers ", + "color": "blue" + }, + { + "text": "- Opens the\\nservers menu\\n", + "color": "reset" + }, + { + "text": "/rules", + "color": "blue" + }, + { + "text": " - Grants this\\nbook", + "color": "reset" + } + ], + [ + { + "text": "/options ", + "color": "blue" + }, + { + "text": "- Opens the player options menu\\n", + "color": "reset" + }, + { + "text": "/tpa ", + "color": "blue" + }, + { + "text": "- Sends a\\nteleport request to another player\\n", + "color": "reset" + }, + { + "text": "/rtp ", + "color": "blue" + }, + { + "text": "- Start a\\nrandom teleport\\n", + "color": "reset" + }, + { + "text": "/pw ", + "color": "blue" + }, + { + "text": "- Opens the playerwarps personal\\nhome menu\\n", + "color": "reset" + }, + { + "text": "/helpme ", + "color": "blue" + }, + { + "text": "- Pings an online staff member\\nfor assistance", + "color": "reset" + } + ], + [ + { + "text": "Trading Commands:", + "bold": true, + "italic": true, + "underlined": true, + "color": "dark_purple" + }, + { + "text": "\\n", + "color": "reset" + }, + { + "text": "/bal ", + "color": "blue" + }, + { + "text": "- Check your\\nbalance\\n", + "color": "reset" + }, + { + "text": "/pay ", + "color": "blue" + }, + { + "text": "- Pay another player\\n", + "color": "reset" + }, + { + "text": "/sell ", + "color": "blue" + }, + { + "text": "- Sell the item in your hand to the server\\n", + "color": "reset" + }, + { + "text": "/worth ", + "color": "blue" + }, + { + "text": "- Shows the\\nitem price when selling\\nto the server", + "color": "reset" + } + ], + [ + { + "text": "/value", + "color": "blue" + }, + { + "text": " - Shows the\\naverage selling price\\nfor an item in\\nplayer shops", + "color": "reset" + } + ], + [ + { + "text": "Extras:", + "bold": true, + "italic": true, + "underlined": true, + "color": "dark_aqua" + }, + { + "text": "\\n", + "color": "reset" + }, + { + "text": "/donate, /vip ", + "color": "blue" + }, + { + "text": "- Gives link to the server Patreon page\\n", + "color": "reset" + }, + { + "text": "/twitter, /twitch, /discord, /merch ", + "color": "blue" + }, + { + "text": "\\n- Gives various social media links\\n", + "color": "reset" + }, + { + "text": "/afk ", + "color": "blue" + }, + { + "text": "- Set your status to AFK\\n", + "color": "reset" + }, + { + "text": "/tamer tool ", + "color": "blue" + }, + { + "text": "- Gives\\ntool to protect pets\\n ", + "color": "reset" + } + ], + [ + { + "text": "Getting Help:", + "bold": true, + "italic": true, + "underlined": true, + "color": "light_purple" + }, + { + "text": "\\nIf you ever need help\\ngetting your way\\naround the server,\\nplease ask any staff!\\n", + "color": "reset" + }, + { + "text": "/helpme", + "color": "blue" + }, + { + "text": "\\n\\nPlease join the\\nDiscord server to get\\ntechnical help!\\n", + "color": "reset" + }, + { + "text": "/discord", + "color": "blue" + } + ], + [ + { + "text": "Please report any\\nbugs, griefing, etc.\\nthat you come across\\nor are a victim of!", + "bold": true, + "underlined": true + }, + { + "text": "\\n\\nUse ", + "color": "reset" + }, + { + "text": "/report \u003cplayer\u003e", + "color": "blue" + }, + { + "text": "\\nto report another\\nplayer to staff!\\n\\nThe help menu has shortcuts that make getting help easy!\\n", + "color": "reset" + }, + { + "text": "/help", + "color": "blue" + } + ], + [ + { + "text": "Credits:", + "bold": true, + "italic": true, + "underlined": true, + "color": "gold" + }, + { + "text": "\\n", + "color": "reset" + }, + { + "text": "dddMC ", + "bold": true, + "color": "dark_purple" + }, + { + "text": "is fully funded\\nthrough player donations. Please consider helping support us on Patreon!\\n", + "color": "reset" + }, + { + "text": "/donate /patreon", + "color": "blue" + }, + { + "text": "\\n\\nPatrons will receive a\\nVIP rank. More ranks\\nwill be added in the\\nfuture.", + "color": "reset" + } + ], + [ + { + "text": "We hope you enjoy\\nyour time playing\\non the server!\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n- Stixil, " + }, + { + "text": "dddMC 2020", + "bold": true, + "color": "dark_purple" + } + ] + ], + "title": "\u0026ddddMC Survival Handbook v1.0", + "author": "Stixil" +} \ No newline at end of file From 328ac6c4ef346d371cfece539ecbad3ca6d622aa Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sat, 6 Feb 2021 13:15:25 -0700 Subject: [PATCH 46/79] Add tests --- .../bukkit/item/BookAndQuillBuilder.java | 2 +- .../bukkit/item/WrittenBookBuilder.java | 4 +- .../stickyapi/common/util/MathUtil.java | 43 ++++++--- .../stickyapi/common/util/StringUtil.java | 96 ++++++++++++------- .../stickyapi/common/util/TextUtil.java | 6 +- .../stickyapi/common/util/StringUtilTest.java | 15 +++ 6 files changed, 119 insertions(+), 47 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java index 446b38eb..9cb04b08 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java @@ -34,7 +34,7 @@ @SuppressWarnings({"UnusedReturnValue", "unused"}) @Accessors(chain = true) -public class BookAndQuillBuilder { +public class BookAndQuillBuilder { private JsonArray pages = new JsonArray(); private static final Gson G = new GsonBuilder().create(); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java index c826df8e..8b6066f5 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java @@ -48,14 +48,14 @@ public class WrittenBookBuilder { */ @Getter @Setter - private @NotNull String author = StringUtil.randomObfuscatedString(1, 17); + private @NotNull String author = StringUtil.randomObfuscatedString(1, 17, 4); /** * The title of the book, can be formatted using color codes. */ @Getter @Setter - private @NotNull String title = StringUtil.randomObfuscatedString(1, 17); + private @NotNull String title = StringUtil.randomObfuscatedString(1, 17, 6); /** * Lore/hover text for the item diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java index d33a6740..4b578d54 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java @@ -4,11 +4,17 @@ */ package com.dumbdogdiner.stickyapi.common.util; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Chars; +import com.google.common.primitives.Ints; import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.NotNull; import java.text.CharacterIterator; import java.text.StringCharacterIterator; +import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.Random; /** @@ -38,13 +44,15 @@ public static int randomInt(int max) { * Get a random number within a range *

    * - * @param min minimum value - * @param max maximum value + * @param min minimum value (inclusive) + * @param max maximum value (inclusive) * @return a random integer within the specified range * @throws IllegalArgumentException when min is greater than max */ public static int randomInt(int min, int max) { - if (min >= max) + if (min == max) + return min; + if (min > max) throw new IllegalArgumentException("Min may not be greater than max!"); return min + randomInt(1 + max - min); } @@ -85,8 +93,8 @@ public static double randomDouble(double min, double max) { * @param array the array that should be used * @return a random element from the specified array */ - public static T randomElement(T[] array) { - if(array.length < 1) return null; + public static T randomElement(@NotNull T @NotNull [] array) { + if (array.length < 1) return null; return array[randomInt(array.length)]; } @@ -98,8 +106,8 @@ public static T randomElement(T[] array) { * @param list the list that should be used * @return a random element from the specified list */ - public static T randomElement(List list) { - if(list.size() < 1) return null; + public static T randomElement(@NotNull List list) { + if (list.size() < 1) return null; return list.get(randomInt(list.size())); } @@ -108,7 +116,7 @@ public static T randomElement(List list) { * Round a double value *

    * - * @param value the value that should be rounded + * @param value the value that should be rounded * @param places amount of decimal places * @return {@link Double} */ @@ -148,12 +156,25 @@ public static String bytesToReadable(long bytes) { *

    * * @param number the number that should be tested - * @param min minimum value - * @param max maximum value + * @param min minimum value + * @param max maximum value * @return true if given number is in range */ public static boolean inRange(int number, int min, int max) { return number >= min && number <= max; } -} \ No newline at end of file + /** + * @see #randomElement(List) + */ + public static char randomElement(char @NotNull [] choices) { + return Objects.requireNonNull(randomElement(Chars.asList(choices))); + } + + /** + * @see #randomElement(List) + */ + public static int randomElement(int @NotNull [] choices) { + return Objects.requireNonNull(randomElement(Ints.asList(choices))); + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java index bf4329c8..4be2e320 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java @@ -10,8 +10,11 @@ import java.util.Random; import java.util.UUID; +import com.google.common.base.Preconditions; import lombok.experimental.UtilityClass; + import net.md_5.bungee.api.ChatColor; + import org.jetbrains.annotations.NotNull; /** @@ -39,10 +42,10 @@ public final class StringUtil { /** * Create a horizontal progress bar, similar to how htop does it. - * + * *

    * Returns a progress bar - * + * * @param size The size of the bar (inside) * @param percentage The percentage to fill the bar to * @param monospace If false, the bars will be a character with the @@ -56,7 +59,7 @@ public final class StringUtil { * @return {@link String} */ public static String createProgressBar(@NotNull double size, @NotNull double percentage, @NotNull boolean monospace, - @NotNull boolean includePercentage, @NotNull boolean includeBrackets) { + @NotNull boolean includePercentage, @NotNull boolean includeBrackets) { double barCount = ((percentage / 100) * size); StringBuilder barBuilder = new StringBuilder(); for (double i = 0; i < size; i++) { @@ -85,7 +88,7 @@ public static String createProgressBar(@NotNull double size, @NotNull double per * Create a horizontal progress bar, similar to how htop does it. *

    * Returns a progress bar - * + * * @param size The size of the bar * @param percentage The percentage to fill the bar to * @return {@link String} @@ -107,7 +110,7 @@ public static String createProgressBar(@NotNull double size, @NotNull double per * Returns a message with capital letters after every whitespace *

    * See {@link #capitaliseSentenceKeepUpperCase(String)} - * + * * @param string The string to capitalise * @param keepCase Whether or not to keep the uppercase characters * @return {@link String} @@ -142,7 +145,7 @@ public static String capitaliseSentence(@NotNull String string, @NotNull Boolean *

    * See Alternate (keeping uppercase): * {@link #capitaliseSentenceKeepUpperCase(String)} - * + * * @param string The string to capitalise * @return {@link String} */ @@ -158,16 +161,16 @@ public static String capitaliseSentence(@NotNull String string) { * Example: "hello world" == "Hello World" *

    * Example: "hello WORLD" == "Hello WORLD" - * + * *

    * See Alternate (not keeping uppercase): {@link #capitaliseSentence(String)} - * + * *

    * Returns a message with capital letters after every whitespace - * - * @since 2.0 + * * @param string The string to capitalise * @return {@link String} + * @since 2.0 */ public static String capitaliseSentenceKeepUpperCase(@NotNull String string) { return capitaliseSentence(string, true); @@ -177,7 +180,7 @@ public static String capitaliseSentenceKeepUpperCase(@NotNull String string) { * Replace a word with asterisks. *

    * The censored word - * + * * @param word The word to censor * @param regex The characters to not censor * @return {@link String} @@ -201,7 +204,7 @@ public static String censorWord(@NotNull String word, @NotNull String regex) { * *

    * The censored word - * + * * @param word The word to censor * @return {@link String} */ @@ -213,14 +216,14 @@ public static String censorWord(@NotNull String word) { * Filter "Leet Speak" out of a message *

    * Example: - * + * *

          * Translation.replaceLeet("50m3 1337 5p34k h3r3") = "some leet speak here"
          * 
    - * + * *

    * The filtered message - * + * * @param message The message to filter * @return {@link String} */ @@ -236,10 +239,10 @@ public static String replaceLeet(@NotNull String message) { /** * Check if many strings equal a single comparison string - * + * *

    * Whether something matches. - * + * * @param haystack the string to compare to * @param needles things that may match the comparison string * @return {@link Boolean} @@ -269,15 +272,30 @@ public static boolean startsWithIgnoreCase(@NotNull final String string, @NotNul return string.regionMatches(true, 0, prefix, 0, prefix.length()); } + /** + * This method uses a region to check case-sensitive equality. + * + * @param string String to check + * @param prefix Prefix of string to compare + * @return {@link Boolean} + * @throws NullPointerException if prefix or string is null + */ + public static boolean startsWith(@NotNull final String string, @NotNull final String prefix) { + if (string.length() < prefix.length()) { + return false; + } + return string.regionMatches(false, 0, prefix, 0, prefix.length()); + } + /** * Put hyphens into a uuid *

    * e.x. de8c89e12f25424d8078c6ff58db7d6e > * de8c89e1-2f25-424d-8078-c6ff58db7d6e - * + * * @param uuid to hyphenate * @return {@link UUID} - * @throws NullPointerException if uuid string is null + * @throws NullPointerException if uuid string is null * @throws IllegalArgumentException if uuid is not 32 characters and is invalid */ public static UUID hyphenateUUID(@NotNull String uuid) { @@ -291,18 +309,20 @@ public static UUID hyphenateUUID(@NotNull String uuid) { } - - /** * Creates a random string of "magic" characters of characters - * @param min the minimum length of the string (inclusive) - * @param max the maximum length of the string (exclusive) + * + * @param min the minimum length of the string (inclusive) + * @param max the maximum length of the string (inclusive) + * @param minRunBeforeSpace Minimum number of characters before a space can appear, set to 0 to disable space * @return A string of random characters, where the length */ - public static String randomObfuscatedString(int min, int max) { + public static String randomObfuscatedString(int min, int max, int minRunBeforeSpace) { + Preconditions.checkArgument(max >= min, "Max cannot be less than min"); // Placeholder chars by width - char [] choices = new char[] { - ' ', // 1 px + char[] choices = new char[]{ + // Space is boring + // ' ', // 1 px 'i', // 2 px 'l', // 3 px 't', // 4 px @@ -311,21 +331,33 @@ public static String randomObfuscatedString(int min, int max) { '@' // 7 px }; StringBuilder obfuscated = new StringBuilder(); - obfuscated.append(ChatColor.COLOR_CHAR).append(ChatColor.MAGIC); - int len = MathUtil.randomInt(max) - min; - for(int i = 0; i < max; i++){ - obfuscated.append(choices[MathUtil.randomInt(choices.length)]); + + int len = MathUtil.randomInt(min, max); + int charsSinceSpace = 0; + while (obfuscated.length() < len) { + if ( minRunBeforeSpace > 0 && + charsSinceSpace > minRunBeforeSpace && + // Set a 5% probability of the character being a space + MathUtil.randomInt(1, 100) <= 5) { + obfuscated.append(' '); + charsSinceSpace = 0; + } else { + obfuscated.append(MathUtil.randomElement(choices)); + charsSinceSpace++; + } } - obfuscated.append(ChatColor.COLOR_CHAR).append(ChatColor.RESET); + obfuscated.insert(0, ChatColor.MAGIC); + obfuscated.append(ChatColor.RESET); return obfuscated.toString(); } /** * Replaces & followed by any valid minecraft format code (matching the regex

    (?=([a-f]|[0-9]|[klmnor]))
    with § + * * @param input The input string * @return A string where the relevant ampersands are replaced with section symbols */ - public static String formatChatCodes(String input){ + public static String formatChatCodes(String input) { return input.replaceAll("&(?=([a-f]|[0-9]|[klmnor]))", Character.toString(ChatColor.COLOR_CHAR)); } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java index a0df7adb..12f22979 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java @@ -13,6 +13,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.protocol.packet.Chat; + import java.io.InputStream; import java.io.InputStreamReader; import java.util.HashMap; @@ -121,8 +124,9 @@ public static int getCharacterWidth(char c) throws IllegalArgumentException{ * @return The width of the string, in half-pixels */ public static int getStringWidth(@NonNull String text, boolean isBold) { + text = ChatColor.stripColor(text); int width = 0; - + for (char c : text.toCharArray()) { width += TextUtil.getCharacterWidth(c); } diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/StringUtilTest.java b/src/test/java/com/dumbdogdiner/stickyapi/common/util/StringUtilTest.java index 2e01cb0b..1e2173c4 100644 --- a/src/test/java/com/dumbdogdiner/stickyapi/common/util/StringUtilTest.java +++ b/src/test/java/com/dumbdogdiner/stickyapi/common/util/StringUtilTest.java @@ -4,8 +4,11 @@ */ package com.dumbdogdiner.stickyapi.common.util; +import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; +import net.md_5.bungee.api.ChatColor; + import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -219,4 +222,16 @@ public void testHyphenateUUIDNull() { StringUtil.hyphenateUUID(null); }); } + + @RepeatedTest(100) + public void testRandomObfuscatedString() { + String rand = StringUtil.randomObfuscatedString(3,3, 0); + assertTrue(StringUtil.startsWith(rand, ChatColor.MAGIC.toString())); + System.out.println(rand); + assertEquals(3, ChatColor.stripColor(rand).length()); + + rand = StringUtil.randomObfuscatedString(1, 100, 0); + assertTrue(ChatColor.stripColor(rand).length() >= 1 && ChatColor.stripColor(rand).length() <= 100); + System.out.println(rand); + } } From 812abb0fb2ccaa2dd3bc38c2773ab21c2de85a32 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sat, 6 Feb 2021 15:11:02 -0700 Subject: [PATCH 47/79] minor fixup --- .../stickyapi/common/util/MathUtil.java | 4 ++-- .../stickyapi/common/util/TextUtil.java | 3 +-- .../stickyapi/common/util/TimeUtil.java | 2 +- .../common/util/reflection/UnsafeUtil.java | 5 ++--- .../stickyapi/common/util/url/URLPair.java | 16 +++++----------- .../stickyapi/bukkit/item/BookBuilderTest.java | 4 ++++ .../stickyapi/common/util/StringUtilTest.java | 1 + .../util/reflection/ReflectionUtilTest.java | 3 ++- 8 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java index 4b578d54..68c6c198 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java @@ -44,8 +44,8 @@ public static int randomInt(int max) { * Get a random number within a range *

    * - * @param min minimum value (inclusive) - * @param max maximum value (inclusive) + * @param min minimum value (inclusive) + * @param max maximum value (inclusive) * @return a random integer within the specified range * @throws IllegalArgumentException when min is greater than max */ diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java index 12f22979..8cc6b77b 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java @@ -48,7 +48,6 @@ public class TextUtil { /** Number of lines per sign */ public static final int LINES_PER_SIGN = 4; - private static final Pattern SPLIT_PATTERN = Pattern.compile("(?<=[ \n])|(?=[ \n])"); private static final HashMap widths = new HashMap<>(); @@ -126,7 +125,7 @@ public static int getCharacterWidth(char c) throws IllegalArgumentException{ public static int getStringWidth(@NonNull String text, boolean isBold) { text = ChatColor.stripColor(text); int width = 0; - + for (char c : text.toCharArray()) { width += TextUtil.getCharacterWidth(c); } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java index 62dbf3ec..c1fbdf6e 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java @@ -226,7 +226,7 @@ public static Optional duration(@NotNull String string) { if ((ch >= '0') && (ch <= '9')) subtotal = (subtotal * 10) + (ch - '0'); else { - // Found something thats not a number, find out how much it multiplies the built + // Found something that's not a number, find out how much it multiplies the built // up number by, multiply the total and reset the built up number. Long multiplier = TimeUtil.DURATION_CHARS.get(ch); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/UnsafeUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/UnsafeUtil.java index af460e8d..4bbc3672 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/UnsafeUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/UnsafeUtil.java @@ -8,6 +8,7 @@ import java.util.logging.Level; import java.util.logging.Logger; +import lombok.experimental.UtilityClass; import sun.misc.Unsafe; /** @@ -17,10 +18,8 @@ * * @since 2.0 */ +@UtilityClass public class UnsafeUtil { - private UnsafeUtil() { - } - /** * Get an instance of the Unsafe class. * diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLPair.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLPair.java index 3b400fbd..06d29054 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLPair.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLPair.java @@ -4,24 +4,18 @@ */ package com.dumbdogdiner.stickyapi.common.util.url; +import lombok.Data; + /** * Sub-class for easier URL formatting between methods. */ +@Data public class URLPair { - String fullPath; - String shortened; + private String fullPath; + private String shortened; public URLPair(String fullUrl, String shortenedUrl) { this.fullPath = fullUrl; this.shortened = shortenedUrl; } - - public String getShortened() { - return shortened; - } - - public String getFullPath() { - return fullPath; - } - } diff --git a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/BookBuilderTest.java b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/BookBuilderTest.java index b24fcd51..c73a5e23 100644 --- a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/BookBuilderTest.java +++ b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/BookBuilderTest.java @@ -17,5 +17,9 @@ public void testJsonBuild(){ System.out.println("Pages NBT:"); System.out.println(bb.generatePagesNBT()); + + + System.out.println("Please paste the following line into a command block, and activate it"); + System.out.println("give @p minecraft:writable_book" + bb.generatePagesNBT()); } } diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/StringUtilTest.java b/src/test/java/com/dumbdogdiner/stickyapi/common/util/StringUtilTest.java index 1e2173c4..bfb6db78 100644 --- a/src/test/java/com/dumbdogdiner/stickyapi/common/util/StringUtilTest.java +++ b/src/test/java/com/dumbdogdiner/stickyapi/common/util/StringUtilTest.java @@ -232,6 +232,7 @@ public void testRandomObfuscatedString() { rand = StringUtil.randomObfuscatedString(1, 100, 0); assertTrue(ChatColor.stripColor(rand).length() >= 1 && ChatColor.stripColor(rand).length() <= 100); + assertEquals(ChatColor.stripColor(rand).length(), rand.length() - 4); System.out.println(rand); } } diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtilTest.java b/src/test/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtilTest.java index a31d93b3..e0241b7c 100644 --- a/src/test/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtilTest.java +++ b/src/test/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtilTest.java @@ -7,6 +7,7 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; public class ReflectionUtilTest { private class ExampleClass { @@ -82,6 +83,6 @@ public void testGetProtectedValueObjectNoSuchField() { Object o = ReflectionUtil.getProtectedValue((Object) instance, "nonexistent_field"); - assertEquals(o, null); + assertNull(o); } } From 701dd0c563448f12740def6cd6e66ba4edc672e6 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sat, 6 Feb 2021 15:41:11 -0700 Subject: [PATCH 48/79] Javadoc fix --- .../java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java index 8cc6b77b..208f7640 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java @@ -23,7 +23,9 @@ import java.util.regex.Pattern; /** - * Utilities for text and books. + * Utilities for text, such as in chat, books, and signs + * + * @since 2.1.0 */ @UtilityClass public class TextUtil { From ad30a239bb49bc9fe7063e1b04ec4758aa45e2cc Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Fri, 12 Feb 2021 23:12:45 -0700 Subject: [PATCH 49/79] Add cool new nbt thingies --- build.gradle | 1 + .../stickyapi/common/nbt/NbtBooleanTag.java | 62 ++++++++++ .../stickyapi/common/nbt/NbtCompoundTag.java | 79 +++++++++++++ .../stickyapi/common/nbt/NbtJsonAdapter.java | 47 ++++++++ .../stickyapi/common/nbt/NbtJsonTag.java | 54 +++++++++ .../stickyapi/common/nbt/NbtListTag.java | 67 +++++++++++ .../stickyapi/common/nbt/NbtNumberTag.java | 85 ++++++++++++++ .../stickyapi/common/nbt/NbtPrimitiveTag.java | 20 ++++ .../stickyapi/common/nbt/NbtStringTag.java | 90 +++++++++++++++ .../stickyapi/common/nbt/NbtTag.java | 24 ++++ .../stickyapi/common/nbt/package-info.java | 9 ++ .../stickyapi/common/util/NumberUtil.java | 1 + .../stickyapi/common/util/StringUtil.java | 19 +++- .../common/nbt/NbtBooleanTagTest.java | 57 ++++++++++ .../common/nbt/NbtNumberTagTest.java | 106 ++++++++++++++++++ .../common/nbt/NbtStringTagTest.java | 37 ++++++ 16 files changed, 756 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTag.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtCompoundTag.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtJsonAdapter.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtJsonTag.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtListTag.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtNumberTag.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtPrimitiveTag.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTag.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtTag.java create mode 100644 src/main/java/com/dumbdogdiner/stickyapi/common/nbt/package-info.java create mode 100644 src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTagTest.java create mode 100644 src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtNumberTagTest.java create mode 100644 src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTagTest.java diff --git a/build.gradle b/build.gradle index 05b250c1..ebff8ea2 100644 --- a/build.gradle +++ b/build.gradle @@ -56,6 +56,7 @@ dependencies { implementation 'com.github.seancfoley:ipaddress:5.3.3' // Tests - JUnit 5 + testImplementation("org.junit.jupiter:junit-jupiter-params:5.7.0") testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.0") diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTag.java b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTag.java new file mode 100644 index 00000000..ce96ca71 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTag.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.nbt; + +import com.google.common.base.Preconditions; +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import org.jetbrains.annotations.NotNull; + + +/** + * A convenience class for converting booleans from {@link JsonPrimitive}s, and for easily creating + */ +public class NbtBooleanTag extends NbtPrimitiveTag { + private final boolean bool; + + public NbtBooleanTag(boolean bool) { + this.bool = bool; + } + + /** + * Converts a {@link JsonPrimitive} of a boolean to a new {@link NbtBooleanTag} + * It is recommended to make sure the primitive is a boolean first + * + * @param primitive The incoming {@link JsonPrimitive} to be converted, must be a boolean type! + * @return A new tag with tbe boolean value of the primitive + * @throws ClassCastException if the primitive is not a boolean + * @see JsonPrimitive#isBoolean() + */ + public static @NotNull NbtBooleanTag fromPrimitive(@NotNull JsonPrimitive primitive) throws ClassCastException { + return new NbtBooleanTag(primitive.getAsBoolean()); + } + + // As much as I hate the object form... we have to because generics + @Override + public @NotNull Boolean asPrimitive() { + return bool; + } + + @Override + public @NotNull JsonElement toJson() { + return new JsonPrimitive(bool); + } + + @Override + public @NotNull String toSNbt() { + return bool ? NbtNumberTag.TRUE.toSNbt() : NbtNumberTag.FALSE.toSNbt(); + } + + @Override + public boolean equals(Object other) { + if (other instanceof NbtBooleanTag) { + return ((NbtBooleanTag) other).asPrimitive() == bool; + } else if (other instanceof NbtNumberTag) { + return (!((NbtNumberTag) other).asPrimitive().equals(0)) == bool; + } else { + return false; + } + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtCompoundTag.java b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtCompoundTag.java new file mode 100644 index 00000000..a40d2d08 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtCompoundTag.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.nbt; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; +import java.util.StringJoiner; + +/** + * A wrapper tag that allows working with Compound NBT tags as maps! + */ +public class NbtCompoundTag extends HashMap implements NbtTag{ + + /** + * Creates a new {@link NbtCompoundTag} from an existing {@link Map} + * {@inheritDoc} + */ + public NbtCompoundTag(Map map) { + super(map); + } + + /** + * Create a new, blank {@link NbtCompoundTag} + * + * {@inheritDoc} + */ + public NbtCompoundTag() { + super(); + } + + /** + * Constructs a new {@link NbtCompoundTag} from a given {@link JsonObject} + */ + public static NbtCompoundTag fromJsonObject(JsonObject object){ + NbtCompoundTag tag = new NbtCompoundTag(); + for(String elementName : object.keySet()){ + tag.put(elementName, NbtJsonAdapter.jsonToNbt(object.get(elementName))); + } + return tag; + } + + @Override + public @NotNull JsonElement toJson() { + JsonObject object = new JsonObject(); + forEach((name, nbtTag) -> { + if(nbtTag instanceof NbtPrimitiveTag){ + Object primitive = ((NbtPrimitiveTag) nbtTag).asPrimitive(); + if(primitive instanceof NbtNumberTag){ + object.addProperty(name, ((NbtNumberTag) primitive).asPrimitive()); + } else if(primitive instanceof NbtBooleanTag){ + object.addProperty(name, ((NbtBooleanTag) primitive).asPrimitive()); + } else if(primitive instanceof NbtStringTag){ + object.addProperty(name, ((NbtStringTag) primitive).asPrimitive()); + } + } else { + object.add(name, nbtTag.toJson()); + } + }); + return object; + } + + @Override + public @NotNull String toSNbt() { + StringJoiner SNBT = new StringJoiner(",", "{", "}"); + forEach((name, nbtTag) -> { + StringJoiner element = new StringJoiner(":"); + element.add(name); + element.add(nbtTag.toSNbt()); + SNBT.add(element.toString()); + }); + return SNBT.toString(); + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtJsonAdapter.java b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtJsonAdapter.java new file mode 100644 index 00000000..63d588d2 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtJsonAdapter.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.nbt; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.NotNull; + +import java.text.MessageFormat; + +/** + * Utility class for easy creation of the appropriate {@link NbtTag} from an existing {@link JsonElement} + */ +@UtilityClass +public final class NbtJsonAdapter { + /** + * Creates the appropriate tag from a given {@link JsonElement}, but never creates a {@link NbtJsonTag} + * @param jse The incoming {@link JsonElement} to convert + * @return the new {@link NbtTag} + */ + public static NbtTag jsonToNbt(@NotNull JsonElement jse) { + if(jse.isJsonArray()){ + return NbtListTag.fromJsonArray(jse.getAsJsonArray()); + } else if(jse.isJsonObject()){ + return NbtCompoundTag.fromJsonObject(jse.getAsJsonObject()); + } else if(jse.isJsonPrimitive()){ + JsonPrimitive primitive = jse.getAsJsonPrimitive(); + if(primitive.isBoolean()){ + return NbtBooleanTag.fromPrimitive(primitive); + } else if(primitive.isNumber()){ + return NbtNumberTag.fromPrimitive(primitive); + } else if(primitive.isString()){ + return NbtStringTag.fromPrimitive(primitive); + } else { + throw new UnsupportedOperationException("Illegal type of NBT primitive"); + } + } else if(jse.isJsonNull()) { + return null; + } else { + throw new UnsupportedOperationException(MessageFormat.format("This type of JSONElement is unsupported ({0})", jse.getClass().getName())); + } + + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtJsonTag.java b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtJsonTag.java new file mode 100644 index 00000000..e72170c7 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtJsonTag.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.nbt; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import org.jetbrains.annotations.NotNull; + +/** + * A special type of {@link NbtTag} that converts an arbitrary {@link JsonElement} into an appropriately escaped string as SNBT + */ +public class NbtJsonTag implements NbtTag{ + private final @NotNull JsonElement element; + private static final Gson G = new GsonBuilder() + // Make sure things aren't weirdly escaped, may need to turn this back on + .disableHtmlEscaping() + .create(); + + public NbtJsonTag(@NotNull JsonElement element) { + this.element = element; + } + + /** + * {@inheritDoc} + */ + @Override + public @NotNull JsonElement toJson() { + return element; + } + + /** + * {@inheritDoc} + */ + @Override + public @NotNull String toSNbt() { + return '\'' + G.toJson(element) + // Because minecraft json is a hack on a hack..... + // And sometimes the NBT is just json that gets quoted + + .replaceAll("(?. All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.nbt; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.StringJoiner; + +/** + * A wrapper class that allows the construction of or conversion (from JSON) of SNBT List Tags + */ + +public class NbtListTag extends ArrayList implements NbtTag { + /** + * Converts a JSON array into an NBT List tag of the native types + * @param arr The Json Array to convert + * @return the new {@link NbtListTag} + */ + public static NbtListTag fromJsonArray(JsonArray arr){ + NbtListTag listTag = new NbtListTag(); + for(JsonElement jse : arr){ + listTag.add(NbtJsonAdapter.jsonToNbt(jse)); + } + return listTag; + } + + /** + * Creates an NBT tag that is a list of stringified JSON elements from source array + * @param arr Source JSON array to convert + * @return The newly converted NBT list tag + */ + public static NbtListTag fromJsonArrayQuoted(JsonArray arr){ + NbtListTag listTag = new NbtListTag(); + for(JsonElement jse : arr){ + listTag.add(new NbtJsonTag(jse)); + } + return listTag; + } + + @Override + public @NotNull JsonElement toJson() { + JsonArray array = new JsonArray(); + for(NbtTag tag : this){ + array.add(tag.toJson()); + } + return array; + } + + @Override + public @NotNull String toSNbt() { + StringJoiner joiner = new StringJoiner(",", "[", "]"); + forEach(nbtTag -> joiner.add(nbtTag.toSNbt())); + return joiner.toString(); + } + + /** + * Creates a {@link NbtStringTag} of escaped NBT as a string + */ + public NbtStringTag toNbtStringTag() { + return new NbtStringTag(toSNbt(), true); + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtNumberTag.java b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtNumberTag.java new file mode 100644 index 00000000..4d8abe9f --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtNumberTag.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.nbt; + +import com.google.common.base.Preconditions; +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.MessageFormat; +import java.text.NumberFormat; +import java.util.Locale; + +/** + * A wrapper class that allows you to deal with numbers in NBT + */ +public class NbtNumberTag extends NbtPrimitiveTag { + private final @NotNull Number number; + + // AFIK, Minecraft numbers are always in US type format, I.E. US style decimal separator + public static final @NotNull NumberFormat NUMBER_FORMAT = new DecimalFormat("#.##########", DecimalFormatSymbols.getInstance(Locale.US)); + public static final @NotNull NbtNumberTag TRUE = new NbtNumberTag(1); + public static final @NotNull NbtNumberTag FALSE = new NbtNumberTag(0); + + /** + * Create a new {@link NbtNumberTag} from an existing {@link Number} + * Warning: this may sometimes produce unintended consequences if the type of number is not supported by minecraft + * @param number the number to wrap + */ + public NbtNumberTag(@NotNull Number number) { + Preconditions.checkNotNull(number); + this.number = number; + } + + /** + * Converts a numerical {@link JsonPrimitive} to the {@link NbtNumberTag} wrapper type + * @param primitive the incoming primative to convert + * @return The newly created {@link NbtNumberTag} + */ + public static NbtNumberTag fromPrimitive(@NotNull JsonPrimitive primitive){ + Preconditions.checkNotNull(primitive); + Preconditions.checkArgument(primitive.isNumber(), "The primative must be a number"); + return new NbtNumberTag(primitive.getAsNumber()); + } + + /** + * {@inheritDoc} + */ + @Override + public @NotNull Number asPrimitive() { + return number; + } + + /** + * {@inheritDoc} + */ + @Override + public @NotNull JsonElement toJson() { + return new JsonPrimitive(number); + } + + /** + * {@inheritDoc} + */ + @Override + public @NotNull String toSNbt() { + return NUMBER_FORMAT.format(number); + } + + @Override + public boolean equals(Object other){ + if(other instanceof NbtNumberTag){ + return number.equals(((NbtNumberTag) other).asPrimitive()); + } else if(other instanceof NbtBooleanTag){ + return other.equals(this); + } else { + return false; + } + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtPrimitiveTag.java b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtPrimitiveTag.java new file mode 100644 index 00000000..4be701fe --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtPrimitiveTag.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.nbt; + +import org.jetbrains.annotations.NotNull; + +/** + * Base class for any NBT tags that wrap simple primitives (and strings) + * + * @param The type of primitive + */ +public abstract class NbtPrimitiveTag implements NbtTag { + /** + * Gets the original primitive back from the tag + */ + @NotNull + public abstract T asPrimitive(); +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTag.java b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTag.java new file mode 100644 index 00000000..a4a78662 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTag.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.nbt; + +import com.dumbdogdiner.stickyapi.common.util.StringUtil; +import com.google.common.base.Preconditions; +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import org.jetbrains.annotations.NotNull; + +/** + * A {@link NbtTag} that wraps and escapes {@link String}s + */ +public class NbtStringTag extends NbtPrimitiveTag { + private final String string; + private final boolean escaped; + + /** + * Creates a new NbtStringTag from a given string + * @param string The string to make a tag from + */ + public NbtStringTag(String string) { + this.string = string; + this.escaped = false; + } + + /** + * For package-local use only, allows preventing additional string escaping + * @see #NbtStringTag(String) + */ + NbtStringTag(String string, boolean escaped){ + this.string = string; + this.escaped = escaped; + } + + + /** + * Converts a {@link JsonPrimitive} into a new {@link NbtStringTag} + * + * @param primitive The incoming primitive + * @return a new {@link NbtStringTag} containing the string + * @throws IllegalArgumentException if the primitive type is wrong + * @see JsonPrimitive#isString() + */ + public static NbtStringTag fromPrimitive(JsonPrimitive primitive) throws IllegalArgumentException { + Preconditions.checkArgument(primitive.isString(), "The primitive must be a string"); + return new NbtStringTag(primitive.getAsString()); + } + + @Override + public String toString() { + return string; + } + + @Override + public @NotNull JsonElement toJson() { + return new JsonPrimitive(string); + } + + @SuppressWarnings("UnnecessaryStringEscape") + @Override + public @NotNull String toSNbt() { + // Make sure there are no other escapes needed + return '\'' + + (escaped ? string : StringUtil.formatChatCodes(string) + .replace("\'", "\\\'") + .replace("\"", "\\\"") + .replace("\n", "\\n")) + + '\''; + + } + + @Override + public @NotNull String asPrimitive() { + return string; + } + + @Override + public boolean equals(Object other){ + if(other instanceof NbtStringTag){ + return escaped == ((NbtStringTag) other).escaped && string.equals(((NbtStringTag) other).asPrimitive()); + } else if(other instanceof NbtJsonTag){ + return other.equals(this); + } else { + return false; + } + } +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtTag.java b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtTag.java new file mode 100644 index 00000000..41e28ed3 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtTag.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.nbt; + +import com.google.gson.JsonElement; +import org.jetbrains.annotations.NotNull; + +public interface NbtTag { + /** + * Converts the {@link NbtTag} back to a {@link JsonElement} + * @return a {@link JsonElement} of type equivalent to the source tag + */ + @NotNull + JsonElement toJson(); + + /** + * Converts a tag into Stringified NBT + * @return A representation of the object as Stringified NBT (SNbt) + */ + @NotNull + String toSNbt(); +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/package-info.java new file mode 100644 index 00000000..1e9b20c9 --- /dev/null +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/package-info.java @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +/** + * This package contains classes designed to help work with SNBT + */ + +package com.dumbdogdiner.stickyapi.common.nbt; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java index 9f64139f..1515543e 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java @@ -106,6 +106,7 @@ public static String getPercentageString(@NotNull int x, @NotNull int total) { * @return {@link Integer} * @throws IllegalArgumentException when min is greater than max */ + @Deprecated public static int getRandomNumber(@NotNull int min, @NotNull int max) { if (min >= max) throw new IllegalArgumentException("Min may not be greater than max!"); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java index 516852d0..dcaff3a6 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java @@ -9,14 +9,18 @@ import java.util.Map; import java.util.UUID; +import com.google.common.base.Preconditions; +import lombok.experimental.UtilityClass; + +import net.md_5.bungee.api.ChatColor; + import org.jetbrains.annotations.NotNull; /** * Operations on {@link java.lang.String} */ +@UtilityClass public final class StringUtil { - private StringUtil() { - } private static HashMap leetReplace = new HashMap<>(); @@ -287,4 +291,15 @@ public static UUID hyphenateUUID(@NotNull String uuid) { return UUID.fromString(uuid); } } + + /** + * Replaces & followed by any valid minecraft format code (matching the regex
    (?=([a-f]|[0-9]|[klmnor]))
    with § + * + * @param input The input string + * @return A string where the relevant ampersands are replaced with section symbols + */ + public static String formatChatCodes(String input) { + return input.replaceAll("&(?=([a-f]|[0-9]|[klmnor]))", Character.toString(ChatColor.COLOR_CHAR)); + } + } diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTagTest.java b/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTagTest.java new file mode 100644 index 00000000..8e55a1d3 --- /dev/null +++ b/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTagTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.nbt; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + + +import static org.junit.jupiter.api.Assertions.*; + +@RunWith(Parameterized.class) +class NbtBooleanTagTest { + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void fromPrimitive(boolean b) { + assertEquals(new NbtBooleanTag(b), NbtBooleanTag.fromPrimitive(new JsonPrimitive(b))); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void asPrimitive(boolean b) { + assertEquals(b, new NbtBooleanTag(b).asPrimitive()); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void toJson(boolean b) { + JsonPrimitive primitive = new JsonPrimitive(b); + assertEquals(primitive, new NbtBooleanTag(b).toJson()); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void toSNbt(boolean b) { + int i = b ? 1 : 0; + assertEquals(Integer.toString(i), new NbtBooleanTag(b).toSNbt()); + } + + @SuppressWarnings("AssertBetweenInconvertibleTypes") + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void equals(boolean b) { + int i = b ? 1 : 0; + assertEquals(new NbtNumberTag(i), new NbtBooleanTag(b)); + } +} \ No newline at end of file diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtNumberTagTest.java b/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtNumberTagTest.java new file mode 100644 index 00000000..cffcf033 --- /dev/null +++ b/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtNumberTagTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.nbt; + +import com.google.gson.JsonPrimitive; +import org.junit.Before; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.text.MessageFormat; + +import static com.dumbdogdiner.stickyapi.common.util.MathUtil.randomDouble; +import static com.dumbdogdiner.stickyapi.common.util.MathUtil.randomInt; +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assumptions.*; + +class NbtNumberTagTest { + private static final int REPEAT = 1000; + int i; + float f; + + @BeforeEach + public void setUp(){ + i = randomInt(-256, 4096); + f = (float) randomDouble(-256, 8192); + } + + @RepeatedTest(REPEAT) + void fromPrimitive() { + System.out.println(MessageFormat.format("i={0,number,#.##########}; f={1,number,#.##########}", i, f)); + JsonPrimitive iPrim = new JsonPrimitive(i); + JsonPrimitive fPrim = new JsonPrimitive(f); + assertEquals(new NbtNumberTag(i), NbtNumberTag.fromPrimitive(iPrim)); + assertEquals(new NbtNumberTag(f), NbtNumberTag.fromPrimitive(fPrim)); + } + + @RepeatedTest(REPEAT) + void asPrimitive() { + System.out.println(MessageFormat.format("i={0,number,#.##########}; f={1,number,#.##########}", i, f)); + assertEquals(i, new NbtNumberTag(i).asPrimitive()); + assertEquals(i, NbtNumberTag.fromPrimitive(new JsonPrimitive(i)).asPrimitive()); + assertEquals(f, new NbtNumberTag(f).asPrimitive()); + assertEquals(f, NbtNumberTag.fromPrimitive(new JsonPrimitive(f)).asPrimitive()); + } + + @RepeatedTest(REPEAT) + void toJson() { + System.out.println(MessageFormat.format("i={0,number,#.##########}; f={1,number,#.##########}", i, f)); + JsonPrimitive iPrim = new JsonPrimitive(i); + JsonPrimitive fPrim = new JsonPrimitive(f); + assertEquals(iPrim, new NbtNumberTag(i).toJson()); + assertEquals(iPrim, NbtNumberTag.fromPrimitive(iPrim).toJson()); + assertEquals(fPrim, new NbtNumberTag(f).toJson()); + assertEquals(fPrim, NbtNumberTag.fromPrimitive(fPrim).toJson()); + } + + @RepeatedTest(REPEAT) + void toSNbt() { + System.out.println(MessageFormat.format("i={0,number,#.##########}; f={1,number,#.##########}", i, f)); + String iString = new NbtNumberTag(i).toSNbt(); + String negativeIString = new NbtNumberTag(-i).toSNbt(); + String fString = new NbtNumberTag(f).toSNbt(); + String negativeFString = new NbtNumberTag(-f).toSNbt(); + assertEquals(NbtNumberTag.NUMBER_FORMAT.format(i), iString); + assertEquals(NbtNumberTag.NUMBER_FORMAT.format(f), fString); + assertEquals(NbtNumberTag.NUMBER_FORMAT.format(-i), negativeIString); + assertEquals(NbtNumberTag.NUMBER_FORMAT.format(-f), negativeFString); + + assumeTrue(i > -i); + assertFalse(iString.contains("-")); + assertFalse(iString.contains(".")); + assertFalse(iString.contains(",")); + assertTrue(negativeIString.contains("-")); + assertFalse(negativeIString.contains(".")); + assertFalse(negativeIString.contains(",")); + + assumeTrue(f != (int) f); + assumeTrue(f > -f); + assertTrue(fString.contains(".")); + assertFalse(fString.contains("-")); + assertFalse(fString.contains(",")); + assertTrue(negativeFString.contains(".")); + assertTrue(negativeFString.contains("-")); + assertFalse(negativeFString.contains(",")); + } + + @RepeatedTest(REPEAT) + void notEquals() { + assertNotEquals(new NbtNumberTag(i), NbtNumberTag.fromPrimitive(new JsonPrimitive(i - 1))); + assertNotEquals(new NbtNumberTag(f), NbtNumberTag.fromPrimitive(new JsonPrimitive(f + 0.1f))); + } + + @Test + @SuppressWarnings("AssertBetweenInconvertibleTypes") + void testEquals() { + assertEquals(new NbtNumberTag(0), NbtNumberTag.FALSE); + assertEquals(new NbtNumberTag(0), new NbtBooleanTag(false)); + assertEquals(new NbtNumberTag(1), NbtNumberTag.TRUE); + assertEquals(new NbtNumberTag(1), new NbtBooleanTag(true)); + } +} diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTagTest.java b/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTagTest.java new file mode 100644 index 00000000..cd81582f --- /dev/null +++ b/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTagTest.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.nbt; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class NbtStringTagTest { + + @Test + void fromPrimitive() { + + } + + @Test + void testToString() { + } + + @Test + void toJson() { + } + + @Test + void toSNbt() { + } + + @Test + void asPrimitive() { + } + + @Test + void testEquals() { + } +} \ No newline at end of file From 6e68cc16155454159edf4e17eb2628c2c0ed4332 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Fri, 12 Feb 2021 23:42:20 -0700 Subject: [PATCH 50/79] Additional constructor for NbtCompoundTag --- .../stickyapi/common/nbt/NbtCompoundTag.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtCompoundTag.java b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtCompoundTag.java index a40d2d08..c3bccf62 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtCompoundTag.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtCompoundTag.java @@ -34,6 +34,16 @@ public NbtCompoundTag() { super(); } + /** + * Create a new {@link NbtCompoundTag} with an existing key and tag (useful for 1-element compound tags!) + * @param key The key to set + * @param tag The tag to assign + */ + public NbtCompoundTag(String key, NbtTag tag){ + super(); + put(key, tag); + } + /** * Constructs a new {@link NbtCompoundTag} from a given {@link JsonObject} */ From c722a7397267f623fed396f97b99fb99654d5396 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Fri, 12 Feb 2021 23:48:09 -0700 Subject: [PATCH 51/79] Allow creating NbtListTag with predefined array --- .../stickyapi/common/nbt/NbtListTag.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtListTag.java b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtListTag.java index f38c94c6..5bc55a30 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtListTag.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtListTag.java @@ -9,6 +9,7 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Arrays; import java.util.StringJoiner; /** @@ -16,6 +17,21 @@ */ public class NbtListTag extends ArrayList implements NbtTag { + /** + * Generates a new, empty {@link NbtListTag} + * {@inheritDoc} + */ + public NbtListTag() { + super(); + } + + /** + * Generate a new {@link NbtListTag} with elements from an existing array or individual objects + */ + public NbtListTag(NbtTag ... tags){ + super(Arrays.asList(tags)); + } + /** * Converts a JSON array into an NBT List tag of the native types * @param arr The Json Array to convert From 587bba958ee66bbe8575ae47a29499789b60c531 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Sat, 13 Feb 2021 00:00:08 -0700 Subject: [PATCH 52/79] Add convenience methods to NbtCompoundTag --- .../stickyapi/common/nbt/NbtCompoundTag.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtCompoundTag.java b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtCompoundTag.java index c3bccf62..94924910 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtCompoundTag.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtCompoundTag.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.StringJoiner; /** @@ -86,4 +87,32 @@ public static NbtCompoundTag fromJsonObject(JsonObject object){ }); return SNBT.toString(); } + + /** + * Convenience method to add a number directly to the compound tag with a given key + * @return The original number + */ + public @NotNull Number put(@NotNull String key, @NotNull Number n) { + put(key, new NbtNumberTag(n)); + return n; + } + + /** + * Convenience method to add a boolean directly to the compound tag with a given key + * @return The original boolean + */ + public boolean put(@NotNull String key, boolean b) { + put(key, new NbtBooleanTag(b)); + return b; + } + + /** + * Convenience method to add a String directly to the compound tag with a given key + * @return The original String + */ + public String put(@NotNull String key, @NotNull String s){ + put(key, new NbtStringTag(s)); + return s; + } + } From 3b212af70173100f57601e0ac7c54cf4cdee0153 Mon Sep 17 00:00:00 2001 From: Andrew Katz Date: Fri, 12 Feb 2021 23:16:24 -0700 Subject: [PATCH 53/79] Cleanups --- .../bukkit/item/BookAndQuillBuilder.java | 15 ++++-------- .../bukkit/item/WrittenBookBuilder.java | 16 ++++++------- .../bukkit/item/WrittenBookBuilderTest.java | 23 +++++++++++++++++++ 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java index 9cb04b08..c2cd88c5 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java @@ -12,6 +12,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import lombok.experimental.Accessors; import org.bukkit.Bukkit; @@ -34,6 +35,7 @@ @SuppressWarnings({"UnusedReturnValue", "unused"}) @Accessors(chain = true) +@NoArgsConstructor public class BookAndQuillBuilder { private JsonArray pages = new JsonArray(); private static final Gson G = new GsonBuilder().create(); @@ -46,11 +48,6 @@ public class BookAndQuillBuilder { @Getter private @Nullable String lore; - public BookAndQuillBuilder() { - - } - - /** * Creates a new BookGenerator from a given JsonObject, representing a book, which can * be obtained in whatever way you want. @@ -90,17 +87,15 @@ public BookAndQuillBuilder() { } /** - * Build a book from this generator. + * Build a book and quill from this generator. * - * @param qty Quantity of the item stack. * @return an {@link ItemStack} of the book, with pages and all other data */ @SuppressWarnings("deprecation") - public @NotNull ItemStack toItemStack(int qty) { - Preconditions.checkArgument(qty > 0 && qty <= 16, "Invalid quantity specified, qty should be greater than 0 and less than or equal to 16, but was " + qty); + public @NotNull ItemStack toItemStack() { Preconditions.checkState(pages.size() > 0, "Cannot generate book with no pages"); Preconditions.checkState(pages.size() < TextUtil.PAGES_PER_BOOK, "Cannot generate book with an invalid number of pages (must be less than " + TextUtil.PAGES_PER_BOOK + ")"); - ItemStack stack = new ItemStack(Material.WRITABLE_BOOK, qty); + ItemStack stack = new ItemStack(Material.WRITABLE_BOOK, 1); stack = Bukkit.getUnsafe().modifyItemStack(stack, generatePagesNBT()); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java index 8b6066f5..ff95a4d0 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java @@ -12,6 +12,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.Setter; import lombok.experimental.Accessors; @@ -34,6 +35,7 @@ */ @SuppressWarnings({"UnusedReturnValue", "unused"}) @Accessors(chain = true) +@NoArgsConstructor public class WrittenBookBuilder { private @NotNull JsonArray pages = new JsonArray(); /** @@ -69,9 +71,6 @@ public class WrittenBookBuilder { .disableHtmlEscaping() .create(); - public WrittenBookBuilder() { - - } /** * Creates a new BookGenerator from a given JsonObject, representing a book, which can @@ -135,15 +134,15 @@ public WrittenBookBuilder() { /** * Build a book from this generator. * - * @param qty Quantity of the item stack. + * @param quantity Quantity of the item stack. * @return an {@link ItemStack} of the book, with pages and all other data */ @SuppressWarnings("deprecation") - public @NotNull ItemStack toItemStack(int qty) { - Preconditions.checkArgument(qty > 0 && qty <= 16, "Invalid quantity specified, qty should be greater than 0 and less than or equal to 16, but was " + qty); + public @NotNull ItemStack toItemStack(int quantity) { + Preconditions.checkArgument(quantity > 0 && quantity <= 16, "Invalid quantity specified, quantity should be greater than 0 and less than or equal to 16, but was " + quantity); Preconditions.checkState(pages.size() > 0, "Cannot generate book with no pages"); Preconditions.checkState(pages.size() < TextUtil.PAGES_PER_BOOK, "Cannot generate book with an invalid number of pages (must be less than " + TextUtil.PAGES_PER_BOOK + ")"); - ItemStack stack = new ItemStack(Material.WRITTEN_BOOK, qty); + ItemStack stack = new ItemStack(Material.WRITTEN_BOOK, quantity); stack = Bukkit.getUnsafe().modifyItemStack(stack, generatePagesNBT()); @@ -188,13 +187,14 @@ public boolean isFull() { pages.forEach(jsonElement -> { if (jsonElement instanceof JsonArray) { JsonArray newArr = new JsonArray(); - newArr.add(""); + newArr.add(""); // TODO test without this and see what happens, if bad things then make custom element i guess newArr.addAll(jsonElement.getAsJsonArray()); jsonElement = newArr; } NBT.add("'" + G.toJson(jsonElement) // Because minecraft json is a hack on a hack..... + // And we don't have any NBT compound tag classes or similar .replaceAll("(? Date: Sat, 13 Feb 2021 00:32:13 -0700 Subject: [PATCH 54/79] Finish cleaned version of book stuff --- .../bukkit/item/BookAndQuillBuilder.java | 65 +++++++---- .../bukkit/item/WrittenBookBuilder.java | 108 ++++++++++++------ .../bukkit/item/BookBuilderTest.java | 4 +- .../bukkit/item/WrittenBookBuilderTest.java | 18 +-- src/test/resources/rulebook.json | 13 ++- 5 files changed, 133 insertions(+), 75 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java index c2cd88c5..c1fb3a3d 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java @@ -4,6 +4,10 @@ */ package com.dumbdogdiner.stickyapi.bukkit.item; +import com.dumbdogdiner.stickyapi.common.nbt.NbtCompoundTag; +import com.dumbdogdiner.stickyapi.common.nbt.NbtJsonTag; +import com.dumbdogdiner.stickyapi.common.nbt.NbtListTag; +import com.dumbdogdiner.stickyapi.common.nbt.NbtStringTag; import com.dumbdogdiner.stickyapi.common.util.TextUtil; import com.dumbdogdiner.stickyapi.common.util.StringUtil; import com.google.common.base.Preconditions; @@ -23,6 +27,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.VisibleForTesting; +import java.awt.print.Book; import java.util.Collections; import java.util.StringJoiner; @@ -37,16 +42,14 @@ @Accessors(chain = true) @NoArgsConstructor public class BookAndQuillBuilder { - private JsonArray pages = new JsonArray(); + private @NotNull JsonArray pages = new JsonArray(); private static final Gson G = new GsonBuilder().create(); @Setter @Getter private @Nullable String displayName; - @Setter - @Getter - private @Nullable String lore; + private JsonArray lore = new JsonArray(); /** * Creates a new BookGenerator from a given JsonObject, representing a book, which can @@ -57,7 +60,12 @@ public class BookAndQuillBuilder { */ public static @NotNull BookAndQuillBuilder fromJson(@NotNull JsonObject bookObject) { BookAndQuillBuilder b = new BookAndQuillBuilder(); - b.pages = bookObject.get("pages").getAsJsonArray(); + JsonArray pages = bookObject.get("pages").getAsJsonArray(); + Preconditions.checkNotNull(pages); + b.pages = pages; + if(bookObject.has("lore") && bookObject.get("lore").isJsonArray()){ + b.lore = bookObject.get("lore").getAsJsonArray(); + } return b; } @@ -97,15 +105,7 @@ public class BookAndQuillBuilder { Preconditions.checkState(pages.size() < TextUtil.PAGES_PER_BOOK, "Cannot generate book with an invalid number of pages (must be less than " + TextUtil.PAGES_PER_BOOK + ")"); ItemStack stack = new ItemStack(Material.WRITABLE_BOOK, 1); - stack = Bukkit.getUnsafe().modifyItemStack(stack, generatePagesNBT()); - - ItemMeta im = stack.getItemMeta(); - if (displayName != null) - im.setDisplayName(StringUtil.formatChatCodes(displayName)); - - if (lore != null) - im.setLore(Collections.singletonList(lore)); - stack.setItemMeta(im); + stack = Bukkit.getUnsafe().modifyItemStack(stack, generateNBT()); return stack; } @@ -127,21 +127,38 @@ public boolean isFull() { return percentFull() >= 1.0f; } + /** + * Adds a line of lore (formatted JSON text stuffs) to the book + */ + public @NotNull BookAndQuillBuilder addLoreLine(JsonObject lore){ + this.lore.add(lore); + return this; + } + + public @NotNull BookAndQuillBuilder addLoreLines(JsonObject ... lores){ + for(JsonObject lore : lores){ + addLoreLine(lore); + } + return this; + } + /** * Uses a {@link StringJoiner} to convert pages JsonArray to the weird NBT list * * @return {@link String} with NBT of the pages */ @VisibleForTesting - public @NotNull String generatePagesNBT() { - StringJoiner NBT = new StringJoiner(",", "{pages:[", "]}"); - pages.forEach(jsonElement -> - NBT.add(G.toJson(jsonElement) - // Because minecraft json is a hack on a hack..... - .replace("\n", "\\n") - .replace("\\", "\\\\")) - - ); - return NBT.toString(); + public @NotNull String generateNBT() { + NbtCompoundTag bookNBT = new NbtCompoundTag(); + bookNBT.put("pages", NbtListTag.fromJsonArray(this.pages)); + NbtCompoundTag display = new NbtCompoundTag(); + if(displayName != null) + display.put("Name", displayName); + if(lore.size() > 0){ + display.put("Lore", NbtListTag.fromJsonArrayQuoted(lore)); + } + if(!display.isEmpty()) + bookNBT.put("display", display); + return bookNBT.toSNbt(); } } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java index ff95a4d0..9a98f4e9 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java @@ -4,6 +4,9 @@ */ package com.dumbdogdiner.stickyapi.bukkit.item; +import com.dumbdogdiner.stickyapi.common.nbt.NbtCompoundTag; +import com.dumbdogdiner.stickyapi.common.nbt.NbtListTag; +import com.dumbdogdiner.stickyapi.common.nbt.NbtStringTag; import com.dumbdogdiner.stickyapi.common.util.TextUtil; import com.dumbdogdiner.stickyapi.common.util.StringUtil; import com.google.common.base.Preconditions; @@ -62,9 +65,14 @@ public class WrittenBookBuilder { /** * Lore/hover text for the item */ + private @NotNull JsonArray lore = new JsonArray(); + + /** + * The book display name (In inventory) + */ @Getter @Setter - private @Nullable String lore; + private @Nullable String displayName; private static final Gson G = new GsonBuilder() // Make sure things aren't weirdly escaped, may need to turn this back on @@ -101,11 +109,43 @@ public class WrittenBookBuilder { default: b.generation = BookMeta.Generation.ORIGINAL; } + if(bookObject.has("lore") && bookObject.get("lore").isJsonArray()) + b.lore = bookObject.get("lore").getAsJsonArray(); b.pages = bookObject.get("pages").getAsJsonArray(); return b; } + /** + * Adds a line of lore (formatted JSON text stuffs) to the book + */ + public @NotNull WrittenBookBuilder addLoreLine(JsonObject lore){ + this.lore.add(lore); + return this; + } + + public @NotNull WrittenBookBuilder addLoreLines(JsonObject ... lores){ + for(JsonObject lore : lores){ + addLoreLine(lore); + } + return this; + } + + /** + * Adds a line of lore (formatted JSON text stuffs) to the book + */ + public @NotNull WrittenBookBuilder addLoreLine(NbtStringTag lore){ + this.lore.add(lore.toJson()); + return this; + } + + public @NotNull WrittenBookBuilder addLoreLines(NbtStringTag ... lores){ + for(NbtStringTag lore : lores){ + addLoreLine(lore); + } + return this; + } + /** * Add some pages to the book. May fail with {@link IllegalStateException} if the book is full or fills up. * @@ -144,17 +184,7 @@ public class WrittenBookBuilder { Preconditions.checkState(pages.size() < TextUtil.PAGES_PER_BOOK, "Cannot generate book with an invalid number of pages (must be less than " + TextUtil.PAGES_PER_BOOK + ")"); ItemStack stack = new ItemStack(Material.WRITTEN_BOOK, quantity); - stack = Bukkit.getUnsafe().modifyItemStack(stack, generatePagesNBT()); - - BookMeta meta = (BookMeta) stack.getItemMeta(); - //noinspection ConstantConditions - meta.setTitle(title != null ? StringUtil.formatChatCodes(title) : ""); - //noinspection ConstantConditions - meta.setAuthor(author != null ? StringUtil.formatChatCodes(author) : ""); - meta.setGeneration(generation); - if (lore != null) - meta.setLore(Collections.singletonList(StringUtil.formatChatCodes(lore))); - stack.setItemMeta(meta); + stack = Bukkit.getUnsafe().modifyItemStack(stack, generateNBT()); return stack; } @@ -182,26 +212,38 @@ public boolean isFull() { * @return {@link String} with NBT of the pages */ @VisibleForTesting - public @NotNull String generatePagesNBT() { - StringJoiner NBT = new StringJoiner(",", "{pages:[", "]}"); - pages.forEach(jsonElement -> { - if (jsonElement instanceof JsonArray) { - JsonArray newArr = new JsonArray(); - newArr.add(""); // TODO test without this and see what happens, if bad things then make custom element i guess - newArr.addAll(jsonElement.getAsJsonArray()); - jsonElement = newArr; - } - NBT.add("'" + - G.toJson(jsonElement) - // Because minecraft json is a hack on a hack..... - // And we don't have any NBT compound tag classes or similar - - .replaceAll("(? 0){ + display.put("Lore", NbtListTag.fromJsonArrayQuoted(lore)); + } + if(!display.isEmpty()) + bookNBT.put("display", display); + bookNBT.put("pages", NbtListTag.fromJsonArrayQuoted(pages)); + return bookNBT.toSNbt(); + } + + /** + * Gets the generation as an int + */ + private int getGenerationInt() { + switch (generation){ + case ORIGINAL: + return 0; + case COPY_OF_ORIGINAL: + return 1; + case COPY_OF_COPY: + return 2; + case TATTERED: + return 3; + default: + throw new IllegalStateException(); + } } } diff --git a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/BookBuilderTest.java b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/BookBuilderTest.java index c73a5e23..6884d01a 100644 --- a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/BookBuilderTest.java +++ b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/BookBuilderTest.java @@ -16,10 +16,10 @@ public void testJsonBuild(){ bb.addPages(new String [] {"yet more", "and more still"}); System.out.println("Pages NBT:"); - System.out.println(bb.generatePagesNBT()); + System.out.println(bb.generateNBT()); System.out.println("Please paste the following line into a command block, and activate it"); - System.out.println("give @p minecraft:writable_book" + bb.generatePagesNBT()); + System.out.println("give @p minecraft:writable_book" + bb.generateNBT()); } } diff --git a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilderTest.java b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilderTest.java index e148895f..8dd1e709 100644 --- a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilderTest.java +++ b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilderTest.java @@ -15,7 +15,6 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import com.google.gson.stream.JsonReader; import org.junit.jupiter.api.*; import java.io.IOException; @@ -81,21 +80,10 @@ public void testJSON(String filename) { JsonObject bookObject = JsonParser.parseReader(bookReader).getAsJsonObject(); WrittenBookBuilder bb = WrittenBookBuilder.fromJson(bookObject); System.out.println("Testing BookBuilder, please make sure the following NBT string is valid (It does not yet contain the title or author):"); - System.out.println(bb.generatePagesNBT()); + bb.addLoreLines(new NbtStringTag("The rules owo")); + System.out.println(bb.generateNBT()); System.out.println("Please paste the following line into a command block, and activate it"); - System.out.println("give @p minecraft:written_book" + makeValidWrittenBookNBT(bb)); - } - - /** - * Fix the command so it actually is valid, in a hacky way - * @param bookBuilder Original bookbuilder - * @return NBT that has the title forcibly put in - */ - private String makeValidWrittenBookNBT(WrittenBookBuilder bookBuilder) { - StringBuilder sb = new StringBuilder(); - sb.append(bookBuilder.generatePagesNBT()); - sb.insert(sb.length() - 1, StringUtil.formatChatCodes(MessageFormat.format(",title:\"{0}\",author:\"{1}\"", bookBuilder.getTitle(), bookBuilder.getAuthor()))); - return sb.toString(); + System.out.println("give @p minecraft:written_book" + bb.generateNBT()); } } diff --git a/src/test/resources/rulebook.json b/src/test/resources/rulebook.json index 5b361ee2..2dbc04f8 100644 --- a/src/test/resources/rulebook.json +++ b/src/test/resources/rulebook.json @@ -443,5 +443,16 @@ ] ], "title": "\u0026ddddMC Survival Handbook v1.0", - "author": "Stixil" + "author": "Stixil", + "lore" : [ + { + "text": "dddMC 2020", + "bold": true, + "color": "dark_purple" + }, + { + "text" : "", + "color": "reset" + } + ] } \ No newline at end of file From c08b56d1354f11891af55ea1a761e84d9f8185e9 Mon Sep 17 00:00:00 2001 From: James Date: Sat, 13 Feb 2021 12:07:31 +0000 Subject: [PATCH 55/79] Add note to comment in copyMCFontExtractor --- build.gradle | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 533ff057..426bccf1 100644 --- a/build.gradle +++ b/build.gradle @@ -153,7 +153,9 @@ task copyMCFontExtractor(type: Copy) { def path = project.configurations.compile.find {it.name.startsWith("mc-font-extractor") } println path from file(path) - //into file("src/main/resources") + // into file("src/main/resources") + // - Please keep this comment for future reference. + // - This is how we would do this if we weren't also adding build info (see processSourceTokens) destinationDir file("src/main/resources/generated/") rename 'mc-font-extractor-main-mojangles_width_data.json', 'mojangles_width_data.json' } From 8600bfc9e833ea30260071f072065f09b22b5c03 Mon Sep 17 00:00:00 2001 From: James Date: Sat, 13 Feb 2021 12:15:15 +0000 Subject: [PATCH 56/79] Move minify TODO to github issue for tracking --- build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.gradle b/build.gradle index 426bccf1..80d610b8 100644 --- a/build.gradle +++ b/build.gradle @@ -146,8 +146,6 @@ task processSourceTokens(type: Sync) { // Use the filter task as the input for compileJava compileJava.source = processSourceTokens.outputs -// TODO: Make task to minify resources (json) on compile - // Font Width Info task copyMCFontExtractor(type: Copy) { def path = project.configurations.compile.find {it.name.startsWith("mc-font-extractor") } From c0cc8b928a8375aa157d307d76a47a87a7f8f515 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 12:00:57 +0000 Subject: [PATCH 57/79] Recreate StringUtil from master --- .../stickyapi/common/util/StringUtil.java | 56 +++++++++++-------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java index 76e3b1c4..b289e5c5 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java @@ -7,9 +7,10 @@ import java.text.DecimalFormat; import java.util.HashMap; import java.util.Map; -import java.util.Random; import java.util.UUID; +import com.google.common.base.Preconditions; + import net.md_5.bungee.api.ChatColor; import org.jetbrains.annotations.NotNull; @@ -17,8 +18,9 @@ /** * Operations on {@link java.lang.String} */ -@UtilityClass public final class StringUtil { + private StringUtil() { + } private static HashMap leetReplace = new HashMap<>(); @@ -39,10 +41,10 @@ public final class StringUtil { /** * Create a horizontal progress bar, similar to how htop does it. - * + * *

    * Returns a progress bar - * + * * @param size The size of the bar (inside) * @param percentage The percentage to fill the bar to * @param monospace If false, the bars will be a character with the @@ -56,7 +58,7 @@ public final class StringUtil { * @return {@link String} */ public static String createProgressBar(@NotNull double size, @NotNull double percentage, @NotNull boolean monospace, - @NotNull boolean includePercentage, @NotNull boolean includeBrackets) { + @NotNull boolean includePercentage, @NotNull boolean includeBrackets) { double barCount = ((percentage / 100) * size); StringBuilder barBuilder = new StringBuilder(); for (double i = 0; i < size; i++) { @@ -85,7 +87,7 @@ public static String createProgressBar(@NotNull double size, @NotNull double per * Create a horizontal progress bar, similar to how htop does it. *

    * Returns a progress bar - * + * * @param size The size of the bar * @param percentage The percentage to fill the bar to * @return {@link String} @@ -107,7 +109,7 @@ public static String createProgressBar(@NotNull double size, @NotNull double per * Returns a message with capital letters after every whitespace *

    * See {@link #capitaliseSentenceKeepUpperCase(String)} - * + * * @param string The string to capitalise * @param keepCase Whether or not to keep the uppercase characters * @return {@link String} @@ -142,7 +144,7 @@ public static String capitaliseSentence(@NotNull String string, @NotNull Boolean *

    * See Alternate (keeping uppercase): * {@link #capitaliseSentenceKeepUpperCase(String)} - * + * * @param string The string to capitalise * @return {@link String} */ @@ -158,16 +160,16 @@ public static String capitaliseSentence(@NotNull String string) { * Example: "hello world" == "Hello World" *

    * Example: "hello WORLD" == "Hello WORLD" - * + * *

    * See Alternate (not keeping uppercase): {@link #capitaliseSentence(String)} - * + * *

    * Returns a message with capital letters after every whitespace - * + * + * @since 2.0 * @param string The string to capitalise * @return {@link String} - * @since 2.0 */ public static String capitaliseSentenceKeepUpperCase(@NotNull String string) { return capitaliseSentence(string, true); @@ -177,7 +179,7 @@ public static String capitaliseSentenceKeepUpperCase(@NotNull String string) { * Replace a word with asterisks. *

    * The censored word - * + * * @param word The word to censor * @param regex The characters to not censor * @return {@link String} @@ -201,7 +203,7 @@ public static String censorWord(@NotNull String word, @NotNull String regex) { * *

    * The censored word - * + * * @param word The word to censor * @return {@link String} */ @@ -213,14 +215,14 @@ public static String censorWord(@NotNull String word) { * Filter "Leet Speak" out of a message *

    * Example: - * + * *

          * Translation.replaceLeet("50m3 1337 5p34k h3r3") = "some leet speak here"
          * 
    - * + * *

    * The filtered message - * + * * @param message The message to filter * @return {@link String} */ @@ -236,10 +238,10 @@ public static String replaceLeet(@NotNull String message) { /** * Check if many strings equal a single comparison string - * + * *

    * Whether something matches. - * + * * @param haystack the string to compare to * @param needles things that may match the comparison string * @return {@link Boolean} @@ -289,7 +291,7 @@ public static boolean startsWith(@NotNull final String string, @NotNull final St *

    * e.x. de8c89e12f25424d8078c6ff58db7d6e > * de8c89e1-2f25-424d-8078-c6ff58db7d6e - * + * * @param uuid to hyphenate * @return {@link UUID} * @throws NullPointerException if uuid string is null @@ -348,13 +350,21 @@ public static String randomObfuscatedString(int min, int max, int minRunBeforeSp } /** - * Replaces & followed by any valid minecraft format code (matching the regex

    (?=([a-f]|[0-9]|[klmnor]))
    with § + * Replaces & followed by any valid minecraft format code (matching the + * regex + * + *
    +     * (?=([a-f]|[0-9]|[klmnor]))
    +     * 
    + * + * with § * * @param input The input string - * @return A string where the relevant ampersands are replaced with section symbols + * @return A string where the relevant ampersands are replaced with section + * symbols */ public static String formatChatCodes(String input) { return input.replaceAll("&(?=([a-f]|[0-9]|[klmnor]))", Character.toString(ChatColor.COLOR_CHAR)); } -} +} \ No newline at end of file From cc9f7d9e04dcfa0fef1cac41d7858b9a90854725 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 12:01:27 +0000 Subject: [PATCH 58/79] replace toSNbt with toNbtString --- .../dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java | 2 +- .../dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java | 2 +- .../stickyapi/bukkit/item/WrittenBookBuilderTest.java | 2 +- .../com/dumbdogdiner/stickyapi/common/nbt/NbtStringTagTest.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java index c1fb3a3d..fd16356c 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java @@ -159,6 +159,6 @@ public boolean isFull() { } if(!display.isEmpty()) bookNBT.put("display", display); - return bookNBT.toSNbt(); + return bookNBT.toNbtString(); } } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java index 9a98f4e9..40d0dbd9 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java @@ -226,7 +226,7 @@ public boolean isFull() { if(!display.isEmpty()) bookNBT.put("display", display); bookNBT.put("pages", NbtListTag.fromJsonArrayQuoted(pages)); - return bookNBT.toSNbt(); + return bookNBT.toNbtString(); } /** diff --git a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilderTest.java b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilderTest.java index 8dd1e709..0b4c012e 100644 --- a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilderTest.java +++ b/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilderTest.java @@ -72,7 +72,7 @@ void testNbtStuff() { pages.add(new NbtJsonTag(element)); } test123.put("pages", pages); - System.out.println("give @p minecraft:written_book" + test123.toSNbt()); + System.out.println("give @p minecraft:written_book" + test123.toNbtString()); } public void testJSON(String filename) { diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTagTest.java b/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTagTest.java index cd81582f..be5287c6 100644 --- a/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTagTest.java +++ b/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTagTest.java @@ -24,7 +24,7 @@ void toJson() { } @Test - void toSNbt() { + void toNbtString() { } @Test From 3ffa5b4d954c1459aa11e55bbf8410ee20cde36a Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 12:05:56 +0000 Subject: [PATCH 59/79] Adjust comments --- build.gradle | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index 80d610b8..0234273e 100644 --- a/build.gradle +++ b/build.gradle @@ -76,10 +76,6 @@ dependencies { // Tests - Mocking Suite (eg. mocking Bukkit for tests) testImplementation("org.mockito:mockito-core:3.7.7") -// -// // Mocked bukkit -// testImplementation 'com.github.seeseemelk:MockBukkit-v1.16:0.5.0' -// testImplementation group: 'it.unimi.dsi', name: 'fastutil', version: '8.2.1' } test { @@ -177,8 +173,8 @@ javadoc { options.overview('src/main/overview.html') outputs.upToDateWhen { false } - //TODO replace frames with JANITOR to get around removal of -frames in jdk15 - //options.footer("") + // TODO: replace frames with JANITOR to get around removal of -frames in jdk15 + // options.footer("") test.ignoreFailures true; dependsOn delombok } From edb522a089af82c024b3d2543bc0ade2d858a786 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 12:09:40 +0000 Subject: [PATCH 60/79] Add browseTests task --- build.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build.gradle b/build.gradle index 0234273e..a300f1b2 100644 --- a/build.gradle +++ b/build.gradle @@ -186,6 +186,14 @@ task browseJavadoc { } } +task browseTests { + dependsOn test + doLast { + java.awt.Desktop.desktop.browse new URI(("file:///" << System.getProperty("user.dir").replace('\\','/') << "/build/reports/tests/test/index.html").toString()) + java.awt.Desktop.desktop.browse new URI(("file:///" << System.getProperty("user.dir").replace('\\','/') << "/build/reports/jacoco/test/html/index.html").toString()) + } +} + publishing { repositories { maven { From 16758cd727cde0c1e6c0a22d3e33b0a96932b26c Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 12:10:58 +0000 Subject: [PATCH 61/79] Don't bump version --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a300f1b2..3a36d27c 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ jacoco { group = 'com.dumbdogdiner' -version = '2.2.0' +version = '2.1.0' // License Plugin Options license { From 699c05478d336a4f332d97ea145d1e236898a1a4 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 13:11:22 +0000 Subject: [PATCH 62/79] (1st pass) going back to private constructors for now --- .../com/dumbdogdiner/stickyapi/common/ServerVersion.java | 6 +++--- .../com/dumbdogdiner/stickyapi/common/util/IPUtil.java | 5 +++-- .../com/dumbdogdiner/stickyapi/common/util/MemoryUtil.java | 5 +++-- .../com/dumbdogdiner/stickyapi/common/util/NumberUtil.java | 5 +++-- .../com/dumbdogdiner/stickyapi/common/util/ShortID.java | 5 ++--- .../com/dumbdogdiner/stickyapi/common/util/TimeUtil.java | 7 ++++--- .../stickyapi/common/util/reflection/UnsafeUtil.java | 5 +++-- .../dumbdogdiner/stickyapi/common/util/url/URLUtil.java | 5 +++-- 8 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java b/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java index da6f8d57..2caf8826 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java @@ -4,13 +4,13 @@ */ package com.dumbdogdiner.stickyapi.common; -import lombok.experimental.UtilityClass; - /** * Utility class for fetching version data. */ -@UtilityClass public final class ServerVersion { + private ServerVersion() { + } + public enum ServerType { BUKKIT, SPIGOT, PAPER, BUNGEE, WATERFALL } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/IPUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/IPUtil.java index 257a1d22..d1e0f45b 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/IPUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/IPUtil.java @@ -4,7 +4,6 @@ */ package com.dumbdogdiner.stickyapi.common.util; -import lombok.experimental.UtilityClass; import org.jetbrains.annotations.NotNull; import inet.ipaddr.IPAddress; @@ -13,8 +12,10 @@ /** * Utility class for IP Addresses */ -@UtilityClass public final class IPUtil { + private IPUtil() { + } + /** * Check if an IP Address is within a CIDR range *

    diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MemoryUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/MemoryUtil.java index 3725a382..33379947 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MemoryUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/MemoryUtil.java @@ -8,7 +8,6 @@ import java.lang.reflect.Modifier; import com.dumbdogdiner.stickyapi.common.util.reflection.ReflectionUtil; -import lombok.experimental.UtilityClass; /** * Provides a very crude method of measuring the memory consumption of Java @@ -16,8 +15,10 @@ * with each new object, but can be useful to measure the estimated size of an * object. */ -@UtilityClass public final class MemoryUtil { + private MemoryUtil() { + } + public enum Unit { BITS, BYTES, KILOBYTES, MEGABYTES } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java index 1b9e1360..1515543e 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java @@ -4,7 +4,6 @@ */ package com.dumbdogdiner.stickyapi.common.util; -import lombok.experimental.UtilityClass; import org.jetbrains.annotations.NotNull; /** @@ -12,8 +11,10 @@ * Provides extra functionality for Java Number classes. *

    */ -@UtilityClass public final class NumberUtil { + private NumberUtil() { + } + /** *

    * Checks if the String contains only unicode digits. A decimal point is not a diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/ShortID.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/ShortID.java index 231b9333..154a130f 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/ShortID.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/ShortID.java @@ -8,13 +8,12 @@ import java.util.UUID; import java.util.zip.CRC32; -import lombok.experimental.UtilityClass; import org.apache.commons.lang.Validate; import org.jetbrains.annotations.NotNull; -// TODO this is in the apache validation used in another PR -@UtilityClass final class Luhn { + private Luhn() { + } /** * Checks if the card is valid diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java index c1fbdf6e..b729daa8 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java @@ -14,14 +14,15 @@ import javax.annotation.Nullable; -import lombok.experimental.UtilityClass; import org.jetbrains.annotations.NotNull; /** * Utility methods for dealing with time and duration parsing. */ -@UtilityClass public final class TimeUtil { + private TimeUtil() { + } + private static final SimpleDateFormat sdf = new SimpleDateFormat("EEE, MMM d yyyy HH:mm:ss"); private static final HashMap DURATION_CHARS = new HashMap<>(); @@ -226,7 +227,7 @@ public static Optional duration(@NotNull String string) { if ((ch >= '0') && (ch <= '9')) subtotal = (subtotal * 10) + (ch - '0'); else { - // Found something that's not a number, find out how much it multiplies the built + // Found something thats not a number, find out how much it multiplies the built // up number by, multiply the total and reset the built up number. Long multiplier = TimeUtil.DURATION_CHARS.get(ch); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/UnsafeUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/UnsafeUtil.java index 4bbc3672..af460e8d 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/UnsafeUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/UnsafeUtil.java @@ -8,7 +8,6 @@ import java.util.logging.Level; import java.util.logging.Logger; -import lombok.experimental.UtilityClass; import sun.misc.Unsafe; /** @@ -18,8 +17,10 @@ * * @since 2.0 */ -@UtilityClass public class UnsafeUtil { + private UnsafeUtil() { + } + /** * Get an instance of the Unsafe class. * diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java index 4b65fb33..dde8d1c4 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java @@ -7,7 +7,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import lombok.experimental.UtilityClass; import net.md_5.bungee.api.chat.HoverEvent; import net.md_5.bungee.api.chat.hover.content.Text; import org.jetbrains.annotations.NotNull; @@ -15,8 +14,10 @@ import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.TextComponent; -@UtilityClass public class URLUtil { + private URLUtil() { + } + private static final Pattern urlPattern = Pattern.compile( "(https:\\/\\/|http:\\/\\/)((?:[-;:&=\\+\\$,\\w]+@)?[A-Za-z0-9.-]+|(www.|[-;:&=\\+\\$,\\w]+@)[A-Za-z0-9.-]+)((?:\\/[\\+~%\\/.\\w-_]*)?\\??(?:[-\\+=&;%@.\\w_]*)#?(?:[\\w]*))?"); From 2b53a395189a9976b11fb8264553387fb3851258 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 13:15:20 +0000 Subject: [PATCH 63/79] Try to split annotation changes --- .../dumbdogdiner/stickyapi/annotation/OnHold.java | 15 --------------- .../stickyapi/annotation/Untested.java | 3 --- 2 files changed, 18 deletions(-) delete mode 100644 src/main/java/com/dumbdogdiner/stickyapi/annotation/OnHold.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/annotation/OnHold.java b/src/main/java/com/dumbdogdiner/stickyapi/annotation/OnHold.java deleted file mode 100644 index 27e4c383..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/annotation/OnHold.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.annotation; - -import java.lang.annotation.Documented; - -/** - * Denotes a feature or class that is in-progress but has had development halted - */ -@Documented -public @interface OnHold { - -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/annotation/Untested.java b/src/main/java/com/dumbdogdiner/stickyapi/annotation/Untested.java index 5bd7d1b3..590e1862 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/annotation/Untested.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/annotation/Untested.java @@ -6,9 +6,6 @@ import java.lang.annotation.Documented; -/** - * Denotes beta features that are not officially stable/tested - */ @Documented public @interface Untested { } From afc755a525e7b828d48aa156d70f53d62321196b Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 13:24:41 +0000 Subject: [PATCH 64/79] Split VoidGenerator changes into own pr --- .../stickyapi/bukkit/generator/VoidGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java index 69588027..3ffdbc06 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java @@ -16,7 +16,7 @@ public class VoidGenerator extends ChunkGenerator { @Override - public @NotNull ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome) { + public ChunkData generateChunkData(@NotNull World world, Random random, int x, int z, BiomeGrid biome) { return createChunkData(world); } -} +} \ No newline at end of file From 10791819dadd03bd243d7de745457dfbe379631f Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 13:28:55 +0000 Subject: [PATCH 65/79] Improved instance naming --- .../bukkit/item/BookAndQuillBuilder.java | 8 ++++---- .../bukkit/item/WrittenBookBuilder.java | 20 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java index fd16356c..95b1f4a5 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java @@ -59,14 +59,14 @@ public class BookAndQuillBuilder { * @return a {@link BookAndQuillBuilder} with the specified pages; if a title and author are both specified, it will be a {@link Material#WRITTEN_BOOK}, otherwise it will be a {@link Material#WRITABLE_BOOK} */ public static @NotNull BookAndQuillBuilder fromJson(@NotNull JsonObject bookObject) { - BookAndQuillBuilder b = new BookAndQuillBuilder(); + BookAndQuillBuilder bookBuilder = new BookAndQuillBuilder(); JsonArray pages = bookObject.get("pages").getAsJsonArray(); Preconditions.checkNotNull(pages); - b.pages = pages; + bookBuilder.pages = pages; if(bookObject.has("lore") && bookObject.get("lore").isJsonArray()){ - b.lore = bookObject.get("lore").getAsJsonArray(); + bookBuilder.lore = bookObject.get("lore").getAsJsonArray(); } - return b; + return bookBuilder; } /** diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java index 40d0dbd9..2509bb2a 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java @@ -89,31 +89,31 @@ public class WrittenBookBuilder { */ public static @NotNull WrittenBookBuilder fromJson(@NotNull JsonObject bookObject) { Preconditions.checkArgument(bookObject.has("pages") && bookObject.get("pages").isJsonArray(), "The provided JSON object must have a pages array!"); - WrittenBookBuilder b = new WrittenBookBuilder(); + WrittenBookBuilder bookBuilder = new WrittenBookBuilder(); if (bookObject.has("author")) - b.author = bookObject.get("author").getAsString(); + bookBuilder.author = bookObject.get("author").getAsString(); if (bookObject.has("title")) - b.title = bookObject.get("title").getAsString(); + bookBuilder.title = bookObject.get("title").getAsString(); if (bookObject.has("generation")) switch (bookObject.get("generation").getAsInt()) { case 1: - b.generation = BookMeta.Generation.COPY_OF_ORIGINAL; + bookBuilder.generation = BookMeta.Generation.COPY_OF_ORIGINAL; break; case 2: - b.generation = BookMeta.Generation.COPY_OF_COPY; + bookBuilder.generation = BookMeta.Generation.COPY_OF_COPY; break; case 3: - b.generation = BookMeta.Generation.TATTERED; + bookBuilder .generation = BookMeta.Generation.TATTERED; break; case 0: default: - b.generation = BookMeta.Generation.ORIGINAL; + bookBuilder.generation = BookMeta.Generation.ORIGINAL; } if(bookObject.has("lore") && bookObject.get("lore").isJsonArray()) - b.lore = bookObject.get("lore").getAsJsonArray(); + bookBuilder.lore = bookObject.get("lore").getAsJsonArray(); - b.pages = bookObject.get("pages").getAsJsonArray(); - return b; + bookBuilder.pages = bookObject.get("pages").getAsJsonArray(); + return bookBuilder; } /** From e38ba7c66ae8e60860a1a9f47241297760b3847d Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 13:38:19 +0000 Subject: [PATCH 66/79] Misc javadoc step changes --- build.gradle | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index 3a36d27c..86d68b8a 100644 --- a/build.gradle +++ b/build.gradle @@ -166,16 +166,12 @@ task rebuild{ } javadoc { - options.addBooleanOption('XDignore.symbol.file', true) - options.addBooleanOption('-frames', true) - options.addBooleanOption('private', true) + options.addBooleanOption('private', true) // Show all classes and members options.addBooleanOption("-allow-script-in-comments",true) - options.overview('src/main/overview.html') + options.overview('src/main/overview.html') // Customized overview HTML outputs.upToDateWhen { false } - // TODO: replace frames with JANITOR to get around removal of -frames in jdk15 - // options.footer("") - test.ignoreFailures true; + // TODO: Is this line neded? dependsOn delombok } From 29fa23fdfe31456df83094c3e61f2f23d44c5a00 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 13:42:30 +0000 Subject: [PATCH 67/79] Revert StickyAPI.java to master for split --- .../com/dumbdogdiner/stickyapi/StickyAPI.java | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java b/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java index f2270dda..a61fbc5a 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java @@ -13,23 +13,17 @@ import lombok.Getter; import lombok.Setter; -import lombok.experimental.UtilityClass; /** *

    StickyAPI

    Utility methods, classes and potentially * code-dupe-annihilating code for DDD plugins. * * @author DumbDogDiner (dumbdogdiner.com) - * @author aakatz3 - * @author SkyezerFox - * @author JCX - * @author ZachyFoxx - * @author vladfrangu - * @author spazzylemons - * @author kokumaji */ -@UtilityClass public class StickyAPI { + private StickyAPI() { + } + @Getter public static Logger logger = Logger.getLogger("StickyAPI"); @@ -44,6 +38,7 @@ public class StickyAPI { * * @since TBA * @return {@link String} version + * */ @Getter private static final String version = "@BUILDINFO_VERSION@"; @@ -85,7 +80,8 @@ public class StickyAPI { public static Date getTimestamp() { SimpleDateFormat formatter = new SimpleDateFormat(dateFormat); try { - return formatter.parse(timestamp); + Date date = formatter.parse(timestamp); + return date; } catch (ParseException e) { e.printStackTrace(); return null; @@ -110,7 +106,6 @@ public static String getSha() { * @since TBA * @return {@link Boolean} isDirty */ - @SuppressWarnings("ConstantConditions") public static Boolean getIsDirty() { return Boolean.parseBoolean(isDirty); } From 82569663a36d983370cdd6e682e15d3b68d0c996 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 13:42:49 +0000 Subject: [PATCH 68/79] Split gradle / javadoc changes for after PR merge --- build.gradle | 29 ------------------------ src/main/overview.html | 50 ------------------------------------------ 2 files changed, 79 deletions(-) delete mode 100644 src/main/overview.html diff --git a/build.gradle b/build.gradle index 86d68b8a..bae0d8a0 100644 --- a/build.gradle +++ b/build.gradle @@ -160,35 +160,6 @@ tasks.compileJava.dependsOn licenseFormatMain, licenseFormatTest, copyMCFontExtr tasks.build.dependsOn sources tasks.publish.dependsOn build -task rebuild{ - dependsOn clean - finalizedBy build -} - -javadoc { - options.addBooleanOption('private', true) // Show all classes and members - options.addBooleanOption("-allow-script-in-comments",true) - options.overview('src/main/overview.html') // Customized overview HTML - outputs.upToDateWhen { false } - - // TODO: Is this line neded? - dependsOn delombok -} - -task browseJavadoc { - dependsOn javadoc - doLast { - java.awt.Desktop.desktop.browse new URI(("file:///" << System.getProperty("user.dir").replace('\\','/') << "/build/docs/javadoc/index.html").toString()) - } -} - -task browseTests { - dependsOn test - doLast { - java.awt.Desktop.desktop.browse new URI(("file:///" << System.getProperty("user.dir").replace('\\','/') << "/build/reports/tests/test/index.html").toString()) - java.awt.Desktop.desktop.browse new URI(("file:///" << System.getProperty("user.dir").replace('\\','/') << "/build/reports/jacoco/test/html/index.html").toString()) - } -} publishing { repositories { diff --git a/src/main/overview.html b/src/main/overview.html deleted file mode 100644 index 83e2b4b7..00000000 --- a/src/main/overview.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - Overview - - -

    - stixilDoggers - StickyAPI - stixilDoggers -

    -

    Utility methods, classes and potentially code-dupe-annihilating code for DDD plugins.

    - - -
    -

    - Copyright © 2020-CURRENT_YEAR DumbDogDiner <dumbdogdiner.com>. All rights reserved.
    - Licensed under the MIT license, see LICENSE for more information... -

    -
    - -

    - Developed by:   -

    - - -

    This code is stored at https://github.com/DumbDogDiner/StickyAPI - - - - From c94e280bbb3e19d5d53afb6133807683ea7d624e Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 13:53:22 +0000 Subject: [PATCH 69/79] Add newline to voidgen --- .../dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java index 3ffdbc06..8403386a 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java @@ -19,4 +19,4 @@ public class VoidGenerator extends ChunkGenerator { public ChunkData generateChunkData(@NotNull World world, Random random, int x, int z, BiomeGrid biome) { return createChunkData(world); } -} \ No newline at end of file +} From 7f4f7236e8dc585f6889c53e6f32a8a1206500eb Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 13:55:55 +0000 Subject: [PATCH 70/79] Remove unused Gson imports and var --- .../stickyapi/bukkit/item/BookAndQuillBuilder.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java index 95b1f4a5..6cc77388 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java @@ -11,8 +11,6 @@ import com.dumbdogdiner.stickyapi.common.util.TextUtil; import com.dumbdogdiner.stickyapi.common.util.StringUtil; import com.google.common.base.Preconditions; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.Getter; @@ -43,7 +41,6 @@ @NoArgsConstructor public class BookAndQuillBuilder { private @NotNull JsonArray pages = new JsonArray(); - private static final Gson G = new GsonBuilder().create(); @Setter @Getter From 5a0cccf54a6089c71fcac0d73a50515928b0973e Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 13:59:26 +0000 Subject: [PATCH 71/79] Remove another unused Gson --- .../stickyapi/bukkit/item/WrittenBookBuilder.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java index 2509bb2a..e648b2a0 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java @@ -10,8 +10,6 @@ import com.dumbdogdiner.stickyapi.common.util.TextUtil; import com.dumbdogdiner.stickyapi.common.util.StringUtil; import com.google.common.base.Preconditions; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.Getter; @@ -74,12 +72,6 @@ public class WrittenBookBuilder { @Setter private @Nullable String displayName; - private static final Gson G = new GsonBuilder() - // Make sure things aren't weirdly escaped, may need to turn this back on - .disableHtmlEscaping() - .create(); - - /** * Creates a new BookGenerator from a given JsonObject, representing a book, which can * be obtained in whatever way you want. From 503dab5b722e46ee81ec061282988779140cb5dd Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 14:03:16 +0000 Subject: [PATCH 72/79] replace new since annotations with TBA --- .../dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java | 2 +- .../dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java | 2 +- .../java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java index 6cc77388..40fb01d0 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java @@ -33,7 +33,7 @@ * This class allows for easy construction of a writable book, which is unfortunately much * simpler than a written/signed book, either manually in code, or by loading a JSON object * - * @since 2.1.0 + * @since TBA */ @SuppressWarnings({"UnusedReturnValue", "unused"}) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java index e648b2a0..31aae34d 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java @@ -32,7 +32,7 @@ * This class allows for easy construction of a Written Book, whether through JSON objects and manual * creation, or by loading a full JSON object from a file or other source * - * @since 2.1.0 + * @since TBA */ @SuppressWarnings({"UnusedReturnValue", "unused"}) @Accessors(chain = true) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java index 208f7640..4d4561a5 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java @@ -25,7 +25,7 @@ /** * Utilities for text, such as in chat, books, and signs * - * @since 2.1.0 + * @since TBA (rewritten) */ @UtilityClass public class TextUtil { From d7b7dabc7d1061bd4ef2ab0a746990caf7aede41 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 14:14:27 +0000 Subject: [PATCH 73/79] Remove empty test class --- .../common/nbt/NbtStringTagTest.java | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTagTest.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTagTest.java b/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTagTest.java deleted file mode 100644 index be5287c6..00000000 --- a/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTagTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.nbt; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class NbtStringTagTest { - - @Test - void fromPrimitive() { - - } - - @Test - void testToString() { - } - - @Test - void toJson() { - } - - @Test - void toNbtString() { - } - - @Test - void asPrimitive() { - } - - @Test - void testEquals() { - } -} \ No newline at end of file From 85d1e5bdca58780ca8684d023e6948a8f54b1902 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 14:15:10 +0000 Subject: [PATCH 74/79] Use same javadoc as base StickyAPI.java --- .../java/com/dumbdogdiner/stickyapi/package-info.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/package-info.java index 3081ee9c..827f5776 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/package-info.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/package-info.java @@ -5,14 +5,7 @@ /** *

    StickyAPI

    Utility methods, classes and potentially * code-dupe-annihilating code for DDD plugins. - * + * * @author DumbDogDiner (dumbdogdiner.com) - * @author aakatz3 - * @author SkyezerFox - * @author JCX - * @author ZachyFoxx - * @author vladfrangu - * @author spazzylemons - * @author kokumaji */ package com.dumbdogdiner.stickyapi; From d98e13998fae9971753aee87b0fcc12e07975308 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 14:16:02 +0000 Subject: [PATCH 75/79] remove unused imports from mathutil --- .../java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java index 68c6c198..4cf6ed7d 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java @@ -4,7 +4,6 @@ */ package com.dumbdogdiner.stickyapi.common.util; -import com.google.common.base.Preconditions; import com.google.common.primitives.Chars; import com.google.common.primitives.Ints; import lombok.experimental.UtilityClass; @@ -12,7 +11,6 @@ import java.text.CharacterIterator; import java.text.StringCharacterIterator; -import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Random; From 0f19d7e1a2d55603b00ade46073354e3bc63ec87 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 14:16:57 +0000 Subject: [PATCH 76/79] Remove unused import from textutil --- .../java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java index 4d4561a5..88f5c5e4 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java @@ -14,7 +14,6 @@ import org.jetbrains.annotations.Nullable; import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.protocol.packet.Chat; import java.io.InputStream; import java.io.InputStreamReader; From a1a3d68ff18187de12278c33a8174c1e110f4751 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 14:17:45 +0000 Subject: [PATCH 77/79] (MathUtil/TextUtil): Use constructor instead of utilityclass annotation for now --- .../com/dumbdogdiner/stickyapi/common/util/MathUtil.java | 4 ++-- .../com/dumbdogdiner/stickyapi/common/util/TextUtil.java | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java index 4cf6ed7d..f65d3b7f 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java @@ -6,7 +6,6 @@ import com.google.common.primitives.Chars; import com.google.common.primitives.Ints; -import lombok.experimental.UtilityClass; import org.jetbrains.annotations.NotNull; import java.text.CharacterIterator; @@ -20,8 +19,9 @@ * Util class for commonly used math operations. *

    */ -@UtilityClass public class MathUtil { + private MathUtil() { + } private static final Random random = new Random(); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java index 88f5c5e4..5adae3ca 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java @@ -9,7 +9,6 @@ import com.google.gson.Gson; import lombok.Data; import lombok.NonNull; -import lombok.experimental.UtilityClass; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,8 +25,10 @@ * * @since TBA (rewritten) */ -@UtilityClass public class TextUtil { + private TextUtil() { + } + /** Offset for bold (in each direction) */ public static final float BOLD_OFFSET = 0.5f; /** Offset for shadows (in each direction) */ From aa21aa17f6c18295bd4e68ea1380f1618fcbabd8 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 14:21:29 +0000 Subject: [PATCH 78/79] (TextUtil): Remove unused var --- .../java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java index 5adae3ca..e612e4bc 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java @@ -18,7 +18,6 @@ import java.io.InputStreamReader; import java.util.HashMap; import java.util.Set; -import java.util.regex.Pattern; /** * Utilities for text, such as in chat, books, and signs @@ -50,8 +49,6 @@ private TextUtil() { /** Number of lines per sign */ public static final int LINES_PER_SIGN = 4; - private static final Pattern SPLIT_PATTERN = Pattern.compile("(?<=[ \n])|(?=[ \n])"); - private static final HashMap widths = new HashMap<>(); /** From 4003bae6db0311cdb898310750dea5f35ad0764e Mon Sep 17 00:00:00 2001 From: James Date: Sun, 14 Feb 2021 14:24:12 +0000 Subject: [PATCH 79/79] Add basic comments to TextUtil fallback loading --- .../com/dumbdogdiner/stickyapi/common/util/TextUtil.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java index e612e4bc..2409e091 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java +++ b/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java @@ -72,13 +72,18 @@ private static class WidthEntry { } } catch (Exception e) { StickyAPI.getLogger().severe(e.getMessage()); - // fallback to a minimal , in case anything fails + // fallback to a minimal configuration, in case anything fails for (char c = 32; c <= 126; ++c) { widths.put(c, 12); } + // Extra fallback data to load in in case anything fails + // Minecraft font data is formatted in a very particular way + // so we are forced to use unfriendly code to load in extra fallback data. "\0 ".chars().forEach(c -> widths.put((char) c, 2)); "!',.:;i|".chars().forEach(c -> widths.put((char) c, 4)); "`l".chars().forEach(c -> widths.put((char) c, 6)); + // Some characters are represented by their Unicode code point to ensure they + // load correctly "\"()*I[]t{}\u2022".chars().forEach(c -> widths.put((char) c, 8)); "<>fk\u00b7".chars().forEach(c -> widths.put((char) c, 10)); "@~".chars().forEach(c -> widths.put((char) c, 14));