Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Paper's chat events #6033

Open
wants to merge 6 commits into
base: 2.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.earth2me.essentials.utils;

import net.ess3.api.IEssentials;
import net.ess3.provider.AbstractChatEvent;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.flattener.ComponentFlattener;
import net.kyori.adventure.text.format.NamedTextColor;
Expand All @@ -20,6 +21,7 @@ public final class AdventureUtil {
static {
final LegacyComponentSerializer.Builder builder = LegacyComponentSerializer.builder()
.flattener(ComponentFlattener.basic())
.extractUrls(AbstractChatEvent.URL_PATTERN)
.useUnusualXRepeatedCharacterHexFormat();
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_16_1_R01)) {
builder.hexColors();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.earth2me.essentials.utils;

import net.ess3.api.IUser;
import net.ess3.provider.AbstractChatEvent;
import org.bukkit.ChatColor;
import org.bukkit.Color;

Expand All @@ -24,7 +25,6 @@ public final class FormatUtil {
private static final Pattern REPLACE_ALL_RGB_PATTERN = Pattern.compile("(&)?&#([0-9a-fA-F]{6})");
//Used to prepare xmpp output
private static final Pattern LOGCOLOR_PATTERN = Pattern.compile("\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]");
private static final Pattern URL_PATTERN = Pattern.compile("((?:(?:https?)://)?[\\w-_\\.]{2,})\\.([a-zA-Z]{2,3}(?:/\\S+)?)");
//Used to strip ANSI control codes from console
private static final Pattern ANSI_CONTROL_PATTERN = Pattern.compile("[\\x1B\\x9B][\\[\\]()#;?]*(?:(?:(?:;[-a-zA-Z\\d/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d/#&.:=?%@~_]*)*)?\\x07|(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~])");
private static final Pattern PAPER_CONTROL_PATTERN = Pattern.compile("(?i)" + (char) 0x7f + "[0-9A-FK-ORX]");
Expand Down Expand Up @@ -297,9 +297,9 @@ static String blockURL(final String input) {
if (input == null) {
return null;
}
String text = URL_PATTERN.matcher(input).replaceAll("$1 $2");
while (URL_PATTERN.matcher(text).find()) {
text = URL_PATTERN.matcher(text).replaceAll("$1 $2");
String text = AbstractChatEvent.URL_PATTERN.matcher(input).replaceAll("$1 $2");
while (AbstractChatEvent.URL_PATTERN.matcher(text).find()) {
text = AbstractChatEvent.URL_PATTERN.matcher(text).replaceAll("$1 $2");
}
return text;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.EssentialsLogger;
import com.earth2me.essentials.chat.processing.ChatHandler;
import com.earth2me.essentials.chat.processing.PaperChatHandler;
import com.earth2me.essentials.metrics.MetricsWrapper;
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.IEssentials;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
Expand Down Expand Up @@ -32,8 +34,13 @@ public void onEnable() {
return;
}

final ChatHandler legacyHandler = new ChatHandler((Essentials) ess, this);
legacyHandler.registerListeners();
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_16_5_R01) && VersionUtil.isPaper()) {
final PaperChatHandler paperHandler = new PaperChatHandler((Essentials) ess, this);
paperHandler.registerListeners();
} else {
final ChatHandler legacyHandler = new ChatHandler((Essentials) ess, this);
legacyHandler.registerListeners();
}

if (metrics == null) {
metrics = new MetricsWrapper(this, 3814, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.earth2me.essentials.utils.AdventureUtil;
import com.earth2me.essentials.utils.FormatUtil;
import net.ess3.api.events.LocalChatSpyEvent;
import net.ess3.provider.AbstractChatEvent;
import net.essentialsx.api.v2.ChatType;
import net.essentialsx.api.v2.events.chat.ChatEvent;
import net.essentialsx.api.v2.events.chat.GlobalChatEvent;
Expand All @@ -22,10 +23,8 @@
import org.bukkit.scoreboard.Team;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import java.util.logging.Level;

import static com.earth2me.essentials.I18n.tlLiteral;

Expand All @@ -48,7 +47,7 @@ protected AbstractChatHandler(Essentials ess, EssentialsChat essChat) {
* <p>
* Handled at {@link org.bukkit.event.EventPriority#LOWEST} on both preview and chat events.
*/
protected void handleChatFormat(AsyncPlayerChatEvent event) {
protected void handleChatFormat(AbstractChatEvent event) {
if (isAborted(event)) {
return;
}
Expand All @@ -73,8 +72,9 @@ protected void handleChatFormat(AsyncPlayerChatEvent event) {
final long configRadius = ess.getSettings().getChatRadius();
chat.setRadius(Math.max(configRadius, 0));

final String formatted = FormatUtil.formatMessage(user, "essentials.chat", event.getMessage());
// This listener should apply the general chat formatting only...then return control back the event handler
event.setMessage(FormatUtil.formatMessage(user, "essentials.chat", event.getMessage()));
event.setMessage(formatted);

if (ChatColor.stripColor(event.getMessage()).isEmpty()) {
event.setCancelled(true);
Expand Down Expand Up @@ -110,6 +110,12 @@ protected void handleChatFormat(AsyncPlayerChatEvent event) {
event.setMessage(event.getMessage().substring(1));
}

// Prevent messages like "!&c" or "?&c" from being sent which would cause an empty message
if (ChatColor.stripColor(event.getMessage()).isEmpty()) {
event.setCancelled(true);
return;
}

if (chat.getType() == ChatType.UNKNOWN) {
format = AdventureUtil.miniToLegacy(tlLiteral("chatTypeLocal")).concat(format);
} else {
Expand All @@ -128,7 +134,7 @@ protected void handleChatFormat(AsyncPlayerChatEvent event) {
* <p>
* Runs at {@link org.bukkit.event.EventPriority#NORMAL} priority on submitted chat events only.
*/
protected void handleChatRecipients(AsyncPlayerChatEvent event) {
protected void handleChatRecipients(AbstractChatEvent event) {
if (isAborted(event)) {
return;
}
Expand All @@ -151,12 +157,12 @@ protected void handleChatRecipients(AsyncPlayerChatEvent event) {
return;
}

event.getRecipients().removeIf(player -> !ess.getUser(player).isAuthorized("essentials.chat.receive.local"));
event.removeRecipients(player -> !ess.getUser(player).isAuthorized("essentials.chat.receive.local"));
} else {
final String permission = "essentials.chat." + chat.getType().key();

if (user.isAuthorized(permission)) {
event.getRecipients().removeIf(player -> !ess.getUser(player).isAuthorized("essentials.chat.receive." + chat.getType().key()));
event.removeRecipients(player -> !ess.getUser(player).isAuthorized("essentials.chat.receive." + chat.getType().key()));

callChatEvent(event, chat.getType(), null);
} else {
Expand All @@ -171,22 +177,10 @@ protected void handleChatRecipients(AsyncPlayerChatEvent event) {
final Location loc = user.getLocation();
final World world = loc.getWorld();

final Set<Player> outList = event.getRecipients();
final Set<Player> spyList = new HashSet<>();

try {
outList.add(event.getPlayer());
} catch (final UnsupportedOperationException ex) {
if (ess.getSettings().isDebug()) {
essChat.getLogger().log(Level.INFO, "Plugin triggered custom chat event, local chat handling aborted.", ex);
}
return;
}

final Iterator<Player> it = outList.iterator();
while (it.hasNext()) {
final Player onlinePlayer = it.next();
final User onlineUser = ess.getUser(onlinePlayer);
event.removeRecipients(player -> {
final User onlineUser = ess.getUser(player);
if (!onlineUser.equals(user)) {
boolean abort = false;
final Location playerLoc = onlineUser.getLocation();
Expand All @@ -200,20 +194,21 @@ protected void handleChatRecipients(AsyncPlayerChatEvent event) {
}
if (abort) {
if (onlineUser.isAuthorized("essentials.chat.spy")) {
spyList.add(onlinePlayer);
spyList.add(player);
}
it.remove();
return true;
}
}
}
return false;
});

callChatEvent(event, ChatType.LOCAL, chat.getRadius());

if (event.isCancelled()) {
return;
}

if (outList.size() < 2) {
if (event.recipients().size() < 2) {
user.sendTl("localNoOne");
}

Expand Down Expand Up @@ -242,17 +237,22 @@ protected void handleChatRecipients(AsyncPlayerChatEvent event) {
* @param chatType Chat type which determines which event will be created and called.
* @param radius If chat is a local chat, this is a non-squared radius used to calculate recipients, otherwise {@code null}.
*/
protected void callChatEvent(final AsyncPlayerChatEvent event, final ChatType chatType, final Long radius) {
protected void callChatEvent(final AbstractChatEvent event, final ChatType chatType, final Long radius) {
final ChatEvent chatEvent;

if (chatType == ChatType.LOCAL) {
chatEvent = new LocalChatEvent(event.isAsynchronous(), event.getPlayer(), event.getFormat(), event.getMessage(), event.getRecipients(), radius);
chatEvent = new LocalChatEvent(event.isAsynchronous(), event.getPlayer(), event.getFormat(), event.getMessage(), event.recipients(), radius);
} else {
chatEvent = new GlobalChatEvent(event.isAsynchronous(), chatType, event.getPlayer(), event.getFormat(), event.getMessage(), event.getRecipients());
chatEvent = new GlobalChatEvent(event.isAsynchronous(), chatType, event.getPlayer(), event.getFormat(), event.getMessage(), event.recipients());
}

server.getPluginManager().callEvent(chatEvent);

event.removeRecipients(player -> !chatEvent.getRecipients().contains(player));
for (final Player recipient : chatEvent.getRecipients()) {
event.addRecipient(recipient);
}

event.setFormat(chatEvent.getFormat());
event.setMessage(chatEvent.getMessage());
event.setCancelled(chatEvent.isCancelled());
Expand All @@ -262,9 +262,9 @@ protected void callChatEvent(final AsyncPlayerChatEvent event, final ChatType ch
* Finalise the formatting stage of chat processing.
* <p>
* Handled at {@link org.bukkit.event.EventPriority#HIGHEST} during previews, and immediately after
* {@link #handleChatFormat(AsyncPlayerChatEvent)} when previews are not available.
* {@link #handleChatFormat(AbstractChatEvent)} when previews are not available.
*/
protected void handleChatPostFormat(AsyncPlayerChatEvent event) {
protected void handleChatPostFormat(AbstractChatEvent event) {
if (isAborted(event)) {
cache.clearProcessedChat(event.getPlayer());
}
Expand All @@ -273,7 +273,7 @@ protected void handleChatPostFormat(AsyncPlayerChatEvent event) {
/**
* Run costs for chat and clean up the cached {@link com.earth2me.essentials.chat.processing.ChatProcessingCache.ProcessedChat}
*/
protected void handleChatSubmit(AsyncPlayerChatEvent event) {
protected void handleChatSubmit(AbstractChatEvent event) {
if (isAborted(event)) {
return;
}
Expand All @@ -284,7 +284,7 @@ protected void handleChatSubmit(AsyncPlayerChatEvent event) {
cache.clearProcessedChat(event.getPlayer());
}

boolean isAborted(final AsyncPlayerChatEvent event) {
boolean isAborted(final AbstractChatEvent event) {
return event.isCancelled();
}

Expand Down Expand Up @@ -320,7 +320,7 @@ private void charge(final User user, final Trade charge) throws ChargeException
charge.charge(user);
}

boolean charge(final AsyncPlayerChatEvent event, final ChatProcessingCache.ProcessedChat chat) {
boolean charge(final AbstractChatEvent event, final ChatProcessingCache.ProcessedChat chat) {
try {
charge(chat.getUser(), chat.getCharge());
} catch (final ChargeException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.chat.EssentialsChat;
import net.ess3.provider.AbstractChatEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.AsyncPlayerChatEvent;
Expand All @@ -19,28 +20,33 @@ public void registerListeners() {
pm.registerEvents(new ChatHighest(), essChat);
}

private class ChatLowest implements ChatListener {
private AbstractChatEvent wrap(final AsyncPlayerChatEvent event) {
return new SpigotChatEvent(event);
}

private final class ChatLowest implements ChatListener {
@Override
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerChat(AsyncPlayerChatEvent event) {
handleChatFormat(event);
handleChatFormat(wrap(event));
}
}

private class ChatNormal implements ChatListener {
private final class ChatNormal implements ChatListener {
@Override
@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerChat(AsyncPlayerChatEvent event) {
handleChatRecipients(event);
handleChatRecipients(wrap(event));
}
}

private class ChatHighest implements ChatListener {
private final class ChatHighest implements ChatListener {
@Override
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerChat(AsyncPlayerChatEvent event) {
handleChatPostFormat(event);
handleChatSubmit(event);
final AbstractChatEvent absEvent = wrap(event);
handleChatPostFormat(absEvent);
handleChatSubmit(absEvent);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.earth2me.essentials.chat.processing;

import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.chat.EssentialsChat;
import net.ess3.provider.AbstractChatEvent;
import net.ess3.provider.providers.PaperChatListenerProvider;
import org.bukkit.plugin.PluginManager;

public class PaperChatHandler extends AbstractChatHandler {
public PaperChatHandler(Essentials ess, EssentialsChat essChat) {
super(ess, essChat);
}

public void registerListeners() {
final PluginManager pm = essChat.getServer().getPluginManager();
pm.registerEvents(new ChatListener(), essChat);
}

public final class ChatListener extends PaperChatListenerProvider {
@Override
public void onChatLowest(AbstractChatEvent event) {
handleChatFormat(event);
}

@Override
public void onChatNormal(AbstractChatEvent event) {
handleChatRecipients(event);
}

@Override
public void onChatHighest(AbstractChatEvent event) {
handleChatPostFormat(event);
handleChatSubmit(event);
}
}
}
Loading
Loading