Fixed /shrug, name mentioning and other formatting issues #87
4 changed files with 73 additions and 47 deletions
|
@ -27,10 +27,9 @@ import org.bukkit.entity.Player;
|
|||
import org.bukkit.scoreboard.Objective;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class ChatProcessing {
|
||||
|
@ -55,12 +54,12 @@ public class ChatProcessing {
|
|||
public static final ChatFormatter ESCAPE_FORMATTER = ChatFormatter.builder().regex(ESCAPE_PATTERN).build();
|
||||
|
||||
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(),
|
||||
ChatFormatter.builder().regex(ITALIC_PATTERN).italic(true).removeCharCount((short) 1).range(true).build(),
|
||||
ChatFormatter.builder().regex(UNDERLINED_PATTERN).underlined(true).removeCharCount((short) 1).range(true)
|
||||
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).type(ChatFormatter.Type.Range)
|
||||
.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(),
|
||||
ESCAPE_FORMATTER, ChatFormatter.builder().regex(URL_PATTERN).underlined(true).openlink("$1").build(),
|
||||
ChatFormatter.builder().regex(NULL_MENTION_PATTERN).color(Color.DarkRed).build(), // Properly added a bug as a feature
|
||||
|
@ -75,7 +74,7 @@ public class ChatProcessing {
|
|||
ChatFormatter.builder().regex(HASHTAG_PATTERN).color(Color.Blue).openlink("https://twitter.com/hashtag/$1")
|
||||
.priority(Priority.High).build(),
|
||||
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(),
|
||||
ChatFormatter.builder().regex(MASKED_LINK_PATTERN).underlined(true).onmatch((match, builder) -> {
|
||||
return match; // TODO!
|
||||
|
@ -85,6 +84,7 @@ public class ChatProcessing {
|
|||
.registerTypeHierarchyAdapter(Collection.class, new TellrawSerializer.TwCollection())
|
||||
.registerTypeAdapter(Boolean.class, new TellrawSerializer.TwBool())
|
||||
.registerTypeAdapter(boolean.class, new TellrawSerializer.TwBool()).disableHtmlEscaping().create();
|
||||
private static final String[] testPlayers = {"Koiiev", "iie", "Alisolarflare", "NorbiPeti", "Arsen_Derby_FTW", "carrot_lynx"};
|
||||
|
||||
private ChatProcessing() {
|
||||
}
|
||||
|
@ -242,10 +242,15 @@ public class ChatProcessing {
|
|||
formatters.add(
|
||||
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)(");
|
||||
for (Player p : Bukkit.getOnlinePlayers())
|
||||
namesb.append(p.getName()).append("|");
|
||||
if (nottest)
|
||||
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.append(")");
|
||||
StringBuilder nicksb = new StringBuilder("(?i)(");
|
||||
|
@ -265,23 +270,31 @@ public class ChatProcessing {
|
|||
}
|
||||
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)
|
||||
.onmatch((match, builder) -> {
|
||||
Player p = Bukkit.getPlayer(match);
|
||||
if (p == null) {
|
||||
PluginMain.Instance.getLogger()
|
||||
.warning("Error: Can't find player " + match + " but was reported as online.");
|
||||
if (nottest ? p == null : Arrays.stream(testPlayers).noneMatch(tp -> tp.equalsIgnoreCase(match))) {
|
||||
error.accept("Error: Can't find player " + match + " but was reported as online.");
|
||||
return "§c" + match + "§r";
|
||||
}
|
||||
ChatPlayer mpp = TBMCPlayer.getPlayer(p.getUniqueId(), ChatPlayer.class);
|
||||
if (PlayerListener.NotificationSound == null)
|
||||
p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 0.5f); // TODO: Airhorn
|
||||
else
|
||||
p.playSound(p.getLocation(), PlayerListener.NotificationSound, 1.0f,
|
||||
(float) PlayerListener.NotificationPitch);
|
||||
ChatPlayer mpp = TBMCPlayer.getPlayer(nottest ? p.getUniqueId() : new UUID(0, 0), ChatPlayer.class);
|
||||
if (nottest) {
|
||||
if (PlayerListener.NotificationSound == null)
|
||||
p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 0.5f); // TODO: Airhorn
|
||||
else
|
||||
p.playSound(p.getLocation(), PlayerListener.NotificationSound, 1.0f,
|
||||
(float) PlayerListener.NotificationPitch);
|
||||
}
|
||||
String color = String.format("§%x", (mpp.GetFlairColor() == 0x00 ? 0xb : mpp.GetFlairColor()));
|
||||
return color + p.getName() + "§r";
|
||||
}).priority(Priority.High).build());
|
||||
return color + (nottest ? p.getName() : match) + "§r"; //Fix name casing, except when testing
|
||||
}).priority(Priority.High).type(ChatFormatter.Type.Excluder).build());
|
||||
|
||||
if (addNickFormatter)
|
||||
formatters.add(ChatFormatter.builder().regex((Pattern.compile(nicksb.toString()))).color(Color.Aqua)
|
||||
|
@ -289,7 +302,7 @@ public class ChatProcessing {
|
|||
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()));
|
||||
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.");
|
||||
return "§c" + match + "§r";
|
||||
}
|
||||
|
@ -300,10 +313,10 @@ public class ChatProcessing {
|
|||
(float) PlayerListener.NotificationPitch);
|
||||
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.");
|
||||
return "§c" + match + "§r";
|
||||
}).priority(Priority.High).build());
|
||||
}).priority(Priority.High).type(ChatFormatter.Type.Excluder).build());
|
||||
}
|
||||
return formatters;
|
||||
}
|
||||
|
|
|
@ -40,13 +40,25 @@ public final class ChatFormatter {
|
|||
@Builder.Default
|
||||
short removeCharCount = 0;
|
||||
@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) {
|
||||
/*
|
||||
* This method assumes that there is always a global formatter
|
||||
*/
|
||||
header("ChatFormatter.Combine begin");
|
||||
*/
|
||||
header("ChatFormatter.Combine begin"); //TODO: Handle excluder formatters first
|
||||
ArrayList<FormattedSection> sections = new ArrayList<FormattedSection>();
|
||||
for (ChatFormatter formatter : formatters) {
|
||||
Matcher matcher = formatter.regex.matcher(str);
|
||||
|
@ -60,7 +72,7 @@ public final class ChatFormatter {
|
|||
if (groups.size() > 0)
|
||||
DebugCommand.SendDebugMessage("First group: " + groups.get(0));
|
||||
FormattedSection section = new FormattedSection(formatter, matcher.start(), matcher.end() - 1, groups,
|
||||
formatter.range);
|
||||
formatter.type);
|
||||
sections.add(section);
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +96,7 @@ public final class ChatFormatter {
|
|||
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
|
||||
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
|
||||
if (escaped) // Don't add the escape character
|
||||
remchars.add(new int[]{section.Start, section.Start});
|
||||
|
@ -92,9 +104,9 @@ public final class ChatFormatter {
|
|||
DebugCommand.SendDebugMessage("Added " + (!escaped ? "not " : "") + "escaper section: " + section);
|
||||
sendMessageWithPointer(str, section.Start, section.End);
|
||||
continue;
|
||||
}
|
||||
if (!escaped) {
|
||||
if (combined.stream().anyMatch(s -> s.IsRange && (s.Start == section.Start
|
||||
}
|
||||
if (!escaped) {
|
||||
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)))) {
|
||||
DebugCommand.SendDebugMessage("Range " + section + " overlaps with a combined section, ignoring.");
|
||||
sendMessageWithPointer(str, section.Start, section.End);
|
||||
|
@ -192,7 +204,7 @@ public final class ChatFormatter {
|
|||
origend2 = tmp;
|
||||
}
|
||||
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.Matches.addAll(sections.get(i).Matches); // TODO: Clean
|
||||
sections.add(i, section);
|
||||
|
@ -283,8 +295,8 @@ public final class ChatFormatter {
|
|||
DebugCommand.SendDebugMessage("Section text: " + originaltext);
|
||||
Color color = null;
|
||||
boolean bold = false, italic = false, underlined = false, strikethrough = false, obfuscated = false;
|
||||
String openlink = null;
|
||||
section.Formatters.sort((cf2, cf1) -> cf1.priority.compareTo(cf2.priority));
|
||||
String openlink = null;
|
||||
section.Formatters.sort(Comparator.comparing(cf2 -> cf2.priority.GetValue())); //Apply the highest last, to overwrite previous ones
|
||||
for (ChatFormatter formatter : section.Formatters) {
|
||||
DebugCommand.SendDebugMessage("Applying formatter: " + formatter);
|
||||
if (formatter.onmatch != null)
|
||||
|
|
|
@ -8,32 +8,29 @@ class FormattedSection {
|
|||
int End;
|
||||
ArrayList<ChatFormatter> Formatters = new ArrayList<ChatFormatter>();
|
||||
ArrayList<String> Matches = new ArrayList<String>();
|
||||
/**
|
||||
* Is it a 1-long section indicating a start or an end
|
||||
*/
|
||||
boolean IsRange;
|
||||
ChatFormatter.Type type;
|
||||
|
||||
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;
|
||||
End = end;
|
||||
Formatters.add(formatter);
|
||||
Matches.addAll(matches);
|
||||
IsRange = isrange;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
FormattedSection(Collection<ChatFormatter> formatters, int start, int end, ArrayList<String> matches,
|
||||
boolean isrange) {
|
||||
ChatFormatter.Type type) {
|
||||
Start = start;
|
||||
End = end;
|
||||
Formatters.addAll(formatters);
|
||||
Matches.addAll(matches);
|
||||
IsRange = isrange;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder("Section(").append(Start).append(", ").append(End).append(", formatters: ")
|
||||
.append(Formatters.toString()).append(", matches: ").append(Matches.toString()).append(", ")
|
||||
.append(IsRange).append(")").toString();
|
||||
return "Section(" + Start + ", " + End + ", formatters: " +
|
||||
Formatters.toString() + ", matches: " + Matches.toString() + ", " +
|
||||
type + ")";
|
||||
}
|
||||
}
|
|
@ -49,6 +49,10 @@ public class ChatFormatIT {
|
|||
list.add(new ChatFormatIT(sender, "*test", new TellrawPart("*test").setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "**test*", new TellrawPart("*test").setItalic(true).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)));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue