diff --git a/api/src/main/java/com/alttd/chat/config/Config.java b/api/src/main/java/com/alttd/chat/config/Config.java index 112fe17..34a97b1 100755 --- a/api/src/main/java/com/alttd/chat/config/Config.java +++ b/api/src/main/java/com/alttd/chat/config/Config.java @@ -79,7 +79,7 @@ public final class Config { method.setAccessible(true); method.invoke(instance); } catch (InvocationTargetException | IllegalAccessException ex) { - throw Throwables.propagate(ex.getCause()); + ex.printStackTrace(); } } } @@ -87,7 +87,7 @@ public final class Config { try { configLoader.save(config); } catch (IOException ex) { - throw Throwables.propagate(ex.getCause()); + ex.printStackTrace(); } } @@ -95,7 +95,7 @@ public final class Config { try { configLoader.save(config); } catch (IOException ex) { - throw Throwables.propagate(ex.getCause()); + ex.printStackTrace(); } } @@ -108,6 +108,7 @@ public final class Config { try { config.node(splitPath(path)).set(def); } catch (SerializationException e) { + e.printStackTrace(); } } } @@ -117,6 +118,7 @@ public final class Config { if(config.node(splitPath(path)).virtual()) config.node(splitPath(path)).set(io.leangen.geantyref.TypeToken.get(String.class), def); } catch(SerializationException ex) { + ex.printStackTrace(); } } @@ -150,6 +152,7 @@ public final class Config { set(path, def); return config.node(splitPath(path)).getList(TypeToken.get(String.class)); } catch(SerializationException ex) { + ex.printStackTrace(); } return new ArrayList<>(); } @@ -169,6 +172,7 @@ public final class Config { public static String MINIMIUMSTAFFRANK = "trainee"; public static String CONSOLENAME = "Console"; public static UUID CONSOLEUUID = UUID.randomUUID(); + public static int EMOTELIMIT = 3; private static void settings() { PREFIXGROUPS = getList("settings.prefix-groups", Lists.newArrayList("discord", "socialmedia", "eventteam", "eventleader", "youtube", "twitch", "developer")); @@ -179,6 +183,7 @@ public final class Config { CONSOLENAME = getString("settings.console-name", CONSOLENAME); CONSOLEUUID = UUID.fromString(getString("settings.console-uuid", CONSOLEUUID.toString())); MINIMIUMSTAFFRANK = getString("settings.minimum-staff-rank", MINIMIUMSTAFFRANK); + EMOTELIMIT = getInt("settings.emote-limit", EMOTELIMIT); } public static List MESSAGECOMMANDALIASES = new ArrayList<>(); @@ -466,4 +471,73 @@ public final class Config { private static void loadMessages() { HELP_REPORT = getString("settings.mail.mail-sent", HELP_REPORT); } + + public static String EMOTELIST_HEADER = "Available Chat Emotes"; + public static String EMOTELIST_ITEM = "\"> : "; + public static String EMOTELIST_FOOTER = "----<< Prev / Next >>----"; + private static void emoteListCommand() { + EMOTELIST_HEADER = getString("commands.emotelist.header", EMOTELIST_HEADER); + EMOTELIST_ITEM = getString("commands.emotelist.item", EMOTELIST_ITEM); + EMOTELIST_FOOTER = getString("commands.emotelist.footer", EMOTELIST_FOOTER); + } + + // nicknames TODO minimessage for colors and placeholders + public static String NICK_CHANGED = "&eYour nickname was changed to %nickname%&e."; + public static String NICK_NOT_CHANGED = "&eYour nickname request was denied."; + public static String NICK_RESET = "&eNickname changed back to normal."; + public static String NICK_CHANGED_OTHERS = "&6%targetplayer%&e's nickname was changed to %nickname%&e."; + public static String NICK_TARGET_NICK_CHANGE = "&eYour nickname was changed to %nickname% &eby %sendernick%&e"; + public static String NICK_RESET_OTHERS = "&6%player%&6's &enickname was reset back to normal."; + public static String NICK_INVALID_CHARACTERS = "&eYou can only use letters and numbers in nicknames."; + public static String NICK_INVALID_LENGTH = "&eNicknames need to be between 3 to 16 characters long."; + public static String NICK_PLAYER_NOT_ONLINE = "&cThat player is not online."; + public static String NICK_BLOCKED_COLOR_CODES = "&eYou have blocked color codes in that nickname."; + public static String NICK_USER_NOT_FOUND = "&cFailed to set nickname from player, try again from a server this player has been on before."; + public static String NICK_ACCEPTED = "&aYou accepted %targetPlayer%&a's nickname. They are now called %newNick%&a."; + public static String NICK_DENIED = "&aYou denied %targetPlayer%&a's nickname. They are still called %oldNick%&a."; + public static String NICK_ALREADY_HANDLED = "&c%targetPlayer%&c's nickname was already accepted or denied."; + public static String NICK_NO_LUCKPERMS = "&cDue to an issue with LuckPerms /nick try won't work at the moment."; + public static String NICK_TOO_SOON = "&cPlease wait %time%&c until requesting a new nickname"; + public static String NICK_REQUEST_PLACED = "&aReplaced your previous request %oldRequestedNick%&a with %newRequestedNick%&a."; + public static String NICK_REQUEST_NEW = "&aNew nickname request by %player%&a!"; + public static String NICK_TRYOUT = "&f%prefix&f %nick%&7: &fHi, this is what my new nickname could look like!"; + public static String NICK_REQUESTED = "&aYour requested to be nicknamed %nick%&a has been received. Staff will accept or deny this request asap!"; + public static String NICK_REVIEW_WAITING = "&aThere are %amount% nicknames waiting for review!"; + public static String NICK_TAKEN = "&cSomeone else already has this nickname, or has this name as their username."; + public static String NICK_REQUESTS_ON_LOGIN = "&aCurrent nick requests: %amount%"; + public static long NICK_WAIT_TIME = 86400000; + public static List NICK_ITEM_LORE = new ArrayList<>(); + public static List NICK_BLOCKED_COLOR_CODESLIST = new ArrayList<>(); + public static List NICK_ALLOWED_COLOR_CODESLIST = new ArrayList<>(); + public static String NICK_CURRENT = "Current nickname: (\">)"; + private static void nicknameSettings() { + NICK_CHANGED = getString("nicknames.messages.nick-changed", NICK_CHANGED); + NICK_NOT_CHANGED = getString("nicknames.messages.nick-not-changed", NICK_NOT_CHANGED); + NICK_RESET = getString("nicknames.messages.nick-reset", NICK_RESET); + NICK_CHANGED_OTHERS = getString("nicknames.messages.nick-changed-others", NICK_CHANGED_OTHERS); + NICK_TARGET_NICK_CHANGE = getString("nicknames.messages.nick-target-nick-change", NICK_TARGET_NICK_CHANGE); + NICK_RESET_OTHERS = getString("nicknames.messages.nick-reset-others", NICK_RESET_OTHERS); + NICK_INVALID_CHARACTERS = getString("nicknames.messages.nick-invalid-characters", NICK_INVALID_CHARACTERS); + NICK_INVALID_LENGTH = getString("nicknames.messages.nick-invalid-length", NICK_INVALID_LENGTH); + NICK_PLAYER_NOT_ONLINE = getString("nicknames.messages.nick-player-not-online", NICK_PLAYER_NOT_ONLINE); + NICK_BLOCKED_COLOR_CODES = getString("nicknames.messages.nick-blocked-color-codes", NICK_BLOCKED_COLOR_CODES); + NICK_USER_NOT_FOUND = getString("nicknames.messages.nick-user-not-found", NICK_USER_NOT_FOUND); + NICK_ACCEPTED = getString("nicknames.messages.nick-accepted", NICK_ACCEPTED); + NICK_DENIED = getString("nicknames.messages.nick-denied", NICK_DENIED); + NICK_ALREADY_HANDLED = getString("nicknames.messages.nick-already-handled", NICK_ALREADY_HANDLED); + NICK_NO_LUCKPERMS = getString("nicknames.messages.nick-no-luckperms", NICK_NO_LUCKPERMS); + NICK_TOO_SOON = getString("nicknames.messages.nick-too-soon", NICK_TOO_SOON); + NICK_REQUEST_PLACED = getString("nicknames.messages.nick-request-placed", NICK_REQUEST_PLACED); + NICK_REQUEST_NEW = getString("nicknames.messages.nick-request-new", NICK_REQUEST_NEW); + NICK_TRYOUT = getString("nicknames.messages.nick-tryout", NICK_TRYOUT); + NICK_REQUESTED = getString("nicknames.messages.nick-requested", NICK_REQUESTED); + NICK_REVIEW_WAITING = getString("nicknames.messages.nick-review-waiting", NICK_REVIEW_WAITING); + NICK_TAKEN = getString("nicknames.messages.nick-taken", NICK_TAKEN); + NICK_REQUESTS_ON_LOGIN = getString("nicknames.messages.nick-reauests-on-login", NICK_REQUESTS_ON_LOGIN); + NICK_WAIT_TIME = getLong("nicknames.wait-time", NICK_WAIT_TIME); + NICK_ITEM_LORE = getList("nicknames.item-lore", List.of("&bNew nick: %newNick%", "&bOld nick: %oldNick%", "&bLast changed: %lastChanged%", "&aLeft click to Accept &d| &cRight click to Deny")); + NICK_BLOCKED_COLOR_CODESLIST = getList("nicknames.blocked-color-codes", List.of("&k", "&l", "&n", "&m", "&o")); + NICK_ALLOWED_COLOR_CODESLIST = getList("nicknames.allowed-color-codes", List.of("&0", "&1", "&2", "&3", "&4", "&5", "&6", "&7", "&8", "&9", "&a", "&b", "&c", "&d", "&e", "&f", "&r")); + NICK_CURRENT = getString("nicknames.messages.nick-current", NICK_CURRENT); + } } diff --git a/api/src/main/java/com/alttd/chat/config/PrefixConfig.java b/api/src/main/java/com/alttd/chat/config/PrefixConfig.java index 3b5b483..37ef1d9 100755 --- a/api/src/main/java/com/alttd/chat/config/PrefixConfig.java +++ b/api/src/main/java/com/alttd/chat/config/PrefixConfig.java @@ -80,7 +80,7 @@ public final class PrefixConfig { method.setAccessible(true); method.invoke(instance); } catch (InvocationTargetException | IllegalAccessException ex) { - throw Throwables.propagate(ex.getCause()); + ex.printStackTrace(); } } } @@ -88,7 +88,7 @@ public final class PrefixConfig { try { configLoader.save(config); } catch (IOException ex) { - throw Throwables.propagate(ex.getCause()); + ex.printStackTrace(); } } @@ -96,7 +96,7 @@ public final class PrefixConfig { try { configLoader.save(config); } catch (IOException ex) { - throw Throwables.propagate(ex.getCause()); + ex.printStackTrace(); } } @@ -109,6 +109,7 @@ public final class PrefixConfig { try { config.node(splitPath(path)).set(def); } catch (SerializationException e) { + e.printStackTrace(); } } } @@ -118,6 +119,7 @@ public final class PrefixConfig { if(config.node(splitPath(path)).virtual()) config.node(splitPath(path)).set(io.leangen.geantyref.TypeToken.get(String.class), def); } catch(SerializationException ex) { + ex.printStackTrace(); } } diff --git a/api/src/main/java/com/alttd/chat/config/RegexConfig.java b/api/src/main/java/com/alttd/chat/config/RegexConfig.java index 17ab7e3..da77981 100755 --- a/api/src/main/java/com/alttd/chat/config/RegexConfig.java +++ b/api/src/main/java/com/alttd/chat/config/RegexConfig.java @@ -3,14 +3,12 @@ package com.alttd.chat.config; import com.alttd.chat.managers.RegexManager; import com.alttd.chat.objects.ChatFilter; import com.alttd.chat.util.ALogger; -import com.google.common.base.Throwables; import io.leangen.geantyref.TypeToken; import org.spongepowered.configurate.ConfigurationNode; import org.spongepowered.configurate.ConfigurationOptions; import org.spongepowered.configurate.serialize.SerializationException; import org.spongepowered.configurate.yaml.NodeStyle; import org.spongepowered.configurate.yaml.YamlConfigurationLoader; -import org.yaml.snakeyaml.DumperOptions; import java.io.File; import java.io.IOException; @@ -78,7 +76,7 @@ public final class RegexConfig { method.setAccessible(true); method.invoke(instance); } catch (InvocationTargetException | IllegalAccessException ex) { - throw Throwables.propagate(ex.getCause()); + ex.printStackTrace(); } } } @@ -86,7 +84,7 @@ public final class RegexConfig { try { configLoader.save(config); } catch (IOException ex) { - throw Throwables.propagate(ex.getCause()); + ex.printStackTrace(); } } diff --git a/api/src/main/java/com/alttd/chat/database/Queries.java b/api/src/main/java/com/alttd/chat/database/Queries.java index 76161ac..5d3df66 100755 --- a/api/src/main/java/com/alttd/chat/database/Queries.java +++ b/api/src/main/java/com/alttd/chat/database/Queries.java @@ -1,18 +1,13 @@ package com.alttd.chat.database; import com.alttd.chat.managers.PartyManager; -import com.alttd.chat.objects.ChatUser; -import com.alttd.chat.objects.Mail; -import com.alttd.chat.objects.Party; -import com.alttd.chat.objects.PartyUser; +import com.alttd.chat.objects.*; import com.alttd.chat.objects.channels.Channel; import com.alttd.chat.util.ALogger; import java.sql.*; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.UUID; +import java.util.*; +import java.util.Date; public class Queries { @@ -24,7 +19,8 @@ public class Queries { tables.add("CREATE TABLE IF NOT EXISTS parties (`id` INT NOT NULL AUTO_INCREMENT, `owner_uuid` VARCHAR(36) NOT NULL, `party_name` VARCHAR(36) NOT NULL, `password` VARCHAR(36), PRIMARY KEY (`id`))"); tables.add("CREATE TABLE IF NOT EXISTS chat_users (`uuid` VARCHAR(36) NOT NULL, `party_id` INT NOT NULL, `toggled_channel` VARCHAR(36) NULL DEFAULT NULL, PRIMARY KEY (`uuid`))"); tables.add("CREATE TABLE IF NOT EXISTS mails (`id` INT NOT NULL AUTO_INCREMENT, `uuid` VARCHAR(36) NOT NULL, `sender` VARCHAR(36) NOT NULL, `message` VARCHAR(256) NOT NULL, `sendtime` BIGINT default 0, `readtime` BIGINT default 0, PRIMARY KEY (`id`))"); - + createNicknamesTable(); + createRequestedNicknamesTable(); try { Connection connection = DatabaseConnection.getConnection(); @@ -39,6 +35,51 @@ public class Queries { //----------------------------------------- //Nicknames + private static void createNicknamesTable() { + + try { + String nicknamesTableQuery = "CREATE TABLE IF NOT EXISTS nicknames(" + + "uuid VARCHAR(48) NOT NULL," + + "PRIMARY KEY (uuid))"; + DatabaseConnection.getConnection().prepareStatement(nicknamesTableQuery).executeUpdate(); + } catch (Throwable throwable) { + throwable.printStackTrace(); + } + + List columns = new ArrayList<>(); + columns.add("ALTER TABLE nicknames ADD nickname VARCHAR(192)"); + columns.add("ALTER TABLE nicknames ADD date_changed BIGINT default 0"); + for (String string : columns) { + try { + DatabaseConnection.getConnection().prepareStatement(string).executeUpdate(); + } catch (Throwable ignored) { + } + } + + } + + private static void createRequestedNicknamesTable() { + + try { + String requestedNicknamesTableQuery = "CREATE TABLE IF NOT EXISTS requested_nicknames(" + + "uuid VARCHAR(48) NOT NULL," + + "PRIMARY KEY (uuid))"; + DatabaseConnection.getConnection().prepareStatement(requestedNicknamesTableQuery).executeUpdate(); + } catch (Throwable throwable) { + throwable.printStackTrace(); + } + + List columns = new ArrayList<>(); + columns.add("ALTER TABLE requested_nicknames ADD nickname VARCHAR(192)"); + columns.add("ALTER TABLE requested_nicknames ADD date_requested BIGINT default 0"); + for (String string : columns) { + try { + DatabaseConnection.getConnection().prepareStatement(string).executeUpdate(); + } catch (Throwable ignored) { + } + } + + } public static String getNickname(UUID uuid) { // View has been created. @@ -564,4 +605,172 @@ public class Queries { e.printStackTrace(); } } + + // Nicknames + public static void setNicknameInDatabase(final UUID uuid, final String nickName) { + final String sql = "INSERT INTO nicknames (uuid, nickname, date_changed) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE nickname = ?"; + try (final PreparedStatement statement = DatabaseConnection.getConnection().prepareStatement(sql)) { + statement.setString(1, uuid.toString()); + statement.setString(2, nickName); + statement.setLong(3, new java.util.Date().getTime()); + statement.setString(4, nickName); + statement.execute(); + } + catch (SQLException e) { + e.printStackTrace(); + } + } + + public static void removePlayerFromDataBase(final UUID uuid) throws SQLException { + final PreparedStatement insert = DatabaseConnection.getConnection().prepareStatement("DELETE FROM nicknames WHERE uuid = ?"); + insert.setString(1, uuid.toString()); + insert.executeUpdate(); + insert.close(); + } + + public static ArrayList getNicknamesList() { + ArrayList nickList = new ArrayList<>(); + String queryNicknames = "SELECT uuid, nickname, date_changed FROM nicknames "; + String queryRequests = "SELECT `requested_nicknames`.`nickname` AS new_nick, `requested_nicknames`.`date_requested`, " + + "`nicknames`.`nickname` AS old_nick, `nicknames`.`date_changed`, `requested_nicknames`.`uuid` " + + "FROM `requested_nicknames`" + + "LEFT JOIN `nicknames` ON `requested_nicknames`.`uuid` = `nicknames`.`uuid` "; + + try { + ResultSet resultSetNicknames = getStringResult(queryNicknames); + while (resultSetNicknames.next()){ + nickList.add(new Nick( + UUID.fromString(resultSetNicknames.getString("uuid")), + resultSetNicknames.getString("nickname"), + resultSetNicknames.getLong("date_changed"))); + } + + ResultSet resultSetRequests = getStringResult(queryRequests); + while (resultSetRequests.next()){ + nickList.add(new Nick( + UUID.fromString(resultSetRequests.getString("uuid")), + resultSetRequests.getString("old_nick"), + resultSetRequests.getLong("date_changed"), + resultSetRequests.getString("new_nick"), + resultSetRequests.getLong("date_requested"))); + } + } catch (SQLException e) { + ALogger.warn("Failed to get nicknames list\n" + Arrays.toString(e.getStackTrace()) + .replace(",", "\n")); + } + return nickList; + } + + public static Nick getNick(UUID uniqueId) { + String getNick = "SELECT nickname, date_changed, uuid FROM nicknames WHERE uuid = ?"; + String getRequest = "SELECT nickname, date_requested, uuid FROM requested_nicknames WHERE uuid = ?"; + + try { + ResultSet resultSetNick = getStringResult(getNick, uniqueId.toString()); + ResultSet resultSetRequest = getStringResult(getRequest, uniqueId.toString()); + String uuid = null; + String currentNick = null; + long dateChanged = 0; + String requestedNick = null; + long dateRequested = 0; + + if (resultSetNick.next()) { + uuid = resultSetNick.getString("uuid"); + currentNick = resultSetNick.getString("nickname"); + dateChanged = resultSetNick.getLong("date_changed"); + } + if (resultSetRequest.next()) { + uuid = resultSetRequest.getString("uuid"); + requestedNick = resultSetRequest.getString("nickname"); + dateRequested = resultSetRequest.getLong("date_requested"); + } + if (uuid != null) { + return new Nick(UUID.fromString(uuid), currentNick, dateChanged, requestedNick, dateRequested); + } + } catch (SQLException e){ + ALogger.warn("Failed to get nicknames for " + + uniqueId.toString() + "\n" + Arrays.toString(e.getStackTrace()) + .replace(",", "\n")); + + } + return null; + } + + public static void denyNewNickname(UUID uniqueId) { + String query = "DELETE FROM requested_nicknames WHERE uuid = ?"; + try { + PreparedStatement statement = DatabaseConnection.getConnection().prepareStatement(query); + statement.setString(1, uniqueId.toString()); + statement.execute(); + } catch (SQLException e) { + ALogger.warn("Failed to delete requested nickname for " + + uniqueId.toString() + "\n" + Arrays.toString(e.getStackTrace()) + .replace(",", "\n")); + } + } + + public static void acceptNewNickname(UUID uniqueId, String newNick){ + String delete = "DELETE FROM requested_nicknames WHERE uuid = ?"; + String update = "INSERT INTO nicknames (uuid, nickname, date_changed) VALUES (?, ?, ?) " + + "ON DUPLICATE KEY UPDATE nickname = ?, date_changed = ?"; + long time = new java.util.Date().getTime(); + + try { + PreparedStatement deleteStatement = DatabaseConnection.getConnection().prepareStatement(delete); + deleteStatement.setString(1, uniqueId.toString()); + + deleteStatement.execute(); + + PreparedStatement updateStatement = DatabaseConnection.getConnection().prepareStatement(update); + updateStatement.setString(1, uniqueId.toString()); + updateStatement.setString(2, newNick); + updateStatement.setLong(3, time); + updateStatement.setString(4, newNick); + updateStatement.setLong(5, time); + + updateStatement.execute(); + } catch (SQLException e) { + ALogger.warn("Failed to accept requested nickname for " + + uniqueId.toString() + "\n" + Arrays.toString(e.getStackTrace()) + .replace(",", "\n")); + } + } + + public static void newNicknameRequest(UUID uniqueId, String nickName) { + String requestQuery = "INSERT INTO requested_nicknames (uuid, nickname, date_requested) VALUES (?, ?, ?) " + + "ON DUPLICATE KEY UPDATE nickname = ?, date_requested = ?"; + String nickQuery = "INSERT INTO nicknames (uuid, nickname, date_changed) VALUES (?, ?, 0) " + + "ON DUPLICATE KEY UPDATE uuid = uuid"; + long time = new Date().getTime(); + + try { + PreparedStatement requestPreparedStatement = DatabaseConnection.getConnection().prepareStatement(requestQuery); + requestPreparedStatement.setString(1, uniqueId.toString()); + requestPreparedStatement.setString(2, nickName); + requestPreparedStatement.setLong(3, time); + requestPreparedStatement.setString(4, nickName); + requestPreparedStatement.setLong(5, time); + + requestPreparedStatement.execute(); + + PreparedStatement nickPreparedStatement = DatabaseConnection.getConnection().prepareStatement(nickQuery); + nickPreparedStatement.setString(1, uniqueId.toString()); + nickPreparedStatement.setString(2, null); + + nickPreparedStatement.execute(); + + } catch (SQLException e) { + ALogger.warn("Failed to store requested nickname for " + + uniqueId.toString() + "\n" + Arrays.toString(e.getStackTrace()) + .replace(",", "\n")); + } + } + + private static ResultSet getStringResult(final String query, final String... parameters) throws SQLException { + final PreparedStatement statement = DatabaseConnection.getConnection().prepareStatement(query); + for (int i = 1; i < parameters.length + 1; ++i) { + statement.setString(i, parameters[i - 1]); + } + return statement.executeQuery(); + } } diff --git a/api/src/main/java/com/alttd/chat/events/NickEvent.java b/api/src/main/java/com/alttd/chat/events/NickEvent.java new file mode 100644 index 0000000..fbf5257 --- /dev/null +++ b/api/src/main/java/com/alttd/chat/events/NickEvent.java @@ -0,0 +1,56 @@ +package com.alttd.chat.events; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; + +public class NickEvent extends Event{ + + String senderName; + String targetName; + String nickName; + NickEventType nickEventType; + + public NickEvent(String senderName, String targetName, String nickName, NickEventType nickEventType) { + this.senderName = senderName; + this.targetName = targetName; + this.nickName = nickName; + this.nickEventType = nickEventType; + } + + public String getSenderName() { + return this.senderName; + } + + public String getTargetName() { + return this.targetName; + } + + public String getNickName() { + return this.nickName; + } + + public NickEventType getNickEventType() { + return this.nickEventType; + } + + private static final HandlerList HANDLERS = new HandlerList(); + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @NotNull + @Override + public HandlerList getHandlers() { + return HANDLERS; + } + + public enum NickEventType { + ACCEPTED, + DENIED, + SET, + RESET + } + +} \ No newline at end of file diff --git a/api/src/main/java/com/alttd/chat/managers/RegexManager.java b/api/src/main/java/com/alttd/chat/managers/RegexManager.java index 4a85e93..629be05 100755 --- a/api/src/main/java/com/alttd/chat/managers/RegexManager.java +++ b/api/src/main/java/com/alttd/chat/managers/RegexManager.java @@ -3,6 +3,7 @@ package com.alttd.chat.managers; import com.alttd.chat.ChatAPI; import com.alttd.chat.config.RegexConfig; import com.alttd.chat.objects.ChatFilter; +import com.alttd.chat.objects.FilterType; import com.alttd.chat.objects.ModifiableString; import com.alttd.chat.util.ALogger; import net.luckperms.api.cacheddata.CachedPermissionData; @@ -17,11 +18,24 @@ public class RegexManager { private static List chatFilters; private static final Pattern pattern = Pattern.compile("(.)\\1{4,}"); + private static final List emotes = new ArrayList<>(); + public static final List emotesList = new ArrayList<>(); public static void initialize() { chatFilters = new ArrayList<>(); RegexConfig.init(); + loadEmotes(); + } + + private static void loadEmotes() { + emotes.clear(); + for(ChatFilter chatFilter : chatFilters) { + if (chatFilter.getType() != FilterType.EMOTE) return; + + emotes.add(chatFilter); + emotesList.add(chatFilter.getRegex()); + } } public static void addFilter(ChatFilter filter) { @@ -65,4 +79,11 @@ public class RegexManager { return true; } + public static List getChatFilters() { + return chatFilters; + } + + public static List getEmoteFilters() { + return emotes; + } } diff --git a/api/src/main/java/com/alttd/chat/objects/ChatUser.java b/api/src/main/java/com/alttd/chat/objects/ChatUser.java index 8dd9780..56185c0 100755 --- a/api/src/main/java/com/alttd/chat/objects/ChatUser.java +++ b/api/src/main/java/com/alttd/chat/objects/ChatUser.java @@ -180,4 +180,8 @@ public class ChatUser { } setDisplayName(name); } + + public String getNickNameString() { + return name; + } } diff --git a/api/src/main/java/com/alttd/chat/objects/EmoteList.java b/api/src/main/java/com/alttd/chat/objects/EmoteList.java new file mode 100644 index 0000000..aa13531 --- /dev/null +++ b/api/src/main/java/com/alttd/chat/objects/EmoteList.java @@ -0,0 +1,64 @@ +package com.alttd.chat.objects; + +import com.alttd.chat.config.Config; +import com.alttd.chat.managers.RegexManager; +import com.alttd.chat.util.Utility; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import org.bukkit.Bukkit; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class EmoteList { + + public static final Map emoteLists = new HashMap<>(); + public static final int pageSize = 7; +// public static int pages = RegexManager.getEmoteFilters().size() / pageSize;// TODO reload this when config is reloaded. + + public static EmoteList getEmoteList(UUID uuid) { + synchronized (emoteLists) { + return emoteLists.computeIfAbsent(uuid, k -> new EmoteList()); + } + } + + private int page; + public Component showEmotePage() { + int startIndex = page * pageSize; + int pages = RegexManager.getEmoteFilters().size() / pageSize; + int endIndex = Math.min(startIndex + pageSize, RegexManager.getEmoteFilters().size()); + TagResolver placeholders = TagResolver.resolver( + Placeholder.unparsed("page", String.valueOf(page)), + Placeholder.unparsed("pages", String.valueOf(pages)) + ); + Component list = Utility.parseMiniMessage(Config.EMOTELIST_HEADER, placeholders); + + for (int i = startIndex; i < endIndex; i++) { + ChatFilter emote = RegexManager.getEmoteFilters().get(i); + TagResolver emotes = TagResolver.resolver( + Placeholder.parsed("regex", emote.getRegex()), + Placeholder.parsed("emote", emote.getReplacement()) + ); + list = list.append(Utility.parseMiniMessage(Config.EMOTELIST_ITEM, emotes)); + } + list = list.append(Utility.parseMiniMessage(Config.EMOTELIST_FOOTER, placeholders)); + return list; + } + + public void setPage(int page) { + this.page = Math.min(page, RegexManager.getEmoteFilters().size() / pageSize); + } + + public void nextPage() { + this.page = Math.min(page + 1, RegexManager.getEmoteFilters().size() / pageSize); + } + + public void prevPage() { + this.page -= 1; + this.page = Math.max(page - 1, 0); + } + + +} diff --git a/api/src/main/java/com/alttd/chat/objects/FilterType.java b/api/src/main/java/com/alttd/chat/objects/FilterType.java index 9eaaa6b..b8e299e 100755 --- a/api/src/main/java/com/alttd/chat/objects/FilterType.java +++ b/api/src/main/java/com/alttd/chat/objects/FilterType.java @@ -2,6 +2,7 @@ package com.alttd.chat.objects; public enum FilterType { REPLACE("replace"), + EMOTE("emote"), CHAT("chat"), REPLACEMATCHER("replacematcher"), BLOCK("block"); diff --git a/api/src/main/java/com/alttd/chat/objects/Nick.java b/api/src/main/java/com/alttd/chat/objects/Nick.java new file mode 100644 index 0000000..da139a4 --- /dev/null +++ b/api/src/main/java/com/alttd/chat/objects/Nick.java @@ -0,0 +1,99 @@ +package com.alttd.chat.objects; + +import com.alttd.chat.util.Utility; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.UUID; + +public class Nick { + private final UUID uuid; + private String currentNick; + private String currentNickNoColor; + private long lastChangedDate; + private String newNick; + private String newNickNoColor; + private long requestedDate; + private boolean hasRequest; + + public Nick(UUID uuid, String currentNick, long lastChangedDate) { + this.uuid = uuid; + this.currentNick = currentNick; + currentNickNoColor = currentNick == null ? null : Utility.removeAllColors(currentNick); + this.lastChangedDate = lastChangedDate; + newNick = null; + newNickNoColor = null; + requestedDate = 0; + hasRequest = false; + } + + public Nick(UUID uuid, String currentNick, long lastChangedDate, String newNick, long requestedDate) { + this.uuid = uuid; + this.currentNick = currentNick; + currentNickNoColor = currentNick == null ? null : Utility.removeAllColors(currentNick); + this.lastChangedDate = lastChangedDate; + this.newNick = newNick; + newNickNoColor = newNick == null ? null : Utility.removeAllColors(newNick); + this.requestedDate = requestedDate; + hasRequest = newNick != null; + } + + public UUID getUuid() { + return uuid; + } + + public String getCurrentNickNoColor() { + return currentNickNoColor; + } + + public String getCurrentNick() { + return currentNick; + } + + public void setCurrentNick(String currentNick) { + this.currentNick = currentNick; + currentNickNoColor = currentNick == null ? null : Utility.removeAllColors(currentNick); + } + + public long getLastChangedDate(){ + return lastChangedDate; + } + + public String getLastChangedDateFormatted() { + return new SimpleDateFormat("yyyy-MM-dd").format(new Date(lastChangedDate)); + } + + public void setLastChangedDate(long lastChangedDate) { + this.lastChangedDate = lastChangedDate; + } + + public String getNewNickNoColor() { + return newNickNoColor; + } + + public String getNewNick() { + return newNick; + } + + public void setNewNick(String newNick) { + this.newNick = newNick; + newNickNoColor = newNick == null ? null : Utility.removeAllColors(newNick); + hasRequest = newNick != null; + } + + public long getRequestedDate(){ + return requestedDate; + } + + public String getRequestedDateFormatted() { + return new SimpleDateFormat("yyyy-MM-dd").format(new Date(requestedDate)); + } + + public void setRequestedDate(long requestedDate) { + this.requestedDate = requestedDate; + } + + public boolean hasRequest() { + return hasRequest; + } +} diff --git a/api/src/main/java/com/alttd/chat/util/Pair.java b/api/src/main/java/com/alttd/chat/util/Pair.java new file mode 100644 index 0000000..f52fa45 --- /dev/null +++ b/api/src/main/java/com/alttd/chat/util/Pair.java @@ -0,0 +1,20 @@ +package com.alttd.chat.util; + +public class Pair { + + private final X x; + private final Y y; + + public Pair(X x, Y y) { + this.x = x; + this.y = y; + } + + public X getX() { + return x; + } + + public Y getY() { + return y; + } +} diff --git a/api/src/main/java/com/alttd/chat/util/Utility.java b/api/src/main/java/com/alttd/chat/util/Utility.java index 8e26736..d6ec511 100755 --- a/api/src/main/java/com/alttd/chat/util/Utility.java +++ b/api/src/main/java/com/alttd/chat/util/Utility.java @@ -3,13 +3,16 @@ package com.alttd.chat.util; import com.alttd.chat.ChatAPI; import com.alttd.chat.config.Config; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.kyori.adventure.text.minimessage.tag.standard.StandardTags; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.luckperms.api.LuckPerms; import net.luckperms.api.model.group.Group; import net.luckperms.api.model.user.User; import net.luckperms.api.node.Node; +import org.bukkit.permissions.Permission; import java.util.*; import java.util.regex.Matcher; @@ -18,6 +21,7 @@ import java.util.stream.Collectors; public class Utility { + private static final List EMPTY_LIST = new ArrayList<>(); static final Pattern DEFAULT_URL_PATTERN = Pattern.compile("(?:(https?)://)?([-\\w_.]+\\.\\w{2,})(/\\S*)?"); private static MiniMessage miniMessage = null; @@ -44,6 +48,38 @@ public class Utility { colors.put("&e", ""); colors.put("&f", ""); } + + public static HashMap>> formattingPerms = new HashMap<>(); + static { + formattingPerms.put("chat.format.color", + new Pair<>(StandardTags.color(), colors.values().stream().toList())); + formattingPerms.put("chat.format.bold", + new Pair<>(StandardTags.decorations(TextDecoration.BOLD), List.of("", ""))); + formattingPerms.put("chat.format.italic", + new Pair<>(StandardTags.decorations(TextDecoration.ITALIC), List.of("", ""))); + formattingPerms.put("chat.format.underlined", + new Pair<>(StandardTags.decorations(TextDecoration.UNDERLINED), List.of("", ""))); + formattingPerms.put("chat.format.strikethrough", + new Pair<>(StandardTags.decorations(TextDecoration.STRIKETHROUGH), List.of("", ""))); + formattingPerms.put("chat.format.obfuscated", + new Pair<>(StandardTags.decorations(TextDecoration.OBFUSCATED), List.of("", ""))); + formattingPerms.put("chat.format.gradient", + new Pair<>(StandardTags.gradient(), EMPTY_LIST)); + formattingPerms.put("chat.format.font", + new Pair<>(StandardTags.font(), EMPTY_LIST)); + formattingPerms.put("chat.format.rainbow", + new Pair<>(StandardTags.rainbow(), List.of(""))); + formattingPerms.put("chat.format.hover", + new Pair<>(StandardTags.hoverEvent(), EMPTY_LIST)); + formattingPerms.put("chat.format.click", + new Pair<>(StandardTags.clickEvent(), EMPTY_LIST)); + formattingPerms.put("chat.format.transition", + new Pair<>(StandardTags.transition(), EMPTY_LIST)); + formattingPerms.put("chat.format.reset", + new Pair<>(StandardTags.reset(), List.of("", ""))); + formattingPerms.put("chat.format.newline", + new Pair<>(StandardTags.newline(), List.of(""))); + } public static String parseColors(String message) { if (message == null) return ""; @@ -264,4 +300,13 @@ public class Utility { return miniMessage; } + public static String removeAllColors(String string) { + + for (String colorCodes : colors.keySet()) { + string = string.replace(colorCodes, ""); + } + + return string.replaceAll("\\{#[A-Fa-f0-9]{6}(<)?(>)?}", ""); + } + } diff --git a/build.gradle.kts b/build.gradle.kts index 0eefa41..75b8e7d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,7 @@ plugins { allprojects { group = "com.alttd.chat" - version = "1.0.0-SNAPSHOT" + version = "2.0.0-SNAPSHOT" description = "All in one minecraft chat plugin" // repositories { @@ -61,7 +61,7 @@ dependencies { tasks { shadowJar { - archiveFileName.set("${project.name}-${project.version}.jar") + archiveFileName.set("${project.name}.jar") minimize() { exclude { it.moduleName == "galaxy" } exclude { it.moduleName == "velocity" } @@ -77,4 +77,7 @@ tasks { dependsOn(shadowJar) } + jar { + enabled = false + } } \ No newline at end of file diff --git a/galaxy/build.gradle.kts b/galaxy/build.gradle.kts index 326f684..72194a2 100644 --- a/galaxy/build.gradle.kts +++ b/galaxy/build.gradle.kts @@ -12,6 +12,7 @@ dependencies { compileOnly("com.alttd:Galaxy-API:1.19.2-R0.1-SNAPSHOT") // Galaxy compileOnly("com.gitlab.ruany:LiteBansAPI:0.3.5") // move to proxy compileOnly("org.apache.commons:commons-lang3:3.12.0") // needs an alternative, already removed from upstream api and will be removed in server + compileOnly("net.luckperms:api:5.3") // Luckperms } tasks { @@ -22,7 +23,7 @@ tasks { } build { - setBuildDir("${rootProject.buildDir}") +// setBuildDir("${rootProject.buildDir}") dependsOn(shadowJar) } diff --git a/galaxy/src/main/java/com/alttd/chat/ChatPlugin.java b/galaxy/src/main/java/com/alttd/chat/ChatPlugin.java index cc4501a..eb92eef 100755 --- a/galaxy/src/main/java/com/alttd/chat/ChatPlugin.java +++ b/galaxy/src/main/java/com/alttd/chat/ChatPlugin.java @@ -5,9 +5,12 @@ import com.alttd.chat.config.Config; import com.alttd.chat.config.ServerConfig; import com.alttd.chat.database.DatabaseConnection; import com.alttd.chat.handler.ChatHandler; +import com.alttd.chat.listeners.BookListener; import com.alttd.chat.listeners.ChatListener; import com.alttd.chat.listeners.PlayerListener; import com.alttd.chat.listeners.PluginMessage; +import com.alttd.chat.nicknames.Nicknames; +import com.alttd.chat.nicknames.NicknamesEvents; import com.alttd.chat.objects.channels.Channel; import com.alttd.chat.objects.channels.CustomChannel; import com.alttd.chat.util.ALogger; @@ -38,7 +41,7 @@ public class ChatPlugin extends JavaPlugin { chatHandler = new ChatHandler(); DatabaseConnection.initialize(); serverConfig = new ServerConfig(Bukkit.getServerName()); - registerListener(new PlayerListener(), new ChatListener()); + registerListener(new PlayerListener(), new ChatListener(), new BookListener()); if(serverConfig.GLOBALCHAT) { registerCommand("globalchat", new GlobalChat()); registerCommand("toggleglobalchat", new ToggleGlobalChat()); @@ -53,6 +56,7 @@ public class ChatPlugin extends JavaPlugin { registerCommand("chatclear", new ChatClear()); // registerCommand("chatparty", new ChatParty()); registerCommand("p", new PartyChat()); + registerCommand("emotes", new Emotes()); for (Channel channel : Channel.getChannels()) { if (!(channel instanceof CustomChannel customChannel)) continue; this.getServer().getCommandMap().register(channel.getChannelName().toLowerCase(), new ChatChannel(customChannel)); @@ -61,6 +65,11 @@ public class ChatPlugin extends JavaPlugin { messageChannel = Config.MESSAGECHANNEL; getServer().getMessenger().registerOutgoingPluginChannel(this, messageChannel); getServer().getMessenger().registerIncomingPluginChannel(this, messageChannel, new PluginMessage()); + + NicknamesEvents nicknamesEvents = new NicknamesEvents(); + getServer().getMessenger().registerIncomingPluginChannel(this, messageChannel, nicknamesEvents); + getServer().getPluginManager().registerEvents(nicknamesEvents, this); + registerCommand("nick", new Nicknames()); } @Override diff --git a/galaxy/src/main/java/com/alttd/chat/commands/Emotes.java b/galaxy/src/main/java/com/alttd/chat/commands/Emotes.java new file mode 100644 index 0000000..711f26a --- /dev/null +++ b/galaxy/src/main/java/com/alttd/chat/commands/Emotes.java @@ -0,0 +1,33 @@ +package com.alttd.chat.commands; + +import com.alttd.chat.objects.EmoteList; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class Emotes implements CommandExecutor { + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if(!(sender instanceof Player player)) { // must be a player + return true; + } + EmoteList emoteList = EmoteList.getEmoteList(player.getUniqueId()); + if(args.length > 0) { + try { + int page = Integer.parseInt(args[0]); + emoteList.setPage(page); + } catch (NumberFormatException ignored) { + switch (args[0].toLowerCase()) { + case "next" -> emoteList.nextPage(); + case "prev", "previous" -> emoteList.prevPage(); + default -> {} + } + } + } + player.sendMessage(emoteList.showEmotePage()); + return false; + } +} diff --git a/galaxy/src/main/java/com/alttd/chat/handler/ChatHandler.java b/galaxy/src/main/java/com/alttd/chat/handler/ChatHandler.java index 614dd35..204d463 100755 --- a/galaxy/src/main/java/com/alttd/chat/handler/ChatHandler.java +++ b/galaxy/src/main/java/com/alttd/chat/handler/ChatHandler.java @@ -4,6 +4,7 @@ import com.alttd.chat.ChatPlugin; import com.alttd.chat.config.Config; import com.alttd.chat.managers.ChatUserManager; import com.alttd.chat.managers.RegexManager; +import com.alttd.chat.objects.ChatFilter; import com.alttd.chat.objects.ChatUser; import com.alttd.chat.objects.ModifiableString; import com.alttd.chat.objects.channels.CustomChannel; @@ -14,6 +15,7 @@ import com.google.common.io.ByteStreams; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; @@ -48,24 +50,14 @@ public class ChatHandler { target); return; // the message was blocked } - String updatedMessage = modifiableString.string(); - - if(!player.hasPermission("chat.format")) { - updatedMessage = Utility.stripTokens(updatedMessage); - } else { - updatedMessage = Utility.parseColors(updatedMessage); - } - - updatedMessage = Utility.formatText(updatedMessage); TagResolver placeholders = TagResolver.resolver( - Placeholder.component("message", Utility.parseMiniMessage(updatedMessage)), + Placeholder.component("message", parseMessageContent(player, modifiableString.string())), Placeholder.component("sendername", player.name()), Placeholder.parsed("receivername", target) ); - Component component = Utility.parseMiniMessage("", placeholders) - .replaceText(TextReplacementConfig.builder().once().matchLiteral("[i]").replacement(ChatHandler.itemComponent(player.getInventory().getItemInMainHand())).build()); + Component component = Utility.parseMiniMessage("", placeholders); sendPrivateMessage(player, target, "privatemessage", component); Component spymessage = Utility.parseMiniMessage(Config.MESSAGESPY, placeholders); @@ -88,19 +80,8 @@ public class ChatHandler { target); return; // the message was blocked } - String updatedMessage = modifiableString.string(); - if(!player.hasPermission("chat.format")) { - updatedMessage = Utility.stripTokens(updatedMessage); - } else { - updatedMessage = Utility.parseColors(updatedMessage); - } - - updatedMessage = Utility.formatText(updatedMessage); - - Component messageComponent = Utility.parseMiniMessage(updatedMessage) - .replaceText(TextReplacementConfig.builder().once().matchLiteral("[i]") - .replacement(ChatHandler.itemComponent(player.getInventory().getItemInMainHand())).build()); + Component messageComponent = parseMessageContent(player, modifiableString.string()); TagResolver placeholders = TagResolver.resolver( Placeholder.component("message", messageComponent), Placeholder.component("sendername", player.name()), @@ -149,18 +130,10 @@ public class ChatHandler { return; // the message was blocked } - String updatedMessage = modifiableString.string(); - if(!player.hasPermission("chat.format")) { - updatedMessage = Utility.stripTokens(updatedMessage); - } else { - updatedMessage = Utility.parseColors(updatedMessage); - } - - updatedMessage = Utility.formatText(updatedMessage); TagResolver placeholders = TagResolver.resolver( Placeholder.component("sender", senderName), Placeholder.component("prefix", prefix), - Placeholder.component("message", Utility.parseMiniMessage(updatedMessage)), + Placeholder.component("message", parseMessageContent(player, modifiableString.string())), Placeholder.parsed("server", Bukkit.getServerName()) ); @@ -190,21 +163,13 @@ public class ChatHandler { return; // the message was blocked } - String updatedMessage = modifiableString.string(); - if(!player.hasPermission("chat.format")) { - updatedMessage = Utility.stripTokens(updatedMessage); - } - - updatedMessage = Utility.formatText(updatedMessage); - TagResolver placeholders = TagResolver.resolver( Placeholder.component("sender", senderName), - Placeholder.component("message", Utility.parseMiniMessage(updatedMessage)), + Placeholder.component("message", parseMessageContent(player, modifiableString.string())), Placeholder.parsed("server", Bukkit.getServerName()), Placeholder.parsed("channel", channel.getChannelName()) ); - Component component = Utility.parseMiniMessage(channel.getFormat(), placeholders) - .replaceText(TextReplacementConfig.builder().once().matchLiteral("[i]").replacement(ChatHandler.itemComponent(player.getInventory().getItemInMainHand())).build()); + Component component = Utility.parseMiniMessage(channel.getFormat(), placeholders); if (channel.isProxy()) { sendChatChannelMessage(player, channel.getChannelName(), "chatchannel", component); @@ -349,4 +314,34 @@ public class ChatHandler { } // end - move these to util + private Component parseMessageContent(Player player, String rawMessage) { + TagResolver.Builder tagResolver = TagResolver.builder(); + + Utility.formattingPerms.forEach((perm, pair) -> { + if (player.hasPermission(perm)) { + tagResolver.resolver(pair.getX()); + } + }); + + MiniMessage miniMessage = MiniMessage.builder().tags(tagResolver.build()).build(); + Component component = miniMessage.deserialize(rawMessage); + for(ChatFilter chatFilter : RegexManager.getEmoteFilters()) { + component = component.replaceText( + TextReplacementConfig.builder() + .times(Config.EMOTELIMIT) + .match(chatFilter.getRegex()) + .replacement(chatFilter.getReplacement()).build()); + } + + component = component + .replaceText( + TextReplacementConfig.builder() + .once() + .matchLiteral("[i]") + .replacement(ChatHandler.itemComponent(player.getInventory().getItemInMainHand())) + .build()); + + return component; + + } } diff --git a/galaxy/src/main/java/com/alttd/chat/listeners/BookListener.java b/galaxy/src/main/java/com/alttd/chat/listeners/BookListener.java new file mode 100755 index 0000000..71236f4 --- /dev/null +++ b/galaxy/src/main/java/com/alttd/chat/listeners/BookListener.java @@ -0,0 +1,61 @@ +package com.alttd.chat.listeners; + +import com.alttd.chat.config.Config; +import com.alttd.chat.managers.RegexManager; +import com.alttd.chat.objects.ChatFilter; +import com.alttd.chat.util.Utility; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextReplacementConfig; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerEditBookEvent; +import org.bukkit.inventory.meta.BookMeta; + +import java.util.ArrayList; +import java.util.List; + +public class BookListener implements Listener { + + private final PlainTextComponentSerializer plainTextComponentSerializer = PlainTextComponentSerializer.plainText(); + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerEditBookEvent(PlayerEditBookEvent event) { + BookMeta bookMeta = event.getNewBookMeta(); + List pages = new ArrayList<>(); + for (Component component : bookMeta.pages()) { + Component formatComponent = Component.text("%message%"); + Component message = parseMessageContent(event.getPlayer(), plainTextComponentSerializer.serialize(component)); + pages.add(formatComponent.replaceText(TextReplacementConfig.builder().match("%message%").replacement(message).build())); + } + bookMeta.pages(pages); + event.setNewBookMeta(bookMeta); + } + + private Component parseMessageContent(Player player, String rawMessage) { + TagResolver.Builder tagResolver = TagResolver.builder(); + + Utility.formattingPerms.forEach((perm, pair) -> { + if (player.hasPermission(perm)) { + tagResolver.resolver(pair.getX()); + } + }); + + MiniMessage miniMessage = MiniMessage.builder().tags(tagResolver.build()).build(); + Component component = miniMessage.deserialize(rawMessage); + for(ChatFilter chatFilter : RegexManager.getEmoteFilters()) { + component = component.replaceText( + TextReplacementConfig.builder() + .times(Config.EMOTELIMIT) + .match(chatFilter.getRegex()) + .replacement(chatFilter.getReplacement()).build()); + } + return component; + + } + +} \ No newline at end of file diff --git a/galaxy/src/main/java/com/alttd/chat/listeners/ChatListener.java b/galaxy/src/main/java/com/alttd/chat/listeners/ChatListener.java index 958bb40..19d2526 100755 --- a/galaxy/src/main/java/com/alttd/chat/listeners/ChatListener.java +++ b/galaxy/src/main/java/com/alttd/chat/listeners/ChatListener.java @@ -5,21 +5,25 @@ import com.alttd.chat.config.Config; import com.alttd.chat.handler.ChatHandler; import com.alttd.chat.managers.ChatUserManager; import com.alttd.chat.managers.RegexManager; +import com.alttd.chat.objects.ChatFilter; import com.alttd.chat.objects.ChatUser; import com.alttd.chat.objects.ModifiableString; import com.alttd.chat.objects.Toggleable; import com.alttd.chat.util.ALogger; import com.alttd.chat.util.GalaxyUtility; import com.alttd.chat.util.Utility; +import io.papermc.paper.event.player.AsyncChatCommandDecorateEvent; +import io.papermc.paper.event.player.AsyncChatDecorateEvent; import io.papermc.paper.event.player.AsyncChatEvent; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; +import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; -import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.jetbrains.annotations.NotNull; @@ -28,6 +32,29 @@ import java.util.stream.Collectors; public class ChatListener implements Listener { + private final PlainTextComponentSerializer plainTextComponentSerializer = PlainTextComponentSerializer.plainText(); + + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onChatCommandDecorate(AsyncChatCommandDecorateEvent event) { + if (event.player() == null) return; + + Component formatComponent = Component.text("%message%"); + Component message = parseMessageContent(event.player(), plainTextComponentSerializer.serialize(event.originalMessage())); + + event.result(formatComponent.replaceText(TextReplacementConfig.builder().match("%message%").replacement(message).build())); + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onChatDecorate(AsyncChatDecorateEvent event) { + if (event.player() == null) return; + + Component formatComponent = Component.text("%message%"); + Component message = parseMessageContent(event.player(), plainTextComponentSerializer.serialize(event.originalMessage())); + + event.result(formatComponent.replaceText(TextReplacementConfig.builder().match("%message%").replacement(message).build())); + } + @EventHandler(ignoreCancelled = true) public void onPlayerChat(AsyncChatEvent event) { event.setCancelled(true); //Always cancel the event because we do not want to deal with Microsoft's stupid bans @@ -43,7 +70,6 @@ public class ChatListener implements Listener { } Player player = event.getPlayer(); -// ChatUser user = ChatUserManager.getChatUser(player.getUniqueId()); Set receivers = event.viewers().stream().filter(audience -> audience instanceof Player) .map(audience -> (Player) audience) @@ -61,40 +87,57 @@ public class ChatListener implements Listener { ""); return; // the message was blocked } - message = modifiableString.string(); - if(!player.hasPermission("chat.format")) { - message = Utility.stripTokens(message); - } else { - message = Utility.parseColors(message); - } - Component component = Utility.parseMiniMessage(Utility.formatText(message)); - component = component.replaceText( - TextReplacementConfig.builder() - .once() - .matchLiteral("[i]") - .replacement(ChatHandler.itemComponent(player.getInventory().getItemInMainHand())) - .build()); - - component = render(player, component); + input = render(player, plainTextComponentSerializer.deserialize(modifiableString.string())); for (Player receiver : receivers) { - receiver.sendMessage(component); + receiver.sendMessage(input); } - ALogger.info(PlainTextComponentSerializer.plainText().serialize(component)); + ALogger.info(PlainTextComponentSerializer.plainText().serialize(input)); } public @NotNull Component render(@NotNull Player player, @NotNull Component message) { ChatUser user = ChatUserManager.getChatUser(player.getUniqueId()); TagResolver placeholders = TagResolver.resolver( Placeholder.component("sender", user.getDisplayName()), -// Placeholder.component("sendername", player.name()), + Placeholder.parsed("sendername", player.getName()), Placeholder.component("prefix", user.getPrefix()), Placeholder.component("prefixall", user.getPrefixAll()), Placeholder.component("staffprefix", user.getStaffPrefix()), Placeholder.component("message", message) ); - return Utility.parseMiniMessage(Config.CHATFORMAT.replaceAll("", player.getName()), placeholders); + return Utility.parseMiniMessage(Config.CHATFORMAT, placeholders); + } + + private Component parseMessageContent(Player player, String rawMessage) { + TagResolver.Builder tagResolver = TagResolver.builder(); + + Utility.formattingPerms.forEach((perm, pair) -> { + if (player.hasPermission(perm)) { + tagResolver.resolver(pair.getX()); + } + }); + + MiniMessage miniMessage = MiniMessage.builder().tags(tagResolver.build()).build(); + Component component = miniMessage.deserialize(rawMessage); + for(ChatFilter chatFilter : RegexManager.getEmoteFilters()) { + component = component.replaceText( + TextReplacementConfig.builder() + .times(Config.EMOTELIMIT) + .match(chatFilter.getRegex()) + .replacement(chatFilter.getReplacement()).build()); + } + + component = component + .replaceText( + TextReplacementConfig.builder() + .once() + .matchLiteral("[i]") + .replacement(ChatHandler.itemComponent(player.getInventory().getItemInMainHand())) + .build()); + + return component; + } } \ No newline at end of file diff --git a/galaxy/src/main/java/com/alttd/chat/listeners/PlayerListener.java b/galaxy/src/main/java/com/alttd/chat/listeners/PlayerListener.java index 02a1f97..456d676 100755 --- a/galaxy/src/main/java/com/alttd/chat/listeners/PlayerListener.java +++ b/galaxy/src/main/java/com/alttd/chat/listeners/PlayerListener.java @@ -23,7 +23,9 @@ public class PlayerListener implements Listener { @EventHandler private void onPlayerLogin(PlayerJoinEvent event) { - UUID uuid = event.getPlayer().getUniqueId(); + Player player = event.getPlayer(); + GalaxyUtility.addAdditionalChatCompletions(player); + UUID uuid = player.getUniqueId(); Toggleable.disableToggles(uuid); ChatUser user = ChatUserManager.getChatUser(uuid); if(user != null) return; diff --git a/galaxy/src/main/java/com/alttd/chat/nicknames/NickUtilities.java b/galaxy/src/main/java/com/alttd/chat/nicknames/NickUtilities.java new file mode 100644 index 0000000..a8043aa --- /dev/null +++ b/galaxy/src/main/java/com/alttd/chat/nicknames/NickUtilities.java @@ -0,0 +1,214 @@ +package com.alttd.chat.nicknames; + +import com.alttd.chat.ChatPlugin; +import com.alttd.chat.config.Config; +import com.alttd.chat.database.Queries; +import com.alttd.chat.objects.Nick; +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteStreams; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.awt.*; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.UUID; + +public class NickUtilities +{ + public static String stringRegen; + + public static String applyColor(String message) { + ChatColor hexColor1 = null; + ChatColor hexColor2; + StringBuilder stringBuilder = new StringBuilder(); + message = ChatColor.translateAlternateColorCodes('&', message); + boolean startsWithColor = false; + boolean lastColorMatters = false; + + if (message.matches(".*" + NickUtilities.stringRegen + ".*")) { + String[] split = message.split(NickUtilities.stringRegen); + + ArrayList list = new ArrayList<>(); + int nextIndex = 0; + if (message.indexOf("}") <= 11) { + startsWithColor = true; + list.add(message.substring(0, message.indexOf("}") + 1)); + } + for (String s : split) { + nextIndex += s.length(); + int tmp = message.indexOf("}", nextIndex); + if (tmp < message.length() && tmp>=0) { + list.add(message.substring(nextIndex, tmp + 1)); + nextIndex = tmp + 1; + } + } + + int i; + boolean firstLoop = true; + if (startsWithColor) { + i = -1; + } else { + i = 0; + stringBuilder.append(split[i]); + } + + for (String s : list) { + boolean lesser = s.contains("<"); + boolean bigger = s.contains(">"); + + if (bigger && lesser) { + hexColor2 = ChatColor.of(s.substring(1, s.length() - 3)); + } else if (bigger || lesser) { + hexColor2 = ChatColor.of(s.substring(1, s.length() - 2)); + } else { + hexColor2 = ChatColor.of(s.substring(1, s.length() -1)); + } + + if (firstLoop) { + lastColorMatters = bigger; + hexColor1 = hexColor2; + firstLoop = false; + i++; + continue; + } + + if (lesser && lastColorMatters) { + stringBuilder.append(hexGradient(hexColor1.getColor(), hexColor2.getColor(), split[i])); + } else { + stringBuilder.append(hexColor1).append(split[i]); + } + + hexColor1 = hexColor2; + lastColorMatters = bigger; + i++; + } + if (split.length > i){ + stringBuilder.append(hexColor1).append(split[i]); + } + } + return stringBuilder.length()==0 ? message : stringBuilder.toString(); + } + + public static String removeAllColors(String string) { + + for (final String colorCodes : Config.NICK_ALLOWED_COLOR_CODESLIST) { + string = string.replace(colorCodes, ""); + } + + return string.replaceAll("\\{#[A-Fa-f0-9]{6}(<)?(>)?}", ""); + } + + static { + NickUtilities.stringRegen = "\\{#[A-Fa-f0-9]{6}(<)?(>)?}"; + } + + public static String hexGradient(Color color1, Color color2, String text){ + double r = color1.getRed(); + double g = color1.getGreen(); + double b = color1.getBlue(); + + double rDifference = (color1.getRed() - color2.getRed()) / ((double) text.length() - 1); + double gDifference = (color1.getGreen() - color2.getGreen()) / ((double) text.length() - 1); + double bDifference = (color1.getBlue() - color2.getBlue()) / ((double) text.length() - 1); + + StringBuilder stringBuilder = new StringBuilder(); + char[] chars = text.toCharArray(); + for (int i = 0; i < text.length(); i++) { + if (i > 0) { + r = r - rDifference; + g = g - gDifference; + b = b - bDifference; + } + stringBuilder.append(ChatColor.of(new Color((int) r, (int) g, (int) b))).append(chars[i]); + } + + return stringBuilder.toString(); + } + + public static void updateCache() { + if (!Nicknames.getInstance().nickCacheUpdate.isEmpty()){ + Nicknames.getInstance().nickCacheUpdate.forEach(uuid ->{ + Nick nick = Queries.getNick(uuid); + if (nick == null){ + Nicknames.getInstance().NickCache.remove(uuid); + } else { + Nicknames.getInstance().NickCache.put(uuid, nick); + } + }); + } + } + + public static boolean validNick(Player sender, OfflinePlayer target, String nickName) { + if (noBlockedCodes(nickName)) { + + String cleanNick = NickUtilities.removeAllColors(nickName); + + if (cleanNick.length() >= 3 && cleanNick.length() <= 16) { + + if (cleanNick.matches("[a-zA-Z0-9_]*") && nickName.length()<=192) {//192 is if someone puts {#xxxxxx<>} in front of every letter + + if (!cleanNick.equalsIgnoreCase(target.getName())){ + for (Nick nick : Nicknames.getInstance().NickCache.values()){ + if (!nick.getUuid().equals(target.getUniqueId()) + && ((nick.getCurrentNickNoColor() != null && nick.getCurrentNickNoColor().equalsIgnoreCase(cleanNick)) + || (nick.getNewNickNoColor() != null && nick.getNewNickNoColor().equalsIgnoreCase(cleanNick)))){ + UUID uuid = nick.getUuid(); + UUID uniqueId = target.getUniqueId(); + if (uniqueId.equals(uuid)){ + ChatPlugin.getInstance().getLogger().info(uuid + " " + uniqueId); + } + sender.sendMessage(applyColor(Config.NICK_TAKEN)); + return false; + } + } + } + + return true; + + } else { + sender.sendMessage(applyColor(Config.NICK_INVALID_CHARACTERS)); + } + } else { + sender.sendMessage(applyColor(Config.NICK_INVALID_LENGTH)); + } + } else { + sender.sendMessage(applyColor(Config.NICK_BLOCKED_COLOR_CODES)); + } + return false; + } + + public static boolean noBlockedCodes(final String getNick) { + for (final String blockedCodes : Config.NICK_BLOCKED_COLOR_CODESLIST) { + if (getNick.contains(blockedCodes)) { + return false; + } + } + return true; + } + + public static void bungeeMessageHandled(UUID uniqueId, Player player, String channel) { + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + +// out.writeUTF("Forward"); // So BungeeCord knows to forward it +// out.writeUTF("ALL"); + out.writeUTF("NickName" + channel); // The channel name to check if this your data + + ByteArrayOutputStream msgbytes = new ByteArrayOutputStream(); + DataOutputStream msgout = new DataOutputStream(msgbytes); + try { + msgout.writeUTF(uniqueId.toString()); + } catch (IOException exception){ + exception.printStackTrace(); + return; + } + byte[] bytes = msgbytes.toByteArray(); + out.writeShort(bytes.length); + out.write(bytes); + + player.sendPluginMessage(ChatPlugin.getInstance(), Config.MESSAGECHANNEL, out.toByteArray()); + } +} diff --git a/galaxy/src/main/java/com/alttd/chat/nicknames/Nicknames.java b/galaxy/src/main/java/com/alttd/chat/nicknames/Nicknames.java new file mode 100644 index 0000000..866fed2 --- /dev/null +++ b/galaxy/src/main/java/com/alttd/chat/nicknames/Nicknames.java @@ -0,0 +1,410 @@ +package com.alttd.chat.nicknames; + +import com.alttd.chat.ChatAPI; +import com.alttd.chat.ChatPlugin; +import com.alttd.chat.config.Config; +import com.alttd.chat.database.Queries; +import com.alttd.chat.events.NickEvent; +import com.alttd.chat.managers.ChatUserManager; +import com.alttd.chat.objects.ChatUser; +import com.alttd.chat.objects.Nick; +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteStreams; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.luckperms.api.LuckPerms; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.NotNull; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.sql.SQLException; +import java.util.*; + +public class Nicknames implements CommandExecutor, TabCompleter { + + static Nicknames instance; + HashMap NickCache; + ArrayList nickCacheUpdate; + + public Nicknames() { + instance = this; + NickCache = new HashMap<>(); + nickCacheUpdate = new ArrayList<>(); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, String[] args) { + if (sender instanceof Player player) { + if (args.length == 0) { + sender.sendMessage(format(helpMessage(sender, HelpType.ALL))); + return true; + } + switch (args[0].toLowerCase()) { + case "set": + if (args.length == 2 && hasPermission(sender, "utility.nick.set")) { + handleNick(player, player, args[1]); + } else if (args.length == 3 && hasPermission(sender, "utility.nick.set.others")) { + OfflinePlayer offlinePlayer = sender.getServer().getOfflinePlayer(args[1]); + + if (offlinePlayer.isOnline() || offlinePlayer.hasPlayedBefore()) { + handleNick(player, offlinePlayer, args[2]); + } else { + sender.sendMessage(format(helpMessage(sender, HelpType.SET_OTHERS))); + } + } else if (args.length > 3) { + sender.sendMessage(format(helpMessage(sender, HelpType.SET_SELF, HelpType.SET_OTHERS))); + } + break; + case "review": + if (args.length == 1 && hasPermission(sender, "utility.nick.review")) { + NicknamesGui nicknamesGui = new NicknamesGui(); + ChatPlugin.getInstance().getServer().getPluginManager().registerEvents(nicknamesGui, ChatPlugin.getInstance()); + nicknamesGui.openInventory(player); + } else { + sender.sendMessage(format(helpMessage(sender, HelpType.REVIEW))); + } + break; + case "request": + if (args.length == 2 && hasPermission(sender, "utility.nick.request")) { + new BukkitRunnable() { + @Override + public void run() { + handleNickRequest(player, args[1]); + } + }.runTaskAsynchronously(ChatPlugin.getInstance()); + } else { + sender.sendMessage(format(helpMessage(sender, HelpType.REQUEST))); + } + break; + case "try": + if (args.length == 2 && hasPermission(sender, "utility.nick.try")) { + LuckPerms api = ChatAPI.get().getLuckPerms(); + if (api != null) { + if (NickUtilities.validNick(player, player, args[1])) { + sender.sendMessage(format(Config.NICK_TRYOUT + .replace("%prefix", api.getUserManager().getUser(player.getUniqueId()) + .getCachedData().getMetaData().getPrefix()) // TODO pull this from chatuser? + .replace("%nick%", args[1]))); + } + } else { + sender.sendMessage(format(Config.NICK_NO_LUCKPERMS)); + } + } else { + sender.sendMessage(format(helpMessage(sender, HelpType.TRY))); + } + break; + case "current": + if (hasPermission(sender, "utility.nick.current")) { + ChatUser chatUser = ChatUserManager.getChatUser(player.getUniqueId()); + TagResolver placeholders = TagResolver.resolver( + Placeholder.component("nickname", chatUser.getDisplayName()), + Placeholder.parsed("currentnickname", chatUser.getNickNameString()) + ); + player.sendMiniMessage(Config.NICK_CURRENT, placeholders); + } + break; + case "help": + sender.sendMessage(format(helpMessage(sender, HelpType.ALL) + + "For more info on nicknames and how to use rgb colors go to: &bhttps://alttd.com/nicknames&f")); + break; + default: + sender.sendMessage(format(helpMessage(sender, HelpType.ALL))); + } + } else { + sender.sendMessage("Console commands are disabled."); + } + return true; + } + + @Override + public List onTabComplete(CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + List completions = new ArrayList<>(); + if (!sender.hasPermission("utility.nick")) return completions; + + if (args.length == 1) { + List choices = new ArrayList<>(); + if (sender.hasPermission("utility.nick.set")) { + choices.add("set"); + } + if (sender.hasPermission("utility.nick.review")) { + choices.add("review"); + } + if (sender.hasPermission("utility.nick.request")) { + choices.add("request"); + } + if (sender.hasPermission("utility.nick.try")) { + choices.add("try"); + } + if (sender.hasPermission("utility.nick.current")) { + choices.add("current"); + } + choices.add("help"); + + for (String s : choices) { + if (s.startsWith(args[0])) { + completions.add(s); + } + } + } else if (args.length == 2) { + if (args[0].equalsIgnoreCase("set")) { + List choices = new ArrayList<>(); + List onlinePlayers = new ArrayList<>(); + Bukkit.getOnlinePlayers().forEach(a -> onlinePlayers.add(a.getName())); + + if (sender.hasPermission("utility.nick.set.others")) { + choices.addAll(onlinePlayers); + } + + for (String s : choices) { + if (s.startsWith(args[1])) { + completions.add(s); + } + } + } + } + return completions; + } + + private void handleNickRequest(Player player, String nickName) { + if (!NickUtilities.validNick(player, player, nickName)) { + return; + } + + NickUtilities.updateCache(); + UUID uniqueId = player.getUniqueId(); + + if (NickCache.containsKey(uniqueId)) { + Nick nick = NickCache.get(uniqueId); + long timeSinceLastChange = new Date().getTime() - nick.getLastChangedDate(); + long waitTime = Config.NICK_WAIT_TIME; + if (timeSinceLastChange > waitTime || player.hasPermission("utility.nick.admin")) { + if (nick.hasRequest()) { + player.sendMessage(format(Config.NICK_REQUEST_PLACED + .replace("%oldRequestedNick%", nick.getNewNick()) + .replace("%newRequestedNick%", nickName))); + } + nick.setNewNick(nickName); + nick.setRequestedDate(new Date().getTime()); + } else { + player.sendMessage(format(Config.NICK_TOO_SOON + .replace("%time%", formatTime((timeSinceLastChange-waitTime)*-1)))); + return; + } + } else { + NickCache.put(uniqueId, new Nick(uniqueId, null, 0, nickName, new Date().getTime())); + } + Queries.newNicknameRequest(uniqueId, nickName); + bungeeMessageRequest(player); + player.sendMessage(format(Config.NICK_REQUESTED + .replace("%nick%", nickName))); + } + + private void bungeeMessageRequest(Player player) { + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + + UUID uniqueId = player.getUniqueId(); + +// out.writeUTF("Forward"); // So BungeeCord knows to forward it +// out.writeUTF("ALL"); + out.writeUTF("NickNameRequest"); // The channel name to check if this your data + + ByteArrayOutputStream msgbytes = new ByteArrayOutputStream(); + DataOutputStream msgout = new DataOutputStream(msgbytes); + try { + msgout.writeUTF(uniqueId.toString()); + } catch (IOException exception) { + exception.printStackTrace(); + return; + } + byte[] bytes = msgbytes.toByteArray(); + out.writeShort(bytes.length); + out.write(bytes); + + player.sendPluginMessage(ChatPlugin.getInstance(), Config.MESSAGECHANNEL, out.toByteArray()); + + Nicknames.getInstance().nickCacheUpdate.add(uniqueId); + } + + private String formatTime(long timeInMillis) { + long second = (timeInMillis / 1000) % 60; + long minute = (timeInMillis / (1000 * 60)) % 60; + long hour = (timeInMillis / (1000 * 60 * 60)) % 24; + long days = (timeInMillis / (1000 * 60 * 60 * 24)); + + StringBuilder stringBuilder = new StringBuilder(); + if (days!=0) { + stringBuilder.append(days).append(" days "); + } + if (days!=0 || hour!=0) { + stringBuilder.append(hour).append(" hours "); + } + if (days!=0 || hour!=0 || minute != 0) { + stringBuilder.append(minute).append(" minutes and "); + } + stringBuilder.append(second).append(" seconds"); + return stringBuilder.toString(); + } + + private void handleNick(Player sender, OfflinePlayer target, final String nickName) { + if (nickName.equalsIgnoreCase("off")) { + + try { + if (target.isOnline()) { + resetNick(target.getPlayer()); + } + Queries.removePlayerFromDataBase(target.getUniqueId()); + NickCache.remove(target.getUniqueId()); + nickCacheUpdate.add(target.getUniqueId()); + } catch (SQLException e) { + e.printStackTrace(); + } + + if (!sender.equals(target)) { + sender.sendMessage(format(Config.NICK_RESET_OTHERS + .replace("%player%", target.getName()))); + } + + if (target.isOnline() && target.getPlayer() != null) { + target.getPlayer().sendMessage(format(Config.NICK_RESET)); + } + + NickEvent nickEvent = new NickEvent(sender.getName(), target.getName(), null, NickEvent.NickEventType.RESET); + nickEvent.callEvent(); + + } else if (NickUtilities.validNick(sender, target, nickName)) { + if (target.isOnline()) { + setNick(target.getUniqueId(), nickName); + } else { + NickUtilities.bungeeMessageHandled(target.getUniqueId(), sender, "Set"); + } + + Queries.setNicknameInDatabase(target.getUniqueId(), nickName); + NickEvent nickEvent = new NickEvent(sender.getName(), target.getName(), nickName, NickEvent.NickEventType.SET); + nickEvent.callEvent(); + + if (NickCache.containsKey(target.getUniqueId())) { + Nick nick = NickCache.get(target.getUniqueId()); + nick.setCurrentNick(nickName); + nick.setLastChangedDate(new Date().getTime()); + setNick(target.getUniqueId(), nickName); + } else { + NickCache.put(target.getUniqueId(), new Nick(target.getUniqueId(), nickName, new Date().getTime())); + } + + if (!sender.equals(target)) { + sender.sendMessage(format(Config.NICK_CHANGED_OTHERS + .replace("%targetplayer%", target.getName()) + .replace("%nickname%", nickName))); + if (target.isOnline()) { + target.getPlayer().sendMessage(format(Config.NICK_TARGET_NICK_CHANGE + .replace("%nickname%", getNick(target.getPlayer())) + .replace("%sendernick%", getNick(sender)) + .replace("%player%", target.getName()))); + } + } else if (target.isOnline()) { + target.getPlayer().sendMessage(format(Config.NICK_CHANGED + .replace("%nickname%", getNick(target.getPlayer())))); + } + } + } + + private String helpMessage(final CommandSender sender, final HelpType... helpTypes) { + StringBuilder message = new StringBuilder(); + for (HelpType helpType : helpTypes) { + if (helpType.equals(HelpType.ALL)) { + return helpMessage(sender, helpType); + } + message.append(helpMessage(sender, helpType)); + } + return message.toString(); + } + + private String helpMessage(CommandSender sender, HelpType type) { + StringBuilder message = new StringBuilder(); + switch (type) { + case ALL: + message.append(helpMessage(sender, HelpType.SET_SELF)); + message.append(helpMessage(sender, HelpType.SET_OTHERS)); + message.append(helpMessage(sender, HelpType.REQUEST)); + message.append(helpMessage(sender, HelpType.REVIEW)); + message.append(helpMessage(sender, HelpType.TRY)); + break; + case SET_SELF: + if (sender.hasPermission("utility.nick.set")) { + message.append("&6/nick set &f - Sets your nickname to the specified name.\n"); + } + break; + case SET_OTHERS: + if (sender.hasPermission("utility.nick.set.others")) { + message.append("&6/nick set &f - Sets the specified user's nickname to the specified name.\n"); + } + break; + case REQUEST: + if (sender.hasPermission("utility.nick.request")) { + message.append("&6/nick request &f - Requests a username to be reviewed by staff.\n" + + " &7Try using &8/nick try &7 to see if you like the name, you can only change it once per day!\n"); + } + break; + case REVIEW: + if (sender.hasPermission("utility.nick.review")) { + message.append("&6/nick review&f - Opens the nickname review GUI (left click to accept a nick, right click to deny it)\n"); + } + break; + case TRY: + if (sender.hasPermission("utility.nick.try")) { + message.append("&6/nick try &f - Shows you what your nickname will look like in chat.\n"); + } + } + return message.toString(); + } + + private boolean hasPermission(CommandSender sender, String permission) { + if (!sender.hasPermission(permission)) { + sender.sendMessage(format(Config.NO_PERMISSION)); + return false; + } + return true; + } + + public void resetNick(final Player player) { + ChatUser user = ChatUserManager.getChatUser(player.getUniqueId()); + user.setDisplayName(player.getName()); + } + + public String getNick(final Player player) { + ChatUser user = ChatUserManager.getChatUser(player.getUniqueId()); + return user.getNickNameString(); + } + + public void setNick(final UUID uuid, final String nickName) { + ChatUser user = ChatUserManager.getChatUser(uuid); + user.setDisplayName(nickName); + } + + public static String format(final String m) { + return NickUtilities.applyColor(m); + } + + public static Nicknames getInstance() { + return Nicknames.instance; + } + + private enum HelpType { + ALL, + SET_SELF, + SET_OTHERS, + REVIEW, + REQUEST, + TRY + } +} diff --git a/galaxy/src/main/java/com/alttd/chat/nicknames/NicknamesEvents.java b/galaxy/src/main/java/com/alttd/chat/nicknames/NicknamesEvents.java new file mode 100644 index 0000000..f255ab2 --- /dev/null +++ b/galaxy/src/main/java/com/alttd/chat/nicknames/NicknamesEvents.java @@ -0,0 +1,192 @@ +package com.alttd.chat.nicknames; + +import com.alttd.chat.ChatPlugin; +import com.alttd.chat.config.Config; +import com.alttd.chat.database.Queries; +import com.alttd.chat.objects.Nick; +import com.alttd.chat.util.ALogger; +import com.google.common.io.ByteArrayDataInput; +import com.google.common.io.ByteStreams; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.plugin.messaging.PluginMessageListener; +import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.NotNull; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.util.UUID; + +public class NicknamesEvents implements Listener, PluginMessageListener { + + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onPlayerJoin(PlayerJoinEvent e) { + + new BukkitRunnable() { + @Override + public void run() { + if (Nicknames.instance.NickCache.isEmpty()) { + Queries.getNicknamesList().forEach(nick -> Nicknames.instance.NickCache.put(nick.getUuid(), nick)); + } + + final Player player = e.getPlayer(); + final Nick nick = Queries.getNick(player.getUniqueId()); + + if (nick == null) { + Nicknames.getInstance().resetNick(player); + return; + } + + String nickName = nick.getCurrentNick(); + String strippedNick = Nicknames.getInstance().getNick(player); +// try { +// strippedNick = MiniMessage.miniMessage().stripTokens(Nicknames.getInstance().getNick(player)); +// } catch (NullPointerException ignored) { +// } +// final String strippedNick = CMIChatColor.stripColor(Nicknames.getInstance().getNick(player)); + + //final String cmiNick = Util.CMIChatColor.deColorize(Nicknames.getInstance().getNick(player)); + + if (nickName == null) { + Nicknames.getInstance().resetNick(player); + } else if (!nickName.equals(strippedNick)) { + Nicknames.getInstance().setNick(player.getUniqueId(), nickName); + } + + Nicknames.getInstance().NickCache.put(e.getPlayer().getUniqueId(), nick); + + if (player.hasPermission("utility.nick.review")) { + int i = 0; + for (Nick iNick : Nicknames.getInstance().NickCache.values()) { + if (iNick.hasRequest()) { + i++; + } + } + + if (i > 0) { + player.sendMessage(format(Config.NICK_REQUESTS_ON_LOGIN + .replace("%amount%", String.valueOf(i)))); + } + } + } + }.runTaskAsynchronously(ChatPlugin.getInstance()); + } + + @Override + public void onPluginMessageReceived(String channel, @NotNull Player player, byte[] message) { + if (!channel.equals(Config.MESSAGECHANNEL)) { + return; + } + + ByteArrayDataInput in = ByteStreams.newDataInput(message); + String subChannel = in.readUTF(); + ALogger.info(channel + ": " + subChannel); + if (!subChannel.equals("NickNameRequest") && !subChannel.equals("NickNameAccepted") + && !subChannel.equals("NickNameDenied") && !subChannel.equals("NickNameSet")) { + return; + } + UUID playerUUID; + OfflinePlayer offlinePlayer; + String name; + try { + short len = in.readShort(); + byte[] msgbytes = new byte[len]; + in.readFully(msgbytes); + + DataInputStream msgin = new DataInputStream(new ByteArrayInputStream(msgbytes)); + playerUUID = UUID.fromString(msgin.readUTF()); + offlinePlayer = ChatPlugin.getInstance().getServer().getOfflinePlayer(playerUUID); + name = offlinePlayer.getName() == null ? playerUUID.toString() : offlinePlayer.getName(); + + } catch (Exception e) { + e.printStackTrace(); + return; + } + + switch (subChannel) { + case "NickNameRequest": + String notification = NickUtilities.applyColor(Config.NICK_REQUEST_NEW + .replace("%player%", name)); + TextComponent component = new TextComponent(TextComponent.fromLegacyText(NickUtilities.applyColor(notification))); + component.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/nick review")); + component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, + new ComponentBuilder(NickUtilities.applyColor("&6Click this text to review the request!")).create())); + ChatPlugin.getInstance().getServer().getOnlinePlayers().forEach(p -> { + if (p.hasPermission("utility.nick.review")) { + p.sendMessage(component); + } + }); + Nicknames.getInstance().nickCacheUpdate.add(playerUUID); + + if (offlinePlayer.isOnline()) { + Nick nick = Queries.getNick(playerUUID); + if (nick != null && nick.getCurrentNick() != null) { + Nicknames.getInstance().setNick(offlinePlayer.getUniqueId(), nick.getCurrentNick()); + } + } + break; + case "NickNameAccepted": + final String messageAccepted = ChatColor.GREEN + name + "'s nickname was accepted!"; + ChatPlugin.getInstance().getServer().getOnlinePlayers().forEach(p -> { + if (p.hasPermission("utility.nick.review")) { + p.sendMessage(messageAccepted); + } + }); + //No break on purpose + case "NickNameSet": + Nicknames.getInstance().nickCacheUpdate.add(playerUUID); + if (offlinePlayer.isOnline()) { + Nick nick = Queries.getNick(playerUUID); + Player target = Bukkit.getPlayer(playerUUID); + if (target != null && nick != null && nick.getCurrentNick() != null) { + Nicknames.getInstance().setNick(target.getUniqueId(), nick.getCurrentNick()); + target.sendMessage(format(Config.NICK_CHANGED + .replace("%nickname%", nick.getCurrentNick()))); + } + } + break; + case "NickNameDenied": + final String messageDenied = ChatColor.RED + name + "'s nickname was denied!"; + Nick nick = Nicknames.getInstance().NickCache.get(playerUUID); + + ChatPlugin.getInstance().getServer().getOnlinePlayers().forEach(p -> { + if (p.hasPermission("utility.nick.review")) { + p.sendMessage(messageDenied); + } + }); + + if (nick.getCurrentNick() == null) { + Nicknames.getInstance().NickCache.remove(playerUUID); + } else { + nick.setNewNick(null); + nick.setRequestedDate(0); + + Nicknames.getInstance().NickCache.put(playerUUID, nick); + } + + if (offlinePlayer.isOnline()) { + Player target = Bukkit.getPlayer(playerUUID); + + if (target == null) break; + target.sendMessage(format(Config.NICK_NOT_CHANGED + .replace("%nickname%", nick.getCurrentNick()))); + } + break; + } + } + + public static String format(final String m) { + return NickUtilities.applyColor(m); + } +} diff --git a/galaxy/src/main/java/com/alttd/chat/nicknames/NicknamesGui.java b/galaxy/src/main/java/com/alttd/chat/nicknames/NicknamesGui.java new file mode 100644 index 0000000..597c03b --- /dev/null +++ b/galaxy/src/main/java/com/alttd/chat/nicknames/NicknamesGui.java @@ -0,0 +1,285 @@ +package com.alttd.chat.nicknames; + +import com.alttd.chat.ChatPlugin; +import com.alttd.chat.config.Config; +import com.alttd.chat.database.Queries; +import com.alttd.chat.events.NickEvent; +import com.alttd.chat.objects.Nick; +import com.alttd.chat.util.Utility; +import net.kyori.adventure.text.Component; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryDragEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +import static com.alttd.chat.nicknames.Nicknames.format; + +public class NicknamesGui implements Listener { + + private final Inventory inv; + private final int currentPage; + + public NicknamesGui() { + // Create a new inventory, with no owner (as this isn't a real inventory) + inv = Bukkit.createInventory(null, 36, Utility.parseMiniMessage("Nicknames GUI")); + + // Put the items into the inventory + currentPage = 1; + setItems(currentPage); + } + + public void setItems(int currentPage) { + new BukkitRunnable() { + @Override + public void run() { + inv.clear(); + NickUtilities.updateCache(); + boolean hasNextPage = false; + int i = (currentPage - 1) * 27; //TODO set to 1 or 2 to test + int limit = i / 27; + + for (Nick nick : Nicknames.getInstance().NickCache.values()) { + if (nick.hasRequest()) { + if (limit >= i / 27) { + inv.setItem(i % 27, createPlayerSkull(nick, Config.NICK_ITEM_LORE)); + i++; + } else { + hasNextPage = true; + break; + } + } + } + + if (currentPage != 1) { + inv.setItem(28, createGuiItem(Material.PAPER, "§bPrevious page", + "§aCurrent page: %page%".replace("%page%", String.valueOf(currentPage)), + "§aPrevious page: %previousPage%".replace("%previousPage%", String.valueOf(currentPage - 1)))); + } + + if (hasNextPage) { + inv.setItem(36, createGuiItem(Material.PAPER, "§bNext page", + "§aCurrent page: %page%".replace("%page%", String.valueOf(currentPage)), + "§aNext page: §b%nextPage%".replace("%nextPage%", String.valueOf(currentPage + 1)))); + } + } + }.runTaskAsynchronously(ChatPlugin.getInstance()); + } + + private ItemStack createPlayerSkull(Nick nick, List lore) { + ItemStack playerHead = new ItemStack(Material.PLAYER_HEAD); + SkullMeta meta = (SkullMeta) playerHead.getItemMeta(); + OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(nick.getUuid()); + + meta.setOwningPlayer(offlinePlayer); + meta.setDisplayName(offlinePlayer.getName()); + + lore.replaceAll(s -> format(s + .replace("%newNick%", nick.getNewNick()) + .replace("%oldNick%", nick.getCurrentNick() == null ? "None" : nick.getCurrentNick()) + .replace("%lastChanged%", nick.getLastChangedDate() == 0 ? "Not Applicable" : nick.getLastChangedDateFormatted()))); + + meta.setLore(lore); + playerHead.setItemMeta(meta); + + return playerHead; + } + + // Nice little method to create a gui item with a custom name, and description + private ItemStack createGuiItem(final Material material, final String name, final String... lore) { + final ItemStack item = new ItemStack(material, 1); + final ItemMeta meta = item.getItemMeta(); + + // Set the name of the item + meta.displayName(Component.text(name)); + + // Set the lore of the item + meta.setLore(Arrays.asList(lore)); + + item.setItemMeta(meta); + + return item; + } + + // You can open the inventory with this + public void openInventory(final HumanEntity ent) {//Possibly with a boolean to show if it should get from cache or update cache + ent.openInventory(inv); + } + + // Check for clicks on items + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onInventoryClick(InventoryClickEvent e) { + if (e.getInventory() != inv) return; + + e.setCancelled(true); + + final ItemStack clickedItem = e.getCurrentItem(); + + if (clickedItem == null || clickedItem.getType() == Material.AIR) return; + + final Player p = (Player) e.getWhoClicked(); + + if (clickedItem.getType().equals(Material.PAPER)) { + if (clickedItem.getItemMeta().getDisplayName().equals("Next Page")) { + setItems(currentPage + 1); + } + } else if (clickedItem.getType().equals(Material.PLAYER_HEAD)) { + SkullMeta meta = (SkullMeta) clickedItem.getItemMeta(); + if (meta.hasEnchants()) { + return; + } + OfflinePlayer owningPlayer = meta.getOwningPlayer(); + + if (owningPlayer == null) { + p.sendMessage(format(Config.NICK_USER_NOT_FOUND)); + return; + } + + new BukkitRunnable() { + @Override + public void run() { + NickUtilities.updateCache(); + + Nick nick; + UUID uniqueId = owningPlayer.getUniqueId(); + if (Nicknames.getInstance().NickCache.containsKey(uniqueId)) { + nick = Nicknames.getInstance().NickCache.get(uniqueId); + } else { + nick = Queries.getNick(uniqueId); + } + + if (nick == null || !nick.hasRequest()) { + p.sendMessage(format(Config.NICK_ALREADY_HANDLED + .replace("%targetPlayer%", clickedItem.getItemMeta().getDisplayName()))); + return; + } + + if (e.isLeftClick()) { + if (owningPlayer.hasPlayedBefore()) { + Queries.acceptNewNickname(uniqueId, nick.getNewNick()); + + String newNick = nick.getNewNick(); + + new BukkitRunnable() { + @Override + public void run() { + NickEvent nickEvent = new NickEvent(e.getWhoClicked().getName(), clickedItem.getItemMeta().getDisplayName(), newNick, NickEvent.NickEventType.ACCEPTED); + nickEvent.callEvent(); + } + }.runTask(ChatPlugin.getInstance()); + + p.sendMessage(format(Config.NICK_ACCEPTED + .replace("%targetPlayer%", clickedItem.getItemMeta().getDisplayName()) + .replace("%newNick%", nick.getNewNick()) + .replace("%oldNick%", nick.getCurrentNick() == null ? clickedItem.getItemMeta().getDisplayName() : nick.getCurrentNick()))); + + if (owningPlayer.isOnline() && owningPlayer.getPlayer() != null) { + Nicknames.getInstance().setNick(owningPlayer.getUniqueId(), nick.getNewNick()); +// owningPlayer.getPlayer().sendMessage(format(Config.NICK_CHANGED // This message is also send when the plugin message is received +// .replace("%nickname%", nick.getNewNick()))); + } + + NickUtilities.bungeeMessageHandled(uniqueId, e.getWhoClicked().getServer().getPlayer(e.getWhoClicked().getName()), "Accepted"); + + nick.setCurrentNick(nick.getNewNick()); + nick.setLastChangedDate(new Date().getTime()); + nick.setNewNick(null); + nick.setRequestedDate(0); + + Nicknames.getInstance().NickCache.put(uniqueId, nick); + + ItemStack itemStack = new ItemStack(Material.SKELETON_SKULL); + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.displayName(clickedItem.getItemMeta().displayName()); + itemMeta.lore(clickedItem.lore()); + itemStack.setItemMeta(itemMeta); + e.getInventory().setItem(e.getSlot(), itemStack); + p.updateInventory(); + } else { + p.sendMessage(format(Config.NICK_PLAYER_NOT_ONLINE + .replace("%playerName%", clickedItem.getItemMeta().getDisplayName()))); + } + + } else if (e.isRightClick()) { + if (owningPlayer.hasPlayedBefore()) { + Queries.denyNewNickname(uniqueId); + + String newNick = nick.getNewNick(); + + new BukkitRunnable() { + @Override + public void run() { + NickEvent nickEvent = new NickEvent(e.getWhoClicked().getName(), clickedItem.getItemMeta().getDisplayName(), newNick, NickEvent.NickEventType.DENIED); + nickEvent.callEvent(); + } + }.runTask(ChatPlugin.getInstance()); + + p.sendMessage(format(Config.NICK_DENIED + .replace("%targetPlayer%", owningPlayer.getName()) + .replace("%newNick%", nick.getNewNick()) + .replace("%oldNick%", nick.getCurrentNick() == null ? owningPlayer.getName() : nick.getCurrentNick()))); + + if (Nicknames.getInstance().NickCache.containsKey(uniqueId) + && Nicknames.getInstance().NickCache.get(uniqueId).getCurrentNick() != null) { + nick.setNewNick(null); + nick.setRequestedDate(0); + Nicknames.getInstance().NickCache.put(uniqueId, nick); + } else { + Nicknames.getInstance().NickCache.remove(uniqueId); + } + + if (owningPlayer.isOnline() && owningPlayer.getPlayer() != null) { + Nicknames.getInstance().setNick(owningPlayer.getUniqueId(), nick.getCurrentNick() == null ? owningPlayer.getName() : nick.getCurrentNick()); + owningPlayer.getPlayer().sendMessage(format(Config.NICK_NOT_CHANGED)); + } + + NickUtilities.bungeeMessageHandled(uniqueId, e.getWhoClicked().getServer().getPlayer(e.getWhoClicked().getName()), "Denied"); + final String messageDenied = ChatColor.RED + owningPlayer.getName() + "'s nickname was denied!"; + ChatPlugin.getInstance().getServer().getOnlinePlayers().forEach(p -> { + if (p.hasPermission("utility.nick.review")) { + p.sendMessage(messageDenied); + } + }); + + + ItemStack itemStack = new ItemStack(Material.SKELETON_SKULL); + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.displayName(clickedItem.getItemMeta().displayName()); + itemMeta.lore(clickedItem.lore()); + itemStack.setItemMeta(itemMeta); + e.getInventory().setItem(e.getSlot(), itemStack); + p.updateInventory(); + } else { + p.sendMessage(format(Config.NICK_PLAYER_NOT_ONLINE + .replace("%playerName%", clickedItem.getItemMeta().getDisplayName()))); + } + } + } + }.runTaskAsynchronously(ChatPlugin.getInstance()); + } + } + + // Cancel dragging in our inventory + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onInventoryClick(InventoryDragEvent e) { + if (e.getInventory() == inv) { + e.setCancelled(true); + } + } +} diff --git a/galaxy/src/main/java/com/alttd/chat/util/GalaxyUtility.java b/galaxy/src/main/java/com/alttd/chat/util/GalaxyUtility.java index e167618..f3949c1 100644 --- a/galaxy/src/main/java/com/alttd/chat/util/GalaxyUtility.java +++ b/galaxy/src/main/java/com/alttd/chat/util/GalaxyUtility.java @@ -1,13 +1,19 @@ package com.alttd.chat.util; import com.alttd.chat.config.Config; +import com.alttd.chat.managers.RegexManager; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.kyori.adventure.text.minimessage.tag.standard.StandardTags; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import java.util.ArrayList; +import java.util.List; + public class GalaxyUtility { public static void sendBlockedNotification(String prefix, Player player, String input, String target) { @@ -32,4 +38,14 @@ public class GalaxyUtility { sendBlockedNotification(prefix, player, PlainTextComponentSerializer.plainText().serialize(input), target); } + public static void addAdditionalChatCompletions(Player player) { + List completions = new ArrayList<>(RegexManager.emotesList); + Utility.formattingPerms.forEach((perm, pair) -> { + if (player.hasPermission(perm)) { + completions.addAll(pair.getY()); + } + }); + player.addAdditionalChatCompletions(completions); + } + } diff --git a/galaxy/src/main/resources/plugin.yml b/galaxy/src/main/resources/plugin.yml index 60a64dd..b68052a 100755 --- a/galaxy/src/main/resources/plugin.yml +++ b/galaxy/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: ChatPlugin -version: ${project.version} +version: 2.0.0-SNAPSHOT main: com.alttd.chat.ChatPlugin api-version: 1.18 authors: [Destro, Teriuihi] @@ -33,4 +33,9 @@ commands: p: permission: command.chat.p chatclear: - permission: chat.command.clear-chat \ No newline at end of file + permission: chat.command.clear-chat + emoteslist: + permission: chat.command.clear-chat + aliases: [emotes] + nick: + permission: chat.command.nick \ No newline at end of file diff --git a/velocity/build.gradle.kts b/velocity/build.gradle.kts index 4b6b47a..385441a 100644 --- a/velocity/build.gradle.kts +++ b/velocity/build.gradle.kts @@ -26,7 +26,7 @@ tasks { } build { - setBuildDir("${rootProject.buildDir}") +// setBuildDir("${rootProject.buildDir}") dependsOn(shadowJar) } diff --git a/velocity/src/main/java/com/alttd/velocitychat/commands/partysubcommands/Info.java b/velocity/src/main/java/com/alttd/velocitychat/commands/partysubcommands/Info.java index b22f1bd..097cba9 100644 --- a/velocity/src/main/java/com/alttd/velocitychat/commands/partysubcommands/Info.java +++ b/velocity/src/main/java/com/alttd/velocitychat/commands/partysubcommands/Info.java @@ -10,6 +10,7 @@ import com.alttd.velocitychat.commands.SubCommand; import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.proxy.Player; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.JoinConfiguration; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; @@ -49,7 +50,7 @@ public class Info implements SubCommand { Placeholder.unparsed("party", party.getPartyName()), Placeholder.unparsed("password", party.getPartyPassword()), Placeholder.component("owner", party.getPartyUser(party.getOwnerUuid()).getDisplayName()), - Placeholder.component("members", Component.join(Component.text(", "), displayNames)) + Placeholder.component("members", Component.join(JoinConfiguration.separator(Component.text(", ")), displayNames)) )); } diff --git a/velocity/src/main/java/com/alttd/velocitychat/handlers/ChatHandler.java b/velocity/src/main/java/com/alttd/velocitychat/handlers/ChatHandler.java index 13805ff..c9fb1a9 100755 --- a/velocity/src/main/java/com/alttd/velocitychat/handlers/ChatHandler.java +++ b/velocity/src/main/java/com/alttd/velocitychat/handlers/ChatHandler.java @@ -5,10 +5,7 @@ import com.alttd.chat.database.Queries; import com.alttd.chat.managers.ChatUserManager; import com.alttd.chat.managers.PartyManager; import com.alttd.chat.managers.RegexManager; -import com.alttd.chat.objects.ChatUser; -import com.alttd.chat.objects.Mail; -import com.alttd.chat.objects.ModifiableString; -import com.alttd.chat.objects.Party; +import com.alttd.chat.objects.*; import com.alttd.chat.util.ALogger; import com.alttd.chat.util.Utility; import com.alttd.velocitychat.VelocityChat; @@ -19,6 +16,7 @@ import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ServerConnection; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; +import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; @@ -108,6 +106,8 @@ public class ChatHandler { return party.getPartyUsers().stream().anyMatch(pu -> pu.getUuid().equals(uuid)); }).forEach(pl -> { pl.sendMessage(message); + // TODO forward sound to backend server. + // https://canary.discord.com/channels/514920774923059209/1020498592219271189 }); } @@ -128,18 +128,11 @@ public class ChatHandler { return; // the message was blocked } - String updatedMessage = modifiableString.string(); - if(!player.hasPermission("chat.format")) { - updatedMessage = Utility.stripTokens(updatedMessage); - } - - updatedMessage = Utility.formatText(updatedMessage); - TagResolver Placeholders = TagResolver.resolver( Placeholder.component("sender", senderName), Placeholder.component("sendername", senderName), Placeholder.unparsed("partyname", party.getPartyName()), - Placeholder.component("message", Utility.parseMiniMessage(updatedMessage)), + Placeholder.component("message", parseMessageContent(player, modifiableString.string())), Placeholder.unparsed("server", serverConnection.getServer().getServerInfo().getName()) ); @@ -175,7 +168,7 @@ public class ChatHandler { } TagResolver Placeholders = TagResolver.resolver( - Placeholder.component("message", Utility.parseMiniMessage(message)), + Placeholder.component("message", parseMessageContent(commandSource, message)), Placeholder.component("sender", senderName), Placeholder.unparsed("server", serverName)); @@ -297,4 +290,27 @@ public class ChatHandler { stringBuilder.append(duration.toMinutesPart()).append("m ago"); return stringBuilder.toString(); } + + private Component parseMessageContent(CommandSource source, String rawMessage) { + TagResolver.Builder tagResolver = TagResolver.builder(); + + Utility.formattingPerms.forEach((perm, pair) -> { + if (source.hasPermission(perm)) { + tagResolver.resolver(pair.getX()); + } + }); + + MiniMessage miniMessage = MiniMessage.builder().tags(tagResolver.build()).build(); + Component component = miniMessage.deserialize(rawMessage); + for(ChatFilter chatFilter : RegexManager.getEmoteFilters()) { + component = component.replaceText( + TextReplacementConfig.builder() + .times(Config.EMOTELIMIT) + .match(chatFilter.getRegex()) + .replacement(chatFilter.getReplacement()).build()); + } + + return component; + + } } \ No newline at end of file diff --git a/velocity/src/main/java/com/alttd/velocitychat/listeners/PluginMessageListener.java b/velocity/src/main/java/com/alttd/velocitychat/listeners/PluginMessageListener.java index 5265521..807b00a 100755 --- a/velocity/src/main/java/com/alttd/velocitychat/listeners/PluginMessageListener.java +++ b/velocity/src/main/java/com/alttd/velocitychat/listeners/PluginMessageListener.java @@ -2,10 +2,9 @@ package com.alttd.velocitychat.listeners; import com.alttd.chat.managers.ChatUserManager; import com.alttd.chat.objects.ChatUser; -import com.alttd.velocitychat.VelocityChat; -import com.alttd.chat.database.Queries; import com.alttd.chat.objects.channels.CustomChannel; import com.alttd.chat.util.ALogger; +import com.alttd.velocitychat.VelocityChat; import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteStreams; import com.velocitypowered.api.event.Subscribe; @@ -23,7 +22,6 @@ import java.util.UUID; public class PluginMessageListener { - //todo add an extra listener for nicknames? private final ChannelIdentifier identifier; public PluginMessageListener(ChannelIdentifier identifier){ @@ -45,38 +43,33 @@ public class PluginMessageListener { String channel = in.readUTF(); VelocityChat.getPlugin().getLogger().info("server " + event.getSource()); switch (channel) { - case "globalchat": - VelocityChat.getPlugin().getServerHandler().sendGlobalChat(in.readUTF(), in.readUTF()); - break; - case "globaladminchat": - VelocityChat.getPlugin().getChatHandler().globalAdminChat(in.readUTF()); - break; - case "privatemessage": - VelocityChat.getPlugin().getChatHandler().privateMessage(in.readUTF(), in.readUTF(), in.readUTF()); - break; - case "chatchannel": { + case "globalchat" -> VelocityChat.getPlugin().getServerHandler().sendGlobalChat(in.readUTF(), in.readUTF()); + case "globaladminchat" -> VelocityChat.getPlugin().getChatHandler().globalAdminChat(in.readUTF()); + case "privatemessage" -> + VelocityChat.getPlugin().getChatHandler().privateMessage(in.readUTF(), in.readUTF(), in.readUTF()); + case "chatchannel" -> { String channelName = in.readUTF(); CustomChannel chatChannel = (CustomChannel) CustomChannel.getChatChannel(channelName); if (chatChannel == null) { - ALogger.warn("Received non existent channel" + channelName +"."); + ALogger.warn("Received non existent channel" + channelName + "."); break; } ProxyServer proxy = VelocityChat.getPlugin().getProxy(); chatChannel.getServers().forEach(server -> proxy.getServer(server).ifPresent(registeredServer -> registeredServer.sendPluginMessage(VelocityChat.getPlugin().getChannelIdentifier(), event.getData()))); - break; } - case "party": { + case "party" -> { VelocityChat.getPlugin().getChatHandler().sendPartyMessage( UUID.fromString(in.readUTF()), in.readUTF(), GsonComponentSerializer.gson().deserialize(in.readUTF()), serverConnection); - break; } - case "NickNameAccepted": { + + // nicknames WIP + case "NickNameAccepted", "NickNameSet" -> { try { short len = in.readShort(); byte[] msgbytes = new byte[len]; @@ -91,15 +84,22 @@ public class PluginMessageListener { e.printStackTrace(); return; } + ProxyServer proxy = VelocityChat.getPlugin().getProxy(); + proxy.getAllServers().forEach(registeredServer -> + registeredServer.sendPluginMessage(VelocityChat.getPlugin().getChannelIdentifier(), event.getData())); } - default: + case "NickNameRequest", "NickNameDenied" -> { + ProxyServer proxy = VelocityChat.getPlugin().getProxy(); + proxy.getAllServers().forEach(registeredServer -> + registeredServer.sendPluginMessage(VelocityChat.getPlugin().getChannelIdentifier(), event.getData())); + } + default -> { VelocityChat.getPlugin().getLogger().info("server " + event.getSource()); ProxyServer proxy = VelocityChat.getPlugin().getProxy(); - for (RegisteredServer registeredServer : proxy.getAllServers()) { registeredServer.sendPluginMessage(VelocityChat.getPlugin().getChannelIdentifier(), event.getData()); } - break; + } } }