From b1c297cccb2588a7b7b7cf4dec0a2e848cf46c17 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Thu, 15 Feb 2024 15:24:52 +0200 Subject: [PATCH 01/14] add HikariCP --- pom.xml | 6 ++++ .../smp/cloudnodemsg/CloudnodeMSG.java | 26 +++++++++++++-- .../smp/cloudnodemsg/PluginConfig.java | 29 +++++++++++++++++ src/main/resources/config.yml | 32 +++++++++++++++++++ 4 files changed, 91 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index b6e25b1..ed72cad 100644 --- a/pom.xml +++ b/pom.xml @@ -81,5 +81,11 @@ 1.20.2-R0.1-SNAPSHOT provided + + com.zaxxer + HikariCP + 5.1.0 + compile + diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java index cbf382a..08d9e7b 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java @@ -1,5 +1,7 @@ package pro.cloudnode.smp.cloudnodemsg; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; import org.bukkit.entity.Player; import org.bukkit.metadata.MetadataValue; import org.bukkit.plugin.java.JavaPlugin; @@ -8,10 +10,11 @@ import pro.cloudnode.smp.cloudnodemsg.command.MainCommand; import pro.cloudnode.smp.cloudnodemsg.command.MessageCommand; import pro.cloudnode.smp.cloudnodemsg.command.ReplyCommand; +import pro.cloudnode.smp.cloudnodemsg.command.ToggleMessageCommand; import pro.cloudnode.smp.cloudnodemsg.command.UnIgnoreCommand; import pro.cloudnode.smp.cloudnodemsg.listener.AsyncChatListener; -import pro.cloudnode.smp.cloudnodemsg.command.ToggleMessageCommand; +import java.util.Map; import java.util.Objects; public final class CloudnodeMSG extends JavaPlugin { @@ -22,6 +25,7 @@ public final class CloudnodeMSG extends JavaPlugin { public void reload() { getInstance().reloadConfig(); getInstance().config.config = getInstance().getConfig(); + setupDbSource(); } @Override @@ -41,7 +45,7 @@ public void onEnable() { @Override public void onDisable() { - // Plugin shutdown logic + dbSource.close(); } public static boolean isVanished(final @NotNull Player player) { @@ -55,4 +59,22 @@ public static boolean isVanished(final @NotNull Player player) { public @NotNull PluginConfig config() { return config; } + + public final @NotNull HikariConfig hikariConfig = new HikariConfig(); + private HikariDataSource dbSource; + + public @NotNull HikariDataSource db() { + return dbSource; + } + + private void setupDbSource() { + if (dbSource != null) dbSource.close(); + hikariConfig.setDriverClassName("org.sqlite.JDBC"); + hikariConfig.setJdbcUrl("jdbc:sqlite:" + getDataFolder().getAbsolutePath() + "/" + config().dbSqliteFile()); + + for (final @NotNull Map.Entry<@NotNull String, @NotNull String> entry : config().dbHikariProperties().entrySet()) + hikariConfig.addDataSourceProperty(entry.getKey(), entry.getValue()); + + dbSource = new HikariDataSource(hikariConfig); + } } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java index 2bb0922..eca3a09 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java @@ -6,6 +6,10 @@ import org.bukkit.configuration.file.FileConfiguration; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Objects; public final class PluginConfig { @@ -15,6 +19,31 @@ public PluginConfig(final @NotNull FileConfiguration config) { this.config = config; } + /** + * Database file name (in the plugin's folder) + *

If the file does not exist, it will be created

+ */ + public @NotNull String dbSqliteFile() { + return Objects.requireNonNull(config.getString("db.sqlite.file")); + } + + /** + * Advanced DB configuration / HikariCP properties + *

Only change if you know what you're doing; you can add or remove any property you want

+ */ + public @NotNull HashMap<@NotNull String, @NotNull String> dbHikariProperties() { + final @NotNull List<@NotNull Map> mapList = config.getMapList("db.hikaricp"); + final @NotNull HashMap<@NotNull String, @NotNull String> properties = new HashMap<>(mapList.size()); + + for (final @NotNull Map map : mapList) + if ( + map.get("name") instanceof final @NotNull String name + && map.get("value") instanceof final @NotNull String value + ) properties.put(name, value); + + return properties; + } + /** * Incoming message format (recipient's point of view) *

Placeholders:

diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index cfaec5f..5b9b065 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,3 +1,35 @@ +# Database configuration +db: + sqlite: + # Database file name (in the plugin's folder) + # If the file does not exist, it will be created + file: 'cloudnodemsg.db' + + # Advanced DB configuration / HikariCP properties + # Only change if you know what you're doing; you can add or remove any property you want + hikaricp: + - name: "cachePrepStmts" + value: "true" + - name: "prepStmtCacheSize" + value: "250" + - name: "prepStmtCacheSqlLimit" + value: "2048" + - name: "useServerPrepStmts" + value: "true" + - name: "useLocalSessionState" + value: "true" + - name: "rewriteBatchedStatements" + value: "true" + - name: "cacheResultSetMetadata" + value: "true" + - name: "cacheServerConfiguration" + value: "true" + - name: "elideSetAutoCommits" + value: "true" + - name: "maintainTimeStats" + value: "false" + + # Incoming message format (recipient's point of view) # Placeholders: # - the username of the message sender From e79b7c8442eefaa2c1ec6cdd217030aef19d2eb8 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Thu, 15 Feb 2024 15:26:28 +0200 Subject: [PATCH 02/14] Add DDL script (db init) --- .../smp/cloudnodemsg/CloudnodeMSG.java | 37 +++++++++++++++++++ src/main/resources/ddl/sqlite.sql | 9 +++++ 2 files changed, 46 insertions(+) create mode 100644 src/main/resources/ddl/sqlite.sql diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java index 08d9e7b..5d6d45b 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java @@ -6,6 +6,7 @@ import org.bukkit.metadata.MetadataValue; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import pro.cloudnode.smp.cloudnodemsg.command.IgnoreCommand; import pro.cloudnode.smp.cloudnodemsg.command.MainCommand; import pro.cloudnode.smp.cloudnodemsg.command.MessageCommand; @@ -14,8 +15,13 @@ import pro.cloudnode.smp.cloudnodemsg.command.UnIgnoreCommand; import pro.cloudnode.smp.cloudnodemsg.listener.AsyncChatListener; +import java.io.InputStream; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Arrays; import java.util.Map; import java.util.Objects; +import java.util.logging.Level; public final class CloudnodeMSG extends JavaPlugin { public static @NotNull CloudnodeMSG getInstance() { @@ -26,6 +32,7 @@ public void reload() { getInstance().reloadConfig(); getInstance().config.config = getInstance().getConfig(); setupDbSource(); + runDDL(); } @Override @@ -77,4 +84,34 @@ private void setupDbSource() { dbSource = new HikariDataSource(hikariConfig); } + + /** + * Run DDL script + */ + public void runDDL() { + final @NotNull String file = "ddl/sqlite.sql"; + final @NotNull String @NotNull [] queries; + try (final @Nullable InputStream inputStream = getClassLoader().getResourceAsStream(file)) { + queries = Arrays.stream( + new String(Objects.requireNonNull(inputStream).readAllBytes()).split(";") + ).map(q -> q.stripTrailing().stripIndent().replaceAll("^\\s+(?:--.+)*", "")).toArray(String[]::new); + } + catch (final @NotNull Exception exception) { + getLogger().log(Level.SEVERE, "Could not read DDL script: " + file, exception); + getServer().getPluginManager().disablePlugin(this); + return; + } + for (final @NotNull String query : queries) { + if (query.isBlank()) continue; + try (final @NotNull PreparedStatement stmt = db().getConnection().prepareStatement(query)) { + stmt.execute(); + } + catch (final @NotNull SQLException exception) { + getLogger().log(Level.SEVERE, "Could not execute DDL query: " + query, exception); + getServer().getPluginManager().disablePlugin(this); + return; + } + } + getLogger().info("Database successfully initialised with DDL"); + } } diff --git a/src/main/resources/ddl/sqlite.sql b/src/main/resources/ddl/sqlite.sql new file mode 100644 index 0000000..901a8aa --- /dev/null +++ b/src/main/resources/ddl/sqlite.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS `cloudnodemsg_mail` +( + `id` CHAR(32) COLLATE NOCASE PRIMARY KEY, + `sender` CHAR(32) COLLATE NOCASE NOT NULL, + `recipient` CHAR(32) COLLATE NOCASE NOT NULL, + `message` TEXT NOT NULL, + `seen` BOOLEAN DEFAULT 0, + `starred` BOOLEAN DEFAULT 0 +); From 543b5278b699c5689502a0671e1094718d8e226a Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Thu, 15 Feb 2024 15:31:19 +0200 Subject: [PATCH 03/14] annotate HikariDataSource nullable and assert not null --- src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java index 5d6d45b..a2a72d9 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java @@ -68,9 +68,10 @@ public static boolean isVanished(final @NotNull Player player) { } public final @NotNull HikariConfig hikariConfig = new HikariConfig(); - private HikariDataSource dbSource; + private @Nullable HikariDataSource dbSource; public @NotNull HikariDataSource db() { + assert dbSource != null; return dbSource; } From cd09eb3e6b9017b06d3adf0f9b9a221dd3ce03e4 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Thu, 15 Feb 2024 18:02:15 +0200 Subject: [PATCH 04/14] mail class --- .../pro/cloudnode/smp/cloudnodemsg/Mail.java | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 src/main/java/pro/cloudnode/smp/cloudnodemsg/Mail.java diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/Mail.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/Mail.java new file mode 100644 index 0000000..901f8fc --- /dev/null +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/Mail.java @@ -0,0 +1,105 @@ +package pro.cloudnode.smp.cloudnodemsg; + +import org.bukkit.OfflinePlayer; +import org.bukkit.Server; +import org.jetbrains.annotations.NotNull; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Optional; +import java.util.UUID; +import java.util.logging.Level; + +public final class Mail { + public final @NotNull UUID id; + public final @NotNull OfflinePlayer sender; + public final @NotNull OfflinePlayer recipient; + public final @NotNull String message; + public boolean seen; + + public boolean starred; + + public Mail(final @NotNull OfflinePlayer sender, final @NotNull OfflinePlayer recipient, final @NotNull String message) { + this.id = UUID.randomUUID(); + this.sender = sender; + this.recipient = recipient; + this.message = message; + this.seen = false; + this.starred = false; + } + + public Mail(final @NotNull ResultSet rs) throws SQLException { + final @NotNull Server server = CloudnodeMSG.getInstance().getServer(); + + this.id = UUID.fromString(rs.getString("id")); + this.sender = server.getOfflinePlayer(UUID.fromString(rs.getString("sender"))); + this.recipient = server.getOfflinePlayer(UUID.fromString(rs.getString("recipient"))); + this.message = rs.getString("message"); + this.seen = rs.getBoolean("seen"); + this.starred = rs.getBoolean("starred"); + } + + public void update() { + try (final @NotNull PreparedStatement stmt = CloudnodeMSG.getInstance().db().getConnection().prepareStatement("UPDATE `cloudnodemsg_mail` SET `seen` = ?, `starred` = ? WHERE `id` = ?")) { + stmt.setBoolean(1, seen); + stmt.setBoolean(2, starred); + stmt.setString(3, id.toString()); + stmt.executeUpdate(); + } + catch (final @NotNull SQLException exception) { + CloudnodeMSG.getInstance().getLogger().log(Level.SEVERE, "Could not update mail: " + id, exception); + } + } + + public void delete() { + try (final @NotNull PreparedStatement stmt = CloudnodeMSG.getInstance().db().getConnection().prepareStatement("DELETE FROM `cloudnodemsg_mail` WHERE `id` = ?")) { + stmt.setString(1, id.toString()); + stmt.executeUpdate(); + } + catch (final @NotNull SQLException exception) { + CloudnodeMSG.getInstance().getLogger().log(Level.SEVERE, "Could not delete mail: " + id, exception); + } + } + + public void insert() { + try (final @NotNull PreparedStatement stmt = CloudnodeMSG.getInstance().db().getConnection().prepareStatement("INSERT INTO `cloudnodemsg_mail` (`id`, `sender`, `recipient`, `message`, `seen`, `starred`) VALUES (?, ?, ?, ?, ?, ?)")) { + stmt.setString(1, id.toString()); + stmt.setString(2, sender.getUniqueId().toString()); + stmt.setString(3, recipient.getUniqueId().toString()); + stmt.setString(4, message); + stmt.setBoolean(5, seen); + stmt.setBoolean(6, starred); + stmt.executeUpdate(); + } + catch (final @NotNull SQLException exception) { + CloudnodeMSG.getInstance().getLogger().log(Level.SEVERE, "Could not insert mail: " + id, exception); + } + } + + public static @NotNull Optional<@NotNull Mail> get(final @NotNull UUID id) { + try (final @NotNull PreparedStatement stmt = CloudnodeMSG.getInstance().db().getConnection().prepareStatement("SELECT * FROM `cloudnodemsg_mail` WHERE `id` = ? LIMIT 1")) { + stmt.setString(1, id.toString()); + final @NotNull ResultSet rs = stmt.executeQuery(); + if (!rs.next()) return Optional.empty(); + return Optional.of(new Mail(rs)); + } + catch (final @NotNull SQLException exception) { + CloudnodeMSG.getInstance().getLogger().log(Level.SEVERE, "Could not get mail: " + id, exception); + return Optional.empty(); + } + } + + public static int unread(final @NotNull OfflinePlayer player) { + try (final @NotNull PreparedStatement stmt = CloudnodeMSG.getInstance().db().getConnection().prepareStatement("SELECT COUNT(`id`) as `n` FROM `cloudnodemsg_mail` WHERE `recipient` = ? AND `seen` = 0")) { + stmt.setString(1, player.getUniqueId().toString()); + final @NotNull ResultSet rs = stmt.executeQuery(); + if (!rs.next()) return 0; + return rs.getInt("n"); + } + catch (final @NotNull SQLException exception) { + CloudnodeMSG.getInstance().getLogger().log(Level.SEVERE, "Could not get unread mails: " + player.getName(), exception); + return 0; + } + } +} From fce58e1ca403933a398cf4bc519186c5bef22a82 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Thu, 15 Feb 2024 19:45:15 +0200 Subject: [PATCH 05/14] unread mail notification on join --- .../smp/cloudnodemsg/CloudnodeMSG.java | 2 ++ .../smp/cloudnodemsg/Permission.java | 5 ++++ .../smp/cloudnodemsg/PluginConfig.java | 27 +++++++++++++++++++ .../listener/PlayerJoinListener.java | 23 ++++++++++++++++ src/main/resources/config.yml | 12 +++++++++ 5 files changed, 69 insertions(+) create mode 100644 src/main/java/pro/cloudnode/smp/cloudnodemsg/listener/PlayerJoinListener.java diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java index a2a72d9..410f6d3 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java @@ -14,6 +14,7 @@ import pro.cloudnode.smp.cloudnodemsg.command.ToggleMessageCommand; import pro.cloudnode.smp.cloudnodemsg.command.UnIgnoreCommand; import pro.cloudnode.smp.cloudnodemsg.listener.AsyncChatListener; +import pro.cloudnode.smp.cloudnodemsg.listener.PlayerJoinListener; import java.io.InputStream; import java.sql.PreparedStatement; @@ -48,6 +49,7 @@ public void onEnable() { Objects.requireNonNull(getCommand("togglemsg")).setExecutor(new ToggleMessageCommand()); getServer().getPluginManager().registerEvents(new AsyncChatListener(), this); + getServer().getPluginManager().registerEvents(new PlayerJoinListener(), this); } @Override diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/Permission.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/Permission.java index a0e6228..e59b968 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/Permission.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/Permission.java @@ -47,4 +47,9 @@ public final class Permission { * Allows to see the private messages of other players */ public final static @NotNull String SPY = "cloudnodemsg.spy"; + + /** + * Allows using the /mail command + */ + public final static @NotNull String MAIL = "cloudnodemsg.mail"; } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java index eca3a09..f18e33d 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java @@ -256,6 +256,33 @@ public PluginConfig(final @NotNull FileConfiguration config) { ); } + /** + * Should players be notified for unread mail on login? + */ + public boolean mailNotifyOnLogin() { + return config.getBoolean("mail.notify-on-login"); + } + + /** + * Interval (in seconds) to notify players of unread mail. Set to 0 to disable. + */ + public int mailNotifyInterval() { + return config.getInt("mail.notify-interval"); + } + + /** + * Unread mail notification message + *

Placeholders:

+ *
  • {@code } - the number of unread mail messages
+ * + * @param unread the number of unread mail messages + */ + public @NotNull Component mailNotify(final int unread) { + return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("mail.notify")), + Placeholder.unparsed("unread", String.valueOf(unread)) + ); + } + /** * No permission */ diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/listener/PlayerJoinListener.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/listener/PlayerJoinListener.java new file mode 100644 index 0000000..09b1581 --- /dev/null +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/listener/PlayerJoinListener.java @@ -0,0 +1,23 @@ +package pro.cloudnode.smp.cloudnodemsg.listener; + +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.jetbrains.annotations.NotNull; +import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG; +import pro.cloudnode.smp.cloudnodemsg.Mail; +import pro.cloudnode.smp.cloudnodemsg.Permission; + +public final class PlayerJoinListener implements Listener { + @EventHandler + public void onPlayerJoin(final @NotNull PlayerJoinEvent event) { + event.getPlayer().getServer().getScheduler().runTaskAsynchronously(CloudnodeMSG.getInstance(), () -> { + if (!CloudnodeMSG.getInstance().config().mailNotifyOnLogin()) return; + final @NotNull Player player = event.getPlayer(); + if (!player.hasPermission(Permission.MAIL)) return; + final int unread = Mail.unread(player); + if (unread > 0) player.sendMessage(CloudnodeMSG.getInstance().config().mailNotify(unread)); + }); + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 5b9b065..415fd25 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -98,6 +98,18 @@ toggle: # - the player's username other: "(!) Re-enabled private messages for ." +mail: + # Should players be notified for unread mail on login? + notify-on-login: true + + # Interval (in seconds) to notify players of unread mail. Set to 0 to disable. + notify-interval: 180 + + # Unread mail notification message + # Placeholders: + # - the number of unread mail messages + notify: "(!) You have unread messages. View mail" + # Error messages errors: # No permission From 6b9892492cc356aca5e2a3b8cf462b6a183ded98 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Thu, 15 Feb 2024 19:51:54 +0200 Subject: [PATCH 06/14] add method to easily run async code --- .../cloudnode/smp/cloudnodemsg/CloudnodeMSG.java | 7 +++++++ .../java/pro/cloudnode/smp/cloudnodemsg/Mail.java | 14 ++++++++++++++ .../smp/cloudnodemsg/command/Command.java | 2 +- .../cloudnodemsg/listener/PlayerJoinListener.java | 2 +- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java index 410f6d3..d00d6ed 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java @@ -117,4 +117,11 @@ public void runDDL() { } getLogger().info("Database successfully initialised with DDL"); } + + /** + * Run code asynchronously + */ + public static void runAsync(final @NotNull Runnable runnable) { + getInstance().getServer().getScheduler().runTaskAsynchronously(getInstance(), runnable); + } } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/Mail.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/Mail.java index 901f8fc..296306f 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/Mail.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/Mail.java @@ -2,6 +2,7 @@ import org.bukkit.OfflinePlayer; import org.bukkit.Server; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.sql.PreparedStatement; @@ -102,4 +103,17 @@ public static int unread(final @NotNull OfflinePlayer player) { return 0; } } + + /** + * Notify online players for their unread mail + */ + public static void notifyUnread() { + CloudnodeMSG.runAsync(() -> { + for (final @NotNull Player player : CloudnodeMSG.getInstance().getServer().getOnlinePlayers()) { + if (!player.hasPermission(Permission.MAIL)) continue; + final int unread = Mail.unread(player); + if (unread > 0) player.sendMessage(CloudnodeMSG.getInstance().config().mailNotify(unread)); + } + }); + } } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/Command.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/Command.java index f5f4bb8..932d7c1 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/Command.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/Command.java @@ -18,7 +18,7 @@ public static boolean sendMessage(final @NotNull Audience recipient, final @NotN @Override public final boolean onCommand(final @NotNull CommandSender sender, final @NotNull org.bukkit.command.Command command, final @NotNull String label, @NotNull String @NotNull [] args) { - CloudnodeMSG.getInstance().getServer().getScheduler().runTaskAsynchronously(CloudnodeMSG.getInstance(), () -> { + CloudnodeMSG.runAsync(() -> { final boolean ignored = run(sender, label, args); }); return true; diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/listener/PlayerJoinListener.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/listener/PlayerJoinListener.java index 09b1581..8881e48 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/listener/PlayerJoinListener.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/listener/PlayerJoinListener.java @@ -12,7 +12,7 @@ public final class PlayerJoinListener implements Listener { @EventHandler public void onPlayerJoin(final @NotNull PlayerJoinEvent event) { - event.getPlayer().getServer().getScheduler().runTaskAsynchronously(CloudnodeMSG.getInstance(), () -> { + CloudnodeMSG.runAsync(() -> { if (!CloudnodeMSG.getInstance().config().mailNotifyOnLogin()) return; final @NotNull Player player = event.getPlayer(); if (!player.hasPermission(Permission.MAIL)) return; From 7a3001d58c75018c7f6b83db4e3dc48f9b7ac20e Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Thu, 15 Feb 2024 19:58:54 +0200 Subject: [PATCH 07/14] use minutes instead of seconds for interval --- .../java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java | 2 +- src/main/resources/config.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java index f18e33d..4844e85 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java @@ -264,7 +264,7 @@ public boolean mailNotifyOnLogin() { } /** - * Interval (in seconds) to notify players of unread mail. Set to 0 to disable. + * Interval (in minutes) to notify players of unread mail. Set to 0 to disable. */ public int mailNotifyInterval() { return config.getInt("mail.notify-interval"); diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 415fd25..22b04d7 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -102,8 +102,8 @@ mail: # Should players be notified for unread mail on login? notify-on-login: true - # Interval (in seconds) to notify players of unread mail. Set to 0 to disable. - notify-interval: 180 + # Interval (in minutes) to notify players of unread mail. Set to 0 to disable. + notify-interval: 3 # Unread mail notification message # Placeholders: From 81b44aa204acadf8c75cf85aca6983b9d2e1d030 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Thu, 15 Feb 2024 20:02:49 +0200 Subject: [PATCH 08/14] notify periodically for unread mail --- .../cloudnode/smp/cloudnodemsg/CloudnodeMSG.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java index d00d6ed..5432c07 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java @@ -5,6 +5,8 @@ import org.bukkit.entity.Player; import org.bukkit.metadata.MetadataValue; import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import pro.cloudnode.smp.cloudnodemsg.command.IgnoreCommand; @@ -50,11 +52,14 @@ public void onEnable() { getServer().getPluginManager().registerEvents(new AsyncChatListener(), this); getServer().getPluginManager().registerEvents(new PlayerJoinListener(), this); + + minuteLoop = minuteLoop(); } @Override public void onDisable() { - dbSource.close(); + if (dbSource != null) dbSource.close(); + if (minuteLoop != null) minuteLoop.cancel(); } public static boolean isVanished(final @NotNull Player player) { @@ -124,4 +129,11 @@ public void runDDL() { public static void runAsync(final @NotNull Runnable runnable) { getInstance().getServer().getScheduler().runTaskAsynchronously(getInstance(), runnable); } + + private @NotNull BukkitTask minuteLoop() { + return getServer().getScheduler().runTaskTimerAsynchronously(this, () -> { + Mail.notifyUnread(); + }, 0, 20 * 60); + } + private @Nullable BukkitTask minuteLoop; } From 2df68a77aac0eb0c3a4f1109632f808919656abf Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Fri, 16 Feb 2024 10:32:01 +0200 Subject: [PATCH 09/14] apply mail notify interval --- src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java index 5432c07..961017e 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java @@ -132,7 +132,7 @@ public static void runAsync(final @NotNull Runnable runnable) { private @NotNull BukkitTask minuteLoop() { return getServer().getScheduler().runTaskTimerAsynchronously(this, () -> { - Mail.notifyUnread(); + if ((System.currentTimeMillis() / 1000) % config().mailNotifyInterval() == 0) Mail.notifyUnread(); }, 0, 20 * 60); } private @Nullable BukkitTask minuteLoop; From f9c0a9864da611bccaf3e1b795167d140b6cae6f Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Fri, 16 Feb 2024 10:45:50 +0200 Subject: [PATCH 10/14] send mail command --- .../smp/cloudnodemsg/CloudnodeMSG.java | 3 +- .../cloudnode/smp/cloudnodemsg/Message.java | 6 +++ .../smp/cloudnodemsg/PluginConfig.java | 23 +++++++++ .../smp/cloudnodemsg/command/MailCommand.java | 50 +++++++++++++++++++ src/main/resources/config.yml | 9 ++++ src/main/resources/plugin.yml | 4 ++ 6 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java index 961017e..cebe369 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java @@ -5,11 +5,11 @@ import org.bukkit.entity.Player; import org.bukkit.metadata.MetadataValue; import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import pro.cloudnode.smp.cloudnodemsg.command.IgnoreCommand; +import pro.cloudnode.smp.cloudnodemsg.command.MailCommand; import pro.cloudnode.smp.cloudnodemsg.command.MainCommand; import pro.cloudnode.smp.cloudnodemsg.command.MessageCommand; import pro.cloudnode.smp.cloudnodemsg.command.ReplyCommand; @@ -49,6 +49,7 @@ public void onEnable() { Objects.requireNonNull(getCommand("ignore")).setExecutor(new IgnoreCommand()); Objects.requireNonNull(getCommand("unignore")).setExecutor(new UnIgnoreCommand()); Objects.requireNonNull(getCommand("togglemsg")).setExecutor(new ToggleMessageCommand()); + Objects.requireNonNull(getCommand("mail")).setExecutor(new MailCommand()); getServer().getPluginManager().registerEvents(new AsyncChatListener(), this); getServer().getPluginManager().registerEvents(new PlayerJoinListener(), this); diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/Message.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/Message.java index ea5b3f9..93d548a 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/Message.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/Message.java @@ -72,6 +72,12 @@ public void send() throws InvalidPlayerError { return executor instanceof final @NotNull Player player ? player : console; } + public static @NotNull String name(final @NotNull OfflinePlayer player) { + if (player.getUniqueId().equals(console.getUniqueId())) return CloudnodeMSG.getInstance().config().consoleName(); + final @NotNull Optional<@NotNull String> name = Optional.ofNullable(player.getName()); + return name.orElse("Unknown Player"); + } + public static void sendMessage(final @NotNull OfflinePlayer recipient, final @NotNull Component message) { if (recipient.getUniqueId() == console.getUniqueId()) CloudnodeMSG.getInstance().getServer().getConsoleSender().sendMessage(message); diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java index 4844e85..a41138e 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java @@ -2,6 +2,7 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Formatter; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import org.bukkit.configuration.file.FileConfiguration; import org.jetbrains.annotations.NotNull; @@ -283,6 +284,28 @@ public int mailNotifyInterval() { ); } + /** + * Successfully sent mail + *

Placeholders:

+ *
    + *
  • {@code } - the username of the sender
  • + *
  • {@code } - the username of the recipient
  • + *
  • {@code } - the message
  • + *
  • {@code } - whether the mail was read/opened by the recipient (see: Insert a choice)
  • + *
  • {@code } - whether the recipient has starred the mail (see: Insert a choice)
  • + *
+ * + * @param mail the mail + */ + public @NotNull Component mailSent(final @NotNull Mail mail) { + return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("mail.sent")) + .replace("", Message.name(mail.sender)) + .replace("", Message.name(mail.recipient)), + Formatter.booleanChoice("seen", mail.seen), + Formatter.booleanChoice("starred", mail.starred) + ).replaceText(configurer -> configurer.matchLiteral("").replacement(Component.text(mail.message))); + } + /** * No permission */ diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java new file mode 100644 index 0000000..bf1cc21 --- /dev/null +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java @@ -0,0 +1,50 @@ +package pro.cloudnode.smp.cloudnodemsg.command; + +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG; +import pro.cloudnode.smp.cloudnodemsg.Mail; +import pro.cloudnode.smp.cloudnodemsg.Message; +import pro.cloudnode.smp.cloudnodemsg.Permission; + +import java.util.Arrays; +import java.util.List; + +public final class MailCommand extends Command { + + @Override + public boolean run(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args) { + if (!sender.hasPermission(Permission.MAIL)) return sendMessage(sender, CloudnodeMSG.getInstance().config().noPermission()); + if (args.length == 0) return help(sender); + final @NotNull String @NotNull [] subCommandArgs = Arrays.copyOfRange(args, 1, args.length); + final @NotNull String subCommandLabel = label + " " + args[0]; + return switch (args[0]) { + case "send", "new", "to" -> send(sender, subCommandLabel, subCommandArgs); + default -> help(sender); + }; + } + + public static boolean help(final @NotNull CommandSender sender) { + // TODO + return false; + } + + public static boolean send(final @NotNull CommandSender sender, final @NotNull String label, final @NotNull String[] args) { + if (args.length == 0) return sendMessage(sender, CloudnodeMSG.getInstance().config().usage(label, " ")); + if (args.length == 1) return sendMessage(sender, CloudnodeMSG.getInstance().config().usage(label, args[0] + " ")); + final @NotNull String message = String.join(" ", Arrays.copyOfRange(args, 1, args.length)); + final @NotNull OfflinePlayer recipient = CloudnodeMSG.getInstance().getServer().getOfflinePlayer(args[0]); + if (!recipient.hasPlayedBefore()) return sendMessage(sender, CloudnodeMSG.getInstance().config().playerNotFound(args[0])); + final @NotNull Mail mail = new Mail(Message.offlinePlayer(sender), recipient, message); + mail.insert(); + // TODO: notify recipient (if online) + return sendMessage(sender, CloudnodeMSG.getInstance().config().mailSent(mail)); + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args) { + return null; + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 22b04d7..571f73d 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -110,6 +110,15 @@ mail: # - the number of unread mail messages notify: "(!) You have unread messages. View mail" + # Successfully sent mail + # Placeholders: + # - the username of the sender + # - the username of the recipient + # - the message + # - whether the mail was read/opened by the recipient (see: https://docs.advntr.dev/minimessage/dynamic-replacements.html#insert-a-choice) + # - whether the recipient has starred the mail (see: https://docs.advntr.dev/minimessage/dynamic-replacements.html#insert-a-choice) + sent: "(!) Successfully sent mail to ." + # Error messages errors: # No permission diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index dc927a3..1c16383 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -27,3 +27,7 @@ commands: description: Toggles private messages from a player usage: / aliases: [ "toggledms", "togglepms" ] + mail: + description: Send and receive offline messages + usage: / + aliases: [ "post" ] From ee172352f0b1d3f8f84d07a686bb95dd91481459 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Fri, 16 Feb 2024 11:15:58 +0200 Subject: [PATCH 11/14] remove some redundancies --- .../cloudnode/smp/cloudnodemsg/Message.java | 31 +---- .../smp/cloudnodemsg/PluginConfig.java | 131 +++++++++--------- .../cloudnodemsg/command/IgnoreCommand.java | 11 +- .../smp/cloudnodemsg/command/MailCommand.java | 2 +- .../cloudnodemsg/command/MessageCommand.java | 21 +-- .../cloudnodemsg/command/ReplyCommand.java | 4 +- .../command/ToggleMessageCommand.java | 9 +- .../cloudnodemsg/command/UnIgnoreCommand.java | 2 +- .../cloudnodemsg/error/CannotIgnoreError.java | 3 +- .../cloudnodemsg/error/NeverJoinedError.java | 3 +- .../cloudnodemsg/error/NotIgnoredError.java | 3 +- .../error/PlayerHasIncomingDisabledError.java | 3 +- .../error/PlayerNotFoundError.java | 3 +- .../cloudnodemsg/error/ReplyOfflineError.java | 3 +- .../listener/AsyncChatListener.java | 2 +- src/main/resources/config.yml | 3 + 16 files changed, 114 insertions(+), 120 deletions(-) diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/Message.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/Message.java index 93d548a..80ccdd3 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/Message.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/Message.java @@ -31,24 +31,11 @@ public Message(@NotNull OfflinePlayer sender, @NotNull OfflinePlayer recipient, this(sender, recipient, Component.text(message)); } - private @NotNull String playerOrServerUsername(final @NotNull OfflinePlayer player) throws InvalidPlayerError { - if (player.getUniqueId().equals(console.getUniqueId())) - return CloudnodeMSG.getInstance().config().consoleName(); - else { - final @NotNull Optional<@NotNull String> name = Optional.ofNullable(player.getName()); - if (name.isEmpty()) throw new InvalidPlayerError(); - else return name.get(); - } - } - public void send() throws InvalidPlayerError { - final @NotNull String senderUsername = playerOrServerUsername(this.sender); - final @NotNull String recipientUsername = playerOrServerUsername(this.recipient); - final @NotNull Optional<@NotNull Player> senderPlayer = Optional.ofNullable(this.sender.getPlayer()); final @NotNull Optional<@NotNull Player> recipientPlayer = Optional.ofNullable(this.recipient.getPlayer()); - sendMessage(sender, CloudnodeMSG.getInstance().config().outgoing(senderUsername, recipientUsername, message)); + sendMessage(sender, CloudnodeMSG.getInstance().config().outgoing(sender, recipient, message)); if (senderPlayer.isPresent() && !Message.hasChannel(senderPlayer.get(), recipient)) setReplyTo(sender, recipient); @@ -60,7 +47,7 @@ public void send() throws InvalidPlayerError { (senderPlayer.isPresent() && !senderPlayer.get().hasPermission(Permission.IGNORE_BYPASS)) ) return; sendMessage(recipient, CloudnodeMSG.getInstance().config() - .incoming(senderUsername, recipientUsername, message)); + .incoming(sender, recipient, message)); if (recipientPlayer.isPresent() && !Message.hasChannel(recipientPlayer.get(), sender)) setReplyTo(recipient, sender); } @@ -75,7 +62,7 @@ public void send() throws InvalidPlayerError { public static @NotNull String name(final @NotNull OfflinePlayer player) { if (player.getUniqueId().equals(console.getUniqueId())) return CloudnodeMSG.getInstance().config().consoleName(); final @NotNull Optional<@NotNull String> name = Optional.ofNullable(player.getName()); - return name.orElse("Unknown Player"); + return name.orElse(CloudnodeMSG.getInstance().config().unknownName()); } public static void sendMessage(final @NotNull OfflinePlayer recipient, final @NotNull Component message) { @@ -88,18 +75,16 @@ public static void sendMessage(final @NotNull OfflinePlayer recipient, final @No * Send social spy to online players with permission */ public static void sendSpyMessage(final @NotNull OfflinePlayer sender, final @NotNull OfflinePlayer recipient, final @NotNull Component message) { - final @NotNull String senderName = sender.getUniqueId().equals(console.getUniqueId()) ? CloudnodeMSG.getInstance().config().consoleName() : Optional.ofNullable(sender.getName()).orElse("Unknown Player"); - final @NotNull String recipientName = recipient.getUniqueId().equals(console.getUniqueId()) ? CloudnodeMSG.getInstance().config().consoleName() : Optional.ofNullable(recipient.getName()).orElse("Unknown Player"); for (final @NotNull Player player : CloudnodeMSG.getInstance().getServer().getOnlinePlayers()) { if ( !player.hasPermission(Permission.SPY) || player.getUniqueId().equals(sender.getUniqueId()) || player.getUniqueId().equals(recipient.getUniqueId()) ) continue; - sendMessage(player, CloudnodeMSG.getInstance().config().spy(senderName, recipientName, message)); + sendMessage(player, CloudnodeMSG.getInstance().config().spy(sender, recipient, message)); } if (!sender.getUniqueId().equals(console.getUniqueId()) && !recipient.getUniqueId().equals(console.getUniqueId())) - sendMessage(console, CloudnodeMSG.getInstance().config().spy(senderName, recipientName, message)); + sendMessage(console, CloudnodeMSG.getInstance().config().spy(sender, recipient, message)); } private static @Nullable UUID consoleReply; @@ -123,12 +108,6 @@ else if (sender.isOnline()) return Optional.empty(); } - public static void removeReplyTo(final @NotNull OfflinePlayer player) { - if (player.getUniqueId().equals(console.getUniqueId())) consoleReply = null; - else if (player.isOnline()) - Objects.requireNonNull(player.getPlayer()).getPersistentDataContainer().remove(REPLY_TO); - } - public static final @NotNull NamespacedKey IGNORED_PLAYERS = new NamespacedKey(CloudnodeMSG.getInstance(), "ignored"); public static final @NotNull NamespacedKey CHANNEL_RECIPIENT = new NamespacedKey(CloudnodeMSG.getInstance(), "channel-recipient"); diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java index a41138e..ac6f682 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java @@ -4,10 +4,10 @@ import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.Formatter; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import org.bukkit.OfflinePlayer; import org.bukkit.configuration.file.FileConfiguration; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -54,14 +54,14 @@ public PluginConfig(final @NotNull FileConfiguration config) { *
  • {@code } - the message text
  • * * - * @param sender The username of the message sender - * @param recipient The username of the message recipient + * @param sender The message sender + * @param recipient The message recipient * @param message The message text */ - public @NotNull Component incoming(final @NotNull String sender, final @NotNull String recipient, final @NotNull Component message) { + public @NotNull Component incoming(final @NotNull OfflinePlayer sender, final @NotNull OfflinePlayer recipient, final @NotNull Component message) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("incoming")) - .replace("", sender) - .replace("", recipient), + .replace("", Message.name(sender)) + .replace("", Message.name(recipient)), Placeholder.component("message", message) ); } @@ -70,19 +70,19 @@ public PluginConfig(final @NotNull FileConfiguration config) { * Outgoing message format (sender's point of view) *

    Placeholders:

    *
      - *
    • {@code } - the username of the message sender
    • + *
    • {@code } - the message sender
    • *
    • {@code } - the username of the message recipient
    • *
    • {@code } - the message text
    • *
    * - * @param sender The username of the message sender - * @param recipient The username of the message recipient + * @param sender The message sender + * @param recipient The message recipient * @param message The message text */ - public @NotNull Component outgoing(final @NotNull String sender, final @NotNull String recipient, final @NotNull Component message) { + public @NotNull Component outgoing(final @NotNull OfflinePlayer sender, final @NotNull OfflinePlayer recipient, final @NotNull Component message) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("outgoing")) - .replace("", sender) - .replace("", recipient), + .replace("", Message.name(sender)) + .replace("", Message.name(recipient)), Placeholder.component("message", message) ); } @@ -96,14 +96,14 @@ public PluginConfig(final @NotNull FileConfiguration config) { *
  • {@code } - the message text
  • * * - * @param sender The username of the message sender - * @param recipient The username of the message recipient + * @param sender The message sender + * @param recipient The message recipient * @param message The message text */ - public @NotNull Component spy(final @NotNull String sender, final @NotNull String recipient, final @NotNull Component message) { + public @NotNull Component spy(final @NotNull OfflinePlayer sender, final @NotNull OfflinePlayer recipient, final @NotNull Component message) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("spy")) - .replace("", sender) - .replace("", recipient), + .replace("", Message.name(sender)) + .replace("", Message.name(recipient)), Placeholder.component("message", message) ); } @@ -113,11 +113,11 @@ public PluginConfig(final @NotNull FileConfiguration config) { *

    Placeholders:

    *
    • {@code } - the username of the player
    * - * @param player The username of the player + * @param player The player */ - public @NotNull Component ignored(final @NotNull String player) { + public @NotNull Component ignored(final @NotNull OfflinePlayer player) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("ignored")), - Placeholder.unparsed("player", player) + Placeholder.unparsed("player", Message.name(player)) ); } @@ -126,11 +126,11 @@ public PluginConfig(final @NotNull FileConfiguration config) { *

    Placeholders:

    *
    • {@code } - the username of the player
    * - * @param player The username of the player + * @param player The player */ - public @NotNull Component unignored(final @NotNull String player) { + public @NotNull Component unignored(final @NotNull OfflinePlayer player) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("unignored")), - Placeholder.unparsed("player", player) + Placeholder.unparsed("player", Message.name(player)) ); } @@ -143,14 +143,14 @@ public PluginConfig(final @NotNull FileConfiguration config) { *
  • {@code } - the command used, e.g. `msg`, `dm`, etc.
  • * * - * @param sender The username of the message sender - * @param recipient The username of the message recipient + * @param sender The message sender + * @param recipient The message recipient * @param command The command used, e.g. `msg`, `dm`, etc. */ - public @NotNull Component channelCreated(final @NotNull String sender, final @NotNull String recipient, final @NotNull String command) { + public @NotNull Component channelCreated(final @NotNull OfflinePlayer sender, final @NotNull OfflinePlayer recipient, final @NotNull String command) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("channel.created")) - .replace("", sender) - .replace("", recipient) + .replace("", Message.name(sender)) + .replace("", Message.name(recipient)) .replace("", command)); } @@ -163,14 +163,14 @@ public PluginConfig(final @NotNull FileConfiguration config) { *
  • {@code } - the command used, e.g. `msg`, `dm`, etc.
  • * * - * @param sender The username of the message sender - * @param recipient The username of the message recipient + * @param sender The message sender + * @param recipient The message recipient * @param command The command used, e.g. `msg`, `dm`, etc. */ - public @NotNull Component channelClosed(final @NotNull String sender, final @NotNull String recipient, final @NotNull String command) { + public @NotNull Component channelClosed(final @NotNull OfflinePlayer sender, final @NotNull OfflinePlayer recipient, final @NotNull String command) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("channel.closed")) - .replace("", sender) - .replace("", recipient) + .replace("", Message.name(sender)) + .replace("", Message.name(recipient)) .replace("", command)); } @@ -182,13 +182,13 @@ public PluginConfig(final @NotNull FileConfiguration config) { *
  • {@code } - the username of the message recipient
  • * * - * @param sender The username of the message sender - * @param recipient The username of the message recipient + * @param sender The message sender + * @param recipient The message recipient */ - public @NotNull Component channelOffline(final @NotNull String sender, final @NotNull String recipient) { + public @NotNull Component channelOffline(final @NotNull OfflinePlayer sender, final @NotNull OfflinePlayer recipient) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("channel.offline")) - .replace("", sender) - .replace("", recipient)); + .replace("", Message.name(sender)) + .replace("", Message.name(recipient))); } /** @@ -223,6 +223,13 @@ public PluginConfig(final @NotNull FileConfiguration config) { return Objects.requireNonNull(config.getString("console-name")); } + /** + * Name for player when name not found (usually very unlikely to happen) + */ + public @NotNull String unknownName() { + return Objects.requireNonNull(config.getString("unknown-name")); + } + public @NotNull Component toggleDisable() { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("toggle.disable.message"))); } @@ -232,11 +239,11 @@ public PluginConfig(final @NotNull FileConfiguration config) { *

    Placeholders:

    *
    • {@code } - the player's username
    * - * @param player the player's username + * @param player the player */ - public @NotNull Component toggleDisableOther(final @NotNull String player) { + public @NotNull Component toggleDisableOther(final @NotNull OfflinePlayer player) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("toggle.disable.other")), - Placeholder.unparsed("player", player) + Placeholder.unparsed("player", Message.name(player)) ); } @@ -249,11 +256,11 @@ public PluginConfig(final @NotNull FileConfiguration config) { *

    Placeholders:

    *
    • {@code } - the player's username
    * - * @param player the player's username + * @param player the player */ - public @NotNull Component toggleEnableOther(final @NotNull String player) { + public @NotNull Component toggleEnableOther(final @NotNull OfflinePlayer player) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("toggle.enable.other")), - Placeholder.unparsed("player", player) + Placeholder.unparsed("player", Message.name(player)) ); } @@ -325,11 +332,11 @@ public int mailNotifyInterval() { *

    Placeholders:

    *
    • {@code } - the player's username
    * - * @param player The player's username + * @param player The player */ - public @NotNull Component playerNotFound(final @NotNull String player) { + public @NotNull Component playerNotFound(final @NotNull OfflinePlayer player) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("errors.player-not-found")), - Placeholder.unparsed("player", player) + Placeholder.unparsed("player", Message.name(player)) ); } @@ -346,11 +353,11 @@ public int mailNotifyInterval() { *

    Placeholders:

    *
    • {@code } - the player's username
    * - * @param player The player's username + * @param player The player */ - public @NotNull Component replyOffline(final @NotNull String player) { + public @NotNull Component replyOffline(final @NotNull OfflinePlayer player) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("errors.reply-offline")), - Placeholder.unparsed("player", player) + Placeholder.unparsed("player", Message.name(player)) ); } @@ -366,11 +373,11 @@ public int mailNotifyInterval() { *

    Placeholders:

    *
    • {@code } - the player's username
    * - * @param player The player's username + * @param player The player */ - public @NotNull Component notIgnored(final @NotNull String player) { + public @NotNull Component notIgnored(final @NotNull OfflinePlayer player) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("errors.not-ignored")), - Placeholder.unparsed("player", player) + Placeholder.unparsed("player", Message.name(player)) ); } @@ -379,11 +386,11 @@ public int mailNotifyInterval() { *

    Placeholders:

    *
    • {@code } - the player's username
    * - * @param player The player's username + * @param player The player */ - public @NotNull Component cannotIgnore(final @NotNull String player) { + public @NotNull Component cannotIgnore(final @NotNull OfflinePlayer player) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("errors.cannot-ignore")), - Placeholder.unparsed("player", player) + Placeholder.unparsed("player", Message.name(player)) ); } @@ -392,11 +399,11 @@ public int mailNotifyInterval() { *

    Placeholders:

    *
    • {@code } - the player's username
    * - * @param player The player's username + * @param player The player */ - public @NotNull Component neverJoined(final @NotNull String player) { + public @NotNull Component neverJoined(final @NotNull OfflinePlayer player) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("errors.never-joined")), - Placeholder.unparsed("player", player) + Placeholder.unparsed("player", Message.name(player)) ); } @@ -405,11 +412,11 @@ public int mailNotifyInterval() { *

    Placeholders:

    *
    • {@code } - the player's username
    * - * @param player The player's username + * @param player The player */ - public @NotNull Component incomingDisabled(final @NotNull String player) { + public @NotNull Component incomingDisabled(final @NotNull OfflinePlayer player) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("errors.incoming-disabled")), - Placeholder.unparsed("player", player) + Placeholder.unparsed("player", Message.name(player)) ); } } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/IgnoreCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/IgnoreCommand.java index c77cc98..2996bfe 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/IgnoreCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/IgnoreCommand.java @@ -6,17 +6,16 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG; +import pro.cloudnode.smp.cloudnodemsg.Message; import pro.cloudnode.smp.cloudnodemsg.Permission; import pro.cloudnode.smp.cloudnodemsg.error.CannotIgnoreError; import pro.cloudnode.smp.cloudnodemsg.error.NeverJoinedError; import pro.cloudnode.smp.cloudnodemsg.error.NoPermissionError; import pro.cloudnode.smp.cloudnodemsg.error.NotPlayerError; -import pro.cloudnode.smp.cloudnodemsg.Message; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import java.util.Optional; public final class IgnoreCommand extends Command { public static final @NotNull String usage = ""; @@ -32,15 +31,15 @@ public boolean run(final @NotNull CommandSender sender, final @NotNull String la } public static boolean ignore(final @NotNull Player player, final @NotNull OfflinePlayer target) { - if (target.isOnline() && Objects.requireNonNull(target.getPlayer()).hasPermission(Permission.IGNORE_BYPASS)) return new CannotIgnoreError(Optional.ofNullable(target.getName()).orElse("Unknown Player")).send(player); - if (!target.isOnline() && !target.hasPlayedBefore()) return new NeverJoinedError(Optional.ofNullable(target.getName()).orElse("Unknown Player")).send(player); + if (target.isOnline() && Objects.requireNonNull(target.getPlayer()).hasPermission(Permission.IGNORE_BYPASS)) return new CannotIgnoreError(target).send(player); + if (!target.isOnline() && !target.hasPlayedBefore()) return new NeverJoinedError(target).send(player); Message.ignore(player, target); - return sendMessage(player, CloudnodeMSG.getInstance().config().ignored(Optional.ofNullable(target.getName()).orElse("Unknown Player"))); + return sendMessage(player, CloudnodeMSG.getInstance().config().ignored(target)); } public static boolean unignore(final @NotNull Player player, final @NotNull OfflinePlayer target) { Message.unignore(player, target); - return sendMessage(player, CloudnodeMSG.getInstance().config().unignored(Optional.ofNullable(target.getName()).orElse("Unknown Player"))); + return sendMessage(player, CloudnodeMSG.getInstance().config().unignored(target)); } @Override diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java index bf1cc21..d46d564 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java @@ -36,7 +36,7 @@ public static boolean send(final @NotNull CommandSender sender, final @NotNull S if (args.length == 1) return sendMessage(sender, CloudnodeMSG.getInstance().config().usage(label, args[0] + " ")); final @NotNull String message = String.join(" ", Arrays.copyOfRange(args, 1, args.length)); final @NotNull OfflinePlayer recipient = CloudnodeMSG.getInstance().getServer().getOfflinePlayer(args[0]); - if (!recipient.hasPlayedBefore()) return sendMessage(sender, CloudnodeMSG.getInstance().config().playerNotFound(args[0])); + if (!recipient.hasPlayedBefore()) return sendMessage(sender, CloudnodeMSG.getInstance().config().playerNotFound(recipient)); final @NotNull Mail mail = new Mail(Message.offlinePlayer(sender), recipient, message); mail.insert(); // TODO: notify recipient (if online) diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MessageCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MessageCommand.java index 7977c90..68a9136 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MessageCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MessageCommand.java @@ -1,5 +1,6 @@ package pro.cloudnode.smp.cloudnodemsg.command; +import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -31,25 +32,25 @@ public boolean run(final @NotNull CommandSender sender, final @NotNull String la if (args.length == 1 && !(sender instanceof Player)) return sendMessage(sender, CloudnodeMSG.getInstance().config() .usage(label, usageConsole.replace("", args[0]))); - final @NotNull Optional<@NotNull Player> recipient = Optional.ofNullable(CloudnodeMSG.getInstance().getServer() - .getPlayer(args[0])); - if (recipient.isEmpty() || (CloudnodeMSG.isVanished(recipient.get()) && !sender.hasPermission(Permission.SEND_VANISHED))) return new PlayerNotFoundError(args[0]).send(sender); - if (sender instanceof final @NotNull Player player && recipient.get().getUniqueId().equals(player.getUniqueId())) + final @NotNull OfflinePlayer recipient = CloudnodeMSG.getInstance().getServer().getOfflinePlayer(args[0]); + final @NotNull Optional<@NotNull Player> onlineRecipient = Optional.ofNullable(recipient.getPlayer()); + if (onlineRecipient.isEmpty() || (CloudnodeMSG.isVanished(onlineRecipient.get()) && !sender.hasPermission(Permission.SEND_VANISHED))) return new PlayerNotFoundError(recipient).send(sender); + if (sender instanceof final @NotNull Player player && recipient.getUniqueId().equals(player.getUniqueId())) return new MessageYourselfError().send(sender); - if (!Message.isIncomingEnabled(recipient.get()) && !sender.hasPermission(Permission.TOGGLE_BYPASS)) return new PlayerHasIncomingDisabledError(recipient.get().getName()).send(sender); + if (!Message.isIncomingEnabled(onlineRecipient.get()) && !sender.hasPermission(Permission.TOGGLE_BYPASS)) return new PlayerHasIncomingDisabledError(recipient).send(sender); if (args.length == 1) { final @NotNull Player player = (Player) sender; - if (Message.getChannel(player).map(r -> r.getUniqueId().equals(recipient.get().getUniqueId())).orElse(false)) { + if (Message.getChannel(player).map(r -> r.getUniqueId().equals(recipient.getUniqueId())).orElse(false)) { Message.exitChannel(player); - return sendMessage(player, CloudnodeMSG.getInstance().config().channelClosed(player.getName(), recipient.get().getName(), label)); + return sendMessage(player, CloudnodeMSG.getInstance().config().channelClosed(player, recipient, label)); } - Message.createChannel(player, recipient.get()); - return sendMessage(player, CloudnodeMSG.getInstance().config().channelCreated(player.getName(), recipient.get().getName(), label)); + Message.createChannel(player, recipient); + return sendMessage(player, CloudnodeMSG.getInstance().config().channelCreated(player, recipient, label)); } try { - new Message(Message.offlinePlayer(sender), recipient.get(), String.join(" ", Arrays.copyOfRange(args, 1, args.length))).send(); + new Message(Message.offlinePlayer(sender), recipient, String.join(" ", Arrays.copyOfRange(args, 1, args.length))).send(); return true; } catch (final @NotNull InvalidPlayerError e) { diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ReplyCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ReplyCommand.java index 8d61c2e..9ebdb30 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ReplyCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ReplyCommand.java @@ -27,7 +27,7 @@ public boolean run(final @NotNull CommandSender sender, final @NotNull String la final @NotNull Optional<@NotNull OfflinePlayer> recipient = Message.getReplyTo(Message.offlinePlayer(sender)); if (recipient.isEmpty()) return new NobodyReplyError().send(sender); - if (!recipient.get().getUniqueId().equals(Message.console.getUniqueId()) && !Message.isIncomingEnabled(Objects.requireNonNull(recipient.get().getPlayer())) && !sender.hasPermission(Permission.TOGGLE_BYPASS)) return new PlayerHasIncomingDisabledError(Objects.requireNonNull(recipient.get().getName())).send(sender); + if (!recipient.get().getUniqueId().equals(Message.console.getUniqueId()) && !Message.isIncomingEnabled(Objects.requireNonNull(recipient.get().getPlayer())) && !sender.hasPermission(Permission.TOGGLE_BYPASS)) return new PlayerHasIncomingDisabledError(recipient.get()).send(sender); if ( !recipient.get().getUniqueId().equals(Message.console.getUniqueId()) && ( @@ -35,7 +35,7 @@ public boolean run(final @NotNull CommandSender sender, final @NotNull String la || (CloudnodeMSG.isVanished(Objects.requireNonNull(recipient.get().getPlayer())) && !sender.hasPermission(Permission.SEND_VANISHED)) ) ) - return new ReplyOfflineError(Optional.ofNullable(recipient.get().getName()).orElse("Unknown Player")).send(sender); + return new ReplyOfflineError(recipient.get()).send(sender); try { new Message(Message.offlinePlayer(sender), recipient.get(), String.join(" ", args)).send(); diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ToggleMessageCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ToggleMessageCommand.java index 6f19d41..b6c02eb 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ToggleMessageCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ToggleMessageCommand.java @@ -6,15 +6,14 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG; +import pro.cloudnode.smp.cloudnodemsg.Message; import pro.cloudnode.smp.cloudnodemsg.Permission; import pro.cloudnode.smp.cloudnodemsg.error.NeverJoinedError; import pro.cloudnode.smp.cloudnodemsg.error.NoPermissionError; import pro.cloudnode.smp.cloudnodemsg.error.NotPlayerError; -import pro.cloudnode.smp.cloudnodemsg.Message; import java.util.ArrayList; import java.util.List; -import java.util.Optional; public final class ToggleMessageCommand extends Command { @Override @@ -25,15 +24,15 @@ public boolean run(@NotNull CommandSender sender, @NotNull String label, @NotNul final @NotNull OfflinePlayer recipient = CloudnodeMSG.getInstance().getServer().getOfflinePlayer(args[0]); if (recipient.getPlayer() == null) - return new NeverJoinedError(Optional.ofNullable(recipient.getName()).orElse("Unknown Player")).send(sender); + return new NeverJoinedError(recipient).send(sender); if (Message.isIncomingEnabled(recipient.getPlayer())) { Message.incomingDisable(recipient.getPlayer()); - return sendMessage(sender, CloudnodeMSG.getInstance().config().toggleDisableOther(Optional.of(recipient.getPlayer().getName()).orElse("Unknown Player"))); + return sendMessage(sender, CloudnodeMSG.getInstance().config().toggleDisableOther(recipient)); } Message.incomingEnable(recipient.getPlayer()); - return sendMessage(sender, CloudnodeMSG.getInstance().config().toggleEnableOther(Optional.of(recipient.getPlayer().getName()).orElse("Unknown Player"))); + return sendMessage(sender, CloudnodeMSG.getInstance().config().toggleEnableOther(recipient)); } if (!(sender instanceof final @NotNull Player player)) return new NotPlayerError().send(sender); diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/UnIgnoreCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/UnIgnoreCommand.java index d165c38..f29e5e9 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/UnIgnoreCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/UnIgnoreCommand.java @@ -29,7 +29,7 @@ public boolean run(final @NotNull CommandSender sender, final @NotNull String la if (args.length == 0) return sendMessage(sender, CloudnodeMSG.getInstance().config().usage(label, usage)); final @NotNull OfflinePlayer target = CloudnodeMSG.getInstance().getServer().getOfflinePlayer(args[0]); if (Message.isIgnored(player, target)) return IgnoreCommand.unignore(player, target); - return new NotIgnoredError(args[0]).send(sender); + return new NotIgnoredError(target).send(sender); } @Override diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/CannotIgnoreError.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/CannotIgnoreError.java index 7c8ee01..50ee0e0 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/CannotIgnoreError.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/CannotIgnoreError.java @@ -1,5 +1,6 @@ package pro.cloudnode.smp.cloudnodemsg.error; +import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG; @@ -7,7 +8,7 @@ * Player cannot be ignored */ public final class CannotIgnoreError extends Error { - public CannotIgnoreError(final @NotNull String player) { + public CannotIgnoreError(final @NotNull OfflinePlayer player) { super(CloudnodeMSG.getInstance().config().cannotIgnore(player)); } } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/NeverJoinedError.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/NeverJoinedError.java index e1e1780..5cc9753 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/NeverJoinedError.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/NeverJoinedError.java @@ -1,5 +1,6 @@ package pro.cloudnode.smp.cloudnodemsg.error; +import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG; @@ -12,7 +13,7 @@ public final class NeverJoinedError extends Error { * * @param player the player's username */ - public NeverJoinedError(final @NotNull String player) { + public NeverJoinedError(final @NotNull OfflinePlayer player) { super(CloudnodeMSG.getInstance().config().neverJoined(player)); } } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/NotIgnoredError.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/NotIgnoredError.java index 1295628..c92e181 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/NotIgnoredError.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/NotIgnoredError.java @@ -1,5 +1,6 @@ package pro.cloudnode.smp.cloudnodemsg.error; +import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG; @@ -12,7 +13,7 @@ public final class NotIgnoredError extends Error { * * @param player the player's username */ - public NotIgnoredError(final @NotNull String player) { + public NotIgnoredError(final @NotNull OfflinePlayer player) { super(CloudnodeMSG.getInstance().config().notIgnored(player)); } } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/PlayerHasIncomingDisabledError.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/PlayerHasIncomingDisabledError.java index 980dd55..032ef3f 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/PlayerHasIncomingDisabledError.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/PlayerHasIncomingDisabledError.java @@ -1,10 +1,11 @@ package pro.cloudnode.smp.cloudnodemsg.error; +import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG; public class PlayerHasIncomingDisabledError extends Error { - public PlayerHasIncomingDisabledError(final @NotNull String player) { + public PlayerHasIncomingDisabledError(final @NotNull OfflinePlayer player) { super(CloudnodeMSG.getInstance().config().incomingDisabled(player)); } } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/PlayerNotFoundError.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/PlayerNotFoundError.java index 63c832b..7699a56 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/PlayerNotFoundError.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/PlayerNotFoundError.java @@ -1,5 +1,6 @@ package pro.cloudnode.smp.cloudnodemsg.error; +import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG; @@ -12,7 +13,7 @@ public final class PlayerNotFoundError extends Error { * * @param player the player's username */ - public PlayerNotFoundError(final @NotNull String player) { + public PlayerNotFoundError(final @NotNull OfflinePlayer player) { super(CloudnodeMSG.getInstance().config().playerNotFound(player)); } } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/ReplyOfflineError.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/ReplyOfflineError.java index 3122050..6d29c90 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/ReplyOfflineError.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/ReplyOfflineError.java @@ -1,5 +1,6 @@ package pro.cloudnode.smp.cloudnodemsg.error; +import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG; @@ -12,7 +13,7 @@ public final class ReplyOfflineError extends Error { * * @param player The player's username */ - public ReplyOfflineError(final @NotNull String player) { + public ReplyOfflineError(final @NotNull OfflinePlayer player) { super(CloudnodeMSG.getInstance().config().replyOffline(player)); } } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/listener/AsyncChatListener.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/listener/AsyncChatListener.java index a5890af..30d8ba2 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/listener/AsyncChatListener.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/listener/AsyncChatListener.java @@ -46,7 +46,7 @@ public void channels(final @NotNull AsyncChatEvent event) { final @NotNull Optional<@NotNull Player> recipient = channelRecipient.map(p -> p.isOnline() ? p.getPlayer() : null); if (recipient.isEmpty()) { Message.exitChannel(sender); - sender.sendMessage(CloudnodeMSG.getInstance().config().channelOffline(sender.getName(), Optional.ofNullable(channelRecipient.get().getName()).orElse("Unknown Player"))); + sender.sendMessage(CloudnodeMSG.getInstance().config().channelOffline(sender, channelRecipient.get())); return; } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 571f73d..062103f 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -75,6 +75,9 @@ channel: # Name for console/server that should appear as or in messages console-name: "Server" +# Name for player when name not found (usually very unlikely to happen) +unknown-name: "Unknown Player" + # Command usage format # Placeholders: # - the command name From 40b8f3e9a94be27f555063b596d76574121ace4e Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Fri, 16 Feb 2024 11:22:55 +0200 Subject: [PATCH 12/14] the reform faction has besieged this plugin --- .../cloudnode/smp/cloudnodemsg/command/Command.java | 11 ++++++++++- .../smp/cloudnodemsg/command/IgnoreCommand.java | 2 +- .../smp/cloudnodemsg/command/MailCommand.java | 4 ++-- .../smp/cloudnodemsg/command/MainCommand.java | 2 +- .../smp/cloudnodemsg/command/MessageCommand.java | 2 +- .../smp/cloudnodemsg/command/ReplyCommand.java | 2 +- .../cloudnodemsg/command/ToggleMessageCommand.java | 4 ++-- .../smp/cloudnodemsg/command/UnIgnoreCommand.java | 2 +- 8 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/Command.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/Command.java index 932d7c1..d9c7ca4 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/Command.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/Command.java @@ -6,15 +6,19 @@ import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG; +import java.util.List; + public abstract class Command implements TabCompleter, CommandExecutor { public static boolean sendMessage(final @NotNull Audience recipient, final @NotNull Component message) { recipient.sendMessage(message); return true; } - public abstract boolean run(final @NotNull CommandSender sender, final @NotNull String label, final @NotNull String[] args); + public abstract boolean run(final @NotNull CommandSender sender, final @NotNull String label, final @NotNull String @NotNull [] args); + public abstract @Nullable List<@NotNull String> tab(final @NotNull CommandSender sender, final @NotNull String label, final @NotNull String @NotNull [] args); @Override public final boolean onCommand(final @NotNull CommandSender sender, final @NotNull org.bukkit.command.Command command, final @NotNull String label, @NotNull String @NotNull [] args) { @@ -23,4 +27,9 @@ public final boolean onCommand(final @NotNull CommandSender sender, final @NotNu }); return true; } + + @Override + public final @Nullable List<@NotNull String> onTabComplete(final @NotNull CommandSender sender, final @NotNull org.bukkit.command.Command command, final @NotNull String label, final @NotNull String @NotNull [] args) { + return tab(sender, label, args); + } } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/IgnoreCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/IgnoreCommand.java index 2996bfe..92d0436 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/IgnoreCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/IgnoreCommand.java @@ -43,7 +43,7 @@ public static boolean unignore(final @NotNull Player player, final @NotNull Offl } @Override - public @Nullable List<@NotNull String> onTabComplete(final @NotNull CommandSender sender, final @NotNull org.bukkit.command.Command command, final @NotNull String label, final @NotNull String @NotNull [] args) { + public @Nullable List<@NotNull String> tab(final @NotNull CommandSender sender, final @NotNull String label, final @NotNull String @NotNull [] args) { if (args.length == 1 && sender.hasPermission(Permission.IGNORE) && sender instanceof Player) return null; return new ArrayList<>(); } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java index d46d564..e1bae0a 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java @@ -15,7 +15,7 @@ public final class MailCommand extends Command { @Override - public boolean run(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args) { + public boolean run(@NotNull CommandSender sender, @NotNull String label, @NotNull String @NotNull [] args) { if (!sender.hasPermission(Permission.MAIL)) return sendMessage(sender, CloudnodeMSG.getInstance().config().noPermission()); if (args.length == 0) return help(sender); final @NotNull String @NotNull [] subCommandArgs = Arrays.copyOfRange(args, 1, args.length); @@ -44,7 +44,7 @@ public static boolean send(final @NotNull CommandSender sender, final @NotNull S } @Override - public @Nullable List onTabComplete(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args) { + public @Nullable List<@NotNull String> tab(final @NotNull CommandSender sender, final @NotNull String label, final @NotNull String @NotNull [] args) { return null; } } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MainCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MainCommand.java index 879ad63..107c8e7 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MainCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MainCommand.java @@ -40,7 +40,7 @@ private boolean reload(final @NotNull CommandSender sender) { } @Override - public @NotNull List<@NotNull String> onTabComplete(@NotNull CommandSender sender, @NotNull org.bukkit.command.Command command, @NotNull String label, @NotNull String @NotNull [] args) { + public @NotNull List<@NotNull String> tab(final @NotNull CommandSender sender, final @NotNull String label, final @NotNull String @NotNull [] args) { final @NotNull List<@NotNull String> completions = new ArrayList<>(); if (args.length == 1) if (sender.hasPermission(Permission.RELOAD) && "reload".startsWith(args[0].toLowerCase())) completions.add("reload"); diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MessageCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MessageCommand.java index 68a9136..2b59160 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MessageCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MessageCommand.java @@ -59,7 +59,7 @@ public boolean run(final @NotNull CommandSender sender, final @NotNull String la } @Override - public @Nullable List<@NotNull String> onTabComplete(final @NotNull CommandSender sender, final @NotNull org.bukkit.command.Command command, final @NotNull String label, final @NotNull String @NotNull [] args) { + public @Nullable List<@NotNull String> tab(final @NotNull CommandSender sender, final @NotNull String label, final @NotNull String @NotNull [] args) { if (!sender.hasPermission(Permission.USE)) return new ArrayList<>(); // `null` works for list of players if (args.length == 1) return null; diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ReplyCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ReplyCommand.java index 9ebdb30..002871b 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ReplyCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ReplyCommand.java @@ -47,7 +47,7 @@ public boolean run(final @NotNull CommandSender sender, final @NotNull String la } @Override - public @NotNull List<@NotNull String> onTabComplete(final @NotNull CommandSender sender, final @NotNull org.bukkit.command.Command command, final @NotNull String label, final @NotNull String @NotNull [] args) { + public @NotNull List<@NotNull String> tab(final @NotNull CommandSender sender, final @NotNull String label, final @NotNull String @NotNull [] args) { return new ArrayList<>(); } } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ToggleMessageCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ToggleMessageCommand.java index b6c02eb..bc4964f 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ToggleMessageCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/ToggleMessageCommand.java @@ -17,7 +17,7 @@ public final class ToggleMessageCommand extends Command { @Override - public boolean run(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args) { + public boolean run(@NotNull CommandSender sender, @NotNull String label, @NotNull String @NotNull [] args) { if (!sender.hasPermission(Permission.TOGGLE) || (args.length == 1 && !sender.hasPermission(Permission.TOGGLE_OTHER))) return new NoPermissionError().send(sender); if (args.length == 1) { @@ -46,7 +46,7 @@ public boolean run(@NotNull CommandSender sender, @NotNull String label, @NotNul } @Override - public @Nullable List onTabComplete(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String s, @NotNull String[] strings) { + public @Nullable List<@NotNull String> tab(final @NotNull CommandSender sender, final @NotNull String label, final @NotNull String @NotNull [] args) { if (sender.hasPermission(Permission.TOGGLE_OTHER)) return null; return new ArrayList<>(); diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/UnIgnoreCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/UnIgnoreCommand.java index f29e5e9..6e5104b 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/UnIgnoreCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/UnIgnoreCommand.java @@ -33,7 +33,7 @@ public boolean run(final @NotNull CommandSender sender, final @NotNull String la } @Override - public @Nullable List<@NotNull String> onTabComplete(final @NotNull CommandSender sender, final @NotNull org.bukkit.command.Command command, final @NotNull String label, final @NotNull String @NotNull [] args) { + public @Nullable List<@NotNull String> tab(final @NotNull CommandSender sender, final @NotNull String label, final @NotNull String @NotNull [] args) { if (args.length == 1 && sender.hasPermission(Permission.IGNORE) && sender instanceof final @NotNull Player player) { final @NotNull HashSet<@NotNull UUID> ignored = Message.getIgnored(player); final @NotNull Server server = CloudnodeMSG.getInstance().getServer(); From 9dd174a029a34aa51bb7f893869b75d1e51a8f9a Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Mon, 6 May 2024 12:55:14 +0300 Subject: [PATCH 13/14] fix errors --- .../smp/cloudnodemsg/CloudnodeMSG.java | 1 + .../cloudnode/smp/cloudnodemsg/Message.java | 5 ++--- .../smp/cloudnodemsg/PluginConfig.java | 20 +++++++++---------- .../smp/cloudnodemsg/command/MailCommand.java | 2 +- .../cloudnodemsg/command/MessageCommand.java | 2 +- .../command/TeamMessageCommand.java | 12 +++++------ .../error/ChannelOfflineError.java | 3 ++- .../error/PlayerNotFoundError.java | 3 +-- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java index 04e9373..f17909e 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/CloudnodeMSG.java @@ -13,6 +13,7 @@ import pro.cloudnode.smp.cloudnodemsg.command.MainCommand; import pro.cloudnode.smp.cloudnodemsg.command.MessageCommand; import pro.cloudnode.smp.cloudnodemsg.command.ReplyCommand; +import pro.cloudnode.smp.cloudnodemsg.command.TeamMessageCommand; import pro.cloudnode.smp.cloudnodemsg.command.ToggleMessageCommand; import pro.cloudnode.smp.cloudnodemsg.command.UnIgnoreCommand; import pro.cloudnode.smp.cloudnodemsg.listener.AsyncChatListener; diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/Message.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/Message.java index 67ef1c7..6f489b2 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/Message.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/Message.java @@ -47,15 +47,14 @@ public void send(final boolean channel) throws InvalidPlayerError { if (!channel) new PlayerNotFoundError(senderPlayer.get().getName()).send(senderPlayer.get()); else { Message.exitChannel(senderPlayer.get()); - new ChannelOfflineError(senderPlayer.get().getName(), Optional.ofNullable(recipient.getName()) - .orElse("Unknown Player")).send(senderPlayer.get()); + new ChannelOfflineError(senderPlayer.get(), recipient).send(senderPlayer.get()); } return; } if (recipientPlayer.isPresent() && senderPlayer.isPresent() && !Message.isIncomingEnabled(recipientPlayer.get()) && !senderPlayer .get().hasPermission(Permission.TOGGLE_BYPASS)) { - new PlayerHasIncomingDisabledError(recipientPlayer.get().getName()).send(senderPlayer.get()); + new PlayerHasIncomingDisabledError(recipientPlayer.get()).send(senderPlayer.get()); return; } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java index 51e388b..e12907a 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java @@ -102,9 +102,9 @@ public PluginConfig(final @NotNull FileConfiguration config) { * @param team The team * @param message The message text */ - public @NotNull Component team(final @NotNull String sender, final @NotNull Team team, final @NotNull Component message) { + public @NotNull Component team(final @NotNull OfflinePlayer sender, final @NotNull Team team, final @NotNull Component message) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("team")) - .replace("", sender), + .replace("", Message.name(sender)), Placeholder.component("team", team.displayName()), Placeholder.component("message", message) ); @@ -144,9 +144,9 @@ public PluginConfig(final @NotNull FileConfiguration config) { * @param team The team * @param message The message text */ - public @NotNull Component teamSpy(final @NotNull String sender, final @NotNull Team team, final @NotNull Component message) { + public @NotNull Component teamSpy(final @NotNull OfflinePlayer sender, final @NotNull Team team, final @NotNull Component message) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("team-spy")) - .replace("", sender), + .replace("", Message.name(sender)), Placeholder.component("team", team.displayName()), Placeholder.component("message", message) ); @@ -246,9 +246,9 @@ public PluginConfig(final @NotNull FileConfiguration config) { * @param sender The username of the message sender * @param team The team@ */ - public @NotNull Component channelTeamCreated(final @NotNull String sender, final @NotNull Team team) { + public @NotNull Component channelTeamCreated(final @NotNull OfflinePlayer sender, final @NotNull Team team) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("channel.team-created")) - .replace("", sender), + .replace("", Message.name(sender)), Placeholder.component("team", team.displayName())); } @@ -263,9 +263,9 @@ public PluginConfig(final @NotNull FileConfiguration config) { * @param sender The username of the message sender * @param team The team */ - public @NotNull Component channelTeamClosed(final @NotNull String sender, final @NotNull Team team) { + public @NotNull Component channelTeamClosed(final @NotNull OfflinePlayer sender, final @NotNull Team team) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("channel.team-closed")) - .replace("", sender), + .replace("", Message.name(sender)), Placeholder.component("team", team.displayName())); } @@ -412,9 +412,9 @@ public int mailNotifyInterval() { * * @param player The player */ - public @NotNull Component playerNotFound(final @NotNull OfflinePlayer player) { + public @NotNull Component playerNotFound(final @NotNull String player) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("errors.player-not-found")), - Placeholder.unparsed("player", Message.name(player)) + Placeholder.unparsed("player", player) ); } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java index e1bae0a..2f8e000 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java @@ -36,7 +36,7 @@ public static boolean send(final @NotNull CommandSender sender, final @NotNull S if (args.length == 1) return sendMessage(sender, CloudnodeMSG.getInstance().config().usage(label, args[0] + " ")); final @NotNull String message = String.join(" ", Arrays.copyOfRange(args, 1, args.length)); final @NotNull OfflinePlayer recipient = CloudnodeMSG.getInstance().getServer().getOfflinePlayer(args[0]); - if (!recipient.hasPlayedBefore()) return sendMessage(sender, CloudnodeMSG.getInstance().config().playerNotFound(recipient)); + if (!recipient.hasPlayedBefore()) return sendMessage(sender, CloudnodeMSG.getInstance().config().playerNotFound(Message.name(recipient))); final @NotNull Mail mail = new Mail(Message.offlinePlayer(sender), recipient, message); mail.insert(); // TODO: notify recipient (if online) diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MessageCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MessageCommand.java index ff37372..5dc026b 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MessageCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MessageCommand.java @@ -47,7 +47,7 @@ public boolean run(final @NotNull CommandSender sender, final @NotNull String la if (recipient.isEmpty() || (CloudnodeMSG.isVanished(recipient.get()) && !player.hasPermission(Permission.SEND_VANISHED))) return new PlayerNotFoundError(args[0]).send(player); if (!Message.isIncomingEnabled(recipient.get())) return new PlayerHasIncomingDisabledError(recipient.get()).send(player); Message.createChannel(player, recipient.get()); - return sendMessage(player, CloudnodeMSG.getInstance().config().channelCreated(player.getName(), recipient.get().getName(), label)); + return sendMessage(player, CloudnodeMSG.getInstance().config().channelCreated(player, recipient.get(), label)); } try { diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/TeamMessageCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/TeamMessageCommand.java index cea49bf..16aedfb 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/TeamMessageCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/TeamMessageCommand.java @@ -28,19 +28,19 @@ public boolean run(final @NotNull CommandSender sender, final @NotNull String la if (Message.hasTeamChannel(player)) { Message.exitTeamChannel(player); return sendMessage(player, CloudnodeMSG.getInstance().config() - .channelTeamClosed(player.getName(), team.get())); + .channelTeamClosed(player, team.get())); } else { Message.createTeamChannel(player); return sendMessage(player, CloudnodeMSG.getInstance().config() - .channelTeamCreated(player.getName(), team.get())); + .channelTeamCreated(player, team.get())); } } return sendTeamMessage(player, team.get(), Component.text(String.join(" ", args))); } @Override - public @Nullable List<@NotNull String> onTabComplete(final @NotNull CommandSender sender, final org.bukkit.command.@NotNull Command command, final @NotNull String label, final @NotNull String @NotNull [] args) { + public @Nullable List<@NotNull String> tab(final @NotNull CommandSender sender, final @NotNull String label, final @NotNull String @NotNull [] args) { return new ArrayList<>(); } @@ -52,12 +52,12 @@ public static boolean sendTeamMessage(final @NotNull Player sender, final @NotNu if (Message.isIgnored(player, sender)) continue; if (Optional.ofNullable(player.getScoreboard().getPlayerTeam(player)).map(t -> t.equals(team)) .orElse(false)) - sendMessage(player, CloudnodeMSG.getInstance().config().team(sender.getName(), team, message)); + sendMessage(player, CloudnodeMSG.getInstance().config().team(sender, team, message)); else if (player.hasPermission(Permission.SPY)) - sendMessage(player, CloudnodeMSG.getInstance().config().teamSpy(sender.getName(), team, message)); + sendMessage(player, CloudnodeMSG.getInstance().config().teamSpy(sender, team, message)); } sender.getServer().getConsoleSender() - .sendMessage(CloudnodeMSG.getInstance().config().teamSpy(sender.getName(), team, message)); + .sendMessage(CloudnodeMSG.getInstance().config().teamSpy(sender, team, message)); return true; } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/ChannelOfflineError.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/ChannelOfflineError.java index db6f776..0de6ddc 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/ChannelOfflineError.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/ChannelOfflineError.java @@ -1,5 +1,6 @@ package pro.cloudnode.smp.cloudnodemsg.error; +import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG; @@ -13,7 +14,7 @@ public final class ChannelOfflineError extends Error { * @param sender The username of the message sender * @param recipient The username of the message recipient */ - public ChannelOfflineError(final @NotNull String sender, final @NotNull String recipient) { + public ChannelOfflineError(final @NotNull OfflinePlayer sender, final @NotNull OfflinePlayer recipient) { super(CloudnodeMSG.getInstance().config().channelOffline(sender, recipient)); } } diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/PlayerNotFoundError.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/PlayerNotFoundError.java index 7699a56..63c832b 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/PlayerNotFoundError.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/error/PlayerNotFoundError.java @@ -1,6 +1,5 @@ package pro.cloudnode.smp.cloudnodemsg.error; -import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG; @@ -13,7 +12,7 @@ public final class PlayerNotFoundError extends Error { * * @param player the player's username */ - public PlayerNotFoundError(final @NotNull OfflinePlayer player) { + public PlayerNotFoundError(final @NotNull String player) { super(CloudnodeMSG.getInstance().config().playerNotFound(player)); } } From 4ed6241dd3ecbecb836a0e5880d3cb445a1b4421 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Sun, 19 May 2024 17:57:59 +0300 Subject: [PATCH 14/14] notify for received mail --- .../smp/cloudnodemsg/PluginConfig.java | 26 +++++++++++++++++++ .../smp/cloudnodemsg/command/MailCommand.java | 8 +++++- src/main/resources/config.yml | 11 ++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java index e12907a..a283d19 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/PluginConfig.java @@ -378,12 +378,38 @@ public int mailNotifyInterval() { *
  • {@code } - the message
  • *
  • {@code } - whether the mail was read/opened by the recipient (see: Insert a choice)
  • *
  • {@code } - whether the recipient has starred the mail (see: Insert a choice)
  • + *
  • {@code } - the ID of the mail
  • * * * @param mail the mail */ public @NotNull Component mailSent(final @NotNull Mail mail) { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("mail.sent")) + .replace("", mail.id.toString()) + .replace("", Message.name(mail.sender)) + .replace("", Message.name(mail.recipient)), + Formatter.booleanChoice("seen", mail.seen), + Formatter.booleanChoice("starred", mail.starred) + ).replaceText(configurer -> configurer.matchLiteral("").replacement(Component.text(mail.message))); + } + + /** + * Received mail while online + *

    Placeholders:

    + *
      + *
    • {@code } - the username of the sender
    • + *
    • {@code } - the username of the recipient
    • + *
    • {@code } - the message
    • + *
    • {@code } - whether the mail was read/opened by the recipient (see: Insert a choice)
    • + *
    • {@code } - whether the recipient has starred the mail (see: Insert a choice)
    • + *
    • {@code } - the ID of the mail
    • + *
    + * + * @param mail the mail + */ + public @NotNull Component mailReceived(final @NotNull Mail mail) { + return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("mail.received")) + .replace("", mail.id.toString()) .replace("", Message.name(mail.sender)) .replace("", Message.name(mail.recipient)), Formatter.booleanChoice("seen", mail.seen), diff --git a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java index 2f8e000..8bf283c 100644 --- a/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java +++ b/src/main/java/pro/cloudnode/smp/cloudnodemsg/command/MailCommand.java @@ -2,6 +2,7 @@ import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import pro.cloudnode.smp.cloudnodemsg.CloudnodeMSG; @@ -11,6 +12,7 @@ import java.util.Arrays; import java.util.List; +import java.util.Optional; public final class MailCommand extends Command { @@ -39,7 +41,11 @@ public static boolean send(final @NotNull CommandSender sender, final @NotNull S if (!recipient.hasPlayedBefore()) return sendMessage(sender, CloudnodeMSG.getInstance().config().playerNotFound(Message.name(recipient))); final @NotNull Mail mail = new Mail(Message.offlinePlayer(sender), recipient, message); mail.insert(); - // TODO: notify recipient (if online) + final @NotNull OfflinePlayer senderOfflinePlayer = Message.offlinePlayer(sender); + final @NotNull Optional<@NotNull Player> senderPlayer = Optional.ofNullable(senderOfflinePlayer.getPlayer()); + final @NotNull Optional<@NotNull Player> recipientPlayer = Optional.ofNullable(recipient.getPlayer()); + if (recipientPlayer.isPresent() && (!Message.isIgnored(recipientPlayer.get(), senderOfflinePlayer) || senderPlayer.isEmpty() || senderPlayer.get().hasPermission(Permission.IGNORE_BYPASS))) + sendMessage(recipientPlayer.get(), CloudnodeMSG.getInstance().config().mailReceived(mail)); return sendMessage(sender, CloudnodeMSG.getInstance().config().mailSent(mail)); } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index e47e246..5deb192 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -142,8 +142,19 @@ mail: # - the message # - whether the mail was read/opened by the recipient (see: https://docs.advntr.dev/minimessage/dynamic-replacements.html#insert-a-choice) # - whether the recipient has starred the mail (see: https://docs.advntr.dev/minimessage/dynamic-replacements.html#insert-a-choice) + # - the ID of the mail sent: "(!) Successfully sent mail to ." + # Received mail while online + # Placeholders: + # - the username of the sender + # - the username of the recipient + # - the message + # - whether the mail was read/opened by the recipient (see: https://docs.advntr.dev/minimessage/dynamic-replacements.html#insert-a-choice) + # - whether the recipient has starred the mail (see: https://docs.advntr.dev/minimessage/dynamic-replacements.html#insert-a-choice) + # - the ID of the mail + received: "(!) You have new mail from . >Click to view" + # Error messages errors: # No permission