diff --git a/README.md b/README.md index 72a00cb..c2f4c14 100644 --- a/README.md +++ b/README.md @@ -93,3 +93,45 @@ Register the listener with getProxy().getPluginManager().registerListener(this, new StaffChatListener()); ``` in your plugin onEnable. + +### Velocity + +```java +public class StaffChatListener { + + @Subscribe + public void onStaffChat(VelocityStaffChatEvent event) { + // Player player = event.getPlayer(); + // String format = event.getFormat(); + // String message = event.getMessage(); + // StaffChatResult result = StaffChatResult.denied(); + // StaffChatResult result = StaffChatResult.format("&b{NAME} >> {MESSAGE}"); + // StaffChatResult result = StaffChatResult.message(filterMessage(message)); + // StaffChatResult result = StaffChatResult.formatAndMessage("&b{NAME} >> {MESSAGE}", filterMessage(message)); + // event.setResult(result); + } + + private static String filterMessage(String message) { + // ... + return message; + } +} +``` +Register the listener on the `ProxyInitializeEvent` in your plugin. +```java +@Plugin +public class Plugin { + + private final ProxyServer server; + + @Inject + public Plugin(ProxyServer server) { + this.server = server; + } + + @Subscribe + public void onProxyInitialization(ProxyInitializeEvent event) { + server.getEventManager().register(this, new StaffChatListener()); + } +} +``` \ No newline at end of file diff --git a/src/velocity/java/me/oskar3123/staffchat/velocity/event/VelocityStaffChatEvent.java b/src/velocity/java/me/oskar3123/staffchat/velocity/event/VelocityStaffChatEvent.java new file mode 100644 index 0000000..93f6b81 --- /dev/null +++ b/src/velocity/java/me/oskar3123/staffchat/velocity/event/VelocityStaffChatEvent.java @@ -0,0 +1,260 @@ +package me.oskar3123.staffchat.velocity.event; + +import com.velocitypowered.api.event.ResultedEvent; +import com.velocitypowered.api.proxy.Player; +import java.util.Objects; +import java.util.Optional; +import java.util.StringJoiner; +import me.oskar3123.staffchat.velocity.event.VelocityStaffChatEvent.StaffChatResult; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +/** + * Event fired after deciding to broadcast a staff message. + * + *

Denying this event will still block the chat message. + */ +public class VelocityStaffChatEvent implements ResultedEvent { + + private final Player player; + private final String format; + private final String message; + + private StaffChatResult result = StaffChatResult.allowed(); + + @Contract(pure = true) + public VelocityStaffChatEvent( + @NotNull Player player, @NotNull String format, @NotNull String message) { + this.player = Objects.requireNonNull(player, "player must not be null"); + this.format = Objects.requireNonNull(format, "format must not be null"); + this.message = Objects.requireNonNull(message, "message must not be null"); + } + + /** + * Gets the player that is sending the staff chat message. + * + * @return the player + */ + @NotNull + @Contract(pure = true) + public Player getPlayer() { + return player; + } + + /** + * Gets the initial format decided by the plugin. + * + *

Use {@link #getResult()} to get the potentially modified format. + * + * @return the initial format + */ + @NotNull + @Contract(pure = true) + public String getFormat() { + return format; + } + + /** + * Gets the initial message entered by the player. + * + *

Use {@link #getResult()} to get the potentially modified message. + * + * @return the initial message + */ + @NotNull + @Contract(pure = true) + public String getMessage() { + return message; + } + + /** + * Gets the current result. + * + *

This will by default be an allowed result with no modifications. + * + * @return the current result + */ + @NotNull + @Contract(pure = true) + @Override + public StaffChatResult getResult() { + return result; + } + + /** + * Sets the current result. + * + *

You can {@linkplain StaffChatResult#allowed() allow}, {@linkplain StaffChatResult#denied() + * deny}, {@linkplain StaffChatResult#format(String) modify the format}, {@linkplain + * StaffChatResult#message(String) modify the message}, or {@linkplain + * StaffChatResult#formatAndMessage(String, String) modify both the format and message}. + * + * @param result the new result + */ + @Override + public void setResult(@NotNull StaffChatResult result) { + this.result = Objects.requireNonNull(result, "result must not be null"); + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + VelocityStaffChatEvent that = (VelocityStaffChatEvent) o; + return Objects.equals(player, that.player) + && Objects.equals(format, that.format) + && Objects.equals(message, that.message) + && Objects.equals(result, that.result); + } + + @Override + public int hashCode() { + return Objects.hash(player, format, message, result); + } + + @Override + public String toString() { + return new StringJoiner(", ", VelocityStaffChatEvent.class.getSimpleName() + "[", "]") + .add("player=" + player) + .add("format='" + format + "'") + .add("message='" + message + "'") + .add("result=" + result) + .toString(); + } + + /** Result of the {@linkplain VelocityStaffChatEvent}. */ + public static class StaffChatResult implements Result { + + private static final StaffChatResult ALLOWED = new StaffChatResult(true, null, null); + private static final StaffChatResult DENIED = new StaffChatResult(false, null, null); + + private final boolean allowed; + private final String format; + private final String message; + + private StaffChatResult(boolean allowed, String format, String message) { + this.allowed = allowed; + this.format = format; + this.message = message; + } + + /** + * Allows the message to be sent, without modifying anything. + * + * @return the allowed result + */ + @NotNull + @Contract(pure = true) + public static StaffChatResult allowed() { + return ALLOWED; + } + + /** + * Prevents the message from being sent. + * + * @return the denied result + */ + @NotNull + @Contract(pure = true) + public static StaffChatResult denied() { + return DENIED; + } + + /** + * Allows the message to be sent, modifying the format. + * + * @param format the format + * @return the modify format result + */ + @NotNull + @Contract(value = "_ -> new", pure = true) + public static StaffChatResult format(@NotNull String format) { + return new StaffChatResult( + true, Objects.requireNonNull(format, "format must not be null"), null); + } + + /** + * Allows the message to be sent, modifying the message. + * + * @param message the message + * @return the modify message result + */ + @NotNull + @Contract(value = "_ -> new", pure = true) + public static StaffChatResult message(@NotNull String message) { + return new StaffChatResult( + true, null, Objects.requireNonNull(message, "message must not be null")); + } + + /** + * Allows the message to be sent, modifying the format and message. + * + * @param format the format + * @param message the message + * @return the modify format and message result + */ + @NotNull + @Contract(value = "_, _ -> new", pure = true) + public static StaffChatResult formatAndMessage( + @NotNull String format, @NotNull String message) { + return new StaffChatResult( + true, + Objects.requireNonNull(format, "format must not be null"), + Objects.requireNonNull(message, "message must not be null")); + } + + @Contract(pure = true) + @Override + public boolean isAllowed() { + return allowed; + } + + /** + * Gets the potentially modified format. + * + *

An empty optional means that the format has not been modified. + * + * @return the potentially modified format + */ + @NotNull + @Contract(pure = true) + public Optional getFormat() { + return Optional.ofNullable(format); + } + + /** + * Gets the potentially modified message. + * + *

An empty optional means that the message has not been modified. + * + * @return the potentially modified message + */ + @NotNull + @Contract(pure = true) + public Optional getMessage() { + return Optional.ofNullable(message); + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + StaffChatResult that = (StaffChatResult) o; + return allowed == that.allowed + && Objects.equals(format, that.format) + && Objects.equals(message, that.message); + } + + @Override + public int hashCode() { + return Objects.hash(allowed, format, message); + } + + @Override + public String toString() { + return new StringJoiner(", ", StaffChatResult.class.getSimpleName() + "[", "]") + .add("allowed=" + allowed) + .add("format='" + format + "'") + .add("message='" + message + "'") + .toString(); + } + } +} diff --git a/src/velocity/java/me/oskar3123/staffchat/velocity/handler/VelocityStaffChatHandler.java b/src/velocity/java/me/oskar3123/staffchat/velocity/handler/VelocityStaffChatHandler.java index 34b196b..c425594 100644 --- a/src/velocity/java/me/oskar3123/staffchat/velocity/handler/VelocityStaffChatHandler.java +++ b/src/velocity/java/me/oskar3123/staffchat/velocity/handler/VelocityStaffChatHandler.java @@ -8,6 +8,8 @@ import java.util.function.Function; import me.oskar3123.staffchat.util.FormatUtils; import me.oskar3123.staffchat.util.Permissions; import me.oskar3123.staffchat.velocity.VelocityStaffChat; +import me.oskar3123.staffchat.velocity.event.VelocityStaffChatEvent; +import me.oskar3123.staffchat.velocity.event.VelocityStaffChatEvent.StaffChatResult; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; @@ -35,11 +37,31 @@ public class VelocityStaffChatHandler { } } - public void broadcastStaffMessage(Player sender, String message) { + public void broadcastStaffMessage(Player player, String message) { String format = plugin.getConfig().node("settings", "format").getString("&b{NAME}: {MESSAGE}"); + plugin + .getServer() + .getEventManager() + .fire(new VelocityStaffChatEvent(player, format, message)) + .thenAccept( + staffChatEvent -> { + StaffChatResult result = staffChatEvent.getResult(); + + if (result.isAllowed()) { + plugin + .getStaffChatHandler() + .broadcastStaffMessage( + player, + result.getFormat().orElse(format), + result.getMessage().orElse(message)); + } + }); + } + + private void broadcastStaffMessage(Player player, String format, String message) { String formattedMessage = - FormatUtils.replacePlaceholders(format, Function.identity(), sender::getUsername, message); + FormatUtils.replacePlaceholders(format, Function.identity(), player::getUsername, message); TextComponent component = LegacyComponentSerializer.legacyAmpersand().deserialize(formattedMessage);