Merge pull request #87 from TBMCPlugins/dev

Fixed /shrug, name mentioning and other formatting issues
This commit is contained in:
Norbi Peti 2018-08-14 00:57:22 +02:00 committed by GitHub
commit c080a857fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 160 additions and 81 deletions

View file

@ -27,10 +27,9 @@ import org.bukkit.entity.Player;
import org.bukkit.scoreboard.Objective; import org.bukkit.scoreboard.Objective;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class ChatProcessing { public class ChatProcessing {
@ -40,7 +39,7 @@ public class ChatProcessing {
private static final Pattern CONSOLE_PING_PATTERN = Pattern.compile("(?i)" + Pattern.quote("@console")); private static final Pattern CONSOLE_PING_PATTERN = Pattern.compile("(?i)" + Pattern.quote("@console"));
private static final Pattern HASHTAG_PATTERN = Pattern.compile("#(\\w+)"); private static final Pattern HASHTAG_PATTERN = Pattern.compile("#(\\w+)");
private static final Pattern URL_PATTERN = Pattern.compile("(http[\\w:/?=$\\-_.+!*'(),]+)"); private static final Pattern URL_PATTERN = Pattern.compile("(http[\\w:/?=$\\-_.+!*'(),]+)");
private static final Pattern ENTIRE_MESSAGE_PATTERN = Pattern.compile(".+"); public static final Pattern ENTIRE_MESSAGE_PATTERN = Pattern.compile(".+");
private static final Pattern UNDERLINED_PATTERN = Pattern.compile("_"); private static final Pattern UNDERLINED_PATTERN = Pattern.compile("_");
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("\\*\\*");
@ -55,14 +54,14 @@ public class ChatProcessing {
public static final ChatFormatter ESCAPE_FORMATTER = ChatFormatter.builder().regex(ESCAPE_PATTERN).build(); public static final ChatFormatter ESCAPE_FORMATTER = ChatFormatter.builder().regex(ESCAPE_PATTERN).build();
private static ArrayList<ChatFormatter> commonFormatters = Lists.newArrayList( private static ArrayList<ChatFormatter> commonFormatters = Lists.newArrayList(
ChatFormatter.builder().regex(BOLD_PATTERN).bold(true).removeCharCount((short) 2).range(true) ChatFormatter.builder().regex(BOLD_PATTERN).bold(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range)
.priority(Priority.High).build(), .priority(Priority.High).build(),
ChatFormatter.builder().regex(ITALIC_PATTERN).italic(true).removeCharCount((short) 1).range(true).build(), ChatFormatter.builder().regex(ITALIC_PATTERN).italic(true).removeCharCount((short) 1).type(ChatFormatter.Type.Range).build(),
ChatFormatter.builder().regex(UNDERLINED_PATTERN).underlined(true).removeCharCount((short) 1).range(true) ChatFormatter.builder().regex(UNDERLINED_PATTERN).underlined(true).removeCharCount((short) 1).type(ChatFormatter.Type.Range)
.build(), .build(),
ChatFormatter.builder().regex(STRIKETHROUGH_PATTERN).strikethrough(true).removeCharCount((short) 2).range(true) 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").build(), ESCAPE_FORMATTER, ChatFormatter.builder().regex(URL_PATTERN).underlined(true).openlink("$1").type(ChatFormatter.Type.Excluder).build(),
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) -> { ChatFormatter.builder().regex(CONSOLE_PING_PATTERN).color(Color.Aqua).onmatch((match, builder) -> {
if (!pingedconsole) { if (!pingedconsole) {
@ -75,7 +74,7 @@ public class ChatProcessing {
ChatFormatter.builder().regex(HASHTAG_PATTERN).color(Color.Blue).openlink("https://twitter.com/hashtag/$1") ChatFormatter.builder().regex(HASHTAG_PATTERN).color(Color.Blue).openlink("https://twitter.com/hashtag/$1")
.priority(Priority.High).build(), .priority(Priority.High).build(),
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).range(true) 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) -> {
return match; // TODO! return match; // TODO!
@ -85,6 +84,7 @@ public class ChatProcessing {
.registerTypeHierarchyAdapter(Collection.class, new TellrawSerializer.TwCollection()) .registerTypeHierarchyAdapter(Collection.class, new TellrawSerializer.TwCollection())
.registerTypeAdapter(Boolean.class, new TellrawSerializer.TwBool()) .registerTypeAdapter(Boolean.class, new TellrawSerializer.TwBool())
.registerTypeAdapter(boolean.class, new TellrawSerializer.TwBool()).disableHtmlEscaping().create(); .registerTypeAdapter(boolean.class, new TellrawSerializer.TwBool()).disableHtmlEscaping().create();
private static final String[] testPlayers = {"Koiiev", "iie", "Alisolarflare", "NorbiPeti", "Arsen_Derby_FTW", "carrot_lynx"};
private ChatProcessing() { private ChatProcessing() {
} }
@ -242,10 +242,15 @@ public class ChatProcessing {
formatters.add( formatters.add(
ChatFormatter.builder().regex(ENTIRE_MESSAGE_PATTERN).color(colormode).priority(Priority.Low).build()); ChatFormatter.builder().regex(ENTIRE_MESSAGE_PATTERN).color(colormode).priority(Priority.Low).build());
if (Bukkit.getOnlinePlayers().size() > 0) { boolean nottest; //Not assigning a default value, so that it can only be used in the if
if ((nottest = Bukkit.getOnlinePlayers().size() > 0) || Bukkit.getVersion().equals("test")) {
StringBuilder namesb = new StringBuilder("(?i)("); StringBuilder namesb = new StringBuilder("(?i)(");
for (Player p : Bukkit.getOnlinePlayers()) if (nottest)
namesb.append(p.getName()).append("|"); for (Player p : Bukkit.getOnlinePlayers())
namesb.append(p.getName()).append("|");
else
for (String testPlayer : testPlayers)
namesb.append(testPlayer).append("|");
namesb.deleteCharAt(namesb.length() - 1); namesb.deleteCharAt(namesb.length() - 1);
namesb.append(")"); namesb.append(")");
StringBuilder nicksb = new StringBuilder("(?i)("); StringBuilder nicksb = new StringBuilder("(?i)(");
@ -265,23 +270,33 @@ public class ChatProcessing {
} }
nicksb.append(")"); nicksb.append(")");
Consumer<String> error = message -> {
if (PluginMain.Instance != null)
PluginMain.Instance.getLogger().warning(message);
else
System.out.println(message);
};
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) -> {
Player p = Bukkit.getPlayer(match); Player p = Bukkit.getPlayer(match);
if (p == null) { Optional<String> pn = nottest ? Optional.empty()
PluginMain.Instance.getLogger() : Arrays.stream(testPlayers).filter(tp -> tp.equalsIgnoreCase(match)).findAny();
.warning("Error: Can't find player " + match + " but was reported as online."); if (nottest ? p == null : !pn.isPresent()) {
error.accept("Error: Can't find player " + match + " but was reported as online.");
return "§c" + match + "§r"; return "§c" + match + "§r";
} }
ChatPlayer mpp = TBMCPlayer.getPlayer(p.getUniqueId(), ChatPlayer.class); ChatPlayer mpp = TBMCPlayer.getPlayer(nottest ? p.getUniqueId() : new UUID(0, 0), ChatPlayer.class);
if (PlayerListener.NotificationSound == null) if (nottest) {
p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 0.5f); // TODO: Airhorn if (PlayerListener.NotificationSound == null)
else p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 0.5f); // TODO: Airhorn
p.playSound(p.getLocation(), PlayerListener.NotificationSound, 1.0f, else
(float) PlayerListener.NotificationPitch); p.playSound(p.getLocation(), PlayerListener.NotificationSound, 1.0f,
(float) PlayerListener.NotificationPitch);
}
String color = String.format("§%x", (mpp.GetFlairColor() == 0x00 ? 0xb : mpp.GetFlairColor())); String color = String.format("§%x", (mpp.GetFlairColor() == 0x00 ? 0xb : mpp.GetFlairColor()));
return color + p.getName() + "§r"; return color + (nottest ? p.getName() : pn.get()) + "§r"; //Fix name casing, except when testing
}).priority(Priority.High).build()); }).priority(Priority.High).type(ChatFormatter.Type.Excluder).build());
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)
@ -289,7 +304,7 @@ public class ChatProcessing {
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) {
PluginMain.Instance.getLogger().warning("Error: Can't find player nicknamed " error.accept("Error: Can't find player nicknamed "
+ match.toLowerCase() + " but was reported as online."); + match.toLowerCase() + " but was reported as online.");
return "§c" + match + "§r"; return "§c" + match + "§r";
} }
@ -300,10 +315,10 @@ public class ChatProcessing {
(float) PlayerListener.NotificationPitch); (float) PlayerListener.NotificationPitch);
return PluginMain.essentials.getUser(p).getNickname(); return PluginMain.essentials.getUser(p).getNickname();
} }
Bukkit.getServer().getLogger().warning("Player nicknamed " + match.toLowerCase() error.accept("Player nicknamed " + match.toLowerCase()
+ " not found in nickname map but was reported as online."); + " not found in nickname map but was reported as online.");
return "§c" + match + "§r"; return "§c" + match + "§r";
}).priority(Priority.High).build()); }).priority(Priority.High).type(ChatFormatter.Type.Excluder).build());
} }
return formatters; return formatters;
} }

View file

@ -40,27 +40,70 @@ public final class ChatFormatter {
@Builder.Default @Builder.Default
short removeCharCount = 0; short removeCharCount = 0;
@Builder.Default @Builder.Default
boolean range = false; Type type = Type.Normal;
public enum Type {
Normal,
/**
* Matches a start and an end section which gets converted to one section (for example see italics)
*/
Range,
/**
* Exclude matching area from further processing (besides this formatter)
*/
Excluder
}
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
*/ */
header("ChatFormatter.Combine begin"); header("ChatFormatter.Combine begin");
ArrayList<FormattedSection> sections = new ArrayList<FormattedSection>(); ArrayList<FormattedSection> sections = new ArrayList<FormattedSection>();
for (ChatFormatter formatter : formatters) {
if (formatter.type != Type.Excluder)
continue;
Matcher matcher = formatter.regex.matcher(str);
while (matcher.find()) {
DebugCommand.SendDebugMessage("Found match from " + matcher.start() + " to " + (matcher.end() - 1));
DebugCommand.SendDebugMessage("With excluder formatter:" + formatter);
sendMessageWithPointer(str, matcher.start(), matcher.end() - 1);
if (formatter.regex != ChatProcessing.ENTIRE_MESSAGE_PATTERN && sections.stream().anyMatch(fs -> fs.type == Type.Excluder && (fs.End >= matcher.start() && fs.Start <= matcher.end() - 1))) {
DebugCommand.SendDebugMessage("Ignoring formatter because of an excluder");
continue; //Exclude areas matched by excluders - Range sections are correctly handled afterwards
}
ArrayList<String> groups = new ArrayList<String>();
for (int i = 0; i < matcher.groupCount(); i++)
groups.add(matcher.group(i + 1));
if (groups.size() > 0)
DebugCommand.SendDebugMessage("First group: " + groups.get(0));
FormattedSection section = new FormattedSection(formatter, matcher.start(), matcher.end() - 1, groups,
formatter.type);
sections.add(section);
}
}
header("Section creation (excluders done)");
for (ChatFormatter formatter : formatters) { for (ChatFormatter formatter : formatters) {
if (formatter.type == Type.Excluder)
continue;
Matcher matcher = formatter.regex.matcher(str); Matcher matcher = formatter.regex.matcher(str);
while (matcher.find()) { while (matcher.find()) {
DebugCommand.SendDebugMessage("Found match from " + matcher.start() + " to " + (matcher.end() - 1)); DebugCommand.SendDebugMessage("Found match from " + matcher.start() + " to " + (matcher.end() - 1));
DebugCommand.SendDebugMessage("With formatter:" + formatter); DebugCommand.SendDebugMessage("With formatter:" + formatter);
sendMessageWithPointer(str, matcher.start(), matcher.end() - 1); sendMessageWithPointer(str, matcher.start(), matcher.end() - 1);
if (formatter.regex != ChatProcessing.ENTIRE_MESSAGE_PATTERN && sections.stream().anyMatch(fs -> fs.type == Type.Excluder && (fs.End >= matcher.start() && fs.Start <= matcher.end() - 1))) {
DebugCommand.SendDebugMessage("Ignoring formatter because of an excluder");
continue; //Exclude areas matched by excluders - Range sections are correctly handled afterwards
}
ArrayList<String> groups = new ArrayList<String>(); ArrayList<String> groups = new ArrayList<String>();
for (int i = 0; i < matcher.groupCount(); i++) for (int i = 0; i < matcher.groupCount(); i++)
groups.add(matcher.group(i + 1)); groups.add(matcher.group(i + 1));
if (groups.size() > 0) if (groups.size() > 0)
DebugCommand.SendDebugMessage("First group: " + groups.get(0)); DebugCommand.SendDebugMessage("First group: " + groups.get(0));
FormattedSection section = new FormattedSection(formatter, matcher.start(), matcher.end() - 1, groups, FormattedSection section = new FormattedSection(formatter, matcher.start(), matcher.end() - 1, groups,
formatter.range); formatter.type);
sections.add(section); sections.add(section);
} }
} }
@ -84,17 +127,20 @@ public final class ChatFormatter {
for (int i = 0; i < sections.size(); i++) { for (int i = 0; i < sections.size(); i++) {
// Set ending to -1 until closed with another 1 long "section" - only do this if IsRange is true // Set ending to -1 until closed with another 1 long "section" - only do this if IsRange is true
final FormattedSection section = sections.get(i); final FormattedSection section = sections.get(i);
if (!section.IsRange) { if (section.type!=Type.Range) {
escaped = section.Formatters.contains(ChatProcessing.ESCAPE_FORMATTER) && !escaped; // Enable escaping on first \, disable on second escaped = section.Formatters.contains(ChatProcessing.ESCAPE_FORMATTER) && !escaped; // Enable escaping on first \, disable on second
if (escaped) // Don't add the escape character if (escaped) {// Don't add the escape character
remchars.add(new int[]{section.Start, section.Start}); remchars.add(new int[]{section.Start, section.Start});
combined.add(section); // This will delete the \ DebugCommand.SendDebugMessage("Found escaper section: " + section);
DebugCommand.SendDebugMessage("Added " + (!escaped ? "not " : "") + "escaper section: " + section); } else {
combined.add(section); // The above will delete the \
DebugCommand.SendDebugMessage("Added section: " + section);
}
sendMessageWithPointer(str, section.Start, section.End); sendMessageWithPointer(str, section.Start, section.End);
continue; continue;
} }
if (!escaped) { if (!escaped) {
if (combined.stream().anyMatch(s -> s.IsRange && (s.Start == section.Start if (combined.stream().anyMatch(s -> section.type != Type.Range && (s.Start == section.Start
|| (s.Start < section.Start ? s.End >= section.Start : s.Start <= section.End)))) { || (s.Start < section.Start ? s.End >= section.Start : s.Start <= section.End)))) {
DebugCommand.SendDebugMessage("Range " + section + " overlaps with a combined section, ignoring."); DebugCommand.SendDebugMessage("Range " + section + " overlaps with a combined section, ignoring.");
sendMessageWithPointer(str, section.Start, section.End); sendMessageWithPointer(str, section.Start, section.End);
@ -140,12 +186,7 @@ public final class ChatFormatter {
escaped = false; // Reset escaping if applied, like if we're at the '*' in '\*' escaped = false; // Reset escaping if applied, like if we're at the '*' in '\*'
} }
} }
for (val sec : nextSection.values()) { //Do not finish unfinished sections, ignore them
sec.End = str.length() - 1;
combined.add(sec);
DebugCommand.SendDebugMessage("Finished unfinished section: " + sec);
sendMessageWithPointer(str, sec.Start, sec.End);
}
sections = combined; sections = combined;
header("Adding remove chars (RC)"); // Important to add after the range section conversion header("Adding remove chars (RC)"); // Important to add after the range section conversion
@ -192,7 +233,7 @@ public final class ChatFormatter {
origend2 = tmp; origend2 = tmp;
} }
FormattedSection section = new FormattedSection(firstSection.Formatters, sections.get(i).Start, origend, FormattedSection section = new FormattedSection(firstSection.Formatters, sections.get(i).Start, origend,
firstSection.Matches, false); firstSection.Matches, Type.Normal);
section.Formatters.addAll(sections.get(i).Formatters); section.Formatters.addAll(sections.get(i).Formatters);
section.Matches.addAll(sections.get(i).Matches); // TODO: Clean section.Matches.addAll(sections.get(i).Matches); // TODO: Clean
sections.add(i, section); sections.add(i, section);
@ -238,6 +279,7 @@ public final class ChatFormatter {
DebugCommand.SendDebugMessage("Removing section: " + sections.get(j)); DebugCommand.SendDebugMessage("Removing section: " + sections.get(j));
sendMessageWithPointer(str, sections.get(j).Start, sections.get(j).End); sendMessageWithPointer(str, sections.get(j).Start, sections.get(j).End);
sections.remove(j); sections.remove(j);
j--;
found = true; found = true;
} }
} }
@ -260,15 +302,16 @@ public final class ChatFormatter {
} }
header("Section applying"); header("Section applying");
for (int i = 0; i < sections.size(); i++) { TellrawPart lasttp = null; String lastlink = null;
FormattedSection section = sections.get(i); for (FormattedSection section : sections) {
DebugCommand.SendDebugMessage("Applying section: " + section); DebugCommand.SendDebugMessage("Applying section: " + section);
String originaltext; String originaltext;
int start = section.Start, end = section.End; int start = section.Start, end = section.End;
DebugCommand.SendDebugMessage("Start: " + start + " - End: " + end); DebugCommand.SendDebugMessage("Start: " + start + " - End: " + end);
sendMessageWithPointer(str, start, end); sendMessageWithPointer(str, start, end);
val rcs = remchars.stream().filter(rc -> rc[0] <= start && start <= rc[1]).findAny(); val rcs = remchars.stream().filter(rc -> rc[0] <= start && start <= rc[1]).findAny();
val rce = remchars.stream().filter(rc -> rc[0] <= end && end <= rc[1]).findAny(); val rce = remchars.stream().filter(rc -> rc[0] <= end && end <= rc[1]).findAny();
val rci = remchars.stream().filter(rc -> start < rc[0] && rc[1] < end).toArray(int[][]::new);
int s = start, e = end; int s = start, e = end;
if (rcs.isPresent()) if (rcs.isPresent())
s = rcs.get()[1] + 1; s = rcs.get()[1] + 1;
@ -280,39 +323,45 @@ public final class ChatFormatter {
continue; continue;
} }
originaltext = str.substring(s, e + 1); originaltext = str.substring(s, e + 1);
val sb = new StringBuilder(originaltext);
for (int x = rci.length - 1; x >= 0; x--)
sb.delete(rci[x][0] - start - 1, rci[x][1] - start); //Delete going backwards
originaltext = sb.toString();
DebugCommand.SendDebugMessage("Section text: " + originaltext); DebugCommand.SendDebugMessage("Section text: " + originaltext);
Color color = null; String openlink = null;
boolean bold = false, italic = false, underlined = false, strikethrough = false, obfuscated = false; section.Formatters.sort(Comparator.comparing(cf2 -> cf2.priority.GetValue())); //Apply the highest last, to overwrite previous ones
String openlink = null; TellrawPart newtp = new TellrawPart("");
section.Formatters.sort((cf2, cf1) -> cf1.priority.compareTo(cf2.priority));
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);
if (formatter.color != null) if (formatter.color != null)
color = formatter.color; newtp.setColor(formatter.color);
if (formatter.bold) if (formatter.bold)
bold = true; newtp.setBold(formatter.bold);
if (formatter.italic) if (formatter.italic)
italic = true; newtp.setItalic(formatter.italic);
if (formatter.underlined) if (formatter.underlined)
underlined = true; newtp.setUnderlined(formatter.underlined);
if (formatter.strikethrough) if (formatter.strikethrough)
strikethrough = true; newtp.setStrikethrough(formatter.strikethrough);
if (formatter.obfuscated) if (formatter.obfuscated)
obfuscated = true; newtp.setObfuscated(formatter.obfuscated);
if (formatter.openlink != null) if (formatter.openlink != null)
openlink = formatter.openlink; openlink = formatter.openlink;
} }
TellrawPart newtp = new TellrawPart(""); if (lasttp != null && newtp.getColor() == lasttp.getColor()
&& newtp.isBold() == lasttp.isBold()
&& newtp.isItalic() == lasttp.isItalic()
&& newtp.isUnderlined() == lasttp.isUnderlined()
&& newtp.isStrikethrough() == lasttp.isStrikethrough()
&& newtp.isObfuscated() == lasttp.isObfuscated()
&& (openlink == null ? lastlink == null : openlink.equals(lastlink))) {
DebugCommand.SendDebugMessage("This part has the same properties as the previous one, combining.");
lasttp.setText(lasttp.getText() + originaltext);
continue; //Combine parts with the same properties
}
newtp.setText(originaltext); newtp.setText(originaltext);
if (color != null)
newtp.setColor(color);
newtp.setBold(bold);
newtp.setItalic(italic);
newtp.setUnderlined(underlined);
newtp.setStrikethrough(strikethrough);
newtp.setObfuscated(obfuscated);
if (openlink != null && openlink.length() > 0) { if (openlink != null && openlink.length() > 0) {
newtp.setClickEvent(TellrawEvent.create(TellrawEvent.ClickAction.OPEN_URL, newtp.setClickEvent(TellrawEvent.create(TellrawEvent.ClickAction.OPEN_URL,
(section.Matches.size() > 0 ? openlink.replace("$1", section.Matches.get(0)) : openlink))) (section.Matches.size() > 0 ? openlink.replace("$1", section.Matches.get(0)) : openlink)))
@ -320,6 +369,7 @@ public final class ChatFormatter {
new TellrawPart("Click to open").setColor(Color.Blue))); new TellrawPart("Click to open").setColor(Color.Blue)));
} }
tp.addExtra(newtp); tp.addExtra(newtp);
lasttp = newtp;
} }
header("ChatFormatter.Combine done"); header("ChatFormatter.Combine done");
} }

View file

@ -8,32 +8,29 @@ class FormattedSection {
int End; int End;
ArrayList<ChatFormatter> Formatters = new ArrayList<ChatFormatter>(); ArrayList<ChatFormatter> Formatters = new ArrayList<ChatFormatter>();
ArrayList<String> Matches = new ArrayList<String>(); ArrayList<String> Matches = new ArrayList<String>();
/** ChatFormatter.Type type;
* Is it a 1-long section indicating a start or an end
*/
boolean IsRange;
FormattedSection(ChatFormatter formatter, int start, int end, ArrayList<String> matches, boolean isrange) { FormattedSection(ChatFormatter formatter, int start, int end, ArrayList<String> matches, ChatFormatter.Type type) {
Start = start; Start = start;
End = end; End = end;
Formatters.add(formatter); Formatters.add(formatter);
Matches.addAll(matches); Matches.addAll(matches);
IsRange = isrange; this.type = type;
} }
FormattedSection(Collection<ChatFormatter> formatters, int start, int end, ArrayList<String> matches, FormattedSection(Collection<ChatFormatter> formatters, int start, int end, ArrayList<String> matches,
boolean isrange) { ChatFormatter.Type type) {
Start = start; Start = start;
End = end; End = end;
Formatters.addAll(formatters); Formatters.addAll(formatters);
Matches.addAll(matches); Matches.addAll(matches);
IsRange = isrange; this.type = type;
} }
@Override @Override
public String toString() { public String toString() {
return new StringBuilder("Section(").append(Start).append(", ").append(End).append(", formatters: ") return "Section(" + Start + ", " + End + ", formatters: " +
.append(Formatters.toString()).append(", matches: ").append(Matches.toString()).append(", ") Formatters.toString() + ", matches: " + Matches.toString() + ", " +
.append(IsRange).append(")").toString(); type + ")";
} }
} }

View file

@ -40,14 +40,31 @@ public class ChatFormatIT {
new TellrawPart("test").setBold(true).setItalic(true).setUnderlined(true).setColor(Color.White))); new TellrawPart("test").setBold(true).setItalic(true).setUnderlined(true).setColor(Color.White)));
list.add(new ChatFormatIT(sender, "***_~~test~~_***", new TellrawPart("test").setBold(true).setItalic(true) list.add(new ChatFormatIT(sender, "***_~~test~~_***", new TellrawPart("test").setBold(true).setItalic(true)
.setUnderlined(true).setStrikethrough(true).setColor(Color.White))); .setUnderlined(true).setStrikethrough(true).setColor(Color.White)));
list.add(new ChatFormatIT(sender, "¯\\\\\\_(ツ)\\_/¯", new TellrawPart("¯").setColor(Color.White), list.add(new ChatFormatIT(sender, "¯\\\\\\_(ツ)\\_/¯", new TellrawPart("¯\\_(ツ)_/¯").setColor(Color.White)));
new TellrawPart("\\").setColor(Color.White), new TellrawPart("_(ツ)").setColor(Color.White),
new TellrawPart("_/¯").setColor(Color.White)));
list.add(new ChatFormatIT(sender, "https://google.hu/", list.add(new ChatFormatIT(sender, "https://google.hu/",
new TellrawPart("https://google.hu/").setColor(Color.White).setUnderlined(true) new TellrawPart("https://google.hu/").setColor(Color.White).setUnderlined(true)
.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://google.hu/")))); .setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://google.hu/"))));
list.add(new ChatFormatIT(sender, "*test", new TellrawPart("*test").setColor(Color.White)));
list.add(new ChatFormatIT(sender, "**test*", new TellrawPart("**test*").setColor(Color.White)));
list.add(new ChatFormatIT(sender, "***test", new TellrawPart("***test").setColor(Color.White)));
list.add(new ChatFormatIT(sender, "Koiiev", new TellrawPart("§bKoiiev§r").setColor(Color.Aqua)));
list.add(new ChatFormatIT(sender, "norbipeti", new TellrawPart("§bNorbiPeti§r").setColor(Color.Aqua)));
list.add(new ChatFormatIT(sender, "Arsen_Derby_FTW", new TellrawPart("§bArsen_Derby_FTW§r").setColor(Color.Aqua)));
list.add(new ChatFormatIT(sender, "carrot_lynx", new TellrawPart("§bcarrot_lynx§r").setColor(Color.Aqua)));
list.add(new ChatFormatIT(sender, "*carrot_lynx*", new TellrawPart("§bcarrot_lynx§r").setItalic(true).setColor(Color.Aqua)));
list.add(new ChatFormatIT(sender, "https://norbipeti.github.io/", new TellrawPart("https://norbipeti.github.io/")
.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/"))));
list.add(new ChatFormatIT(sender, "*https://norbipeti.github.io/ heh*", new TellrawPart("https://norbipeti.github.io/").setItalic(true).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/")), new TellrawPart(" heh").setItalic(true)));
list.add(new ChatFormatIT(sender, "*test _test_ test*", new TellrawPart("test ").setItalic(true).setColor(Color.White),
new TellrawPart("test").setItalic(true).setUnderlined(true).setColor(Color.White), new TellrawPart(" test").setItalic(true).setColor(Color.White)));
return list; return list;
} }