Skip to content

Commit

Permalink
Add separate events for local and global chat
Browse files Browse the repository at this point in the history
This commit adds two new events: GlobalChatEvent and LocalChatEvent,
which allow other plugin developers to know whether the message sent is
a global or local one and act accordingly. If either of those events is
cancelled, then the source event is cancelled too.

Since all chat-related events share the same structure, a new abstract
class ChatEvent is created with change made for LocalChatSpyEvent to use
it without breaking its API.

Aids DiscordSRV/DiscordSRV#1223
  • Loading branch information
brawaru committed Apr 2, 2022
1 parent d891268 commit f9e6f52
Show file tree
Hide file tree
Showing 8 changed files with 262 additions and 109 deletions.
Original file line number Diff line number Diff line change
@@ -1,115 +1,28 @@
package net.ess3.api.events;

import net.essentialsx.api.v2.ChatType;
import net.essentialsx.api.v2.events.ChatEvent;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;

import java.util.IllegalFormatException;
import java.util.Set;

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

/**
* Fired when a player uses local chat.
* Fired when a player uses local chat and message is being sent to spies
*/
public class LocalChatSpyEvent extends Event implements Cancellable {
public class LocalChatSpyEvent extends ChatEvent {
private static final HandlerList handlers = new HandlerList();
private final Player player;
private final Set<Player> recipients;
private boolean cancelled = false;
private String message;
private String format;

public LocalChatSpyEvent(final boolean async, final Player who, final String format, final String message, final Set<Player> players) {
super(async);
this.format = tl("chatTypeLocal").concat(tl("chatTypeSpy")).concat(format);
this.message = message;
recipients = players;
player = who;
public LocalChatSpyEvent(final boolean async, final Player player, final String format, final String message, final Set<Player> recipients) {
super(async, ChatType.SPY, player, tl("chatTypeLocal").concat(tl("chatTypeSpy")).concat(format), message, recipients);
}

public static HandlerList getHandlerList() {
return handlers;
}

/**
* Gets the message that the player is attempting to send. This message will be used with {@link #getFormat()}.
*
* @return Message the player is attempting to send
*/
public String getMessage() {
return message;
}

/**
* Sets the message that the player will send. This message will be used with {@link #getFormat()}.
*
* @param message New message that the player will send
*/
public void setMessage(final String message) {
this.message = message;
}

/**
* Gets the format to use to display this chat message. When this event finishes execution, the first format
* parameter is the {@link Player#getDisplayName()} and the second parameter is {@link #getMessage()}
*
* @return {@link String#format(String, Object...)} compatible format string
*/
public String getFormat() {
return format;
}

/**
* Sets the format to use to display this chat message. When this event finishes execution, the first format
* parameter is the {@link Player#getDisplayName()} and the second parameter is {@link #getMessage()}
*
* @param format {@link String#format(String, Object...)} compatible format string
* @throws IllegalFormatException if the underlying API throws the exception
* @throws NullPointerException if format is null
* @see String#format(String, Object...)
*/
public void setFormat(final String format) throws IllegalFormatException, NullPointerException {
// Oh for a better way to do this!
try {
String.format(format, player, message);
} catch (final RuntimeException ex) {
ex.fillInStackTrace();
throw ex;
}

this.format = format;
}

/**
* Gets a set of recipients that this chat message will be displayed to.
*
* @return All Players who will see this chat message
*/
public Set<Player> getRecipients() {
return recipients;
}

/**
* Returns the player involved in this event
*
* @return Player who is involved in this event
*/
public final Player getPlayer() {
return player;
}

@Override
public boolean isCancelled() {
return cancelled;
}

@Override
public void setCancelled(final boolean cancel) {
this.cancelled = cancel;
}

@Override
public HandlerList getHandlers() {
return handlers;
Expand Down
33 changes: 33 additions & 0 deletions Essentials/src/main/java/net/essentialsx/api/v2/ChatType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package net.essentialsx.api.v2;

/**
* Represent a type of chat for a message
*/
public enum ChatType {
/**
* Message is being sent to global chat as a shout
*/
SHOUT,

/**
* Message is being sent to global chat as a question
*/
QUESTION,

/**
* Message is being sent locally
*/
LOCAL,

/**
* Message is being sent to spy channel
*/
SPY,

/**
* Type of chat is not determined
*
* <p>This type used when local/global chat features are disabled
*/
UNKNOWN,
}
118 changes: 118 additions & 0 deletions Essentials/src/main/java/net/essentialsx/api/v2/events/ChatEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package net.essentialsx.api.v2.events;

import net.essentialsx.api.v2.ChatType;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;

import java.util.IllegalFormatException;
import java.util.Set;

/**
* This handles common boilerplate for other ChatEvents
*/
public abstract class ChatEvent extends Event implements Cancellable {
private final ChatType chatType;
private final Player player;
private final Set<Player> recipients;
private String message;
private String format;

private boolean cancelled = false;

public ChatEvent(final boolean async, final ChatType chatType, final Player player, final String format, final String message, final Set<Player> recipients) {
super(async);

this.chatType = chatType;
this.player = player;
this.format = format;
this.message = message;
this.recipients = recipients;
}

/**
* Gets the message that the player is attempting to send. This message will be used with {@link #getFormat()}.
*
* @return Message the player is attempting to send
*/
public String getMessage() {
return message;
}

/**
* Sets the message that the player will send. This message will be used with {@link #getFormat()}.
*
* @param message New message that the player will send
*/
public void setMessage(final String message) {
this.message = message;
}

/**
* Gets the format to use to display this chat message. When this event finishes execution, the first format
* parameter is the {@link Player#getDisplayName()} and the second parameter is {@link #getMessage()}
*
* @return {@link String#format(String, Object...)} compatible format string
*/
public String getFormat() {
return format;
}

/**
* Sets the format to use to display this chat message. When this event finishes execution, the first format
* parameter is the {@link Player#getDisplayName()} and the second parameter is {@link #getMessage()}
*
* @param format {@link String#format(String, Object...)} compatible format string
* @throws IllegalFormatException if the underlying API throws the exception
* @throws NullPointerException if format is null
* @see String#format(String, Object...)
*/
public void setFormat(final String format) throws IllegalFormatException, NullPointerException {
// Oh for a better way to do this!
try {
String.format(format, player, message);
} catch (final RuntimeException ex) {
ex.fillInStackTrace();
throw ex;
}

this.format = format;
}

/**
* Gets a set of recipients that this chat message will be displayed to.
*
* @return All Players who will see this chat message
*/
public Set<Player> getRecipients() {
return recipients;
}

/**
* Returns the player involved in this event
*
* @return Player who is involved in this event
*/
public final Player getPlayer() {
return player;
}

/**
* Returns the type of chat this event is fired for
*
* @return Type of chat this event is fired for
*/
public ChatType getChatType() {
return chatType;
}

@Override
public boolean isCancelled() {
return cancelled;
}

@Override
public void setCancelled(final boolean cancel) {
this.cancelled = cancel;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package net.essentialsx.api.v2.events;

import net.essentialsx.api.v2.ChatType;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;

import java.util.Set;

/**
* Fired when a player uses global chat
*/
public class GlobalChatEvent extends ChatEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();

public GlobalChatEvent(final boolean async, final ChatType chatType, final Player player, final String format, final String message, final Set<Player> recipients) {
super(async, chatType, player, format, message, recipients);
}

public static HandlerList getHandlerList() {
return handlers;
}

@Override
public HandlerList getHandlers() {
return handlers;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package net.essentialsx.api.v2.events;

import net.essentialsx.api.v2.ChatType;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;

import java.util.Set;

/**
* Fired when a player uses local chat
*/
public class LocalChatEvent extends ChatEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();

public LocalChatEvent(final boolean async, final Player player, final String format, final String message, final Set<Player> recipients) {
super(async, ChatType.LOCAL, player, format, message, recipients);
}

public static HandlerList getHandlerList() {
return handlers;
}

@Override
public HandlerList getHandlers() {
return handlers;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@

import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import net.essentialsx.api.v2.ChatType;
import net.ess3.api.IEssentials;

import java.util.Locale;

class ChatStore {
private final User user;
private final String type;
private final ChatType type;
private final Trade charge;
private long radius;

ChatStore(final IEssentials ess, final User user, final String type) {
ChatStore(final IEssentials ess, final User user, final ChatType type) {
this.user = user;
this.type = type;
this.charge = new Trade(getLongType(), ess);
Expand All @@ -24,12 +27,12 @@ Trade getCharge() {
return charge;
}

String getType() {
ChatType getType() {
return type;
}

final String getLongType() {
return type.length() == 0 ? "chat" : "chat-" + type;
return type == ChatType.UNKNOWN ? "chat" : "chat-" + type.name().toLowerCase(Locale.ENGLISH);
}

long getRadius() {
Expand Down
Loading

0 comments on commit f9e6f52

Please sign in to comment.