Compare commits
4
Commits
fc7860145f
..
matrix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
636ee3c57e | ||
|
|
7cc7cca129 | ||
|
|
3bfd358e78 | ||
|
|
eb30750134 |
@@ -40,3 +40,5 @@ target/
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
*.bat
|
||||
|
||||
@@ -3,10 +3,10 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// compileOnly("com.alttd:Galaxy-API:1.21-R0.1-SNAPSHOT") {
|
||||
// exclude("net.kyori")
|
||||
// }
|
||||
compileOnly("io.papermc.paper:paper-api:1.21-R0.1-SNAPSHOT")
|
||||
// Cosmos
|
||||
compileOnly("com.alttd.cosmos:cosmos-api:1.21.10-R0.1-SNAPSHOT") {
|
||||
isChanging = true
|
||||
}
|
||||
compileOnly("org.spongepowered:configurate-yaml:4.2.0") // Configurate
|
||||
compileOnly("net.luckperms:api:5.5") // Luckperms
|
||||
}
|
||||
|
||||
@@ -182,7 +182,8 @@ public final class Config {
|
||||
|
||||
private static void settings() {
|
||||
PREFIXGROUPS = getList("settings.prefix-groups",
|
||||
Lists.newArrayList("discord", "socialmedia", "eventteam", "eventleader", "youtube", "twitch", "developer"));
|
||||
Lists.newArrayList("discord", "socialmedia", "eventteam", "eventleader", "youtube", "twitch",
|
||||
"developer"));
|
||||
CONFLICTINGPREFIXGROUPS = getList("settings.prefix-conflicts-groups",
|
||||
Lists.newArrayList("eventteam", "eventleader"));
|
||||
STAFFGROUPS = getList("settings.staff-groups",
|
||||
@@ -196,8 +197,10 @@ public final class Config {
|
||||
|
||||
public static List<String> MESSAGECOMMANDALIASES = new ArrayList<>();
|
||||
public static List<String> REPLYCOMMANDALIASES = new ArrayList<>();
|
||||
public static String MESSAGESENDER = "<hover:show_text:Click to reply><click:suggest_command:/msg <receivername> ><light_purple>(Me -> <gray><receiver></gray>)</hover> <message>";
|
||||
public static String MESSAGERECIEVER = "<hover:show_text:Click to reply><click:suggest_command:/msg <sendername> ><light_purple>(<gray><sender></gray> on <server> -> Me)</hover> <message>";
|
||||
public static String MESSAGESENDER =
|
||||
"<hover:show_text:Click to reply><click:suggest_command:/msg <receivername> ><light_purple>(Me -> <gray><receiver></gray>)</hover> <message>";
|
||||
public static String MESSAGERECIEVER =
|
||||
"<hover:show_text:Click to reply><click:suggest_command:/msg <sendername> ><light_purple>(<gray><sender></gray> on <server> -> Me)</hover> <message>";
|
||||
public static String MESSAGESPY = "<gray>(<gray><sendername></gray> -> <receivername>) <message>";
|
||||
public static String RECEIVER_DOES_NOT_EXIST = "<red><player> is not a valid player.</red>";
|
||||
|
||||
@@ -212,7 +215,8 @@ public final class Config {
|
||||
RECEIVER_DOES_NOT_EXIST = getString("commands.message.receiver-does-not-exist", RECEIVER_DOES_NOT_EXIST);
|
||||
}
|
||||
|
||||
public static String GCFORMAT = "<white><light_purple><prefix></light_purple> <gray><sender></gray> <hover:show_text:on <server>><yellow>to Global</yellow></hover><gray>: <message>";
|
||||
public static String GCFORMAT =
|
||||
"<white><light_purple><prefix></light_purple> <gray><sender></gray> <hover:show_text:on <server>><yellow>to Global</yellow></hover><gray>: <message>";
|
||||
public static String GCPERMISSION = "proxy.globalchat";
|
||||
public static List<String> GCALIAS = new ArrayList<>();
|
||||
public static String GCNOTENABLED = "You don't have global chat enabled.";
|
||||
@@ -228,7 +232,8 @@ public final class Config {
|
||||
GCCOOLDOWN = getInt("commands.globalchat.cooldown", GCCOOLDOWN);
|
||||
}
|
||||
|
||||
public static String CHATFORMAT = "<white><light_purple><prefixall> <gray><hover:show_text:Click to message <sendername>><click:suggest_command:/msg <sendername> ><sender></hover>: <white><message>";
|
||||
public static String CHATFORMAT =
|
||||
"<white><light_purple><prefixall> <gray><hover:show_text:Click to message <sendername>><click:suggest_command:/msg <sendername> ><sender></hover>: <white><message>";
|
||||
public static String URLFORMAT = "<click:OPEN_URL:<clickurl>><url></click>";
|
||||
|
||||
private static void Chat() {
|
||||
@@ -237,7 +242,8 @@ public final class Config {
|
||||
}
|
||||
|
||||
public static List<String> GACECOMMANDALIASES = new ArrayList<>();
|
||||
public static String GACFORMAT = "<hover:show_text:Click to reply><click:suggest_command:/acg ><yellow>(<sender> on <server> -> Team)</hover> <message>";
|
||||
public static String GACFORMAT =
|
||||
"<hover:show_text:Click to reply><click:suggest_command:/acg ><yellow>(<sender> on <server> -> Team)</hover> <message>";
|
||||
|
||||
private static void globalAdminChat() {
|
||||
GACECOMMANDALIASES = getList("commands.globaladminchat.aliases", Lists.newArrayList("acg"));
|
||||
@@ -269,8 +275,10 @@ public final class Config {
|
||||
|
||||
}
|
||||
|
||||
public static String PARTY_FORMAT = "<dark_aqua>(<gray><sender></gray><hover:show_text:\"on <server>\"> → <party></hover>) <message>";
|
||||
public static String PARTY_SPY = "<i><gray>PC:</gray><dark_gray> <dark_gray><username></dark_gray>: <dark_gray><party></dark_gray> <message></dark_gray></i>";
|
||||
public static String PARTY_FORMAT =
|
||||
"<dark_aqua>(<gray><sender></gray><hover:show_text:\"on <server>\"> → <party></hover>) <message>";
|
||||
public static String PARTY_SPY =
|
||||
"<i><gray>PC:</gray><dark_gray> <dark_gray><username></dark_gray>: <dark_gray><party></dark_gray> <message></dark_gray></i>";
|
||||
public static String NO_PERMISSION = "<red>You don't have permission to use this command.</red>";
|
||||
public static String NO_CONSOLE = "<red>This command can not be used by console</red>";
|
||||
public static String CREATED_PARTY = "<green>You created a chat party called: " +
|
||||
@@ -284,9 +292,11 @@ public final class Config {
|
||||
public static String INVALID_PASSWORD = "<red>Invalid password.</red>";
|
||||
public static String JOINED_PARTY = "<green>You joined <party_name>!</green>";
|
||||
public static String PLAYER_JOINED_PARTY = "<green><player_name> joined <party_name>!</green>";
|
||||
public static String NOTIFY_FINDING_NEW_OWNER = "<dark_aqua>Since you own this chat party a new party owner will be chosen.<dark_aqua>";
|
||||
public static String NOTIFY_FINDING_NEW_OWNER =
|
||||
"<dark_aqua>Since you own this chat party a new party owner will be chosen.<dark_aqua>";
|
||||
public static String LEFT_PARTY = "<green>You have left the chat party!</green>";
|
||||
public static String OWNER_LEFT_PARTY = "<dark_aqua>[ChatParty]: <old_owner> left the chat party, the new party owner is <new_owner></dark_aqua>";
|
||||
public static String OWNER_LEFT_PARTY =
|
||||
"<dark_aqua>[ChatParty]: <old_owner> left the chat party, the new party owner is <new_owner></dark_aqua>";
|
||||
public static String PLAYER_LEFT_PARTY = "<dark_aqua>[ChatParty]: <player_name> left the chat party!</dark_aqua>";
|
||||
public static String NEW_PARTY_OWNER = "<dark_aqua>[ChatParty]: <old_owner> transferred the party to <new_owner>!";
|
||||
public static String CANT_REMOVE_PARTY_OWNER = "<red>You can't remove yourself, please leave instead.</red>";
|
||||
@@ -300,11 +310,13 @@ public final class Config {
|
||||
"<dark_aqua>You received an invite to join <party>, click this message to accept.</dark_aqua></click>";
|
||||
public static String PARTY_MEMBER_LOGGED_ON = "<dark_aqua>[ChatParty] <player> joined Altitude...</dark_aqua>";
|
||||
public static String PARTY_MEMBER_LOGGED_OFF = "<dark_aqua>[ChatParty] <player> left Altitude...</dark_aqua>";
|
||||
public static String RENAMED_PARTY = "<dark_aqua>[ChatParty] <owner> changed the party name from <old_name> to <new_name>!</dark_aqua>";
|
||||
public static String RENAMED_PARTY =
|
||||
"<dark_aqua>[ChatParty] <owner> changed the party name from <old_name> to <new_name>!</dark_aqua>";
|
||||
public static String CHANGED_PASSWORD = "<green>Password was set to <password></green>";
|
||||
public static String DISBAND_PARTY_CONFIRM = "<green><bold>Are you sure you want to disband your party?</bold> " +
|
||||
"Type <gold>/party disband confirm <party></gold> to confirm.";
|
||||
public static String DISBANDED_PARTY = "<dark_aqua>[ChatParty] <owner> has disbanded <party>, everyone has been removed.</dark_aqua>";
|
||||
public static String DISBANDED_PARTY =
|
||||
"<dark_aqua>[ChatParty] <owner> has disbanded <party>, everyone has been removed.</dark_aqua>";
|
||||
public static String PARTY_INFO = """
|
||||
<gold><bold>Chat party info</bold>:
|
||||
</gold><green>Name: <dark_aqua><party></dark_aqua>
|
||||
@@ -353,16 +365,25 @@ public final class Config {
|
||||
|
||||
public static String PARTY_HELP_WRAPPER = "<gold>ChatParty help:\n<commands></gold>";
|
||||
public static String PARTY_HELP_HELP = "<green>Show this menu: <gold>/party help</gold></green>";
|
||||
public static String PARTY_HELP_CREATE = "<green>Create a party: <gold>/party create <party_name> <party_password></gold></green>";
|
||||
public static String PARTY_HELP_INFO = "<green>Show info about your current party: <gold>/party info</gold></green>";
|
||||
public static String PARTY_HELP_INVITE = "<green>Invite a user to your party: <gold>/party invite <username></gold></green>";
|
||||
public static String PARTY_HELP_JOIN = "<green>Join a party: <gold>/party join <party_name> <party_password></gold></green>";
|
||||
public static String PARTY_HELP_CREATE =
|
||||
"<green>Create a party: <gold>/party create <party_name> <party_password></gold></green>";
|
||||
public static String PARTY_HELP_INFO =
|
||||
"<green>Show info about your current party: <gold>/party info</gold></green>";
|
||||
public static String PARTY_HELP_INVITE =
|
||||
"<green>Invite a user to your party: <gold>/party invite <username></gold></green>";
|
||||
public static String PARTY_HELP_JOIN =
|
||||
"<green>Join a party: <gold>/party join <party_name> <party_password></gold></green>";
|
||||
public static String PARTY_HELP_LEAVE = "<green>Leave your current party: <gold>/party leave</gold></green>";
|
||||
public static String PARTY_HELP_NAME = "<green>Change the name of your party: <gold>/party name <new_name></gold></green>";
|
||||
public static String PARTY_HELP_OWNER = "<green>Change the owner of your party: <gold>/party owner <new_owner_name></gold></green>";
|
||||
public static String PARTY_HELP_PASSWORD = "<green>Change the password of your party: <gold>/party password <new_password></gold></green>";
|
||||
public static String PARTY_HELP_REMOVE = "<green>Remove a member from your party: <gold>/party remove <member_name></gold></green>";
|
||||
public static String PARTY_HELP_DISBAND = "<green>Remove everyone from your party and disband it: <gold>/party disband</gold></green>";
|
||||
public static String PARTY_HELP_NAME =
|
||||
"<green>Change the name of your party: <gold>/party name <new_name></gold></green>";
|
||||
public static String PARTY_HELP_OWNER =
|
||||
"<green>Change the owner of your party: <gold>/party owner <new_owner_name></gold></green>";
|
||||
public static String PARTY_HELP_PASSWORD =
|
||||
"<green>Change the password of your party: <gold>/party password <new_password></gold></green>";
|
||||
public static String PARTY_HELP_REMOVE =
|
||||
"<green>Remove a member from your party: <gold>/party remove <member_name></gold></green>";
|
||||
public static String PARTY_HELP_DISBAND =
|
||||
"<green>Remove everyone from your party and disband it: <gold>/party disband</gold></green>";
|
||||
public static String PARTY_HELP_CHAT = "<green>Talk in party chat: <gold>/p <message></gold></green>";
|
||||
|
||||
private static void partyHelp() {
|
||||
@@ -385,12 +406,14 @@ public final class Config {
|
||||
public static ComponentLike TOGGLED_ON = null;
|
||||
public static ComponentLike TOGGLED_OFF = null;
|
||||
public static double LOCAL_DISTANCE;
|
||||
public static String CHANNEL_SPY = "<i><gray>SPY:</gray> <dark_gray>(<dark_gray><sender> → <channel>) <message></dark_gray>";
|
||||
public static String CHANNEL_SPY =
|
||||
"<i><gray>SPY:</gray> <dark_gray>(<dark_gray><sender> → <channel>) <message></dark_gray>";
|
||||
|
||||
private static void chatChannels() {
|
||||
ConfigurationNode node = getNode("chat-channels");
|
||||
if (node.empty()) {
|
||||
getString("chat-channels.ac.format", "<white><gray><sender></gray> <hover:show_text:on <server>><yellow>to <channel></yellow></hover><gray>: <message>");
|
||||
getString("chat-channels.ac.format",
|
||||
"<white><gray><sender></gray> <hover:show_text:on <server>><yellow>to <channel></yellow></hover><gray>: <message>");
|
||||
getList("chat-channels.ac.servers", List.of("lobby"));
|
||||
getBoolean("chat-channels.ac.proxy", false);
|
||||
node = getNode("chat-channels");
|
||||
@@ -402,13 +425,15 @@ public final class Config {
|
||||
new CustomChannel(channelName,
|
||||
getString(key + "format", ""),
|
||||
getList(key + "servers", Collections.EMPTY_LIST),
|
||||
getList(key + "alias", Collections.EMPTY_LIST),
|
||||
getBoolean(key + "proxy", false),
|
||||
getBoolean(key + "local", 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_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>"));
|
||||
LOCAL_DISTANCE = getDouble("chat-channels-messages.local-distance", 200.0);
|
||||
CHANNEL_SPY = getString("chat-channels-messages.spy", CHANNEL_SPY);
|
||||
@@ -443,12 +468,16 @@ public final class Config {
|
||||
}
|
||||
|
||||
public static String mailHeader = "===== List Mails ====='";
|
||||
public static String mailBody = "<white>From:</white> [<staffprefix>] <sender> <white><hover:show_text:'<date>'><time_ago> day(s) ago</hover>: </white><message>";
|
||||
public static String mailBody =
|
||||
"<white>From:</white> [<staffprefix>] <sender> <white><hover:show_text:'<date>'><time_ago> day(s) ago</hover>: </white><message>";
|
||||
public static String mailFooter = "======================";
|
||||
public static String mailNoUser = "<red>A player with this name hasn't logged in recently.";
|
||||
public static String mailReceived = "<yellow><click:run_command:/mail list unread>New mail from <sender>, click to view</click></yellow>";
|
||||
public static String mailUnread = "<green><click:run_command:/mail list unread>You have <amount> unread mail, click to view it.</click></green>";
|
||||
public static String mailSent = "<green>Successfully send mail to <player_name></green>: <#2e8b57><message></#2e8b57>";
|
||||
public static String mailReceived =
|
||||
"<yellow><click:run_command:/mail list unread>New mail from <sender>, click to view</click></yellow>";
|
||||
public static String mailUnread =
|
||||
"<green><click:run_command:/mail list unread>You have <amount> unread mail, click to view it.</click></green>";
|
||||
public static String mailSent =
|
||||
"<green>Successfully send mail to <player_name></green>: <#2e8b57><message></#2e8b57>";
|
||||
public static List<String> mailCommandAlias = new ArrayList<>();
|
||||
public static int mailDisplayDelay = 5;
|
||||
|
||||
@@ -464,8 +493,10 @@ public final class Config {
|
||||
}
|
||||
|
||||
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_TOO_SHORT = "<red>Please ensure your report is descriptive. We require at least 3 words per report</red>";
|
||||
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() {
|
||||
serverChannelId.clear();
|
||||
@@ -500,7 +531,8 @@ public final class Config {
|
||||
}
|
||||
|
||||
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>";
|
||||
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() {
|
||||
HELP_REPORT = getString("settings.mail.mail-sent", HELP_REPORT);
|
||||
@@ -509,7 +541,8 @@ public final class Config {
|
||||
|
||||
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> >>----";
|
||||
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);
|
||||
@@ -521,31 +554,41 @@ public final class Config {
|
||||
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_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_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_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><click:suggest_command:/nick request <nickrequest>>Hi, this is what my new nickname could look like! Click this message to request.";
|
||||
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_TRYOUT =
|
||||
"<white><prefix><white> <nick><gray>: <white><click:suggest_command:/nick request <nickrequest>>Hi, this is what my new nickname could look like! Click this message to request.";
|
||||
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_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>)";
|
||||
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);
|
||||
@@ -572,9 +615,13 @@ public final class Config {
|
||||
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_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_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);
|
||||
}
|
||||
|
||||
@@ -583,7 +630,8 @@ public final class Config {
|
||||
|
||||
private static void deathMessagesSettings() {
|
||||
DEATH_MESSAGES_MAX_PER_PERIOD = getInt("death-messages.max-per-period", DEATH_MESSAGES_MAX_PER_PERIOD);
|
||||
DEATH_MESSAGES_LIMIT_PERIOD_MINUTES = getInt("death-messages.limit-period-minutes", DEATH_MESSAGES_LIMIT_PERIOD_MINUTES);
|
||||
DEATH_MESSAGES_LIMIT_PERIOD_MINUTES =
|
||||
getInt("death-messages.limit-period-minutes", DEATH_MESSAGES_LIMIT_PERIOD_MINUTES);
|
||||
}
|
||||
|
||||
public static long CHAT_LOG_DELETE_OLDER_THAN_DAYS = 31;
|
||||
@@ -593,4 +641,14 @@ public final class Config {
|
||||
CHAT_LOG_DELETE_OLDER_THAN_DAYS = getLong("chat-log.delete-older-than-days", CHAT_LOG_DELETE_OLDER_THAN_DAYS);
|
||||
CHAT_LOG_SAVE_DELAY_MINUTES = getLong("chat-log.save-delay-minutes", CHAT_LOG_SAVE_DELAY_MINUTES);
|
||||
}
|
||||
|
||||
public static String MATRIX_SERVER = "http://127.0.0.1:8008";
|
||||
public static String MATRIX_AS_TOKEN = "<token>";
|
||||
public static String MATRIX_HS_TOKEN = "<token>";
|
||||
|
||||
private static void matrixSettings() {
|
||||
MATRIX_SERVER = getString("matrix.server", MATRIX_SERVER);
|
||||
MATRIX_AS_TOKEN = getString("matrix.as_token", MATRIX_AS_TOKEN);
|
||||
MATRIX_HS_TOKEN = getString("matrix.hs_token", MATRIX_HS_TOKEN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
package com.alttd.chat.objects.channels;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
public class CustomChannel extends Channel {
|
||||
private final List<String> servers;
|
||||
private final List<String> aliases;
|
||||
|
||||
public CustomChannel(String channelName, String format, List<String> servers, boolean proxy, boolean local) {
|
||||
public CustomChannel(String channelName, String format, List<String> servers, List<String> aliases, boolean proxy,
|
||||
boolean local) {
|
||||
super(channelName, format, proxy, local);
|
||||
this.permission = "chat.channel." + channelName.toLowerCase();
|
||||
this.channelName = channelName;
|
||||
this.format = format;
|
||||
this.servers = servers;
|
||||
this.proxy = proxy;
|
||||
this.aliases = aliases;
|
||||
}
|
||||
|
||||
public List<String> getServers() {
|
||||
return servers;
|
||||
}
|
||||
|
||||
public List<String> getAliases() {
|
||||
return aliases;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
implementation(project(":api")) // API
|
||||
compileOnly("com.alttd.cosmos:cosmos-api:1.21.6-R0.1-SNAPSHOT") {
|
||||
compileOnly("com.alttd.cosmos:cosmos-api:1.21.10-R0.1-SNAPSHOT") {
|
||||
isChanging = true
|
||||
}
|
||||
compileOnly("com.gitlab.ruany:LiteBansAPI:0.6.1") // move to proxy
|
||||
|
||||
@@ -12,7 +12,6 @@ import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ChatChannel extends BukkitCommand {
|
||||
@@ -28,7 +27,7 @@ public class ChatChannel extends BukkitCommand {
|
||||
this.command = channel.getChannelName().toLowerCase();
|
||||
this.description = "Chat channel named " + channel.getChannelName() + ".";
|
||||
this.usageMessage = "/" + command + " <message>";
|
||||
this.setAliases(Collections.emptyList());
|
||||
this.setAliases(channel.getAliases());
|
||||
activeCommands.add(this);
|
||||
this.toggleableForCustomChannel = new ToggleableForCustomChannel(channel);
|
||||
}
|
||||
@@ -43,7 +42,7 @@ public class ChatChannel extends BukkitCommand {
|
||||
player.sendRichMessage(Config.CUSTOM_CHANNEL_TOGGLED, TagResolver.resolver(
|
||||
Placeholder.unparsed("channel", channel.getChannelName()),
|
||||
Placeholder.component("status", toggleableForCustomChannel.toggle(player.getUniqueId())
|
||||
? Config.TOGGLED_ON : Config.TOGGLED_OFF)));
|
||||
? Config.TOGGLED_ON : Config.TOGGLED_OFF)));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public class PluginMessage implements PluginMessageListener {
|
||||
ByteArrayDataInput in = ByteStreams.newDataInput(bytes);
|
||||
String subChannel = in.readUTF();
|
||||
switch (subChannel) {
|
||||
case "privatemessagein": {
|
||||
case "privatemessagein" -> {
|
||||
UUID uuid = UUID.fromString(in.readUTF());
|
||||
String target = in.readUTF();
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
@@ -49,14 +49,15 @@ public class PluginMessage implements PluginMessageListener {
|
||||
ChatUser chatUser = ChatUserManager.getChatUser(uuid);
|
||||
if (isTargetNotIgnored(chatUser, targetuuid)) {
|
||||
player.sendMessage(GsonComponentSerializer.gson().deserialize(message));
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 1, 1); // todo load this from config
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 1,
|
||||
1); // todo load this from config
|
||||
ChatUser user = ChatUserManager.getChatUser(uuid);
|
||||
if (!user.getReplyContinueTarget().equalsIgnoreCase(target)) {
|
||||
user.setReplyTarget(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
case "privatemessageout": {
|
||||
case "privatemessageout" -> {
|
||||
UUID uuid = UUID.fromString(in.readUTF());
|
||||
String target = in.readUTF();
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
@@ -72,9 +73,8 @@ public class PluginMessage implements PluginMessageListener {
|
||||
// ChatUser user = ChatUserManager.getChatUser(uuid);
|
||||
// user.setReplyTarget(target);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "globalchat": {
|
||||
case "globalchat" -> {
|
||||
if (!ChatPlugin.getInstance().serverGlobalChatEnabled() || ChatPlugin.getInstance().serverMuted()) {
|
||||
break;
|
||||
}
|
||||
@@ -88,31 +88,27 @@ public class PluginMessage implements PluginMessageListener {
|
||||
p.sendMessage(GsonComponentSerializer.gson().deserialize(message));
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "ignore": {
|
||||
case "ignore" -> {
|
||||
ChatUser chatUser = ChatUserManager.getChatUser(UUID.fromString(in.readUTF()));
|
||||
UUID targetUUID = UUID.fromString(in.readUTF());
|
||||
|
||||
if (!chatUser.getIgnoredPlayers().contains(targetUUID)) {
|
||||
chatUser.addIgnoredPlayers(targetUUID);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "unignore": {
|
||||
case "unignore" -> {
|
||||
ChatUser chatUser = ChatUserManager.getChatUser(UUID.fromString(in.readUTF()));
|
||||
chatUser.removeIgnoredPlayers(UUID.fromString(in.readUTF()));
|
||||
break;
|
||||
}
|
||||
case "chatchannel": {
|
||||
case "chatchannel" -> {
|
||||
if (ChatPlugin.getInstance().serverMuted()) {
|
||||
break;
|
||||
}
|
||||
|
||||
chatChannel(in);
|
||||
break;
|
||||
}
|
||||
case "tmppartyupdate": {
|
||||
case "tmppartyupdate" -> {
|
||||
int id = Integer.parseInt(in.readUTF());
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
@@ -120,9 +116,8 @@ public class PluginMessage implements PluginMessageListener {
|
||||
Queries.loadPartyUsers(id);
|
||||
}
|
||||
}.runTaskAsynchronously(ChatPlugin.getInstance());
|
||||
break;
|
||||
}
|
||||
case "partylogin": {
|
||||
case "partylogin" -> {
|
||||
int id = Integer.parseInt(in.readUTF());
|
||||
Party party = PartyManager.getParty(id);
|
||||
if (party == null) {
|
||||
@@ -135,18 +130,19 @@ public class PluginMessage implements PluginMessageListener {
|
||||
public void run() {
|
||||
PartyUser user = party.getPartyUser(uuid);
|
||||
if (user != null) {
|
||||
ComponentLike component = Utility.parseMiniMessage("<dark_aqua>* " + user.getPlayerName() + " logged in to Altitude.");
|
||||
ComponentLike component = Utility.parseMiniMessage(
|
||||
"<dark_aqua>* " + user.getPlayerName() + " logged in to Altitude.");
|
||||
|
||||
Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> party.getPartyUsersUuid().contains(p.getUniqueId()))
|
||||
.filter(p -> !ChatUserManager.getChatUser(p.getUniqueId()).getIgnoredPlayers().contains(uuid))
|
||||
.filter(p -> !ChatUserManager.getChatUser(p.getUniqueId()).getIgnoredPlayers()
|
||||
.contains(uuid))
|
||||
.forEach(p -> p.sendMessage(component));
|
||||
}
|
||||
}
|
||||
}.runTaskAsynchronously(ChatPlugin.getInstance());
|
||||
break;
|
||||
}
|
||||
case "partylogout": {
|
||||
case "partylogout" -> {
|
||||
int id = Integer.parseInt(in.readUTF());
|
||||
Party party = PartyManager.getParty(id);
|
||||
if (party == null) {
|
||||
@@ -159,21 +155,20 @@ public class PluginMessage implements PluginMessageListener {
|
||||
public void run() {
|
||||
PartyUser user = party.getPartyUser(uuid);
|
||||
if (user != null) {
|
||||
ComponentLike component = Utility.parseMiniMessage("<dark_aqua>* " + user.getPlayerName() + " logged out of Altitude.");
|
||||
ComponentLike component = Utility.parseMiniMessage(
|
||||
"<dark_aqua>* " + user.getPlayerName() + " logged out of Altitude.");
|
||||
|
||||
Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> party.getPartyUsersUuid().contains(p.getUniqueId()))
|
||||
.filter(p -> !ChatUserManager.getChatUser(p.getUniqueId()).getIgnoredPlayers().contains(uuid))
|
||||
.filter(p -> !ChatUserManager.getChatUser(p.getUniqueId()).getIgnoredPlayers()
|
||||
.contains(uuid))
|
||||
.forEach(p -> p.sendMessage(component));
|
||||
}
|
||||
}
|
||||
}.runTaskAsynchronously(ChatPlugin.getInstance());
|
||||
break;
|
||||
}
|
||||
case "reloadconfig":
|
||||
ChatPlugin.getInstance().reloadConfig();
|
||||
break;
|
||||
case "chatpunishments":
|
||||
case "reloadconfig" -> ChatPlugin.getInstance().reloadConfig();
|
||||
case "chatpunishments" -> {
|
||||
UUID uuid = UUID.fromString(in.readUTF());
|
||||
boolean mute = in.readBoolean();
|
||||
ChatUser user = ChatUserManager.getChatUser(uuid);
|
||||
@@ -181,9 +176,9 @@ public class PluginMessage implements PluginMessageListener {
|
||||
return;
|
||||
}
|
||||
user.setMuted(mute);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +215,8 @@ public class PluginMessage implements PluginMessageListener {
|
||||
public void run() {
|
||||
Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> p.hasPermission(finalChatChannel.getPermission()))
|
||||
.filter(p -> !ChatUserManager.getChatUser(p.getUniqueId()).getIgnoredPlayers().contains(finalUuid))
|
||||
.filter(p -> !ChatUserManager.getChatUser(p.getUniqueId()).getIgnoredPlayers()
|
||||
.contains(finalUuid))
|
||||
.forEach(p -> p.sendMessage(finalComponent));
|
||||
}
|
||||
}.runTaskAsynchronously(ChatPlugin.getInstance());
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
plugins {
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":api"))
|
||||
compileOnly("com.velocitypowered:velocity-api:3.2.0-SNAPSHOT")
|
||||
|
||||
api("com.fasterxml.jackson.core:jackson-databind:2.17.2")
|
||||
api("com.fasterxml.jackson.core:jackson-core:2.17.2")
|
||||
api("com.fasterxml.jackson.core:jackson-annotations:2.17.2")
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.encoding = "UTF-8"
|
||||
options.release.set(21)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.alttd.matrix;
|
||||
|
||||
public record MatrixConfig(
|
||||
String homeserver, // e.g. "http://127.0.0.1:8008"
|
||||
String asToken, // from as registration yaml
|
||||
String hsToken, // from as registration yaml
|
||||
String domain, // "matrix.alttd.com"
|
||||
String userPrefix, // "mc_"
|
||||
String bindHost, // "127.0.0.1"
|
||||
int bindPort // 9000
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.alttd.matrix;
|
||||
|
||||
import com.alttd.matrix.app_service.MatrixAppServiceHttpServer;
|
||||
import com.alttd.matrix.client.HttpMatrixClient;
|
||||
import com.alttd.matrix.interfaces.MatrixAppServiceServer;
|
||||
import com.alttd.matrix.interfaces.MatrixClient;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
public final class MatrixRuntime {
|
||||
|
||||
private MatrixRuntime() {
|
||||
}
|
||||
|
||||
public static MatrixAppServiceServer startAppService(MatrixConfig cfg) throws IOException {
|
||||
var server = new MatrixAppServiceHttpServer(
|
||||
new InetSocketAddress(cfg.bindHost(), cfg.bindPort()),
|
||||
cfg.hsToken()
|
||||
);
|
||||
server.start();
|
||||
return server;
|
||||
}
|
||||
|
||||
public static MatrixClient createClient(MatrixConfig cfg) {
|
||||
return new HttpMatrixClient(cfg.homeserver(), cfg.asToken());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
package com.alttd.matrix.app_service;
|
||||
|
||||
import com.alttd.matrix.interfaces.MatrixAppServiceServer;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class MatrixAppServiceHttpServer implements MatrixAppServiceServer {
|
||||
|
||||
private final HttpServer server;
|
||||
private final String hsToken;
|
||||
private final ObjectMapper om = new ObjectMapper();
|
||||
|
||||
private volatile Consumer<TransactionEvent> txListener;
|
||||
|
||||
public MatrixAppServiceHttpServer(InetSocketAddress bind, String hsToken) throws IOException {
|
||||
this.server = HttpServer.create(bind, 0);
|
||||
this.hsToken = hsToken;
|
||||
|
||||
server.createContext("/_matrix/app/v1/transactions", this::handleTransactions);
|
||||
server.createContext("/_matrix/app/v1/users", this::handleUsers);
|
||||
|
||||
server.setExecutor(Executors.newCachedThreadPool(r -> {
|
||||
Thread t = new Thread(r, "matrix-as-http");
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
}));
|
||||
}
|
||||
|
||||
public void start() {
|
||||
server.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransactionListener(Consumer<TransactionEvent> listener) {
|
||||
this.txListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
server.stop(0);
|
||||
}
|
||||
|
||||
private void handleUsers(HttpExchange ex) throws IOException {
|
||||
if (!"GET".equals(ex.getRequestMethod())) {
|
||||
send(ex, 405, "{}");
|
||||
return;
|
||||
}
|
||||
if (!validHsToken(ex)) {
|
||||
send(ex, 401, "{}");
|
||||
return;
|
||||
}
|
||||
|
||||
// Synapse asks "does this user exist?" -> for AS, answer 200 so Synapse will proceed.
|
||||
// You can optionally restrict to your namespace by inspecting the path.
|
||||
send(ex, 200, "{}");
|
||||
}
|
||||
|
||||
private void handleTransactions(HttpExchange ex) throws IOException {
|
||||
if (!"PUT".equals(ex.getRequestMethod())) {
|
||||
send(ex, 405, "{}");
|
||||
return;
|
||||
}
|
||||
if (!validHsToken(ex)) {
|
||||
send(ex, 401, "{}");
|
||||
return;
|
||||
}
|
||||
|
||||
JsonNode root;
|
||||
try (InputStream in = ex.getRequestBody()) {
|
||||
root = om.readTree(in);
|
||||
} catch (Exception e) {
|
||||
send(ex, 400, "{}");
|
||||
return;
|
||||
}
|
||||
|
||||
Consumer<TransactionEvent> listener = txListener;
|
||||
if (listener != null) {
|
||||
JsonNode events = root.path("events");
|
||||
if (events.isArray()) {
|
||||
for (Iterator<JsonNode> it = events.elements(); it.hasNext(); ) {
|
||||
JsonNode ev = it.next();
|
||||
|
||||
// only handle m.room.message text
|
||||
if (!"m.room.message".equals(ev.path("type").asText())) {
|
||||
continue;
|
||||
}
|
||||
if (!"m.text".equals(ev.path("content").path("msgtype").asText())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String roomId = ev.path("room_id").asText(null);
|
||||
String sender = ev.path("sender").asText(null);
|
||||
String eventId = ev.path("event_id").asText(null);
|
||||
String body = ev.path("content").path("body").asText(null);
|
||||
|
||||
if (roomId != null && body != null) {
|
||||
listener.accept(new TransactionEvent(roomId, sender, body, eventId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
send(ex, 200, "{}");
|
||||
}
|
||||
|
||||
private boolean validHsToken(HttpExchange ex) {
|
||||
String q = ex.getRequestURI().getRawQuery();
|
||||
if (q == null) {
|
||||
return false;
|
||||
}
|
||||
Map<String, String> params = parseQuery(q);
|
||||
String token = params.get("access_token");
|
||||
return token != null && token.equals(hsToken);
|
||||
}
|
||||
|
||||
private static Map<String, String> parseQuery(String raw) {
|
||||
var map = new java.util.HashMap<String, String>();
|
||||
for (String part : raw.split("&")) {
|
||||
int i = part.indexOf('=');
|
||||
if (i <= 0) {
|
||||
continue;
|
||||
}
|
||||
String k = urlDecode(part.substring(0, i));
|
||||
String v = urlDecode(part.substring(i + 1));
|
||||
map.put(k, v);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static String urlDecode(String s) {
|
||||
return URLDecoder.decode(s, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static void send(HttpExchange ex, int code, String body) throws IOException {
|
||||
byte[] b = body.getBytes(StandardCharsets.UTF_8);
|
||||
ex.getResponseHeaders().set("Content-Type", "application/json");
|
||||
ex.sendResponseHeaders(code, b.length);
|
||||
ex.getResponseBody().write(b);
|
||||
ex.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.alttd.matrix.bridge;
|
||||
|
||||
import com.alttd.matrix.MatrixConfig;
|
||||
import com.alttd.matrix.interfaces.MatrixAppServiceServer;
|
||||
import com.alttd.matrix.interfaces.MatrixBridge;
|
||||
import com.alttd.matrix.interfaces.MatrixClient;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public final class DefaultMatrixBridge implements MatrixBridge {
|
||||
|
||||
private final MatrixClient client;
|
||||
private final MatrixConfig cfg;
|
||||
private final Executor io = Executors.newSingleThreadExecutor(r -> {
|
||||
Thread t = new Thread(r, "matrix-io");
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
});
|
||||
|
||||
private volatile InboundHandler inbound;
|
||||
private volatile RoomResolver rooms;
|
||||
|
||||
public DefaultMatrixBridge(MatrixConfig cfg, MatrixAppServiceServer asServer, MatrixClient client) {
|
||||
this.cfg = cfg;
|
||||
this.client = client;
|
||||
|
||||
asServer.setTransactionListener(evt -> {
|
||||
InboundHandler h = inbound;
|
||||
RoomResolver rr = rooms;
|
||||
if (h == null || rr == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// drop our own puppets to prevent loops
|
||||
if (evt.senderMxid() != null && evt.senderMxid().startsWith("@" + cfg.userPrefix())) {
|
||||
return;
|
||||
}
|
||||
|
||||
h.onMatrixChat(evt.roomId(), evt.senderMxid(), evt.body());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInboundHandler(InboundHandler handler) {
|
||||
this.inbound = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRoomResolver(RoomResolver resolver) {
|
||||
this.rooms = resolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChat(UUID playerUuid, String mcUsername, String serverName, String message) {
|
||||
RoomResolver rr = rooms;
|
||||
if (rr == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String roomId = rr.roomIdForServer(serverName);
|
||||
if (roomId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String mxid = "@" + cfg.userPrefix() + playerUuid + ":" + cfg.domain();
|
||||
|
||||
io.execute(() -> {
|
||||
client.ensureUser(mxid);
|
||||
client.setDisplayName(mxid, mcUsername);
|
||||
client.ensureJoined(mxid, roomId);
|
||||
client.sendText(mxid, roomId, message);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package com.alttd.matrix.client;
|
||||
|
||||
import com.alttd.matrix.interfaces.MatrixClient;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URLEncoder;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class HttpMatrixClient implements MatrixClient {
|
||||
|
||||
private final HttpClient http = HttpClient.newBuilder()
|
||||
.connectTimeout(Duration.ofSeconds(5))
|
||||
.build();
|
||||
|
||||
private final ObjectMapper om = new ObjectMapper();
|
||||
|
||||
private final String hs; // e.g. http://127.0.0.1:8008
|
||||
private final String asToken; // AS access token
|
||||
|
||||
public HttpMatrixClient(String homeserver, String asToken) {
|
||||
this.hs = homeserver.endsWith("/") ? homeserver.substring(0, homeserver.length() - 1) : homeserver;
|
||||
this.asToken = asToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ensureUser(String mxid) {
|
||||
String localpart = localpart(mxid);
|
||||
|
||||
String url = hs + "/_matrix/client/v3/register"
|
||||
+ "?access_token=" + enc(asToken);
|
||||
|
||||
String body = "{\"type\":\"m.login.application_service\",\"username\":\"" + json(localpart) + "\"}";
|
||||
|
||||
HttpRequest req = HttpRequest.newBuilder(URI.create(url))
|
||||
.timeout(Duration.ofSeconds(10))
|
||||
.header("Content-Type", "application/json")
|
||||
.POST(HttpRequest.BodyPublishers.ofString(body))
|
||||
.build();
|
||||
|
||||
sendIgnoreConflict(req);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplayName(String mxid, String displayName) {
|
||||
String url = hs + "/_matrix/client/v3/profile/" + encPath(mxid) + "/displayname"
|
||||
+ "?access_token=" + enc(asToken)
|
||||
+ "&user_id=" + enc(mxid);
|
||||
|
||||
String body = "{\"displayname\":\"" + json(displayName) + "\"}";
|
||||
|
||||
HttpRequest req = HttpRequest.newBuilder(URI.create(url))
|
||||
.timeout(Duration.ofSeconds(10))
|
||||
.header("Content-Type", "application/json")
|
||||
.PUT(HttpRequest.BodyPublishers.ofString(body))
|
||||
.build();
|
||||
|
||||
sendOkOrIgnore(req);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ensureJoined(String mxid, String roomId) {
|
||||
String url = hs + "/_matrix/client/v3/rooms/" + encPath(roomId) + "/join"
|
||||
+ "?access_token=" + enc(asToken)
|
||||
+ "&user_id=" + enc(mxid);
|
||||
|
||||
HttpRequest req = HttpRequest.newBuilder(URI.create(url))
|
||||
.timeout(Duration.ofSeconds(10))
|
||||
.header("Content-Type", "application/json")
|
||||
.POST(HttpRequest.BodyPublishers.ofString("{}"))
|
||||
.build();
|
||||
|
||||
sendOkOrIgnore(req);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendText(String mxid, String roomId, String bodyText) {
|
||||
String txnId = UUID.randomUUID().toString();
|
||||
|
||||
String url = hs + "/_matrix/client/v3/rooms/" + encPath(roomId) + "/send/m.room.message/" + encPath(txnId)
|
||||
+ "?access_token=" + enc(asToken)
|
||||
+ "&user_id=" + enc(mxid);
|
||||
|
||||
String body = "{\"msgtype\":\"m.text\",\"body\":\"" + json(bodyText) + "\"}";
|
||||
|
||||
HttpRequest req = HttpRequest.newBuilder(URI.create(url))
|
||||
.timeout(Duration.ofSeconds(10))
|
||||
.header("Content-Type", "application/json")
|
||||
.PUT(HttpRequest.BodyPublishers.ofString(body))
|
||||
.build();
|
||||
|
||||
sendOkOrIgnore(req);
|
||||
}
|
||||
|
||||
private void sendIgnoreConflict(HttpRequest req) {
|
||||
try {
|
||||
HttpResponse<String> res = http.send(req, HttpResponse.BodyHandlers.ofString());
|
||||
int c = res.statusCode();
|
||||
if (c == 200) {
|
||||
return;
|
||||
}
|
||||
if (c == 400 && res.body() != null && res.body().contains("M_USER_IN_USE")) {
|
||||
return;
|
||||
}
|
||||
if (c == 401 || c == 403) {
|
||||
throw new RuntimeException("Matrix auth failed: " + c + " " + res.body());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendOkOrIgnore(HttpRequest req) {
|
||||
try {
|
||||
HttpResponse<String> res = http.send(req, HttpResponse.BodyHandlers.ofString());
|
||||
int c = res.statusCode();
|
||||
if (c >= 200 && c < 300) {
|
||||
return;
|
||||
}
|
||||
if (c == 401 || c == 403) {
|
||||
throw new RuntimeException("Matrix auth failed: " + c + " " + res.body());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String localpart(String mxid) {
|
||||
// "@localpart:domain"
|
||||
int at = mxid.indexOf('@');
|
||||
int colon = mxid.indexOf(':');
|
||||
if (at != 0 || colon < 0) {
|
||||
throw new IllegalArgumentException("bad mxid: " + mxid);
|
||||
}
|
||||
return mxid.substring(1, colon);
|
||||
}
|
||||
|
||||
private static String enc(String s) {
|
||||
return URLEncoder.encode(s, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static String encPath(String s) {
|
||||
// safe enough for matrix path segments
|
||||
return URLEncoder.encode(s, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static String json(String s) {
|
||||
return s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.alttd.matrix.interfaces;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface MatrixAppServiceServer extends Closeable {
|
||||
void setTransactionListener(Consumer<TransactionEvent> listener);
|
||||
|
||||
record TransactionEvent(String roomId, String senderMxid, String body, String eventId) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.alttd.matrix.interfaces;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface MatrixBridge {
|
||||
void setInboundHandler(InboundHandler handler);
|
||||
|
||||
void setRoomResolver(RoomResolver resolver);
|
||||
|
||||
void sendChat(UUID playerUuid, String mcUsername, String serverName, String message);
|
||||
|
||||
interface InboundHandler {
|
||||
void onMatrixChat(String roomId, String senderMxid, String body);
|
||||
}
|
||||
|
||||
interface RoomResolver {
|
||||
String roomIdForServer(String serverName);
|
||||
|
||||
String serverForRoomId(String roomId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.alttd.matrix.interfaces;
|
||||
|
||||
public interface MatrixClient {
|
||||
void ensureUser(String mxid);
|
||||
|
||||
void setDisplayName(String mxid, String displayName);
|
||||
|
||||
void ensureJoined(String mxid, String roomId);
|
||||
|
||||
void sendText(String mxid, String roomId, String body);
|
||||
}
|
||||
+10
-10
@@ -3,22 +3,13 @@ rootProject.name = "Chat"
|
||||
include(":api")
|
||||
include(":galaxy")
|
||||
include(":velocity")
|
||||
include(":matrix")
|
||||
|
||||
val nexusUser = providers.gradleProperty("alttdSnapshotUsername").get()
|
||||
val nexusPass = providers.gradleProperty("alttdSnapshotPassword").get()
|
||||
|
||||
dependencyResolutionManagement {
|
||||
repositories {
|
||||
// mavenLocal()
|
||||
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://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")
|
||||
maven {
|
||||
name = "nexus"
|
||||
url = uri("https://repo.alttd.com/repository/alttd-snapshot/")
|
||||
@@ -27,6 +18,13 @@ dependencyResolutionManagement {
|
||||
password = nexusPass
|
||||
}
|
||||
}
|
||||
// mavenLocal()
|
||||
mavenCentral()
|
||||
maven("https://oss.sonatype.org/content/groups/public/") // Adventure
|
||||
maven("https://oss.sonatype.org/content/repositories/snapshots/") // Minimessage
|
||||
maven("https://repo.spongepowered.org/maven") // Configurate
|
||||
maven("https://repo.extendedclip.com/content/repositories/placeholderapi/") // Papi
|
||||
maven("https://jitpack.io")
|
||||
}
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
}
|
||||
@@ -36,3 +34,5 @@ pluginManagement {
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
include("matrix")
|
||||
|
||||
@@ -2,23 +2,33 @@ package com.alttd.velocitychat;
|
||||
|
||||
import com.alttd.chat.ChatAPI;
|
||||
import com.alttd.chat.ChatImplementation;
|
||||
import com.alttd.chat.config.Config;
|
||||
import com.alttd.chat.database.DatabaseConnection;
|
||||
import com.alttd.chat.managers.ChatUserManager;
|
||||
import com.alttd.chat.managers.PartyManager;
|
||||
import com.alttd.chat.objects.ChatUser;
|
||||
import com.alttd.chat.objects.chat_log.ChatLogHandler;
|
||||
import com.alttd.chat.util.ALogger;
|
||||
import com.alttd.matrix.MatrixConfig;
|
||||
import com.alttd.matrix.MatrixRuntime;
|
||||
import com.alttd.matrix.bridge.DefaultMatrixBridge;
|
||||
import com.alttd.matrix.interfaces.MatrixAppServiceServer;
|
||||
import com.alttd.matrix.interfaces.MatrixBridge;
|
||||
import com.alttd.matrix.interfaces.MatrixClient;
|
||||
import com.alttd.velocitychat.commands.*;
|
||||
import com.alttd.chat.config.Config;
|
||||
import com.alttd.chat.database.DatabaseConnection;
|
||||
import com.alttd.velocitychat.handlers.ChatHandler;
|
||||
import com.alttd.velocitychat.handlers.ServerHandler;
|
||||
import com.alttd.velocitychat.listeners.ChatListener;
|
||||
import com.alttd.velocitychat.listeners.LiteBansListener;
|
||||
import com.alttd.velocitychat.listeners.ProxyPlayerListener;
|
||||
import com.alttd.velocitychat.listeners.PluginMessageListener;
|
||||
import com.alttd.chat.util.ALogger;
|
||||
import com.alttd.velocitychat.listeners.ProxyPlayerListener;
|
||||
import com.alttd.velocitychat.matrix.MatrixRoomMap;
|
||||
import com.alttd.velocitychat.matrix.VelocityMatrixInbound;
|
||||
import com.alttd.velocitychat.matrix.VelocityMatrixOutbound;
|
||||
import com.google.common.io.ByteArrayDataOutput;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.inject.Inject;
|
||||
import com.velocitypowered.api.event.EventManager;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||
import com.velocitypowered.api.plugin.Dependency;
|
||||
@@ -36,14 +46,16 @@ import java.nio.file.Path;
|
||||
description = "A chat plugin for Altitude Minecraft Server",
|
||||
authors = {"destro174", "teri"},
|
||||
dependencies = {@Dependency(id = "luckperms"), @Dependency(id = "litebans"), @Dependency(id = "proxydiscordlink")}
|
||||
)
|
||||
)
|
||||
public class VelocityChat {
|
||||
|
||||
private static VelocityChat plugin;
|
||||
private final ProxyServer server;
|
||||
private final Logger logger;
|
||||
private final Path dataDirectory;
|
||||
private final EventManager eventManager;
|
||||
|
||||
private MatrixAppServiceServer matrixAsServer;
|
||||
private ChatAPI chatAPI;
|
||||
private ChatHandler chatHandler;
|
||||
private ServerHandler serverHandler;
|
||||
@@ -51,11 +63,12 @@ public class VelocityChat {
|
||||
private ChannelIdentifier channelIdentifier;
|
||||
|
||||
@Inject
|
||||
public VelocityChat(ProxyServer proxyServer, Logger proxyLogger, @DataDirectory Path proxydataDirectory) {
|
||||
public VelocityChat(ProxyServer proxyServer, Logger proxyLogger, @DataDirectory Path proxydataDirectory, EventManager eventManager) {
|
||||
plugin = this;
|
||||
server = proxyServer;
|
||||
logger = proxyLogger;
|
||||
dataDirectory = proxydataDirectory;
|
||||
this.eventManager = eventManager;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -80,6 +93,7 @@ public class VelocityChat {
|
||||
ChatUser console = new ChatUser(Config.CONSOLEUUID, -1, null);
|
||||
console.setDisplayName(Config.CONSOLENAME);
|
||||
ChatUserManager.addUser(console);
|
||||
initMatrix();
|
||||
}
|
||||
|
||||
public void reloadConfig() {
|
||||
@@ -92,6 +106,42 @@ public class VelocityChat {
|
||||
getProxy().getAllServers().stream().forEach(registeredServer -> registeredServer.sendPluginMessage(getChannelIdentifier(), buf.toByteArray()));
|
||||
}
|
||||
|
||||
//TODO call initMatrix
|
||||
private void initMatrix() {
|
||||
MatrixConfig cfg = new MatrixConfig(
|
||||
Config.MATRIX_SERVER,
|
||||
Config.MATRIX_AS_TOKEN,
|
||||
Config.MATRIX_HS_TOKEN,
|
||||
"matrix.alttd.com",
|
||||
"mc_",
|
||||
"127.0.0.1",
|
||||
9000
|
||||
);
|
||||
|
||||
MatrixAppServiceServer asServer;
|
||||
try {
|
||||
asServer = MatrixRuntime.startAppService(cfg);
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to start Matrix AppService server", e);
|
||||
return;
|
||||
}
|
||||
|
||||
MatrixClient client = MatrixRuntime.createClient(cfg);
|
||||
|
||||
initMatrix(cfg, asServer, client);
|
||||
}
|
||||
|
||||
public void initMatrix(MatrixConfig matrixConfig, MatrixAppServiceServer asServer, MatrixClient client) {
|
||||
MatrixRoomMap roomMap = new MatrixRoomMap();
|
||||
roomMap.put("bayou", "!bayou:matrix.alttd.com");
|
||||
|
||||
MatrixBridge matrix = new DefaultMatrixBridge(matrixConfig, asServer, client);
|
||||
matrix.setRoomResolver(roomMap);
|
||||
matrix.setInboundHandler(new VelocityMatrixInbound(server, roomMap));
|
||||
|
||||
eventManager.register(this, new VelocityMatrixOutbound(matrix));
|
||||
}
|
||||
|
||||
public File getDataDirectory() {
|
||||
return dataDirectory.toFile();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.alttd.velocitychat.matrix;
|
||||
|
||||
import com.alttd.matrix.interfaces.MatrixBridge;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public final class MatrixRoomMap implements MatrixBridge.RoomResolver {
|
||||
private final Map<String, String> serverToRoom = new ConcurrentHashMap<>();
|
||||
private final Map<String, String> roomToServer = new ConcurrentHashMap<>();
|
||||
|
||||
public void put(String serverName, String roomId) {
|
||||
serverToRoom.put(serverName, roomId);
|
||||
roomToServer.put(roomId, serverName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String roomIdForServer(String serverName) {
|
||||
return serverToRoom.get(serverName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String serverForRoomId(String roomId) {
|
||||
return roomToServer.get(roomId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.alttd.velocitychat.matrix;
|
||||
|
||||
import com.alttd.matrix.interfaces.MatrixBridge;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public final class VelocityMatrixInbound implements MatrixBridge.InboundHandler {
|
||||
private final ProxyServer proxy;
|
||||
private final MatrixRoomMap rooms;
|
||||
|
||||
public VelocityMatrixInbound(ProxyServer proxy, MatrixRoomMap rooms) {
|
||||
this.proxy = proxy;
|
||||
this.rooms = rooms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMatrixChat(String roomId, String senderMxid, String body) {
|
||||
final String serverName = rooms.serverForRoomId(roomId);
|
||||
if (serverName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// route to backend server players connected to that server
|
||||
Optional<RegisteredServer> rs = proxy.getServer(serverName);
|
||||
if (rs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// minimal formatting; adjust to your chat format
|
||||
String sender = senderMxid != null ? senderMxid : "matrix";
|
||||
Component msg = Component.text("[M] " + sender + ": " + body);
|
||||
|
||||
rs.get().getPlayersConnected().forEach(p -> p.sendMessage(msg));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.alttd.velocitychat.matrix;
|
||||
|
||||
import com.alttd.matrix.interfaces.MatrixBridge;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.player.PlayerChatEvent;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
|
||||
public final class VelocityMatrixOutbound {
|
||||
private final MatrixBridge matrix;
|
||||
|
||||
public VelocityMatrixOutbound(MatrixBridge matrix) {
|
||||
this.matrix = matrix;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onChat(PlayerChatEvent e) {
|
||||
if (!e.getResult().isAllowed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player p = e.getPlayer();
|
||||
String serverName = p.getCurrentServer().map(s -> s.getServerInfo().getName()).orElse(null);
|
||||
if (serverName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String msg = PlainTextComponentSerializer.plainText().serialize(e.getMessage());
|
||||
if (msg == null || msg.isBlank()) {
|
||||
return;
|
||||
}
|
||||
|
||||
matrix.sendChat(p.getUniqueId(), p.getUsername(), serverName, msg);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user