Misc. fixes, chat history config, clickable announcements #114
3 changed files with 76 additions and 21 deletions
|
@ -25,6 +25,7 @@ import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
import buttondevteam.lib.player.TBMCPlayer;
|
import buttondevteam.lib.player.TBMCPlayer;
|
||||||
import buttondevteam.lib.player.TBMCPlayerBase;
|
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||||
import com.earth2me.essentials.User;
|
import com.earth2me.essentials.User;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
@ -51,6 +52,7 @@ public class ChatProcessing {
|
||||||
public 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 ITALIC_PATTERN_2 = 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("\\[([^\\[\\]]+)]\\(([^()]+)\\)");
|
||||||
|
@ -68,7 +70,8 @@ public class ChatProcessing {
|
||||||
ChatFormatter.builder("bold", BOLD_PATTERN).bold(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range)
|
ChatFormatter.builder("bold", BOLD_PATTERN).bold(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range)
|
||||||
.priority(Priority.High).build(),
|
.priority(Priority.High).build(),
|
||||||
ChatFormatter.builder("italic", ITALIC_PATTERN).italic(true).removeCharCount((short) 1).type(ChatFormatter.Type.Range).build(),
|
ChatFormatter.builder("italic", ITALIC_PATTERN).italic(true).removeCharCount((short) 1).type(ChatFormatter.Type.Range).build(),
|
||||||
ChatFormatter.builder("underlined", UNDERLINED_PATTERN).underlined(true).removeCharCount((short) 1).type(ChatFormatter.Type.Range)
|
ChatFormatter.builder("italic2", ITALIC_PATTERN_2).italic(true).removeCharCount((short) 1).type(ChatFormatter.Type.Range).build(),
|
||||||
|
ChatFormatter.builder("underlined", UNDERLINED_PATTERN).underlined(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range)
|
||||||
.build(),
|
.build(),
|
||||||
ChatFormatter.builder("strikethrough", STRIKETHROUGH_PATTERN).strikethrough(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range)
|
ChatFormatter.builder("strikethrough", STRIKETHROUGH_PATTERN).strikethrough(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range)
|
||||||
.build(),
|
.build(),
|
||||||
|
@ -98,7 +101,15 @@ public class ChatProcessing {
|
||||||
builder.setOpenlink(link);
|
builder.setOpenlink(link);
|
||||||
return text;
|
return text;
|
||||||
}).type(ChatFormatter.Type.Excluder).build(),
|
}).type(ChatFormatter.Type.Excluder).build(),
|
||||||
ChatFormatter.builder("url", URL_PATTERN).underlined(true).openlink("$1").type(ChatFormatter.Type.Excluder).build());
|
ChatFormatter.builder("url", URL_PATTERN).underlined(true).openlink("$1").type(ChatFormatter.Type.Excluder).build(),
|
||||||
|
ChatFormatter.builder("someone", SOMEONE_PATTERN).color(Color.Aqua).onmatch((match, builder, section) -> {
|
||||||
|
if (Bukkit.getOnlinePlayers().size() == 0) return match;
|
||||||
|
var players = ImmutableList.copyOf(Bukkit.getOnlinePlayers());
|
||||||
|
var playerC = new Random().nextInt(players.size());
|
||||||
|
var player = players.get(playerC);
|
||||||
|
playPingSound(player);
|
||||||
|
return "@someone (" + player.getDisplayName() + ")";
|
||||||
|
}).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())
|
||||||
|
@ -211,8 +222,8 @@ public class ChatProcessing {
|
||||||
}
|
}
|
||||||
|
|
||||||
static TellrawPart createTellraw(CommandSender sender, String message, @Nullable Player player,
|
static TellrawPart createTellraw(CommandSender sender, String message, @Nullable Player player,
|
||||||
@Nullable ChatPlayer mp, @Nullable ChromaGamerBase cg, final String channelidentifier,
|
@Nullable ChatPlayer mp, @Nullable ChromaGamerBase cg, final String channelidentifier,
|
||||||
String origin) {
|
String origin) {
|
||||||
TellrawPart json = new TellrawPart("");
|
TellrawPart json = new TellrawPart("");
|
||||||
ChatOnlyComponent.tellrawCreate(mp, json); //TODO: Make nice API
|
ChatOnlyComponent.tellrawCreate(mp, json); //TODO: Make nice API
|
||||||
json.addExtra(
|
json.addExtra(
|
||||||
|
|
|
@ -45,6 +45,13 @@ public final class ChatFormatter {
|
||||||
String hoverText;
|
String hoverText;
|
||||||
String name;
|
String name;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ChatFormatter{" +
|
||||||
|
"name='" + name + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
public static ChatFormatterBuilder builder(String name, Pattern regex) {
|
public static ChatFormatterBuilder builder(String name, Pattern regex) {
|
||||||
return builder().regex(regex).name(name);
|
return builder().regex(regex).name(name);
|
||||||
}
|
}
|
||||||
|
@ -98,7 +105,7 @@ public final class ChatFormatter {
|
||||||
sections = convertRangeSections(str, sections, remchars);
|
sections = convertRangeSections(str, sections, remchars);
|
||||||
|
|
||||||
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
|
||||||
addRemChars(sections, remchars);
|
addRemChars(sections, remchars, str);
|
||||||
|
|
||||||
header("Section combining");
|
header("Section combining");
|
||||||
combineSections(str, sections);
|
combineSections(str, sections);
|
||||||
|
@ -134,6 +141,19 @@ public final class ChatFormatter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void newCombine(String str, ArrayList<FormattedSection> sections, ArrayList<int[]> remchars) {
|
||||||
|
var stack = new Stack<FormattedSection>();
|
||||||
|
for (int i = 0; i < str.length(); i++) {
|
||||||
|
for (Iterator<FormattedSection> iterator = sections.iterator(); iterator.hasNext(); ) {
|
||||||
|
FormattedSection section = iterator.next();
|
||||||
|
if (section.Start <= i) {
|
||||||
|
stack.push(section);
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static ArrayList<FormattedSection> convertRangeSections(String str, ArrayList<FormattedSection> sections, ArrayList<int[]> remchars) {
|
private static ArrayList<FormattedSection> convertRangeSections(String str, ArrayList<FormattedSection> sections, ArrayList<int[]> remchars) {
|
||||||
ArrayList<FormattedSection> combined = new ArrayList<>();
|
ArrayList<FormattedSection> combined = new ArrayList<>();
|
||||||
Map<ChatFormatter, FormattedSection> nextSection = new HashMap<>();
|
Map<ChatFormatter, FormattedSection> nextSection = new HashMap<>();
|
||||||
|
@ -200,7 +220,7 @@ public final class ChatFormatter {
|
||||||
return sections;
|
return sections;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addRemChars(ArrayList<FormattedSection> sections, ArrayList<int[]> remchars) {
|
private static void addRemChars(ArrayList<FormattedSection> sections, ArrayList<int[]> remchars, String str) {
|
||||||
sections.stream()
|
sections.stream()
|
||||||
.flatMap(fs -> fs.Formatters.stream().filter(cf -> cf.removeCharCount > 0)
|
.flatMap(fs -> fs.Formatters.stream().filter(cf -> cf.removeCharCount > 0)
|
||||||
.mapToInt(cf -> cf.removeCharCount).mapToObj(rcc -> new int[]{fs.Start, fs.Start + rcc - 1}))
|
.mapToInt(cf -> cf.removeCharCount).mapToObj(rcc -> new int[]{fs.Start, fs.Start + rcc - 1}))
|
||||||
|
@ -210,8 +230,9 @@ public final class ChatFormatter {
|
||||||
.mapToInt(cf -> cf.removeCharCount).mapToObj(rcc -> new int[]{fs.End - rcc + 1, fs.End}))
|
.mapToInt(cf -> cf.removeCharCount).mapToObj(rcc -> new int[]{fs.End - rcc + 1, fs.End}))
|
||||||
.forEach(remchars::add);
|
.forEach(remchars::add);
|
||||||
DebugCommand.SendDebugMessage("Added remchars:");
|
DebugCommand.SendDebugMessage("Added remchars:");
|
||||||
DebugCommand
|
DebugCommand.SendDebugMessage(remchars.stream().map(Arrays::toString).collect(Collectors.joining("; ")));
|
||||||
.SendDebugMessage(remchars.stream().map(Arrays::toString).collect(Collectors.joining("; ")));
|
sendMessageWithPointer(str,
|
||||||
|
remchars.stream().flatMapToInt(Arrays::stream).toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void combineSections(String str, ArrayList<FormattedSection> sections) {
|
private static void combineSections(String str, ArrayList<FormattedSection> sections) {
|
||||||
|
@ -222,10 +243,21 @@ public final class ChatFormatter {
|
||||||
if (sections.size() < 2)
|
if (sections.size() < 2)
|
||||||
break;
|
break;
|
||||||
DebugCommand.SendDebugMessage("i: " + i);
|
DebugCommand.SendDebugMessage("i: " + i);
|
||||||
FormattedSection firstSection = sections.get(i - 1);
|
final FormattedSection firstSection;
|
||||||
|
final FormattedSection lastSection;
|
||||||
|
{
|
||||||
|
FormattedSection firstSect = sections.get(i - 1);
|
||||||
|
FormattedSection lastSect = sections.get(i);
|
||||||
|
if (firstSect.Start > lastSect.Start) { //The first can't start later
|
||||||
|
var section = firstSect;
|
||||||
|
firstSect = lastSect;
|
||||||
|
lastSect = section;
|
||||||
|
}
|
||||||
|
firstSection = firstSect;
|
||||||
|
lastSection = lastSect;
|
||||||
|
}
|
||||||
DebugCommand.SendDebugMessage("Combining sections " + firstSection);
|
DebugCommand.SendDebugMessage("Combining sections " + firstSection);
|
||||||
sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
||||||
final FormattedSection lastSection = sections.get(i);
|
|
||||||
DebugCommand.SendDebugMessage(" and " + lastSection);
|
DebugCommand.SendDebugMessage(" and " + lastSection);
|
||||||
sendMessageWithPointer(str, lastSection.Start, lastSection.End);
|
sendMessageWithPointer(str, lastSection.Start, lastSection.End);
|
||||||
if (firstSection.Start == lastSection.Start && firstSection.End == lastSection.End) {
|
if (firstSection.Start == lastSection.Start && firstSection.End == lastSection.End) {
|
||||||
|
@ -256,7 +288,7 @@ public final class ChatFormatter {
|
||||||
|
|
||||||
Predicate<FormattedSection> removeIfNeeded = s -> {
|
Predicate<FormattedSection> removeIfNeeded = s -> {
|
||||||
if (s.Start < 0 || s.End < 0 || s.Start > s.End) {
|
if (s.Start < 0 || s.End < 0 || s.Start > s.End) {
|
||||||
DebugCommand.SendDebugMessage("Removing section: " + s);
|
DebugCommand.SendDebugMessage(" Removed: " + s);
|
||||||
sendMessageWithPointer(str, s.Start, s.End);
|
sendMessageWithPointer(str, s.Start, s.End);
|
||||||
sections.remove(s);
|
sections.remove(s);
|
||||||
return true;
|
return true;
|
||||||
|
@ -310,11 +342,13 @@ public final class ChatFormatter {
|
||||||
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();
|
/*DebugCommand.SendDebugMessage("RCS: "+remchars.stream().filter(rc -> rc[0] <= start && start <= rc[1]).count());
|
||||||
val rce = remchars.stream().filter(rc -> rc[0] <= end && end <= rc[1]).findAny();
|
DebugCommand.SendDebugMessage("RCE: "+remchars.stream().filter(rc -> rc[0] <= end && end <= rc[1]).count());
|
||||||
val rci = remchars.stream().filter(rc -> start < rc[0] && rc[1] < end).toArray(int[][]::new);
|
DebugCommand.SendDebugMessage("RCI: "+remchars.stream().filter(rc -> start < rc[0] || rc[1] < end).count());*/
|
||||||
int s = start, e = end;
|
val rci = remchars.stream().filter(rc -> (rc[0] <= start && rc[1] >= start)
|
||||||
if (rcs.isPresent())
|
|| (rc[0] >= start && rc[1] <= end)
|
||||||
|
|| (rc[0] <= end && rc[1] >= end)).sorted(Comparator.comparingInt(rc -> rc[0] * 10000 + rc[1])).toArray(int[][]::new);
|
||||||
|
/*if (rcs.isPresent())
|
||||||
s = rcs.get()[1] + 1;
|
s = rcs.get()[1] + 1;
|
||||||
if (rce.isPresent())
|
if (rce.isPresent())
|
||||||
e = rce.get()[0] - 1;
|
e = rce.get()[0] - 1;
|
||||||
|
@ -322,12 +356,17 @@ public final class ChatFormatter {
|
||||||
if (e - s < 0) { //e-s==0 means the end char is the same as start char, so one char message
|
if (e - s < 0) { //e-s==0 means the end char is the same as start char, so one char message
|
||||||
DebugCommand.SendDebugMessage("Skipping section because of remchars (length would be " + (e - s + 1) + ")");
|
DebugCommand.SendDebugMessage("Skipping section because of remchars (length would be " + (e - s + 1) + ")");
|
||||||
continue;
|
continue;
|
||||||
}
|
}*/
|
||||||
originaltext = str.substring(s, e + 1);
|
DebugCommand.SendDebugMessage("Applying RC: " + Arrays.stream(rci).map(Arrays::toString).collect(Collectors.joining(", ", "[", "]")));
|
||||||
|
originaltext = str.substring(start, end + 1);
|
||||||
val sb = new StringBuilder(originaltext);
|
val sb = new StringBuilder(originaltext);
|
||||||
for (int x = rci.length - 1; x >= 0; x--)
|
for (int x = rci.length - 1; x >= 0; x--)
|
||||||
sb.delete(rci[x][0] - start - 1, rci[x][1] - start); //Delete going backwards
|
sb.delete(Math.max(rci[x][0] - start, 0), Math.min(rci[x][1] - start, end) + 1); //Delete going backwards
|
||||||
originaltext = sb.toString();
|
originaltext = sb.toString();
|
||||||
|
if (originaltext.length() == 0) {
|
||||||
|
DebugCommand.SendDebugMessage("Skipping section because of remchars");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
DebugCommand.SendDebugMessage("Section text: " + originaltext);
|
DebugCommand.SendDebugMessage("Section text: " + originaltext);
|
||||||
String openlink = null;
|
String openlink = null;
|
||||||
section.Formatters.sort(Comparator.comparing(cf2 -> cf2.priority.GetValue())); //Apply the highest last, to overwrite previous ones
|
section.Formatters.sort(Comparator.comparing(cf2 -> cf2.priority.GetValue())); //Apply the highest last, to overwrite previous ones
|
||||||
|
|
|
@ -65,8 +65,13 @@ 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/")), new TellrawPart(" heh").setItalic(true)));
|
.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),
|
list.add(new ChatFormatIT(sender, "*test _test_ test*", new TellrawPart("test test test").setItalic(true).setColor(Color.White)));
|
||||||
new TellrawPart("test").setItalic(true).setUnderlined(true).setColor(Color.White), new TellrawPart(" test").setItalic(true).setColor(Color.White)));
|
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)));
|
||||||
|
list.add(new ChatFormatIT(sender, "**test __test__ test**", new TellrawPart("test ").setBold(true).setColor(Color.White),
|
||||||
|
new TellrawPart("test").setBold(true).setUnderlined(true).setColor(Color.White), new TellrawPart(" test").setBold(true).setColor(Color.White)));
|
||||||
|
list.add(new ChatFormatIT(sender, "**test _test_ test**", new TellrawPart("test ").setBold(true).setColor(Color.White),
|
||||||
|
new TellrawPart("test").setItalic(true).setBold(true).setColor(Color.White), new TellrawPart(" test").setBold(true).setColor(Color.White)));
|
||||||
list.add(new ChatFormatIT(sender, "https://norbipeti.github.io/test?test&test#test", new TellrawPart("https://norbipeti.github.io/test?test&test#test")
|
list.add(new ChatFormatIT(sender, "https://norbipeti.github.io/test?test&test#test", new TellrawPart("https://norbipeti.github.io/test?test&test#test")
|
||||||
.setColor(Color.White).setUnderlined(true)
|
.setColor(Color.White).setUnderlined(true)
|
||||||
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT,
|
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT,
|
||||||
|
|
Loading…
Reference in a new issue