From f85b56fe28691936bfc41c559e91a98bbe9e2056 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sun, 29 Oct 2017 02:00:44 +0200 Subject: [PATCH 1/6] Quite big hack for hooking into all broadcasts Right now it doesn't let anyone in. --- pom.xml | 8 + .../discordplugin/DiscordPlugin.java | 2 + .../discordplugin/PlayerListWatcher.java | 352 ++++++++++++++++++ 3 files changed, 362 insertions(+) create mode 100644 src/main/java/buttondevteam/discordplugin/PlayerListWatcher.java diff --git a/pom.xml b/pom.xml index d2d1e7b..dea2593 100644 --- a/pom.xml +++ b/pom.xml @@ -210,5 +210,13 @@ + + + org.objenesis + objenesis + 2.6 + test + + diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java index e2d22e2..bfe0784 100644 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java @@ -49,6 +49,8 @@ public class DiscordPlugin extends JavaPlugin implements IListener { public void onEnable() { try { Bukkit.getLogger().info("Initializing DiscordPlugin..."); + PlayerListWatcher.hookUp(); + Bukkit.getLogger().info("Finished hooking into the player list"); plugin = this; lastannouncementtime = getConfig().getLong("lastannouncementtime"); lastseentime = getConfig().getLong("lastseentime"); diff --git a/src/main/java/buttondevteam/discordplugin/PlayerListWatcher.java b/src/main/java/buttondevteam/discordplugin/PlayerListWatcher.java new file mode 100644 index 0000000..16fd7a2 --- /dev/null +++ b/src/main/java/buttondevteam/discordplugin/PlayerListWatcher.java @@ -0,0 +1,352 @@ +package buttondevteam.discordplugin; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.List; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_12_R1.CraftServer; +import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import org.objenesis.ObjenesisStd; + +import com.mojang.authlib.GameProfile; + +import buttondevteam.discordplugin.listeners.MCChatListener; +import buttondevteam.lib.TBMCCoreAPI; +import lombok.val; +import net.minecraft.server.v1_12_R1.AdvancementDataPlayer; +import net.minecraft.server.v1_12_R1.DedicatedPlayerList; +import net.minecraft.server.v1_12_R1.DedicatedServer; +import net.minecraft.server.v1_12_R1.Entity; +import net.minecraft.server.v1_12_R1.EntityHuman; +import net.minecraft.server.v1_12_R1.EntityPlayer; +import net.minecraft.server.v1_12_R1.GameProfileBanList; +import net.minecraft.server.v1_12_R1.IChatBaseComponent; +import net.minecraft.server.v1_12_R1.IpBanList; +import net.minecraft.server.v1_12_R1.LoginListener; +import net.minecraft.server.v1_12_R1.MinecraftServer; +import net.minecraft.server.v1_12_R1.NBTTagCompound; +import net.minecraft.server.v1_12_R1.NetworkManager; +import net.minecraft.server.v1_12_R1.OpList; +import net.minecraft.server.v1_12_R1.Packet; +import net.minecraft.server.v1_12_R1.ScoreboardServer; +import net.minecraft.server.v1_12_R1.ServerStatisticManager; +import net.minecraft.server.v1_12_R1.WhiteList; +import net.minecraft.server.v1_12_R1.World; +import net.minecraft.server.v1_12_R1.WorldServer; + +public class PlayerListWatcher extends DedicatedPlayerList { + private DedicatedPlayerList plist; + + public PlayerListWatcher(DedicatedServer minecraftserver) { + super(minecraftserver); // <-- Does some init stuff and calls Bukkit.setServer() so we have to use Objenesis + } + + @Override + public void sendMessage(IChatBaseComponent ichatbasecomponent, boolean flag) { + super.sendMessage(ichatbasecomponent, flag); + MCChatListener.sendSystemMessageToChat(ichatbasecomponent.toPlainText()); + } + + public static void hookUp() { + try { + Field conf = CraftServer.class.getDeclaredField("console"); + conf.setAccessible(true); + val server = (MinecraftServer) conf.get(Bukkit.getServer()); + val plw = new ObjenesisStd().newInstance(PlayerListWatcher.class); // Cannot call super constructor + plw.plist = (DedicatedPlayerList) server.getPlayerList(); + plw.maxPlayers = plw.plist.getMaxPlayers(); + Field plf = plw.getClass().getField("players"); + plf.setAccessible(true); + Field modf = plf.getClass().getDeclaredField("modifiers"); + modf.setAccessible(true); + modf.set(plf, plf.getModifiers() & ~Modifier.FINAL); + plf.set(plw, plw.plist.players); + server.a(plw); + } catch (Exception e) { + TBMCCoreAPI.SendException("Error while hacking the player list!", e); + } + } + + public void a(EntityHuman entityhuman, IChatBaseComponent ichatbasecomponent) { + plist.a(entityhuman, ichatbasecomponent); + } + + public ServerStatisticManager a(EntityHuman entityhuman) { + return plist.a(entityhuman); + } + + public void a(EntityPlayer entityplayer, int i) { + plist.a(entityplayer, i); + } + + public void a(EntityPlayer entityplayer, WorldServer worldserver) { + plist.a(entityplayer, worldserver); + } + + public NBTTagCompound a(EntityPlayer entityplayer) { + return plist.a(entityplayer); + } + + public void a(int i) { + plist.a(i); + } + + public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { + plist.a(networkmanager, entityplayer); + } + + public void a(Packet packet, int i) { + plist.a(packet, i); + } + + public EntityPlayer a(UUID uuid) { + return plist.a(uuid); + } + + public void addOp(GameProfile gameprofile) { + plist.addOp(gameprofile); + } + + public void addWhitelist(GameProfile gameprofile) { + plist.addWhitelist(gameprofile); + } + + public EntityPlayer attemptLogin(LoginListener loginlistener, GameProfile gameprofile, String hostname) { + return plist.attemptLogin(loginlistener, gameprofile, hostname); + } + + public String b(boolean flag) { + return plist.b(flag); + } + + public void b(EntityHuman entityhuman, IChatBaseComponent ichatbasecomponent) { + plist.b(entityhuman, ichatbasecomponent); + } + + public void b(EntityPlayer entityplayer, WorldServer worldserver) { + plist.b(entityplayer, worldserver); + } + + public List b(String s) { + return plist.b(s); + } + + public Location calculateTarget(Location enter, World target) { + return plist.calculateTarget(enter, target); + } + + public void changeDimension(EntityPlayer entityplayer, int i, TeleportCause cause) { + plist.changeDimension(entityplayer, i, cause); + } + + public void changeWorld(Entity entity, int i, WorldServer worldserver, WorldServer worldserver1) { + plist.changeWorld(entity, i, worldserver, worldserver1); + } + + public int d() { + return plist.d(); + } + + public void d(EntityPlayer entityplayer) { + plist.d(entityplayer); + } + + public String disconnect(EntityPlayer entityplayer) { + return plist.disconnect(entityplayer); + } + + public boolean equals(Object obj) { + return plist.equals(obj); + } + + public String[] f() { + return plist.f(); + } + + public void f(EntityPlayer entityplayer) { + plist.f(entityplayer); + } + + public boolean f(GameProfile gameprofile) { + return plist.f(gameprofile); + } + + public GameProfile[] g() { + return plist.g(); + } + + public boolean getHasWhitelist() { + return plist.getHasWhitelist(); + } + + public IpBanList getIPBans() { + return plist.getIPBans(); + } + + public int getMaxPlayers() { + return plist.getMaxPlayers(); + } + + public OpList getOPs() { + return plist.getOPs(); + } + + public EntityPlayer getPlayer(String s) { + return plist.getPlayer(s); + } + + public int getPlayerCount() { + return plist.getPlayerCount(); + } + + public GameProfileBanList getProfileBans() { + return plist.getProfileBans(); + } + + public String[] getSeenPlayers() { + return plist.getSeenPlayers(); + } + + public DedicatedServer getServer() { + return plist.getServer(); + } + + public WhiteList getWhitelist() { + return plist.getWhitelist(); + } + + public String[] getWhitelisted() { + return plist.getWhitelisted(); + } + + public AdvancementDataPlayer h(EntityPlayer entityplayer) { + return plist.h(entityplayer); + } + + public int hashCode() { + return plist.hashCode(); + } + + public boolean isOp(GameProfile gameprofile) { + return plist.isOp(gameprofile); + } + + public boolean isWhitelisted(GameProfile gameprofile) { + return plist.isWhitelisted(gameprofile); + } + + public EntityPlayer moveToWorld(EntityPlayer entityplayer, int i, boolean flag, Location location, + boolean avoidSuffocation) { + return plist.moveToWorld(entityplayer, i, flag, location, avoidSuffocation); + } + + public EntityPlayer moveToWorld(EntityPlayer entityplayer, int i, boolean flag) { + return plist.moveToWorld(entityplayer, i, flag); + } + + public String[] n() { + return plist.n(); + } + + public void onPlayerJoin(EntityPlayer entityplayer, String joinMessage) { + plist.onPlayerJoin(entityplayer, joinMessage); + } + + public EntityPlayer processLogin(GameProfile gameprofile, EntityPlayer player) { + return plist.processLogin(gameprofile, player); + } + + public void reload() { + plist.reload(); + } + + public void reloadWhitelist() { + plist.reloadWhitelist(); + } + + public void removeOp(GameProfile gameprofile) { + plist.removeOp(gameprofile); + } + + public void removeWhitelist(GameProfile gameprofile) { + plist.removeWhitelist(gameprofile); + } + + public void repositionEntity(Entity entity, Location exit, boolean portal) { + plist.repositionEntity(entity, exit, portal); + } + + public int s() { + return plist.s(); + } + + public void savePlayers() { + plist.savePlayers(); + } + + @SuppressWarnings("rawtypes") + public void sendAll(Packet packet, EntityHuman entityhuman) { + plist.sendAll(packet, entityhuman); + } + + @SuppressWarnings("rawtypes") + public void sendAll(Packet packet, World world) { + plist.sendAll(packet, world); + } + + public void sendAll(Packet packet) { + plist.sendAll(packet); + } + + public void sendMessage(IChatBaseComponent ichatbasecomponent) { + plist.sendMessage(ichatbasecomponent); + } + + public void sendMessage(IChatBaseComponent[] iChatBaseComponents) { + plist.sendMessage(iChatBaseComponents); + } + + public void sendPacketNearby(EntityHuman entityhuman, double d0, double d1, double d2, double d3, int i, + Packet packet) { + plist.sendPacketNearby(entityhuman, d0, d1, d2, d3, i, packet); + } + + public void sendScoreboard(ScoreboardServer scoreboardserver, EntityPlayer entityplayer) { + plist.sendScoreboard(scoreboardserver, entityplayer); + } + + public void setHasWhitelist(boolean flag) { + plist.setHasWhitelist(flag); + } + + public void setPlayerFileData(WorldServer[] aworldserver) { + plist.setPlayerFileData(aworldserver); + } + + public NBTTagCompound t() { + return plist.t(); + } + + public void tick() { + plist.tick(); + } + + public String toString() { + return plist.toString(); + } + + public void u() { + plist.u(); + } + + public void updateClient(EntityPlayer entityplayer) { + plist.updateClient(entityplayer); + } + + public List v() { + return plist.v(); + } +} From f8c543017a3e95009ad2abd11310b94cb42e9180 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sun, 29 Oct 2017 18:49:52 +0100 Subject: [PATCH 2/6] The hack works! --- pom.xml | 2 +- .../discordplugin/DiscordPlugin.java | 6 ++ .../discordplugin/PlayerListWatcher.java | 61 +++++++++++++------ 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index dea2593..2c3031f 100644 --- a/pom.xml +++ b/pom.xml @@ -153,7 +153,7 @@ org.spigotmc spigot - 1.12-R0.1-SNAPSHOT + 1.12.2-R0.1-SNAPSHOT provided diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java index bfe0784..64a9c63 100644 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java @@ -39,6 +39,7 @@ import sx.blah.discord.util.RequestBuffer.IVoidRequest; public class DiscordPlugin extends JavaPlugin implements IListener { private static final String SubredditURL = "https://www.reddit.com/r/ChromaGamers"; private static boolean stop = false; + private static Thread mainThread; public static IDiscordClient dc; public static DiscordPlugin plugin; public static boolean SafeMode = true; @@ -59,6 +60,7 @@ public class DiscordPlugin extends JavaPlugin implements IListener { cb.withToken(Files.readFirstLine(new File("TBMC", "Token.txt"), StandardCharsets.UTF_8)); dc = cb.login(); dc.getDispatcher().registerListener(this); + mainThread = Thread.currentThread(); } catch (Exception e) { e.printStackTrace(); Bukkit.getPluginManager().disablePlugin(this); @@ -372,6 +374,8 @@ public class DiscordPlugin extends JavaPlugin implements IListener { public static T perform(IRequest action) { if (SafeMode) return null; + if (Thread.currentThread() == mainThread) + throw new RuntimeException("Tried to wait for a Discord request on the main thread. This could cause lag."); return RequestBuffer.request(action).get(); // Let the pros handle this } @@ -381,6 +385,8 @@ public class DiscordPlugin extends JavaPlugin implements IListener { public static Void perform(IVoidRequest action) { if (SafeMode) return null; + if (Thread.currentThread() == mainThread) + throw new RuntimeException("Tried to wait for a Discord request on the main thread. This could cause lag."); return RequestBuffer.request(action).get(); // Let the pros handle this } diff --git a/src/main/java/buttondevteam/discordplugin/PlayerListWatcher.java b/src/main/java/buttondevteam/discordplugin/PlayerListWatcher.java index 16fd7a2..365e1be 100644 --- a/src/main/java/buttondevteam/discordplugin/PlayerListWatcher.java +++ b/src/main/java/buttondevteam/discordplugin/PlayerListWatcher.java @@ -8,6 +8,7 @@ import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.craftbukkit.v1_12_R1.CraftServer; +import org.bukkit.craftbukkit.v1_12_R1.util.CraftChatMessage; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.objenesis.ObjenesisStd; @@ -17,6 +18,7 @@ import buttondevteam.discordplugin.listeners.MCChatListener; import buttondevteam.lib.TBMCCoreAPI; import lombok.val; import net.minecraft.server.v1_12_R1.AdvancementDataPlayer; +import net.minecraft.server.v1_12_R1.ChatMessageType; import net.minecraft.server.v1_12_R1.DedicatedPlayerList; import net.minecraft.server.v1_12_R1.DedicatedServer; import net.minecraft.server.v1_12_R1.Entity; @@ -31,6 +33,7 @@ import net.minecraft.server.v1_12_R1.NBTTagCompound; import net.minecraft.server.v1_12_R1.NetworkManager; import net.minecraft.server.v1_12_R1.OpList; import net.minecraft.server.v1_12_R1.Packet; +import net.minecraft.server.v1_12_R1.PacketPlayOutChat; import net.minecraft.server.v1_12_R1.ScoreboardServer; import net.minecraft.server.v1_12_R1.ServerStatisticManager; import net.minecraft.server.v1_12_R1.WhiteList; @@ -44,10 +47,39 @@ public class PlayerListWatcher extends DedicatedPlayerList { super(minecraftserver); // <-- Does some init stuff and calls Bukkit.setServer() so we have to use Objenesis } + public void sendAll(Packet packet) { + plist.sendAll(packet); + try { // Some messages get sent by directly constructing a packet + if (packet instanceof PacketPlayOutChat) { + Field msgf = PacketPlayOutChat.class.getDeclaredField("a"); + msgf.setAccessible(true); + MCChatListener.sendSystemMessageToChat(((IChatBaseComponent) msgf.get(packet)).toPlainText()); + } + } catch (Exception e) { + TBMCCoreAPI.SendException("Failed to broadcast message sent to all players - hacking failed.", e); + } + } + @Override - public void sendMessage(IChatBaseComponent ichatbasecomponent, boolean flag) { - super.sendMessage(ichatbasecomponent, flag); - MCChatListener.sendSystemMessageToChat(ichatbasecomponent.toPlainText()); + public void sendMessage(IChatBaseComponent ichatbasecomponent, boolean flag) { // Needed so it calls the overriden method + plist.getServer().sendMessage(ichatbasecomponent); + ChatMessageType chatmessagetype = flag ? ChatMessageType.SYSTEM : ChatMessageType.CHAT; + + // CraftBukkit start - we run this through our processor first so we can get web links etc + this.sendAll(new PacketPlayOutChat(CraftChatMessage.fixComponent(ichatbasecomponent), chatmessagetype)); + // CraftBukkit end + } + + @Override + public void sendMessage(IChatBaseComponent ichatbasecomponent) { // Needed so it calls the overriden method + this.sendMessage(ichatbasecomponent, true); + } + + @Override + public void sendMessage(IChatBaseComponent[] iChatBaseComponents) { // Needed so it calls the overriden method + for (IChatBaseComponent component : iChatBaseComponents) { + sendMessage(component, true); + } } public static void hookUp() { @@ -65,6 +97,9 @@ public class PlayerListWatcher extends DedicatedPlayerList { modf.set(plf, plf.getModifiers() & ~Modifier.FINAL); plf.set(plw, plw.plist.players); server.a(plw); + Field pllf = CraftServer.class.getDeclaredField("playerList"); + pllf.setAccessible(true); + pllf.set(Bukkit.getServer(), plw); } catch (Exception e) { TBMCCoreAPI.SendException("Error while hacking the player list!", e); } @@ -74,10 +109,6 @@ public class PlayerListWatcher extends DedicatedPlayerList { plist.a(entityhuman, ichatbasecomponent); } - public ServerStatisticManager a(EntityHuman entityhuman) { - return plist.a(entityhuman); - } - public void a(EntityPlayer entityplayer, int i) { plist.a(entityplayer, i); } @@ -297,18 +328,6 @@ public class PlayerListWatcher extends DedicatedPlayerList { plist.sendAll(packet, world); } - public void sendAll(Packet packet) { - plist.sendAll(packet); - } - - public void sendMessage(IChatBaseComponent ichatbasecomponent) { - plist.sendMessage(ichatbasecomponent); - } - - public void sendMessage(IChatBaseComponent[] iChatBaseComponents) { - plist.sendMessage(iChatBaseComponents); - } - public void sendPacketNearby(EntityHuman entityhuman, double d0, double d1, double d2, double d3, int i, Packet packet) { plist.sendPacketNearby(entityhuman, d0, d1, d2, d3, i, packet); @@ -349,4 +368,8 @@ public class PlayerListWatcher extends DedicatedPlayerList { public List v() { return plist.v(); } + + public ServerStatisticManager getStatisticManager(EntityPlayer entityhuman) { + return plist.getStatisticManager(entityhuman); + } } From 0c9dd6f49a8fe72c370488352f1787e57815e53a Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Fri, 24 Nov 2017 23:53:48 +0100 Subject: [PATCH 3/6] Server crash stack trace zero Forgot to commit this for a whiiile --- .travis.yml | 4 ++-- .../java/buttondevteam/discordplugin/DiscordPlugin.java | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 36779c2..808d9b0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,10 +2,10 @@ cache: directories: - $HOME/.m2/repository/org/ before_install: | # Wget BuildTools and run if cached folder not found - if [ ! -d "$HOME/.m2/repository/org/spigotmc/spigot/1.12-R0.1-SNAPSHOT" ]; then + if [ ! -d "$HOME/.m2/repository/org/spigotmc/spigot/1.12.2-R0.1-SNAPSHOT" ]; then wget -O BuildTools.jar https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar # grep so that download counts don't appear in log files - java -jar BuildTools.jar --rev 1.12 | grep -vE "[^/ ]*/[^/ ]*\s*KB\s*$" | grep -v "^\s*$" + java -jar BuildTools.jar --rev 1.12.2 | grep -vE "[^/ ]*/[^/ ]*\s*KB\s*$" | grep -v "^\s*$" fi language: java jdk: diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java index 64a9c63..4b7fe3e 100644 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java @@ -125,8 +125,10 @@ public class DiscordPlugin extends JavaPlugin implements IListener { if (getConfig().getBoolean("serverup", false)) { sendMessageToChannel(chatchannel, "", new EmbedBuilder().withColor(Color.YELLOW) .withTitle("Server recovered from a crash - chat connected.").build()); - TBMCCoreAPI.SendException("The server crashed!", new Throwable( - "The server shut down unexpectedly. See the log of the previous run for more details.")); + val thr = new Throwable( + "The server shut down unexpectedly. See the log of the previous run for more details."); + thr.setStackTrace(new StackTraceElement[0]); + TBMCCoreAPI.SendException("The server crashed!", thr); } else sendMessageToChannel(chatchannel, "", new EmbedBuilder().withColor(Color.GREEN) .withTitle("Server started - chat connected.").build()); From 20ff9cc3e6fb40bec4d070040edd36b99543c2cb Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Tue, 28 Nov 2017 23:07:34 +0100 Subject: [PATCH 4/6] Only showing join/leave/etc. messages if not hooked --- .../java/buttondevteam/discordplugin/ChromaBot.java | 11 +++++++++++ .../buttondevteam/discordplugin/DiscordPlugin.java | 11 +++++++++-- .../discordplugin/listeners/MCListener.java | 9 ++++++--- 3 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 src/main/java/buttondevteam/discordplugin/ChromaBot.java diff --git a/src/main/java/buttondevteam/discordplugin/ChromaBot.java b/src/main/java/buttondevteam/discordplugin/ChromaBot.java new file mode 100644 index 0000000..9acc861 --- /dev/null +++ b/src/main/java/buttondevteam/discordplugin/ChromaBot.java @@ -0,0 +1,11 @@ +package buttondevteam.discordplugin; + +import lombok.Getter; + +public class ChromaBot { + /** + * May be null if it's not initialized + */ + public @Getter ChromaBot instance; + // TODO +} diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java index 4b7fe3e..41abe7d 100644 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java @@ -44,14 +44,21 @@ public class DiscordPlugin extends JavaPlugin implements IListener { public static DiscordPlugin plugin; public static boolean SafeMode = true; public static List GameRoles; + public static boolean hooked = false; @SuppressWarnings("unchecked") @Override public void onEnable() { try { Bukkit.getLogger().info("Initializing DiscordPlugin..."); - PlayerListWatcher.hookUp(); - Bukkit.getLogger().info("Finished hooking into the player list"); + try { + PlayerListWatcher.hookUp(); + hooked = true; + Bukkit.getLogger().info("Finished hooking into the player list"); + } catch (Throwable e) { + e.printStackTrace(); + Bukkit.getLogger().warning("Couldn't hook into the player list!"); + } plugin = this; lastannouncementtime = getConfig().getLong("lastannouncementtime"); lastseentime = getConfig().getLong("lastseentime"); diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java index 6f1bf9a..0ee2a35 100644 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java @@ -68,7 +68,8 @@ public class MCListener implements Listener { + " do /discord accept"); p.sendMessage("§bIf it wasn't you, do /discord decline"); } - MCChatListener.sendSystemMessageToChat(e.GetPlayer().PlayerName().get() + " joined the game"); + if (!DiscordPlugin.hooked) + MCChatListener.sendSystemMessageToChat(e.GetPlayer().PlayerName().get() + " joined the game"); MCChatListener.ListC = 0; DiscordPlugin.updatePlayerList(); } @@ -83,7 +84,8 @@ public class MCListener implements Listener { () -> MCChatListener.ConnectedSenders.values().stream() .filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny() .ifPresent(dcp -> callEventExcludingSome(new PlayerJoinEvent(dcp, "")))); - MCChatListener.sendSystemMessageToChat(e.GetPlayer().PlayerName().get() + " left the game"); + if (!DiscordPlugin.hooked) + MCChatListener.sendSystemMessageToChat(e.GetPlayer().PlayerName().get() + " left the game"); Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, DiscordPlugin::updatePlayerList, 5); } @@ -105,7 +107,8 @@ public class MCListener implements Listener { @EventHandler(priority = EventPriority.LOW) public void onPlayerDeath(PlayerDeathEvent e) { - MCChatListener.sendSystemMessageToChat(e.getDeathMessage()); + if (!DiscordPlugin.hooked) + MCChatListener.sendSystemMessageToChat(e.getDeathMessage()); } @EventHandler From 4c8a1c45822c173c8abd40335f67db49dad33f19 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Wed, 29 Nov 2017 22:30:34 +0100 Subject: [PATCH 5/6] Refactoring, ChromaBot API, fixes, needs testing --- .../discordplugin/ChromaBot.java | 126 +++++++++++++++++- .../buttondevteam/discordplugin/DPUtils.java | 67 ++++++++++ .../discordplugin/DiscordPlugin.java | 85 +----------- .../discordplugin/DiscordSenderBase.java | 2 +- .../discordplugin/commands/RoleCommand.java | 5 +- .../listeners/AutoUpdaterListener.java | 3 +- .../listeners/MCChatListener.java | 54 ++++---- .../discordplugin/listeners/MCListener.java | 11 +- 8 files changed, 240 insertions(+), 113 deletions(-) create mode 100644 src/main/java/buttondevteam/discordplugin/DPUtils.java diff --git a/src/main/java/buttondevteam/discordplugin/ChromaBot.java b/src/main/java/buttondevteam/discordplugin/ChromaBot.java index 9acc861..de4b70c 100644 --- a/src/main/java/buttondevteam/discordplugin/ChromaBot.java +++ b/src/main/java/buttondevteam/discordplugin/ChromaBot.java @@ -1,11 +1,131 @@ package buttondevteam.discordplugin; +import java.awt.Color; +import java.util.Arrays; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.scheduler.BukkitScheduler; + +import buttondevteam.discordplugin.listeners.MCChatListener; import lombok.Getter; +import sx.blah.discord.api.internal.json.objects.EmbedObject; +import sx.blah.discord.handle.obj.IChannel; +import sx.blah.discord.util.EmbedBuilder; public class ChromaBot { /** - * May be null if it's not initialized + * May be null if it's not initialized. Initialization happens after the server is done loading (using {@link BukkitScheduler#runTaskAsynchronously(org.bukkit.plugin.Plugin, Runnable)}) */ - public @Getter ChromaBot instance; - // TODO + private static @Getter ChromaBot instance; + private DiscordPlugin dp; + + /** + * This will set the instance field. + * + * @param dp + * The Discord plugin + */ + ChromaBot(DiscordPlugin dp) { + instance = this; + this.dp = dp; + } + + static void delete() { + instance = null; + } + + /** + * Send a message to the chat channel and private chats. + * + * @param message + * The message to send, duh + */ + public void sendMessage(String message) { + MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message)); + } + + /** + * Send a message to the chat channel and private chats. + * + * @param message + * The message to send, duh + * @param embed + * Custom fancy stuff, use {@link EmbedBuilder} to create one + */ + public void sendMessage(String message, EmbedObject embed) { + MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, embed)); + } + + /** + * Send a message to an arbitrary channel. This will not send it to the private chats. + * + * @param channel + * The channel to send to, use the channel variables in {@link DiscordPlugin} + * @param message + * The message to send, duh + * @param embed + * Custom fancy stuff, use {@link EmbedBuilder} to create one + */ + public void sendMessage(IChannel channel, String message, EmbedObject embed) { + DiscordPlugin.sendMessageToChannel(channel, message, embed); + } + + /** + * Send a fancy message to the chat channel. This will show a bold text with a colored line. + * + * @param message + * The message to send, duh + * @param color + * The color of the line before the text + */ + public void sendFancyMessage(String message, Color color) { + MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, + new EmbedBuilder().withTitle(message).withColor(color).build())); + } + + /** + * Send a fancy message to the chat channel. This will show a bold text with a colored line. + * + * @param message + * The message to send, duh + * @param color + * The color of the line before the text + * @param mcauthor + * The name of the Minecraft player who is the author of this message + */ + public void sendFancyMessage(String message, Color color, String mcauthor) { + MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, + DPUtils.embedWithHead(new EmbedBuilder().withTitle(message).withColor(color), mcauthor).build())); + } + + /** + * Send a fancy message to the chat channel. This will show a bold text with a colored line. + * + * @param message + * The message to send, duh + * @param color + * The color of the line before the text + * @param authorname + * The name of the author of this message + * @param authorimg + * The URL of the avatar image for this message's author + */ + public void sendFancyMessage(String message, Color color, String authorname, String authorimg) { + MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, new EmbedBuilder() + .withTitle(message).withColor(color).withAuthorName(authorname).withAuthorIcon(authorimg).build())); + } + + public void updatePlayerList() { + DPUtils.performNoWait(() -> { + String[] s = DiscordPlugin.chatchannel.getTopic().split("\\n----\\n"); + if (s.length < 3) + return; + s[0] = Bukkit.getOnlinePlayers().size() + " player" + (Bukkit.getOnlinePlayers().size() != 1 ? "s" : "") + + " online"; + s[s.length - 1] = "Players: " + Bukkit.getOnlinePlayers().stream() + .map(p -> DPUtils.sanitizeString(p.getDisplayName())).collect(Collectors.joining(", ")); + DiscordPlugin.chatchannel.changeTopic(Arrays.stream(s).collect(Collectors.joining("\n----\n"))); + }); + } } diff --git a/src/main/java/buttondevteam/discordplugin/DPUtils.java b/src/main/java/buttondevteam/discordplugin/DPUtils.java new file mode 100644 index 0000000..22fc8d7 --- /dev/null +++ b/src/main/java/buttondevteam/discordplugin/DPUtils.java @@ -0,0 +1,67 @@ +package buttondevteam.discordplugin; + +import sx.blah.discord.util.EmbedBuilder; +import sx.blah.discord.util.RequestBuffer; +import sx.blah.discord.util.RequestBuffer.IRequest; +import sx.blah.discord.util.RequestBuffer.IVoidRequest; + +public final class DPUtils { + + public static EmbedBuilder embedWithHead(EmbedBuilder builder, String playername) { + return builder.withAuthorIcon("https://minotar.net/avatar/" + playername + "/32.png"); + } + + /** Removes §[char] colour codes from strings */ + public static String sanitizeString(String string) { + String sanitizedString = ""; + boolean random = false; + for (int i = 0; i < string.length(); i++) { + if (string.charAt(i) == '§') { + i++;// Skips the data value, the 4 in "§4Alisolarflare" + if (string.charAt(i) == 'k') + random = true; + else + random = false; + } else { + if (!random) // Skip random/obfuscated characters + sanitizedString += string.charAt(i); + } + } + return sanitizedString; + } + + /** + * Performs Discord actions, retrying when ratelimited. May return null if action fails too many times or in safe mode. + */ + public static T perform(IRequest action) { + if (DiscordPlugin.SafeMode) + return null; + if (Thread.currentThread() == DiscordPlugin.mainThread) + throw new RuntimeException("Tried to wait for a Discord request on the main thread. This could cause lag."); + return RequestBuffer.request(action).get(); // Let the pros handle this + } + + /** + * Performs Discord actions, retrying when ratelimited. + */ + public static Void perform(IVoidRequest action) { + if (DiscordPlugin.SafeMode) + return null; + if (Thread.currentThread() == DiscordPlugin.mainThread) + throw new RuntimeException("Tried to wait for a Discord request on the main thread. This could cause lag."); + return RequestBuffer.request(action).get(); // Let the pros handle this + } + + public static void performNoWait(IVoidRequest action) { + if (DiscordPlugin.SafeMode) + return; + RequestBuffer.request(action); + } + + public static void performNoWait(IRequest action) { + if (DiscordPlugin.SafeMode) + return; + RequestBuffer.request(action); + } + +} diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java index 41abe7d..e15904b 100644 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java @@ -4,11 +4,9 @@ import java.awt.Color; import java.io.File; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Arrays; import java.util.Calendar; import java.util.List; import java.util.Random; -import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.event.player.PlayerQuitEvent; @@ -33,13 +31,11 @@ import sx.blah.discord.handle.impl.events.ReadyEvent; import sx.blah.discord.handle.impl.obj.ReactionEmoji; import sx.blah.discord.handle.obj.*; import sx.blah.discord.util.*; -import sx.blah.discord.util.RequestBuffer.IRequest; -import sx.blah.discord.util.RequestBuffer.IVoidRequest; public class DiscordPlugin extends JavaPlugin implements IListener { private static final String SubredditURL = "https://www.reddit.com/r/ChromaGamers"; private static boolean stop = false; - private static Thread mainThread; + static Thread mainThread; public static IDiscordClient dc; public static DiscordPlugin plugin; public static boolean SafeMode = true; @@ -141,7 +137,7 @@ public class DiscordPlugin extends JavaPlugin implements IListener { .withTitle("Server started - chat connected.").build()); getConfig().set("serverup", true); saveConfig(); - performNoWait(() -> { + DPUtils.performNoWait(() -> { try { List msgs = genchannel.getPinnedMessages(); for (int i = msgs.size() - 1; i >= 10; i--) { // Unpin all pinned messages except the newest 10 @@ -172,7 +168,7 @@ public class DiscordPlugin extends JavaPlugin implements IListener { "You could make a religion out of this"); } } - updatePlayerList(); + new ChromaBot(this).updatePlayerList(); } }, 0, 10); for (IListener listener : CommandListener.getListeners()) @@ -218,6 +214,7 @@ public class DiscordPlugin extends JavaPlugin implements IListener { sendMessageToChannel(chatchannel, "", new EmbedBuilder().withColor(Restart ? Color.ORANGE : Color.RED) .withTitle(Restart ? "Server restarting" : "Server stopping").build()); try { + ChromaBot.delete(); dc.online("on TBMC"); dc.logout(); } catch (Exception e) { @@ -326,9 +323,9 @@ public class DiscordPlugin extends JavaPlugin implements IListener { RequestBuffer.IRequest r = () -> embed == null ? channel.sendMessage(content) : channel.sendMessage(content, embed, false); if (wait) - return perform(r); + return DPUtils.perform(r); else { - performNoWait(r); + DPUtils.performNoWait(r); return null; } } catch (Exception e) { @@ -338,10 +335,6 @@ public class DiscordPlugin extends JavaPlugin implements IListener { } } - public static EmbedBuilder embedWithHead(EmbedBuilder builder, String playername) { - return builder.withAuthorIcon("https://minotar.net/avatar/" + playername + "/32.png"); - } - public static Permission perms; public boolean setupProviders() { @@ -357,70 +350,4 @@ public class DiscordPlugin extends JavaPlugin implements IListener { perms = permsProvider.getProvider(); return perms != null; } - - /** Removes §[char] colour codes from strings */ - public static String sanitizeString(String string) { - String sanitizedString = ""; - boolean random = false; - for (int i = 0; i < string.length(); i++) { - if (string.charAt(i) == '§') { - i++;// Skips the data value, the 4 in "§4Alisolarflare" - if (string.charAt(i) == 'k') - random = true; - else - random = false; - } else { - if (!random) // Skip random/obfuscated characters - sanitizedString += string.charAt(i); - } - } - return sanitizedString; - } - - /** - * Performs Discord actions, retrying when ratelimited. May return null if action fails too many times or in safe mode. - */ - public static T perform(IRequest action) { - if (SafeMode) - return null; - if (Thread.currentThread() == mainThread) - throw new RuntimeException("Tried to wait for a Discord request on the main thread. This could cause lag."); - return RequestBuffer.request(action).get(); // Let the pros handle this - } - - /** - * Performs Discord actions, retrying when ratelimited. - */ - public static Void perform(IVoidRequest action) { - if (SafeMode) - return null; - if (Thread.currentThread() == mainThread) - throw new RuntimeException("Tried to wait for a Discord request on the main thread. This could cause lag."); - return RequestBuffer.request(action).get(); // Let the pros handle this - } - - public static void performNoWait(IVoidRequest action) { - if (SafeMode) - return; - RequestBuffer.request(action); - } - - public static void performNoWait(IRequest action) { - if (SafeMode) - return; - RequestBuffer.request(action); - } - - public static void updatePlayerList() { - performNoWait(() -> { - String[] s = chatchannel.getTopic().split("\\n----\\n"); - if (s.length < 3) - return; - s[0] = Bukkit.getOnlinePlayers().size() + " player" + (Bukkit.getOnlinePlayers().size() != 1 ? "s" : "") - + " online"; - s[s.length - 1] = "Players: " + Bukkit.getOnlinePlayers().stream() - .map(p -> DiscordPlugin.sanitizeString(p.getDisplayName())).collect(Collectors.joining(", ")); - chatchannel.changeTopic(Arrays.stream(s).collect(Collectors.joining("\n----\n"))); - }); - } } diff --git a/src/main/java/buttondevteam/discordplugin/DiscordSenderBase.java b/src/main/java/buttondevteam/discordplugin/DiscordSenderBase.java index 5b18f50..6da2ff4 100644 --- a/src/main/java/buttondevteam/discordplugin/DiscordSenderBase.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordSenderBase.java @@ -50,7 +50,7 @@ public abstract class DiscordSenderBase implements IDiscordSender { final boolean broadcast = new Exception().getStackTrace()[2].getMethodName().contains("broadcast"); if (broadcast) return; - final String sendmsg = DiscordPlugin.sanitizeString(message); + final String sendmsg = DPUtils.sanitizeString(message); msgtosend += "\n" + sendmsg; if (sendtask == null) sendtask = Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, () -> { diff --git a/src/main/java/buttondevteam/discordplugin/commands/RoleCommand.java b/src/main/java/buttondevteam/discordplugin/commands/RoleCommand.java index 6f573f8..6a8d8e6 100644 --- a/src/main/java/buttondevteam/discordplugin/commands/RoleCommand.java +++ b/src/main/java/buttondevteam/discordplugin/commands/RoleCommand.java @@ -3,6 +3,7 @@ package buttondevteam.discordplugin.commands; import java.util.List; import java.util.stream.Collectors; +import buttondevteam.discordplugin.DPUtils; import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.lib.TBMCCoreAPI; import sx.blah.discord.handle.obj.IMessage; @@ -28,7 +29,7 @@ public class RoleCommand extends DiscordCommandBase { if (role == null) return; try { - DiscordPlugin.perform(() -> message.getAuthor().addRole(role)); + DPUtils.perform(() -> message.getAuthor().addRole(role)); DiscordPlugin.sendMessageToChannel(message.getChannel(), "Added game role."); } catch (Exception e) { TBMCCoreAPI.SendException("Error while adding role!", e); @@ -39,7 +40,7 @@ public class RoleCommand extends DiscordCommandBase { if (role == null) return; try { - DiscordPlugin.perform(() -> message.getAuthor().removeRole(role)); + DPUtils.perform(() -> message.getAuthor().removeRole(role)); DiscordPlugin.sendMessageToChannel(message.getChannel(), "Removed game role."); } catch (Exception e) { TBMCCoreAPI.SendException("Error while removing role!", e); diff --git a/src/main/java/buttondevteam/discordplugin/listeners/AutoUpdaterListener.java b/src/main/java/buttondevteam/discordplugin/listeners/AutoUpdaterListener.java index c0fb834..cc8593a 100644 --- a/src/main/java/buttondevteam/discordplugin/listeners/AutoUpdaterListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/AutoUpdaterListener.java @@ -3,6 +3,7 @@ package buttondevteam.discordplugin.listeners; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import buttondevteam.discordplugin.DPUtils; import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.lib.PluginUpdater; import buttondevteam.lib.TBMCCoreAPI; @@ -13,7 +14,7 @@ public class AutoUpdaterListener implements Listener { if (DiscordPlugin.SafeMode) return; try { - DiscordPlugin.performNoWait(() -> DiscordPlugin.officechannel.getMessageHistory(10).stream() + DPUtils.performNoWait(() -> DiscordPlugin.officechannel.getMessageHistory(10).stream() .filter(m -> m.getWebhookLongID() == 239123781401051138L && m.getEmbeds().get(0).getTitle() .contains(event.getData().get("repository").getAsJsonObject().get("name").getAsString())) .findFirst().get().addReaction(DiscordPlugin.DELIVERED_REACTION)); diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java index 52c9991..49704ae 100644 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java @@ -35,7 +35,7 @@ public class MCChatListener implements Listener, IListener return; Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, () -> { synchronized (this) { - final String authorPlayer = DiscordPlugin.sanitizeString(e.getSender() instanceof Player // + final String authorPlayer = DPUtils.sanitizeString(e.getSender() instanceof Player // ? ((Player) e.getSender()).getDisplayName() // : e.getSender().getName()); final EmbedBuilder embed = new EmbedBuilder().withAuthorName(authorPlayer) @@ -44,11 +44,10 @@ public class MCChatListener implements Listener, IListener // embed.appendField("Channel", ((e.getSender() instanceof DiscordSenderBase ? "d|" : "") // + DiscordPlugin.sanitizeString(e.getChannel().DisplayName)), false); if (e.getSender() instanceof Player) - DiscordPlugin - .embedWithHead( - embed.withAuthorUrl("https://tbmcplugins.github.io/profile.html?type=minecraft&id=" - + ((Player) e.getSender()).getUniqueId()), - ((Player) e.getSender()).getName()); + DPUtils.embedWithHead( + embed.withAuthorUrl("https://tbmcplugins.github.io/profile.html?type=minecraft&id=" + + ((Player) e.getSender()).getUniqueId()), + ((Player) e.getSender()).getName()); else if (e.getSender() instanceof DiscordSenderBase) embed.withAuthorIcon(((DiscordSenderBase) e.getSender()).getUser().getAvatarURL()) .withAuthorUrl("https://tbmcplugins.github.io/profile.html?type=discord&id=" @@ -59,13 +58,14 @@ public class MCChatListener implements Listener, IListener Consumer doit = lastmsgdata -> { final EmbedObject embedObject = embed.build(); final String dmsg = lastmsgdata.channel.isPrivate() - ? DiscordPlugin.sanitizeString(e.getChannel().DisplayName) : ""; + ? DPUtils.sanitizeString(e.getChannel().DisplayName) + : ""; if (lastmsgdata.message == null || lastmsgdata.message.isDeleted() || !authorPlayer.equals(lastmsgdata.message.getEmbeds().get(0).getAuthor().getName()) || lastmsgdata.time / 1000000000f < nanoTime / 1000000000f - 120 || !lastmsgdata.mcchannel.ID.equals(e.getChannel().ID)) { lastmsgdata.message = DiscordPlugin.sendMessageToChannelWait(lastmsgdata.channel, dmsg, - embedObject); + embedObject); // TODO Use ChromaBot API lastmsgdata.time = nanoTime; lastmsgdata.mcchannel = e.getChannel(); lastmsgdata.content = embedObject.description; @@ -74,7 +74,7 @@ public class MCChatListener implements Listener, IListener lastmsgdata.content = embedObject.description = lastmsgdata.content + "\n" + embedObject.description;// The message object doesn't get updated final LastMsgData _lastmsgdata = lastmsgdata; - DiscordPlugin.perform(() -> _lastmsgdata.message.edit(dmsg, embedObject)); + DPUtils.perform(() -> _lastmsgdata.message.edit(dmsg, embedObject)); } catch (MissingPermissionsException | DiscordException e1) { TBMCCoreAPI.SendException("An error occured while editing chat message!", e1); } @@ -85,8 +85,9 @@ public class MCChatListener implements Listener, IListener if ((e.getChannel() == Channel.GlobalChat || e.getChannel().ID.equals("rp")) && isdifferentchannel.test(DiscordPlugin.chatchannel)) - doit.accept(lastmsgdata == null - ? lastmsgdata = new LastMsgData(DiscordPlugin.chatchannel, null, null) : lastmsgdata); + doit.accept( + lastmsgdata == null ? lastmsgdata = new LastMsgData(DiscordPlugin.chatchannel, null, null) + : lastmsgdata); for (LastMsgData data : lastmsgPerUser) { if (data.dp.isMinecraftChatEnabled() && isdifferentchannel.test(data.channel) @@ -123,8 +124,7 @@ public class MCChatListener implements Listener, IListener DiscordPlugin.dc.getUsersByName(event.getMessage().substring(start + 1, mid)).stream() .filter(u -> u.getDiscriminator().equals(event.getMessage().substring(mid + 1, end))).findAny() .ifPresent(user -> event.setMessage(event.getMessage().substring(0, startF) + "@" + user.getName() - + (event.getMessage().length() > end ? event.getMessage().substring(end) - : ""))); // TODO: Add formatting + + (event.getMessage().length() > end ? event.getMessage().substring(end) : ""))); // TODO: Add formatting start = end; // Skip any @s inside the mention } } @@ -203,18 +203,26 @@ public class MCChatListener implements Listener, IListener * This overload sends it to the global chat. */ public static void sendSystemMessageToChat(String msg) { - DiscordPlugin.sendMessageToChannel(DiscordPlugin.chatchannel, DiscordPlugin.sanitizeString(msg)); - for (LastMsgData data : lastmsgPerUser) - DiscordPlugin.sendMessageToChannel(data.channel, DiscordPlugin.sanitizeString(msg)); + forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, DPUtils.sanitizeString(msg))); } public static void sendSystemMessageToChat(TBMCSystemChatEvent event) { + forAllowedMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, DPUtils.sanitizeString(event.getMessage())), + event); + } + + public static void forAllMCChat(Consumer action) { + action.accept(DiscordPlugin.chatchannel); + for (LastMsgData data : lastmsgPerUser) + action.accept(data.channel); + } + + private static void forAllowedMCChat(Consumer action, TBMCSystemChatEvent event) { if (Channel.GlobalChat.ID.equals(event.getChannel().ID)) - DiscordPlugin.sendMessageToChannel(DiscordPlugin.chatchannel, - DiscordPlugin.sanitizeString(event.getMessage())); + action.accept(DiscordPlugin.chatchannel); for (LastMsgData data : lastmsgPerUser) if (event.shouldSendTo(getSender(data.channel, data.user, data.dp))) - DiscordPlugin.sendMessageToChannel(data.channel, DiscordPlugin.sanitizeString(event.getMessage())); + action.accept(data.channel); } @Override // Discord @@ -257,7 +265,7 @@ public class MCChatListener implements Listener, IListener boolean react = false; if (dmessage.startsWith("/")) { // Ingame command - DiscordPlugin.perform(() -> { + DPUtils.perform(() -> { if (!event.getMessage().isDeleted() && !event.getChannel().isPrivate()) event.getMessage().delete(); }); @@ -308,7 +316,7 @@ public class MCChatListener implements Listener, IListener } else dsender.setMcchannel(Channel.GlobalChat); dsender.sendMessage("You're now talking in: " - + DiscordPlugin.sanitizeString(dsender.getMcchannel().DisplayName)); + + DPUtils.sanitizeString(dsender.getMcchannel().DisplayName)); } else { // Send single message sendChatMessage.accept(chc, cmd.substring(spi + 1)); react = true; @@ -333,12 +341,12 @@ public class MCChatListener implements Listener, IListener try { final IReaction reaction = m.getReactionByEmoji(DiscordPlugin.DELIVERED_REACTION); if (reaction != null) - DiscordPlugin.perform(() -> m.removeReaction(DiscordPlugin.dc.getOurUser(), reaction)); + DPUtils.perform(() -> m.removeReaction(DiscordPlugin.dc.getOurUser(), reaction)); } catch (Exception e) { TBMCCoreAPI.SendException("An error occured while removing reactions from chat!", e); } }); - DiscordPlugin.performNoWait(() -> event.getMessage().addReaction(DiscordPlugin.DELIVERED_REACTION)); + DPUtils.performNoWait(() -> event.getMessage().addReaction(DiscordPlugin.DELIVERED_REACTION)); } } catch (Exception e) { TBMCCoreAPI.SendException("An error occured while handling message \"" + dmessage + "\"!", e); diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java index 0ee2a35..57a4ba2 100644 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCListener.java @@ -23,6 +23,8 @@ import org.bukkit.plugin.RegisteredListener; import com.earth2me.essentials.CommandSource; +import buttondevteam.discordplugin.ChromaBot; +import buttondevteam.discordplugin.DPUtils; import buttondevteam.discordplugin.DiscordConnectedPlayer; import buttondevteam.discordplugin.DiscordPlayer; import buttondevteam.discordplugin.DiscordPlayerSender; @@ -71,7 +73,7 @@ public class MCListener implements Listener { if (!DiscordPlugin.hooked) MCChatListener.sendSystemMessageToChat(e.GetPlayer().PlayerName().get() + " joined the game"); MCChatListener.ListC = 0; - DiscordPlugin.updatePlayerList(); + ChromaBot.getInstance().updatePlayerList(); } @EventHandler(priority = EventPriority.HIGHEST) @@ -86,7 +88,8 @@ public class MCListener implements Listener { .ifPresent(dcp -> callEventExcludingSome(new PlayerJoinEvent(dcp, "")))); if (!DiscordPlugin.hooked) MCChatListener.sendSystemMessageToChat(e.GetPlayer().PlayerName().get() + " left the game"); - Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, DiscordPlugin::updatePlayerList, 5); + Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, + ChromaBot.getInstance()::updatePlayerList, 5); } @EventHandler @@ -115,7 +118,7 @@ public class MCListener implements Listener { public void onPlayerAFK(AfkStatusChangeEvent e) { if (e.isCancelled() || !e.getAffected().getBase().isOnline()) return; - MCChatListener.sendSystemMessageToChat(DiscordPlugin.sanitizeString(e.getAffected().getBase().getDisplayName()) + MCChatListener.sendSystemMessageToChat(DPUtils.sanitizeString(e.getAffected().getBase().getDisplayName()) + " is " + (e.getValue() ? "now" : "no longer") + " AFK."); } @@ -127,7 +130,7 @@ public class MCListener implements Listener { @EventHandler public void onPlayerMute(MuteStatusChangeEvent e) { try { - DiscordPlugin.performNoWait(() -> { + DPUtils.performNoWait(() -> { final IRole role = DiscordPlugin.dc.getRoleByID(164090010461667328L); final CommandSource source = e.getAffected().getSource(); if (!source.isPlayer()) From 6fc92d5083402dadde6d08ecaca50971dbf3122e Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Thu, 30 Nov 2017 22:15:34 +0100 Subject: [PATCH 6/6] Made smaller API changes --- .../discordplugin/ChromaBot.java | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/main/java/buttondevteam/discordplugin/ChromaBot.java b/src/main/java/buttondevteam/discordplugin/ChromaBot.java index de4b70c..0a4507a 100644 --- a/src/main/java/buttondevteam/discordplugin/ChromaBot.java +++ b/src/main/java/buttondevteam/discordplugin/ChromaBot.java @@ -5,6 +5,7 @@ import java.util.Arrays; import java.util.stream.Collectors; import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitScheduler; import buttondevteam.discordplugin.listeners.MCChatListener; @@ -79,7 +80,7 @@ public class ChromaBot { * @param color * The color of the line before the text */ - public void sendFancyMessage(String message, Color color) { + public void sendMessage(String message, Color color) { MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, new EmbedBuilder().withTitle(message).withColor(color).build())); } @@ -94,7 +95,7 @@ public class ChromaBot { * @param mcauthor * The name of the Minecraft player who is the author of this message */ - public void sendFancyMessage(String message, Color color, String mcauthor) { + public void sendMessage(String message, Color color, String mcauthor) { MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, DPUtils.embedWithHead(new EmbedBuilder().withTitle(message).withColor(color), mcauthor).build())); } @@ -111,11 +112,26 @@ public class ChromaBot { * @param authorimg * The URL of the avatar image for this message's author */ - public void sendFancyMessage(String message, Color color, String authorname, String authorimg) { + public void sendMessage(String message, Color color, String authorname, String authorimg) { MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, new EmbedBuilder() .withTitle(message).withColor(color).withAuthorName(authorname).withAuthorIcon(authorimg).build())); } + /** + * Send a message to the chat channel. This will show a bold text with a colored line. + * + * @param message + * The message to send, duh + * @param color + * The color of the line before the text + * @param sender + * The player who sends this message + */ + public void sendMessage(String message, Color color, Player sender) { + MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, DPUtils + .embedWithHead(new EmbedBuilder().withTitle(message).withColor(color), sender.getName()).build())); + } + public void updatePlayerList() { DPUtils.performNoWait(() -> { String[] s = DiscordPlugin.chatchannel.getTopic().split("\\n----\\n");