Compare commits

..

6 Commits
matrix ... main

23 changed files with 391 additions and 1070 deletions

2
.gitignore vendored
View File

@ -40,5 +40,3 @@ 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

View File

@ -4,7 +4,7 @@ plugins {
dependencies {
// Cosmos
compileOnly("com.alttd.cosmos:cosmos-api:1.21.10-R0.1-SNAPSHOT") {
compileOnly("com.alttd.cosmos:cosmos-api:1.21.8-R0.1-SNAPSHOT") {
isChanging = true
}
compileOnly("org.spongepowered:configurate-yaml:4.2.0") // Configurate

View File

@ -641,14 +641,4 @@ 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);
}
}

View File

@ -3,14 +3,18 @@ plugins {
id("io.github.goooler.shadow")
}
val nexusUser = providers.gradleProperty("alttdSnapshotUsername").orNull ?: System.getenv("NEXUS_USERNAME")
val nexusPass = providers.gradleProperty("alttdSnapshotPassword").orNull ?: System.getenv("NEXUS_PASSWORD")
dependencies {
implementation(project(":api")) // API
compileOnly("com.alttd.cosmos:cosmos-api:1.21.10-R0.1-SNAPSHOT") {
compileOnly("com.alttd.cosmos:cosmos-api:1.21.8-R0.1-SNAPSHOT") {
isChanging = true
}
compileOnly("com.gitlab.ruany:LiteBansAPI:0.6.1") // move to proxy
compileOnly("org.apache.commons:commons-lang3:3.17.0") // needs an alternative, already removed from upstream api and will be removed in server
compileOnly("net.luckperms:api:5.5") // Luckperms
implementation("com.alttd.inventory_gui:InventoryGUI:1.1.5-SNAPSHOT")
}
tasks {

View File

@ -45,13 +45,83 @@ public class Nicknames implements CommandExecutor, TabCompleter {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, String[] args) {
if (sender instanceof Player player) {
if (!(sender instanceof Player player)) {
sender.sendMessage("Console commands are disabled.");
return true;
}
if (args.length == 0) {
sender.sendRichMessage(helpMessage(sender, HelpType.ALL));
return true;
}
switch (args[0].toLowerCase()) {
case "set":
case "set" -> setNickname(sender, args, player);
case "review" -> reviewNickname(sender, args, player);
case "request" -> requestNickname(sender, args, player);
case "try" -> tryNickname(sender, args, player);
case "current" -> showCurrentNickname(sender, player);
case "help" ->
sender.sendRichMessage(helpMessage(sender, HelpType.ALL) + "For more info on nicknames and how to use rgb colors go to: <aqua>https://alttd.com/nicknames<white>");
default -> sender.sendRichMessage(helpMessage(sender, HelpType.ALL));
}
return true;
}
private void showCurrentNickname(@NotNull CommandSender sender, Player player) {
if (!hasPermission(sender, "chat.command.nick.current")) {
return;
}
ChatUser chatUser = ChatUserManager.getChatUser(player.getUniqueId());
TagResolver placeholders = TagResolver.resolver(
Placeholder.component("nickname", chatUser.getDisplayName()),
Placeholder.parsed("currentnickname", chatUser.getNickNameString())
);
player.sendRichMessage(Config.NICK_CURRENT, placeholders);
}
private void tryNickname(@NotNull CommandSender sender, String[] args, Player player) {
if (args.length != 2 || !hasPermission(sender, "chat.command.nick.try")) {
sender.sendRichMessage(helpMessage(sender, HelpType.TRY));
return;
}
LuckPerms api = ChatAPI.get().getLuckPerms();
if (api == null) {
sender.sendRichMessage(Config.NICK_NO_LUCKPERMS);
return;
}
if (!NickUtilities.validNick(player, player, args[1])) {
return;
}
sender.sendRichMessage(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])),
Placeholder.unparsed("nickrequest", args[1]));
}
private void requestNickname(@NotNull CommandSender sender, String[] args, Player player) {
if (args.length != 2 || !hasPermission(sender, "chat.command.nick.request")) {
sender.sendRichMessage(helpMessage(sender, HelpType.REQUEST));
return;
}
new BukkitRunnable() {
@Override
public void run() {
handleNickRequest(player, args[1]);
}
}.runTaskAsynchronously(ChatPlugin.getInstance());
}
private void reviewNickname(@NotNull CommandSender sender, String[] args, Player player) {
if (args.length != 1 || !hasPermission(sender, "chat.command.nick.review")) {
sender.sendRichMessage(helpMessage(sender, HelpType.REVIEW));
return;
}
NicknamesGui nicknamesGui = new NicknamesGui(player);
ChatPlugin.getInstance().getServer().getPluginManager().registerEvents(nicknamesGui, ChatPlugin.getInstance());
nicknamesGui.openInventory(player);
}
private void setNickname(@NotNull CommandSender sender, String[] args, Player player) {
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")) {
@ -65,67 +135,6 @@ public class Nicknames implements CommandExecutor, TabCompleter {
} else if (args.length > 3) {
sender.sendRichMessage(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.sendRichMessage(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.sendRichMessage(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.sendRichMessage(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])),
Placeholder.unparsed("nickrequest", args[1]));
}
} else {
sender.sendRichMessage(Config.NICK_NO_LUCKPERMS);
}
} else {
sender.sendRichMessage(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.sendRichMessage(Config.NICK_CURRENT, placeholders);
}
break;
case "help":
sender.sendRichMessage(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.sendRichMessage(helpMessage(sender, HelpType.ALL));
}
} else {
sender.sendMessage("Console commands are disabled.");
}
return true;
}
@Override
@ -136,6 +145,33 @@ public class Nicknames implements CommandExecutor, TabCompleter {
}
if (args.length == 1) {
tabCompleteArgLengthOne(sender, args, completions);
} else if (args.length == 2) {
tabCompleteArgLengthTwo(sender, args, completions);
}
return completions;
}
private static void tabCompleteArgLengthTwo(CommandSender sender, String[] args, List<String> completions) {
if (!args[0].equalsIgnoreCase("set")) {
return;
}
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);
}
}
}
private static void tabCompleteArgLengthOne(CommandSender sender, String[] args, List<String> completions) {
List<String> choices = new ArrayList<>();
if (sender.hasPermission("chat.command.nick.set")) {
choices.add("set");
@ -159,24 +195,6 @@ public class Nicknames implements CommandExecutor, TabCompleter {
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) {
@ -261,31 +279,13 @@ public class Nicknames implements CommandExecutor, TabCompleter {
private void handleNick(Player sender, OfflinePlayer target, final String nickName) {
if (nickName.equalsIgnoreCase("off")) {
try {
if (target.isOnline()) {
resetNick(Objects.requireNonNull(target.getPlayer()));
}
Queries.removePlayerFromDataBase(target.getUniqueId());
NickCache.remove(target.getUniqueId());
nickCacheUpdate.add(target.getUniqueId());
} catch (SQLException e) {
ALogger.error("Failed to remove nickname from database", e);
}
if (!sender.equals(target)) {
sender.sendRichMessage(Config.NICK_RESET_OTHERS,
Placeholder.unparsed("player", Objects.requireNonNull(target.getName())));
}
if (target.isOnline() && target.getPlayer() != null) {
target.getPlayer().sendRichMessage(Config.NICK_RESET);
}
NickEvent nickEvent = new NickEvent(sender.getName(), target.getName(), null, NickEvent.NickEventType.RESET);
nickEvent.callEvent();
handleNickOff(sender, target);
} else if (NickUtilities.validNick(sender, target, nickName)) {
setValidNick(sender, target, nickName);
}
}
private void setValidNick(Player sender, OfflinePlayer target, String nickName) {
if (target.isOnline()) {
setNick(target.getPlayer(), nickName);
} else {
@ -322,6 +322,30 @@ public class Nicknames implements CommandExecutor, TabCompleter {
Placeholder.unparsed("nickname", getNick(target.getPlayer())));
}
}
private void handleNickOff(Player sender, OfflinePlayer target) {
try {
if (target.isOnline()) {
resetNick(Objects.requireNonNull(target.getPlayer()));
}
Queries.removePlayerFromDataBase(target.getUniqueId());
NickCache.remove(target.getUniqueId());
nickCacheUpdate.add(target.getUniqueId());
} catch (SQLException e) {
ALogger.error("Failed to remove nickname from database", e);
}
if (!sender.equals(target)) {
sender.sendRichMessage(Config.NICK_RESET_OTHERS,
Placeholder.unparsed("player", Objects.requireNonNull(target.getName())));
}
if (target.isOnline() && target.getPlayer() != null) {
target.getPlayer().sendRichMessage(Config.NICK_RESET);
}
NickEvent nickEvent = new NickEvent(sender.getName(), target.getName(), null, NickEvent.NickEventType.RESET);
nickEvent.callEvent();
}
private String helpMessage(final CommandSender sender, final HelpType... helpTypes) {

View File

@ -5,24 +5,22 @@ 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.ALogger;
import com.alttd.chat.util.Utility;
import com.alttd.inventory_gui.click.GuiItem;
import com.alttd.inventory_gui.gui.InventoryGui;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike;
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;
@ -31,39 +29,45 @@ 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;
public static final String UNKNOWN_PLAYER_NAME = "UNKNOWN PLAYER NAME";
private final int currentPage;
private final ChatPlugin plugin = ChatPlugin.getInstance();
private final InventoryGui nicknamesGui;
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").asComponent());
// Put the items into the inventory
public NicknamesGui(Player player) {
nicknamesGui = InventoryGui.builder()
.plugin(plugin)
.title(Component.text("Nicknames GUI"))
.rows(6)
.build();
currentPage = 1;
setItems(currentPage);
setItems(currentPage, player);
}
public void setItems(int currentPage) {
public void setItems(int currentPage, Player player) {
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;
MiniMessage miniMessage = MiniMessage.miniMessage();
for (Nick nick : Nicknames.getInstance().NickCache.values()) {
if (nick.hasRequest()) {
if (limit >= i / 27) {
inv.setItem(i % 27, createPlayerSkull(nick, Config.NICK_ITEM_LORE));
ItemStack playerSkull = createPlayerSkull(nick, Config.NICK_ITEM_LORE);
nicknamesGui.getRoot().setItem(i % 27, GuiItem.clickable(playerSkull, inventoryClickEvent ->
handleInventoryClick(nick, inventoryClickEvent, miniMessage, playerSkull)));
ALogger.info("Added nick " + i + " to gui: " + nick.getUuid());
i++;
} else {
ALogger.info("Reached end of nicknames gui page");
hasNextPage = true;
break;
}
@ -71,20 +75,137 @@ public class NicknamesGui implements Listener {
}
if (currentPage != 1) {
inv.setItem(28, createGuiItem(Material.PAPER, "§bPrevious page",
ItemStack itemStack = createGuiItem(Material.PAPER, "§bPrevious page",
"§aCurrent page: %page%".replace("%page%", String.valueOf(currentPage)),
"§aPrevious page: %previousPage%".replace("%previousPage%", String.valueOf(currentPage - 1))));
"§aPrevious page: %previousPage%".replace("%previousPage%", String.valueOf(currentPage - 1)));
GuiItem previousPage = GuiItem.clickable(itemStack, e -> setItems(currentPage - 1, player));
nicknamesGui.getRoot().setItem(28, previousPage);
}
if (hasNextPage) {
inv.setItem(36, createGuiItem(Material.PAPER, "§bNext page",
ItemStack itemStack = createGuiItem(Material.PAPER, "§bNext page",
"§aCurrent page: %page%".replace("%page%", String.valueOf(currentPage)),
"§aNext page: §b%nextPage%".replace("%nextPage%", String.valueOf(currentPage + 1))));
"§aNext page: §b%nextPage%".replace("%nextPage%", String.valueOf(currentPage + 1)));
GuiItem nextPage = GuiItem.clickable(itemStack, e -> setItems(currentPage + 1, player));
nicknamesGui.getRoot().setItem(36, nextPage);
}
nicknamesGui.render(player);
}
}.runTaskAsynchronously(ChatPlugin.getInstance());
}
private void handleInventoryClick(Nick nick, InventoryClickEvent inventoryClickEvent, MiniMessage miniMessage, ItemStack playerSkull) {
final Player playerWhoClicked = (Player) inventoryClickEvent.getWhoClicked();
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(nick.getUuid());
Component offlinePlayerName = miniMessage.deserialize(getOfflinePlayerName(offlinePlayer));
if (!nick.hasRequest()) {
playerWhoClicked.sendRichMessage(Config.NICK_ALREADY_HANDLED,
Placeholder.component("targetplayer", offlinePlayerName));
return;
}
if (inventoryClickEvent.isLeftClick()) {
handleLeftClickPlayerSkull(nick, inventoryClickEvent, offlinePlayer, playerWhoClicked, offlinePlayerName, playerSkull);
} else if (inventoryClickEvent.isRightClick()) {
handleRightClickPlayerSkull(nick, inventoryClickEvent, offlinePlayer, playerWhoClicked, offlinePlayerName, playerSkull);
}
//TODO what do we do no click?
}
private void handleRightClickPlayerSkull(Nick nick, InventoryClickEvent inventoryClickEvent, OfflinePlayer offlinePlayer, Player playerWhoClicked, Component offlinePlayerName, ItemStack playerSkull) {
Queries.denyNewNickname(nick.getUuid());
String newNick = nick.getNewNick();
new BukkitRunnable() {
@Override
public void run() {
NickEvent nickEvent = new NickEvent(inventoryClickEvent.getWhoClicked().getName(), getOfflinePlayerName(offlinePlayer), newNick, NickEvent.NickEventType.DENIED);
nickEvent.callEvent();
}
}.runTask(ChatPlugin.getInstance());
playerWhoClicked.sendRichMessage(Config.NICK_DENIED,
Placeholder.unparsed("targetplayer", getOfflinePlayerName(offlinePlayer)),
Placeholder.component("newnick", Utility.applyColor(nick.getNewNick())),
Placeholder.component("oldnick", Utility.applyColor(nick.getCurrentNick() == null ? getOfflinePlayerName(offlinePlayer) : nick.getCurrentNick())));
if (Nicknames.getInstance().NickCache.containsKey(nick.getUuid())
&& Nicknames.getInstance().NickCache.get(nick.getUuid()).getCurrentNick() != null) {
nick.setNewNick(null);
nick.setRequestedDate(0);
Nicknames.getInstance().NickCache.put(nick.getUuid(), nick);
} else {
Nicknames.getInstance().NickCache.remove(nick.getUuid());
}
if (offlinePlayer.isOnline() && offlinePlayer.getPlayer() != null) {
Nicknames.getInstance().setNick(offlinePlayer.getPlayer(), nick.getCurrentNick() == null ? getOfflinePlayerName(offlinePlayer) : nick.getCurrentNick());
offlinePlayer.getPlayer().sendRichMessage(Config.NICK_NOT_CHANGED);
}
NickUtilities.bungeeMessageHandled(nick.getUuid(), inventoryClickEvent.getWhoClicked().getServer().getPlayer(inventoryClickEvent.getWhoClicked().getName()), "Denied");
final ComponentLike messageDenied = MiniMessage.miniMessage().deserialize("<red><name>'s nickname was denied!",
Placeholder.unparsed("name", getOfflinePlayerName(offlinePlayer)));
ChatPlugin.getInstance().getServer().getOnlinePlayers().stream()
.filter(player -> player.hasPermission("chat.command.nick.review"))
.forEach(player -> player.sendMessage(messageDenied));
ItemStack completedNickRequestItem = createCompletedNickRequestItem(offlinePlayerName, playerSkull);
inventoryClickEvent.getInventory().setItem(inventoryClickEvent.getSlot(), completedNickRequestItem);
nicknamesGui.render(playerWhoClicked);
}
private void handleLeftClickPlayerSkull(Nick nick, InventoryClickEvent inventoryClickEvent, OfflinePlayer offlinePlayer, Player playerWhoClicked, Component offlinePlayerName, ItemStack playerSkull) {
Queries.acceptNewNickname(nick.getUuid(), nick.getNewNick());
String newNick = nick.getNewNick();
new BukkitRunnable() {
@Override
public void run() {
NickEvent nickEvent = new NickEvent(inventoryClickEvent.getWhoClicked().getName(), getOfflinePlayerName(offlinePlayer), newNick, NickEvent.NickEventType.ACCEPTED);
nickEvent.callEvent();
}
}.runTask(ChatPlugin.getInstance());
playerWhoClicked.sendRichMessage(Config.NICK_ACCEPTED,
Placeholder.component("targetplayer", offlinePlayerName),
Placeholder.component("newnick", Utility.applyColor(nick.getNewNick())),
Placeholder.component("oldnick", nick.getCurrentNick() == null ? offlinePlayerName : Utility.applyColor(nick.getCurrentNick())));
Player affectedPlayer = offlinePlayer.getPlayer();
if (offlinePlayer.isOnline() && affectedPlayer != null) {
Nicknames.getInstance().setNick(affectedPlayer, nick.getNewNick());
}
NickUtilities.bungeeMessageHandled(nick.getUuid(), inventoryClickEvent.getWhoClicked().getServer().getPlayer(inventoryClickEvent.getWhoClicked().getName()), "Accepted");
nick.setCurrentNick(nick.getNewNick());
nick.setLastChangedDate(new Date().getTime());
nick.setNewNick(null);
nick.setRequestedDate(0);
Nicknames.getInstance().NickCache.put(nick.getUuid(), nick);
ItemStack completedNickRequestItem = createCompletedNickRequestItem(offlinePlayerName, playerSkull);
inventoryClickEvent.getInventory().setItem(inventoryClickEvent.getSlot(), completedNickRequestItem);
nicknamesGui.render(playerWhoClicked);
}
private static ItemStack createCompletedNickRequestItem(Component offlinePlayerName, ItemStack playerSkull) {
ItemStack itemStack = new ItemStack(Material.SKELETON_SKULL);
ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.displayName(offlinePlayerName);
itemMeta.lore(playerSkull.lore());
itemStack.setItemMeta(itemMeta);
return itemStack;
}
private static String getOfflinePlayerName(OfflinePlayer offlinePlayer) {
return offlinePlayer.getName() == null ? UNKNOWN_PLAYER_NAME : offlinePlayer.getName();
}
private ItemStack createPlayerSkull(Nick nick, List<String> lore) {
MiniMessage miniMessage = MiniMessage.miniMessage();
ItemStack playerHead = new ItemStack(Material.PLAYER_HEAD);
@ -94,9 +215,9 @@ public class NicknamesGui implements Listener {
meta.setOwningPlayer(offlinePlayer);
String name = offlinePlayer.getName();
if (name == null) {
meta.displayName(miniMessage.deserialize("UNKNOWN PLAYER NAME"));
meta.displayName(miniMessage.deserialize("<red>" + getOfflinePlayerName(offlinePlayer) + "</red>"));
} else {
meta.displayName(miniMessage.deserialize(offlinePlayer.getName()));
meta.displayName(miniMessage.deserialize(getOfflinePlayerName(offlinePlayer)));
}
TagResolver resolver = TagResolver.resolver(
@ -128,185 +249,6 @@ public class NicknamesGui implements Listener {
// 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)) {
Component component = clickedItem.getItemMeta().displayName();
if (component == null) {
throw new IllegalStateException("Nicknames GUI: Item with no display name clicked!");
}
String serialize = PlainTextComponentSerializer.plainText().serialize(component);
if (serialize.equals("Next Page")) {
setItems(currentPage + 1);
}
} else if (clickedItem.getType().equals(Material.PLAYER_HEAD)) {
ItemMeta itemMeta = clickedItem.getItemMeta();
if (itemMeta == null) {
return;
}
SkullMeta meta = (SkullMeta) itemMeta;
if (meta.hasEnchants()) {
return;
}
OfflinePlayer owningPlayer = meta.getOwningPlayer();
if (owningPlayer == null) {
p.sendRichMessage(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);
}
Component itemDisplayName = itemMeta.displayName();
if (itemDisplayName == null) {
return;
}
if (nick == null || !nick.hasRequest()) {
p.sendRichMessage(Config.NICK_ALREADY_HANDLED,
Placeholder.component("targetplayer", itemDisplayName))
;
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(), itemMeta.getDisplayName(), newNick, NickEvent.NickEventType.ACCEPTED);
nickEvent.callEvent();
}
}.runTask(ChatPlugin.getInstance());
p.sendRichMessage(Config.NICK_ACCEPTED,
Placeholder.component("targetplayer", itemDisplayName),
Placeholder.component("newnick", Utility.applyColor(nick.getNewNick())),
Placeholder.component("oldnick", Utility.applyColor(nick.getCurrentNick() == null ? itemMeta.getDisplayName() : nick.getCurrentNick())));
if (owningPlayer.isOnline() && owningPlayer.getPlayer() != null) {
Nicknames.getInstance().setNick(owningPlayer.getPlayer(), 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(itemMeta.displayName());
itemMeta.lore(clickedItem.lore());
itemStack.setItemMeta(itemMeta);
e.getInventory().setItem(e.getSlot(), itemStack);
p.updateInventory();
} else {
p.sendRichMessage(Config.NICK_PLAYER_NOT_ONLINE, Placeholder.component("player", itemDisplayName));
}
} else if (e.isRightClick()) {
if (owningPlayer.hasPlayedBefore()) {
Queries.denyNewNickname(uniqueId);
String newNick = nick.getNewNick();
new BukkitRunnable() {
@Override
public void run() {
NickEvent nickEvent = new NickEvent(e.getWhoClicked().getName(), itemMeta.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().sendRichMessage(Config.NICK_NOT_CHANGED);
}
NickUtilities.bungeeMessageHandled(uniqueId, e.getWhoClicked().getServer().getPlayer(e.getWhoClicked().getName()), "Denied");
final ComponentLike 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(itemDisplayName);
itemMeta.lore(clickedItem.lore());
itemStack.setItemMeta(itemMeta);
e.getInventory().setItem(e.getSlot(), itemStack);
p.updateInventory();
} else {
if (itemDisplayName == null) {
p.sendRichMessage(Config.NICK_PLAYER_NOT_ONLINE, Placeholder.parsed("player", "UNKNOWN PLAYER NAME"));
} else {
p.sendRichMessage(Config.NICK_PLAYER_NOT_ONLINE, Placeholder.component("player", itemDisplayName));
}
}
}
}
}.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);
}
nicknamesGui.open(ent);
}
}

View File

@ -1,17 +0,0 @@
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)
}

View File

@ -1,12 +0,0 @@
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
) {
}

View File

@ -1,29 +0,0 @@
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());
}
}

View File

@ -1,153 +0,0 @@
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();
}
}

View File

@ -1,76 +0,0 @@
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);
});
}
}

View File

@ -1,155 +0,0 @@
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");
}
}

View File

@ -1,11 +0,0 @@
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) {
}
}

View File

@ -1,21 +0,0 @@
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);
}
}

View File

@ -1,11 +0,0 @@
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);
}

View File

@ -3,13 +3,21 @@ 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.alttd.com/snapshots") // Altitude - Galaxy
maven("https://oss.sonatype.org/content/groups/public/") // Adventure
maven("https://oss.sonatype.org/content/repositories/snapshots/") // Minimessage
maven("https://repo.papermc.io/repository/maven-public/")
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/")
@ -18,13 +26,6 @@ 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)
}
@ -34,5 +35,3 @@ pluginManagement {
gradlePluginPortal()
}
}
include("matrix")

View File

@ -5,8 +5,8 @@ plugins {
dependencies {
implementation(project(":api")) // API
compileOnly("com.velocitypowered:velocity-api:3.2.0-SNAPSHOT")
annotationProcessor("com.velocitypowered:velocity-api:3.2.0-SNAPSHOT")
compileOnly("com.velocitypowered:velocity-api:3.5.0-SNAPSHOT")
annotationProcessor("com.velocitypowered:velocity-api:3.5.0-SNAPSHOT")
implementation("mysql:mysql-connector-java:8.0.33") // mysql
implementation("org.spongepowered", "configurate-yaml", "4.2.0")
compileOnly("net.kyori:adventure-text-minimessage:4.23.0")

View File

@ -2,33 +2,23 @@ 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.PluginMessageListener;
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.alttd.velocitychat.listeners.PluginMessageListener;
import com.alttd.chat.util.ALogger;
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;
@ -46,16 +36,14 @@ 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;
@ -63,12 +51,11 @@ public class VelocityChat {
private ChannelIdentifier channelIdentifier;
@Inject
public VelocityChat(ProxyServer proxyServer, Logger proxyLogger, @DataDirectory Path proxydataDirectory, EventManager eventManager) {
public VelocityChat(ProxyServer proxyServer, Logger proxyLogger, @DataDirectory Path proxydataDirectory) {
plugin = this;
server = proxyServer;
logger = proxyLogger;
dataDirectory = proxydataDirectory;
this.eventManager = eventManager;
}
@Subscribe
@ -93,7 +80,6 @@ public class VelocityChat {
ChatUser console = new ChatUser(Config.CONSOLEUUID, -1, null);
console.setDisplayName(Config.CONSOLENAME);
ChatUserManager.addUser(console);
initMatrix();
}
public void reloadConfig() {
@ -106,42 +92,6 @@ 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();
}

View File

@ -5,7 +5,6 @@ import com.alttd.chat.util.Utility;
import com.alttd.velocitychat.VelocityChat;
import com.alttd.velocitychat.events.GlobalAdminChatEvent;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.text.ComponentLike;
@ -19,7 +18,7 @@ public class ChatListener {
plugin = VelocityChat.getPlugin();
}
@Subscribe(order = PostOrder.FIRST)
@Subscribe(priority = 0)
public void onGlobalStaffChat(GlobalAdminChatEvent event) {
String senderName = Config.CONSOLENAME;
String serverName = "Altitude";

View File

@ -11,7 +11,6 @@ import com.alttd.velocitychat.VelocityChat;
import com.alttd.velocitychat.commands.vote_to_mute.ActiveVoteToMute;
import com.alttd.velocitychat.data.ServerWrapper;
import com.alttd.velocitychat.handlers.ServerHandler;
import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.DisconnectEvent;
import com.velocitypowered.api.event.connection.LoginEvent;
@ -34,7 +33,7 @@ import java.util.concurrent.TimeUnit;
public class ProxyPlayerListener {
@Subscribe(order = PostOrder.FIRST)
@Subscribe(priority = 0)
public void onPlayerLogin(LoginEvent event) {
Player player = event.getPlayer();
UUID uuid = player.getUniqueId();
@ -57,7 +56,7 @@ public class ProxyPlayerListener {
ServerHandler.addPlayerUUID(player.getUsername(), uuid);
}
@Subscribe(order = PostOrder.LAST)
@Subscribe(priority = 4)
public void afterPlayerLogin(ServerPostConnectEvent event) {
Player player = event.getPlayer();
RegisteredServer previousServer = event.getPreviousServer();

View File

@ -1,26 +0,0 @@
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);
}
}

View File

@ -1,38 +0,0 @@
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));
}
}

View File

@ -1,35 +0,0 @@
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);
}
}