Fixed cast error, NPE, masked links

Fixed config cast error
Fixed mcchat NPE
Implemented masked links
Added a test for it
This commit is contained in:
Norbi Peti 2019-01-19 20:26:39 +01:00
parent 0802de4b6f
commit 3a29010042
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
7 changed files with 459 additions and 447 deletions

View file

@ -46,7 +46,7 @@ public class ChatProcessing {
private static final Pattern ITALIC_PATTERN = Pattern.compile("\\*"); private static final Pattern ITALIC_PATTERN = Pattern.compile("\\*");
private static final Pattern BOLD_PATTERN = Pattern.compile("\\*\\*"); private static final Pattern BOLD_PATTERN = Pattern.compile("\\*\\*");
private static final Pattern CODE_PATTERN = Pattern.compile("`"); private static final Pattern CODE_PATTERN = Pattern.compile("`");
private static final Pattern MASKED_LINK_PATTERN = Pattern.compile("\\[([^\\[\\]])]\\(([^()])\\)"); private static final Pattern MASKED_LINK_PATTERN = Pattern.compile("\\[([^\\[\\]]+)]\\(([^()]+)\\)");
private static final Pattern SOMEONE_PATTERN = Pattern.compile("@someone"); //TODO private static final Pattern SOMEONE_PATTERN = Pattern.compile("@someone"); //TODO
private static final Pattern STRIKETHROUGH_PATTERN = Pattern.compile("~~"); private static final Pattern STRIKETHROUGH_PATTERN = Pattern.compile("~~");
private static final Color[] RainbowPresserColors = new Color[]{Color.Red, Color.Gold, Color.Yellow, Color.Green, private static final Color[] RainbowPresserColors = new Color[]{Color.Red, Color.Gold, Color.Yellow, Color.Green,
@ -63,9 +63,8 @@ public class ChatProcessing {
.build(), .build(),
ChatFormatter.builder().regex(STRIKETHROUGH_PATTERN).strikethrough(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range) ChatFormatter.builder().regex(STRIKETHROUGH_PATTERN).strikethrough(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range)
.build(), .build(),
ESCAPE_FORMATTER, ChatFormatter.builder().regex(URL_PATTERN).underlined(true).openlink("$1").type(ChatFormatter.Type.Excluder).build(), ESCAPE_FORMATTER, ChatFormatter.builder().regex(NULL_MENTION_PATTERN).color(Color.DarkRed).build(), // Properly added a bug as a feature
ChatFormatter.builder().regex(NULL_MENTION_PATTERN).color(Color.DarkRed).build(), // Properly added a bug as a feature ChatFormatter.builder().regex(CONSOLE_PING_PATTERN).color(Color.Aqua).onmatch((match, builder, section) -> {
ChatFormatter.builder().regex(CONSOLE_PING_PATTERN).color(Color.Aqua).onmatch((match, builder) -> {
if (!pingedconsole) { if (!pingedconsole) {
System.out.print("\007"); System.out.print("\007");
pingedconsole = true; // Will set it to false in ProcessChat pingedconsole = true; // Will set it to false in ProcessChat
@ -78,9 +77,14 @@ public class ChatProcessing {
ChatFormatter.builder().regex(CYAN_PATTERN).color(Color.Aqua).build(), // #55 ChatFormatter.builder().regex(CYAN_PATTERN).color(Color.Aqua).build(), // #55
ChatFormatter.builder().regex(CODE_PATTERN).color(Color.DarkGray).removeCharCount((short) 1).type(ChatFormatter.Type.Range) ChatFormatter.builder().regex(CODE_PATTERN).color(Color.DarkGray).removeCharCount((short) 1).type(ChatFormatter.Type.Range)
.build(), .build(),
ChatFormatter.builder().regex(MASKED_LINK_PATTERN).underlined(true).onmatch((match, builder) -> { ChatFormatter.builder().regex(MASKED_LINK_PATTERN).underlined(true).onmatch((match, builder, section) -> {
return match; // TODO! String text, link;
}).build()); if (section.Matches.size() < 2 || (text = section.Matches.get(0)).length() == 0 || (link = section.Matches.get(1)).length() == 0)
return "";
builder.setOpenlink(link);
return text;
}).type(ChatFormatter.Type.Excluder).build(),
ChatFormatter.builder().regex(URL_PATTERN).underlined(true).openlink("$1").type(ChatFormatter.Type.Excluder).build());
private static Gson gson = new GsonBuilder() private static Gson gson = new GsonBuilder()
.registerTypeHierarchyAdapter(TellrawSerializableEnum.class, new TellrawSerializer.TwEnum()) .registerTypeHierarchyAdapter(TellrawSerializableEnum.class, new TellrawSerializer.TwEnum())
.registerTypeHierarchyAdapter(Collection.class, new TellrawSerializer.TwCollection()) .registerTypeHierarchyAdapter(Collection.class, new TellrawSerializer.TwCollection())
@ -124,7 +128,7 @@ public class ChatProcessing {
ArrayList<ChatFormatter> formatters = addFormatters(colormode); ArrayList<ChatFormatter> formatters = addFormatters(colormode);
if (colormode == channel.Color().get() && mp != null && mp.RainbowPresserColorMode) { // Only overwrite channel color if (colormode == channel.Color().get() && mp != null && mp.RainbowPresserColorMode) { // Only overwrite channel color
final AtomicInteger rpc = new AtomicInteger(0); final AtomicInteger rpc = new AtomicInteger(0);
formatters.add(ChatFormatter.builder().color(colormode).onmatch((match, cf) -> { formatters.add(ChatFormatter.builder().color(colormode).onmatch((match, cf, s) -> {
cf.setColor(RainbowPresserColors[rpc.getAndUpdate(i -> ++i < RainbowPresserColors.length ? i : 0)]); cf.setColor(RainbowPresserColors[rpc.getAndUpdate(i -> ++i < RainbowPresserColors.length ? i : 0)]);
return match; return match;
}).build()); }).build());
@ -275,7 +279,7 @@ public class ChatProcessing {
}; };
formatters.add(ChatFormatter.builder().regex(Pattern.compile(namesb.toString())).color(Color.Aqua) formatters.add(ChatFormatter.builder().regex(Pattern.compile(namesb.toString())).color(Color.Aqua)
.onmatch((match, builder) -> { .onmatch((match, builder, section) -> {
Player p = Bukkit.getPlayer(match); Player p = Bukkit.getPlayer(match);
Optional<String> pn = nottest ? Optional.empty() Optional<String> pn = nottest ? Optional.empty()
: Arrays.stream(testPlayers).filter(tp -> tp.equalsIgnoreCase(match)).findAny(); : Arrays.stream(testPlayers).filter(tp -> tp.equalsIgnoreCase(match)).findAny();
@ -297,7 +301,7 @@ public class ChatProcessing {
if (addNickFormatter) if (addNickFormatter)
formatters.add(ChatFormatter.builder().regex((Pattern.compile(nicksb.toString()))).color(Color.Aqua) formatters.add(ChatFormatter.builder().regex((Pattern.compile(nicksb.toString()))).color(Color.Aqua)
.onmatch((match, builder) -> { .onmatch((match, builder, section) -> {
if (PlayerListener.nicknames.containsKey(match.toLowerCase())) { //Made a stream and all that but I can actually store it lowercased if (PlayerListener.nicknames.containsKey(match.toLowerCase())) { //Made a stream and all that but I can actually store it lowercased
Player p = Bukkit.getPlayer(PlayerListener.nicknames.get(match.toLowerCase())); Player p = Bukkit.getPlayer(PlayerListener.nicknames.get(match.toLowerCase()));
if (p == null) { if (p == null) {

View file

@ -42,7 +42,7 @@ public class TownColorComponent extends Component {
public static Map<String, Color> NationColor = new HashMap<>(); public static Map<String, Color> NationColor = new HashMap<>();
public ConfigData<Byte> colorCount() { public ConfigData<Byte> colorCount() {
return getConfig().getData("colorCount", (byte) 1, cc -> (byte) cc, cc -> (int) cc); return getConfig().getData("colorCount", (byte) 1, cc -> ((Integer) cc).byteValue(), Byte::intValue);
} }
public ConfigData<Boolean> useNationColors() { //TODO public ConfigData<Boolean> useNationColors() { //TODO

View file

@ -9,7 +9,6 @@ import lombok.Data;
import lombok.val; import lombok.val;
import java.util.*; import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -33,7 +32,7 @@ public final class ChatFormatter {
boolean strikethrough; boolean strikethrough;
boolean obfuscated; boolean obfuscated;
Color color; Color color;
BiFunction<String, ChatFormatter, String> onmatch; TriFunc<String, ChatFormatter, FormattedSection, String> onmatch;
String openlink; String openlink;
@Builder.Default @Builder.Default
Priority priority = Priority.Normal; Priority priority = Priority.Normal;
@ -54,6 +53,11 @@ public final class ChatFormatter {
Excluder Excluder
} }
@FunctionalInterface
public interface TriFunc<T1, T2, T3, R> {
R apply(T1 x1, T2 x2, T3 x3);
}
public static void Combine(List<ChatFormatter> formatters, String str, TellrawPart tp) { public static void Combine(List<ChatFormatter> formatters, String str, TellrawPart tp) {
/* /*
* This method assumes that there is always a global formatter * This method assumes that there is always a global formatter
@ -334,7 +338,7 @@ public final class ChatFormatter {
for (ChatFormatter formatter : section.Formatters) { for (ChatFormatter formatter : section.Formatters) {
DebugCommand.SendDebugMessage("Applying formatter: " + formatter); DebugCommand.SendDebugMessage("Applying formatter: " + formatter);
if (formatter.onmatch != null) if (formatter.onmatch != null)
originaltext = formatter.onmatch.apply(originaltext, formatter); originaltext = formatter.onmatch.apply(originaltext, formatter, section);
if (formatter.color != null) if (formatter.color != null)
newtp.setColor(formatter.color); newtp.setColor(formatter.color);
if (formatter.bold) if (formatter.bold)
@ -356,7 +360,7 @@ public final class ChatFormatter {
&& newtp.isUnderlined() == lasttp.isUnderlined() && newtp.isUnderlined() == lasttp.isUnderlined()
&& newtp.isStrikethrough() == lasttp.isStrikethrough() && newtp.isStrikethrough() == lasttp.isStrikethrough()
&& newtp.isObfuscated() == lasttp.isObfuscated() && newtp.isObfuscated() == lasttp.isObfuscated()
&& (openlink == null ? lastlink == null : openlink.equals(lastlink))) { && Objects.equals(openlink, lastlink)) {
DebugCommand.SendDebugMessage("This part has the same properties as the previous one, combining."); DebugCommand.SendDebugMessage("This part has the same properties as the previous one, combining.");
lasttp.setText(lasttp.getText() + originaltext); lasttp.setText(lasttp.getText() + originaltext);
continue; //Combine parts with the same properties continue; //Combine parts with the same properties

View file

@ -3,12 +3,12 @@ package buttondevteam.chat.formatting;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
class FormattedSection { public class FormattedSection {
int Start; public int Start;
int End; public int End;
ArrayList<ChatFormatter> Formatters = new ArrayList<ChatFormatter>(); public ArrayList<ChatFormatter> Formatters = new ArrayList<ChatFormatter>();
ArrayList<String> Matches = new ArrayList<String>(); public ArrayList<String> Matches = new ArrayList<String>();
ChatFormatter.Type type; public ChatFormatter.Type type;
FormattedSection(ChatFormatter formatter, int start, int end, ArrayList<String> matches, ChatFormatter.Type type) { FormattedSection(ChatFormatter formatter, int start, int end, ArrayList<String> matches, ChatFormatter.Type type) {
Start = start; Start = start;

View file

@ -12,7 +12,6 @@ import buttondevteam.core.ComponentManager;
import buttondevteam.lib.player.TBMCPlayerJoinEvent; import buttondevteam.lib.player.TBMCPlayerJoinEvent;
import buttondevteam.lib.player.TBMCPlayerLoadEvent; import buttondevteam.lib.player.TBMCPlayerLoadEvent;
import buttondevteam.lib.player.TBMCPlayerSaveEvent; import buttondevteam.lib.player.TBMCPlayerSaveEvent;
import org.bukkit.Bukkit;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@ -32,7 +31,7 @@ public class PlayerJoinLeaveListener implements Listener {
@EventHandler @EventHandler
public void onPlayerTBMCJoin(TBMCPlayerJoinEvent e) { public void onPlayerTBMCJoin(TBMCPlayerJoinEvent e) {
ChatPlayer cp = e.GetPlayer().asPluginPlayer(ChatPlayer.class); ChatPlayer cp = e.GetPlayer().asPluginPlayer(ChatPlayer.class);
Player p = Bukkit.getPlayer(cp.getUUID()); Player p = e.getPlayer();
if (ComponentManager.isEnabled(FlairComponent.class)) { if (ComponentManager.isEnabled(FlairComponent.class)) {
if (!cp.FlairState().get().equals(FlairStates.NoComment)) { if (!cp.FlairState().get().equals(FlairStates.NoComment)) {

View file

@ -37,9 +37,9 @@ depend:
- Votifier - Votifier
- Vault - Vault
- ButtonCore - ButtonCore
- Dynmap-Towny
soft-depend: soft-depend:
- Minigames - Minigames
- Dynmap-Towny
permissions: permissions:
tbmc.admin: tbmc.admin:
description: Gives access to /un- commands and /u admin commands description: Gives access to /un- commands and /u admin commands

View file

@ -70,6 +70,11 @@ public class ChatFormatIT {
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT, .setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT,
new TellrawPart("Click to open").setColor(Color.Blue))) new TellrawPart("Click to open").setColor(Color.Blue)))
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/test?test&test#test")))); .setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/test?test&test#test"))));
list.add(new ChatFormatIT(sender, "[hmm](https://norbipeti.github.io/test)", new TellrawPart("hmm")
.setColor(Color.White).setUnderlined(true)
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT,
new TellrawPart("Click to open").setColor(Color.Blue)))
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/test"))));
return list; return list;
} }