162 Commits
Author SHA1 Message Date
auto 42736bd566 Update APRIL_FOOLS_RESET string in Config class
APRIL_FOOLS_RESET string in Config class has been updated from "reverse" to "esrever". This change updates the behavior of the April Fools feature in the chat application.
2024-03-31 14:53:36 +02:00
auto 157edbd6b6 Merge branch 'main' into april_fools 2024-03-31 13:37:42 +02:00
auto 4af85d0e79 Add option to disable chat filters in private channels
A constructor parameter and corresponding field 'disableInPrivate' have been added to the ChatFilter class. This handles disabling specific chat filters in private channels. The necessary checks have been implemented in RegexManager. The configuration for each filter is also updated in RegexConfig to incorporate this new functionality.
2024-03-31 13:37:05 +02:00
auto a7e029b0a1 Refactor April 1st date check in ChatListener
Removed the more complex date logic used to check for April 1st in the ChatListener class. This check checked if it was April 1st in any timezone. Replaced it with a simpler check using LocalDate's methods for month and day comparison. This only checks if it's April 1st in UTC. This aims to enhance code readability and simplify date handling.
2024-03-31 10:56:21 +02:00
auto ab98222f06 Refactor April 1st check in ChatListener class
A new method, `isWithinApril1st`, is introduced to simplify April 1st date check logic in the `ChatListener` class. This new method calculates the start and end of April 1st for all timezones in UTC and determines if the current time falls within this range.
2024-03-24 17:24:24 +01:00
auto ad91cda0c0 Add method to remove string at start
A new method `removeStringAtStart` has been added to the `ModifiableString` class. It replaces the starting string in a given text. Also, a condition has been modified in the `ChatListener` class to invoke this new method when the input string starts with the `APRIL_FOOLS_RESET` string. Additional unit tests were created to validate these changes.
2024-03-24 17:12:55 +01:00
auto 9270423928 Add reverse chat feature for April Fools' and corresponding tests
This commit includes a new feature that reverses the text speech of chat users on April 1st as an April Fools' prank. It also includes a reset option, configurable via a new parameter in the configuration file. Furthermore, it provides tests for the reverse string functionality, ensuring that it works correctly, even with complex strings that include tags.
2024-03-24 16:58:09 +01:00
auto 034de90062 Implement evidence for automatic ban for 'punish' filter violations
When a user who violate the 'punish' filter rules is automatically banned, there will now be a post about it in the #evidence channel.
2024-03-02 20:41:59 +01:00
auto bd8fa02f1e Add 'punish' filter and automatic banning functionality
Extended the RegexManager filterText method to include a 'punish' case that triggers an automatic ban for users who violate the filter. This commit also updates the PluginMessageListener to handle 'punish' commands, thus completing the execution of an auto-ban function.
2024-03-02 19:18:13 +01:00
Len 8a5b407359 update gradle 2024-01-04 09:28:53 +01:00
Len f63c4c0836 Update velocity 2023-12-17 12:39:07 +01:00
Len eb7c1dd1e1 Update to 1.20.4 2023-12-17 12:37:21 +01:00
auto 278129e8d8 Changed pinging to prevent ping for not @'d user
Allowed \ to escape ping
2023-08-14 01:29:06 +02:00
auto f1deebf49e Merge remote-tracking branch 'origin/main' 2023-08-11 22:30:34 +02:00
auto 3e29fc7d17 Added minimum hex value for nick colors 2023-08-11 22:30:23 +02:00
Len ffa90b5c94 add MENTIONPLAYERTAG to Config.java 2023-07-15 17:45:03 +02:00
Len 9d7f944c88 Fix Tagging players and triggering a replacematcher not resetting chatcolor 2023-07-15 17:42:12 +02:00
auto 4b930e62c3 Log party messages that are from a toggled user on the local server as well 2023-07-10 23:33:42 +02:00
auto c02e4dd884 Log all party messages 2023-07-10 23:15:08 +02:00
auto 8a463696ed Made chatusermanager use synchronized functions 2023-07-07 23:16:32 +02:00
auto ce5ea19961 Removed unused imports 2023-07-07 23:16:15 +02:00
auto 591ca93981 Fixed first join messages only working if chat user is not loaded yet 2023-07-07 23:15:45 +02:00
auto d7cfe97644 Added first join messages back 2023-06-26 21:40:15 +02:00
auto c86a344d49 Trying a different way to see if a player is a new player 2023-06-22 02:00:51 +02:00
auto 5583abbbca Fix party info not showing if party owner is null 2023-06-20 23:44:32 +02:00
auto 55918670bc Maybe fixed mentions 2023-06-20 00:40:44 +02:00
auto f3c7a312c0 Added first join messages 2023-06-20 00:35:46 +02:00
auto d8f064e7ca Fix spy needing mute-server permission 2023-06-20 00:09:48 +02:00
auto 9b7868bea7 Fix mentions happening within words 2023-06-17 23:58:33 +02:00
auto 6c6b798677 Fix load order 2023-04-23 22:48:33 +02:00
auto 0c1b197054 Don't send players a ping sound if they have the player that's pinging them ignored 2022-11-25 19:49:37 +01:00
Len 57afbbe805 Update permissions for nicknames 2022-10-29 10:29:26 +02:00
Len 5398d97248 Merge branch 'main' of https://github.com/Altitude-Devs/Chat 2022-10-09 20:25:52 +02:00
Len d90f5ac376 Update nicknames for Player and CMI. 2022-10-09 20:25:40 +02:00
auto 0c7ad69e85 Only replace the first instance of a name/nickname 2022-10-09 19:33:06 +02:00
auto 7ef9b4a64a Make .replace require a TextReplacementConfig 2022-10-09 19:32:51 +02:00
auto 5b06049265 Fixed double @ if someone doesn't have a nickname (or has the same nickname as the username) 2022-10-09 18:04:41 +02:00
auto ea051fd905 Fixed spacing for target replacement 2022-10-09 01:21:10 +02:00
auto 87d5c1b264 Fixed blocked messages not highlighting what was blocked 2022-10-09 01:18:13 +02:00
auto 5e62786010 Fixed case-sensitive name matching for replacing names/nicknames 2022-10-09 00:47:43 +02:00
auto 4f01c86877 @ players when they are mentioned by name or nickname (case-insensitive) 2022-10-09 00:36:50 +02:00
auto 6beb398e10 Added a way to replace text with components and patterns with strings/components 2022-10-09 00:36:07 +02:00
Len e811b0ca9a Update permissions for nickcommand. V2 2022-10-08 22:36:46 +02:00
Len 3eff30a4be Update permissions for nickcommand. 2022-10-08 11:14:58 +02:00
Len 3aa0b09133 Fix ChatFilter.java not applying to message. 2022-10-08 11:05:56 +02:00
Len 5db22461cf Fix [i] duplicating in GC 2022-10-08 10:36:06 +02:00
Len 3bdaa798c3 Continue the loop do not break it. 2022-10-03 19:39:41 +02:00
Len 7fcfb2321f Update config style 2022-10-03 19:29:25 +02:00
Len 7af91c1c94 Fix permission for emoteslist 2022-10-03 19:13:42 +02:00
Len 7de83f536b Show correct nickname in previews 2022-10-03 18:27:58 +02:00
Len 76f713409b Parse components in nicktry 2022-10-03 12:04:08 +02:00
Len ef831c48b3 Remove legacy codes in Nicknames.java 2022-10-03 11:29:06 +02:00
Len 8baa254d5e Revert "Fix replacement filers not working."
This reverts commit df4ff7f6b3.
2022-10-03 11:29:06 +02:00
Len 3d14cca551 Update minimessage tags to be lowercase 2022-10-03 11:29:06 +02:00
Len d1df551f35 Update minimessage tags to be lowercase 2022-10-03 10:30:27 +02:00
Len db8524134e update player displayname when changing Nicknames 2022-10-02 16:33:01 +02:00
Len e99626cebb Remove deprecation usages 2022-10-02 10:53:26 +02:00
auto d7bd3aa222 Switched to using minimessage (mostly) 2022-10-02 04:52:33 +02:00
auto 9407ba8bec Switched to using minimessage (mostly) 2022-10-02 03:52:02 +02:00
destro174andGitHub aab68e5e7f Merge pull request #2 from Altitude-Devs/Changes
Make use of the new 1.19 chat features + other updates
2022-10-01 20:53:49 +02:00
Len 5ec1f08fe1 Update version in plugin.yml 2022-10-01 20:46:07 +02:00
Len a4e4982dc3 Update nicknames to use Chat's plugin message channels. 2022-10-01 20:42:35 +02:00
Len 3d432a5af6 Change Nicknames.getNick to use UUID 2022-10-01 19:39:20 +02:00
Len ac994d35a1 Update version 2022-10-01 18:24:42 +02:00
Len 4b947996da Change some minor things to Nicknames 2022-10-01 15:04:08 +02:00
Len df4ff7f6b3 Fix replacement filers not working. 2022-10-01 13:32:04 +02:00
Len 2764446e41 Switch to new formatting permissions. 2022-09-30 16:48:08 +02:00
Len 5db3bc5ffe update formatting and emotes in written books. 2022-09-29 17:00:53 +02:00
Len 271500bae3 Add permission for newline 2022-09-29 16:51:03 +02:00
Len 244b2aeda2 Register Nickname events and commands 2022-09-29 16:27:49 +02:00
Len d6562826e4 Add /nick current 2022-09-29 16:26:55 +02:00
Len 6329eacd07 Fix some deprecated issues 2022-09-29 16:26:55 +02:00
Len 99cbc01106 Update buildscript 2022-09-29 16:26:55 +02:00
Len 58b80e9eaf Fork NickNameAccepted to update nickname on proxy before forwarding. 2022-09-29 16:26:55 +02:00
Len 282fdde48b Use AsyncChatDecorateEvent. 2022-09-27 09:35:10 +02:00
Len a405862fe1 Update Config.java references for Nicknames 2022-09-27 00:45:23 +02:00
Len 11ecf1ad16 Merge Nicknames 2022-09-27 00:02:27 +02:00
Len fb997ae4ed Update ChatListener.java 2022-09-27 00:02:27 +02:00
Len b0e453295b Add addAdditionalChatCompletions 2022-09-27 00:02:27 +02:00
Len 1ea2c03fcd Add nicknameString getting in ChatUser.java 2022-09-27 00:02:27 +02:00
Len 4d01ccb065 Update Config.java 2022-09-27 00:02:27 +02:00
Len a15b13e8ac Add Nick.java 2022-09-27 00:02:27 +02:00
Len 00f4e00011 Add Pair.java 2022-09-27 00:02:27 +02:00
Len 3888298827 Add Emote to FilterType.java
Add EmoteList command.
2022-09-27 00:02:27 +02:00
Len 643fb5a633 Fix mail output message not showing recipient name. 2022-09-26 19:08:51 +02:00
Len 3ca854e507 Remove GitHub workflows 2022-09-26 19:08:51 +02:00
Len 1eb4d619d6 Remove plugin script 2022-09-26 19:08:51 +02:00
Len 9d7f50ad37 Update to apache commons lang3 2022-09-26 19:08:51 +02:00
Len d644dbef6e Add runserver task 2022-09-26 19:08:51 +02:00
Len 425c06af33 Update build scripts 2022-09-26 19:08:51 +02:00
Len fb3358e2ea Remove unused command 2022-09-26 19:08:51 +02:00
Len ee2a2c2225 Use 1.19.2 API 2022-09-26 19:08:51 +02:00
auto 341a330e3d Removed sout for adding party users 2022-09-22 23:53:09 +02:00
auto 0339458c66 Added logging for chat messages 2022-09-22 23:52:46 +02:00
Stijn d3be713c9a Added optional sender argument to /mail list <username> 2022-09-21 18:26:16 +02:00
Len 6e41a81ed1 Do not shade minimessage in velocity module 2022-09-19 18:27:19 +02:00
Stijn ce1ec164ef added confirmation message to mail send 2022-09-19 18:10:15 +02:00
auto 9832abbb90 Fixed only sending to ignored players 2022-06-25 06:10:17 +02:00
Stijn 66a058225d Fixed chat not sending messages by bypassing Microsoft's chat report system 2022-06-24 21:11:54 +02:00
auto 35ad214901 Fixed regex injection 2022-06-02 05:09:43 +02:00
auto 32e38ef32b spot the bug 2022-06-02 04:57:04 +02:00
auto b1f2370bec Added continue, fixed mail 2022-06-02 03:48:51 +02:00
auto 20c7f0a6d9 ez tmp fix for sendername receivername not being replaced properly 2022-05-30 23:59:54 +02:00
auto 40a6e6bcc9 Fixed colors not working in chat 2022-05-30 22:10:54 +02:00
auto 7ab95e437a Fixed bypass spam limits by spamming more than one character 2022-05-30 19:58:00 +02:00
auto 4068ad8ea6 Fixed message for toggling chat channel
Fixed stack overflow for untoggling chat channels
2022-05-30 19:43:31 +02:00
auto 82eecc3142 Colored toggle word, improved default party online/offline marker 2022-05-30 19:27:47 +02:00
auto 679602c1f7 Registered SilentJoinCommand 2022-05-30 19:19:41 +02:00
Len 8c3d03383d build using velocity 3.1.2-SNAPSHOT 2022-05-30 18:47:29 +02:00
Stijn fe64fb3785 Added the string that was filtered to the logs 2022-05-27 17:52:34 +02:00
Len c836452d19 Update minimessage references 2022-05-27 00:31:36 +02:00
auto 0997c2bab6 Disable toggles on join 2022-05-24 04:20:21 +02:00
auto e39bab34fd Moved class to more logical place 2022-05-24 04:18:34 +02:00
auto 41897f4b16 Added toggle to party as well and made it so it can be added to other channels if needed 2022-05-24 04:17:55 +02:00
auto 60e1ad2220 Added a way to toggle custom channels 2022-05-24 03:06:34 +02:00
auto c645201ef3 Removed variable, moved call inline 2022-05-24 02:50:18 +02:00
auto fdd9d81400 Fix party users not being removed correctly (they left the party but still had their party id set) 2022-05-24 02:49:36 +02:00
auto 3e313cb00b Fixed being able to bypass replacement filters by having multiple of the same match in one string 2022-05-24 02:41:11 +02:00
auto dac0f7936e Use util to parse message 2022-05-24 02:06:28 +02:00
Stijn 408d38fb78 Added silent join 2022-05-23 22:32:43 +02:00
Stijn faa0435131 Require reports to be at least 3 words long 2022-05-23 22:06:17 +02:00
Stijn 1946cd4ab7 Added online indicators for party info 2022-05-23 21:55:36 +02:00
destro174 29dd5d2d55 Commit reply/continue rework 2022-04-21 15:45:50 +02:00
auto 0a6dfe799e Properly handle filtered messages in party chat 2022-03-15 00:20:07 +01:00
destro174 e6dfd19b84 Merge branch 4.9 2022-03-14 16:48:35 +01:00
destro174 42585c97cf fix invalid urls in chat 2022-02-19 15:34:16 +01:00
destro174 342957ef68 Fix build! 2022-02-19 15:14:41 +01:00
destro174 ab852cf55e add minimessage snapshots repo 2022-02-17 09:32:02 +01:00
destro174 ef94169f04 Add gradle-wrapper to gitignore 2022-02-17 09:01:36 +01:00
destro174 5042d62247 Add gh actions 2022-02-17 08:58:12 +01:00
destro174 fe022a02fe null check in parsecolors 2022-02-17 08:32:27 +01:00
auto fbbe0d6ef3 Maybe added proxydiscordlink and added report command 2022-02-15 16:37:47 +01:00
auto 647ad2b62a Added party leave notif 2022-02-15 03:20:05 +01:00
auto 59781f486d Added confirmation message to mail sent 2022-02-15 03:07:56 +01:00
auto fa79491088 Maybe made nicknames auto sync 2022-02-15 02:57:50 +01:00
auto e6e1073958 Fixed party notifs and spy 2022-02-15 02:32:38 +01:00
auto 2b77607072 Maybe fixed party 2022-02-14 01:25:51 +01:00
auto 777415f97e Grammar in config message 2022-02-08 00:39:07 +01:00
auto bc010bea6e Notify players that chat was cleared 2022-02-07 00:22:33 +01:00
auto 8628dacd10 Fixed storing sender as receiver and receiver as sender 2022-02-06 18:07:16 +01:00
auto 3d42fb8bbf Added bypass perm and confirmation message 2022-02-06 03:39:53 +01:00
auto 08a695f2ac Added chatclear command 2022-02-06 03:31:07 +01:00
auto 2c0637b1d1 Parse / strip chat color tokens based on if the commandSender has permission for chat colors 2022-02-06 03:13:51 +01:00
destro174 e08c5a4a3b Update minimessage to 4.10.0 2022-02-05 21:16:20 +01:00
destro174 f00f6e7658 fix url in global admin chat 2022-02-05 10:17:49 +01:00
auto a5d5d8d985 Tweaked mails, added notifs, added config options 2022-02-05 02:45:38 +01:00
auto c18ffb9578 Added missing config messages 2022-01-31 03:15:58 +01:00
auto 79501c619a Check if a user has permission to see tab complete suggestions 2022-01-31 03:15:43 +01:00
auto 0c8a4a97d3 Added party disband command and a way to remove all users from a party 2022-01-31 03:06:52 +01:00
auto 032d0e2bef Added party chat help message 2022-01-31 02:54:23 +01:00
auto 8d0ed326b5 Changed api version 2022-01-30 21:54:01 +01:00
auto d40c3a45ed Removed todo 2022-01-30 20:23:45 +01:00
auto 040c8cfa96 Removed old chatparty command 2022-01-30 20:23:23 +01:00
auto 787927672a Added messages for commands that had no output 2022-01-30 20:20:42 +01:00
auto aed1885a59 Added logout notif 2022-01-30 20:13:38 +01:00
auto 43a2be1b1b Notify players if their party member joins 2022-01-30 20:11:25 +01:00
auto fd58617e44 Edited templates for spy/party format 2022-01-30 19:52:53 +01:00
auto 6360d74b30 Added more config messages 2022-01-30 19:50:33 +01:00
auto a0a60757f6 Check if a user is already in a party before letting them make another party 2022-01-30 19:50:22 +01:00
auto 89938338b1 Configure party invite messages 2022-01-30 19:50:06 +01:00
auto f8ede610b2 Parse commands before putting them in template 2022-01-30 19:49:53 +01:00
TeriuihiandGitHub 70d26a2255 Merge pull request #1 from Altitude-Devs/party
Party
2022-01-30 20:32:21 +01:00
74 changed files with 3442 additions and 642 deletions
-18
View File
@@ -1,18 +0,0 @@
name: Build
on: [ push, pull_request ]
jobs:
build:
runs-on: ubuntu-latest
if: "!contains(github.event.commits[0].message, '[ci-skip]')"
steps:
- uses: actions/checkout@v2
- uses: gradle/wrapper-validation-action@v1
- uses: actions/setup-java@v2
with:
distribution: temurin
java-version: 17
- name: Configure Git
run: git config --global user.email "[email protected]" && git config --global user.name "Github Actions"
- name: Build
run: ./gradlew build --stacktrace
+9 -7
View File
@@ -3,16 +3,14 @@ plugins {
} }
dependencies { dependencies {
compileOnly("com.alttd:Galaxy-API:1.18.1-R0.1-SNAPSHOT") { compileOnly("com.alttd:Galaxy-API:1.19.2-R0.1-SNAPSHOT") {
exclude("net.kyori.adventure.text.minimessag") // exclude("net.kyori")
}
compileOnly("net.kyori", "adventure-text-minimessage", "4.10.0-20220122.015731-43") { // Minimessage
exclude("net.kyori")
exclude("net.kyori.examination")
} }
compileOnly("org.spongepowered:configurate-yaml:4.1.2") // Configurate compileOnly("org.spongepowered:configurate-yaml:4.1.2") // Configurate
compileOnly("net.luckperms:api:5.3") // Luckperms compileOnly("net.luckperms:api:5.3") // Luckperms
compileOnly(files("../libs/minimessage-4.10.0-SNAPSHOT.jar")) // Workaround for minimessage testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.0")
testImplementation("com.alttd:Galaxy-API:1.19.2-R0.1-SNAPSHOT")
} }
publishing { publishing {
@@ -30,3 +28,7 @@ publishing {
} }
} }
} }
tasks.test {
useJUnitPlatform()
}
@@ -1,13 +1,15 @@
package com.alttd.chat.config; package com.alttd.chat.config;
import com.alttd.chat.objects.channels.CustomChannel; import com.alttd.chat.objects.channels.CustomChannel;
import com.google.common.base.Throwables; import com.alttd.chat.util.Utility;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import io.leangen.geantyref.TypeToken; import io.leangen.geantyref.TypeToken;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.spongepowered.configurate.ConfigurationNode; import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.ConfigurationOptions;
import org.spongepowered.configurate.serialize.SerializationException; import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.yaml.NodeStyle; import org.spongepowered.configurate.yaml.NodeStyle;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -16,8 +18,6 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.*; import java.util.*;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import org.spongepowered.configurate.ConfigurationOptions;
public final class Config { public final class Config {
private static final Pattern PATH_PATTERN = Pattern.compile("\\."); private static final Pattern PATH_PATTERN = Pattern.compile("\\.");
@@ -78,7 +78,7 @@ public final class Config {
method.setAccessible(true); method.setAccessible(true);
method.invoke(instance); method.invoke(instance);
} catch (InvocationTargetException | IllegalAccessException ex) { } catch (InvocationTargetException | IllegalAccessException ex) {
throw Throwables.propagate(ex.getCause()); ex.printStackTrace();
} }
} }
} }
@@ -86,7 +86,7 @@ public final class Config {
try { try {
configLoader.save(config); configLoader.save(config);
} catch (IOException ex) { } catch (IOException ex) {
throw Throwables.propagate(ex.getCause()); ex.printStackTrace();
} }
} }
@@ -94,7 +94,7 @@ public final class Config {
try { try {
configLoader.save(config); configLoader.save(config);
} catch (IOException ex) { } catch (IOException ex) {
throw Throwables.propagate(ex.getCause()); ex.printStackTrace();
} }
} }
@@ -107,6 +107,7 @@ public final class Config {
try { try {
config.node(splitPath(path)).set(def); config.node(splitPath(path)).set(def);
} catch (SerializationException e) { } catch (SerializationException e) {
e.printStackTrace();
} }
} }
} }
@@ -116,6 +117,7 @@ public final class Config {
if(config.node(splitPath(path)).virtual()) if(config.node(splitPath(path)).virtual())
config.node(splitPath(path)).set(io.leangen.geantyref.TypeToken.get(String.class), def); config.node(splitPath(path)).set(io.leangen.geantyref.TypeToken.get(String.class), def);
} catch(SerializationException ex) { } catch(SerializationException ex) {
ex.printStackTrace();
} }
} }
@@ -149,6 +151,7 @@ public final class Config {
set(path, def); set(path, def);
return config.node(splitPath(path)).getList(TypeToken.get(String.class)); return config.node(splitPath(path)).getList(TypeToken.get(String.class));
} catch(SerializationException ex) { } catch(SerializationException ex) {
ex.printStackTrace();
} }
return new ArrayList<>(); return new ArrayList<>();
} }
@@ -168,6 +171,8 @@ public final class Config {
public static String MINIMIUMSTAFFRANK = "trainee"; public static String MINIMIUMSTAFFRANK = "trainee";
public static String CONSOLENAME = "Console"; public static String CONSOLENAME = "Console";
public static UUID CONSOLEUUID = UUID.randomUUID(); public static UUID CONSOLEUUID = UUID.randomUUID();
public static int EMOTELIMIT = 3;
public static String MENTIONPLAYERTAG = "<aqua>@</aqua>";
private static void settings() { private static void settings() {
PREFIXGROUPS = getList("settings.prefix-groups", PREFIXGROUPS = getList("settings.prefix-groups",
Lists.newArrayList("discord", "socialmedia", "eventteam", "eventleader", "youtube", "twitch", "developer")); Lists.newArrayList("discord", "socialmedia", "eventteam", "eventleader", "youtube", "twitch", "developer"));
@@ -178,6 +183,8 @@ public final class Config {
CONSOLENAME = getString("settings.console-name", CONSOLENAME); CONSOLENAME = getString("settings.console-name", CONSOLENAME);
CONSOLEUUID = UUID.fromString(getString("settings.console-uuid", CONSOLEUUID.toString())); CONSOLEUUID = UUID.fromString(getString("settings.console-uuid", CONSOLEUUID.toString()));
MINIMIUMSTAFFRANK = getString("settings.minimum-staff-rank", MINIMIUMSTAFFRANK); MINIMIUMSTAFFRANK = getString("settings.minimum-staff-rank", MINIMIUMSTAFFRANK);
EMOTELIMIT = getInt("settings.emote-limit", EMOTELIMIT);
MENTIONPLAYERTAG = getString("settings.mention-player-tag", MENTIONPLAYERTAG);
} }
public static List<String> MESSAGECOMMANDALIASES = new ArrayList<>(); public static List<String> MESSAGECOMMANDALIASES = new ArrayList<>();
@@ -290,6 +297,9 @@ public final class Config {
Password: <dark_aqua><password></dark_aqua> Password: <dark_aqua><password></dark_aqua>
Owner: <owner> Owner: <owner>
Members: <members>"""; Members: <members>""";
public static Component ONLINE_PREFIX = null;
public static Component OFFLINE_PREFIX = null;
public static String PARTY_TOGGLED = "<dark_aqua>Party chat toggled <status>.</dark_aqua>";
private static void party() { private static void party() {
PARTY_FORMAT = getString("party.format", PARTY_FORMAT); PARTY_FORMAT = getString("party.format", PARTY_FORMAT);
PARTY_SPY = getString("party.spy", PARTY_SPY); PARTY_SPY = getString("party.spy", PARTY_SPY);
@@ -321,6 +331,9 @@ public final class Config {
DISBANDED_PARTY = getString("party.messages.disbanded-party", DISBANDED_PARTY); DISBANDED_PARTY = getString("party.messages.disbanded-party", DISBANDED_PARTY);
PARTY_INFO = getString("party.messages.party-info", PARTY_INFO); PARTY_INFO = getString("party.messages.party-info", PARTY_INFO);
ALREADY_IN_THIS_PARTY = getString("party.messages.already-in-this-party", ALREADY_IN_THIS_PARTY); ALREADY_IN_THIS_PARTY = getString("party.messages.already-in-this-party", ALREADY_IN_THIS_PARTY);
ONLINE_PREFIX = Utility.parseMiniMessage(getString("party.messages.online-prefix", "<green>■</green>"));
OFFLINE_PREFIX = Utility.parseMiniMessage(getString("party.messages.offline-prefix", "<red>■</red>"));
PARTY_TOGGLED = getString("party.messages.party-toggled", PARTY_TOGGLED);
} }
public static String PARTY_HELP_WRAPPER = "<gold>ChatParty help:\n<commands></gold>"; public static String PARTY_HELP_WRAPPER = "<gold>ChatParty help:\n<commands></gold>";
@@ -352,6 +365,9 @@ public final class Config {
PARTY_HELP_CHAT = getString("party.help.chat", PARTY_HELP_CHAT); PARTY_HELP_CHAT = getString("party.help.chat", PARTY_HELP_CHAT);
} }
public static String CUSTOM_CHANNEL_TOGGLED = "<yellow>Toggled <channel> <status>.</yellow>";
public static Component TOGGLED_ON = null;
public static Component TOGGLED_OFF = null;
private static void chatChannels() { private static void chatChannels() {
ConfigurationNode node = getNode("chat-channels"); ConfigurationNode node = getNode("chat-channels");
if (node.empty()) { if (node.empty()) {
@@ -369,13 +385,17 @@ public final class Config {
getList(key + "servers", Collections.EMPTY_LIST), getList(key + "servers", Collections.EMPTY_LIST),
getBoolean(key + "proxy", false)); getBoolean(key + "proxy", false));
} }
CUSTOM_CHANNEL_TOGGLED = getString("chat-channels-messages.channel-toggled", CUSTOM_CHANNEL_TOGGLED);
TOGGLED_ON = Utility.parseMiniMessage(getString("chat-channels-messages.channel-on", "<green>on</green><gray>"));
TOGGLED_OFF = Utility.parseMiniMessage(getString("chat-channels-messages.channel-off", "<red>off</red><gray>"));
} }
public static String SERVERMUTEPERMISSION = "chat.command.mute-server"; public static String SERVERMUTEPERMISSION = "chat.command.mute-server";
public static String SPYPERMISSION = "chat.socialspy"; public static String SPYPERMISSION = "chat.socialspy";
private static void permissions() { private static void permissions() {
SERVERMUTEPERMISSION = getString("permissions.server-mute", SERVERMUTEPERMISSION); SERVERMUTEPERMISSION = getString("permissions.server-mute", SERVERMUTEPERMISSION);
SPYPERMISSION = getString("permissions.server-mute", SPYPERMISSION); SPYPERMISSION = getString("permissions.spy-permission", SPYPERMISSION);
} }
public static String IP = "0.0.0.0"; public static String IP = "0.0.0.0";
@@ -416,6 +436,7 @@ public final class Config {
public static HashMap<String, Long> serverChannelId = new HashMap<>(); public static HashMap<String, Long> serverChannelId = new HashMap<>();
public static String REPORT_SENT = "<green>Your report was sent, staff will contact you asap to help resolve your issue!</green>"; public static String REPORT_SENT = "<green>Your report was sent, staff will contact you asap to help resolve your issue!</green>";
public static String REPORT_TOO_SHORT = "<red>Please ensure your report is descriptive. We require at least 3 words per report</red>";
private static void loadChannelIds() { private static void loadChannelIds() {
serverChannelId.clear(); serverChannelId.clear();
serverChannelId.put("general", getLong("discord-channel-id.general", (long) -1)); serverChannelId.put("general", getLong("discord-channel-id.general", (long) -1));
@@ -430,10 +451,101 @@ public final class Config {
serverChannelId.put(key.toLowerCase(), channelId); serverChannelId.put(key.toLowerCase(), channelId);
} }
REPORT_SENT = getString("messages.report-sent", REPORT_SENT); REPORT_SENT = getString("messages.report-sent", REPORT_SENT);
REPORT_TOO_SHORT = getString("messages.report-too-short", REPORT_TOO_SHORT);
}
public static List<String> SILENT_JOIN_COMMAND_ALIASES = new ArrayList<>();
public static String SILENT_JOIN_NO_SERVER = "<red>Unable to find destination server</red>";
public static String SILENT_JOIN_JOINING = "<green>Sending you to <server> silently.</green>";
public static String SILENT_JOIN_JOINED_FROM = "<gold>* <player> silent joined from <from_server>...</gold>";
public static String SILENT_JOIN_JOINED = "<gold>* <player> silent joined...</gold>";
private static void silentJoinCommand() {
SILENT_JOIN_COMMAND_ALIASES = getList("commands.silent-join.aliases", Lists.newArrayList("sj"));
SILENT_JOIN_NO_SERVER = getString("commands.silent-join.no-server", SILENT_JOIN_NO_SERVER);
SILENT_JOIN_JOINING = getString("commands.silent-join.joining", SILENT_JOIN_JOINING);
SILENT_JOIN_JOINED_FROM = getString("commands.silent-join.joined-from", SILENT_JOIN_JOINED_FROM);
SILENT_JOIN_JOINED = getString("commands.silent-join.joined", SILENT_JOIN_JOINED);
} }
public static String HELP_REPORT = "<red>/report <message></red>"; public static String HELP_REPORT = "<red>/report <message></red>";
public static String FIRST_JOIN = "<green>* Welcome <light_purple><player></light_purple> to Altitude! They've joined for the first time.</green>";
private static void loadMessages() { private static void loadMessages() {
HELP_REPORT = getString("settings.mail.mail-sent", HELP_REPORT); HELP_REPORT = getString("settings.mail.mail-sent", HELP_REPORT);
FIRST_JOIN = getString("settings.first-join.message", FIRST_JOIN);
}
public static String EMOTELIST_HEADER = "<bold>Available Chat Emotes</bold><newline>";
public static String EMOTELIST_ITEM = "<insert:\"<regex>\"><gold><regex></gold> : <emote></insert><newline>";
public static String EMOTELIST_FOOTER = "<green>----<< <gray>Prev</gray> <page> <gray>/</gray> <pages> <gray>Next</gray> >>----";
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 = "<yellow>Your nickname was changed to <nickname><yellow>.";
public static String NICK_NOT_CHANGED = "<yellow>Your nickname request was denied.";
public static String NICK_RESET = "<yellow>Nickname changed back to normal.";
public static String NICK_CHANGED_OTHERS = "<gold><targetplayer><yellow>'s nickname was changed to <nickname><yellow>.";
public static String NICK_TARGET_NICK_CHANGE = "<yellow>Your nickname was changed to <nickname> <yellow>by <sendernick><yellow>";
public static String NICK_RESET_OTHERS = "<gold><player><gold>'s <yellow>nickname was reset back to normal.";
public static String NICK_INVALID_CHARACTERS = "<yellow>You can only use letters and numbers in nicknames.";
public static String NICK_INVALID_LENGTH = "<yellow>Nicknames need to be between 3 to 16 characters long.";
public static String NICK_PLAYER_NOT_ONLINE = "<red>That player is not online.";
public static String NICK_BLOCKED_COLOR_CODES = "<yellow>You have blocked color codes in that nickname.";
public static String NICK_USER_NOT_FOUND = "<red>Failed to set nickname from player, try again from a server this player has been on before.";
public static String NICK_ACCEPTED = "<green>You accepted <targetplayer><green>'s nickname. They are now called <newnick><green>.";
public static String NICK_DENIED = "<green>You denied <targetplayer><green>'s nickname. They are still called <oldnick><green>.";
public static String NICK_ALREADY_HANDLED = "<red><targetplayer><red>'s nickname was already accepted or denied.";
public static String NICK_NO_LUCKPERMS = "<red>Due to an issue with LuckPerms /nick try won't work at the moment.";
public static String NICK_TOO_SOON = "<red>Please wait <time><red> until requesting a new nickname";
public static String NICK_REQUEST_PLACED = "<green>Replaced your previous request <oldrequestednick><green> with <newrequestednick><green>.";
public static String NICK_REQUEST_NEW = "<green>New nickname request by <player><green>!";
public static String NICK_TRYOUT = "<white><prefix><white> <nick><gray>: <white>Hi, this is what my new nickname could look like!";
public static String NICK_REQUESTED = "<green>Your requested to be nicknamed <nick><green> has been received. Staff will accept or deny this request asap!";
public static String NICK_REVIEW_WAITING = "<green>There are <amount> nicknames waiting for review!";
public static String NICK_TAKEN = "<red>Someone else already has this nickname, or has this name as their username.";
public static String NICK_REQUESTS_ON_LOGIN = "<green>Current nick requests: <amount>";
public static long NICK_WAIT_TIME = 86400000;
public static List<String> NICK_ITEM_LORE = new ArrayList<>();
public static List<String> NICK_BLOCKED_COLOR_CODESLIST = new ArrayList<>();
public static List<String> NICK_ALLOWED_COLOR_CODESLIST = new ArrayList<>();
public static String NICK_CURRENT = "<gold>Current nickname: <nickname><white>(<insert:\"<currentnickname>\"><currentnickname></insert>)";
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("<aqua>New nick: <newnick>", "<aqua>Old nick: <oldnick>", "<aqua>Last changed: <lastchanged>", "<green>Left click to Accept <light_purple>| <red>Right 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);
}
public static String APRIL_FOOLS_RESET = "esrever";
private static void aprilFools() {
APRIL_FOOLS_RESET = getString("april-fools.reset", APRIL_FOOLS_RESET);
} }
} }
@@ -41,7 +41,7 @@ public final class PrefixConfig {
CONFIG_FILE = new File(Config.CONFIGPATH, "prefix.yml"); CONFIG_FILE = new File(Config.CONFIGPATH, "prefix.yml");
configLoader = YamlConfigurationLoader.builder() configLoader = YamlConfigurationLoader.builder()
.file(CONFIG_FILE) .file(CONFIG_FILE)
.nodeStyle(NodeStyle.FLOW) .nodeStyle(NodeStyle.BLOCK)
.build(); .build();
if (!CONFIG_FILE.getParentFile().exists()) { if (!CONFIG_FILE.getParentFile().exists()) {
if(!CONFIG_FILE.getParentFile().mkdirs()) { if(!CONFIG_FILE.getParentFile().mkdirs()) {
@@ -80,7 +80,7 @@ public final class PrefixConfig {
method.setAccessible(true); method.setAccessible(true);
method.invoke(instance); method.invoke(instance);
} catch (InvocationTargetException | IllegalAccessException ex) { } catch (InvocationTargetException | IllegalAccessException ex) {
throw Throwables.propagate(ex.getCause()); ex.printStackTrace();
} }
} }
} }
@@ -88,7 +88,7 @@ public final class PrefixConfig {
try { try {
configLoader.save(config); configLoader.save(config);
} catch (IOException ex) { } catch (IOException ex) {
throw Throwables.propagate(ex.getCause()); ex.printStackTrace();
} }
} }
@@ -96,7 +96,7 @@ public final class PrefixConfig {
try { try {
configLoader.save(config); configLoader.save(config);
} catch (IOException ex) { } catch (IOException ex) {
throw Throwables.propagate(ex.getCause()); ex.printStackTrace();
} }
} }
@@ -109,6 +109,7 @@ public final class PrefixConfig {
try { try {
config.node(splitPath(path)).set(def); config.node(splitPath(path)).set(def);
} catch (SerializationException e) { } catch (SerializationException e) {
e.printStackTrace();
} }
} }
} }
@@ -118,6 +119,7 @@ public final class PrefixConfig {
if(config.node(splitPath(path)).virtual()) if(config.node(splitPath(path)).virtual())
config.node(splitPath(path)).set(io.leangen.geantyref.TypeToken.get(String.class), def); config.node(splitPath(path)).set(io.leangen.geantyref.TypeToken.get(String.class), def);
} catch(SerializationException ex) { } catch(SerializationException ex) {
ex.printStackTrace();
} }
} }
@@ -3,14 +3,12 @@ package com.alttd.chat.config;
import com.alttd.chat.managers.RegexManager; import com.alttd.chat.managers.RegexManager;
import com.alttd.chat.objects.ChatFilter; import com.alttd.chat.objects.ChatFilter;
import com.alttd.chat.util.ALogger; import com.alttd.chat.util.ALogger;
import com.google.common.base.Throwables;
import io.leangen.geantyref.TypeToken; import io.leangen.geantyref.TypeToken;
import org.spongepowered.configurate.ConfigurationNode; import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.ConfigurationOptions; import org.spongepowered.configurate.ConfigurationOptions;
import org.spongepowered.configurate.serialize.SerializationException; import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.yaml.NodeStyle; import org.spongepowered.configurate.yaml.NodeStyle;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader; import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import org.yaml.snakeyaml.DumperOptions;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -38,7 +36,7 @@ public final class RegexConfig {
CONFIG_FILE = new File(Config.CONFIGPATH, "filters.yml"); CONFIG_FILE = new File(Config.CONFIGPATH, "filters.yml");
configLoader = YamlConfigurationLoader.builder() configLoader = YamlConfigurationLoader.builder()
.file(CONFIG_FILE) .file(CONFIG_FILE)
.nodeStyle(NodeStyle.FLOW) .nodeStyle(NodeStyle.BLOCK)
.build(); .build();
if (!CONFIG_FILE.getParentFile().exists()) { if (!CONFIG_FILE.getParentFile().exists()) {
@@ -78,7 +76,7 @@ public final class RegexConfig {
method.setAccessible(true); method.setAccessible(true);
method.invoke(instance); method.invoke(instance);
} catch (InvocationTargetException | IllegalAccessException ex) { } catch (InvocationTargetException | IllegalAccessException ex) {
throw Throwables.propagate(ex.getCause()); ex.printStackTrace();
} }
} }
} }
@@ -86,7 +84,7 @@ public final class RegexConfig {
try { try {
configLoader.save(config); configLoader.save(config);
} catch (IOException ex) { } catch (IOException ex) {
throw Throwables.propagate(ex.getCause()); ex.printStackTrace();
} }
} }
@@ -180,13 +178,18 @@ public final class RegexConfig {
String regex = entry.getValue().node("regex").getString(); String regex = entry.getValue().node("regex").getString();
String replacement = entry.getValue().node("replacement").getString(); String replacement = entry.getValue().node("replacement").getString();
List<String> exclusions = entry.getValue().node("exclusions").getList(io.leangen.geantyref.TypeToken.get(String.class), new ArrayList<>()); List<String> exclusions = entry.getValue().node("exclusions").getList(io.leangen.geantyref.TypeToken.get(String.class), new ArrayList<>());
boolean disableInPrivate = false;
ConfigurationNode node = entry.getValue().node("disable-in-private");
if (node != null) {
disableInPrivate = node.getBoolean();
}
if (type == null || type.isEmpty() || regex == null || regex.isEmpty()) { if (type == null || type.isEmpty() || regex == null || regex.isEmpty()) {
ALogger.warn("Filter: " + name + " was set up incorrectly"); ALogger.warn("Filter: " + name + " was set up incorrectly");
} else { } else {
if (replacement == null || replacement.isEmpty()) { if (replacement == null || replacement.isEmpty()) {
replacement = name; replacement = name;
} }
ChatFilter chatFilter = new ChatFilter(name, type, regex, replacement, exclusions); ChatFilter chatFilter = new ChatFilter(name, type, regex, replacement, exclusions, disableInPrivate);
RegexManager.addFilter(chatFilter); RegexManager.addFilter(chatFilter);
} }
} catch(SerializationException ex) { } catch(SerializationException ex) {
@@ -74,9 +74,11 @@ public final class ServerConfig {
public boolean GLOBALCHAT = false; public boolean GLOBALCHAT = false;
public boolean JOINLEAVEMSSAGES = true; public boolean JOINLEAVEMSSAGES = true;
public boolean MUTED = false; public boolean MUTED = false;
public boolean FIRST_JOIN_MESSAGES = false;
private void ServerSettings() { private void ServerSettings() {
GLOBALCHAT = getBoolean("global-chat-enabled", GLOBALCHAT); GLOBALCHAT = getBoolean("global-chat-enabled", GLOBALCHAT);
JOINLEAVEMSSAGES = getBoolean("joinleave-messages-enabled", JOINLEAVEMSSAGES); JOINLEAVEMSSAGES = getBoolean("joinleave-messages-enabled", JOINLEAVEMSSAGES);
MUTED = getBoolean("server-muted", MUTED); MUTED = getBoolean("server-muted", MUTED);
FIRST_JOIN_MESSAGES = getBoolean("first-join-messages", FIRST_JOIN_MESSAGES);
} }
} }
@@ -1,18 +1,13 @@
package com.alttd.chat.database; package com.alttd.chat.database;
import com.alttd.chat.managers.PartyManager; import com.alttd.chat.managers.PartyManager;
import com.alttd.chat.objects.ChatUser; import com.alttd.chat.objects.*;
import com.alttd.chat.objects.Mail;
import com.alttd.chat.objects.Party;
import com.alttd.chat.objects.PartyUser;
import com.alttd.chat.objects.channels.Channel; import com.alttd.chat.objects.channels.Channel;
import com.alttd.chat.util.ALogger; import com.alttd.chat.util.ALogger;
import java.sql.*; import java.sql.*;
import java.util.ArrayList; import java.util.*;
import java.util.HashSet; import java.util.Date;
import java.util.List;
import java.util.UUID;
public class Queries { 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 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 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`))"); 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 { try {
Connection connection = DatabaseConnection.getConnection(); Connection connection = DatabaseConnection.getConnection();
@@ -39,6 +35,51 @@ public class Queries {
//----------------------------------------- //-----------------------------------------
//Nicknames //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<String> 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<String> 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) { public static String getNickname(UUID uuid) {
// View has been created. // View has been created.
@@ -564,4 +605,172 @@ public class Queries {
e.printStackTrace(); 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<Nick> getNicknamesList() {
ArrayList<Nick> 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();
}
} }
@@ -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
}
}
@@ -2,10 +2,10 @@ package com.alttd.chat.managers;
import com.alttd.chat.database.Queries; import com.alttd.chat.database.Queries;
import com.alttd.chat.objects.ChatUser; import com.alttd.chat.objects.ChatUser;
import com.alttd.chat.objects.Mail;
import java.util.*; import java.util.Map;
import java.util.stream.Collectors; import java.util.TreeMap;
import java.util.UUID;
public final class ChatUserManager { public final class ChatUserManager {
@@ -15,15 +15,15 @@ public final class ChatUserManager {
chatUsers = new TreeMap<>(); chatUsers = new TreeMap<>();
} }
public static void addUser(ChatUser user) { public static synchronized void addUser(ChatUser user) {
chatUsers.put(user.getUuid(), user); chatUsers.put(user.getUuid(), user);
} }
public static void removeUser(ChatUser user) { public static synchronized void removeUser(ChatUser user) {
chatUsers.remove(user.getUuid()); chatUsers.remove(user.getUuid());
} }
public static ChatUser getChatUser(UUID uuid) { public static synchronized ChatUser getChatUser(UUID uuid) {
return chatUsers.computeIfAbsent(uuid, k -> Queries.loadChatUser(uuid)); return chatUsers.computeIfAbsent(uuid, k -> Queries.loadChatUser(uuid));
} }
@@ -3,25 +3,42 @@ package com.alttd.chat.managers;
import com.alttd.chat.ChatAPI; import com.alttd.chat.ChatAPI;
import com.alttd.chat.config.RegexConfig; import com.alttd.chat.config.RegexConfig;
import com.alttd.chat.objects.ChatFilter; import com.alttd.chat.objects.ChatFilter;
import com.alttd.chat.objects.FilterType;
import com.alttd.chat.objects.ModifiableString; import com.alttd.chat.objects.ModifiableString;
import com.alttd.chat.util.ALogger; import com.alttd.chat.util.ALogger;
import net.luckperms.api.cacheddata.CachedPermissionData; import net.luckperms.api.cacheddata.CachedPermissionData;
import net.luckperms.api.model.user.User; import net.luckperms.api.model.user.User;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class RegexManager { public class RegexManager {
private static List<ChatFilter> chatFilters; private static List<ChatFilter> chatFilters;
private static final Pattern pattern = Pattern.compile("(.)\\1{4,}"); private static final Pattern pattern = Pattern.compile("(.)\\1{4,}");
private static final List<ChatFilter> emotes = new ArrayList<>();
public static final List<String> emotesList = new ArrayList<>();
public static void initialize() { public static void initialize() {
chatFilters = new ArrayList<>(); chatFilters = new ArrayList<>();
RegexConfig.init(); RegexConfig.init();
loadEmotes();
}
private static void loadEmotes() {
emotes.clear();
for(ChatFilter chatFilter : chatFilters) {
if (chatFilter.getType() != FilterType.EMOTE) continue;
emotes.add(chatFilter);
emotesList.add(chatFilter.getRegex());
}
} }
public static void addFilter(ChatFilter filter) { public static void addFilter(ChatFilter filter) {
@@ -29,17 +46,24 @@ public class RegexManager {
} }
public static boolean filterText(String playerName, UUID uuid, ModifiableString modifiableString, String channel) { // TODO loop all objects in the list and check if they violate based on the MATCHER public static boolean filterText(String playerName, UUID uuid, ModifiableString modifiableString, String channel) { // TODO loop all objects in the list and check if they violate based on the MATCHER
return filterText(playerName, uuid, modifiableString, true, channel); return filterText(playerName, uuid, modifiableString, true, channel, null);
} }
public static boolean filterText(String playerName, UUID uuid, ModifiableString modifiableString, boolean matcher, String channel) { public static boolean filterText(String playerName, UUID uuid, ModifiableString modifiableString, boolean matcher, String channel) {
return filterText(playerName, uuid, modifiableString, matcher, channel, null);
}
public static boolean filterText(String playerName, UUID uuid, ModifiableString modifiableString, boolean matcher, String channel, Consumer<FilterType> filterAction) {
User user = ChatAPI.get().getLuckPerms().getUserManager().getUser(uuid); User user = ChatAPI.get().getLuckPerms().getUserManager().getUser(uuid);
if (user == null) { if (user == null) {
ALogger.warn("Tried to check chat filters for a user who doesn't exist in LuckPerms"); ALogger.warn("Tried to check chat filters for a user who doesn't exist in LuckPerms");
return false; return false;
} }
CachedPermissionData permissionData = user.getCachedData().getPermissionData(); CachedPermissionData permissionData = user.getCachedData().getPermissionData();
boolean isPrivate = channel.equals("party");
for(ChatFilter chatFilter : chatFilters) { for(ChatFilter chatFilter : chatFilters) {
if (isPrivate && chatFilter.isDisabledInPrivate())
continue;
switch (chatFilter.getType()) { switch (chatFilter.getType()) {
case CHAT: case CHAT:
break; break;
@@ -50,7 +74,8 @@ public class RegexManager {
if(!permissionData.checkPermission("chat.bypass-filter-channel." + channel).asBoolean() && if(!permissionData.checkPermission("chat.bypass-filter-channel." + channel).asBoolean() &&
!permissionData.checkPermission("chat.bypass-filter." + chatFilter.getName()).asBoolean() && !permissionData.checkPermission("chat.bypass-filter." + chatFilter.getName()).asBoolean() &&
chatFilter.matches(modifiableString)) { // todo find a better way to do this? chatFilter.matches(modifiableString)) { // todo find a better way to do this?
ALogger.info(playerName + " triggered the chat filter for " + chatFilter.getName() + "."); ALogger.info(playerName + " triggered the chat filter for " + chatFilter.getName()
+ " with: " + modifiableString.string() + ".");
return false; return false;
} }
break; break;
@@ -59,9 +84,35 @@ public class RegexManager {
chatFilter.replaceMatcher(modifiableString); chatFilter.replaceMatcher(modifiableString);
} }
break; break;
case PUNISH:
if (permissionData.checkPermission("chat.bypass-punish").asBoolean())
break;
if (chatFilter.matches(modifiableString)) {
ALogger.info(playerName + " triggered the punish filter for " + chatFilter.getName()
+ " with: " + modifiableString.string() + ".");
if (filterAction == null){
ALogger.info("No filterAction was provided, not doing anything");
return false;
}
Player player = Bukkit.getPlayer(uuid);
if (player == null) {
ALogger.warn("Tried to punish a player who triggered the filter, but the player is offline.");
return false;
}
filterAction.accept(FilterType.PUNISH);
return false;
}
} }
} }
return true; return true;
} }
public static List<ChatFilter> getChatFilters() {
return chatFilters;
}
public static List<ChatFilter> getEmoteFilters() {
return emotes;
}
} }
@@ -1,5 +1,10 @@
package com.alttd.chat.objects; package com.alttd.chat.objects;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextReplacementConfig;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.Style;
import java.util.List; import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -12,14 +17,16 @@ public class ChatFilter {
private final Pattern pattern; private final Pattern pattern;
private final String replacement; private final String replacement;
private final List<String> exclusions; private final List<String> exclusions;
private final boolean disableInPrivate;
public ChatFilter(String name, String type, String regex, String replacement, List<String> exclusions) { public ChatFilter(String name, String type, String regex, String replacement, List<String> exclusions, boolean disableInPrivate) {
this.name = name; this.name = name;
this.filterType = FilterType.getType(type); this.filterType = FilterType.getType(type);
this.regex = regex; this.regex = regex;
this.pattern = Pattern.compile(getRegex(), Pattern.CASE_INSENSITIVE); this.pattern = Pattern.compile(getRegex(), Pattern.CASE_INSENSITIVE);
this.replacement = replacement; this.replacement = replacement;
this.exclusions = exclusions; this.exclusions = exclusions;
this.disableInPrivate = disableInPrivate;
} }
public String getName() { public String getName() {
@@ -42,12 +49,22 @@ public class ChatFilter {
return this.exclusions; return this.exclusions;
} }
public boolean isDisabledInPrivate() {
return disableInPrivate;
}
public boolean matches(ModifiableString filterableString) { public boolean matches(ModifiableString filterableString) {
String input = filterableString.string(); String input = filterableString.string();
Matcher matcher = pattern.matcher(input); Matcher matcher = pattern.matcher(input);
while (matcher.find()) while (matcher.find())
if (!isException(input, matcher.start())) { if (!isException(input, matcher.start())) {
filterableString.string(filterableString.string().replaceFirst(matcher.group(), "<gold>" + matcher.group() + "</gold>")); // filterableString.string(filterableString.string().replaceFirst(matcher.group(), "<gold>" + matcher.group() + "</gold>"));
filterableString.string(filterableString.component()
.replaceText(
TextReplacementConfig.builder()
.match(matcher.pattern())
.replacement(Component.text(matcher.group()).style(Style.style(NamedTextColor.GOLD)))
.build()));
return true; return true;
} }
return matcher.matches(); return matcher.matches();
@@ -76,7 +93,12 @@ public class ChatFilter {
while (matcher.find()) { while (matcher.find()) {
String group = matcher.group(); // todo debug String group = matcher.group(); // todo debug
if (getExclusions().stream().noneMatch(s -> s.equalsIgnoreCase(group))) { // idk how heavy this is:/ if (getExclusions().stream().noneMatch(s -> s.equalsIgnoreCase(group))) { // idk how heavy this is:/
modifiableString.string(input.replace(group, getReplacement())); modifiableString.replace(
TextReplacementConfig.builder()
.matchLiteral(group)
.replacement(getReplacement())
.build()
);
} }
} }
} }
@@ -92,7 +114,10 @@ public class ChatFilter {
Matcher matcher = pattern.matcher(input); Matcher matcher = pattern.matcher(input);
while (matcher.find()) { while (matcher.find()) {
String group = matcher.group(); String group = matcher.group();
modifiableString.string(input.replace(group, group.substring(0, length))); modifiableString.replace(TextReplacementConfig.builder()
.matchLiteral(group)
.replacement(Component.text(group.substring(0, length), modifiableString.component().color()))
.build());
} }
} }
} }
@@ -21,6 +21,7 @@ public class ChatUser {
// private Component prefixAll; // doesn't need saving, we get this from luckperms // private Component prefixAll; // doesn't need saving, we get this from luckperms
//private boolean toggleGc; // should be saved, this toggles if the player can see and use global chat //private boolean toggleGc; // should be saved, this toggles if the player can see and use global chat
private String replyTarget; // reply target for use in /msg i don't mind setting this to null on login, feedback? private String replyTarget; // reply target for use in /msg i don't mind setting this to null on login, feedback?
private String replyContinueTarget; // reply target for use in /c
private long gcCooldown; // the time when they last used gc, is used for the cooldown, i wouldn't save this, but setting this to the login time means they can't use gc for 30 seconds after logging in private long gcCooldown; // the time when they last used gc, is used for the cooldown, i wouldn't save this, but setting this to the login time means they can't use gc for 30 seconds after logging in
private boolean spy; private boolean spy;
private List<Mail> mails; // mails aren't finalized yet, so for now a table sender, reciever, sendtime, readtime(if emtpy mail isn't read yet?, could also do a byte to control this), the actual message private List<Mail> mails; // mails aren't finalized yet, so for now a table sender, reciever, sendtime, readtime(if emtpy mail isn't read yet?, could also do a byte to control this), the actual message
@@ -44,7 +45,8 @@ public class ChatUser {
// //
// prefixAll = Utility.getPrefix(uuid, false); // prefixAll = Utility.getPrefix(uuid, false);
replyTarget = null; replyTarget = "";
replyContinueTarget = "";
gcCooldown = System.currentTimeMillis(); // players can't use gc for 30 seconds after logging in if we use this? gcCooldown = System.currentTimeMillis(); // players can't use gc for 30 seconds after logging in if we use this?
mails = Queries.getMails(uuid); mails = Queries.getMails(uuid);
ignoredPlayers = Queries.getIgnoredUsers(uuid); ignoredPlayers = Queries.getIgnoredUsers(uuid);
@@ -101,10 +103,18 @@ public class ChatUser {
return replyTarget; return replyTarget;
} }
public String getReplyContinueTarget() {
return replyContinueTarget;
}
public void setReplyTarget(String replyTarget) { public void setReplyTarget(String replyTarget) {
this.replyTarget = replyTarget; this.replyTarget = replyTarget;
} }
public void setReplyContinueTarget(String replyTarget) {
this.replyContinueTarget = replyTarget;
}
public List<Mail> getMails() { public List<Mail> getMails() {
return mails; return mails;
} }
@@ -170,4 +180,8 @@ public class ChatUser {
} }
setDisplayName(name); setDisplayName(name);
} }
public String getNickNameString() {
return name;
}
} }
@@ -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<UUID, EmoteList> 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);
}
}
@@ -2,9 +2,11 @@ package com.alttd.chat.objects;
public enum FilterType { public enum FilterType {
REPLACE("replace"), REPLACE("replace"),
EMOTE("emote"),
CHAT("chat"), CHAT("chat"),
REPLACEMATCHER("replacematcher"), REPLACEMATCHER("replacematcher"),
BLOCK("block"); BLOCK("block"),
PUNISH("punish");
private final String name; private final String name;
@@ -1,17 +1,68 @@
package com.alttd.chat.objects; package com.alttd.chat.objects;
public class ModifiableString { import net.kyori.adventure.text.Component;
private String string; import net.kyori.adventure.text.JoinConfiguration;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TextReplacementConfig;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
public ModifiableString(String string) { import java.util.Collections;
this.string = string; import java.util.List;
import java.util.stream.Collectors;
public class ModifiableString {
private Component text;
public ModifiableString(Component text) {
this.text = text;
} }
public void string(String string) { public void string(Component text) {
this.string = string; this.text = text;
}
public void replace(TextReplacementConfig textReplacementConfig) {
text = text.replaceText(textReplacementConfig);
} }
public String string() { public String string() {
return string; return PlainTextComponentSerializer.plainText().serialize(text);
}
public Component component() {
return text;
}
public void reverse() {
text = reverseComponent(text);
}
public Component reverseComponent(Component component) {
if (!(component instanceof TextComponent textComponent)) {
return Component.text("")
.append(Component.join(JoinConfiguration.noSeparators(), reverseChildren(component.children())));
}
String content = textComponent.content();
String reversedContent = new StringBuilder(content).reverse().toString();
List<Component> reversedChildren = reverseChildren(component.children());
return Component.text("")
.append(Component.join(JoinConfiguration.noSeparators(), reversedChildren)
.append(Component.text(reversedContent, component.style())));
}
public List<Component> reverseChildren(List<Component> children) {
return children.stream()
.map(this::reverseComponent)
.collect(Collectors.collectingAndThen(Collectors.toList(), list -> {
Collections.reverse(list);
return list;
}));
}
public void removeStringAtStart(String s) {
text = text.replaceText(TextReplacementConfig.builder().match("^" + s).replacement("").build());
} }
} }
@@ -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;
}
}
@@ -48,6 +48,7 @@ public class Party {
.findFirst(); .findFirst();
if (first.isEmpty()) return; if (first.isEmpty()) return;
partyUsers.remove(first.get()); partyUsers.remove(first.get());
chatUser.setPartyId(-1);
Queries.removePartyUser(uuid); Queries.removePartyUser(uuid);
} }
@@ -0,0 +1,62 @@
package com.alttd.chat.objects;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public abstract class Toggleable {
private static final List<Toggleable> togglableClasses = new ArrayList<>();
public Toggleable() {
togglableClasses.add(this);
}
public static Toggleable getToggleable(UUID uuid) {
for (Toggleable toggleableClass : togglableClasses) {
if (toggleableClass.isToggled(uuid))
return toggleableClass;
}
return null;
}
public abstract boolean isToggled(UUID uuid);
public abstract void setOff(UUID uuid);
public boolean toggle(UUID uuid) {
if (isToggled(uuid)) {
setOff(uuid);
return (false);
}
for (Toggleable toggleable : togglableClasses) {
if (toggleable.isToggled(uuid)) {
setOff(uuid);
break;
}
}
setOn(uuid);
return (true);
}
public abstract void setOn(UUID uuid);
public static void disableToggles(UUID uuid) {
for (Toggleable toggleable : togglableClasses) {
if (toggleable.isToggled(uuid)) {
toggleable.setOff(uuid);
}
}
}
public void sendMessage(Player player, Component message) {
sendMessage(player, PlainTextComponentSerializer.plainText().serialize(message));
}
public abstract void sendMessage(Player player, String message);
}
@@ -3,7 +3,7 @@ package com.alttd.chat.objects.channels;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
public abstract class Channel { public class Channel {
public static HashMap<String, Channel> channels = new HashMap<>(); public static HashMap<String, Channel> channels = new HashMap<>();
protected String permission; protected String permission;
@@ -1,6 +1,6 @@
package com.alttd.chat.objects.channels; package com.alttd.chat.objects.channels;
public class DefaultChannel extends Channel{ public abstract class DefaultChannel extends Channel{
public DefaultChannel(String channelName, String format, boolean proxy) { public DefaultChannel(String channelName, String format, boolean proxy) {
super(channelName, format, proxy); super(channelName, format, proxy);
} }
@@ -0,0 +1,20 @@
package com.alttd.chat.util;
public class Pair<X, Y> {
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;
}
}
@@ -3,15 +3,16 @@ package com.alttd.chat.util;
import com.alttd.chat.ChatAPI; import com.alttd.chat.ChatAPI;
import com.alttd.chat.config.Config; import com.alttd.chat.config.Config;
import net.kyori.adventure.text.Component; 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.MiniMessage;
import net.kyori.adventure.text.minimessage.placeholder.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.kyori.adventure.text.minimessage.placeholder.PlaceholderResolver; import net.kyori.adventure.text.minimessage.tag.standard.StandardTags;
import net.kyori.adventure.text.minimessage.placeholder.Replacement;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.luckperms.api.LuckPerms; import net.luckperms.api.LuckPerms;
import net.luckperms.api.model.group.Group; import net.luckperms.api.model.group.Group;
import net.luckperms.api.model.user.User; import net.luckperms.api.model.user.User;
import net.luckperms.api.node.Node; import net.luckperms.api.node.Node;
import org.bukkit.permissions.Permission;
import java.util.*; import java.util.*;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@@ -20,6 +21,7 @@ import java.util.stream.Collectors;
public class Utility { public class Utility {
private static final List<String> EMPTY_LIST = new ArrayList<>();
static final Pattern DEFAULT_URL_PATTERN = Pattern.compile("(?:(https?)://)?([-\\w_.]+\\.\\w{2,})(/\\S*)?"); static final Pattern DEFAULT_URL_PATTERN = Pattern.compile("(?:(https?)://)?([-\\w_.]+\\.\\w{2,})(/\\S*)?");
private static MiniMessage miniMessage = null; private static MiniMessage miniMessage = null;
@@ -47,6 +49,38 @@ public class Utility {
colors.put("&f", "<white>"); colors.put("&f", "<white>");
} }
public static HashMap<String, Pair<TagResolver, List<String>>> 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("<bold>", "<b>")));
formattingPerms.put("chat.format.italic",
new Pair<>(StandardTags.decorations(TextDecoration.ITALIC), List.of("<italic>", "<i>")));
formattingPerms.put("chat.format.underlined",
new Pair<>(StandardTags.decorations(TextDecoration.UNDERLINED), List.of("<underlined>", "<u>")));
formattingPerms.put("chat.format.strikethrough",
new Pair<>(StandardTags.decorations(TextDecoration.STRIKETHROUGH), List.of("<strikethrough>", "<st>")));
formattingPerms.put("chat.format.obfuscated",
new Pair<>(StandardTags.decorations(TextDecoration.OBFUSCATED), List.of("<obfuscated>", "<obf>")));
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("<rainbow>")));
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("<reset>", "<r>")));
formattingPerms.put("chat.format.newline",
new Pair<>(StandardTags.newline(), List.of("<newline>")));
}
public static String parseColors(String message) { public static String parseColors(String message) {
if (message == null) return ""; if (message == null) return "";
// split string in sections and check those vs looping hashmap?:/ // split string in sections and check those vs looping hashmap?:/
@@ -215,6 +249,47 @@ public class Utility {
: Utility.parseMiniMessage(stringBuilder.toString()); : Utility.parseMiniMessage(stringBuilder.toString());
} }
public static boolean checkNickBrightEnough(String nickname) {
if (!nickname.matches(".*" + stringRegen + ".*")) {
return true;
}
Pattern pattern = Pattern.compile(stringRegen);
Matcher matcher = pattern.matcher(nickname);
while (matcher.find()) {
String hexColor = matcher.group();
if (!checkHexHighEnough(hexColor)) {
return false;
}
}
return true;
}
private static boolean checkHexHighEnough(String hexColor) {
// Remove the leading "#" if present
if (hexColor.startsWith("{")) {
hexColor = hexColor.substring(1);
}
if (hexColor.startsWith("#")) {
hexColor = hexColor.substring(1);
}
// Extract the color parts
String redPart = hexColor.substring(0, 2);
String greenPart = hexColor.substring(2, 4);
String bluePart = hexColor.substring(4, 6);
// Convert the color parts to integers
int red = Integer.parseInt(redPart, 16);
int green = Integer.parseInt(greenPart, 16);
int blue = Integer.parseInt(bluePart, 16);
// Check if any part is over 30 in hexadecimal
return red > 0x30 || green > 0x30 || blue > 0x30;
}
public static String formatText(String message) { public static String formatText(String message) {
/* /*
.match(pattern) .match(pattern)
@@ -241,24 +316,24 @@ public class Utility {
return getMiniMessage().deserialize(message); return getMiniMessage().deserialize(message);
} }
public static Component parseMiniMessage(String message, Map<String, Replacement<?>> placeholders) { public static Component parseMiniMessage(String message, TagResolver placeholders) {
if (placeholders == null) { if (placeholders == null) {
return getMiniMessage().deserialize(message); return getMiniMessage().deserialize(message);
} else { } else {
return getMiniMessage().deserialize(message, PlaceholderResolver.map(placeholders)); return getMiniMessage().deserialize(message, placeholders);
} }
} }
public static Component parseMiniMessage(String message, Placeholder<?> ... placeholders) { public static Component parseMiniMessage(String message, TagResolver ... placeholders) {
if (placeholders == null) { if (placeholders == null) {
return getMiniMessage().deserialize(message); return getMiniMessage().deserialize(message);
} else { } else {
return getMiniMessage().deserialize(message, PlaceholderResolver.placeholders(placeholders)); return getMiniMessage().deserialize(message, TagResolver.resolver(placeholders));
} }
} }
public static String stripTokens(String input) { public static String stripTokens(String input) {
return getMiniMessage().stripTokens(input); return getMiniMessage().stripTags(input);
} }
public static MiniMessage getMiniMessage() { public static MiniMessage getMiniMessage() {
@@ -266,4 +341,13 @@ public class Utility {
return miniMessage; 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}(<)?(>)?}", "");
}
} }
+86
View File
@@ -0,0 +1,86 @@
import com.alttd.chat.config.Config;
import com.alttd.chat.objects.ModifiableString;
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.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import net.kyori.adventure.text.minimessage.MiniMessage;
public class ReverseTest {
@Test
public void testReverseString() {
String input = "Hello how are you doing today?";
String expectedOutput = new StringBuilder(input).reverse().toString();
MiniMessage miniMessage = MiniMessage.miniMessage();
ModifiableString modifiableString = new ModifiableString(miniMessage.deserialize(input));
modifiableString.reverse();
assertEquals(expectedOutput, modifiableString.string());
}
@Test
public void testRemoveKeyword() {
String input = "Hello how are you doing today?";
MiniMessage miniMessage = MiniMessage.miniMessage();
ModifiableString modifiableString = new ModifiableString(miniMessage.deserialize(Config.APRIL_FOOLS_RESET + " " + input));
modifiableString.removeStringAtStart(Config.APRIL_FOOLS_RESET + " ");
assertEquals(input, modifiableString.string());
}
@Test
public void testRemoveKeywordWithTags() {
MiniMessage miniMessage = MiniMessage.miniMessage();
String input = "<blue>" + Config.APRIL_FOOLS_RESET + " <red>Hello how are</red> you <blue>doing today</blue>?</blue>";
String expectedOutput = "Hello how are you doing today?";
Component deserialize = miniMessage.deserialize(input);
ModifiableString modifiableString = new ModifiableString(deserialize);
modifiableString.removeStringAtStart(Config.APRIL_FOOLS_RESET + " ");
assertEquals(expectedOutput, modifiableString.string());
}
@Test
public void testReverseStringWithTags() {
String input = "<red>Hello how are</red> you <blue>doing today</blue>?";
MiniMessage miniMessage = MiniMessage.miniMessage();
Component deserialize = miniMessage.deserialize(input);
ModifiableString modifiableString = new ModifiableString(deserialize);
String expectedOutput = new StringBuilder(PlainTextComponentSerializer.plainText().serialize(deserialize)).reverse().toString();
modifiableString.reverse();
assertEquals(expectedOutput, modifiableString.string());
}
@Test
public void complexTestReverseStringWithTags() {
String input = "<green><red>Hello <b>how</b> are</red> you <blue>doing today</blue><gold>?</gold></green>";
MiniMessage miniMessage = MiniMessage.miniMessage();
Component deserialize = miniMessage.deserialize(input);
ModifiableString modifiableString = new ModifiableString(deserialize);
String expectedOutput = new StringBuilder(PlainTextComponentSerializer.plainText().serialize(deserialize)).reverse().toString();
modifiableString.reverse();
assertEquals(expectedOutput, modifiableString.string());
}
@Test
public void extraComplexTestReverseStringWithTags() {
String input = "<gold>This <red>is</red> longer<green> <name> <red>Hello <b>how</b> are</red> you <test> <blue>doing <name> today</blue><gold>?</gold></green></gold>";
MiniMessage miniMessage = MiniMessage.miniMessage();
Component deserialize = miniMessage.deserialize(input, TagResolver.resolver(
Placeholder.component("name", miniMessage.deserialize("<red>Cool<blue><rainbow>_player_</rainbow>name</red>")),
Placeholder.parsed("test", "test replacement")
));
ModifiableString modifiableString = new ModifiableString(deserialize);
String expectedOutput = new StringBuilder(PlainTextComponentSerializer.plainText().serialize(deserialize)).reverse().toString();
modifiableString.reverse();
System.out.println(expectedOutput);
assertEquals(expectedOutput, modifiableString.string());
}
}
+19 -3
View File
@@ -5,8 +5,21 @@ plugins {
allprojects { allprojects {
group = "com.alttd.chat" group = "com.alttd.chat"
version = "1.0.0-SNAPSHOT" version = "2.0.0-SNAPSHOT"
description = "All in one minecraft chat plugin" description = "All in one minecraft chat plugin"
// repositories {
// mavenCentral()
// maven("https://repo.destro.xyz/snapshots") // Altitude - Galaxy
// maven("https://oss.sonatype.org/content/groups/public/") // Adventure
// maven("https://oss.sonatype.org/content/repositories/snapshots/") // Minimessage
// maven("https://oss.sonatype.org/content/repositories/") // Minimessage
// maven("https://nexus.velocitypowered.com/repository/") // Velocity
// maven("https://nexus.velocitypowered.com/repository/maven-public/") // Velocity
// maven("https://repo.spongepowered.org/maven") // Configurate
// maven("https://repo.extendedclip.com/content/repositories/placeholderapi/") // Papi
// maven("https://jitpack.io")
// }
} }
subprojects { subprojects {
@@ -48,13 +61,13 @@ dependencies {
tasks { tasks {
shadowJar { shadowJar {
archiveFileName.set("${project.name}-${project.version}.jar") archiveFileName.set("${project.name}.jar")
minimize() { minimize() {
exclude { it.moduleName == "galaxy" } exclude { it.moduleName == "galaxy" }
exclude { it.moduleName == "velocity" } exclude { it.moduleName == "velocity" }
} }
listOf( listOf(
"net.kyori.adventure.text.minimessage", // "net.kyori.adventure.text.minimessage",
"org.spongepowered.configurate" "org.spongepowered.configurate"
// ).forEach { relocate(it, "${rootProject.group}.lib.$it") } // ).forEach { relocate(it, "${rootProject.group}.lib.$it") }
).forEach { relocate(it, "${rootProject.group}.lib.${it.substringAfterLast(".")}") } ).forEach { relocate(it, "${rootProject.group}.lib.${it.substringAfterLast(".")}") }
@@ -64,4 +77,7 @@ tasks {
dependsOn(shadowJar) dependsOn(shadowJar)
} }
jar {
enabled = false
}
} }
+37 -8
View File
@@ -1,29 +1,58 @@
import java.io.FileOutputStream
import java.net.URL
plugins { plugins {
`maven-publish` `maven-publish`
id("com.github.johnrengelman.shadow") id("com.github.johnrengelman.shadow")
id("xyz.jpenilla.run-paper") version "1.0.6"
} }
dependencies { dependencies {
implementation(project(":api")) // API implementation(project(":api")) // API
compileOnly("com.alttd:Galaxy-API:1.18.1-R0.1-SNAPSHOT") { compileOnly("com.alttd:Galaxy-API:1.20.4-R0.1-SNAPSHOT") // Galaxy
exclude("net.kyori.adventure.text.minimessag")
} // Galaxy
compileOnly("net.kyori", "adventure-text-minimessage", "4.10.0-20220122.015731-43") { // Minimessage
exclude("net.kyori")
exclude("net.kyori.examination")
}
compileOnly("com.gitlab.ruany:LiteBansAPI:0.3.5") // move to proxy 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
compileOnly(files("../libs/CMI.jar"))
} }
tasks { tasks {
shadowJar { shadowJar {
archiveFileName.set("${project.name}-${project.version}.jar") archiveFileName.set("${rootProject.name}-${project.name}-${project.version}.jar")
// minimize() // minimize()
} }
build { build {
// setBuildDir("${rootProject.buildDir}")
dependsOn(shadowJar) dependsOn(shadowJar)
} }
runServer {
val dir = File(System.getProperty("user.home") + "/share/devserver/");
if (!dir.parentFile.exists()) {
dir.parentFile.mkdirs()
}
runDirectory.set(dir)
val fileName = "/galaxy.jar"
var file = File(dir.path + fileName)
if (!file.parentFile.exists()) {
file.parentFile.mkdirs()
}
if (!file.exists()) {
download("https://repo.destro.xyz/snapshots/com/alttd/Galaxy-Server/Galaxy-paperclip-1.19.2-R0.1-SNAPSHOT-reobf.jar", file)
}
serverJar(file)
minecraftVersion("1.19.2")
}
}
fun download(link: String, path: File) {
URL(link).openStream().use { input ->
FileOutputStream(path).use { output ->
input.copyTo(output)
}
}
} }
@@ -5,9 +5,12 @@ import com.alttd.chat.config.Config;
import com.alttd.chat.config.ServerConfig; import com.alttd.chat.config.ServerConfig;
import com.alttd.chat.database.DatabaseConnection; import com.alttd.chat.database.DatabaseConnection;
import com.alttd.chat.handler.ChatHandler; import com.alttd.chat.handler.ChatHandler;
import com.alttd.chat.listeners.BookListener;
import com.alttd.chat.listeners.ChatListener; import com.alttd.chat.listeners.ChatListener;
import com.alttd.chat.listeners.PlayerListener; import com.alttd.chat.listeners.PlayerListener;
import com.alttd.chat.listeners.PluginMessage; 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.Channel;
import com.alttd.chat.objects.channels.CustomChannel; import com.alttd.chat.objects.channels.CustomChannel;
import com.alttd.chat.util.ALogger; import com.alttd.chat.util.ALogger;
@@ -38,13 +41,14 @@ public class ChatPlugin extends JavaPlugin {
chatHandler = new ChatHandler(); chatHandler = new ChatHandler();
DatabaseConnection.initialize(); DatabaseConnection.initialize();
serverConfig = new ServerConfig(Bukkit.getServerName()); serverConfig = new ServerConfig(Bukkit.getServerName());
registerListener(new PlayerListener(), new ChatListener()); registerListener(new PlayerListener(serverConfig), new ChatListener(), new BookListener());
if(serverConfig.GLOBALCHAT) { if(serverConfig.GLOBALCHAT) {
registerCommand("globalchat", new GlobalChat()); registerCommand("globalchat", new GlobalChat());
registerCommand("toggleglobalchat", new ToggleGlobalChat()); registerCommand("toggleglobalchat", new ToggleGlobalChat());
} }
registerCommand("message", new Message()); registerCommand("message", new Message());
registerCommand("reply", new Reply()); registerCommand("reply", new Reply());
registerCommand("continue", new Continue());
registerCommand("ignore", new Ignore()); registerCommand("ignore", new Ignore());
registerCommand("unignore", new Unignore()); registerCommand("unignore", new Unignore());
registerCommand("muteserver", new MuteServer()); registerCommand("muteserver", new MuteServer());
@@ -52,6 +56,7 @@ public class ChatPlugin extends JavaPlugin {
registerCommand("chatclear", new ChatClear()); registerCommand("chatclear", new ChatClear());
// registerCommand("chatparty", new ChatParty()); // registerCommand("chatparty", new ChatParty());
registerCommand("p", new PartyChat()); registerCommand("p", new PartyChat());
registerCommand("emotes", new Emotes());
for (Channel channel : Channel.getChannels()) { for (Channel channel : Channel.getChannels()) {
if (!(channel instanceof CustomChannel customChannel)) continue; if (!(channel instanceof CustomChannel customChannel)) continue;
this.getServer().getCommandMap().register(channel.getChannelName().toLowerCase(), new ChatChannel(customChannel)); this.getServer().getCommandMap().register(channel.getChannelName().toLowerCase(), new ChatChannel(customChannel));
@@ -60,6 +65,11 @@ public class ChatPlugin extends JavaPlugin {
messageChannel = Config.MESSAGECHANNEL; messageChannel = Config.MESSAGECHANNEL;
getServer().getMessenger().registerOutgoingPluginChannel(this, messageChannel); getServer().getMessenger().registerOutgoingPluginChannel(this, messageChannel);
getServer().getMessenger().registerIncomingPluginChannel(this, messageChannel, new PluginMessage()); 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 @Override
@@ -1,20 +1,24 @@
package com.alttd.chat.commands; package com.alttd.chat.commands;
import com.alttd.chat.ChatPlugin; import com.alttd.chat.config.Config;
import com.alttd.chat.objects.channels.CustomChannel; import com.alttd.chat.objects.channels.CustomChannel;
import org.apache.commons.lang.StringUtils; import com.alttd.chat.util.ToggleableForCustomChannel;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand; import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Collections; import java.util.*;
public class ChatChannel extends BukkitCommand { public class ChatChannel extends BukkitCommand {
CustomChannel channel; CustomChannel channel;
String command; String command;
ToggleableForCustomChannel toggleableForCustomChannel;
private static List<ChatChannel> activeCommands = new ArrayList<>();
public ChatChannel(CustomChannel channel) { public ChatChannel(CustomChannel channel) {
super(channel.getChannelName().toLowerCase()); super(channel.getChannelName().toLowerCase());
@@ -23,6 +27,8 @@ public class ChatChannel extends BukkitCommand {
this.description = "Chat channel named " + channel.getChannelName() + "."; this.description = "Chat channel named " + channel.getChannelName() + ".";
this.usageMessage = "/" + command + " <message>"; this.usageMessage = "/" + command + " <message>";
this.setAliases(Collections.emptyList()); this.setAliases(Collections.emptyList());
activeCommands.add(this);
this.toggleableForCustomChannel = new ToggleableForCustomChannel(channel);
} }
@Override @Override
@@ -30,16 +36,18 @@ public class ChatChannel extends BukkitCommand {
if(!(sender instanceof Player player)) { // must be a player if(!(sender instanceof Player player)) { // must be a player
return true; return true;
} }
if(args.length == 0) return false;
if(args.length == 0 && player.hasPermission(channel.getPermission())) {
player.sendMiniMessage(Config.CUSTOM_CHANNEL_TOGGLED, TagResolver.resolver(
Placeholder.unparsed("channel", channel.getChannelName()),
Placeholder.component("status", toggleableForCustomChannel.toggle(player.getUniqueId())
? Config.TOGGLED_ON : Config.TOGGLED_OFF)));
return false;
}
String message = StringUtils.join(args, " ", 0, args.length); String message = StringUtils.join(args, " ", 0, args.length);
new BukkitRunnable() { toggleableForCustomChannel.sendMessage(player, message);
@Override
public void run() {
ChatPlugin.getInstance().getChatHandler().chatChannel(player, channel, message);
}
}.runTaskAsynchronously(ChatPlugin.getInstance());
return false; return false;
} }
@@ -3,8 +3,7 @@ package com.alttd.chat.commands;
import com.alttd.chat.util.Utility; import com.alttd.chat.util.Utility;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.placeholder.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.placeholder.PlaceholderResolver;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
@@ -25,10 +24,11 @@ public class ChatClear implements CommandExecutor {
for (Player player : Bukkit.getOnlinePlayers()) for (Player player : Bukkit.getOnlinePlayers())
if (!player.hasPermission("chat.clear-bypass")) if (!player.hasPermission("chat.clear-bypass"))
player.sendMessage(component); player.sendMessage(component);
Bukkit.getServer().sendMessage(miniMessage.deserialize( Bukkit.getServer().sendMessage(miniMessage.deserialize(
"<gold><player> cleared chat.</gold>", PlaceholderResolver.placeholders( "<gold><player> cleared chat.</gold>",
Placeholder.component("player", miniMessage.deserialize(sender.getName())) Placeholder.component("player",sender.name()))
))); );
return true; return true;
} }
} }
@@ -0,0 +1,27 @@
package com.alttd.chat.commands;
import com.alttd.chat.ChatPlugin;
import com.alttd.chat.managers.ChatUserManager;
import com.alttd.chat.objects.ChatUser;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class Continue implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if(!(sender instanceof Player player)) {
return true;
}
ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
if (user.getReplyContinueTarget() == null) return false;
if(args.length == 0) return false; // todo error message or command info
String message = StringUtils.join(args, " ", 0, args.length);
ChatPlugin.getInstance().getChatHandler().continuePrivateMessage(player, user.getReplyContinueTarget(), message);
return false;
}
}
@@ -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;
}
}
@@ -1,7 +1,7 @@
package com.alttd.chat.commands; package com.alttd.chat.commands;
import com.alttd.chat.ChatPlugin; import com.alttd.chat.ChatPlugin;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@@ -1,25 +0,0 @@
package com.alttd.chat.commands;
import com.alttd.chat.ChatPlugin;
import org.apache.commons.lang.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class Mail implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if(!(sender instanceof Player)) { // must be a player, @teri should console be able to /msg?
return true;
}
Player player = (Player) sender;
if(args.length > 2) return false; // todo error message or command info
String message = StringUtils.join(args, " ", 1, args.length);
ChatPlugin.getInstance().getChatHandler().privateMessage(player, args[0], message);
return false;
}
}
@@ -1,7 +1,9 @@
package com.alttd.chat.commands; package com.alttd.chat.commands;
import com.alttd.chat.ChatPlugin; import com.alttd.chat.ChatPlugin;
import org.apache.commons.lang.StringUtils; import com.alttd.chat.managers.ChatUserManager;
import com.alttd.chat.objects.ChatUser;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@@ -11,12 +13,13 @@ public class Message implements CommandExecutor {
@Override @Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if(!(sender instanceof Player)) { if(!(sender instanceof Player player)) {
return true; return true;
} }
Player player = (Player) sender;
if(args.length < 2) return false; // todo error message or command info if(args.length < 2) return false; // todo error message or command info
ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
user.setReplyContinueTarget(args[0]);
String message = StringUtils.join(args, " ", 1, args.length); String message = StringUtils.join(args, " ", 1, args.length);
ChatPlugin.getInstance().getChatHandler().privateMessage(player, args[0], message); ChatPlugin.getInstance().getChatHandler().privateMessage(player, args[0], message);
return false; return false;
@@ -1,11 +1,11 @@
package com.alttd.chat.commands; package com.alttd.chat.commands;
import com.alttd.chat.ChatPlugin; import com.alttd.chat.ChatPlugin;
import com.alttd.chat.managers.PartyManager; import com.alttd.chat.config.Config;
import com.alttd.chat.objects.Party; import com.alttd.chat.objects.Toggleable;
import com.alttd.chat.util.Utility; import com.alttd.chat.util.ALogger;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@@ -13,7 +13,12 @@ import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class PartyChat implements CommandExecutor { import java.util.HashSet;
import java.util.UUID;
public class PartyChat extends Toggleable implements CommandExecutor {
private final HashSet<UUID> toggledUsers = new HashSet<>();
@Override @Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
@@ -22,7 +27,8 @@ public class PartyChat implements CommandExecutor {
} }
if(args.length == 0) { if(args.length == 0) {
// TODO: 08/08/2021 lock into party chat player.sendMiniMessage(Config.PARTY_TOGGLED, Placeholder.component("status",
toggle(player.getUniqueId()) ? Config.TOGGLED_ON : Config.TOGGLED_OFF));
return true; return true;
} }
@@ -37,4 +43,31 @@ public class PartyChat implements CommandExecutor {
return true; return true;
} }
@Override
public boolean isToggled(UUID uuid) {
return toggledUsers.contains(uuid);
}
@Override
public void setOff(UUID uuid) {
toggledUsers.remove(uuid);
}
@Override
public void setOn(UUID uuid) {
disableToggles(uuid);
toggledUsers.add(uuid);
}
@Override
public void sendMessage(Player player, String message) {
ALogger.info(player.getName() + " sent party message: " + message);
new BukkitRunnable() {
@Override
public void run() {
ChatPlugin.getInstance().getChatHandler().partyMessage(player, message);
}
}.runTaskAsynchronously(ChatPlugin.getInstance());
}
} }
@@ -3,7 +3,7 @@ package com.alttd.chat.commands;
import com.alttd.chat.ChatPlugin; import com.alttd.chat.ChatPlugin;
import com.alttd.chat.managers.ChatUserManager; import com.alttd.chat.managers.ChatUserManager;
import com.alttd.chat.objects.ChatUser; import com.alttd.chat.objects.ChatUser;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@@ -8,7 +8,7 @@ import com.alttd.chat.objects.ChatUser;
import com.alttd.chat.util.Utility; import com.alttd.chat.util.Utility;
import jdk.jshell.execution.Util; import jdk.jshell.execution.Util;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@@ -4,6 +4,7 @@ import com.alttd.chat.ChatPlugin;
import com.alttd.chat.config.Config; import com.alttd.chat.config.Config;
import com.alttd.chat.managers.ChatUserManager; import com.alttd.chat.managers.ChatUserManager;
import com.alttd.chat.managers.RegexManager; import com.alttd.chat.managers.RegexManager;
import com.alttd.chat.objects.ChatFilter;
import com.alttd.chat.objects.ChatUser; import com.alttd.chat.objects.ChatUser;
import com.alttd.chat.objects.ModifiableString; import com.alttd.chat.objects.ModifiableString;
import com.alttd.chat.objects.channels.CustomChannel; import com.alttd.chat.objects.channels.CustomChannel;
@@ -12,8 +13,11 @@ import com.alttd.chat.util.Utility;
import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextReplacementConfig;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.minimessage.placeholder.Replacement; 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; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
@@ -34,10 +38,19 @@ public class ChatHandler {
GCNOTENABLED = Utility.parseMiniMessage(Config.GCNOTENABLED); GCNOTENABLED = Utility.parseMiniMessage(Config.GCNOTENABLED);
} }
public void privateMessage(Player player, String target, String message) { public void continuePrivateMessage(Player player, String target, String message) {
// ChatUser user = ChatUserManager.getChatUser(player.getUniqueId()); // ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
// user.setReplyTarget(target); // user.setReplyTarget(target);
ModifiableString modifiableString = new ModifiableString(message);
TagResolver placeholders = TagResolver.resolver(
Placeholder.component("message", parseMessageContent(player, message)),
Placeholder.component("sendername", player.name()),
Placeholder.parsed("receivername", target)
);
Component component = Utility.parseMiniMessage("<message>", placeholders);
ModifiableString modifiableString = new ModifiableString(component);
// todo a better way for this // todo a better way for this
if(!RegexManager.filterText(player.getName(), player.getUniqueId(), modifiableString, "privatemessage")) { if(!RegexManager.filterText(player.getName(), player.getUniqueId(), modifiableString, "privatemessage")) {
GalaxyUtility.sendBlockedNotification("DM Language", GalaxyUtility.sendBlockedNotification("DM Language",
@@ -46,26 +59,8 @@ public class ChatHandler {
target); target);
return; // the message was blocked return; // the message was blocked
} }
String updatedMessage = modifiableString.string();
if(!player.hasPermission("chat.format")) { component = modifiableString.component();
updatedMessage = Utility.stripTokens(updatedMessage);
} else {
updatedMessage = Utility.parseColors(updatedMessage);
}
if(updatedMessage.contains("[i]"))
updatedMessage = updatedMessage.replace("[i]", "<[i]>");
updatedMessage = Utility.formatText(updatedMessage);
Map<String, Replacement<?>> placeholders = new HashMap<>();
placeholders.put("message", Replacement.miniMessage(updatedMessage));
placeholders.put("sendername", Replacement.miniMessage(player.getName()));
placeholders.put("receivername", Replacement.miniMessage(target));
placeholders.put("[i]", Replacement.component(itemComponent(player.getInventory().getItemInMainHand())));
Component component = Utility.parseMiniMessage("<message>", placeholders);
sendPrivateMessage(player, target, "privatemessage", component); sendPrivateMessage(player, target, "privatemessage", component);
Component spymessage = Utility.parseMiniMessage(Config.MESSAGESPY, placeholders); Component spymessage = Utility.parseMiniMessage(Config.MESSAGESPY, placeholders);
@@ -76,6 +71,41 @@ public class ChatHandler {
} }
} }
public void privateMessage(Player player, String target, String message) {
// ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
// user.setReplyTarget(target);
Component messageComponent = parseMessageContent(player, message);
TagResolver placeholders = TagResolver.resolver(
Placeholder.component("message", messageComponent),
Placeholder.component("sendername", player.name()),
Placeholder.parsed("receivername", target)
);
ModifiableString modifiableString = new ModifiableString(messageComponent);
// todo a better way for this
if(!RegexManager.filterText(player.getName(), player.getUniqueId(), modifiableString, "privatemessage")) {
GalaxyUtility.sendBlockedNotification("DM Language",
player,
Utility.parseMiniMessage(Utility.parseColors(modifiableString.string())),
target);
return; // the message was blocked
}
messageComponent = modifiableString.component();
// Component component = Utility.parseMiniMessage("<message>", placeholders)
// .replaceText(TextReplacementConfig.builder().once().matchLiteral("[i]").replacement(ChatHandler.itemComponent(player.getInventory().getItemInMainHand())).build());
sendPrivateMessage(player, target, "privatemessage", messageComponent);
Component spymessage = Utility.parseMiniMessage(Config.MESSAGESPY, placeholders);
for(Player pl : Bukkit.getOnlinePlayers()) {
if(pl.hasPermission(Config.SPYPERMISSION) && ChatUserManager.getChatUser(pl.getUniqueId()).isSpy() && !pl.equals(player) && !pl.getName().equalsIgnoreCase(target)) {
pl.sendMessage(spymessage);
}
}
}
public void globalChat(Player player, String message) { public void globalChat(Player player, String message) {
ChatUser user = ChatUserManager.getChatUser(player.getUniqueId()); ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
if(!Utility.hasPermission(player.getUniqueId(), Config.GCPERMISSION)) { if(!Utility.hasPermission(player.getUniqueId(), Config.GCPERMISSION)) {
@@ -89,16 +119,23 @@ public class ChatHandler {
long timeLeft = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - user.getGcCooldown()); long timeLeft = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - user.getGcCooldown());
if(timeLeft <= Config.GCCOOLDOWN && !player.hasPermission("chat.globalchat.cooldownbypass")) { // player is on cooldown and should wait x seconds if(timeLeft <= Config.GCCOOLDOWN && !player.hasPermission("chat.globalchat.cooldownbypass")) { // player is on cooldown and should wait x seconds
Map<String, Replacement<?>> placeholders = new HashMap<>(); player.sendMessage(Utility.parseMiniMessage(Config.GCONCOOLDOWN, Placeholder.parsed("cooldown", Config.GCCOOLDOWN-timeLeft+"")));
placeholders.put("cooldown", Replacement.miniMessage(Config.GCCOOLDOWN-timeLeft+""));
player.sendMessage(Utility.parseMiniMessage(Config.GCONCOOLDOWN, placeholders));
return; return;
} }
Component senderName = user.getDisplayName(); Component senderName = user.getDisplayName();
Component prefix = user.getPrefix(); Component prefix = user.getPrefix();
ModifiableString modifiableString = new ModifiableString(message); TagResolver placeholders = TagResolver.resolver(
Placeholder.component("sender", senderName),
Placeholder.component("prefix", prefix),
Placeholder.component("message", parseMessageContent(player, message)),
Placeholder.parsed("server", Bukkit.getServerName())
);
Component component = Utility.parseMiniMessage(Config.GCFORMAT, placeholders);
ModifiableString modifiableString = new ModifiableString(component);
// todo a better way for this // todo a better way for this
if (!RegexManager.filterText(player.getName(), player.getUniqueId(), modifiableString, "globalchat")) { if (!RegexManager.filterText(player.getName(), player.getUniqueId(), modifiableString, "globalchat")) {
GalaxyUtility.sendBlockedNotification("GC Language", GalaxyUtility.sendBlockedNotification("GC Language",
@@ -107,27 +144,8 @@ public class ChatHandler {
""); "");
return; // the message was blocked return; // the message was blocked
} }
component = modifiableString.component();
String updatedMessage = modifiableString.string();
if(!player.hasPermission("chat.format")) {
updatedMessage = Utility.stripTokens(updatedMessage);
} else {
updatedMessage = Utility.parseColors(updatedMessage);
}
if(updatedMessage.contains("[i]"))
updatedMessage = updatedMessage.replace("[i]", "<[i]>");
updatedMessage = Utility.formatText(updatedMessage);
Map<String, Replacement<?>> placeholders = new HashMap<>();
placeholders.put("sender", Replacement.component(senderName));
placeholders.put("prefix", Replacement.component(prefix));
placeholders.put("message", Replacement.miniMessage(updatedMessage));
placeholders.put("server", Replacement.miniMessage(Bukkit.getServerName()));
placeholders.put("[i]", Replacement.component(itemComponent(player.getInventory().getItemInMainHand())));
Component component = Utility.parseMiniMessage(Config.GCFORMAT, placeholders);
user.setGcCooldown(System.currentTimeMillis()); user.setGcCooldown(System.currentTimeMillis());
sendPluginMessage(player, "globalchat", component); sendPluginMessage(player, "globalchat", component);
} }
@@ -143,7 +161,15 @@ public class ChatHandler {
ChatUser user = ChatUserManager.getChatUser(player.getUniqueId()); ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
Component senderName = user.getDisplayName(); Component senderName = user.getDisplayName();
ModifiableString modifiableString = new ModifiableString(message); TagResolver placeholders = TagResolver.resolver(
Placeholder.component("sender", senderName),
Placeholder.component("message", parseMessageContent(player, message)),
Placeholder.parsed("server", Bukkit.getServerName()),
Placeholder.parsed("channel", channel.getChannelName())
);
Component component = Utility.parseMiniMessage(channel.getFormat(), placeholders);
ModifiableString modifiableString = new ModifiableString(component);
if(!RegexManager.filterText(player.getName(), player.getUniqueId(), modifiableString, channel.getChannelName())) { if(!RegexManager.filterText(player.getName(), player.getUniqueId(), modifiableString, channel.getChannelName())) {
GalaxyUtility.sendBlockedNotification(channel.getChannelName() + " Language", GalaxyUtility.sendBlockedNotification(channel.getChannelName() + " Language",
player, player,
@@ -152,23 +178,7 @@ public class ChatHandler {
return; // the message was blocked return; // the message was blocked
} }
String updatedMessage = modifiableString.string(); component = modifiableString.component();
if(!player.hasPermission("chat.format")) {
updatedMessage = Utility.stripTokens(updatedMessage);
}
if(updatedMessage.contains("[i]")) updatedMessage = updatedMessage.replace("[i]", "<[i]>");
updatedMessage = Utility.formatText(updatedMessage);
Map<String, Replacement<?>> placeholders = new HashMap<>();
placeholders.put("sender", Replacement.component(senderName));
placeholders.put("message", Replacement.miniMessage(updatedMessage));
placeholders.put("server", Replacement.miniMessage(Bukkit.getServerName()));
placeholders.put("channel", Replacement.miniMessage(channel.getChannelName()));
placeholders.put("[i]", Replacement.component(itemComponent(player.getInventory().getItemInMainHand())));
Component component = Utility.parseMiniMessage(channel.getFormat(), placeholders);
if (channel.isProxy()) { if (channel.isProxy()) {
sendChatChannelMessage(player, channel.getChannelName(), "chatchannel", component); sendChatChannelMessage(player, channel.getChannelName(), "chatchannel", component);
@@ -203,11 +213,11 @@ public class ChatHandler {
// updatedMessage = Utility.stripTokens(updatedMessage); // updatedMessage = Utility.stripTokens(updatedMessage);
// } // }
// //
// if(updatedMessage.contains("[i]")) updatedMessage = updatedMessage.replace("[i]", "<[i]>"); // if(updatedMessage.contains("[i]")) updatedMessage = updatedMessage.replaceFirst("[i]", "<item>");
// //
// updatedMessage = Utility.formatText(updatedMessage); // updatedMessage = Utility.formatText(updatedMessage);
// //
// List<Template> templates = new ArrayList<>(List.of( // List<Placeholder> Placeholders = new ArrayList<>(List.of(
// Placeholder.miniMessage("sender", senderName), // Placeholder.miniMessage("sender", senderName),
// Placeholder.miniMessage("sendername", senderName), // Placeholder.miniMessage("sendername", senderName),
// Placeholder.miniMessage("partyname", party.getPartyName()), // Placeholder.miniMessage("partyname", party.getPartyName()),
@@ -215,10 +225,10 @@ public class ChatHandler {
// Placeholder.miniMessage("server", Bukkit.getServerName()), // Placeholder.miniMessage("server", Bukkit.getServerName()),
// Placeholder.miniMessage("[i]", itemComponent(player.getInventory().getItemInMainHand())))); // Placeholder.miniMessage("[i]", itemComponent(player.getInventory().getItemInMainHand()))));
// //
// Component component = Utility.parseMiniMessage(Config.PARTY_FORMAT, templates); // Component component = Utility.parseMiniMessage(Config.PARTY_FORMAT, Placeholders);
//// sendPartyMessage(player, party.getPartyId(), component); //// sendPartyMessage(player, party.getPartyId(), component);
// //
// Component spyMessage = Utility.parseMiniMessage(Config.PARTY_SPY, templates); // Component spyMessage = Utility.parseMiniMessage(Config.PARTY_SPY, Placeholders);
// for(Player pl : Bukkit.getOnlinePlayers()) { // for(Player pl : Bukkit.getOnlinePlayers()) {
// if(pl.hasPermission(Config.SPYPERMISSION) && !party.getPartyUsersUuid().contains(pl.getUniqueId())) { // if(pl.hasPermission(Config.SPYPERMISSION) && !party.getPartyUsersUuid().contains(pl.getUniqueId())) {
// pl.sendMessage(spyMessage); // pl.sendMessage(spyMessage);
@@ -313,4 +323,34 @@ public class ChatHandler {
} }
// end - move these to util // 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;
}
} }
@@ -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<Component> 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;
}
}
@@ -5,89 +5,208 @@ import com.alttd.chat.config.Config;
import com.alttd.chat.handler.ChatHandler; import com.alttd.chat.handler.ChatHandler;
import com.alttd.chat.managers.ChatUserManager; import com.alttd.chat.managers.ChatUserManager;
import com.alttd.chat.managers.RegexManager; import com.alttd.chat.managers.RegexManager;
import com.alttd.chat.objects.ChatUser; import com.alttd.chat.objects.*;
import com.alttd.chat.objects.ModifiableString; import com.alttd.chat.util.ALogger;
import com.alttd.chat.util.GalaxyUtility; import com.alttd.chat.util.GalaxyUtility;
import com.alttd.chat.util.Utility; import com.alttd.chat.util.Utility;
import io.papermc.paper.chat.ChatRenderer; import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import io.papermc.paper.event.player.AsyncChatCommandDecorateEvent;
import io.papermc.paper.event.player.AsyncChatDecorateEvent;
import io.papermc.paper.event.player.AsyncChatEvent; import io.papermc.paper.event.player.AsyncChatEvent;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.placeholder.Replacement; 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.plain.PlainTextComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.HashMap; import java.time.*;
import java.util.Map; import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class ChatListener implements Listener, ChatRenderer { 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()));
}
private final Component mention = MiniMessage.miniMessage().deserialize(Config.MENTIONPLAYERTAG);
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void onPlayerChat(AsyncChatEvent event) { public void onPlayerChat(AsyncChatEvent event) {
event.setCancelled(true); //Always cancel the event because we do not want to deal with Microsoft's stupid bans
Toggleable toggleable = Toggleable.getToggleable(event.getPlayer().getUniqueId());
if (toggleable != null) {
toggleable.sendMessage(event.getPlayer(), event.message());
return;
}
if (ChatPlugin.getInstance().serverMuted() && !event.getPlayer().hasPermission("chat.bypass-server-muted")) { if (ChatPlugin.getInstance().serverMuted() && !event.getPlayer().hasPermission("chat.bypass-server-muted")) {
event.setCancelled(true);
Player player = event.getPlayer(); Player player = event.getPlayer();
GalaxyUtility.sendBlockedNotification("Chat Muted", player, event.message(), ""); GalaxyUtility.sendBlockedNotification("Chat Muted", player, event.message(), "");
return; return;
} }
Player player = event.getPlayer(); Player player = event.getPlayer();
// ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
event.viewers().removeIf(audience -> audience instanceof Player receiver Set<Player> receivers = event.viewers().stream().filter(audience -> audience instanceof Player)
&& ChatUserManager.getChatUser(receiver.getUniqueId()).getIgnoredPlayers().contains(player.getUniqueId())); .map(audience -> (Player) audience)
.filter(receiver -> !ChatUserManager.getChatUser(receiver.getUniqueId()).getIgnoredPlayers().contains(player.getUniqueId()))
.collect(Collectors.toSet());
Component input = event.message().colorIfAbsent(NamedTextColor.WHITE);
ModifiableString modifiableString = new ModifiableString(input);
Component input = event.message();
String message = PlainTextComponentSerializer.plainText().serialize(input);
ModifiableString modifiableString = new ModifiableString(message);
// todo a better way for this // todo a better way for this
if(!RegexManager.filterText(player.getName(), player.getUniqueId(), modifiableString, "chat")) { if(!RegexManager.filterText(player.getName(), player.getUniqueId(), modifiableString, true, "chat", filterType -> {
if (!filterType.equals(FilterType.PUNISH)) {
ALogger.warn("Received another FilterType than punish when filtering chat and executing a filter action");
return;
}
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("punish");
out.writeUTF(player.getName());
out.writeUTF(player.getUniqueId().toString());
out.writeUTF(modifiableString.string());
player.sendPluginMessage(ChatPlugin.getInstance(), Config.MESSAGECHANNEL, out.toByteArray());
})) {
event.setCancelled(true); event.setCancelled(true);
GalaxyUtility.sendBlockedNotification("Language", player, GalaxyUtility.sendBlockedNotification("Language", player,
Utility.parseMiniMessage(Utility.parseColors(modifiableString.string())), modifiableString.component(),
""); "");
return; // the message was blocked return; // the message was blocked
} }
message = modifiableString.string();
if(!player.hasPermission("chat.format")) { Set<Player> playersToPing = new HashSet<>();
message = Utility.stripTokens(message); pingPlayers(playersToPing, modifiableString, player);
LocalDate now = LocalDate.now();
if (now.getMonth().equals(Month.APRIL) && now.getDayOfMonth() == 1) {
if (modifiableString.string().startsWith(Config.APRIL_FOOLS_RESET + " ")) {
modifiableString.removeStringAtStart(Config.APRIL_FOOLS_RESET + " ");
} else { } else {
message = Utility.parseColors(message); modifiableString.reverse();
}
}
input = render(player, modifiableString.component());
for (Player receiver : receivers) {
receiver.sendMessage(input);
}
for (Player pingPlayer : playersToPing) {
pingPlayer.playSound(pingPlayer.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 1, 1);
}
ALogger.info(PlainTextComponentSerializer.plainText().serialize(input));
} }
if(message.contains("[i]")) private void pingPlayers(Set<Player> playersToPing, ModifiableString modifiableString, Player player) {
message = message.replace("[i]", "<[i]>"); // end of todo for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
String name = onlinePlayer.getName();
String nickName = PlainTextComponentSerializer.plainText().serialize(onlinePlayer.displayName());
message = Utility.formatText(message); Pattern namePattern = Pattern.compile("\\b(?<!\\\\)" + name + "\\b", Pattern.CASE_INSENSITIVE);
// Pattern escapedNamePattern = Pattern.compile("\\b\\\\" + name + "\\b", Pattern.CASE_INSENSITIVE);
Pattern nickPattern = Pattern.compile("\\b(?<!\\\\)" + nickName + "\\b", Pattern.CASE_INSENSITIVE);
// Pattern escapedNickPattern = Pattern.compile("\\b\\\\" + nickName + "\\b", Pattern.CASE_INSENSITIVE);
Map<String, Replacement<?>> placeholders = new HashMap<>(); if (namePattern.matcher(modifiableString.string()).find()) {
placeholders.put("message", Replacement.miniMessage(message)); modifiableString.replace(TextReplacementConfig.builder()
placeholders.put("[i]", Replacement.component(ChatHandler.itemComponent(player.getInventory().getItemInMainHand()))); .once()
.match(namePattern)
Component component = Utility.parseMiniMessage("<message>", placeholders); .replacement(mention.append(onlinePlayer.displayName()))
.build());
event.message(component); //TODO replace all instances of \name with just name but using the match result so the capitalization doesn't change
event.renderer(this); // modifiableString.replace(TextReplacementConfig.builder()
// .once()
// .match(escapedNamePattern)
// .replacement((a, b) -> {
// String substring = a.group().substring(1);
// return ;
// });
if (!ChatUserManager.getChatUser(onlinePlayer.getUniqueId()).getIgnoredPlayers().contains(player.getUniqueId()))
playersToPing.add(onlinePlayer);
} else if (nickPattern.matcher(modifiableString.string()).find()) {
modifiableString.replace(TextReplacementConfig.builder()
.once()
.match(nickPattern)
.replacement(mention.append(onlinePlayer.displayName()))
.build());
if (!ChatUserManager.getChatUser(onlinePlayer.getUniqueId()).getIgnoredPlayers().contains(player.getUniqueId()))
playersToPing.add(onlinePlayer);
}
}
} }
@Override public @NotNull Component render(@NotNull Player player, @NotNull Component message) {
public @NotNull Component render(@NotNull Player player, @NotNull Component sourceDisplayName, @NotNull Component message, @NotNull Audience viewer) {
ChatUser user = ChatUserManager.getChatUser(player.getUniqueId()); ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
TagResolver placeholders = TagResolver.resolver(
Map<String, Replacement<?>> placeholders = new HashMap<>(); Placeholder.component("sender", user.getDisplayName()),
placeholders.put("sender", Replacement.component(player.displayName())); Placeholder.parsed("sendername", player.getName()),
placeholders.put("sendername", Replacement.component(player.name())); Placeholder.component("prefix", user.getPrefix()),
placeholders.put("prefix", Replacement.component(user.getPrefix())); Placeholder.component("prefixall", user.getPrefixAll()),
placeholders.put("prefixall", Replacement.component(user.getPrefixAll())); Placeholder.component("staffprefix", user.getStaffPrefix()),
placeholders.put("staffprefix", Replacement.component(user.getStaffPrefix())); Placeholder.component("message", message)
placeholders.put("message", Replacement.component(message)); );
return Utility.parseMiniMessage(Config.CHATFORMAT, 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;
}
} }
@@ -1,14 +1,18 @@
package com.alttd.chat.listeners; package com.alttd.chat.listeners;
import com.alttd.chat.config.Config;
import com.alttd.chat.config.ServerConfig;
import com.alttd.chat.database.Queries; import com.alttd.chat.database.Queries;
import com.alttd.chat.managers.ChatUserManager; import com.alttd.chat.managers.ChatUserManager;
import com.alttd.chat.managers.RegexManager; import com.alttd.chat.managers.RegexManager;
import com.alttd.chat.objects.ChatUser; import com.alttd.chat.objects.ChatUser;
import com.alttd.chat.objects.ModifiableString; import com.alttd.chat.objects.ModifiableString;
import com.alttd.chat.objects.Toggleable;
import com.alttd.chat.util.GalaxyUtility; import com.alttd.chat.util.GalaxyUtility;
import com.alttd.chat.util.Utility; import com.alttd.chat.util.Utility;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
@@ -17,15 +21,31 @@ import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class PlayerListener implements Listener { public class PlayerListener implements Listener {
private final ServerConfig serverConfig;
public PlayerListener(ServerConfig serverConfig) {
this.serverConfig = serverConfig;
}
@EventHandler @EventHandler
private void onPlayerLogin(PlayerJoinEvent event) { private void onPlayerLogin(PlayerJoinEvent event) {
UUID uuid = event.getPlayer().getUniqueId(); Player player = event.getPlayer();
GalaxyUtility.addAdditionalChatCompletions(player);
UUID uuid = player.getUniqueId();
Toggleable.disableToggles(uuid);
if (serverConfig.FIRST_JOIN_MESSAGES && System.currentTimeMillis() - player.getFirstPlayed() < TimeUnit.SECONDS.toMillis(10)) {
player.getServer().sendMessage(MiniMessage.miniMessage().deserialize(Config.FIRST_JOIN, Placeholder.parsed("player", player.getName())));
}
ChatUser user = ChatUserManager.getChatUser(uuid); ChatUser user = ChatUserManager.getChatUser(uuid);
if(user != null) return; if(user != null) return;
// user failed to load - create a new one // user failed to load - create a new one
ChatUser chatUser = new ChatUser(uuid, -1, null); ChatUser chatUser = new ChatUser(uuid, -1, null);
ChatUserManager.addUser(chatUser); ChatUserManager.addUser(chatUser);
@@ -47,8 +67,8 @@ public class PlayerListener implements Listener {
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
Component component = event.line(i); Component component = event.line(i);
if (component != null) { if (component != null) {
String message = PlainTextComponentSerializer.plainText().serialize(component); ModifiableString modifiableString = new ModifiableString(component);
ModifiableString modifiableString = new ModifiableString(message);
Player player = event.getPlayer(); Player player = event.getPlayer();
// todo a better way for this // todo a better way for this
@@ -58,9 +78,8 @@ public class PlayerListener implements Listener {
Utility.parseMiniMessage(Utility.parseColors(modifiableString.string())), Utility.parseMiniMessage(Utility.parseColors(modifiableString.string())),
""); "");
} }
message = modifiableString.string();
component = message == null ? Component.empty() : Component.text(message); component = modifiableString.component() == null ? Component.empty() : modifiableString.component();
event.line(i, component); event.line(i, component);
} }
@@ -47,6 +47,7 @@ public class PluginMessage implements PluginMessageListener {
p.sendMessage(GsonComponentSerializer.gson().deserialize(message)); p.sendMessage(GsonComponentSerializer.gson().deserialize(message));
p.playSound(p.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 1, 1); // todo load this from config p.playSound(p.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 1, 1); // todo load this from config
ChatUser user = ChatUserManager.getChatUser(uuid); ChatUser user = ChatUserManager.getChatUser(uuid);
if (!user.getReplyContinueTarget().equalsIgnoreCase(target))
user.setReplyTarget(target); user.setReplyTarget(target);
} }
} }
@@ -61,9 +62,10 @@ public class PluginMessage implements PluginMessageListener {
if (p != null) { if (p != null) {
ChatUser chatUser = ChatUserManager.getChatUser(uuid); ChatUser chatUser = ChatUserManager.getChatUser(uuid);
if (!chatUser.getIgnoredPlayers().contains(targetuuid)) { if (!chatUser.getIgnoredPlayers().contains(targetuuid)) {
chatUser.setReplyTarget(target);
p.sendMessage(GsonComponentSerializer.gson().deserialize(message)); p.sendMessage(GsonComponentSerializer.gson().deserialize(message));
ChatUser user = ChatUserManager.getChatUser(uuid); // ChatUser user = ChatUserManager.getChatUser(uuid);
user.setReplyTarget(target); // user.setReplyTarget(target);
} }
} }
break; break;
@@ -0,0 +1,225 @@
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.Utility;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.kyori.adventure.text.serializer.legacy.LegacyFormat;
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<String> 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)) {
sender.sendMiniMessage(Config.NICK_BLOCKED_COLOR_CODES, null);
return false;
}
if (!Utility.checkNickBrightEnough(nickName)) {
sender.sendMiniMessage("<red>At least one color must be brighter than 30 for each color</red>", null);
return false;
}
String cleanNick = NickUtilities.removeAllColors(nickName);
if (cleanNick.length() < 3 || cleanNick.length() > 16) {
sender.sendMiniMessage(Config.NICK_INVALID_LENGTH, null);
return false;
}
if (!cleanNick.matches("[a-zA-Z0-9_]*") || nickName.length() > 192) { //192 is if someone puts {#xxxxxx<>} in front of every letter
sender.sendMiniMessage(Config.NICK_INVALID_CHARACTERS, null);
return false;
}
if (cleanNick.equalsIgnoreCase(target.getName())) {
return true;
}
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.sendMiniMessage(Config.NICK_TAKEN, null);
return false;
}
}
return true;
}
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());
}
}
@@ -0,0 +1,446 @@
package com.alttd.chat.nicknames;
import com.Zrips.CMI.CMI;
import com.Zrips.CMI.Containers.CMIUser;
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.alttd.chat.util.Utility;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
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.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.plugin.Plugin;
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<UUID, Nick> NickCache;
ArrayList<UUID> 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(Utility.parseMiniMessage(helpMessage(sender, HelpType.ALL)));
return true;
}
switch (args[0].toLowerCase()) {
case "set":
if (args.length == 2 && hasPermission(sender, "chat.command.nick.set")) {
handleNick(player, player, args[1]);
} else if (args.length == 3 && hasPermission(sender, "chat.command.nick.set.others")) {
OfflinePlayer offlinePlayer = sender.getServer().getOfflinePlayer(args[1]);
if (offlinePlayer.isOnline() || offlinePlayer.hasPlayedBefore()) {
handleNick(player, offlinePlayer, args[2]);
} else {
sender.sendMessage(Utility.parseMiniMessage(helpMessage(sender, HelpType.SET_OTHERS)));
}
} else if (args.length > 3) {
sender.sendMessage(Utility.parseMiniMessage(helpMessage(sender, HelpType.SET_SELF, HelpType.SET_OTHERS)));
}
break;
case "review":
if (args.length == 1 && hasPermission(sender, "chat.command.nick.review")) {
NicknamesGui nicknamesGui = new NicknamesGui();
ChatPlugin.getInstance().getServer().getPluginManager().registerEvents(nicknamesGui, ChatPlugin.getInstance());
nicknamesGui.openInventory(player);
} else {
sender.sendMessage(Utility.parseMiniMessage(helpMessage(sender, HelpType.REVIEW)));
}
break;
case "request":
if (args.length == 2 && hasPermission(sender, "chat.command.nick.request")) {
new BukkitRunnable() {
@Override
public void run() {
handleNickRequest(player, args[1]);
}
}.runTaskAsynchronously(ChatPlugin.getInstance());
} else {
sender.sendMessage(Utility.parseMiniMessage(helpMessage(sender, HelpType.REQUEST)));
}
break;
case "try":
if (args.length == 2 && hasPermission(sender, "chat.command.nick.try")) {
LuckPerms api = ChatAPI.get().getLuckPerms();
if (api != null) {
if (NickUtilities.validNick(player, player, args[1])) {
sender.sendMessage(Utility.parseMiniMessage(Config.NICK_TRYOUT,
Placeholder.component("prefix", Utility.applyColor(api.getUserManager().getUser(player.getUniqueId())
.getCachedData().getMetaData().getPrefix())), // TODO pull this from chatuser?
Placeholder.component("nick", Utility.applyColor(args[1]))));
}
} else {
sender.sendMessage(Utility.parseMiniMessage(Config.NICK_NO_LUCKPERMS));
}
} else {
sender.sendMessage(Utility.parseMiniMessage(helpMessage(sender, HelpType.TRY)));
}
break;
case "current":
if (hasPermission(sender, "chat.command.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(Utility.parseMiniMessage(helpMessage(sender, HelpType.ALL)
+ "For more info on nicknames and how to use rgb colors go to: <aqua>https://alttd.com/nicknames<white>"));
break;
default:
sender.sendMessage(Utility.parseMiniMessage(helpMessage(sender, HelpType.ALL)));
}
} else {
sender.sendMessage("Console commands are disabled.");
}
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
List<String> completions = new ArrayList<>();
if (!sender.hasPermission("chat.command.nick")) return completions;
if (args.length == 1) {
List<String> choices = new ArrayList<>();
if (sender.hasPermission("chat.command.nick.set")) {
choices.add("set");
}
if (sender.hasPermission("chat.command.nick.review")) {
choices.add("review");
}
if (sender.hasPermission("chat.command.nick.request")) {
choices.add("request");
}
if (sender.hasPermission("chat.command.nick.try")) {
choices.add("try");
}
if (sender.hasPermission("chat.command.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<String> choices = new ArrayList<>();
List<String> onlinePlayers = new ArrayList<>();
Bukkit.getOnlinePlayers().forEach(a -> onlinePlayers.add(a.getName()));
if (sender.hasPermission("chat.command.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("chat.command.nick.bypasswaittime")) {
if (nick.hasRequest()) {
player.sendMessage(Utility.parseMiniMessage(Config.NICK_REQUEST_PLACED,
Placeholder.component("oldrequestednick", Utility.applyColor(nick.getNewNick())),
Placeholder.component("newrequestednick", Utility.applyColor(nickName))));
}
nick.setNewNick(nickName);
nick.setRequestedDate(new Date().getTime());
} else {
player.sendMessage(Utility.parseMiniMessage(Config.NICK_TOO_SOON,
Placeholder.unparsed("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(Utility.parseMiniMessage(Config.NICK_REQUESTED,
Placeholder.component("nick", Utility.applyColor(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(Utility.parseMiniMessage(Config.NICK_RESET_OTHERS,
Placeholder.unparsed("player", target.getName())));
}
if (target.isOnline() && target.getPlayer() != null) {
target.getPlayer().sendMessage(Utility.parseMiniMessage(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.getPlayer(), 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.getPlayer(), nickName);
} else {
NickCache.put(target.getUniqueId(), new Nick(target.getUniqueId(), nickName, new Date().getTime()));
}
if (!sender.equals(target)) {
sender.sendMessage(Utility.parseMiniMessage(Config.NICK_CHANGED_OTHERS,
Placeholder.unparsed("targetplayer", target.getName()),
Placeholder.unparsed("nickname", nickName)));
if (target.isOnline()) {
target.getPlayer().sendMessage(Utility.parseMiniMessage(Config.NICK_TARGET_NICK_CHANGE,
Placeholder.unparsed("nickname", getNick(target.getPlayer())),
Placeholder.unparsed("sendernick", getNick(sender)),
Placeholder.unparsed("player", target.getName())));
}
} else if (target.isOnline()) {
target.getPlayer().sendMessage(Utility.parseMiniMessage(Config.NICK_CHANGED,
Placeholder.unparsed("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("chat.command.nick.set")) {
message.append("<gold>/nick set <nickname><white> - Sets your nickname to the specified name.\n");
}
break;
case SET_OTHERS:
if (sender.hasPermission("chat.command.nick.set.others")) {
message.append("<gold>/nick set <username> <nickname><white> - Sets the specified user's nickname to the specified name.\n");
}
break;
case REQUEST:
if (sender.hasPermission("chat.command.nick.request")) {
message.append("<gold>/nick request <nickname><white> - Requests a username to be reviewed by staff.\n" +
" <gray>Try using <dark_gray>/nick try <nickname><gray> to see if you like the name, you can only change it once per day!\n");
}
break;
case REVIEW:
if (sender.hasPermission("chat.command.nick.review")) {
message.append("<gold>/nick review<white> - Opens the nickname review GUI (left click to accept a nick, right click to deny it)\n");
}
break;
case TRY:
if (sender.hasPermission("chat.command.nick.try")) {
message.append("<gold>/nick try <nickname><white> - 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(Utility.parseMiniMessage(Config.NO_PERMISSION));
return false;
}
return true;
}
public void resetNick(final Player player) {
ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
user.setDisplayName(player.getName());
player.displayName(user.getDisplayName());
updateCMIUser(player, null);
}
public String getNick(final Player player) {
ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
return user.getNickNameString();
}
public void setNick(final Player player, final String nickName) {
if (player == null)
return;
ChatUser user = ChatUserManager.getChatUser(player.getUniqueId());
user.setDisplayName(nickName);
player.displayName(user.getDisplayName());
updateCMIUser(player, nickName);
}
// public static String format(final String m) {
// return NickUtilities.applyColor(m);
// }
public void updateCMIUser(Player player, String nickName) {
if (!isCMIEnabled())
return;
CMIUser cmiUser = CMI.getInstance().getPlayerManager().getUser(player);
if (nickName == null){
cmiUser.setNickName(null, true);
} else {
cmiUser.setNickName(NickUtilities.applyColor(nickName), true);
}
cmiUser.updateDisplayName();
}
private Boolean isCMIEnabled = null;
private Boolean isCMIEnabled() {
if (!(isCMIEnabled == null))
return isCMIEnabled;
Plugin plugin = Bukkit.getPluginManager().getPlugin("CMI");
if (plugin != null && plugin.isEnabled())
return isCMIEnabled = true;
return isCMIEnabled = false;
}
public static Nicknames getInstance() {
return Nicknames.instance;
}
private enum HelpType {
ALL,
SET_SELF,
SET_OTHERS,
REVIEW,
REQUEST,
TRY
}
}
@@ -0,0 +1,195 @@
package com.alttd.chat.nicknames;
import com.Zrips.CMI.commands.list.colorlimits;
import com.Zrips.CMI.utils.Util;
import com.alttd.chat.ChatPlugin;
import com.alttd.chat.config.Config;
import com.alttd.chat.database.Queries;
import com.alttd.chat.managers.ChatUserManager;
import com.alttd.chat.objects.ChatUser;
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.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
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().stripTags(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, nickName);
}
Nicknames.getInstance().NickCache.put(e.getPlayer().getUniqueId(), nick);
if (player.hasPermission("chat.command.nick.review")) {
int i = 0;
for (Nick iNick : Nicknames.getInstance().NickCache.values()) {
if (iNick.hasRequest()) {
i++;
}
}
if (i > 0) {
player.sendMessage(MiniMessage.miniMessage().deserialize(Config.NICK_REQUESTS_ON_LOGIN,
Placeholder.unparsed("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;
}
MiniMessage miniMessage = MiniMessage.miniMessage();
switch (subChannel) {
case "NickNameRequest":
Component component = miniMessage.deserialize(Config.NICK_REQUEST_NEW, Placeholder.parsed("player", name))
.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND,
"/nick review"))
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
miniMessage.deserialize("<gold>Click this text to review the request!")));
ChatPlugin.getInstance().getServer().getOnlinePlayers().forEach(p -> {
if (p.hasPermission("chat.command.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.getPlayer(), nick.getCurrentNick());
}
}
break;
case "NickNameAccepted":
Component deserialize = miniMessage.deserialize("<green><name>'s nickname was accepted!",
Placeholder.unparsed("name", name));
ChatPlugin.getInstance().getServer().getOnlinePlayers().forEach(p -> {
if (p.hasPermission("chat.command.nick.review")) {
p.sendMessage(deserialize);
}
});
//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, nick.getCurrentNick());
target.sendMessage(MiniMessage.miniMessage().deserialize(Config.NICK_CHANGED,
Placeholder.unparsed("nickname", nick.getCurrentNick())));
}
}
break;
case "NickNameDenied":
final Component messageDenied = miniMessage.deserialize("<red><name>'s nickname was denied",
Placeholder.unparsed("name", name));
Nick nick = Nicknames.getInstance().NickCache.get(playerUUID);
ChatPlugin.getInstance().getServer().getOnlinePlayers().forEach(p -> {
if (p.hasPermission("chat.command.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(MiniMessage.miniMessage().deserialize(Config.NICK_NOT_CHANGED,
Placeholder.unparsed("nickname", nick.getCurrentNick())));
}
break;
}
}
}
@@ -0,0 +1,297 @@
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.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.PlainTextComponentSerializer;
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 java.util.stream.Collectors;
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<String> lore) {
MiniMessage miniMessage = MiniMessage.miniMessage();
ItemStack playerHead = new ItemStack(Material.PLAYER_HEAD);
SkullMeta meta = (SkullMeta) playerHead.getItemMeta();
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(nick.getUuid());
meta.setOwningPlayer(offlinePlayer);
String name = offlinePlayer.getName();
if (name == null)
meta.displayName(miniMessage.deserialize("UNKNOWN PLAYER NAME"));
else
meta.displayName(miniMessage.deserialize(offlinePlayer.getName()));
TagResolver resolver = TagResolver.resolver(
Placeholder.component("newnick", Utility.applyColor(nick.getNewNick())),
Placeholder.component("oldnick", Utility.applyColor(nick.getCurrentNick() == null ? "None" : nick.getCurrentNick())),
Placeholder.unparsed("lastchanged", nick.getLastChangedDate() == 0 ? "Not Applicable" : nick.getLastChangedDateFormatted()));
meta.lore(lore.stream().map(a -> miniMessage.deserialize(a, resolver)).collect(Collectors.toList()));
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
MiniMessage miniMessage = MiniMessage.miniMessage();
meta.lore(Arrays.stream(lore).map(miniMessage::deserialize).collect(Collectors.toList()));
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)) {
String serialize = PlainTextComponentSerializer.plainText().serialize(clickedItem.getItemMeta().displayName());
if (serialize.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(MiniMessage.miniMessage().deserialize(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(MiniMessage.miniMessage().deserialize(Config.NICK_ALREADY_HANDLED,
Placeholder.component("targetplayer", clickedItem.getItemMeta().displayName())));
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(MiniMessage.miniMessage().deserialize(Config.NICK_ACCEPTED,
Placeholder.component("targetplayer", clickedItem.getItemMeta().displayName()),
Placeholder.component("newnick", Utility.applyColor(nick.getNewNick())),
Placeholder.component("oldnick", Utility.applyColor(nick.getCurrentNick() == null ? clickedItem.getItemMeta().getDisplayName() : nick.getCurrentNick()))));
if (owningPlayer.isOnline() && owningPlayer.getPlayer() != null) {
Nicknames.getInstance().setNick(owningPlayer.getPlayer(), nick.getNewNick());
// owningPlayer.getPlayer().sendMessage(MiniMessage.miniMessage().deserialize(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(MiniMessage.miniMessage().deserialize(Config.NICK_PLAYER_NOT_ONLINE,
Placeholder.component("playerName", clickedItem.getItemMeta().displayName())));
}
} else if (e.isRightClick()) {
Component displayName = clickedItem.getItemMeta().displayName();
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(MiniMessage.miniMessage().deserialize(Config.NICK_DENIED,
Placeholder.unparsed("targetplayer", owningPlayer.getName()),
Placeholder.component("newnick", Utility.applyColor(nick.getNewNick())),
Placeholder.component("oldnick", Utility.applyColor(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.getPlayer(), nick.getCurrentNick() == null ? owningPlayer.getName() : nick.getCurrentNick());
owningPlayer.getPlayer().sendMessage(MiniMessage.miniMessage().deserialize(Config.NICK_NOT_CHANGED));
}
NickUtilities.bungeeMessageHandled(uniqueId, e.getWhoClicked().getServer().getPlayer(e.getWhoClicked().getName()), "Denied");
final Component messageDenied = MiniMessage.miniMessage().deserialize("<red><name>'s nickname was denied!",
Placeholder.unparsed("name", owningPlayer.getName()));
ChatPlugin.getInstance().getServer().getOnlinePlayers().forEach(p -> {
if (p.hasPermission("chat.command.nick.review")) {
p.sendMessage(messageDenied);
}
});
ItemStack itemStack = new ItemStack(Material.SKELETON_SKULL);
ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.displayName(displayName);
itemMeta.lore(clickedItem.lore());
itemStack.setItemMeta(itemMeta);
e.getInventory().setItem(e.getSlot(), itemStack);
p.updateInventory();
} else {
if (displayName == null)
p.sendMessage(MiniMessage.miniMessage().deserialize(Config.NICK_PLAYER_NOT_ONLINE, Placeholder.parsed("playerName", "UNKNOWN PLAYER NAME")));
else
p.sendMessage(MiniMessage.miniMessage().deserialize(Config.NICK_PLAYER_NOT_ONLINE, Placeholder.component("playerName", displayName)));
}
}
}
}.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);
}
}
}
@@ -1,22 +1,28 @@
package com.alttd.chat.util; package com.alttd.chat.util;
import com.alttd.chat.config.Config; import com.alttd.chat.config.Config;
import com.alttd.chat.managers.RegexManager;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.placeholder.Replacement; 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 net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.HashMap; import java.util.ArrayList;
import java.util.Map; import java.util.List;
public class GalaxyUtility { public class GalaxyUtility {
public static void sendBlockedNotification(String prefix, Player player, Component input, String target) {
Map<String, Replacement<?>> placeholders = new HashMap<>(); public static void sendBlockedNotification(String prefix, Player player, String input, String target) {
placeholders.put("prefix", Replacement.miniMessage(prefix)); TagResolver placeholders = TagResolver.resolver(
placeholders.put("displayname", Replacement.miniMessage(Utility.getDisplayName(player.getUniqueId(), player.getName()))); Placeholder.parsed("prefix", prefix),
placeholders.put("target", Replacement.miniMessage((target.isEmpty() ? "tried to say:" : " -> " + target + ": "))); Placeholder.parsed("displayname", Utility.getDisplayName(player.getUniqueId(), player.getName())),
placeholders.put("input", Replacement.component(input)); Placeholder.parsed("target", (target.isEmpty() ? "tried to say:" : "-> " + target + ":")),
Placeholder.parsed("input", input)
);
Component blockedNotification = Utility.parseMiniMessage(Config.NOTIFICATIONFORMAT, placeholders); Component blockedNotification = Utility.parseMiniMessage(Config.NOTIFICATIONFORMAT, placeholders);
Bukkit.getOnlinePlayers().forEach(a ->{ Bukkit.getOnlinePlayers().forEach(a ->{
@@ -27,4 +33,33 @@ public class GalaxyUtility {
player.sendMessage(Utility.parseMiniMessage("<red>The language you used in your message is not allowed, " + player.sendMessage(Utility.parseMiniMessage("<red>The language you used in your message is not allowed, " +
"this constitutes as your only warning. Any further attempts at bypassing the filter will result in staff intervention.</red>")); "this constitutes as your only warning. Any further attempts at bypassing the filter will result in staff intervention.</red>"));
} }
public static void sendBlockedNotification(String prefix, Player player, Component input, String target) {
TagResolver placeholders = TagResolver.resolver(
Placeholder.parsed("prefix", prefix),
Placeholder.parsed("displayname", Utility.getDisplayName(player.getUniqueId(), player.getName())),
Placeholder.parsed("target", (target.isEmpty() ? "tried to say:" : "-> " + target + ":")),
Placeholder.component("input", input)
);
Component blockedNotification = Utility.parseMiniMessage(Config.NOTIFICATIONFORMAT, placeholders);
Bukkit.getOnlinePlayers().forEach(a ->{
if (a.hasPermission("chat.alert-blocked")) {
a.sendMessage(blockedNotification);
}
});
player.sendMessage(Utility.parseMiniMessage("<red>The language you used in your message is not allowed, " +
"this constitutes as your only warning. Any further attempts at bypassing the filter will result in staff intervention.</red>"));
}
public static void addAdditionalChatCompletions(Player player) {
List<String> completions = new ArrayList<>(RegexManager.emotesList);
Utility.formattingPerms.forEach((perm, pair) -> {
if (player.hasPermission(perm)) {
completions.addAll(pair.getY());
}
});
player.addCustomChatCompletions(completions);
}
} }
@@ -0,0 +1,48 @@
package com.alttd.chat.util;
import com.alttd.chat.ChatPlugin;
import com.alttd.chat.objects.Toggleable;
import com.alttd.chat.objects.channels.CustomChannel;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.HashSet;
import java.util.UUID;
public class ToggleableForCustomChannel extends Toggleable {
private final CustomChannel customChannel;
public ToggleableForCustomChannel(CustomChannel customChannel) {
super();
this.customChannel = customChannel;
}
private final HashSet<UUID> toggledUsers = new HashSet<>();
@Override
public boolean isToggled(UUID uuid) {
return toggledUsers.contains(uuid);
}
@Override
public void setOff(UUID uuid) {
toggledUsers.remove(uuid);
}
@Override
public void setOn(UUID uuid) {
disableToggles(uuid);
toggledUsers.add(uuid);
}
@Override
public void sendMessage(Player player, String message) {
new BukkitRunnable() {
@Override
public void run() {
ChatPlugin.getInstance().getChatHandler().chatChannel(player, customChannel, message);
}
}.runTaskAsynchronously(ChatPlugin.getInstance());
}
}
+13 -2
View File
@@ -1,9 +1,12 @@
name: ChatPlugin name: ChatPlugin
version: ${project.version} version: 2.0.0-SNAPSHOT
main: com.alttd.chat.ChatPlugin main: com.alttd.chat.ChatPlugin
api-version: 1.18 api-version: 1.19
authors: [Destro, Teriuihi] authors: [Destro, Teriuihi]
depend: [LuckPerms] depend: [LuckPerms]
loadbefore:
- mcMMO
- GriefPrevention
commands: commands:
globalchat: globalchat:
permission: command.chat.globalchat permission: command.chat.globalchat
@@ -19,6 +22,9 @@ commands:
reply: reply:
permission: command.chat.message permission: command.chat.message
aliases: r aliases: r
continue:
permission: command.chat.message
aliases: c
ignore: ignore:
permission: command.chat.ignore permission: command.chat.ignore
unignore: unignore:
@@ -31,3 +37,8 @@ commands:
permission: command.chat.p permission: command.chat.p
chatclear: chatclear:
permission: chat.command.clear-chat permission: chat.command.clear-chat
emoteslist:
permission: chat.command.emoteslist
aliases: [emotes]
nick:
permission: chat.command.nick
Binary file not shown.
+3 -1
View File
@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
Vendored
+179 -115
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env sh #!/bin/sh
# #
# Copyright 2015 the original author or authors. # Copyright © 2015-2021 the original authors.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@@ -17,67 +17,99 @@
# #
############################################################################## ##############################################################################
## #
## Gradle start up script for UN*X # Gradle start up script for POSIX generated by Gradle.
## #
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
############################################################################## ##############################################################################
# Attempt to set APP_HOME # Attempt to set APP_HOME
# Resolve links: $0 may be a link # Resolve links: $0 may be a link
PRG="$0" app_path=$0
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do # Need this for daisy-chained symlinks.
ls=`ls -ld "$PRG"` while
link=`expr "$ls" : '.*-> \(.*\)$'` APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
if expr "$link" : '/.*' > /dev/null; then [ -h "$app_path" ]
PRG="$link" do
else ls=$( ls -ld "$app_path" )
PRG=`dirname "$PRG"`"/$link" link=${ls#*' -> '}
fi case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle" # This is normally unused
APP_BASE_NAME=`basename "$0"` # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD=maximum
warn () { warn () {
echo "$*" echo "$*"
} } >&2
die () { die () {
echo echo
echo "$*" echo "$*"
echo echo
exit 1 exit 1
} } >&2
# OS specific support (must be 'true' or 'false'). # OS specific support (must be 'true' or 'false').
cygwin=false cygwin=false
msys=false msys=false
darwin=false darwin=false
nonstop=false nonstop=false
case "`uname`" in case "$( uname )" in #(
CYGWIN* ) CYGWIN* ) cygwin=true ;; #(
cygwin=true Darwin* ) darwin=true ;; #(
;; MSYS* | MINGW* ) msys=true ;; #(
Darwin* ) NONSTOP* ) nonstop=true ;;
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -87,9 +119,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
if [ -n "$JAVA_HOME" ] ; then if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables # IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java" JAVACMD=$JAVA_HOME/jre/sh/java
else else
JAVACMD="$JAVA_HOME/bin/java" JAVACMD=$JAVA_HOME/bin/java
fi fi
if [ ! -x "$JAVACMD" ] ; then if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -98,88 +130,120 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation." location of your Java installation."
fi fi
else else
JAVACMD="java" JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the Please set the JAVA_HOME variable in your environment to match the
location of your Java installation." location of your Java installation."
fi fi
fi
# Increase the maximum file descriptors if we can. # Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
MAX_FD_LIMIT=`ulimit -H -n` case $MAX_FD in #(
if [ $? -eq 0 ] ; then max*)
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
MAX_FD="$MAX_FD_LIMIT" # shellcheck disable=SC2039,SC3045
fi MAX_FD=$( ulimit -H -n ) ||
ulimit -n $MAX_FD warn "Could not query maximum file descriptor limit"
if [ $? -ne 0 ] ; then esac
warn "Could not set maximum file descriptor limit: $MAX_FD" case $MAX_FD in #(
fi '' | soft) :;; #(
else *)
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
fi # shellcheck disable=SC2039,SC3045
fi ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac esac
fi fi
# Escape application args # Collect all arguments for the java command, stacking in reverse order:
save () { # * args from the command line
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done # * the main class name
echo " " # * -classpath
} # * -D...appname settings
APP_ARGS=`save "$@"` # * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules # For Cygwin or MSYS, switch paths to Windows format before running java
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@" exec "$JAVACMD" "$@"
Vendored
+7 -4
View File
@@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0 set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=. if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute if %ERRORLEVEL% equ 0 goto execute
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd if %ERRORLEVEL% equ 0 goto mainEnd
:fail :fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code! rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 set EXIT_CODE=%ERRORLEVEL%
exit /b 1 if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd :mainEnd
if "%OS%"=="Windows_NT" endlocal if "%OS%"=="Windows_NT" endlocal
Executable
BIN
View File
Binary file not shown.
-58
View File
@@ -1,58 +0,0 @@
#!/usr/bin/env bash
# get base dir regardless of execution location
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
SOURCE=$([[ "$SOURCE" = /* ]] && echo "$SOURCE" || echo "$PWD/${SOURCE#./}")
basedir=$(dirname "$SOURCE")
. "$basedir"/scripts/init.sh
case "$1" in
"d" | "deploy") # deploy api to repo
;;
"b" | "build")
(
cd "$basedir"
mvn package
)
;;
"upload")
(
cd "$basedir"
scp ./galaxy/target/galaxy-chat.jar sid@leo:/home/sid/servers/meadowTest/plugins/galaxy-chat.jar
scp ./velocity/target/velocity-chat.jar sid@leo:/home/sid/servers/velocity/plugins/velocity-chat.jar
)
;;
"queue")
(
cd "$basedir"
scp ./galaxy/target/galaxy-chat.jar sid@lyra:/home/sid/share/updates/all/plugins/galaxy-chat.jar
scp ./velocity/target/velocity-chat.jar sid@lyra:/home/sid/share/updates/plugins/proxy/velocity-chat.jar
)
;;
"setup")
if [[ -f ~/.bashrc ]] ; then
NAME="${PLUGIN_NAME}"
if [[ ! -z "${2+x}" ]] ; then
NAME="$2"
fi
(grep "alias $NAME=" ~/.bashrc > /dev/null) && (sed -i "s|alias $NAME=.*|alias $NAME='. $SOURCE'|g" ~/.bashrc) || (echo "alias $NAME='. $SOURCE'" >> ~/.bashrc)
alias "$NAME=. $SOURCE"
echo "You can now just type '$NAME' at any time to access the build tool."
fi
;;
*)
echo "${PLUGIN_NAME} build tool. This provides a variety of commands to control the build."
echo "View below for details of the available commands."
echo ""
echo "Commands:"
echo " * b, build | Builds the project"
echo " * upload | uploads the lastest build to a testserver"
echo " * queue | queue the lastest build to Alttiude"
echo " * setup | Add an alias to .bashrc to allow full functionality of this script. Run as:"
echo " | . ./plugin setup"
;;
esac
+1
View File
@@ -9,6 +9,7 @@ dependencyResolutionManagement {
// mavenLocal() // mavenLocal()
mavenCentral() mavenCentral()
maven("https://repo.destro.xyz/snapshots") // Altitude - Galaxy maven("https://repo.destro.xyz/snapshots") // Altitude - Galaxy
maven("https://oss.sonatype.org/content/groups/public/") // Adventure
maven("https://oss.sonatype.org/content/repositories/snapshots/") // Minimessage maven("https://oss.sonatype.org/content/repositories/snapshots/") // Minimessage
maven("https://nexus.velocitypowered.com/repository/") // Velocity maven("https://nexus.velocitypowered.com/repository/") // Velocity
maven("https://nexus.velocitypowered.com/repository/maven-public/") // Velocity maven("https://nexus.velocitypowered.com/repository/maven-public/") // Velocity
+7 -9
View File
@@ -5,30 +5,28 @@ plugins {
dependencies { dependencies {
implementation(project(":api")) // API implementation(project(":api")) // API
compileOnly("com.velocitypowered:velocity-api:3.0.1") // Velocity compileOnly("com.velocitypowered:velocity-api:3.2.0-SNAPSHOT")
annotationProcessor("com.velocitypowered:velocity-api:3.0.1") annotationProcessor("com.velocitypowered:velocity-api:3.2.0-SNAPSHOT")
implementation("mysql:mysql-connector-java:8.0.27") // mysql implementation("mysql:mysql-connector-java:8.0.27") // mysql
implementation("org.spongepowered", "configurate-yaml", "4.1.2") implementation("org.spongepowered", "configurate-yaml", "4.1.2")
compileOnly("com.alttd.proxydiscordlink:ProxyDiscordLink:1.0.0-BETA-SNAPSHOT") compileOnly("net.kyori:adventure-text-minimessage:4.10.1")
implementation("net.kyori", "adventure-text-minimessage", "4.10.0-20220122.015731-43") { // Minimessage
exclude("net.kyori")
exclude("net.kyori.examination")
}
compileOnly("com.gitlab.ruany:LiteBansAPI:0.3.5") compileOnly("com.gitlab.ruany:LiteBansAPI:0.3.5")
compileOnly("com.alttd.proxydiscordlink:ProxyDiscordLink:1.0.0-BETA-SNAPSHOT")
} }
tasks { tasks {
shadowJar { shadowJar {
archiveFileName.set("${project.name}-${project.version}.jar") archiveFileName.set("${rootProject.name}-${project.name}-${project.version}.jar")
// minimize() // minimize()
listOf( listOf(
"net.kyori.adventure.text.minimessage", // "net.kyori.adventure.text.minimessage",
"org.spongepowered.configurate" "org.spongepowered.configurate"
).forEach { relocate(it, "${rootProject.group}.lib.${it.substringAfterLast(".")}") } ).forEach { relocate(it, "${rootProject.group}.lib.${it.substringAfterLast(".")}") }
} }
build { build {
// setBuildDir("${rootProject.buildDir}")
dependsOn(shadowJar) dependsOn(shadowJar)
} }
@@ -108,6 +108,7 @@ public class VelocityChat {
} }
public void loadCommands() { public void loadCommands() {
new SilentJoinCommand(server);
new GlobalAdminChat(server); new GlobalAdminChat(server);
new Reload(server); new Reload(server);
new MailCommand(server); new MailCommand(server);
@@ -41,6 +41,27 @@ public class MailCommand {
return 1; return 1;
}); });
RequiredArgumentBuilder<CommandSource, String> playerNodeSender = RequiredArgumentBuilder
.<CommandSource, String>argument("sender", StringArgumentType.string())
.suggests((context, builder) -> {
Collection<String> possibleValues = new ArrayList<>();
for (Player player : proxyServer.getAllPlayers()) {
possibleValues.add(player.getGameProfile().getName());
}
if(possibleValues.isEmpty()) return Suggestions.empty();
String remaining = builder.getRemaining().toLowerCase();
for (String str : possibleValues) {
if (str.toLowerCase().startsWith(remaining)) {
builder.suggest(str = StringArgumentType.escapeIfRequired(str));
}
}
return builder.buildFuture();
})
.executes(context -> {
sendHelpMessage(context.getSource());
return 1;
});
LiteralCommandNode<CommandSource> command = LiteralArgumentBuilder LiteralCommandNode<CommandSource> command = LiteralArgumentBuilder
.<CommandSource>literal("mail") .<CommandSource>literal("mail")
.requires(ctx -> ctx.hasPermission("command.chat.mail")) .requires(ctx -> ctx.hasPermission("command.chat.mail"))
@@ -79,8 +100,13 @@ public class MailCommand {
) )
.then(playerNode .then(playerNode
.requires(ctx -> ctx.hasPermission("command.chat.mail.list.other"))// TODO permission .requires(ctx -> ctx.hasPermission("command.chat.mail.list.other"))// TODO permission
.then(playerNodeSender
.executes(context -> { .executes(context -> {
VelocityChat.getPlugin().getChatHandler().readMail(context.getSource(), context.getArgument("player", String.class)); VelocityChat.getPlugin().getChatHandler().readMail(context.getSource(), context.getArgument("player", String.class), context.getArgument("sender", String.class));
return 1;
}))
.executes(context -> {
VelocityChat.getPlugin().getChatHandler().readMail(context.getSource(), context.getArgument("player", String.class), null);
return 1; return 1;
}) })
) )
@@ -8,7 +8,7 @@ import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.command.SimpleCommand; import com.velocitypowered.api.command.SimpleCommand;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.placeholder.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -2,11 +2,15 @@ package com.alttd.velocitychat.commands;
import com.alttd.chat.config.Config; import com.alttd.chat.config.Config;
import com.alttd.chat.util.Utility; import com.alttd.chat.util.Utility;
import com.alttd.proxydiscordlink.DiscordLink;
import com.alttd.proxydiscordlink.lib.net.dv8tion.jda.api.EmbedBuilder;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.suggestion.Suggestions;
import com.alttd.proxydiscordlink.DiscordLink;
import com.alttd.proxydiscordlink.lib.net.dv8tion.jda.api.EmbedBuilder;
import com.mojang.brigadier.tree.LiteralCommandNode; import com.mojang.brigadier.tree.LiteralCommandNode;
import com.velocitypowered.api.command.BrigadierCommand; import com.velocitypowered.api.command.BrigadierCommand;
import com.velocitypowered.api.command.CommandMeta; import com.velocitypowered.api.command.CommandMeta;
@@ -16,13 +20,16 @@ import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.ServerConnection; import com.velocitypowered.api.proxy.ServerConnection;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
import java.util.ArrayList;
import java.util.Collection;
import java.awt.*; import java.awt.*;
import java.util.Optional; import java.util.Optional;
public class Report { public class Report {
// private static final MiniMessage miniMessage = MiniMessage.get();
public Report(ProxyServer proxyServer) { public Report(ProxyServer proxyServer) {
LiteralCommandNode<CommandSource> command = LiteralArgumentBuilder LiteralCommandNode<CommandSource> command = LiteralArgumentBuilder
.<CommandSource>literal("report") .<CommandSource>literal("report")
@@ -38,6 +45,11 @@ public class Report {
if (optionalServerConnection.isEmpty()) { if (optionalServerConnection.isEmpty()) {
return 1; return 1;
} }
String report = context.getArgument("report", String.class);
if (report.split(" ").length < 3) {
player.sendMessage(Utility.parseMiniMessage(Config.REPORT_TOO_SHORT));
return 1;
}
ServerConnection serverConnection = optionalServerConnection.get(); ServerConnection serverConnection = optionalServerConnection.get();
String serverName = serverConnection.getServer().getServerInfo().getName(); String serverName = serverConnection.getServer().getServerInfo().getName();
@@ -46,7 +58,7 @@ public class Report {
embedBuilder.setTitle("Player Report"); embedBuilder.setTitle("Player Report");
embedBuilder.setColor(Color.CYAN); embedBuilder.setColor(Color.CYAN);
embedBuilder.addField("Incident", embedBuilder.addField("Incident",
context.getArgument("report", String.class), report,
false); false);
embedBuilder.addField("Server", embedBuilder.addField("Server",
serverName.substring(0, 1).toUpperCase() + serverName.substring(1), serverName.substring(0, 1).toUpperCase() + serverName.substring(1),
@@ -0,0 +1,97 @@
package com.alttd.velocitychat.commands;
import com.alttd.chat.config.Config;
import com.alttd.chat.util.Utility;
import com.alttd.velocitychat.listeners.ProxyPlayerListener;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.tree.LiteralCommandNode;
import com.velocitypowered.api.command.BrigadierCommand;
import com.velocitypowered.api.command.CommandMeta;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;
public class SilentJoinCommand {
public SilentJoinCommand(ProxyServer proxyServer) {
RequiredArgumentBuilder<CommandSource, String> serverNode = RequiredArgumentBuilder
.<CommandSource, String>argument("server", StringArgumentType.string())
.suggests((context, builder) -> {
Collection<String> possibleValues = new ArrayList<>();
for (RegisteredServer server : proxyServer.getAllServers()) {
possibleValues.add(server.getServerInfo().getName());
}
if(possibleValues.isEmpty()) return Suggestions.empty();
String remaining = builder.getRemaining().toLowerCase();
for (String str : possibleValues) {
if (str.toLowerCase().startsWith(remaining)) {
builder.suggest(str = StringArgumentType.escapeIfRequired(str));
}
}
return builder.buildFuture();
})
.executes(context -> {
sendHelpMessage(context.getSource());
return 1;
});
LiteralCommandNode<CommandSource> command = LiteralArgumentBuilder
.<CommandSource>literal("silentjoin")
.requires(ctx -> ctx.hasPermission("command.chat.silent-join"))
.then(serverNode
.executes(context -> {
if (!(context.getSource() instanceof Player player)) {
context.getSource().sendMessage(Utility.parseMiniMessage(Config.NO_CONSOLE));
return 1;
}
if (player.getCurrentServer().isEmpty()) {
return 1;
}
String server = context.getArgument("server", String.class);
Optional<RegisteredServer> optionalServer = proxyServer.getServer(server);
if (optionalServer.isEmpty()) {
player.sendMessage(Utility.parseMiniMessage(Config.SILENT_JOIN_NO_SERVER));
return 1;
}
RegisteredServer registeredServer = optionalServer.get();
player.sendMessage(Utility.parseMiniMessage(Config.SILENT_JOIN_JOINING,
Placeholder.unparsed("server", registeredServer.getServerInfo().getName())));
ProxyPlayerListener.addSilentJoin(player.getUniqueId());
player.createConnectionRequest(registeredServer).connectWithIndication();
return 1;
})
)
.executes(context -> {
sendHelpMessage(context.getSource());
return 1;
})
.build();
BrigadierCommand brigadierCommand = new BrigadierCommand(command);
CommandMeta.Builder metaBuilder = proxyServer.getCommandManager().metaBuilder(brigadierCommand);
for (String alias : Config.SILENT_JOIN_COMMAND_ALIASES) {
metaBuilder.aliases(alias);
}
CommandMeta meta = metaBuilder.build();
proxyServer.getCommandManager().register(meta, brigadierCommand);
}
private void sendHelpMessage(CommandSource commandSource) {
commandSource.sendMessage(Utility.parseMiniMessage("<red>Use: <gold>/silentjoin <server></gold>.</red>"));
}
}
@@ -9,7 +9,7 @@ import com.alttd.chat.util.Utility;
import com.alttd.velocitychat.commands.SubCommand; import com.alttd.velocitychat.commands.SubCommand;
import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.text.minimessage.placeholder.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -38,7 +38,7 @@ public class Create implements SubCommand {
} }
if (PartyManager.getParty(args[1]) != null) { if (PartyManager.getParty(args[1]) != null) {
source.sendMessage(Utility.parseMiniMessage(Config.PARTY_EXISTS, source.sendMessage(Utility.parseMiniMessage(Config.PARTY_EXISTS,
Placeholder.miniMessage("party", args[1]) Placeholder.parsed("party", args[1])
)); ));
return; return;
} }
@@ -47,8 +47,8 @@ public class Create implements SubCommand {
party.addUser(ChatUserManager.getChatUser(player.getUniqueId()), player.getUsername()); party.addUser(ChatUserManager.getChatUser(player.getUniqueId()), player.getUsername());
PartyManager.addParty(party); PartyManager.addParty(party);
source.sendMessage(Utility.parseMiniMessage(Config.CREATED_PARTY, source.sendMessage(Utility.parseMiniMessage(Config.CREATED_PARTY,
Placeholder.miniMessage("party_name", party.getPartyName()), Placeholder.unparsed("party_name", party.getPartyName()),
Placeholder.miniMessage("party_password", party.getPartyPassword()))); Placeholder.unparsed("party_password", party.getPartyPassword())));
} }
@Override @Override
@@ -8,7 +8,7 @@ import com.alttd.velocitychat.VelocityChat;
import com.alttd.velocitychat.commands.SubCommand; import com.alttd.velocitychat.commands.SubCommand;
import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.text.minimessage.placeholder.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -39,7 +39,7 @@ public class Disband implements SubCommand {
return; return;
} }
if (args.length == 1) { if (args.length == 1) {
source.sendMessage(Utility.parseMiniMessage(Config.DISBAND_PARTY_CONFIRM, Placeholder.miniMessage("party", party.getPartyName()))); source.sendMessage(Utility.parseMiniMessage(Config.DISBAND_PARTY_CONFIRM, Placeholder.unparsed("party", party.getPartyName())));
return; return;
} }
if (!args[1].equalsIgnoreCase("confirm") || !args[2].equals(party.getPartyName())) { if (!args[1].equalsIgnoreCase("confirm") || !args[2].equals(party.getPartyName())) {
@@ -48,8 +48,8 @@ public class Disband implements SubCommand {
} }
VelocityChat.getPlugin().getChatHandler().sendPartyMessage(party, VelocityChat.getPlugin().getChatHandler().sendPartyMessage(party,
Utility.parseMiniMessage(Config.DISBANDED_PARTY, Utility.parseMiniMessage(Config.DISBANDED_PARTY,
Placeholder.miniMessage("owner", player.getUsername()), Placeholder.unparsed("owner", player.getUsername()),
Placeholder.miniMessage("party", party.getPartyName()) Placeholder.unparsed("party", party.getPartyName())
), null); ), null);
party.delete(); party.delete();
} }
@@ -5,16 +5,21 @@ import com.alttd.chat.managers.PartyManager;
import com.alttd.chat.objects.Party; import com.alttd.chat.objects.Party;
import com.alttd.chat.objects.PartyUser; import com.alttd.chat.objects.PartyUser;
import com.alttd.chat.util.Utility; import com.alttd.chat.util.Utility;
import com.alttd.velocitychat.VelocityChat;
import com.alttd.velocitychat.commands.SubCommand; import com.alttd.velocitychat.commands.SubCommand;
import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.placeholder.Placeholder; import net.kyori.adventure.text.JoinConfiguration;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
public class Info implements SubCommand { public class Info implements SubCommand {
@Override @Override
public String getName() { public String getName() {
return "info"; return "info";
@@ -34,14 +39,19 @@ public class Info implements SubCommand {
List<Component> displayNames = new ArrayList<>(); List<Component> displayNames = new ArrayList<>();
for (PartyUser partyUser : party.getPartyUsers()) { for (PartyUser partyUser : party.getPartyUsers()) {
displayNames.add(partyUser.getDisplayName()); Optional<Player> optionalPlayer = VelocityChat.getPlugin().getProxy().getPlayer(partyUser.getUuid());
if (optionalPlayer.isPresent() && optionalPlayer.get().isActive())
displayNames.add(Config.ONLINE_PREFIX.append(partyUser.getDisplayName()));
else
displayNames.add(Config.OFFLINE_PREFIX.append(partyUser.getDisplayName()));
} }
PartyUser owner = party.getPartyUser(party.getOwnerUuid());
source.sendMessage(Utility.parseMiniMessage(Config.PARTY_INFO, source.sendMessage(Utility.parseMiniMessage(Config.PARTY_INFO,
Placeholder.miniMessage("party", party.getPartyName()), Placeholder.unparsed("party", party.getPartyName()),
Placeholder.miniMessage("password", party.getPartyPassword()), Placeholder.unparsed("password", party.getPartyPassword()),
Placeholder.component("owner", party.getPartyUser(party.getOwnerUuid()).getDisplayName()), Placeholder.component("owner", owner == null ? MiniMessage.miniMessage().deserialize("Unknown Owner") : owner.getDisplayName()),
Placeholder.component("members", Component.join(Component.text(", "), displayNames)) Placeholder.component("members", Component.join(JoinConfiguration.separator(Component.text(", ")), displayNames))
)); ));
} }
@@ -8,7 +8,7 @@ import com.alttd.velocitychat.VelocityChat;
import com.alttd.velocitychat.commands.SubCommand; import com.alttd.velocitychat.commands.SubCommand;
import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.text.minimessage.placeholder.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -50,17 +50,22 @@ public class Invite implements SubCommand {
if (!target.isActive()) { if (!target.isActive()) {
source.sendMessage(Utility.parseMiniMessage(Config.NOT_ONLINE, source.sendMessage(Utility.parseMiniMessage(Config.NOT_ONLINE,
Placeholder.miniMessage("player", target.getUsername()) Placeholder.unparsed("player", target.getUsername())
)); ));
return; return;
} }
target.sendMessage(Utility.parseMiniMessage(Config.JOIN_PARTY_CLICK_MESSAGE, target.sendMessage(Utility.parseMiniMessage(Config.JOIN_PARTY_CLICK_MESSAGE,
Placeholder.miniMessage("party", party.getPartyName()), Placeholder.unparsed("party", party.getPartyName()),
Placeholder.miniMessage("party_password", party.getPartyPassword()) Placeholder.unparsed("party_password", party.getPartyPassword())
)); ));
source.sendMessage(Utility.parseMiniMessage(Config.SENT_PARTY_INV, source.sendMessage(Utility.parseMiniMessage(Config.SENT_PARTY_INV,
Placeholder.miniMessage("player", target.getUsername()) Placeholder.unparsed("player", target.getUsername()),
Placeholder.unparsed("party", party.getPartyName()),
Placeholder.unparsed("party_password", party.getPartyPassword())
));
source.sendMessage(Utility.parseMiniMessage(Config.SENT_PARTY_INV,
Placeholder.unparsed("player", target.getUsername())
)); ));
} }
@@ -10,8 +10,7 @@ import com.alttd.velocitychat.VelocityChat;
import com.alttd.velocitychat.commands.SubCommand; import com.alttd.velocitychat.commands.SubCommand;
import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.text.minimessage.Template; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.placeholder.Placeholder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -46,16 +45,17 @@ public class Join implements SubCommand {
// party.addUser(ChatUserManager.getChatUser(player.getUniqueId())); //Removed until we can get nicknames to translate to colors correctly // party.addUser(ChatUserManager.getChatUser(player.getUniqueId())); //Removed until we can get nicknames to translate to colors correctly
ChatUser chatUser = ChatUserManager.getChatUser(player.getUniqueId()); ChatUser chatUser = ChatUserManager.getChatUser(player.getUniqueId());
if (chatUser.getPartyId() == party.getPartyId()) { if (chatUser.getPartyId() == party.getPartyId()) {
source.sendMessage(Utility.parseMiniMessage(Config.ALREADY_IN_THIS_PARTY, Placeholder.miniMessage("party", party.getPartyName()))); source.sendMessage(Utility.parseMiniMessage(Config.ALREADY_IN_THIS_PARTY, Placeholder.parsed("party", party.getPartyName())));
return; return;
} }
party.addUser(chatUser, player.getUsername()); party.addUser(chatUser, player.getUsername());
source.sendMessage(Utility.parseMiniMessage(Config.JOINED_PARTY, Placeholder.miniMessage("party_name", party.getPartyName()))); source.sendMessage(Utility.parseMiniMessage(Config.JOINED_PARTY, Placeholder.parsed("party_name", party.getPartyName())));
VelocityChat.getPlugin().getChatHandler().sendPartyMessage(party, VelocityChat.getPlugin().getChatHandler().sendPartyMessage(party,
Utility.parseMiniMessage(Config.PLAYER_JOINED_PARTY, Utility.parseMiniMessage(Config.PLAYER_JOINED_PARTY,
Placeholder.component("player_name", chatUser.getDisplayName()), Placeholder.component("player_name", chatUser.getDisplayName()),
Placeholder.miniMessage("party_name", party.getPartyName()) Placeholder.parsed("party_name", party.getPartyName())
), null); ), null);
} }
@@ -9,7 +9,7 @@ import com.alttd.velocitychat.commands.SubCommand;
import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ServerConnection; import com.velocitypowered.api.proxy.ServerConnection;
import net.kyori.adventure.text.minimessage.placeholder.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -45,8 +45,8 @@ public class Leave implements SubCommand {
source.sendMessage(Utility.parseMiniMessage(Config.NOTIFY_FINDING_NEW_OWNER)); source.sendMessage(Utility.parseMiniMessage(Config.NOTIFY_FINDING_NEW_OWNER));
VelocityChat.getPlugin().getChatHandler().sendPartyMessage(party, VelocityChat.getPlugin().getChatHandler().sendPartyMessage(party,
Utility.parseMiniMessage(Config.OWNER_LEFT_PARTY, Utility.parseMiniMessage(Config.OWNER_LEFT_PARTY,
Placeholder.miniMessage("old_owner", player.getUsername()), Placeholder.unparsed("old_owner", player.getUsername()),
Placeholder.miniMessage("new_owner", party.getPartyUser(uuid).getPlayerName()) Placeholder.unparsed("new_owner", party.getPartyUser(uuid).getPlayerName())
), null); ), null);
} else { } else {
party.delete(); party.delete();
@@ -55,7 +55,7 @@ public class Leave implements SubCommand {
source.sendMessage(Utility.parseMiniMessage(Config.LEFT_PARTY)); source.sendMessage(Utility.parseMiniMessage(Config.LEFT_PARTY));
VelocityChat.getPlugin().getChatHandler().sendPartyMessage(party, VelocityChat.getPlugin().getChatHandler().sendPartyMessage(party,
Utility.parseMiniMessage(Config.PLAYER_LEFT_PARTY, Utility.parseMiniMessage(Config.PLAYER_LEFT_PARTY,
Placeholder.miniMessage("player_name", player.getUsername()) Placeholder.unparsed("player_name", player.getUsername())
), null); ), null);
} }
} }
@@ -9,7 +9,7 @@ import com.alttd.velocitychat.VelocityChat;
import com.alttd.velocitychat.commands.SubCommand; import com.alttd.velocitychat.commands.SubCommand;
import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.text.minimessage.placeholder.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -45,7 +45,7 @@ public class Name implements SubCommand {
} }
if (PartyManager.getParty(args[1]) != null) { if (PartyManager.getParty(args[1]) != null) {
source.sendMessage(Utility.parseMiniMessage(Config.PARTY_EXISTS, source.sendMessage(Utility.parseMiniMessage(Config.PARTY_EXISTS,
Placeholder.miniMessage("party", args[1]) Placeholder.unparsed("party", args[1])
)); ));
return; return;
} }
@@ -54,8 +54,8 @@ public class Name implements SubCommand {
party.setPartyName(args[1]); party.setPartyName(args[1]);
VelocityChat.getPlugin().getChatHandler().sendPartyMessage(party, Utility.parseMiniMessage(Config.RENAMED_PARTY, VelocityChat.getPlugin().getChatHandler().sendPartyMessage(party, Utility.parseMiniMessage(Config.RENAMED_PARTY,
Placeholder.component("owner", ChatUserManager.getChatUser(player.getUniqueId()).getDisplayName()), Placeholder.component("owner", ChatUserManager.getChatUser(player.getUniqueId()).getDisplayName()),
Placeholder.miniMessage("old_name", oldName), Placeholder.unparsed("old_name", oldName),
Placeholder.miniMessage("new_name", args[1]) Placeholder.unparsed("new_name", args[1])
), null); ), null);
} }
@@ -9,7 +9,7 @@ import com.alttd.velocitychat.VelocityChat;
import com.alttd.velocitychat.commands.SubCommand; import com.alttd.velocitychat.commands.SubCommand;
import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.text.minimessage.placeholder.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -44,15 +44,15 @@ public class Owner implements SubCommand {
PartyUser partyUser = party.getPartyUser(args[1]); PartyUser partyUser = party.getPartyUser(args[1]);
if (partyUser == null) { if (partyUser == null) {
source.sendMessage(Utility.parseMiniMessage(Config.NOT_A_PARTY_MEMBER, source.sendMessage(Utility.parseMiniMessage(Config.NOT_A_PARTY_MEMBER,
Placeholder.miniMessage("player", args[1]) Placeholder.unparsed("player", args[1])
)); ));
return; return;
} }
party.setNewOwner(partyUser.getUuid()); party.setNewOwner(partyUser.getUuid());
VelocityChat.getPlugin().getChatHandler().sendPartyMessage(party, VelocityChat.getPlugin().getChatHandler().sendPartyMessage(party,
Utility.parseMiniMessage(Config.NEW_PARTY_OWNER, Utility.parseMiniMessage(Config.NEW_PARTY_OWNER,
Placeholder.miniMessage("old_owner", player.getUsername()), Placeholder.unparsed("old_owner", player.getUsername()),
Placeholder.miniMessage("new_owner", partyUser.getPlayerName()) Placeholder.unparsed("new_owner", partyUser.getPlayerName())
), null); ), null);
} }
@@ -10,7 +10,7 @@ import com.alttd.velocitychat.VelocityChat;
import com.alttd.velocitychat.commands.SubCommand; import com.alttd.velocitychat.commands.SubCommand;
import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.text.minimessage.placeholder.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -50,7 +50,7 @@ public class Remove implements SubCommand {
partyUser = party.getPartyUser(args[1]); partyUser = party.getPartyUser(args[1]);
if (partyUser == null) { if (partyUser == null) {
source.sendMessage(Utility.parseMiniMessage(Config.NOT_A_PARTY_MEMBER, source.sendMessage(Utility.parseMiniMessage(Config.NOT_A_PARTY_MEMBER,
Placeholder.miniMessage("player", args[1]) Placeholder.unparsed("player", args[1])
)); ));
return; return;
} }
@@ -59,26 +59,27 @@ public class Remove implements SubCommand {
partyUser = party.getPartyUser(onlinePlayer.getUniqueId()); partyUser = party.getPartyUser(onlinePlayer.getUniqueId());
if (partyUser == null) { if (partyUser == null) {
source.sendMessage(Utility.parseMiniMessage(Config.NOT_A_PARTY_MEMBER, source.sendMessage(Utility.parseMiniMessage(Config.NOT_A_PARTY_MEMBER,
Placeholder.miniMessage("player", onlinePlayer.getUsername()) Placeholder.unparsed("player", onlinePlayer.getUsername())
)); ));
return; return;
} }
} }
party.removeUser(ChatUserManager.getChatUser(partyUser.getUuid()));
if (partyUser.getUuid().equals(party.getOwnerUuid())) { if (partyUser.getUuid().equals(party.getOwnerUuid())) {
source.sendMessage(Utility.parseMiniMessage(Config.CANT_REMOVE_PARTY_OWNER)); source.sendMessage(Utility.parseMiniMessage(Config.CANT_REMOVE_PARTY_OWNER));
return; return;
} }
party.removeUser(ChatUserManager.getChatUser(partyUser.getUuid()));
if (onlinePlayer != null && onlinePlayer.isActive()) { if (onlinePlayer != null && onlinePlayer.isActive()) {
onlinePlayer.sendMessage(Utility.parseMiniMessage(Config.REMOVED_FROM_PARTY, onlinePlayer.sendMessage(Utility.parseMiniMessage(Config.REMOVED_FROM_PARTY,
Placeholder.miniMessage("party", party.getPartyName()) Placeholder.unparsed("party", party.getPartyName())
)); ));
} }
source.sendMessage(Utility.parseMiniMessage(Config.REMOVED_USER_FROM_PARTY, source.sendMessage(Utility.parseMiniMessage(Config.REMOVED_USER_FROM_PARTY,
Placeholder.miniMessage("player", onlinePlayer == null ? partyUser.getPlayerName() : onlinePlayer.getUsername()) Placeholder.unparsed("player", onlinePlayer == null ? partyUser.getPlayerName() : onlinePlayer.getUsername())
)); ));
} }
@@ -5,10 +5,7 @@ import com.alttd.chat.database.Queries;
import com.alttd.chat.managers.ChatUserManager; import com.alttd.chat.managers.ChatUserManager;
import com.alttd.chat.managers.PartyManager; import com.alttd.chat.managers.PartyManager;
import com.alttd.chat.managers.RegexManager; import com.alttd.chat.managers.RegexManager;
import com.alttd.chat.objects.ChatUser; import com.alttd.chat.objects.*;
import com.alttd.chat.objects.Mail;
import com.alttd.chat.objects.ModifiableString;
import com.alttd.chat.objects.Party;
import com.alttd.chat.util.ALogger; import com.alttd.chat.util.ALogger;
import com.alttd.chat.util.Utility; import com.alttd.chat.util.Utility;
import com.alttd.velocitychat.VelocityChat; import com.alttd.velocitychat.VelocityChat;
@@ -18,14 +15,16 @@ import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ServerConnection; import com.velocitypowered.api.proxy.ServerConnection;
import net.kyori.adventure.text.Component; 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.MiniMessage;
import net.kyori.adventure.text.minimessage.placeholder.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.placeholder.Replacement; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.time.Duration;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit;
public class ChatHandler { public class ChatHandler {
@@ -37,26 +36,25 @@ public class ChatHandler {
Player player = optionalPlayer.get(); Player player = optionalPlayer.get();
Optional<Player> optionalPlayer2 = VelocityChat.getPlugin().getProxy().getPlayer(target); Optional<Player> optionalPlayer2 = VelocityChat.getPlugin().getProxy().getPlayer(target);
if(optionalPlayer2.isEmpty()) { if(optionalPlayer2.isEmpty()) return;
player.sendMessage(MiniMessage.markdown().parse(Config.RECEIVER_DOES_NOT_EXIST, Placeholder.miniMessage("player", target)));
return;
}
Player player2 = optionalPlayer2.get(); Player player2 = optionalPlayer2.get();
ChatUser targetUser = ChatUserManager.getChatUser(player2.getUniqueId()); ChatUser targetUser = ChatUserManager.getChatUser(player2.getUniqueId());
Map<String, Replacement<?>> placeholders = new HashMap<>(); TagResolver Placeholders = TagResolver.resolver(
placeholders.put("sender", Replacement.component(senderUser.getDisplayName())); Placeholder.component("sender", senderUser.getDisplayName()),
placeholders.put("sendername", Replacement.miniMessage(player.getUsername())); Placeholder.unparsed("sendername", player.getUsername()),
placeholders.put("receiver", Replacement.component(targetUser.getDisplayName())); Placeholder.component("receiver", targetUser.getDisplayName()),
placeholders.put("receivername", Replacement.miniMessage(player2.getUsername())); Placeholder.unparsed("receivername", player2.getUsername()),
placeholders.put("message", Replacement.component(GsonComponentSerializer.gson().deserialize(message))); Placeholder.component("message", GsonComponentSerializer.gson().deserialize(message)),
placeholders.put("server", Replacement.miniMessage(player.getCurrentServer().isPresent() ? player.getCurrentServer().get().getServerInfo().getName() : "Altitude")); Placeholder.unparsed("server", player.getCurrentServer().isPresent() ? player.getCurrentServer().get().getServerInfo().getName() : "Altitude"));
ServerConnection serverConnection; ServerConnection serverConnection;
if(player.getCurrentServer().isPresent() && player2.getCurrentServer().isPresent()) { if(player.getCurrentServer().isPresent() && player2.getCurrentServer().isPresent()) {
// redirect to the sender // redirect to the sender
serverConnection = player.getCurrentServer().get(); serverConnection = player.getCurrentServer().get();
Component component = Utility.parseMiniMessage(Config.MESSAGESENDER, placeholders); Component component = Utility.parseMiniMessage(Config.MESSAGESENDER
.replaceAll("<sendername>", player.getUsername())
.replaceAll("<receivername>", player2.getUsername()), Placeholders);
ByteArrayDataOutput buf = ByteStreams.newDataOutput(); ByteArrayDataOutput buf = ByteStreams.newDataOutput();
buf.writeUTF("privatemessageout"); buf.writeUTF("privatemessageout");
buf.writeUTF(player.getUniqueId().toString()); buf.writeUTF(player.getUniqueId().toString());
@@ -67,7 +65,9 @@ public class ChatHandler {
//redirect to the receiver //redirect to the receiver
serverConnection = player2.getCurrentServer().get(); serverConnection = player2.getCurrentServer().get();
component = Utility.parseMiniMessage(Config.MESSAGERECIEVER, placeholders); component = Utility.parseMiniMessage(Config.MESSAGERECIEVER
.replaceAll("<sendername>", player.getUsername())
.replaceAll("<receivername>", player2.getUsername()), Placeholders);
buf = ByteStreams.newDataOutput(); buf = ByteStreams.newDataOutput();
buf.writeUTF("privatemessagein"); buf.writeUTF("privatemessagein");
buf.writeUTF(player2.getUniqueId().toString()); buf.writeUTF(player2.getUniqueId().toString());
@@ -80,12 +80,13 @@ public class ChatHandler {
} }
public static void sendBlockedNotification(String prefix, Player player, String input, String target, ServerConnection serverConnection) { public static void sendBlockedNotification(String prefix, Player player, String input, String target, ServerConnection serverConnection) {
Map<String, Replacement<?>> placeholders = new HashMap<>(); TagResolver Placeholders = TagResolver.resolver(
placeholders.put("prefix", Replacement.miniMessage(prefix)); Placeholder.unparsed("prefix", prefix),
placeholders.put("displayname", Replacement.miniMessage(Utility.getDisplayName(player.getUniqueId(), player.getUsername()))); Placeholder.parsed("displayname", Utility.getDisplayName(player.getUniqueId(), player.getUsername())),
placeholders.put("target", Replacement.miniMessage((target.isEmpty() ? " tried to say: " : " -> " + target + ": "))); Placeholder.unparsed("target", (target.isEmpty() ? " tried to say: " : " -> " + target + ": ")),
placeholders.put("input", Replacement.miniMessage(input)); Placeholder.unparsed("input", input)
Component blockedNotification = Utility.parseMiniMessage(Config.NOTIFICATIONFORMAT, placeholders); );
Component blockedNotification = Utility.parseMiniMessage(Config.NOTIFICATIONFORMAT, Placeholders);
serverConnection.getServer().getPlayersConnected().forEach(pl ->{ serverConnection.getServer().getPlayersConnected().forEach(pl ->{
if (pl.hasPermission("chat.alert-blocked")) { if (pl.hasPermission("chat.alert-blocked")) {
@@ -106,6 +107,8 @@ public class ChatHandler {
return party.getPartyUsers().stream().anyMatch(pu -> pu.getUuid().equals(uuid)); return party.getPartyUsers().stream().anyMatch(pu -> pu.getUuid().equals(uuid));
}).forEach(pl -> { }).forEach(pl -> {
pl.sendMessage(message); pl.sendMessage(message);
// TODO forward sound to backend server.
// https://canary.discord.com/channels/514920774923059209/1020498592219271189
}); });
} }
@@ -121,42 +124,34 @@ public class ChatHandler {
} }
Component senderName = user.getDisplayName(); Component senderName = user.getDisplayName();
ModifiableString modifiableString = new ModifiableString(message); TagResolver Placeholders = TagResolver.resolver(
if (!RegexManager.filterText(player.getUsername(), uuid, modifiableString, "partychat")) { Placeholder.component("sender", senderName),
sendBlockedNotification("Party Language", Placeholder.component("sendername", senderName),
player, Placeholder.unparsed("partyname", party.getPartyName()),
modifiableString.string(), Placeholder.component("message", parseMessageContent(player, message)),
"", Placeholder.unparsed("server", serverConnection.getServer().getServerInfo().getName())
serverConnection); );
Component partyMessage = Utility.parseMiniMessage(Config.PARTY_FORMAT, Placeholders)
.replaceText(TextReplacementConfig.builder().once().matchLiteral("[i]").replacement(item).build());
ModifiableString modifiableString = new ModifiableString(partyMessage);
if (!RegexManager.filterText(player.getUsername(), uuid, modifiableString, "party")) {
sendBlockedNotification("Party Language", player, message, "", serverConnection);
return; // the message was blocked return; // the message was blocked
} }
String updatedMessage = modifiableString.string(); partyMessage = modifiableString.component();
if(!player.hasPermission("chat.format")) {
updatedMessage = Utility.stripTokens(updatedMessage);
}
if(updatedMessage.contains("[i]")) updatedMessage = updatedMessage.replace("[i]", "<[i]>");
updatedMessage = Utility.formatText(updatedMessage);
Map<String, Replacement<?>> placeholders = new HashMap<>();
placeholders.put("sender", Replacement.component(senderName));
placeholders.put("username", Replacement.miniMessage(player.getUsername()));
placeholders.put("party", Replacement.miniMessage(party.getPartyName()));
placeholders.put("message", Replacement.miniMessage(updatedMessage));
placeholders.put("server", Replacement.miniMessage(serverConnection.getServer().getServerInfo().getName()));
placeholders.put("[i]", Replacement.component(item));
Component partyMessage = Utility.parseMiniMessage(Config.PARTY_FORMAT, placeholders);
sendPartyMessage(party, partyMessage, user.getIgnoredBy()); sendPartyMessage(party, partyMessage, user.getIgnoredBy());
Component spyMessage = Utility.parseMiniMessage(Config.PARTY_SPY, placeholders); Component spyMessage = Utility.parseMiniMessage(Config.PARTY_SPY, Placeholders);
for(Player pl : serverConnection.getServer().getPlayersConnected()) { for(Player pl : serverConnection.getServer().getPlayersConnected()) {
if(pl.hasPermission(Config.SPYPERMISSION) && !party.getPartyUsersUuid().contains(pl.getUniqueId())) { if(pl.hasPermission(Config.SPYPERMISSION) && !party.getPartyUsersUuid().contains(pl.getUniqueId())) {
pl.sendMessage(spyMessage); pl.sendMessage(spyMessage);
} }
} }
ALogger.info(PlainTextComponentSerializer.plainText().serialize(partyMessage));
} }
public void globalAdminChat(String message) { public void globalAdminChat(String message) {
@@ -178,12 +173,12 @@ public class ChatHandler {
serverName = sender.getCurrentServer().isPresent() ? sender.getCurrentServer().get().getServerInfo().getName() : "Altitude"; serverName = sender.getCurrentServer().isPresent() ? sender.getCurrentServer().get().getServerInfo().getName() : "Altitude";
} }
Map<String, Replacement<?>> placeholders = new HashMap<>(); TagResolver Placeholders = TagResolver.resolver(
placeholders.put("message", Replacement.miniMessage(Utility.formatText(message))); Placeholder.component("message", parseMessageContent(commandSource, message)),
placeholders.put("sender", Replacement.component(senderName)); Placeholder.component("sender", senderName),
placeholders.put("server", Replacement.miniMessage(serverName)); Placeholder.unparsed("server", serverName));
Component component = Utility.parseMiniMessage(Config.GACFORMAT, placeholders); Component component = Utility.parseMiniMessage(Config.GACFORMAT, Placeholders);
VelocityChat.getPlugin().getProxy().getAllPlayers().stream().filter(target -> target.hasPermission("command.chat.globaladminchat")/*TODO permission*/).forEach(target -> { VelocityChat.getPlugin().getProxy().getAllPlayers().stream().filter(target -> target.hasPermission("command.chat.globaladminchat")/*TODO permission*/).forEach(target -> {
target.sendMessage(component); target.sendMessage(component);
@@ -198,7 +193,6 @@ public class ChatHandler {
uuid = player.getUniqueId(); uuid = player.getUniqueId();
senderName = player.getUsername(); senderName = player.getUsername();
} }
Optional<Player> optionalPlayer = VelocityChat.getPlugin().getProxy().getPlayer(recipient); Optional<Player> optionalPlayer = VelocityChat.getPlugin().getProxy().getPlayer(recipient);
if (optionalPlayer.isEmpty()) { if (optionalPlayer.isEmpty()) {
targetUUID = ServerHandler.getPlayerUUID(recipient); targetUUID = ServerHandler.getPlayerUUID(recipient);
@@ -209,35 +203,39 @@ public class ChatHandler {
} else { } else {
targetUUID = optionalPlayer.get().getUniqueId(); targetUUID = optionalPlayer.get().getUniqueId();
} }
if (!commandSource.hasPermission("chat.format"))
message = Utility.stripTokens(message);
else
message = Utility.parseColors(message);
Mail mail = new Mail(targetUUID, uuid, message); Mail mail = new Mail(targetUUID, uuid, message);
ChatUser chatUser = ChatUserManager.getChatUser(targetUUID); ChatUser chatUser = ChatUserManager.getChatUser(targetUUID);
chatUser.addMail(mail); chatUser.addMail(mail);
// TODO load from config // TODO load from config
Map<String, Replacement<?>> placeholders = new HashMap<>(); String finalSenderName = senderName;
placeholders.put("sender", Replacement.miniMessage(senderName)); optionalPlayer.ifPresent(player -> player.sendMessage(Utility.parseMiniMessage("<yellow>New mail from " + finalSenderName)));
optionalPlayer.ifPresent(player -> player.sendMessage(Utility.parseMiniMessage(Config.mailReceived, placeholders))); commandSource.sendMessage(Utility.parseMiniMessage("<yellow>Sent mail to " + recipient + "!"));
commandSource.sendMessage(Utility.parseMiniMessage(Config.mailSent,
Placeholder.component("player_name", chatUser.getDisplayName()),
Placeholder.miniMessage("message", message)
));
} }
public void readMail(CommandSource commandSource, String targetPlayer) { public void readMail(CommandSource commandSource, String targetPlayer, String senderPlayer) {
UUID uuid = ServerHandler.getPlayerUUID(targetPlayer); UUID uuid = ServerHandler.getPlayerUUID(targetPlayer);
if (uuid == null) { if (uuid == null) {
commandSource.sendMessage(Utility.parseMiniMessage(Config.mailNoUser)); commandSource.sendMessage(Utility.parseMiniMessage(Config.mailNoUser));
return; return;
} }
ChatUser chatUser = ChatUserManager.getChatUser(uuid); ChatUser chatUser = ChatUserManager.getChatUser(uuid);
if (senderPlayer == null) {
commandSource.sendMessage(parseMails(chatUser.getMails(), false)); commandSource.sendMessage(parseMails(chatUser.getMails(), false));
} }
UUID sender = ServerHandler.getPlayerUUID(senderPlayer);
if (sender == null) {
commandSource.sendMessage(Utility.parseMiniMessage(Config.mailNoUser));
return;
}
List<Mail> mails = chatUser.getMails().stream()
.filter(mail -> mail.getSender().equals(sender))
.toList();
commandSource.sendMessage(parseMails(mails, false));
}
public void readMail(CommandSource commandSource, boolean unread) { public void readMail(CommandSource commandSource, boolean unread) {
if (commandSource instanceof Player player) { if (commandSource instanceof Player player) {
ChatUser chatUser = ChatUserManager.getChatUser(player.getUniqueId()); ChatUser chatUser = ChatUserManager.getChatUser(player.getUniqueId());
@@ -252,15 +250,16 @@ public class ChatHandler {
mail.setReadTime(System.currentTimeMillis()); mail.setReadTime(System.currentTimeMillis());
Queries.markMailRead(mail); Queries.markMailRead(mail);
} }
Date date = new Date(mail.getSendTime());
ChatUser chatUser = ChatUserManager.getChatUser(mail.getSender()); ChatUser chatUser = ChatUserManager.getChatUser(mail.getSender());
Date sentTime = new Date(mail.getSendTime()); TagResolver Placeholders = TagResolver.resolver(
Map<String, Replacement<?>> placeholders = new HashMap<>(); Placeholder.component("staffprefix", chatUser.getStaffPrefix()),
placeholders.put("staffprefix", Replacement.component(chatUser.getStaffPrefix())); Placeholder.component("sender", chatUser.getDisplayName()),
placeholders.put("sender", Replacement.component(chatUser.getDisplayName())); Placeholder.component("message", Utility.parseMiniMessage(mail.getMessage())),
placeholders.put("message", Replacement.miniMessage(mail.getMessage())); Placeholder.unparsed("date", date.toString()),
placeholders.put("date", Replacement.miniMessage(sentTime.toString())); Placeholder.unparsed("time_ago", getTimeAgo(Duration.between(date.toInstant(), new Date().toInstant())))
placeholders.put("time_ago", Replacement.miniMessage(String.valueOf(TimeUnit.MILLISECONDS.toDays(new Date().getTime() - sentTime.getTime())))); );
Component mailMessage = Utility.parseMiniMessage(Config.mailBody, placeholders); Component mailMessage = Utility.parseMiniMessage(Config.mailBody, Placeholders);
component = component.append(Component.newline()).append(mailMessage); component = component.append(Component.newline()).append(mailMessage);
} }
component = component.append(Component.newline()).append(Utility.parseMiniMessage(Config.mailFooter)); component = component.append(Component.newline()).append(Utility.parseMiniMessage(Config.mailFooter));
@@ -287,4 +286,37 @@ public class ChatHandler {
buf.writeUTF(uuid); buf.writeUTF(uuid);
buf.writeBoolean(muted); buf.writeBoolean(muted);
} }
private String getTimeAgo(Duration duration) {
StringBuilder stringBuilder = new StringBuilder();
if (duration.toDays() != 0)
stringBuilder.append(duration.toDays()).append("d ");
if (duration.toHoursPart() != 0 || !stringBuilder.isEmpty())
stringBuilder.append(duration.toHoursPart()).append("h ");
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;
}
} }
@@ -9,7 +9,7 @@ import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.placeholder.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -34,9 +34,9 @@ public class ChatListener {
} }
Component message = Utility.parseMiniMessage(Config.GACFORMAT, Component message = Utility.parseMiniMessage(Config.GACFORMAT,
Placeholder.miniMessage("sender", senderName), Placeholder.parsed("sender", senderName),
Placeholder.miniMessage("message", event.getMessage()), Placeholder.component("message", Utility.parseMiniMessage(event.getMessage())),
Placeholder.miniMessage("server", serverName) Placeholder.parsed("server", serverName)
); );
plugin.getProxy().getAllPlayers().stream().filter(target -> target.hasPermission("command.chat.globaladminchat")).forEach(target -> { plugin.getProxy().getAllPlayers().stream().filter(target -> target.hasPermission("command.chat.globaladminchat")).forEach(target -> {
@@ -2,14 +2,16 @@ package com.alttd.velocitychat.listeners;
import com.alttd.chat.managers.ChatUserManager; import com.alttd.chat.managers.ChatUserManager;
import com.alttd.chat.objects.ChatUser; 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.objects.channels.CustomChannel;
import com.alttd.chat.util.ALogger; import com.alttd.chat.util.ALogger;
import com.alttd.proxydiscordlink.DiscordLink;
import com.alttd.proxydiscordlink.lib.net.dv8tion.jda.api.EmbedBuilder;
import com.alttd.velocitychat.VelocityChat;
import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.PluginMessageEvent; import com.velocitypowered.api.event.connection.PluginMessageEvent;
import com.velocitypowered.api.proxy.ConsoleCommandSource;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.ServerConnection; import com.velocitypowered.api.proxy.ServerConnection;
@@ -17,13 +19,14 @@ import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.proxy.server.RegisteredServer;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import java.awt.*;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
public class PluginMessageListener { public class PluginMessageListener {
//todo add an extra listener for nicknames?
private final ChannelIdentifier identifier; private final ChannelIdentifier identifier;
public PluginMessageListener(ChannelIdentifier identifier){ public PluginMessageListener(ChannelIdentifier identifier){
@@ -45,16 +48,11 @@ public class PluginMessageListener {
String channel = in.readUTF(); String channel = in.readUTF();
VelocityChat.getPlugin().getLogger().info("server " + event.getSource()); VelocityChat.getPlugin().getLogger().info("server " + event.getSource());
switch (channel) { switch (channel) {
case "globalchat": case "globalchat" -> VelocityChat.getPlugin().getServerHandler().sendGlobalChat(in.readUTF(), in.readUTF());
VelocityChat.getPlugin().getServerHandler().sendGlobalChat(in.readUTF(), in.readUTF()); case "globaladminchat" -> VelocityChat.getPlugin().getChatHandler().globalAdminChat(in.readUTF());
break; case "privatemessage" ->
case "globaladminchat":
VelocityChat.getPlugin().getChatHandler().globalAdminChat(in.readUTF());
break;
case "privatemessage":
VelocityChat.getPlugin().getChatHandler().privateMessage(in.readUTF(), in.readUTF(), in.readUTF()); VelocityChat.getPlugin().getChatHandler().privateMessage(in.readUTF(), in.readUTF(), in.readUTF());
break; case "chatchannel" -> {
case "chatchannel": {
String channelName = in.readUTF(); String channelName = in.readUTF();
CustomChannel chatChannel = (CustomChannel) CustomChannel.getChatChannel(channelName); CustomChannel chatChannel = (CustomChannel) CustomChannel.getChatChannel(channelName);
@@ -66,17 +64,17 @@ public class PluginMessageListener {
ProxyServer proxy = VelocityChat.getPlugin().getProxy(); ProxyServer proxy = VelocityChat.getPlugin().getProxy();
chatChannel.getServers().forEach(server -> proxy.getServer(server).ifPresent(registeredServer -> chatChannel.getServers().forEach(server -> proxy.getServer(server).ifPresent(registeredServer ->
registeredServer.sendPluginMessage(VelocityChat.getPlugin().getChannelIdentifier(), event.getData()))); registeredServer.sendPluginMessage(VelocityChat.getPlugin().getChannelIdentifier(), event.getData())));
break;
} }
case "party": { case "party" -> {
VelocityChat.getPlugin().getChatHandler().sendPartyMessage( VelocityChat.getPlugin().getChatHandler().sendPartyMessage(
UUID.fromString(in.readUTF()), UUID.fromString(in.readUTF()),
in.readUTF(), in.readUTF(),
GsonComponentSerializer.gson().deserialize(in.readUTF()), GsonComponentSerializer.gson().deserialize(in.readUTF()),
serverConnection); serverConnection);
break;
} }
case "NickNameAccepted": {
// nicknames WIP
case "NickNameAccepted", "NickNameSet" -> {
try { try {
short len = in.readShort(); short len = in.readShort();
byte[] msgbytes = new byte[len]; byte[] msgbytes = new byte[len];
@@ -91,15 +89,36 @@ public class PluginMessageListener {
e.printStackTrace(); e.printStackTrace();
return; 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()));
}
case "punish" -> {
String playerName = in.readUTF();
ProxyServer proxy = VelocityChat.getPlugin().getProxy();
ConsoleCommandSource consoleCommandSource = proxy.getConsoleCommandSource();
proxy.getCommandManager().executeAsync(consoleCommandSource, String.format("ban %s Automatic ban, please appeal if you feel review is needed.", playerName));
ALogger.info(String.format("Auto banned %s due to violating the `punish` filter.", playerName));
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setTitle("Automatic ban through the chat filter");
embedBuilder.setAuthor(playerName, null, "https://crafatar.com/avatars/" + in.readUTF() + "?overlay");
embedBuilder.setDescription(String.format("`%s`\n\n Auto permanent ban\n\n Auto banned for violating the `punish` chat filter. This could be a false positive! Their message was\n||%s||", playerName, in.readUTF()));
embedBuilder.setColor(Color.RED);
DiscordLink.getPlugin().getBot().sendEmbedToDiscord(514922317923614728L, embedBuilder, -1);
}
default -> {
VelocityChat.getPlugin().getLogger().info("server " + event.getSource()); VelocityChat.getPlugin().getLogger().info("server " + event.getSource());
ProxyServer proxy = VelocityChat.getPlugin().getProxy(); ProxyServer proxy = VelocityChat.getPlugin().getProxy();
for (RegisteredServer registeredServer : proxy.getAllServers()) { for (RegisteredServer registeredServer : proxy.getAllServers()) {
registeredServer.sendPluginMessage(VelocityChat.getPlugin().getChannelIdentifier(), event.getData()); registeredServer.sendPluginMessage(VelocityChat.getPlugin().getChannelIdentifier(), event.getData());
} }
break; }
} }
} }
@@ -18,8 +18,9 @@ import com.velocitypowered.api.event.player.ServerConnectedEvent;
import com.velocitypowered.api.event.player.ServerPostConnectEvent; import com.velocitypowered.api.event.player.ServerPostConnectEvent;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.proxy.server.RegisteredServer;
import net.kyori.adventure.text.minimessage.placeholder.Placeholder; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.placeholder.Replacement; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import java.util.*; import java.util.*;
@@ -55,7 +56,7 @@ public class ProxyPlayerListener {
if (unReadMail.isEmpty()) if (unReadMail.isEmpty())
return; return;
player.sendMessage(Utility.parseMiniMessage(Config.mailUnread, player.sendMessage(Utility.parseMiniMessage(Config.mailUnread,
Placeholder.miniMessage("amount", String.valueOf(unReadMail.size())) Placeholder.unparsed("amount", String.valueOf(unReadMail.size()))
)); ));
} }
@@ -76,32 +77,59 @@ public class ProxyPlayerListener {
//VelocityChat.getPlugin().getChatHandler().removePlayer(event.getPlayer().getUniqueId()); //VelocityChat.getPlugin().getChatHandler().removePlayer(event.getPlayer().getUniqueId());
} }
private static final HashSet<UUID> silentJoin = new HashSet<>();
public static void addSilentJoin(UUID uuid)
{
silentJoin.add(uuid);
}
// Server Join and Leave messages // Server Join and Leave messages
@Subscribe @Subscribe
public void serverConnected(ServerConnectedEvent event) { public void serverConnected(ServerConnectedEvent event) {
Player player = event.getPlayer();
UUID uuid = player.getUniqueId();
ServerHandler serverHandler = VelocityChat.getPlugin().getServerHandler(); ServerHandler serverHandler = VelocityChat.getPlugin().getServerHandler();
if (event.getPreviousServer().isPresent()) { if (event.getPreviousServer().isPresent()) {
RegisteredServer previousServer = event.getPreviousServer().get(); RegisteredServer previousServer = event.getPreviousServer().get();
Player player = event.getPlayer(); TagResolver placeholders = TagResolver.resolver(
Placeholder.parsed("player", player.getUsername()),
Placeholder.parsed("from_server", previousServer.getServerInfo().getName()),
Placeholder.parsed("to_server", event.getServer().getServerInfo().getName())
);
Map<String, Replacement<?>> placeholders = new HashMap<>(); if (silentJoin.remove(uuid)) {
placeholders.put("player", Replacement.miniMessage(player.getUsername())); Component message = Utility.parseMiniMessage(Config.SILENT_JOIN_JOINED_FROM,
placeholders.put("from_server", Replacement.miniMessage(previousServer.getServerInfo().getName())); placeholders);
placeholders.put("to_server", Replacement.miniMessage(event.getServer().getServerInfo().getName())); event.getServer().getPlayersConnected().stream()
.filter(player1 -> player1.hasPermission("command.chat.silent-join-notify"))
.forEach(player1 -> player1.sendMessage(message));
return;
}
ServerWrapper wrapper = serverHandler.getWrapper(previousServer.getServerInfo().getName()); ServerWrapper wrapper = serverHandler.getWrapper(previousServer.getServerInfo().getName());
if(wrapper != null) { if(wrapper != null) {
wrapper.sendJoinLeaveMessage(event.getPlayer().getUniqueId(), Utility.parseMiniMessage(Config.SERVERSWTICHMESSAGETO, placeholders)); wrapper.sendJoinLeaveMessage(uuid, Utility.parseMiniMessage(Config.SERVERSWTICHMESSAGETO, placeholders));
} }
wrapper = serverHandler.getWrapper(event.getServer().getServerInfo().getName()); wrapper = serverHandler.getWrapper(event.getServer().getServerInfo().getName());
if(wrapper != null) { if(wrapper != null) {
wrapper.sendJoinLeaveMessage(event.getPlayer().getUniqueId(), Utility.parseMiniMessage(Config.SERVERSWTICHMESSAGEFROM, placeholders)); wrapper.sendJoinLeaveMessage(uuid, Utility.parseMiniMessage(Config.SERVERSWTICHMESSAGEFROM, placeholders));
} }
} else { } else {
if (silentJoin.remove(uuid)) {
Component message = Utility.parseMiniMessage(Config.SILENT_JOIN_JOINED,
Placeholder.unparsed("player", player.getUsername()));
event.getServer().getPlayersConnected().stream()
.filter(player1 -> player1.hasPermission("command.chat.silent-join-notify"))
.forEach(player1 -> player1.sendMessage(message));
return;
}
ServerWrapper wrapper = serverHandler.getWrapper(event.getServer().getServerInfo().getName()); ServerWrapper wrapper = serverHandler.getWrapper(event.getServer().getServerInfo().getName());
if(wrapper != null) { if(wrapper != null) {
wrapper.sendJoinLeaveMessage(event.getPlayer().getUniqueId(), Utility.parseMiniMessage(Config.SERVERJOINMESSAGE, Placeholder.miniMessage("player", event.getPlayer().getUsername()))); wrapper.sendJoinLeaveMessage(uuid, Utility.parseMiniMessage(Config.SERVERJOINMESSAGE, Placeholder.unparsed("player", player.getUsername())));
} }
} }
} }
@@ -115,8 +143,8 @@ public class ProxyPlayerListener {
ServerWrapper wrapper = serverHandler.getWrapper(registeredServer.getServerInfo().getName()); ServerWrapper wrapper = serverHandler.getWrapper(registeredServer.getServerInfo().getName());
if(wrapper != null) { if(wrapper != null) {
wrapper.sendJoinLeaveMessage(event.getPlayer().getUniqueId(), Utility.parseMiniMessage(Config.SERVERLEAVEMESSAGE, wrapper.sendJoinLeaveMessage(event.getPlayer().getUniqueId(), Utility.parseMiniMessage(Config.SERVERLEAVEMESSAGE,
Placeholder.miniMessage("player", event.getPlayer().getUsername()), Placeholder.unparsed("player", event.getPlayer().getUsername()),
Placeholder.miniMessage("from_server", registeredServer.getServerInfo().getName()) Placeholder.unparsed("from_server", registeredServer.getServerInfo().getName())
)); ));
} }
} }