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/pom.xml b/pom.xml
index d2d1e7b..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
@@ -210,5 +210,13 @@
+
+
+ org.objenesis
+ objenesis
+ 2.6
+ test
+
+
diff --git a/src/main/java/buttondevteam/discordplugin/ChromaBot.java b/src/main/java/buttondevteam/discordplugin/ChromaBot.java
new file mode 100644
index 0000000..0a4507a
--- /dev/null
+++ b/src/main/java/buttondevteam/discordplugin/ChromaBot.java
@@ -0,0 +1,147 @@
+package buttondevteam.discordplugin;
+
+import java.awt.Color;
+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;
+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. Initialization happens after the server is done loading (using {@link BukkitScheduler#runTaskAsynchronously(org.bukkit.plugin.Plugin, Runnable)})
+ */
+ 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 sendMessage(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 sendMessage(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 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");
+ 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 e2d22e2..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,22 +31,30 @@ 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;
+ static Thread mainThread;
public static IDiscordClient dc;
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...");
+ 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");
@@ -57,6 +63,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);
@@ -121,14 +128,16 @@ 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());
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
@@ -159,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())
@@ -205,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) {
@@ -313,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) {
@@ -325,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() {
@@ -344,66 +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;
- 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;
- 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/PlayerListWatcher.java b/src/main/java/buttondevteam/discordplugin/PlayerListWatcher.java
new file mode 100644
index 0000000..365e1be
--- /dev/null
+++ b/src/main/java/buttondevteam/discordplugin/PlayerListWatcher.java
@@ -0,0 +1,375 @@
+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.craftbukkit.v1_12_R1.util.CraftChatMessage;
+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.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;
+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.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;
+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
+ }
+
+ 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) { // 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() {
+ 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);
+ 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);
+ }
+ }
+
+ public void a(EntityHuman entityhuman, IChatBaseComponent ichatbasecomponent) {
+ plist.a(entityhuman, ichatbasecomponent);
+ }
+
+ 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 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();
+ }
+
+ public ServerStatisticManager getStatisticManager(EntityPlayer entityhuman) {
+ return plist.getStatisticManager(entityhuman);
+ }
+}
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 6f1bf9a..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;
@@ -68,9 +70,10 @@ 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();
+ ChromaBot.getInstance().updatePlayerList();
}
@EventHandler(priority = EventPriority.HIGHEST)
@@ -83,8 +86,10 @@ 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");
- Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, DiscordPlugin::updatePlayerList, 5);
+ if (!DiscordPlugin.hooked)
+ MCChatListener.sendSystemMessageToChat(e.GetPlayer().PlayerName().get() + " left the game");
+ Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin,
+ ChromaBot.getInstance()::updatePlayerList, 5);
}
@EventHandler
@@ -105,14 +110,15 @@ 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
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.");
}
@@ -124,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())