diff --git a/pom.xml b/pom.xml index 6d75ca6..4218abc 100644 --- a/pom.xml +++ b/pom.xml @@ -14,11 +14,9 @@ jar Chroma-Discord - http://maven.apache.org + https://maven.apache.org - src/main/java @@ -31,7 +29,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.1 + 3.4.1 package @@ -81,32 +79,20 @@ jcenter - http://jcenter.bintray.com + https://jcenter.bintray.com jitpack.io https://jitpack.io - Essentials https://ci.ender.zone/plugin/repository/everything/ projectlombok.org - http://projectlombok.org/mavenrepo + https://projectlombok.org/mavenrepo - - papermc https://papermc.io/repo/repository/maven-public/ @@ -172,38 +158,14 @@ org.projectlombok lombok - 1.18.10 + 1.18.26 provided - com.vdurmont emoji-java 4.0.0 - - - - com.github.lucko.LuckPerms - bukkit - master-SNAPSHOT - provided - org.mockito diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java index 19cc441..adeb004 100644 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java @@ -142,6 +142,7 @@ class MCListener implements Listener { @EventHandler public void onBroadcastMessage(BroadcastMessageEvent event) { + event.getRecipients().removeIf(sender -> sender instanceof DiscordSenderBase); MCChatUtils.forCustomAndAllMCChat(MCChatUtils.send(event.getMessage()), ChannelconBroadcast.BROADCAST, false).subscribe(); } diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java b/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java index 243cf83..4a699fc 100644 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java @@ -6,7 +6,6 @@ import buttondevteam.discordplugin.DPUtils; import buttondevteam.discordplugin.DiscordConnectedPlayer; import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.discordplugin.playerfaker.ServerWatcher; -import buttondevteam.discordplugin.playerfaker.perm.LPInjector; import buttondevteam.discordplugin.util.DPState; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCSystemChatEvent; @@ -35,7 +34,6 @@ public class MinecraftChatModule extends Component { public static DPState state = DPState.RUNNING; private @Getter MCChatListener listener; ServerWatcher serverWatcher; - private LPInjector lpInjector; boolean disabling = false; /** @@ -151,8 +149,8 @@ public class MinecraftChatModule extends Component { } try { - if (lpInjector == null) - lpInjector = new LPInjector(DiscordPlugin.plugin); + // TODO: Fix injector, look for a more stable solution + log("LuckPerms injector is broken atm, you may encounter issues with the mcchat command"); } catch (Exception e) { TBMCCoreAPI.SendException("Failed to init LuckPerms injector", e, this); } catch (NoClassDefFoundError e) { diff --git a/src/main/java/buttondevteam/discordplugin/playerfaker/perm/LPInjector.java b/src/main/java/buttondevteam/discordplugin/playerfaker/perm/LPInjector.java deleted file mode 100644 index 055c5e8..0000000 --- a/src/main/java/buttondevteam/discordplugin/playerfaker/perm/LPInjector.java +++ /dev/null @@ -1,238 +0,0 @@ -package buttondevteam.discordplugin.playerfaker.perm; - -import buttondevteam.discordplugin.DiscordConnectedPlayer; -import buttondevteam.discordplugin.DiscordPlugin; -import buttondevteam.discordplugin.mcchat.MCChatUtils; -import buttondevteam.lib.TBMCCoreAPI; -import me.lucko.luckperms.bukkit.LPBukkitBootstrap; -import me.lucko.luckperms.bukkit.LPBukkitPlugin; -import me.lucko.luckperms.bukkit.inject.permissible.DummyPermissibleBase; -import me.lucko.luckperms.bukkit.inject.permissible.LuckPermsPermissible; -import me.lucko.luckperms.bukkit.listeners.BukkitConnectionListener; -import me.lucko.luckperms.common.config.ConfigKeys; -import me.lucko.luckperms.common.locale.Message; -import me.lucko.luckperms.common.locale.TranslationManager; -import me.lucko.luckperms.common.model.User; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.bukkit.Bukkit; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerLoginEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.permissions.PermissibleBase; -import org.bukkit.permissions.PermissionAttachment; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Collection; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicBoolean; - -public final class LPInjector implements Listener { //Disable login event for LuckPerms - private final LPBukkitPlugin plugin; - private final BukkitConnectionListener connectionListener; - private final Set deniedLogin; - private final Field detectedCraftBukkitOfflineMode; - private final Method printCraftBukkitOfflineModeError; - private final Field PERMISSIBLE_BASE_ATTACHMENTS_FIELD; - private final Method convertAndAddAttachments; - private final Method getActive; - private final Method setOldPermissible; - private final Method getOldPermissible; - - public LPInjector(DiscordPlugin dp) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException { - LPBukkitBootstrap bs = (LPBukkitBootstrap) Bukkit.getPluginManager().getPlugin("LuckPerms"); - Field field = LPBukkitBootstrap.class.getDeclaredField("plugin"); - field.setAccessible(true); - plugin = (LPBukkitPlugin) field.get(bs); - MCChatUtils.addStaticExcludedPlugin(PlayerLoginEvent.class, "LuckPerms"); - MCChatUtils.addStaticExcludedPlugin(PlayerQuitEvent.class, "LuckPerms"); - - field = LPBukkitPlugin.class.getDeclaredField("connectionListener"); - field.setAccessible(true); - connectionListener = (BukkitConnectionListener) field.get(plugin); - field = connectionListener.getClass().getDeclaredField("deniedLogin"); - field.setAccessible(true); - //noinspection unchecked - deniedLogin = (Set) field.get(connectionListener); - field = connectionListener.getClass().getDeclaredField("detectedCraftBukkitOfflineMode"); - field.setAccessible(true); - detectedCraftBukkitOfflineMode = field; - printCraftBukkitOfflineModeError = connectionListener.getClass().getDeclaredMethod("printCraftBukkitOfflineModeError"); - printCraftBukkitOfflineModeError.setAccessible(true); - - //PERMISSIBLE_FIELD = DiscordFakePlayer.class.getDeclaredField("perm"); - //PERMISSIBLE_FIELD.setAccessible(true); //Hacking my own plugin, while we're at it - PERMISSIBLE_BASE_ATTACHMENTS_FIELD = PermissibleBase.class.getDeclaredField("attachments"); - PERMISSIBLE_BASE_ATTACHMENTS_FIELD.setAccessible(true); - - convertAndAddAttachments = LuckPermsPermissible.class.getDeclaredMethod("convertAndAddAttachments", Collection.class); - convertAndAddAttachments.setAccessible(true); - getActive = LuckPermsPermissible.class.getDeclaredMethod("getActive"); - getActive.setAccessible(true); - setOldPermissible = LuckPermsPermissible.class.getDeclaredMethod("setOldPermissible", PermissibleBase.class); - setOldPermissible.setAccessible(true); - getOldPermissible = LuckPermsPermissible.class.getDeclaredMethod("getOldPermissible"); - getOldPermissible.setAccessible(true); - - TBMCCoreAPI.RegisterEventsForExceptions(this, dp); - } - - - //Code copied from LuckPerms - me.lucko.luckperms.bukkit.listeners.BukkitConnectionListener - @EventHandler(priority = EventPriority.LOWEST) - public void onPlayerLogin(PlayerLoginEvent e) { - /* Called when the player starts logging into the server. - At this point, the users data should be present and loaded. */ - - if (!(e.getPlayer() instanceof DiscordConnectedPlayer)) - return; //Normal players must be handled by the plugin - - final DiscordConnectedPlayer player = (DiscordConnectedPlayer) e.getPlayer(); - - if (plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) { - plugin.getLogger().info("Processing login for " + player.getUniqueId() + " - " + player.getName()); - } - - final User user = plugin.getUserManager().getIfLoaded(player.getUniqueId()); - - /* User instance is null for whatever reason. Could be that it was unloaded between asyncpre and now. */ - if (user == null) { - deniedLogin.add(player.getUniqueId()); - - if (!plugin.getConnectionListener().getUniqueConnections().contains(player.getUniqueId())) { - - plugin.getLogger().warn("User " + player.getUniqueId() + " - " + player.getName() + - " doesn't have data pre-loaded, they have never been processed during pre-login in this session." + - " - denying login."); - - try { - if ((Boolean) detectedCraftBukkitOfflineMode.get(connectionListener)) { - printCraftBukkitOfflineModeError.invoke(connectionListener); - - Component reason = TranslationManager.render(Message.LOADING_STATE_ERROR_CB_OFFLINE_MODE.build(), player.getLocale()); - e.disallow(PlayerLoginEvent.Result.KICK_OTHER, LegacyComponentSerializer.legacySection().serialize(reason)); - return; - } - } catch (IllegalAccessException | InvocationTargetException ex) { - ex.printStackTrace(); - } - - } else { - plugin.getLogger().warn("User " + player.getUniqueId() + " - " + player.getName() + - " doesn't currently have data pre-loaded, but they have been processed before in this session." + - " - denying login."); - } - - Component reason = TranslationManager.render(Message.LOADING_STATE_ERROR.build(), player.getLocale()); - e.disallow(PlayerLoginEvent.Result.KICK_OTHER, LegacyComponentSerializer.legacySection().serialize(reason)); - return; - } - - // User instance is there, now we can inject our custom Permissible into the player. - // Care should be taken at this stage to ensure that async tasks which manipulate bukkit data check that the player is still online. - try { - // get the existing PermissibleBase held by the player - PermissibleBase oldPermissible = player.getPerm(); - - // Make a new permissible for the user - LuckPermsPermissible lpPermissible = new LuckPermsPermissible(player, user, this.plugin); - - // Inject into the player - inject(player, lpPermissible, oldPermissible); - - } catch (Throwable t) { - plugin.getLogger().warn("Exception thrown when setting up permissions for " + - player.getUniqueId() + " - " + player.getName() + " - denying login."); - t.printStackTrace(); - - Component reason = TranslationManager.render(Message.LOADING_SETUP_ERROR.build(), player.getLocale()); - e.disallow(PlayerLoginEvent.Result.KICK_OTHER, LegacyComponentSerializer.legacySection().serialize(reason)); - return; - } - - this.plugin.getContextManager().signalContextUpdate(player); - } - - // Wait until the last priority to unload, so plugins can still perform permission checks on this event - @EventHandler(priority = EventPriority.MONITOR) - public void onPlayerQuit(PlayerQuitEvent e) { - if (!(e.getPlayer() instanceof DiscordConnectedPlayer)) - return; - - final DiscordConnectedPlayer player = (DiscordConnectedPlayer) e.getPlayer(); - - connectionListener.handleDisconnect(player.getUniqueId()); - - // perform unhooking from bukkit objects 1 tick later. - // this allows plugins listening after us on MONITOR to still have intact permissions data - this.plugin.getBootstrap().getServer().getScheduler().runTaskLater(this.plugin.getBootstrap(), () -> { - // Remove the custom permissible - try { - uninject(player); - } catch (Exception ex) { - ex.printStackTrace(); - } - - // Handle auto op - if (this.plugin.getConfiguration().get(ConfigKeys.AUTO_OP)) { - player.setOp(false); - } - - // remove their contexts cache - this.plugin.getContextManager().onPlayerQuit(player); - }, 1L); - } - - //me.lucko.luckperms.bukkit.inject.permissible.PermissibleInjector - private void inject(DiscordConnectedPlayer player, LuckPermsPermissible newPermissible, PermissibleBase oldPermissible) throws IllegalAccessException, InvocationTargetException { - - // seems we have already injected into this player. - if (oldPermissible instanceof LuckPermsPermissible) { - throw new IllegalStateException("LPPermissible already injected into player " + player.toString()); - } - - // Move attachments over from the old permissible - - //noinspection unchecked - List attachments = (List) PERMISSIBLE_BASE_ATTACHMENTS_FIELD.get(oldPermissible); - - convertAndAddAttachments.invoke(newPermissible, attachments); - attachments.clear(); - oldPermissible.clearPermissions(); - - // Setup the new permissible - ((AtomicBoolean) getActive.invoke(newPermissible)).set(true); - setOldPermissible.invoke(newPermissible, oldPermissible); - - // inject the new instance - player.setPerm(newPermissible); - } - - private void uninject(DiscordConnectedPlayer player) throws Exception { - - // gets the players current permissible. - PermissibleBase permissible = player.getPerm(); - - // only uninject if the permissible was a luckperms one. - if (permissible instanceof LuckPermsPermissible) { - LuckPermsPermissible lpPermissible = ((LuckPermsPermissible) permissible); - - // clear all permissions - lpPermissible.clearPermissions(); - - // set to inactive - ((AtomicBoolean) getActive.invoke(lpPermissible)).set(false); - - // handle the replacement permissible. - // just inject a dummy class. this is used when we know the player is about to quit the server. - player.setPerm(DummyPermissibleBase.INSTANCE); - - } - } -}