Merge pull request #86 from TBMCPlugins/dev
Reorganized lots of stuff (components)
This commit is contained in:
commit
db743dcd50
31 changed files with 1159 additions and 873 deletions
35
pom.xml
35
pom.xml
|
@ -106,6 +106,9 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<branch>
|
||||||
|
master
|
||||||
|
</branch> <!-- Should be master if building ButtonCore locally - the CI will overwrite it (see below) -->
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
|
@ -159,11 +162,16 @@
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/com.discord4j/Discord4J -->
|
<!-- https://mvnrepository.com/artifact/com.discord4j/Discord4J -->
|
||||||
<dependency>
|
<!-- <dependency>
|
||||||
<groupId>com.discord4j</groupId>
|
<groupId>com.discord4j</groupId>
|
||||||
<artifactId>Discord4J</artifactId>
|
<artifactId>Discord4J</artifactId>
|
||||||
<version>2.10.1</version>
|
<version>2.10.1</version>
|
||||||
</dependency>
|
</dependency> -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.SizableShrimp</groupId>
|
||||||
|
<artifactId>Discord4J</artifactId>
|
||||||
|
<version>httprequestchange-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-jdk14 -->
|
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-jdk14 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
|
@ -173,7 +181,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.TBMCPlugins.ButtonCore</groupId>
|
<groupId>com.github.TBMCPlugins.ButtonCore</groupId>
|
||||||
<artifactId>ButtonCore</artifactId>
|
<artifactId>ButtonCore</artifactId>
|
||||||
<version>master-SNAPSHOT</version>
|
<version>${branch}-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -225,4 +233,19 @@
|
||||||
<version>4.0.0</version>
|
<version>4.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>ci</id>
|
||||||
|
<activation>
|
||||||
|
<property>
|
||||||
|
<name>env.TRAVIS_BRANCH</name>
|
||||||
|
</property>
|
||||||
|
</activation>
|
||||||
|
<properties>
|
||||||
|
<!-- Override only if necessary -->
|
||||||
|
<branch>${env.TRAVIS_BRANCH}</branch>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package buttondevteam.discordplugin;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.bukkit.event.Cancellable;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AsyncDiscordEvent<T extends sx.blah.discord.api.events.Event> extends Event implements Cancellable {
|
||||||
|
private final @Getter T event;
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private boolean cancelled;
|
||||||
|
|
||||||
|
private static final HandlerList handlers = new HandlerList();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,7 @@
|
||||||
package buttondevteam.discordplugin;
|
package buttondevteam.discordplugin;
|
||||||
|
|
||||||
import buttondevteam.discordplugin.listeners.MCChatListener;
|
import buttondevteam.discordplugin.mcchat.MCChatUtils;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.scheduler.BukkitScheduler;
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
import sx.blah.discord.api.internal.json.objects.EmbedObject;
|
import sx.blah.discord.api.internal.json.objects.EmbedObject;
|
||||||
|
@ -11,8 +10,6 @@ import sx.blah.discord.util.EmbedBuilder;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class ChromaBot {
|
public class ChromaBot {
|
||||||
/**
|
/**
|
||||||
|
@ -43,7 +40,7 @@ public class ChromaBot {
|
||||||
* The message to send, duh
|
* The message to send, duh
|
||||||
*/
|
*/
|
||||||
public void sendMessage(String message) {
|
public void sendMessage(String message) {
|
||||||
MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message));
|
MCChatUtils.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,7 +52,7 @@ public class ChromaBot {
|
||||||
* Custom fancy stuff, use {@link EmbedBuilder} to create one
|
* Custom fancy stuff, use {@link EmbedBuilder} to create one
|
||||||
*/
|
*/
|
||||||
public void sendMessage(String message, EmbedObject embed) {
|
public void sendMessage(String message, EmbedObject embed) {
|
||||||
MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, embed));
|
MCChatUtils.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, embed));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,7 +63,7 @@ public class ChromaBot {
|
||||||
* @param toggle The toggle type for channelcon
|
* @param toggle The toggle type for channelcon
|
||||||
*/
|
*/
|
||||||
public void sendMessageCustomAsWell(String message, EmbedObject embed, @Nullable ChannelconBroadcast toggle) {
|
public void sendMessageCustomAsWell(String message, EmbedObject embed, @Nullable ChannelconBroadcast toggle) {
|
||||||
MCChatListener.forCustomAndAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, embed), toggle, false);
|
MCChatUtils.forCustomAndAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, embed), toggle, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,7 +89,7 @@ public class ChromaBot {
|
||||||
* The color of the line before the text
|
* The color of the line before the text
|
||||||
*/
|
*/
|
||||||
public void sendMessage(String message, Color color) {
|
public void sendMessage(String message, Color color) {
|
||||||
MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message,
|
MCChatUtils.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message,
|
||||||
new EmbedBuilder().withTitle(message).withColor(color).build()));
|
new EmbedBuilder().withTitle(message).withColor(color).build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +104,7 @@ public class ChromaBot {
|
||||||
* The name of the Minecraft player who is the author of this message
|
* The name of the Minecraft player who is the author of this message
|
||||||
*/
|
*/
|
||||||
public void sendMessage(String message, Color color, String mcauthor) {
|
public void sendMessage(String message, Color color, String mcauthor) {
|
||||||
MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message,
|
MCChatUtils.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message,
|
||||||
DPUtils.embedWithHead(new EmbedBuilder().withTitle(message).withColor(color), mcauthor).build()));
|
DPUtils.embedWithHead(new EmbedBuilder().withTitle(message).withColor(color), mcauthor).build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +121,7 @@ public class ChromaBot {
|
||||||
* The URL of the avatar image for this message's author
|
* The URL of the avatar image for this message's author
|
||||||
*/
|
*/
|
||||||
public void sendMessage(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()
|
MCChatUtils.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, new EmbedBuilder()
|
||||||
.withTitle(message).withColor(color).withAuthorName(authorname).withAuthorIcon(authorimg).build()));
|
.withTitle(message).withColor(color).withAuthorName(authorname).withAuthorIcon(authorimg).build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,20 +136,11 @@ public class ChromaBot {
|
||||||
* The player who sends this message
|
* The player who sends this message
|
||||||
*/
|
*/
|
||||||
public void sendMessage(String message, Color color, Player sender) {
|
public void sendMessage(String message, Color color, Player sender) {
|
||||||
MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, DPUtils
|
MCChatUtils.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, message, DPUtils
|
||||||
.embedWithHead(new EmbedBuilder().withTitle(message).withColor(color), sender.getName()).build()));
|
.embedWithHead(new EmbedBuilder().withTitle(message).withColor(color), sender.getName()).build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updatePlayerList() {
|
public void updatePlayerList() {
|
||||||
DPUtils.performNoWait(() -> {
|
MCChatUtils.updatePlayerList();
|
||||||
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")));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import sx.blah.discord.util.RequestBuffer.IVoidRequest;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.logging.Logger;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
public final class DPUtils {
|
public final class DPUtils {
|
||||||
|
@ -96,4 +97,10 @@ public final class DPUtils {
|
||||||
return message.replaceAll("([*_~])", Matcher.quoteReplacement("\\")+"$1");
|
return message.replaceAll("([*_~])", Matcher.quoteReplacement("\\")+"$1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Logger getLogger() {
|
||||||
|
if (DiscordPlugin.plugin == null || DiscordPlugin.plugin.getLogger() == null)
|
||||||
|
return Logger.getLogger("DiscordPlugin");
|
||||||
|
return DiscordPlugin.plugin.getLogger();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package buttondevteam.discordplugin;
|
package buttondevteam.discordplugin;
|
||||||
|
|
||||||
import buttondevteam.discordplugin.listeners.MCChatListener;
|
import buttondevteam.discordplugin.mcchat.MCChatPrivate;
|
||||||
import buttondevteam.lib.player.ChromaGamerBase;
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
import buttondevteam.lib.player.UserClass;
|
import buttondevteam.lib.player.UserClass;
|
||||||
|
|
||||||
|
@ -20,9 +20,9 @@ public class DiscordPlayer extends ChromaGamerBase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if player has the private Minecraft chat enabled. For setting the value, see
|
* Returns true if player has the private Minecraft chat enabled. For setting the value, see
|
||||||
* {@link MCChatListener#privateMCChat(sx.blah.discord.handle.obj.IChannel, boolean, sx.blah.discord.handle.obj.IUser, DiscordPlayer)}
|
* {@link MCChatPrivate#privateMCChat(sx.blah.discord.handle.obj.IChannel, boolean, sx.blah.discord.handle.obj.IUser, DiscordPlayer)}
|
||||||
*/
|
*/
|
||||||
public boolean isMinecraftChatEnabled() {
|
public boolean isMinecraftChatEnabled() {
|
||||||
return MCChatListener.isMinecraftChatEnabled(this);
|
return MCChatPrivate.isMinecraftChatEnabled(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
package buttondevteam.discordplugin;
|
package buttondevteam.discordplugin;
|
||||||
|
|
||||||
|
import buttondevteam.discordplugin.broadcaster.GeneralEventBroadcasterModule;
|
||||||
import buttondevteam.discordplugin.commands.DiscordCommandBase;
|
import buttondevteam.discordplugin.commands.DiscordCommandBase;
|
||||||
import buttondevteam.discordplugin.listeners.CommandListener;
|
import buttondevteam.discordplugin.exceptions.ExceptionListenerModule;
|
||||||
import buttondevteam.discordplugin.listeners.ExceptionListener;
|
import buttondevteam.discordplugin.listeners.CommonListeners;
|
||||||
import buttondevteam.discordplugin.listeners.MCChatListener;
|
|
||||||
import buttondevteam.discordplugin.listeners.MCListener;
|
import buttondevteam.discordplugin.listeners.MCListener;
|
||||||
|
import buttondevteam.discordplugin.mcchat.*;
|
||||||
import buttondevteam.discordplugin.mccommands.DiscordMCCommandBase;
|
import buttondevteam.discordplugin.mccommands.DiscordMCCommandBase;
|
||||||
import buttondevteam.discordplugin.mccommands.ResetMCCommand;
|
import buttondevteam.discordplugin.mccommands.ResetMCCommand;
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
|
import buttondevteam.lib.architecture.ButtonPlugin;
|
||||||
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import buttondevteam.lib.architecture.ConfigData;
|
||||||
import buttondevteam.lib.chat.Channel;
|
import buttondevteam.lib.chat.Channel;
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||||
import buttondevteam.lib.player.ChromaGamerBase;
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
|
@ -20,9 +24,7 @@ import lombok.val;
|
||||||
import net.milkbowl.vault.permission.Permission;
|
import net.milkbowl.vault.permission.Permission;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
|
||||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
import sx.blah.discord.api.ClientBuilder;
|
import sx.blah.discord.api.ClientBuilder;
|
||||||
import sx.blah.discord.api.IDiscordClient;
|
import sx.blah.discord.api.IDiscordClient;
|
||||||
|
@ -44,29 +46,28 @@ import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class DiscordPlugin extends JavaPlugin implements IListener<ReadyEvent> {
|
public class DiscordPlugin extends ButtonPlugin implements IListener<ReadyEvent> {
|
||||||
private static final String SubredditURL = "https://www.reddit.com/r/ChromaGamers";
|
private static final String SubredditURL = "https://www.reddit.com/r/ChromaGamers";
|
||||||
private static boolean stop = false;
|
private static boolean stop = false;
|
||||||
public static IDiscordClient dc;
|
public static IDiscordClient dc;
|
||||||
public static DiscordPlugin plugin;
|
public static DiscordPlugin plugin;
|
||||||
public static boolean SafeMode = true;
|
public static boolean SafeMode = true;
|
||||||
public static List<String> GameRoles;
|
public static List<String> GameRoles;
|
||||||
public static boolean hooked = false;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
public ConfigData<Character> Prefix() {
|
||||||
|
return getData("prefix", '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static char getPrefix() {
|
||||||
|
if (plugin == null) return '/';
|
||||||
|
return plugin.Prefix().get();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void pluginEnable() {
|
||||||
stop = false; //If not the first time
|
stop = false; //If not the first time
|
||||||
try {
|
try {
|
||||||
Bukkit.getLogger().info("Initializing DiscordPlugin...");
|
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;
|
plugin = this;
|
||||||
lastannouncementtime = getConfig().getLong("lastannouncementtime");
|
lastannouncementtime = getConfig().getLong("lastannouncementtime");
|
||||||
lastseentime = getConfig().getLong("lastseentime");
|
lastseentime = getConfig().getLong("lastseentime");
|
||||||
|
@ -156,7 +157,7 @@ public class DiscordPlugin extends JavaPlugin implements IListener<ReadyEvent> {
|
||||||
val toggles = chcon.getInt("toggles");
|
val toggles = chcon.getInt("toggles");
|
||||||
if (!mcch.isPresent() || ch == null || user == null || groupid == null)
|
if (!mcch.isPresent() || ch == null || user == null || groupid == null)
|
||||||
continue;
|
continue;
|
||||||
MCChatListener.addCustomChat(ch, groupid, mcch.get(), user, dcp, toggles);
|
MCChatCustom.addCustomChat(ch, groupid, mcch.get(), user, dcp, toggles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,21 +213,16 @@ public class DiscordPlugin extends JavaPlugin implements IListener<ReadyEvent> {
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
}, 0, 10);
|
}, 0, 10);
|
||||||
for (IListener<?> listener : CommandListener.getListeners())
|
for (IListener<?> listener : CommonListeners.getListeners())
|
||||||
dc.getDispatcher().registerListener(listener);
|
dc.getDispatcher().registerListener(listener);
|
||||||
MCChatListener mcchat = new MCChatListener();
|
Component.registerComponent(this, new GeneralEventBroadcasterModule());
|
||||||
dc.getDispatcher().registerListener(mcchat);
|
Component.registerComponent(this, new MinecraftChatModule());
|
||||||
TBMCCoreAPI.RegisterEventsForExceptions(mcchat, this);
|
Component.registerComponent(this, new ExceptionListenerModule());
|
||||||
Bukkit.getPluginManager().registerEvents(new ExceptionListener(), this);
|
|
||||||
TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(), this);
|
TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(), this);
|
||||||
TBMCChatAPI.AddCommands(this, DiscordMCCommandBase.class);
|
TBMCChatAPI.AddCommands(this, DiscordMCCommandBase.class);
|
||||||
TBMCCoreAPI.RegisterUserClass(DiscordPlayer.class);
|
TBMCCoreAPI.RegisterUserClass(DiscordPlayer.class);
|
||||||
ChromaGamerBase.addConverter(sender -> {
|
ChromaGamerBase.addConverter(sender -> Optional.ofNullable(sender instanceof DiscordSenderBase
|
||||||
//System.out.println("Discord converter queried: "+sender+" "+sender.getName()); - TODO: Remove
|
? ((DiscordSenderBase) sender).getChromaUser() : null));
|
||||||
//System.out.println(((DiscordSenderBase) sender).getChromaUser().channel().get().ID); //TODO: TMP
|
|
||||||
return Optional.ofNullable(sender instanceof DiscordSenderBase
|
|
||||||
? ((DiscordSenderBase) sender).getChromaUser() : null);
|
|
||||||
});
|
|
||||||
new Thread(this::AnnouncementGetterThreadMethod).start();
|
new Thread(this::AnnouncementGetterThreadMethod).start();
|
||||||
setupProviders();
|
setupProviders();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -248,17 +244,14 @@ public class DiscordPlugin extends JavaPlugin implements IListener<ReadyEvent> {
|
||||||
public static boolean Restart;
|
public static boolean Restart;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void pluginDisable() {
|
||||||
stop = true;
|
stop = true;
|
||||||
for (val entry : MCChatListener.ConnectedSenders.entrySet())
|
MCChatPrivate.logoutAll();
|
||||||
for (val valueEntry : entry.getValue().entrySet())
|
|
||||||
MCListener.callEventExcludingSome(new PlayerQuitEvent(valueEntry.getValue(), ""));
|
|
||||||
MCChatListener.ConnectedSenders.clear();
|
|
||||||
getConfig().set("lastannouncementtime", lastannouncementtime);
|
getConfig().set("lastannouncementtime", lastannouncementtime);
|
||||||
getConfig().set("lastseentime", lastseentime);
|
getConfig().set("lastseentime", lastseentime);
|
||||||
getConfig().set("serverup", false);
|
getConfig().set("serverup", false);
|
||||||
|
|
||||||
val chcons = MCChatListener.getCustomChats();
|
val chcons = MCChatCustom.getCustomChats();
|
||||||
val chconsc = getConfig().createSection("chcons");
|
val chconsc = getConfig().createSection("chcons");
|
||||||
for (val chcon : chcons) {
|
for (val chcon : chcons) {
|
||||||
val chconc = chconsc.createSection(chcon.channel.getStringID());
|
val chconc = chconsc.createSection(chcon.channel.getStringID());
|
||||||
|
@ -287,7 +280,7 @@ public class DiscordPlugin extends JavaPlugin implements IListener<ReadyEvent> {
|
||||||
+ "kicked the hell out.") //TODO: Make configurable
|
+ "kicked the hell out.") //TODO: Make configurable
|
||||||
: "") //If 'restart' is disabled then this isn't shown even if joinleave is enabled
|
: "") //If 'restart' is disabled then this isn't shown even if joinleave is enabled
|
||||||
.build();
|
.build();
|
||||||
MCChatListener.forCustomAndAllMCChat(ch -> {
|
MCChatUtils.forCustomAndAllMCChat(ch -> {
|
||||||
try {
|
try {
|
||||||
DiscordPlugin.sendMessageToChannelWait(ch, "",
|
DiscordPlugin.sendMessageToChannelWait(ch, "",
|
||||||
embed, 5, TimeUnit.SECONDS);
|
embed, 5, TimeUnit.SECONDS);
|
||||||
|
@ -299,16 +292,6 @@ public class DiscordPlugin extends JavaPlugin implements IListener<ReadyEvent> {
|
||||||
try {
|
try {
|
||||||
SafeMode = true; // Stop interacting with Discord
|
SafeMode = true; // Stop interacting with Discord
|
||||||
MCChatListener.stop(true);
|
MCChatListener.stop(true);
|
||||||
try {
|
|
||||||
if (PlayerListWatcher.hookDown())
|
|
||||||
System.out.println("Finished unhooking the player list!");
|
|
||||||
else
|
|
||||||
System.out.println("Didn't have the player list hooked.");
|
|
||||||
hooked = false;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
Bukkit.getLogger().warning("Couldn't unhook the player list!");
|
|
||||||
}
|
|
||||||
ChromaBot.delete();
|
ChromaBot.delete();
|
||||||
dc.changePresence(StatusType.IDLE, ActivityType.PLAYING, "Chromacraft"); //No longer using the same account for testing
|
dc.changePresence(StatusType.IDLE, ActivityType.PLAYING, "Chromacraft"); //No longer using the same account for testing
|
||||||
dc.logout();
|
dc.logout();
|
||||||
|
@ -424,7 +407,7 @@ public class DiscordPlugin extends JavaPlugin implements IListener<ReadyEvent> {
|
||||||
.warning("Message was too long to send to discord and got truncated. In " + channel.getName());
|
.warning("Message was too long to send to discord and got truncated. In " + channel.getName());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
MCChatListener.resetLastMessage(channel); // If this is a chat message, it'll be set again
|
MCChatUtils.resetLastMessage(channel); // If this is a chat message, it'll be set again
|
||||||
final String content = message;
|
final String content = message;
|
||||||
RequestBuffer.IRequest<IMessage> r = () -> embed == null ? channel.sendMessage(content)
|
RequestBuffer.IRequest<IMessage> r = () -> embed == null ? channel.sendMessage(content)
|
||||||
: channel.sendMessage(content, embed, false);
|
: channel.sendMessage(content, embed, false);
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package buttondevteam.discordplugin;
|
package buttondevteam.discordplugin;
|
||||||
|
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
import buttondevteam.lib.chat.IDiscordSender;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
import sx.blah.discord.handle.obj.IChannel;
|
import sx.blah.discord.handle.obj.IChannel;
|
||||||
import sx.blah.discord.handle.obj.IUser;
|
import sx.blah.discord.handle.obj.IUser;
|
||||||
|
|
||||||
public abstract class DiscordSenderBase implements IDiscordSender {
|
public abstract class DiscordSenderBase implements CommandSender {
|
||||||
/**
|
/**
|
||||||
* May be null.
|
* May be null.
|
||||||
*/
|
*/
|
||||||
|
@ -51,6 +51,7 @@ public abstract class DiscordSenderBase implements IDiscordSender {
|
||||||
public void sendMessage(String message) {
|
public void sendMessage(String message) {
|
||||||
try {
|
try {
|
||||||
final boolean broadcast = new Exception().getStackTrace()[2].getMethodName().contains("broadcast");
|
final boolean broadcast = new Exception().getStackTrace()[2].getMethodName().contains("broadcast");
|
||||||
|
//if (broadcast && DiscordPlugin.hooked) - TODO: What should happen if unhooked
|
||||||
if (broadcast)
|
if (broadcast)
|
||||||
return;
|
return;
|
||||||
final String sendmsg = DPUtils.sanitizeString(message);
|
final String sendmsg = DPUtils.sanitizeString(message);
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package buttondevteam.discordplugin.broadcaster;
|
||||||
|
|
||||||
|
import buttondevteam.discordplugin.DPUtils;
|
||||||
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
|
public class GeneralEventBroadcasterModule extends Component {
|
||||||
|
private static @Getter boolean hooked = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void enable() {
|
||||||
|
try {
|
||||||
|
PlayerListWatcher.hookUp();
|
||||||
|
Bukkit.getLogger().info("Finished hooking into the player list");
|
||||||
|
hooked = true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
TBMCCoreAPI.SendException("Error while hacking the player list!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void disable() {
|
||||||
|
try {
|
||||||
|
if (PlayerListWatcher.hookDown())
|
||||||
|
DPUtils.getLogger().info("Finished unhooking the player list!");
|
||||||
|
else
|
||||||
|
DPUtils.getLogger().info("Didn't have the player list hooked.");
|
||||||
|
hooked = false;
|
||||||
|
} catch (Exception e) {
|
||||||
|
TBMCCoreAPI.SendException("Error while hacking the player list!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package buttondevteam.discordplugin;
|
package buttondevteam.discordplugin.broadcaster;
|
||||||
|
|
||||||
import buttondevteam.discordplugin.listeners.MCChatListener;
|
import buttondevteam.discordplugin.mcchat.MCChatUtils;
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
|
@ -30,7 +30,7 @@ public class PlayerListWatcher extends DedicatedPlayerList {
|
||||||
if (packet instanceof PacketPlayOutChat) {
|
if (packet instanceof PacketPlayOutChat) {
|
||||||
Field msgf = PacketPlayOutChat.class.getDeclaredField("a");
|
Field msgf = PacketPlayOutChat.class.getDeclaredField("a");
|
||||||
msgf.setAccessible(true);
|
msgf.setAccessible(true);
|
||||||
MCChatListener.forAllMCChat(MCChatListener.send(((IChatBaseComponent) msgf.get(packet)).toPlainText()));
|
MCChatUtils.forAllMCChat(MCChatUtils.send(((IChatBaseComponent) msgf.get(packet)).toPlainText()));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
TBMCCoreAPI.SendException("Failed to broadcast message sent to all players - hacking failed.", e);
|
TBMCCoreAPI.SendException("Failed to broadcast message sent to all players - hacking failed.", e);
|
||||||
|
@ -53,52 +53,43 @@ public class PlayerListWatcher extends DedicatedPlayerList {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(IChatBaseComponent[] iChatBaseComponents) { // Needed so it calls the overriden method
|
public void sendMessage(IChatBaseComponent[] iChatBaseComponents) { // Needed so it calls the overridden method
|
||||||
for (IChatBaseComponent component : iChatBaseComponents) {
|
for (IChatBaseComponent component : iChatBaseComponents) {
|
||||||
sendMessage(component, true);
|
sendMessage(component, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void hookUp() {
|
static void hookUp() throws Exception {
|
||||||
try {
|
Field conf = CraftServer.class.getDeclaredField("console");
|
||||||
Field conf = CraftServer.class.getDeclaredField("console");
|
conf.setAccessible(true);
|
||||||
conf.setAccessible(true);
|
val server = (MinecraftServer) conf.get(Bukkit.getServer());
|
||||||
val server = (MinecraftServer) conf.get(Bukkit.getServer());
|
val plw = new ObjenesisStd().newInstance(PlayerListWatcher.class); // Cannot call super constructor
|
||||||
val plw = new ObjenesisStd().newInstance(PlayerListWatcher.class); // Cannot call super constructor
|
plw.plist = (DedicatedPlayerList) server.getPlayerList();
|
||||||
plw.plist = (DedicatedPlayerList) server.getPlayerList();
|
plw.maxPlayers = plw.plist.getMaxPlayers();
|
||||||
plw.maxPlayers = plw.plist.getMaxPlayers();
|
Field plf = plw.getClass().getField("players");
|
||||||
Field plf = plw.getClass().getField("players");
|
plf.setAccessible(true);
|
||||||
plf.setAccessible(true);
|
Field modf = plf.getClass().getDeclaredField("modifiers");
|
||||||
Field modf = plf.getClass().getDeclaredField("modifiers");
|
modf.setAccessible(true);
|
||||||
modf.setAccessible(true);
|
modf.set(plf, plf.getModifiers() & ~Modifier.FINAL);
|
||||||
modf.set(plf, plf.getModifiers() & ~Modifier.FINAL);
|
plf.set(plw, plw.plist.players);
|
||||||
plf.set(plw, plw.plist.players);
|
server.a(plw);
|
||||||
server.a(plw);
|
Field pllf = CraftServer.class.getDeclaredField("playerList");
|
||||||
Field pllf = CraftServer.class.getDeclaredField("playerList");
|
pllf.setAccessible(true);
|
||||||
pllf.setAccessible(true);
|
pllf.set(Bukkit.getServer(), plw);
|
||||||
pllf.set(Bukkit.getServer(), plw);
|
|
||||||
} catch (Exception e) {
|
|
||||||
TBMCCoreAPI.SendException("Error while hacking the player list!", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hookDown() {
|
static boolean hookDown() throws Exception {
|
||||||
try {
|
Field conf = CraftServer.class.getDeclaredField("console");
|
||||||
Field conf = CraftServer.class.getDeclaredField("console");
|
conf.setAccessible(true);
|
||||||
conf.setAccessible(true);
|
val server = (MinecraftServer) conf.get(Bukkit.getServer());
|
||||||
val server = (MinecraftServer) conf.get(Bukkit.getServer());
|
val plist = (DedicatedPlayerList) server.getPlayerList();
|
||||||
val plist = (DedicatedPlayerList) server.getPlayerList();
|
if (!(plist instanceof PlayerListWatcher))
|
||||||
if (!(plist instanceof PlayerListWatcher))
|
return false;
|
||||||
return false;
|
server.a(((PlayerListWatcher) plist).plist);
|
||||||
server.a(((PlayerListWatcher) plist).plist);
|
Field pllf = CraftServer.class.getDeclaredField("playerList");
|
||||||
Field pllf = CraftServer.class.getDeclaredField("playerList");
|
pllf.setAccessible(true);
|
||||||
pllf.setAccessible(true);
|
pllf.set(Bukkit.getServer(), ((PlayerListWatcher) plist).plist);
|
||||||
pllf.set(Bukkit.getServer(), ((PlayerListWatcher) plist).plist);
|
return true;
|
||||||
return true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
TBMCCoreAPI.SendException("Error while hacking the player list!", e);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void a(EntityHuman entityhuman, IChatBaseComponent ichatbasecomponent) {
|
public void a(EntityHuman entityhuman, IChatBaseComponent ichatbasecomponent) {
|
|
@ -3,7 +3,8 @@ package buttondevteam.discordplugin.commands;
|
||||||
import buttondevteam.discordplugin.ChannelconBroadcast;
|
import buttondevteam.discordplugin.ChannelconBroadcast;
|
||||||
import buttondevteam.discordplugin.DiscordConnectedPlayer;
|
import buttondevteam.discordplugin.DiscordConnectedPlayer;
|
||||||
import buttondevteam.discordplugin.DiscordPlayer;
|
import buttondevteam.discordplugin.DiscordPlayer;
|
||||||
import buttondevteam.discordplugin.listeners.MCChatListener;
|
import buttondevteam.discordplugin.DiscordPlugin;
|
||||||
|
import buttondevteam.discordplugin.mcchat.MCChatCustom;
|
||||||
import buttondevteam.lib.chat.Channel;
|
import buttondevteam.lib.chat.Channel;
|
||||||
import buttondevteam.lib.player.TBMCPlayer;
|
import buttondevteam.lib.player.TBMCPlayer;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
|
@ -30,16 +31,16 @@ public class ChannelconCommand extends DiscordCommandBase {
|
||||||
message.reply("you need to have manage permissions for this channel!");
|
message.reply("you need to have manage permissions for this channel!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (MCChatListener.hasCustomChat(message.getChannel())) {
|
if (MCChatCustom.hasCustomChat(message.getChannel())) {
|
||||||
if (args.toLowerCase().startsWith("remove")) {
|
if (args.toLowerCase().startsWith("remove")) {
|
||||||
if (MCChatListener.removeCustomChat(message.getChannel()))
|
if (MCChatCustom.removeCustomChat(message.getChannel()))
|
||||||
message.reply("channel connection removed.");
|
message.reply("channel connection removed.");
|
||||||
else
|
else
|
||||||
message.reply("wait what, couldn't remove channel connection.");
|
message.reply("wait what, couldn't remove channel connection.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (args.toLowerCase().startsWith("toggle")) {
|
if (args.toLowerCase().startsWith("toggle")) {
|
||||||
val cc = MCChatListener.getCustomChat(message.getChannel());
|
val cc = MCChatCustom.getCustomChat(message.getChannel());
|
||||||
Supplier<String> togglesString = () -> Arrays.stream(ChannelconBroadcast.values()).map(t -> t.toString().toLowerCase() + ": " + ((cc.toggles & t.flag) == 0 ? "disabled" : "enabled")).collect(Collectors.joining("\n"));
|
Supplier<String> togglesString = () -> Arrays.stream(ChannelconBroadcast.values()).map(t -> t.toString().toLowerCase() + ": " + ((cc.toggles & t.flag) == 0 ? "disabled" : "enabled")).collect(Collectors.joining("\n"));
|
||||||
String[] argsa = args.split(" ");
|
String[] argsa = args.split(" ");
|
||||||
if (argsa.length < 2) {
|
if (argsa.length < 2) {
|
||||||
|
@ -88,7 +89,7 @@ public class ChannelconCommand extends DiscordCommandBase {
|
||||||
message.reply("sorry, this MC chat is already connected to a different channel, multiple channels are not supported atm.");
|
message.reply("sorry, this MC chat is already connected to a different channel, multiple channels are not supported atm.");
|
||||||
return true;
|
return true;
|
||||||
}*/ //TODO: "Channel admins" that can connect channels?
|
}*/ //TODO: "Channel admins" that can connect channels?
|
||||||
MCChatListener.addCustomChat(message.getChannel(), groupid, chan.get(), message.getAuthor(), dcp, 0);
|
MCChatCustom.addCustomChat(message.getChannel(), groupid, chan.get(), message.getAuthor(), dcp, 0);
|
||||||
message.reply("alright, connection made to group `" + groupid + "`!");
|
message.reply("alright, connection made to group `" + groupid + "`!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -99,10 +100,12 @@ public class ChannelconCommand extends DiscordCommandBase {
|
||||||
"---- Channel connect ---", //
|
"---- Channel connect ---", //
|
||||||
"This command allows you to connect a Minecraft channel to a Discord channel (just like how the global chat is connected to #minecraft-chat).", //
|
"This command allows you to connect a Minecraft channel to a Discord channel (just like how the global chat is connected to #minecraft-chat).", //
|
||||||
"You need to have access to the MC channel and have manage permissions on the Discord channel.", //
|
"You need to have access to the MC channel and have manage permissions on the Discord channel.", //
|
||||||
"You also need to have your Minecraft account connected. In #bot use /connect <mcname>.", //
|
"You also need to have your Minecraft account connected. In #bot use " + DiscordPlugin.getPrefix() + "connect <mcname>.", //
|
||||||
"Call this command from the channel you want to use. Usage: @ChromaBot channelcon <mcchannel>", //
|
"Call this command from the channel you want to use.", //
|
||||||
|
"Usage: @" + DiscordPlugin.dc.getOurUser().getName() + " channelcon <mcchannel>", //
|
||||||
|
"Use the ID (command) of the channel, for example `g` for the global chat.", //
|
||||||
"To remove a connection use @ChromaBot channelcon remove in the channel.", //
|
"To remove a connection use @ChromaBot channelcon remove in the channel.", //
|
||||||
"Mentioning the bot is needed in this case because the / prefix only works in #bot.", //
|
"Mentioning the bot is needed in this case because the " + DiscordPlugin.getPrefix() + " prefix only works in #bot.", //
|
||||||
"Invite link: <https://discordapp.com/oauth2/authorize?client_id=226443037893591041&scope=bot&permissions=268509264>" //
|
"Invite link: <https://discordapp.com/oauth2/authorize?client_id=226443037893591041&scope=bot&permissions=268509264>" //
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ public class ConnectCommand extends DiscordCommandBase {
|
||||||
return false;
|
return false;
|
||||||
if (args.contains(" ")) {
|
if (args.contains(" ")) {
|
||||||
DiscordPlugin.sendMessageToChannel(message.getChannel(),
|
DiscordPlugin.sendMessageToChannel(message.getChannel(),
|
||||||
"Too many arguments.\nUsage: connect <Minecraftname>");
|
"Too many arguments.\nUsage: " + DiscordPlugin.getPrefix() + "connect <Minecraftname>");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (WaitingToConnect.inverse().containsKey(message.getAuthor().getStringID())) {
|
if (WaitingToConnect.inverse().containsKey(message.getAuthor().getStringID())) {
|
||||||
|
@ -68,8 +68,8 @@ public class ConnectCommand extends DiscordCommandBase {
|
||||||
public String[] getHelpText() {
|
public String[] getHelpText() {
|
||||||
return new String[] { //
|
return new String[] { //
|
||||||
"---- Connect command ----", //
|
"---- Connect command ----", //
|
||||||
"This commands let's you connect your acoount with a Minecraft account. This'd allow using the Minecraft chat and other things.", //
|
"This command lets you connect your account with a Minecraft account. This allows using the Minecraft chat and other things.", //
|
||||||
"Usage: connect <Minecraftname>" //
|
"Usage: /connect <Minecraftname>" //
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package buttondevteam.discordplugin.commands;
|
package buttondevteam.discordplugin.commands;
|
||||||
|
|
||||||
import buttondevteam.discordplugin.DiscordPlugin;
|
import buttondevteam.discordplugin.DiscordPlugin;
|
||||||
import buttondevteam.discordplugin.listeners.CommandListener;
|
import buttondevteam.discordplugin.listeners.CommonListeners;
|
||||||
import sx.blah.discord.handle.obj.IMessage;
|
import sx.blah.discord.handle.obj.IMessage;
|
||||||
|
|
||||||
public class DebugCommand extends DiscordCommandBase {
|
public class DebugCommand extends DiscordCommandBase {
|
||||||
|
@ -13,7 +13,7 @@ public class DebugCommand extends DiscordCommandBase {
|
||||||
@Override
|
@Override
|
||||||
public boolean run(IMessage message, String args) {
|
public boolean run(IMessage message, String args) {
|
||||||
if (message.getAuthor().hasRole(DiscordPlugin.mainServer.getRoleByID(126030201472811008L)))
|
if (message.getAuthor().hasRole(DiscordPlugin.mainServer.getRoleByID(126030201472811008L)))
|
||||||
message.reply("Debug " + (CommandListener.debug() ? "enabled" : "disabled"));
|
message.reply("Debug " + (CommonListeners.debug() ? "enabled" : "disabled"));
|
||||||
else
|
else
|
||||||
message.reply("You need to be a moderator to use this command.");
|
message.reply("You need to be a moderator to use this command.");
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package buttondevteam.discordplugin.commands;
|
package buttondevteam.discordplugin.commands;
|
||||||
|
|
||||||
import buttondevteam.discordplugin.DiscordPlugin;
|
import buttondevteam.discordplugin.DiscordPlugin;
|
||||||
|
import buttondevteam.discordplugin.mcchat.MCChatCommand;
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
import sx.blah.discord.handle.obj.IMessage;
|
import sx.blah.discord.handle.obj.IMessage;
|
||||||
|
|
||||||
|
@ -8,7 +9,7 @@ import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static buttondevteam.discordplugin.listeners.CommandListener.debug;
|
import static buttondevteam.discordplugin.listeners.CommonListeners.debug;
|
||||||
|
|
||||||
public abstract class DiscordCommandBase {
|
public abstract class DiscordCommandBase {
|
||||||
public abstract String getCommandName();
|
public abstract String getCommandName();
|
||||||
|
|
|
@ -3,7 +3,6 @@ package buttondevteam.discordplugin.commands;
|
||||||
import buttondevteam.discordplugin.DiscordPlugin;
|
import buttondevteam.discordplugin.DiscordPlugin;
|
||||||
import sx.blah.discord.handle.obj.IMessage;
|
import sx.blah.discord.handle.obj.IMessage;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class HelpCommand extends DiscordCommandBase {
|
public class HelpCommand extends DiscordCommandBase {
|
||||||
|
@ -19,11 +18,11 @@ public class HelpCommand extends DiscordCommandBase {
|
||||||
if (args.length() == 0)
|
if (args.length() == 0)
|
||||||
DiscordPlugin.sendMessageToChannel(message.getChannel(),
|
DiscordPlugin.sendMessageToChannel(message.getChannel(),
|
||||||
"Available commands:\n" + DiscordCommandBase.commands.values().stream()
|
"Available commands:\n" + DiscordCommandBase.commands.values().stream()
|
||||||
.map(dc -> dc.getCommandName()).collect(Collectors.joining("\n")));
|
.map(dc -> DiscordPlugin.getPrefix() + dc.getCommandName()).collect(Collectors.joining("\n")));
|
||||||
else
|
else
|
||||||
DiscordPlugin.sendMessageToChannel(message.getChannel(),
|
DiscordPlugin.sendMessageToChannel(message.getChannel(),
|
||||||
(argdc = DiscordCommandBase.commands.get(args)) == null ? "Command not found: " + args
|
(argdc = DiscordCommandBase.commands.get(args)) == null ? "Command not found: " + args
|
||||||
: Arrays.stream(argdc.getHelpText()).collect(Collectors.joining("\n")));
|
: String.join("\n", argdc.getHelpText()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +31,7 @@ public class HelpCommand extends DiscordCommandBase {
|
||||||
return new String[] { //
|
return new String[] { //
|
||||||
"---- Help command ----", //
|
"---- Help command ----", //
|
||||||
"Shows some info about a command or lists the available commands.", //
|
"Shows some info about a command or lists the available commands.", //
|
||||||
"Usage: help [command]"//
|
"Usage: " + DiscordPlugin.getPrefix() + "help [command]"//
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ public class RoleCommand extends DiscordCommandBase {
|
||||||
public String[] getHelpText() {
|
public String[] getHelpText() {
|
||||||
return new String[]{ //
|
return new String[]{ //
|
||||||
"Add or remove game roles from yourself.", //
|
"Add or remove game roles from yourself.", //
|
||||||
"Usage: role add|remove <name> or role list", //
|
"Usage: " + DiscordPlugin.getPrefix() + "role add|remove <name> or role list", //
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,8 @@ public class UserinfoCommand extends DiscordCommandBase {
|
||||||
"---- User information ----", //
|
"---- User information ----", //
|
||||||
"Shows some information about users, from Discord, from Minecraft or from Reddit if they have these accounts connected.", //
|
"Shows some information about users, from Discord, from Minecraft or from Reddit if they have these accounts connected.", //
|
||||||
"If used without args, shows your info.", //
|
"If used without args, shows your info.", //
|
||||||
"Usage: userinfo [username/nickname[#tag]/ping]\nExamples:\nuserinfo ChromaBot\nuserinfo ChromaBot#6338\nuserinfo @ChromaBot#6338" //
|
"Usage: " + DiscordPlugin.getPrefix() + "userinfo [username/nickname[#tag]/ping]", //
|
||||||
|
"Examples:\n" + DiscordPlugin.getPrefix() + "userinfo ChromaBot\n" + DiscordPlugin.getPrefix() + "userinfo ChromaBot#6338\n" + DiscordPlugin.getPrefix() + "userinfo @ChromaBot#6338" //
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package buttondevteam.discordplugin.listeners;
|
package buttondevteam.discordplugin.exceptions;
|
||||||
|
|
||||||
import buttondevteam.discordplugin.DiscordPlugin;
|
import buttondevteam.discordplugin.DiscordPlugin;
|
||||||
import buttondevteam.lib.TBMCDebugMessageEvent;
|
import buttondevteam.lib.TBMCDebugMessageEvent;
|
|
@ -1,9 +1,12 @@
|
||||||
package buttondevteam.discordplugin.listeners;
|
package buttondevteam.discordplugin.exceptions;
|
||||||
|
|
||||||
|
import buttondevteam.core.ComponentManager;
|
||||||
import buttondevteam.discordplugin.DiscordPlugin;
|
import buttondevteam.discordplugin.DiscordPlugin;
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
import buttondevteam.lib.TBMCExceptionEvent;
|
import buttondevteam.lib.TBMCExceptionEvent;
|
||||||
|
import buttondevteam.lib.architecture.Component;
|
||||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import sx.blah.discord.handle.obj.IRole;
|
import sx.blah.discord.handle.obj.IRole;
|
||||||
|
@ -13,13 +16,13 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class ExceptionListener implements Listener {
|
public class ExceptionListenerModule extends Component implements Listener {
|
||||||
private List<Throwable> lastthrown = new ArrayList<>();
|
private List<Throwable> lastthrown = new ArrayList<>();
|
||||||
private List<String> lastsourcemsg = new ArrayList<>();
|
private List<String> lastsourcemsg = new ArrayList<>();
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onException(TBMCExceptionEvent e) {
|
public void onException(TBMCExceptionEvent e) {
|
||||||
if (DiscordPlugin.SafeMode)
|
if (DiscordPlugin.SafeMode || !ComponentManager.isEnabled(getClass()))
|
||||||
return;
|
return;
|
||||||
if (lastthrown.stream()
|
if (lastthrown.stream()
|
||||||
.anyMatch(ex -> Arrays.equals(e.getException().getStackTrace(), ex.getStackTrace())
|
.anyMatch(ex -> Arrays.equals(e.getException().getStackTrace(), ex.getStackTrace())
|
||||||
|
@ -59,4 +62,15 @@ public class ExceptionListener implements Listener {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void enable() {
|
||||||
|
Bukkit.getPluginManager().registerEvents(new ExceptionListenerModule(), getPlugin());
|
||||||
|
TBMCCoreAPI.RegisterEventsForExceptions(new DebugMessageListener(), getPlugin());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void disable() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
86
src/main/java/buttondevteam/discordplugin/fun/FunModule.java
Normal file
86
src/main/java/buttondevteam/discordplugin/fun/FunModule.java
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
package buttondevteam.discordplugin.fun;
|
||||||
|
|
||||||
|
import buttondevteam.core.ComponentManager;
|
||||||
|
import buttondevteam.discordplugin.DiscordPlugin;
|
||||||
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import buttondevteam.lib.architecture.ConfigData;
|
||||||
|
import sx.blah.discord.handle.obj.IMessage;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class FunModule extends Component {
|
||||||
|
private static FunModule mod;
|
||||||
|
|
||||||
|
private static final String[] serverReadyStrings = new String[]{"In one week from now", // Ali
|
||||||
|
"Between now and the heat-death of the universe.", // Ghostise
|
||||||
|
"Soon™", "Ask again this time next month", // Ghostise
|
||||||
|
"In about 3 seconds", // Nicolai
|
||||||
|
"After we finish 8 plugins", // Ali
|
||||||
|
"Tomorrow.", // Ali
|
||||||
|
"After one tiiiny feature", // Ali
|
||||||
|
"Next commit", // Ali
|
||||||
|
"After we finish strangling Towny", // Ali
|
||||||
|
"When we kill every *fucking* bug", // Ali
|
||||||
|
"Once the server stops screaming.", // Ali
|
||||||
|
"After HL3 comes out", // Ali
|
||||||
|
"Next time you ask", // Ali
|
||||||
|
"When will *you* be open?" // Ali
|
||||||
|
};
|
||||||
|
|
||||||
|
private ConfigData<Boolean> serverReady() {
|
||||||
|
return getData("serverReady", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConfigData<List<String>> serverReadyAnswers() {
|
||||||
|
return getData("serverReadyAnswers", Arrays.asList(serverReadyStrings),
|
||||||
|
data -> (List<String>) data, data -> data); //TODO: Test
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String[] serverReadyQuestions = new String[]{"when will the server be open",
|
||||||
|
"when will the server be ready", "when will the server be done", "when will the server be complete",
|
||||||
|
"when will the server be finished", "when's the server ready", "when's the server open",
|
||||||
|
"Vhen vill ze server be open?"};
|
||||||
|
|
||||||
|
private static final Random serverReadyRandom = new Random();
|
||||||
|
private static final ArrayList<Short> usableServerReadyStrings = new ArrayList<Short>(serverReadyStrings.length) {
|
||||||
|
private static final long serialVersionUID = 2213771460909848770L;
|
||||||
|
|
||||||
|
{
|
||||||
|
createUsableServerReadyStrings(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static void createUsableServerReadyStrings(ArrayList<Short> list) {
|
||||||
|
for (short i = 0; i < serverReadyStrings.length; i++)
|
||||||
|
list.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void enable() {
|
||||||
|
mod = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void disable() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean executeMemes(IMessage message) {
|
||||||
|
if (!ComponentManager.isEnabled(FunModule.class)) return false;
|
||||||
|
if (mod.serverReady().get()) {
|
||||||
|
if (!TBMCCoreAPI.IsTestServer()
|
||||||
|
&& Arrays.stream(serverReadyQuestions).anyMatch(s -> message.getContent().toLowerCase().contains(s))) {
|
||||||
|
int next;
|
||||||
|
if (usableServerReadyStrings.size() == 0)
|
||||||
|
createUsableServerReadyStrings(usableServerReadyStrings);
|
||||||
|
next = usableServerReadyStrings.remove(serverReadyRandom.nextInt(usableServerReadyStrings.size()));
|
||||||
|
DiscordPlugin.sendMessageToChannel(message.getChannel(), serverReadyStrings[next]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
279
src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java
Executable file → Normal file
279
src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java
Executable file → Normal file
|
@ -2,226 +2,71 @@ package buttondevteam.discordplugin.listeners;
|
||||||
|
|
||||||
import buttondevteam.discordplugin.DiscordPlugin;
|
import buttondevteam.discordplugin.DiscordPlugin;
|
||||||
import buttondevteam.discordplugin.commands.DiscordCommandBase;
|
import buttondevteam.discordplugin.commands.DiscordCommandBase;
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
|
||||||
import lombok.val;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import sx.blah.discord.api.events.IListener;
|
|
||||||
import sx.blah.discord.handle.impl.events.guild.channel.message.MentionEvent;
|
|
||||||
import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent;
|
|
||||||
import sx.blah.discord.handle.impl.events.guild.role.RoleCreateEvent;
|
|
||||||
import sx.blah.discord.handle.impl.events.guild.role.RoleDeleteEvent;
|
|
||||||
import sx.blah.discord.handle.impl.events.guild.role.RoleUpdateEvent;
|
|
||||||
import sx.blah.discord.handle.impl.events.user.PresenceUpdateEvent;
|
|
||||||
import sx.blah.discord.handle.obj.IChannel;
|
import sx.blah.discord.handle.obj.IChannel;
|
||||||
import sx.blah.discord.handle.obj.IMessage;
|
import sx.blah.discord.handle.obj.IMessage;
|
||||||
import sx.blah.discord.handle.obj.StatusType;
|
import sx.blah.discord.handle.obj.IRole;
|
||||||
import sx.blah.discord.util.EmbedBuilder;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
public class CommandListener {
|
public class CommandListener {
|
||||||
|
/**
|
||||||
|
* Runs a ChromaBot command. If mentionedonly is false, it will only execute the command if it was in #bot with the correct prefix or in private.
|
||||||
|
*
|
||||||
|
* @param message The Discord message
|
||||||
|
* @param mentionedonly Only run the command if ChromaBot is mentioned at the start of the message
|
||||||
|
* @return Whether it ran the command
|
||||||
|
*/
|
||||||
|
public static boolean runCommand(IMessage message, boolean mentionedonly) {
|
||||||
|
if (message.getContent().length() == 0)
|
||||||
|
return false; //Pin messages and such, let the mcchat listener deal with it
|
||||||
|
final IChannel channel = message.getChannel();
|
||||||
|
if (!mentionedonly) { //mentionedonly conditions are in CommonListeners
|
||||||
|
if (!message.getChannel().isPrivate()
|
||||||
|
&& !(message.getContent().charAt(0) == DiscordPlugin.getPrefix()
|
||||||
|
&& channel.getStringID().equals(DiscordPlugin.botchannel.getStringID()))) //
|
||||||
|
return false;
|
||||||
|
message.getChannel().setTypingStatus(true); // Fun
|
||||||
|
}
|
||||||
|
final StringBuilder cmdwithargs = new StringBuilder(message.getContent());
|
||||||
|
final String mention = DiscordPlugin.dc.getOurUser().mention(false);
|
||||||
|
final String mentionNick = DiscordPlugin.dc.getOurUser().mention(true);
|
||||||
|
boolean gotmention = checkanddeletemention(cmdwithargs, mention, message);
|
||||||
|
gotmention = checkanddeletemention(cmdwithargs, mentionNick, message) || gotmention;
|
||||||
|
for (String mentionRole : (Iterable<String>) message.getRoleMentions().stream().filter(r -> DiscordPlugin.dc.getOurUser().hasRole(r)).map(IRole::mention)::iterator)
|
||||||
|
gotmention = checkanddeletemention(cmdwithargs, mentionRole, message) || gotmention; // Delete all mentions
|
||||||
|
if (mentionedonly && !gotmention) {
|
||||||
|
message.getChannel().setTypingStatus(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
message.getChannel().setTypingStatus(true);
|
||||||
|
String cmdwithargsString = cmdwithargs.toString().trim(); //Remove spaces between mention and command
|
||||||
|
int index = cmdwithargsString.indexOf(" ");
|
||||||
|
String cmd;
|
||||||
|
String args;
|
||||||
|
if (index == -1) {
|
||||||
|
cmd = cmdwithargsString;
|
||||||
|
args = "";
|
||||||
|
} else {
|
||||||
|
cmd = cmdwithargsString.substring(0, index);
|
||||||
|
args = cmdwithargsString.substring(index + 1).trim(); //In case there are multiple spaces
|
||||||
|
}
|
||||||
|
DiscordCommandBase.runCommand(cmd.toLowerCase(), args, message);
|
||||||
|
message.getChannel().setTypingStatus(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static final String[] serverReadyStrings = new String[]{"In one week from now", // Ali
|
private static boolean checkanddeletemention(StringBuilder cmdwithargs, String mention, IMessage message) {
|
||||||
"Between now and the heat-death of the universe.", // Ghostise
|
if (message.getContent().startsWith(mention)) // TODO: Resolve mentions: Compound arguments, either a mention or text
|
||||||
"Soon™", "Ask again this time next month", // Ghostise
|
if (cmdwithargs.length() > mention.length() + 1)
|
||||||
"In about 3 seconds", // Nicolai
|
cmdwithargs.delete(0,
|
||||||
"After we finish 8 plugins", // Ali
|
cmdwithargs.charAt(mention.length()) == ' ' ? mention.length() + 1 : mention.length());
|
||||||
"Tomorrow.", // Ali
|
else
|
||||||
"After one tiiiny feature", // Ali
|
cmdwithargs.replace(0, cmdwithargs.length(), "help");
|
||||||
"Next commit", // Ali
|
else {
|
||||||
"After we finish strangling Towny", // Ali
|
if (cmdwithargs.length() > 0 && cmdwithargs.charAt(0) == '/')
|
||||||
"When we kill every *fucking* bug", // Ali
|
cmdwithargs.deleteCharAt(0); //Don't treat / as mention, mentions can be used in public mcchat
|
||||||
"Once the server stops screaming.", // Ali
|
return false;
|
||||||
"After HL3 comes out", // Ali
|
}
|
||||||
"Next time you ask", // Ali
|
if (cmdwithargs.length() == 0)
|
||||||
"When will *you* be open?" // Ali
|
cmdwithargs.replace(0, cmdwithargs.length(), "help");
|
||||||
};
|
return true;
|
||||||
|
}
|
||||||
private static final String[] serverReadyQuestions = new String[]{"when will the server be open",
|
|
||||||
"when will the server be ready", "when will the server be done", "when will the server be complete",
|
|
||||||
"when will the server be finished", "when's the server ready", "when's the server open",
|
|
||||||
"Vhen vill ze server be open?"};
|
|
||||||
|
|
||||||
private static final Random serverReadyRandom = new Random();
|
|
||||||
private static final ArrayList<Short> usableServerReadyStrings = new ArrayList<Short>(serverReadyStrings.length) {
|
|
||||||
private static final long serialVersionUID = 2213771460909848770L;
|
|
||||||
|
|
||||||
{
|
|
||||||
createUsableServerReadyStrings(this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static void createUsableServerReadyStrings(ArrayList<Short> list) {
|
|
||||||
for (short i = 0; i < serverReadyStrings.length; i++)
|
|
||||||
list.add(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static long lasttime = 0;
|
|
||||||
|
|
||||||
public static IListener<?>[] getListeners() {
|
|
||||||
return new IListener[]{new IListener<MentionEvent>() {
|
|
||||||
@Override
|
|
||||||
public void handle(MentionEvent event) {
|
|
||||||
if (DiscordPlugin.SafeMode)
|
|
||||||
return;
|
|
||||||
if (event.getMessage().getAuthor().isBot())
|
|
||||||
return;
|
|
||||||
final IChannel channel = event.getMessage().getChannel();
|
|
||||||
if (!channel.getStringID().equals(DiscordPlugin.botchannel.getStringID())
|
|
||||||
&& (!event.getMessage().getContent().contains("channelcon") || MCChatListener.hasCustomChat(channel))) //Allow channelcon in other servers but avoid double handling when it's enabled
|
|
||||||
return;
|
|
||||||
if (channel.getStringID().equals(DiscordPlugin.chatchannel.getStringID()))
|
|
||||||
return; // The chat code already handles this - Right now while testing botchannel is the same as chatchannel
|
|
||||||
event.getMessage().getChannel().setTypingStatus(true); // Fun
|
|
||||||
runCommand(event.getMessage(), true);
|
|
||||||
}
|
|
||||||
}, new IListener<MessageReceivedEvent>() {
|
|
||||||
@Override
|
|
||||||
public void handle(MessageReceivedEvent event) {
|
|
||||||
if (DiscordPlugin.SafeMode)
|
|
||||||
return;
|
|
||||||
final String msglowercase = event.getMessage().getContent().toLowerCase();
|
|
||||||
if (!TBMCCoreAPI.IsTestServer()
|
|
||||||
&& Arrays.stream(serverReadyQuestions).anyMatch(s -> msglowercase.contains(s))) {
|
|
||||||
int next;
|
|
||||||
if (usableServerReadyStrings.size() == 0)
|
|
||||||
createUsableServerReadyStrings(usableServerReadyStrings);
|
|
||||||
next = usableServerReadyStrings.remove(serverReadyRandom.nextInt(usableServerReadyStrings.size()));
|
|
||||||
DiscordPlugin.sendMessageToChannel(event.getMessage().getChannel(), serverReadyStrings[next]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!event.getMessage().getChannel().isPrivate()
|
|
||||||
&& !(event.getMessage().getContent().startsWith("/")
|
|
||||||
&& event.getChannel().getStringID().equals(DiscordPlugin.botchannel.getStringID()))) //
|
|
||||||
return;
|
|
||||||
if (MCChatListener.isMinecraftChatEnabled(event.getAuthor().toString()))
|
|
||||||
if (!event.getMessage().getContent().equalsIgnoreCase("mcchat"))
|
|
||||||
return;
|
|
||||||
if (event.getMessage().getAuthor().isBot())
|
|
||||||
return;
|
|
||||||
runCommand(event.getMessage(), false);
|
|
||||||
}
|
|
||||||
}, new IListener<sx.blah.discord.handle.impl.events.user.PresenceUpdateEvent>() {
|
|
||||||
@Override
|
|
||||||
public void handle(PresenceUpdateEvent event) {
|
|
||||||
if (DiscordPlugin.SafeMode)
|
|
||||||
return;
|
|
||||||
val devrole = DiscordPlugin.devServer.getRolesByName("Developer").get(0);
|
|
||||||
if (event.getOldPresence().getStatus().equals(StatusType.OFFLINE)
|
|
||||||
&& !event.getNewPresence().getStatus().equals(StatusType.OFFLINE)
|
|
||||||
&& event.getUser().getRolesForGuild(DiscordPlugin.devServer).stream()
|
|
||||||
.anyMatch(r -> r.getLongID() == devrole.getLongID())
|
|
||||||
&& DiscordPlugin.devServer.getUsersByRole(devrole).stream()
|
|
||||||
.noneMatch(u -> u.getPresence().getStatus().equals(StatusType.OFFLINE))
|
|
||||||
&& lasttime + 10 < TimeUnit.NANOSECONDS.toHours(System.nanoTime())
|
|
||||||
&& Calendar.getInstance().get(Calendar.DAY_OF_MONTH) % 5 == 0) {
|
|
||||||
DiscordPlugin.sendMessageToChannel(DiscordPlugin.devofficechannel, "Full house!",
|
|
||||||
new EmbedBuilder()
|
|
||||||
.withImage(
|
|
||||||
"https://cdn.discordapp.com/attachments/249295547263877121/249687682618359808/poker-hand-full-house-aces-kings-playing-cards-15553791.png")
|
|
||||||
.build());
|
|
||||||
lasttime = TimeUnit.NANOSECONDS.toHours(System.nanoTime());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, (IListener<RoleCreateEvent>) event -> {
|
|
||||||
Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, () -> {
|
|
||||||
if (event.getRole().isDeleted() || !DiscordPlugin.plugin.isGameRole(event.getRole()))
|
|
||||||
return; //Deleted or not a game role
|
|
||||||
DiscordPlugin.GameRoles.add(event.getRole().getName());
|
|
||||||
DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Added " + event.getRole().getName() + " as game role. If you don't want this, change the role's color from the default.");
|
|
||||||
}, 100);
|
|
||||||
}, (IListener<RoleDeleteEvent>) event -> {
|
|
||||||
if (DiscordPlugin.GameRoles.remove(event.getRole().getName()))
|
|
||||||
DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Removed " + event.getRole().getName() + " as a game role.");
|
|
||||||
}, (IListener<RoleUpdateEvent>) event -> { //Role update event
|
|
||||||
if (!DiscordPlugin.plugin.isGameRole(event.getNewRole())) {
|
|
||||||
if (DiscordPlugin.GameRoles.remove(event.getOldRole().getName()))
|
|
||||||
DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Removed " + event.getOldRole().getName() + " as a game role because it's color changed.");
|
|
||||||
} else {
|
|
||||||
if (DiscordPlugin.GameRoles.contains(event.getOldRole().getName()) && event.getOldRole().getName().equals(event.getNewRole().getName()))
|
|
||||||
return;
|
|
||||||
boolean removed = DiscordPlugin.GameRoles.remove(event.getOldRole().getName()); //Regardless of whether it was a game role
|
|
||||||
DiscordPlugin.GameRoles.add(event.getNewRole().getName()); //Add it because it has no color
|
|
||||||
if (removed)
|
|
||||||
DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Changed game role from " + event.getOldRole().getName() + " to " + event.getNewRole().getName() + ".");
|
|
||||||
else
|
|
||||||
DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Added " + event.getNewRole().getName() + " as game role because it has the default color.");
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs a ChromaBot command.
|
|
||||||
*
|
|
||||||
* @param message The Discord message
|
|
||||||
* @param mentionedonly Only run the command if ChromaBot is mentioned at the start of the message
|
|
||||||
* @return Whether it ran the command (always true if mentionedonly is false)
|
|
||||||
*/
|
|
||||||
public static boolean runCommand(IMessage message, boolean mentionedonly) {
|
|
||||||
debug("A");
|
|
||||||
if (DiscordPlugin.SafeMode)
|
|
||||||
return true;
|
|
||||||
debug("B");
|
|
||||||
final StringBuilder cmdwithargs = new StringBuilder(message.getContent());
|
|
||||||
final String mention = DiscordPlugin.dc.getOurUser().mention(false);
|
|
||||||
final String mentionNick = DiscordPlugin.dc.getOurUser().mention(true);
|
|
||||||
boolean gotmention = checkanddeletemention(cmdwithargs, mention, message);
|
|
||||||
gotmention = checkanddeletemention(cmdwithargs, mentionNick, message) || gotmention;
|
|
||||||
for (String mentionRole : (Iterable<String>) message.getRoleMentions().stream().filter(r -> DiscordPlugin.dc.getOurUser().hasRole(r)).map(r -> r.mention())::iterator)
|
|
||||||
gotmention = checkanddeletemention(cmdwithargs, mentionRole, message) || gotmention; // Delete all mentions
|
|
||||||
debug("C");
|
|
||||||
if (mentionedonly && !gotmention) {
|
|
||||||
message.getChannel().setTypingStatus(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
debug("D");
|
|
||||||
message.getChannel().setTypingStatus(true);
|
|
||||||
String cmdwithargsString = cmdwithargs.toString().trim(); //Remove spaces between mention and command
|
|
||||||
int index = cmdwithargsString.indexOf(" ");
|
|
||||||
String cmd;
|
|
||||||
String args;
|
|
||||||
if (index == -1) {
|
|
||||||
cmd = cmdwithargsString;
|
|
||||||
args = "";
|
|
||||||
} else {
|
|
||||||
cmd = cmdwithargsString.substring(0, index);
|
|
||||||
args = cmdwithargsString.substring(index + 1).trim(); //In case there are multiple spaces
|
|
||||||
}
|
|
||||||
debug("E");
|
|
||||||
DiscordCommandBase.runCommand(cmd.toLowerCase(), args, message);
|
|
||||||
message.getChannel().setTypingStatus(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean debug = false;
|
|
||||||
|
|
||||||
public static void debug(String debug) {
|
|
||||||
if (CommandListener.debug) //Debug
|
|
||||||
System.out.println(debug);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean debug() {
|
|
||||||
return debug = !debug;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean checkanddeletemention(StringBuilder cmdwithargs, String mention, IMessage message) {
|
|
||||||
if (message.getContent().startsWith(mention)) // TODO: Resolve mentions: Compound arguments, either a mention or text
|
|
||||||
if (cmdwithargs.length() > mention.length() + 1)
|
|
||||||
cmdwithargs.delete(0,
|
|
||||||
cmdwithargs.charAt(mention.length()) == ' ' ? mention.length() + 1 : mention.length());
|
|
||||||
else
|
|
||||||
cmdwithargs.replace(0, cmdwithargs.length(), "help");
|
|
||||||
else {
|
|
||||||
if (cmdwithargs.length() > 0 && cmdwithargs.charAt(0) == '/')
|
|
||||||
cmdwithargs.deleteCharAt(0); //Don't treat / as mention, mentions can be used in public mcchat
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (cmdwithargs.length() == 0)
|
|
||||||
cmdwithargs.replace(0, cmdwithargs.length(), "help");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
128
src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java
Executable file
128
src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java
Executable file
|
@ -0,0 +1,128 @@
|
||||||
|
package buttondevteam.discordplugin.listeners;
|
||||||
|
|
||||||
|
import buttondevteam.discordplugin.DPUtils;
|
||||||
|
import buttondevteam.discordplugin.DiscordPlugin;
|
||||||
|
import buttondevteam.discordplugin.mcchat.MinecraftChatModule;
|
||||||
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import lombok.val;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import sx.blah.discord.api.events.IListener;
|
||||||
|
import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent;
|
||||||
|
import sx.blah.discord.handle.impl.events.guild.role.RoleCreateEvent;
|
||||||
|
import sx.blah.discord.handle.impl.events.guild.role.RoleDeleteEvent;
|
||||||
|
import sx.blah.discord.handle.impl.events.guild.role.RoleUpdateEvent;
|
||||||
|
import sx.blah.discord.handle.impl.events.user.PresenceUpdateEvent;
|
||||||
|
import sx.blah.discord.handle.obj.StatusType;
|
||||||
|
import sx.blah.discord.util.EmbedBuilder;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class CommonListeners {
|
||||||
|
|
||||||
|
/*private static ArrayList<Object> dcListeners=new ArrayList<>();
|
||||||
|
|
||||||
|
public static void registerDiscordListener(DiscordListener listener) {
|
||||||
|
//Step 1: Get all events that are handled by us
|
||||||
|
//Step 2: Find methods that handle these
|
||||||
|
//...or just simply call the methods in the right order
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void callDiscordEvent(Event event) {
|
||||||
|
String name=event.getClass().getSimpleName();
|
||||||
|
name=Character.toLowerCase(name.charAt(0))+name.substring(1);
|
||||||
|
for (Object listener : dcListeners) {
|
||||||
|
listener.getClass().getMethods(name, AsyncDiscordEvent.class);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
private static long lasttime = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
MentionEvent:
|
||||||
|
- CommandListener (starts with mention, only 'channelcon' and not in #bot)
|
||||||
|
|
||||||
|
MessageReceivedEvent:
|
||||||
|
- v CommandListener (starts with mention, in #bot or a connected chat)
|
||||||
|
- Minecraft chat (is enabled in the channel and message isn't [/]mcchat)
|
||||||
|
- CommandListener (with the correct prefix in #bot, or in private)
|
||||||
|
*/
|
||||||
|
public static IListener<?>[] getListeners() {
|
||||||
|
return new IListener[]{new IListener<MessageReceivedEvent>() {
|
||||||
|
@Override
|
||||||
|
public void handle(MessageReceivedEvent event) {
|
||||||
|
if (DiscordPlugin.SafeMode)
|
||||||
|
return;
|
||||||
|
if (event.getMessage().getAuthor().isBot())
|
||||||
|
return;
|
||||||
|
boolean handled = false;
|
||||||
|
if (event.getChannel().getLongID() == DiscordPlugin.botchannel.getLongID() //If mentioned, that's higher than chat
|
||||||
|
|| event.getMessage().getContent().contains("channelcon")) //Only 'channelcon' is allowed in other channels
|
||||||
|
handled = CommandListener.runCommand(event.getMessage(), true); //#bot is handled here
|
||||||
|
if (handled) return;
|
||||||
|
val mcchat = Component.getComponents().get(MinecraftChatModule.class);
|
||||||
|
if (mcchat != null && mcchat.isEnabled()) //ComponentManager.isEnabled() searches the component again
|
||||||
|
handled = ((MinecraftChatModule) mcchat).getListener().handleDiscord(event); //Also runs Discord commands in chat channels
|
||||||
|
if (!handled)
|
||||||
|
handled = CommandListener.runCommand(event.getMessage(), false);
|
||||||
|
}
|
||||||
|
}, new IListener<sx.blah.discord.handle.impl.events.user.PresenceUpdateEvent>() {
|
||||||
|
@Override
|
||||||
|
public void handle(PresenceUpdateEvent event) {
|
||||||
|
if (DiscordPlugin.SafeMode)
|
||||||
|
return;
|
||||||
|
val devrole = DiscordPlugin.devServer.getRolesByName("Developer").get(0);
|
||||||
|
if (event.getOldPresence().getStatus().equals(StatusType.OFFLINE)
|
||||||
|
&& !event.getNewPresence().getStatus().equals(StatusType.OFFLINE)
|
||||||
|
&& event.getUser().getRolesForGuild(DiscordPlugin.devServer).stream()
|
||||||
|
.anyMatch(r -> r.getLongID() == devrole.getLongID())
|
||||||
|
&& DiscordPlugin.devServer.getUsersByRole(devrole).stream()
|
||||||
|
.noneMatch(u -> u.getPresence().getStatus().equals(StatusType.OFFLINE))
|
||||||
|
&& lasttime + 10 < TimeUnit.NANOSECONDS.toHours(System.nanoTime())
|
||||||
|
&& Calendar.getInstance().get(Calendar.DAY_OF_MONTH) % 5 == 0) {
|
||||||
|
DiscordPlugin.sendMessageToChannel(DiscordPlugin.devofficechannel, "Full house!",
|
||||||
|
new EmbedBuilder()
|
||||||
|
.withImage(
|
||||||
|
"https://cdn.discordapp.com/attachments/249295547263877121/249687682618359808/poker-hand-full-house-aces-kings-playing-cards-15553791.png")
|
||||||
|
.build());
|
||||||
|
lasttime = TimeUnit.NANOSECONDS.toHours(System.nanoTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, (IListener<RoleCreateEvent>) event -> {
|
||||||
|
Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, () -> {
|
||||||
|
if (event.getRole().isDeleted() || !DiscordPlugin.plugin.isGameRole(event.getRole()))
|
||||||
|
return; //Deleted or not a game role
|
||||||
|
DiscordPlugin.GameRoles.add(event.getRole().getName());
|
||||||
|
DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Added " + event.getRole().getName() + " as game role. If you don't want this, change the role's color from the default.");
|
||||||
|
}, 100);
|
||||||
|
}, (IListener<RoleDeleteEvent>) event -> {
|
||||||
|
if (DiscordPlugin.GameRoles.remove(event.getRole().getName()))
|
||||||
|
DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Removed " + event.getRole().getName() + " as a game role.");
|
||||||
|
}, (IListener<RoleUpdateEvent>) event -> { //Role update event
|
||||||
|
if (!DiscordPlugin.plugin.isGameRole(event.getNewRole())) {
|
||||||
|
if (DiscordPlugin.GameRoles.remove(event.getOldRole().getName()))
|
||||||
|
DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Removed " + event.getOldRole().getName() + " as a game role because it's color changed.");
|
||||||
|
} else {
|
||||||
|
if (DiscordPlugin.GameRoles.contains(event.getOldRole().getName()) && event.getOldRole().getName().equals(event.getNewRole().getName()))
|
||||||
|
return;
|
||||||
|
boolean removed = DiscordPlugin.GameRoles.remove(event.getOldRole().getName()); //Regardless of whether it was a game role
|
||||||
|
DiscordPlugin.GameRoles.add(event.getNewRole().getName()); //Add it because it has no color
|
||||||
|
if (removed)
|
||||||
|
DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Changed game role from " + event.getOldRole().getName() + " to " + event.getNewRole().getName() + ".");
|
||||||
|
else
|
||||||
|
DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Added " + event.getNewRole().getName() + " as game role because it has the default color.");
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean debug = false;
|
||||||
|
|
||||||
|
public static void debug(String debug) {
|
||||||
|
if (CommonListeners.debug) //Debug
|
||||||
|
DPUtils.getLogger().info(debug);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean debug() {
|
||||||
|
return debug = !debug;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
package buttondevteam.discordplugin.listeners;
|
||||||
|
|
||||||
|
public interface DiscordListener {
|
||||||
|
}
|
|
@ -1,98 +1,24 @@
|
||||||
package buttondevteam.discordplugin.listeners;
|
package buttondevteam.discordplugin.listeners;
|
||||||
|
|
||||||
import buttondevteam.discordplugin.*;
|
import buttondevteam.discordplugin.DiscordPlayer;
|
||||||
import buttondevteam.discordplugin.commands.ConnectCommand;
|
import buttondevteam.discordplugin.DiscordPlugin;
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.player.TBMCPlayerGetInfoEvent;
|
||||||
import buttondevteam.lib.TBMCSystemChatEvent;
|
|
||||||
import buttondevteam.lib.player.*;
|
|
||||||
import com.earth2me.essentials.CommandSource;
|
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import net.ess3.api.events.AfkStatusChangeEvent;
|
|
||||||
import net.ess3.api.events.MuteStatusChangeEvent;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.event.Event;
|
||||||
import org.bukkit.event.*;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerKickEvent;
|
|
||||||
import org.bukkit.event.player.PlayerLoginEvent;
|
|
||||||
import org.bukkit.event.player.PlayerLoginEvent.Result;
|
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
|
||||||
import org.bukkit.event.server.BroadcastMessageEvent;
|
|
||||||
import org.bukkit.event.server.ServerCommandEvent;
|
import org.bukkit.event.server.ServerCommandEvent;
|
||||||
import org.bukkit.plugin.AuthorNagException;
|
import org.bukkit.plugin.AuthorNagException;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.plugin.RegisteredListener;
|
import org.bukkit.plugin.RegisteredListener;
|
||||||
import sx.blah.discord.handle.obj.IRole;
|
|
||||||
import sx.blah.discord.handle.obj.IUser;
|
import sx.blah.discord.handle.obj.IUser;
|
||||||
import sx.blah.discord.util.DiscordException;
|
|
||||||
import sx.blah.discord.util.MissingPermissionsException;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
public class MCListener implements Listener {
|
public class MCListener implements Listener {
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
|
||||||
public void onPlayerLogin(PlayerLoginEvent e) {
|
|
||||||
if (e.getResult() != Result.ALLOWED)
|
|
||||||
return;
|
|
||||||
MCChatListener.ConnectedSenders.values().stream().flatMap(v -> v.values().stream()) //Only private mcchat should be in ConnectedSenders
|
|
||||||
.filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny()
|
|
||||||
.ifPresent(dcp -> callEventExcludingSome(new PlayerQuitEvent(dcp, "")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
|
||||||
public void onPlayerJoin(TBMCPlayerJoinEvent e) {
|
|
||||||
if (e.getPlayer() instanceof DiscordConnectedPlayer)
|
|
||||||
return; // Don't show the joined message for the fake player
|
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, () -> {
|
|
||||||
final Player p = e.getPlayer();
|
|
||||||
DiscordPlayer dp = e.GetPlayer().getAs(DiscordPlayer.class);
|
|
||||||
if (dp != null) {
|
|
||||||
val user = DiscordPlugin.dc.getUserByID(Long.parseLong(dp.getDiscordID()));
|
|
||||||
MCChatListener.addSender(MCChatListener.OnlineSenders, dp.getDiscordID(),
|
|
||||||
new DiscordPlayerSender(user, user.getOrCreatePMChannel(), p));
|
|
||||||
MCChatListener.addSender(MCChatListener.OnlineSenders, dp.getDiscordID(),
|
|
||||||
new DiscordPlayerSender(user, DiscordPlugin.chatchannel, p)); //Stored per-channel
|
|
||||||
}
|
|
||||||
if (ConnectCommand.WaitingToConnect.containsKey(e.GetPlayer().PlayerName().get())) {
|
|
||||||
IUser user = DiscordPlugin.dc
|
|
||||||
.getUserByID(Long.parseLong(ConnectCommand.WaitingToConnect.get(e.GetPlayer().PlayerName().get())));
|
|
||||||
p.sendMessage("§bTo connect with the Discord account @" + user.getName() + "#" + user.getDiscriminator()
|
|
||||||
+ " do /discord accept");
|
|
||||||
p.sendMessage("§bIf it wasn't you, do /discord decline");
|
|
||||||
}
|
|
||||||
final String message = e.GetPlayer().PlayerName().get() + " joined the game";
|
|
||||||
MCChatListener.forAllowedCustomAndAllMCChat(MCChatListener.send(message), e.getPlayer(), ChannelconBroadcast.JOINLEAVE, true);
|
|
||||||
//System.out.println("Does this appear more than once?"); //No
|
|
||||||
MCChatListener.ListC = 0;
|
|
||||||
ChromaBot.getInstance().updatePlayerList();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
|
||||||
public void onPlayerLeave(TBMCPlayerQuitEvent e) {
|
|
||||||
if (e.getPlayer() instanceof DiscordConnectedPlayer)
|
|
||||||
return; // Only care about real users
|
|
||||||
MCChatListener.OnlineSenders.entrySet()
|
|
||||||
.removeIf(entry -> entry.getValue().entrySet().stream().anyMatch(p -> p.getValue().getUniqueId().equals(e.getPlayer().getUniqueId())));
|
|
||||||
Bukkit.getScheduler().runTask(DiscordPlugin.plugin,
|
|
||||||
() -> MCChatListener.ConnectedSenders.values().stream().flatMap(v -> v.values().stream())
|
|
||||||
.filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny()
|
|
||||||
.ifPresent(dcp -> callEventExcludingSome(new PlayerJoinEvent(dcp, ""))));
|
|
||||||
Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin,
|
|
||||||
ChromaBot.getInstance()::updatePlayerList, 5);
|
|
||||||
final String message = e.GetPlayer().PlayerName().get() + " left the game";
|
|
||||||
MCChatListener.forAllowedCustomAndAllMCChat(MCChatListener.send(message), e.getPlayer(), ChannelconBroadcast.JOINLEAVE, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
|
||||||
public void onPlayerKick(PlayerKickEvent e) {
|
|
||||||
/*if (!DiscordPlugin.hooked && !e.getReason().equals("The server is restarting")
|
|
||||||
&& !e.getReason().equals("Server closed")) // The leave messages errored with the previous setup, I could make it wait since I moved it here, but instead I have a special
|
|
||||||
MCChatListener.forAllowedCustomAndAllMCChat(e.getPlayer().getName() + " left the game"); // message for this - Oh wait this doesn't even send normally because of the hook*/
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onGetInfo(TBMCPlayerGetInfoEvent e) {
|
public void onGetInfo(TBMCPlayerGetInfoEvent e) {
|
||||||
if (DiscordPlugin.SafeMode)
|
if (DiscordPlugin.SafeMode)
|
||||||
|
@ -107,125 +33,71 @@ public class MCListener implements Listener {
|
||||||
e.addInfo(user.getPresence().getActivity().get() + ": " + user.getPresence().getText().get());
|
e.addInfo(user.getPresence().getActivity().get() + ": " + user.getPresence().getText().get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOW)
|
|
||||||
public void onPlayerDeath(PlayerDeathEvent e) {
|
|
||||||
MCChatListener.forAllowedCustomAndAllMCChat(MCChatListener.send(e.getDeathMessage()), e.getEntity(), ChannelconBroadcast.DEATH, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerAFK(AfkStatusChangeEvent e) {
|
|
||||||
final Player base = e.getAffected().getBase();
|
|
||||||
if (e.isCancelled() || !base.isOnline())
|
|
||||||
return;
|
|
||||||
final String msg = base.getDisplayName()
|
|
||||||
+ " is " + (e.getValue() ? "now" : "no longer") + " AFK.";
|
|
||||||
MCChatListener.forAllowedCustomAndAllMCChat(MCChatListener.send(msg), base, ChannelconBroadcast.AFK, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onServerCommand(ServerCommandEvent e) {
|
public void onServerCommand(ServerCommandEvent e) {
|
||||||
DiscordPlugin.Restart = !e.getCommand().equalsIgnoreCase("stop"); // The variable is always true except if stopped
|
DiscordPlugin.Restart = !e.getCommand().equalsIgnoreCase("stop"); // The variable is always true except if stopped
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
private static final String[] EXCLUDED_PLUGINS = {"ProtocolLib", "LibsDisguises", "JourneyMapServer"}; //TODO: Make configurable
|
||||||
public void onPlayerMute(MuteStatusChangeEvent e) {
|
|
||||||
try {
|
|
||||||
DPUtils.performNoWait(() -> {
|
|
||||||
final IRole role = DiscordPlugin.dc.getRoleByID(164090010461667328L);
|
|
||||||
final CommandSource source = e.getAffected().getSource();
|
|
||||||
if (!source.isPlayer())
|
|
||||||
return;
|
|
||||||
final IUser user = DiscordPlugin.dc.getUserByID(
|
|
||||||
Long.parseLong(TBMCPlayerBase.getPlayer(source.getPlayer().getUniqueId(), TBMCPlayer.class)
|
|
||||||
.getAs(DiscordPlayer.class).getDiscordID()));
|
|
||||||
if (e.getValue())
|
|
||||||
user.addRole(role);
|
|
||||||
else
|
|
||||||
user.removeRole(role);
|
|
||||||
});
|
|
||||||
} catch (DiscordException | MissingPermissionsException ex) {
|
|
||||||
TBMCCoreAPI.SendException("Failed to give/take Muted role to player " + e.getAffected().getName() + "!",
|
|
||||||
ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
public static void callEventExcludingSome(Event event) {
|
||||||
public void onChatSystemMessage(TBMCSystemChatEvent event) {
|
callEventExcluding(event, false, EXCLUDED_PLUGINS);
|
||||||
MCChatListener.forAllowedMCChat(MCChatListener.send(event.getMessage()), event);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
/**
|
||||||
public void onBroadcastMessage(BroadcastMessageEvent event) {
|
* Calls an event with the given details.
|
||||||
MCChatListener.forCustomAndAllMCChat(MCChatListener.send(event.getMessage()), ChannelconBroadcast.BROADCAST, false);
|
* <p>
|
||||||
}
|
* This method only synchronizes when the event is not asynchronous.
|
||||||
|
*
|
||||||
|
* @param event Event details
|
||||||
|
* @param only Flips the operation and <b>includes</b> the listed plugins
|
||||||
|
* @param plugins The plugins to exclude. Not case sensitive.
|
||||||
|
*/
|
||||||
|
public static void callEventExcluding(Event event, boolean only, String... plugins) { // Copied from Spigot-API and modified a bit
|
||||||
|
if (event.isAsynchronous()) {
|
||||||
|
if (Thread.holdsLock(Bukkit.getPluginManager())) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
event.getEventName() + " cannot be triggered asynchronously from inside synchronized code.");
|
||||||
|
}
|
||||||
|
if (Bukkit.getServer().isPrimaryThread()) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
event.getEventName() + " cannot be triggered asynchronously from primary server thread.");
|
||||||
|
}
|
||||||
|
fireEventExcluding(event, only, plugins);
|
||||||
|
} else {
|
||||||
|
synchronized (Bukkit.getPluginManager()) {
|
||||||
|
fireEventExcluding(event, only, plugins);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler
|
private static void fireEventExcluding(Event event, boolean only, String... plugins) {
|
||||||
public void onYEEHAW(TBMCYEEHAWEvent event) { //TODO: Inherit from the chat event base to have channel support
|
HandlerList handlers = event.getHandlers(); // Code taken from SimplePluginManager in Spigot-API
|
||||||
String name = event.getSender() instanceof Player ? ((Player) event.getSender()).getDisplayName()
|
RegisteredListener[] listeners = handlers.getRegisteredListeners();
|
||||||
: event.getSender().getName();
|
val server = Bukkit.getServer();
|
||||||
//Channel channel = ChromaGamerBase.getFromSender(event.getSender()).channel().get(); - TODO
|
|
||||||
MCChatListener.forAllMCChat(MCChatListener.send(name + " <:YEEHAW:" + DiscordPlugin.mainServer.getEmojiByName("YEEHAW").getStringID() + ">s"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String[] EXCLUDED_PLUGINS = {"ProtocolLib", "LibsDisguises"};
|
for (RegisteredListener registration : listeners) {
|
||||||
|
if (!registration.getPlugin().isEnabled()
|
||||||
|
|| Arrays.stream(plugins).anyMatch(p -> only ^ p.equalsIgnoreCase(registration.getPlugin().getName())))
|
||||||
|
continue; // Modified to exclude plugins
|
||||||
|
|
||||||
public static void callEventExcludingSome(Event event) {
|
try {
|
||||||
callEventExcluding(event, EXCLUDED_PLUGINS);
|
registration.callEvent(event);
|
||||||
}
|
} catch (AuthorNagException ex) {
|
||||||
|
Plugin plugin = registration.getPlugin();
|
||||||
|
|
||||||
/**
|
if (plugin.isNaggable()) {
|
||||||
* Calls an event with the given details.
|
plugin.setNaggable(false);
|
||||||
* <p>
|
|
||||||
* This method only synchronizes when the event is not asynchronous.
|
|
||||||
*
|
|
||||||
* @param event Event details
|
|
||||||
* @param plugins The plugins to exclude. Not case sensitive.
|
|
||||||
*/
|
|
||||||
private static void callEventExcluding(Event event, String... plugins) { // Copied from Spigot-API and modified a bit
|
|
||||||
if (event.isAsynchronous()) {
|
|
||||||
if (Thread.holdsLock(Bukkit.getPluginManager())) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
event.getEventName() + " cannot be triggered asynchronously from inside synchronized code.");
|
|
||||||
}
|
|
||||||
if (Bukkit.getServer().isPrimaryThread()) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
event.getEventName() + " cannot be triggered asynchronously from primary server thread.");
|
|
||||||
}
|
|
||||||
fireEventExcluding(event, plugins);
|
|
||||||
} else {
|
|
||||||
synchronized (Bukkit.getPluginManager()) {
|
|
||||||
fireEventExcluding(event, plugins);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void fireEventExcluding(Event event, String... plugins) {
|
server.getLogger().log(Level.SEVERE,
|
||||||
HandlerList handlers = event.getHandlers(); // Code taken from SimplePluginManager in Spigot-API
|
String.format("Nag author(s): '%s' of '%s' about the following: %s",
|
||||||
RegisteredListener[] listeners = handlers.getRegisteredListeners();
|
plugin.getDescription().getAuthors(), plugin.getDescription().getFullName(),
|
||||||
val server = Bukkit.getServer();
|
ex.getMessage()));
|
||||||
|
}
|
||||||
for (RegisteredListener registration : listeners) {
|
} catch (Throwable ex) {
|
||||||
if (!registration.getPlugin().isEnabled()
|
server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to "
|
||||||
|| Arrays.stream(plugins).anyMatch(p -> p.equalsIgnoreCase(registration.getPlugin().getName())))
|
+ registration.getPlugin().getDescription().getFullName(), ex);
|
||||||
continue; // Modified to exclude plugins
|
}
|
||||||
|
}
|
||||||
try {
|
}
|
||||||
registration.callEvent(event);
|
|
||||||
} catch (AuthorNagException ex) {
|
|
||||||
Plugin plugin = registration.getPlugin();
|
|
||||||
|
|
||||||
if (plugin.isNaggable()) {
|
|
||||||
plugin.setNaggable(false);
|
|
||||||
|
|
||||||
server.getLogger().log(Level.SEVERE,
|
|
||||||
String.format("Nag author(s): '%s' of '%s' about the following: %s",
|
|
||||||
plugin.getDescription().getAuthors(), plugin.getDescription().getFullName(),
|
|
||||||
ex.getMessage()));
|
|
||||||
}
|
|
||||||
} catch (Throwable ex) {
|
|
||||||
server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to "
|
|
||||||
+ registration.getPlugin().getDescription().getFullName(), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package buttondevteam.discordplugin.commands;
|
package buttondevteam.discordplugin.mcchat;
|
||||||
|
|
||||||
import buttondevteam.discordplugin.DiscordPlayer;
|
import buttondevteam.discordplugin.DiscordPlayer;
|
||||||
import buttondevteam.discordplugin.DiscordPlugin;
|
import buttondevteam.discordplugin.DiscordPlugin;
|
||||||
import buttondevteam.discordplugin.listeners.MCChatListener;
|
import buttondevteam.discordplugin.commands.DiscordCommandBase;
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
import sx.blah.discord.handle.obj.IMessage;
|
import sx.blah.discord.handle.obj.IMessage;
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ public class MCChatCommand extends DiscordCommandBase {
|
||||||
return "mcchat";
|
return "mcchat";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override //TODO: Only register if module is enabled
|
||||||
public boolean run(IMessage message, String args) {
|
public boolean run(IMessage message, String args) {
|
||||||
if (!message.getChannel().isPrivate()) {
|
if (!message.getChannel().isPrivate()) {
|
||||||
DiscordPlugin.sendMessageToChannel(message.getChannel(),
|
DiscordPlugin.sendMessageToChannel(message.getChannel(),
|
||||||
|
@ -22,10 +22,10 @@ public class MCChatCommand extends DiscordCommandBase {
|
||||||
}
|
}
|
||||||
try (final DiscordPlayer user = DiscordPlayer.getUser(message.getAuthor().getStringID(), DiscordPlayer.class)) {
|
try (final DiscordPlayer user = DiscordPlayer.getUser(message.getAuthor().getStringID(), DiscordPlayer.class)) {
|
||||||
boolean mcchat = !user.isMinecraftChatEnabled();
|
boolean mcchat = !user.isMinecraftChatEnabled();
|
||||||
MCChatListener.privateMCChat(message.getChannel(), mcchat, message.getAuthor(), user);
|
MCChatPrivate.privateMCChat(message.getChannel(), mcchat, message.getAuthor(), user);
|
||||||
DiscordPlugin.sendMessageToChannel(message.getChannel(),
|
DiscordPlugin.sendMessageToChannel(message.getChannel(),
|
||||||
"Minecraft chat " + (mcchat //
|
"Minecraft chat " + (mcchat //
|
||||||
? "enabled. Use '/mcchat' again to turn it off." //
|
? "enabled. Use '" + DiscordPlugin.getPrefix() + "mcchat' again to turn it off." //
|
||||||
: "disabled."));
|
: "disabled."));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
TBMCCoreAPI.SendException("Error while setting mcchat for user" + message.getAuthor().getName(), e);
|
TBMCCoreAPI.SendException("Error while setting mcchat for user" + message.getAuthor().getName(), e);
|
||||||
|
@ -36,8 +36,9 @@ public class MCChatCommand extends DiscordCommandBase {
|
||||||
@Override
|
@Override
|
||||||
public String[] getHelpText() {
|
public String[] getHelpText() {
|
||||||
return new String[] { //
|
return new String[] { //
|
||||||
"mcchat enables or disables the Minecraft chat in private messages.", //
|
DiscordPlugin.getPrefix() + "mcchat enables or disables the Minecraft chat in private messages.", //
|
||||||
"It can be useful if you don't want your messages to be visible, for example when talking a private channel." //
|
"It can be useful if you don't want your messages to be visible, for example when talking in a private channel.", //
|
||||||
|
"You can also run all of the ingame commands you have access to using this command, if you have your accounts connected." //
|
||||||
}; // TODO: Pin channel switching to indicate the current channel
|
}; // TODO: Pin channel switching to indicate the current channel
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package buttondevteam.discordplugin.mcchat;
|
||||||
|
|
||||||
|
import buttondevteam.discordplugin.DiscordConnectedPlayer;
|
||||||
|
import buttondevteam.lib.chat.Channel;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.val;
|
||||||
|
import sx.blah.discord.handle.obj.IChannel;
|
||||||
|
import sx.blah.discord.handle.obj.IUser;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class MCChatCustom {
|
||||||
|
/**
|
||||||
|
* Used for town or nation chats or anything else
|
||||||
|
*/
|
||||||
|
static ArrayList<CustomLMD> lastmsgCustom = new ArrayList<>();
|
||||||
|
|
||||||
|
public static void addCustomChat(IChannel channel, String groupid, Channel mcchannel, IUser user, DiscordConnectedPlayer dcp, int toggles) {
|
||||||
|
val lmd = new CustomLMD(channel, user, groupid, mcchannel, dcp, toggles);
|
||||||
|
lastmsgCustom.add(lmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasCustomChat(IChannel channel) {
|
||||||
|
return lastmsgCustom.stream().anyMatch(lmd -> lmd.channel.getLongID() == channel.getLongID());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static CustomLMD getCustomChat(IChannel channel) {
|
||||||
|
return lastmsgCustom.stream().filter(lmd -> lmd.channel.getLongID() == channel.getLongID()).findAny().orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean removeCustomChat(IChannel channel) {
|
||||||
|
MCChatUtils.lastmsgfromd.remove(channel.getLongID());
|
||||||
|
return lastmsgCustom.removeIf(lmd -> lmd.channel.getLongID() == channel.getLongID());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<CustomLMD> getCustomChats() {
|
||||||
|
return Collections.unmodifiableList(lastmsgCustom);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CustomLMD extends MCChatUtils.LastMsgData {
|
||||||
|
public final String groupID;
|
||||||
|
public final Channel mcchannel;
|
||||||
|
public final DiscordConnectedPlayer dcp;
|
||||||
|
public int toggles;
|
||||||
|
|
||||||
|
private CustomLMD(@NonNull IChannel channel, @NonNull IUser user,
|
||||||
|
@NonNull String groupid, @NonNull Channel mcchannel, @NonNull DiscordConnectedPlayer dcp, int toggles) {
|
||||||
|
super(channel, user);
|
||||||
|
groupID = groupid;
|
||||||
|
this.mcchannel = mcchannel;
|
||||||
|
this.dcp = dcp;
|
||||||
|
this.toggles = toggles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,56 +1,48 @@
|
||||||
package buttondevteam.discordplugin.listeners;
|
package buttondevteam.discordplugin.mcchat;
|
||||||
|
|
||||||
import buttondevteam.discordplugin.*;
|
import buttondevteam.core.ComponentManager;
|
||||||
|
import buttondevteam.discordplugin.DPUtils;
|
||||||
|
import buttondevteam.discordplugin.DiscordPlugin;
|
||||||
|
import buttondevteam.discordplugin.DiscordSender;
|
||||||
|
import buttondevteam.discordplugin.DiscordSenderBase;
|
||||||
|
import buttondevteam.discordplugin.listeners.CommandListener;
|
||||||
import buttondevteam.discordplugin.playerfaker.VanillaCommandListener;
|
import buttondevteam.discordplugin.playerfaker.VanillaCommandListener;
|
||||||
import buttondevteam.lib.TBMCChatEvent;
|
import buttondevteam.lib.TBMCChatEvent;
|
||||||
import buttondevteam.lib.TBMCChatPreprocessEvent;
|
import buttondevteam.lib.TBMCChatPreprocessEvent;
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
import buttondevteam.lib.TBMCSystemChatEvent;
|
|
||||||
import buttondevteam.lib.chat.Channel;
|
import buttondevteam.lib.chat.Channel;
|
||||||
import buttondevteam.lib.chat.ChatMessage;
|
import buttondevteam.lib.chat.ChatMessage;
|
||||||
import buttondevteam.lib.chat.ChatRoom;
|
import buttondevteam.lib.chat.ChatRoom;
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||||
import buttondevteam.lib.player.TBMCPlayer;
|
import buttondevteam.lib.player.TBMCPlayer;
|
||||||
import com.vdurmont.emoji.EmojiParser;
|
import com.vdurmont.emoji.EmojiParser;
|
||||||
import io.netty.util.collection.LongObjectHashMap;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.experimental.var;
|
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
import sx.blah.discord.api.events.IListener;
|
|
||||||
import sx.blah.discord.api.internal.json.objects.EmbedObject;
|
import sx.blah.discord.api.internal.json.objects.EmbedObject;
|
||||||
import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent;
|
import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent;
|
||||||
import sx.blah.discord.handle.obj.IChannel;
|
import sx.blah.discord.handle.obj.IChannel;
|
||||||
import sx.blah.discord.handle.obj.IMessage;
|
import sx.blah.discord.handle.obj.IMessage;
|
||||||
import sx.blah.discord.handle.obj.IPrivateChannel;
|
|
||||||
import sx.blah.discord.handle.obj.IUser;
|
import sx.blah.discord.handle.obj.IUser;
|
||||||
import sx.blah.discord.util.DiscordException;
|
import sx.blah.discord.util.DiscordException;
|
||||||
import sx.blah.discord.util.EmbedBuilder;
|
import sx.blah.discord.util.EmbedBuilder;
|
||||||
import sx.blah.discord.util.MissingPermissionsException;
|
import sx.blah.discord.util.MissingPermissionsException;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.*;
|
import java.util.AbstractMap;
|
||||||
import java.util.List;
|
import java.util.Arrays;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
public class MCChatListener implements Listener, IListener<MessageReceivedEvent> {
|
public class MCChatListener implements Listener {
|
||||||
private BukkitTask sendtask;
|
private BukkitTask sendtask;
|
||||||
private LinkedBlockingQueue<AbstractMap.SimpleEntry<TBMCChatEvent, Instant>> sendevents = new LinkedBlockingQueue<>();
|
private LinkedBlockingQueue<AbstractMap.SimpleEntry<TBMCChatEvent, Instant>> sendevents = new LinkedBlockingQueue<>();
|
||||||
private Runnable sendrunnable;
|
private Runnable sendrunnable;
|
||||||
|
@ -58,7 +50,7 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
|
|
||||||
@EventHandler // Minecraft
|
@EventHandler // Minecraft
|
||||||
public void onMCChat(TBMCChatEvent ev) {
|
public void onMCChat(TBMCChatEvent ev) {
|
||||||
if (DiscordPlugin.SafeMode || ev.isCancelled()) //SafeMode: Needed so it doesn't restart after server shutdown
|
if (!ComponentManager.isEnabled(MinecraftChatModule.class) || ev.isCancelled()) //SafeMode: Needed so it doesn't restart after server shutdown
|
||||||
return;
|
return;
|
||||||
sendevents.add(new AbstractMap.SimpleEntry<>(ev, Instant.now()));
|
sendevents.add(new AbstractMap.SimpleEntry<>(ev, Instant.now()));
|
||||||
if (sendtask != null)
|
if (sendtask != null)
|
||||||
|
@ -81,7 +73,7 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
time = se.getValue();
|
time = se.getValue();
|
||||||
|
|
||||||
final String authorPlayer = "[" + DPUtils.sanitizeStringNoEscape(e.getChannel().DisplayName) + "] " //
|
final String authorPlayer = "[" + DPUtils.sanitizeStringNoEscape(e.getChannel().DisplayName) + "] " //
|
||||||
+ (e.getSender() instanceof DiscordSenderBase ? "[D]" : "") //
|
+ ("Minecraft".equals(e.getOrigin()) ? "" : "[" + e.getOrigin().substring(0, 1) + "]") //
|
||||||
+ (DPUtils.sanitizeStringNoEscape(e.getSender() instanceof Player //
|
+ (DPUtils.sanitizeStringNoEscape(e.getSender() instanceof Player //
|
||||||
? ((Player) e.getSender()).getDisplayName() //
|
? ((Player) e.getSender()).getDisplayName() //
|
||||||
: e.getSender().getName()));
|
: e.getSender().getName()));
|
||||||
|
@ -102,7 +94,7 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
// embed.withFooterText(e.getChannel().DisplayName);
|
// embed.withFooterText(e.getChannel().DisplayName);
|
||||||
embed.withTimestamp(time);
|
embed.withTimestamp(time);
|
||||||
final long nanoTime = System.nanoTime();
|
final long nanoTime = System.nanoTime();
|
||||||
InterruptibleConsumer<LastMsgData> doit = lastmsgdata -> {
|
InterruptibleConsumer<MCChatUtils.LastMsgData> doit = lastmsgdata -> {
|
||||||
final EmbedObject embedObject = embed.build();
|
final EmbedObject embedObject = embed.build();
|
||||||
if (lastmsgdata.message == null || lastmsgdata.message.isDeleted()
|
if (lastmsgdata.message == null || lastmsgdata.message.isDeleted()
|
||||||
|| !authorPlayer.equals(lastmsgdata.message.getEmbeds().get(0).getAuthor().getName())
|
|| !authorPlayer.equals(lastmsgdata.message.getEmbeds().get(0).getAuthor().getName())
|
||||||
|
@ -117,7 +109,7 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
try {
|
try {
|
||||||
lastmsgdata.content = embedObject.description = lastmsgdata.content + "\n"
|
lastmsgdata.content = embedObject.description = lastmsgdata.content + "\n"
|
||||||
+ embedObject.description;// The message object doesn't get updated
|
+ embedObject.description;// The message object doesn't get updated
|
||||||
final LastMsgData _lastmsgdata = lastmsgdata;
|
final MCChatUtils.LastMsgData _lastmsgdata = lastmsgdata;
|
||||||
DPUtils.perform(() -> _lastmsgdata.message.edit("", embedObject));
|
DPUtils.perform(() -> _lastmsgdata.message.edit("", embedObject));
|
||||||
} catch (MissingPermissionsException | DiscordException e1) {
|
} catch (MissingPermissionsException | DiscordException e1) {
|
||||||
TBMCCoreAPI.SendException("An error occurred while editing chat message!", e1);
|
TBMCCoreAPI.SendException("An error occurred while editing chat message!", e1);
|
||||||
|
@ -129,21 +121,21 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
|| ((DiscordSenderBase) e.getSender()).getChannel().getLongID() != ch.getLongID();
|
|| ((DiscordSenderBase) e.getSender()).getChannel().getLongID() != ch.getLongID();
|
||||||
|
|
||||||
if (e.getChannel().isGlobal()
|
if (e.getChannel().isGlobal()
|
||||||
&& (e.isFromcmd() || isdifferentchannel.test(DiscordPlugin.chatchannel)))
|
&& (e.isFromCommand() || isdifferentchannel.test(DiscordPlugin.chatchannel)))
|
||||||
doit.accept(lastmsgdata == null
|
doit.accept(MCChatUtils.lastmsgdata == null
|
||||||
? lastmsgdata = new LastMsgData(DiscordPlugin.chatchannel, null)
|
? MCChatUtils.lastmsgdata = new MCChatUtils.LastMsgData(DiscordPlugin.chatchannel, null)
|
||||||
: lastmsgdata);
|
: MCChatUtils.lastmsgdata);
|
||||||
|
|
||||||
for (LastMsgData data : lastmsgPerUser) {
|
for (MCChatUtils.LastMsgData data : MCChatPrivate.lastmsgPerUser) {
|
||||||
if ((e.isFromcmd() || isdifferentchannel.test(data.channel))
|
if ((e.isFromCommand() || isdifferentchannel.test(data.channel))
|
||||||
&& e.shouldSendTo(getSender(data.channel, data.user)))
|
&& e.shouldSendTo(MCChatUtils.getSender(data.channel, data.user)))
|
||||||
doit.accept(data);
|
doit.accept(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
val iterator = lastmsgCustom.iterator();
|
val iterator = MCChatCustom.lastmsgCustom.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
val lmd = iterator.next();
|
val lmd = iterator.next();
|
||||||
if ((e.isFromcmd() || isdifferentchannel.test(lmd.channel)) //Test if msg is from Discord
|
if ((e.isFromCommand() || isdifferentchannel.test(lmd.channel)) //Test if msg is from Discord
|
||||||
&& e.getChannel().ID.equals(lmd.mcchannel.ID) //If it's from a command, the command msg has been deleted, so we need to send it
|
&& e.getChannel().ID.equals(lmd.mcchannel.ID) //If it's from a command, the command msg has been deleted, so we need to send it
|
||||||
&& e.getGroupID().equals(lmd.groupID)) { //Check if this is the group we want to test - #58
|
&& e.getGroupID().equals(lmd.groupID)) { //Check if this is the group we want to test - #58
|
||||||
if (e.shouldSendTo(lmd.dcp)) //Check original user's permissions
|
if (e.shouldSendTo(lmd.dcp)) //Check original user's permissions
|
||||||
|
@ -162,32 +154,6 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public static class LastMsgData {
|
|
||||||
public IMessage message;
|
|
||||||
public long time;
|
|
||||||
public String content;
|
|
||||||
public final IChannel channel;
|
|
||||||
public Channel mcchannel;
|
|
||||||
public final IUser user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class CustomLMD extends LastMsgData {
|
|
||||||
public final String groupID;
|
|
||||||
public final Channel mcchannel;
|
|
||||||
public final DiscordConnectedPlayer dcp;
|
|
||||||
public int toggles;
|
|
||||||
|
|
||||||
private CustomLMD(@NonNull IChannel channel, @NonNull IUser user,
|
|
||||||
@NonNull String groupid, @NonNull Channel mcchannel, @NonNull DiscordConnectedPlayer dcp, int toggles) {
|
|
||||||
super(channel, user);
|
|
||||||
groupID = groupid;
|
|
||||||
this.mcchannel = mcchannel;
|
|
||||||
this.dcp = dcp;
|
|
||||||
this.toggles = toggles;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onChatPreprocess(TBMCChatPreprocessEvent event) {
|
public void onChatPreprocess(TBMCChatPreprocessEvent event) {
|
||||||
int start = -1;
|
int start = -1;
|
||||||
|
@ -211,72 +177,8 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
private static final String[] UnconnectedCmds = new String[]{"list", "u", "shrug", "tableflip", "unflip", "mwiki",
|
private static final String[] UnconnectedCmds = new String[]{"list", "u", "shrug", "tableflip", "unflip", "mwiki",
|
||||||
"yeehaw", "lenny", "rp", "plugins"};
|
"yeehaw", "lenny", "rp", "plugins"};
|
||||||
|
|
||||||
private static LastMsgData lastmsgdata;
|
|
||||||
private static short lastlist = 0;
|
private static short lastlist = 0;
|
||||||
private static short lastlistp = 0;
|
private static short lastlistp = 0;
|
||||||
/**
|
|
||||||
* Used for messages in PMs (mcchat).
|
|
||||||
*/
|
|
||||||
private static ArrayList<LastMsgData> lastmsgPerUser = new ArrayList<LastMsgData>();
|
|
||||||
/**
|
|
||||||
* Used for town or nation chats or anything else
|
|
||||||
*/
|
|
||||||
private static ArrayList<CustomLMD> lastmsgCustom = new ArrayList<>();
|
|
||||||
private static LongObjectHashMap<IMessage> lastmsgfromd = new LongObjectHashMap<>(); // Last message sent by a Discord user, used for clearing checkmarks
|
|
||||||
|
|
||||||
public static boolean privateMCChat(IChannel channel, boolean start, IUser user, DiscordPlayer dp) {
|
|
||||||
TBMCPlayer mcp = dp.getAs(TBMCPlayer.class);
|
|
||||||
if (mcp != null) { // If the accounts aren't connected, can't make a connected sender
|
|
||||||
val p = Bukkit.getPlayer(mcp.getUUID());
|
|
||||||
val op = Bukkit.getOfflinePlayer(mcp.getUUID());
|
|
||||||
if (start) {
|
|
||||||
val sender = new DiscordConnectedPlayer(user, channel, mcp.getUUID(), op.getName());
|
|
||||||
addSender(ConnectedSenders, user, sender);
|
|
||||||
if (p == null)// Player is offline - If the player is online, that takes precedence
|
|
||||||
MCListener.callEventExcludingSome(new PlayerJoinEvent(sender, ""));
|
|
||||||
} else {
|
|
||||||
val sender = removeSender(ConnectedSenders, channel, user);
|
|
||||||
if (p == null)// Player is offline - If the player is online, that takes precedence
|
|
||||||
MCListener.callEventExcludingSome(new PlayerQuitEvent(sender, ""));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!start)
|
|
||||||
lastmsgfromd.remove(channel.getLongID());
|
|
||||||
return start //
|
|
||||||
? lastmsgPerUser.add(new LastMsgData(channel, user)) // Doesn't support group DMs
|
|
||||||
: lastmsgPerUser.removeIf(lmd -> lmd.channel.getLongID() == channel.getLongID());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends DiscordSenderBase> T addSender(HashMap<String, HashMap<IChannel, T>> senders,
|
|
||||||
IUser user, T sender) {
|
|
||||||
return addSender(senders, user.getStringID(), sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends DiscordSenderBase> T addSender(HashMap<String, HashMap<IChannel, T>> senders,
|
|
||||||
String did, T sender) {
|
|
||||||
var map = senders.get(did);
|
|
||||||
if (map == null)
|
|
||||||
map = new HashMap<>();
|
|
||||||
map.put(sender.getChannel(), sender);
|
|
||||||
senders.put(did, map);
|
|
||||||
return sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends DiscordSenderBase> T getSender(HashMap<String, HashMap<IChannel, T>> senders,
|
|
||||||
IChannel channel, IUser user) {
|
|
||||||
var map = senders.get(user.getStringID());
|
|
||||||
if (map != null)
|
|
||||||
return map.get(channel);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends DiscordSenderBase> T removeSender(HashMap<String, HashMap<IChannel, T>> senders,
|
|
||||||
IChannel channel, IUser user) {
|
|
||||||
var map = senders.get(user.getStringID());
|
|
||||||
if (map != null)
|
|
||||||
return map.remove(channel);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ......................DiscordSender....DiscordConnectedPlayer.DiscordPlayerSender
|
// ......................DiscordSender....DiscordConnectedPlayer.DiscordPlayerSender
|
||||||
// Offline public chat......x............................................
|
// Offline public chat......x............................................
|
||||||
|
@ -289,143 +191,8 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
// If online and disabling private chat, don't logout
|
// If online and disabling private chat, don't logout
|
||||||
// The maps may not contain the senders for UnconnectedSenders
|
// The maps may not contain the senders for UnconnectedSenders
|
||||||
|
|
||||||
public static boolean isMinecraftChatEnabled(DiscordPlayer dp) {
|
|
||||||
return isMinecraftChatEnabled(dp.getDiscordID());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isMinecraftChatEnabled(String did) { // Don't load the player data just for this
|
|
||||||
return lastmsgPerUser.stream()
|
|
||||||
.anyMatch(lmd -> ((IPrivateChannel) lmd.channel).getRecipient().getStringID().equals(did));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void addCustomChat(IChannel channel, String groupid, Channel mcchannel, IUser user, DiscordConnectedPlayer dcp, int toggles) {
|
|
||||||
val lmd = new CustomLMD(channel, user, groupid, mcchannel, dcp, toggles);
|
|
||||||
lastmsgCustom.add(lmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean hasCustomChat(IChannel channel) {
|
|
||||||
return lastmsgCustom.stream().anyMatch(lmd -> lmd.channel.getLongID() == channel.getLongID());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static CustomLMD getCustomChat(IChannel channel) {
|
|
||||||
return lastmsgCustom.stream().filter(lmd -> lmd.channel.getLongID() == channel.getLongID()).findAny().orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean removeCustomChat(IChannel channel) {
|
|
||||||
lastmsgfromd.remove(channel.getLongID());
|
|
||||||
return lastmsgCustom.removeIf(lmd -> lmd.channel.getLongID() == channel.getLongID());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<CustomLMD> getCustomChats() {
|
|
||||||
return Collections.unmodifiableList(lastmsgCustom);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* May contain P<DiscordID> as key for public chat
|
|
||||||
*/
|
|
||||||
public static final HashMap<String, HashMap<IChannel, DiscordSender>> UnconnectedSenders = new HashMap<>();
|
|
||||||
public static final HashMap<String, HashMap<IChannel, DiscordConnectedPlayer>> ConnectedSenders = new HashMap<>();
|
|
||||||
/**
|
|
||||||
* May contain P<DiscordID> as key for public chat
|
|
||||||
*/
|
|
||||||
public static final HashMap<String, HashMap<IChannel, DiscordPlayerSender>> OnlineSenders = new HashMap<>();
|
|
||||||
public static short ListC = 0;
|
public static short ListC = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets the last message, so it will start a new one instead of appending to it.
|
|
||||||
* This is used when someone (even the bot) sends a message to the channel.
|
|
||||||
*
|
|
||||||
* @param channel The channel to reset in - the process is slightly different for the public, private and custom chats
|
|
||||||
*/
|
|
||||||
public static void resetLastMessage(IChannel channel) {
|
|
||||||
if (channel.getLongID() == DiscordPlugin.chatchannel.getLongID()) {
|
|
||||||
(lastmsgdata == null ? lastmsgdata = new LastMsgData(DiscordPlugin.chatchannel, null)
|
|
||||||
: lastmsgdata).message = null;
|
|
||||||
return;
|
|
||||||
} // Don't set the whole object to null, the player and channel information should be preserved
|
|
||||||
for (LastMsgData data : channel.isPrivate() ? lastmsgPerUser : lastmsgCustom) {
|
|
||||||
if (data.channel.getLongID() == channel.getLongID()) {
|
|
||||||
data.message = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//If it gets here, it's sending a message to a non-chat channel
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void forAllMCChat(Consumer<IChannel> action) {
|
|
||||||
action.accept(DiscordPlugin.chatchannel);
|
|
||||||
for (LastMsgData data : lastmsgPerUser)
|
|
||||||
action.accept(data.channel);
|
|
||||||
// lastmsgCustom.forEach(cc -> action.accept(cc.channel)); - Only send relevant messages to custom chat
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For custom and all MC chat
|
|
||||||
*
|
|
||||||
* @param action The action to act
|
|
||||||
* @param toggle The toggle to check
|
|
||||||
* @param hookmsg Whether the message is also sent from the hook
|
|
||||||
*/
|
|
||||||
public static void forCustomAndAllMCChat(Consumer<IChannel> action, @Nullable ChannelconBroadcast toggle, boolean hookmsg) {
|
|
||||||
if (!DiscordPlugin.hooked || !hookmsg)
|
|
||||||
forAllMCChat(action);
|
|
||||||
final Consumer<CustomLMD> customLMDConsumer = cc -> action.accept(cc.channel);
|
|
||||||
if (toggle == null)
|
|
||||||
lastmsgCustom.forEach(customLMDConsumer);
|
|
||||||
else
|
|
||||||
lastmsgCustom.stream().filter(cc -> (cc.toggles & toggle.flag) != 0).forEach(customLMDConsumer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do the {@code action} for each custom chat the {@code sender} have access to and has that broadcast type enabled.
|
|
||||||
*
|
|
||||||
* @param action The action to do
|
|
||||||
* @param sender The sender to check perms of or null to send to all that has it toggled
|
|
||||||
* @param toggle The toggle to check or null to send to all allowed
|
|
||||||
*/
|
|
||||||
public static void forAllowedCustomMCChat(Consumer<IChannel> action, @Nullable CommandSender sender, @Nullable ChannelconBroadcast toggle) {
|
|
||||||
lastmsgCustom.stream().filter(clmd -> {
|
|
||||||
//new TBMCChannelConnectFakeEvent(sender, clmd.mcchannel).shouldSendTo(clmd.dcp) - Thought it was this simple hehe - Wait, it *should* be this simple
|
|
||||||
if (toggle != null && (clmd.toggles & toggle.flag) == 0)
|
|
||||||
return false; //If null then allow
|
|
||||||
if (sender == null)
|
|
||||||
return true;
|
|
||||||
return clmd.groupID.equals(clmd.mcchannel.getGroupID(sender));
|
|
||||||
}).forEach(cc -> action.accept(cc.channel)); //TODO: Send error messages on channel connect
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do the {@code action} for each custom chat the {@code sender} have access to and has that broadcast type enabled.
|
|
||||||
*
|
|
||||||
* @param action The action to do
|
|
||||||
* @param sender The sender to check perms of or null to send to all that has it toggled
|
|
||||||
* @param toggle The toggle to check or null to send to all allowed
|
|
||||||
* @param hookmsg Whether the message is also sent from the hook
|
|
||||||
*/
|
|
||||||
public static void forAllowedCustomAndAllMCChat(Consumer<IChannel> action, @Nullable CommandSender sender, @Nullable ChannelconBroadcast toggle, boolean hookmsg) {
|
|
||||||
if (!DiscordPlugin.hooked || !hookmsg)
|
|
||||||
forAllMCChat(action);
|
|
||||||
forAllowedCustomMCChat(action, sender, toggle);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Consumer<IChannel> send(String message) {
|
|
||||||
return ch -> DiscordPlugin.sendMessageToChannel(ch, DPUtils.sanitizeString(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void forAllowedMCChat(Consumer<IChannel> action, TBMCSystemChatEvent event) {
|
|
||||||
if (event.getChannel().isGlobal())
|
|
||||||
action.accept(DiscordPlugin.chatchannel);
|
|
||||||
for (LastMsgData data : lastmsgPerUser)
|
|
||||||
if (event.shouldSendTo(getSender(data.channel, data.user)))
|
|
||||||
action.accept(data.channel);
|
|
||||||
lastmsgCustom.stream().filter(clmd -> {
|
|
||||||
if ((clmd.toggles & ChannelconBroadcast.BROADCAST.flag) == 0)
|
|
||||||
return false;
|
|
||||||
return event.shouldSendTo(clmd.dcp);
|
|
||||||
}).map(clmd -> clmd.channel).forEach(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop the listener. Any calls to onMCChat will restart it as long as we're not in safe mode.
|
* Stop the listener. Any calls to onMCChat will restart it as long as we're not in safe mode.
|
||||||
*
|
*
|
||||||
|
@ -445,13 +212,13 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
if (wait)
|
if (wait)
|
||||||
recthread.join(5000);
|
recthread.join(5000);
|
||||||
}
|
}
|
||||||
lastmsgdata = null;
|
MCChatUtils.lastmsgdata = null;
|
||||||
lastmsgPerUser.clear();
|
MCChatPrivate.lastmsgPerUser.clear();
|
||||||
lastmsgCustom.clear();
|
MCChatCustom.lastmsgCustom.clear();
|
||||||
lastmsgfromd.clear();
|
MCChatUtils.lastmsgfromd.clear();
|
||||||
ConnectedSenders.clear();
|
MCChatUtils.ConnectedSenders.clear();
|
||||||
lastlist = lastlistp = ListC = 0;
|
lastlist = lastlistp = ListC = 0;
|
||||||
UnconnectedSenders.clear();
|
MCChatUtils.UnconnectedSenders.clear();
|
||||||
recthread = sendthread = null;
|
recthread = sendthread = null;
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace(); //This thread shouldn't be interrupted
|
e.printStackTrace(); //This thread shouldn't be interrupted
|
||||||
|
@ -463,27 +230,28 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
private Runnable recrun;
|
private Runnable recrun;
|
||||||
private static Thread recthread;
|
private static Thread recthread;
|
||||||
|
|
||||||
@Override // Discord
|
// Discord
|
||||||
public void handle(MessageReceivedEvent ev) {
|
public boolean handleDiscord(MessageReceivedEvent ev) {
|
||||||
if (DiscordPlugin.SafeMode)
|
if (!ComponentManager.isEnabled(MinecraftChatModule.class))
|
||||||
return;
|
return false;
|
||||||
val author = ev.getMessage().getAuthor();
|
val author = ev.getMessage().getAuthor();
|
||||||
if (author.isBot())
|
final boolean hasCustomChat = MCChatCustom.hasCustomChat(ev.getChannel());
|
||||||
return;
|
if (ev.getMessage().getChannel().getLongID() != DiscordPlugin.chatchannel.getLongID()
|
||||||
final boolean hasCustomChat = hasCustomChat(ev.getChannel());
|
&& !(ev.getMessage().getChannel().isPrivate() && MCChatPrivate.isMinecraftChatEnabled(author.getStringID()))
|
||||||
if (!ev.getMessage().getChannel().getStringID().equals(DiscordPlugin.chatchannel.getStringID())
|
|
||||||
&& !(ev.getMessage().getChannel().isPrivate() && isMinecraftChatEnabled(author.getStringID()))
|
|
||||||
&& !hasCustomChat)
|
&& !hasCustomChat)
|
||||||
return;
|
return false; //Chat isn't enabled on this channel
|
||||||
if (ev.getMessage().getContent().equalsIgnoreCase("mcchat"))
|
if (ev.getMessage().getChannel().isPrivate() //Only in private chat
|
||||||
return; // Race condition: If it gets here after it enabled mcchat it says it - I might as well allow disabling with this (CommandListener)
|
&& ev.getMessage().getContent().length() < "/mcchat<>".length()
|
||||||
|
&& ev.getMessage().getContent().replace("/", "")
|
||||||
|
.equalsIgnoreCase("mcchat")) //Either mcchat or /mcchat
|
||||||
|
return false; //Allow disabling the chat if needed
|
||||||
if (CommandListener.runCommand(ev.getMessage(), true))
|
if (CommandListener.runCommand(ev.getMessage(), true))
|
||||||
return;
|
return true; //Allow running commands in chat channels
|
||||||
resetLastMessage(ev.getChannel());
|
MCChatUtils.resetLastMessage(ev.getChannel());
|
||||||
lastlist++;
|
lastlist++;
|
||||||
recevents.add(ev);
|
recevents.add(ev);
|
||||||
if (rectask != null)
|
if (rectask != null)
|
||||||
return;
|
return true;
|
||||||
recrun = () -> { //Don't return in a while loop next time
|
recrun = () -> { //Don't return in a while loop next time
|
||||||
recthread = Thread.currentThread();
|
recthread = Thread.currentThread();
|
||||||
processDiscordToMC();
|
processDiscordToMC();
|
||||||
|
@ -491,6 +259,7 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
rectask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, recrun); //Continue message processing
|
rectask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, recrun); //Continue message processing
|
||||||
};
|
};
|
||||||
rectask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, recrun); //Start message processing
|
rectask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, recrun); //Start message processing
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processDiscordToMC() {
|
private void processDiscordToMC() {
|
||||||
|
@ -505,7 +274,7 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
val sender = event.getMessage().getAuthor();
|
val sender = event.getMessage().getAuthor();
|
||||||
String dmessage = event.getMessage().getContent();
|
String dmessage = event.getMessage().getContent();
|
||||||
try {
|
try {
|
||||||
final DiscordSenderBase dsender = getSender(event.getMessage().getChannel(), sender);
|
final DiscordSenderBase dsender = MCChatUtils.getSender(event.getMessage().getChannel(), sender);
|
||||||
val user = dsender.getChromaUser();
|
val user = dsender.getChromaUser();
|
||||||
|
|
||||||
for (IUser u : event.getMessage().getMentions()) {
|
for (IUser u : event.getMessage().getMentions()) {
|
||||||
|
@ -525,7 +294,7 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
.getAttachments().stream().map(IMessage.Attachment::getUrl).collect(Collectors.joining("\n"))
|
.getAttachments().stream().map(IMessage.Attachment::getUrl).collect(Collectors.joining("\n"))
|
||||||
: "");
|
: "");
|
||||||
|
|
||||||
CustomLMD clmd = getCustomChat(event.getChannel());
|
MCChatCustom.CustomLMD clmd = MCChatCustom.getCustomChat(event.getChannel());
|
||||||
|
|
||||||
boolean react = false;
|
boolean react = false;
|
||||||
|
|
||||||
|
@ -570,18 +339,13 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
() -> { //TODO: Better handling...
|
() -> { //TODO: Better handling...
|
||||||
val channel = user.channel();
|
val channel = user.channel();
|
||||||
val chtmp = channel.get();
|
val chtmp = channel.get();
|
||||||
//System.out.println("1: "+chtmp.ID);
|
|
||||||
//System.out.println("clmd: "+clmd);
|
|
||||||
if (clmd != null) {
|
if (clmd != null) {
|
||||||
channel.set(clmd.mcchannel); //Hack to send command in the channel
|
channel.set(clmd.mcchannel); //Hack to send command in the channel
|
||||||
//System.out.println("clmd chan: "+clmd.mcchannel.ID);
|
|
||||||
} //TODO: Permcheck isn't implemented for commands
|
} //TODO: Permcheck isn't implemented for commands
|
||||||
//System.out.println("2: "+channel.get().ID);
|
|
||||||
VanillaCommandListener.runBukkitOrVanillaCommand(dsender, cmd);
|
VanillaCommandListener.runBukkitOrVanillaCommand(dsender, cmd);
|
||||||
Bukkit.getLogger().info(dsender.getName() + " issued command from Discord: /" + cmdlowercased);
|
Bukkit.getLogger().info(dsender.getName() + " issued command from Discord: /" + cmdlowercased);
|
||||||
if (clmd != null)
|
if (clmd != null)
|
||||||
channel.set(chtmp);
|
channel.set(chtmp);
|
||||||
//System.out.println("3: "+channel.get().ID); - TODO: Remove
|
|
||||||
});
|
});
|
||||||
else {
|
else {
|
||||||
Channel chc = ch.get();
|
Channel chc = ch.get();
|
||||||
|
@ -619,8 +383,9 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
} else {// Not a command
|
} else {// Not a command
|
||||||
if (dmessage.length() == 0 && event.getMessage().getAttachments().size() == 0
|
if (dmessage.length() == 0 && event.getMessage().getAttachments().size() == 0
|
||||||
&& !event.getChannel().isPrivate() && event.getMessage().isSystemMessage()) {
|
&& !event.getChannel().isPrivate() && event.getMessage().isSystemMessage()) {
|
||||||
val rtr = clmd != null ? clmd.mcchannel.filteranderrormsg.apply(clmd.dcp) : dsender.getChromaUser().channel().get().filteranderrormsg.apply(dsender);
|
val rtr = clmd != null ? clmd.mcchannel.getRTR(clmd.dcp)
|
||||||
TBMCChatAPI.SendSystemMessage(clmd != null ? clmd.mcchannel : dsender.getChromaUser().channel().get(), rtr.score, rtr.groupID,
|
: dsender.getChromaUser().channel().get().getRTR(dsender);
|
||||||
|
TBMCChatAPI.SendSystemMessage(clmd != null ? clmd.mcchannel : dsender.getChromaUser().channel().get(), rtr,
|
||||||
(dsender instanceof Player ? ((Player) dsender).getDisplayName()
|
(dsender instanceof Player ? ((Player) dsender).getDisplayName()
|
||||||
: dsender.getName()) + " pinned a message on Discord.");
|
: dsender.getName()) + " pinned a message on Discord.");
|
||||||
}
|
}
|
||||||
|
@ -635,7 +400,7 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
}
|
}
|
||||||
if (react) {
|
if (react) {
|
||||||
try {
|
try {
|
||||||
val lmfd = lastmsgfromd.get(event.getChannel().getLongID());
|
val lmfd = MCChatUtils.lastmsgfromd.get(event.getChannel().getLongID());
|
||||||
if (lmfd != null) {
|
if (lmfd != null) {
|
||||||
DPUtils.perform(() -> lmfd.removeReaction(DiscordPlugin.dc.getOurUser(),
|
DPUtils.perform(() -> lmfd.removeReaction(DiscordPlugin.dc.getOurUser(),
|
||||||
DiscordPlugin.DELIVERED_REACTION)); // Remove it no matter what, we know it's there 99.99% of the time
|
DiscordPlugin.DELIVERED_REACTION)); // Remove it no matter what, we know it's there 99.99% of the time
|
||||||
|
@ -643,7 +408,7 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
TBMCCoreAPI.SendException("An error occured while removing reactions from chat!", e);
|
TBMCCoreAPI.SendException("An error occured while removing reactions from chat!", e);
|
||||||
}
|
}
|
||||||
lastmsgfromd.put(event.getChannel().getLongID(), event.getMessage());
|
MCChatUtils.lastmsgfromd.put(event.getChannel().getLongID(), event.getMessage());
|
||||||
DPUtils.perform(() -> event.getMessage().addReaction(DiscordPlugin.DELIVERED_REACTION));
|
DPUtils.perform(() -> event.getMessage().addReaction(DiscordPlugin.DELIVERED_REACTION));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -651,19 +416,6 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method will find the best sender to use: if the player is online, use that, if not but connected then use that etc.
|
|
||||||
*/
|
|
||||||
private static DiscordSenderBase getSender(IChannel channel, final IUser author) {
|
|
||||||
//noinspection OptionalGetWithoutIsPresent
|
|
||||||
return Stream.<Supplier<Optional<DiscordSenderBase>>>of( // https://stackoverflow.com/a/28833677/2703239
|
|
||||||
() -> Optional.ofNullable(getSender(OnlineSenders, channel, author)), // Find first non-null
|
|
||||||
() -> Optional.ofNullable(getSender(ConnectedSenders, channel, author)), // This doesn't support the public chat, but it'll always return null for it
|
|
||||||
() -> Optional.ofNullable(getSender(OnlineSenders, channel, author)), //
|
|
||||||
() -> Optional.of(addSender(UnconnectedSenders, author,
|
|
||||||
new DiscordSender(author, channel)))).map(Supplier::get).filter(Optional::isPresent).map(Optional::get).findFirst().get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
private interface InterruptibleConsumer<T> {
|
private interface InterruptibleConsumer<T> {
|
||||||
void accept(T value) throws TimeoutException, InterruptedException;
|
void accept(T value) throws TimeoutException, InterruptedException;
|
|
@ -0,0 +1,69 @@
|
||||||
|
package buttondevteam.discordplugin.mcchat;
|
||||||
|
|
||||||
|
import buttondevteam.discordplugin.DiscordConnectedPlayer;
|
||||||
|
import buttondevteam.discordplugin.DiscordPlayer;
|
||||||
|
import buttondevteam.discordplugin.DiscordPlugin;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayer;
|
||||||
|
import lombok.val;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
import sx.blah.discord.handle.obj.IChannel;
|
||||||
|
import sx.blah.discord.handle.obj.IPrivateChannel;
|
||||||
|
import sx.blah.discord.handle.obj.IUser;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import static buttondevteam.discordplugin.listeners.MCListener.callEventExcludingSome;
|
||||||
|
|
||||||
|
public class MCChatPrivate {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for messages in PMs (mcchat).
|
||||||
|
*/
|
||||||
|
static ArrayList<MCChatUtils.LastMsgData> lastmsgPerUser = new ArrayList<>();
|
||||||
|
|
||||||
|
public static boolean privateMCChat(IChannel channel, boolean start, IUser user, DiscordPlayer dp) {
|
||||||
|
TBMCPlayer mcp = dp.getAs(TBMCPlayer.class);
|
||||||
|
if (mcp != null) { // If the accounts aren't connected, can't make a connected sender
|
||||||
|
val p = Bukkit.getPlayer(mcp.getUUID());
|
||||||
|
val op = Bukkit.getOfflinePlayer(mcp.getUUID());
|
||||||
|
if (start) {
|
||||||
|
val sender = new DiscordConnectedPlayer(user, channel, mcp.getUUID(), op.getName());
|
||||||
|
MCChatUtils.addSender(MCChatUtils.ConnectedSenders, user, sender);
|
||||||
|
if (p == null)// Player is offline - If the player is online, that takes precedence
|
||||||
|
callEventSync(new PlayerJoinEvent(sender, ""));
|
||||||
|
} else {
|
||||||
|
val sender = MCChatUtils.removeSender(MCChatUtils.ConnectedSenders, channel, user);
|
||||||
|
if (p == null)// Player is offline - If the player is online, that takes precedence
|
||||||
|
callEventSync(new PlayerQuitEvent(sender, ""));
|
||||||
|
}
|
||||||
|
} // ---- PermissionsEx warning is normal on logout ----
|
||||||
|
if (!start)
|
||||||
|
MCChatUtils.lastmsgfromd.remove(channel.getLongID());
|
||||||
|
return start //
|
||||||
|
? lastmsgPerUser.add(new MCChatUtils.LastMsgData(channel, user)) // Doesn't support group DMs
|
||||||
|
: lastmsgPerUser.removeIf(lmd -> lmd.channel.getLongID() == channel.getLongID());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isMinecraftChatEnabled(DiscordPlayer dp) {
|
||||||
|
return isMinecraftChatEnabled(dp.getDiscordID());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isMinecraftChatEnabled(String did) { // Don't load the player data just for this
|
||||||
|
return lastmsgPerUser.stream()
|
||||||
|
.anyMatch(lmd -> ((IPrivateChannel) lmd.channel).getRecipient().getStringID().equals(did));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void logoutAll() {
|
||||||
|
for (val entry : MCChatUtils.ConnectedSenders.entrySet())
|
||||||
|
for (val valueEntry : entry.getValue().entrySet())
|
||||||
|
callEventExcludingSome(new PlayerQuitEvent(valueEntry.getValue(), "")); //This is sync
|
||||||
|
MCChatUtils.ConnectedSenders.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void callEventSync(Event event) {
|
||||||
|
Bukkit.getScheduler().runTask(DiscordPlugin.plugin, () -> callEventExcludingSome(event));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,218 @@
|
||||||
|
package buttondevteam.discordplugin.mcchat;
|
||||||
|
|
||||||
|
import buttondevteam.core.ComponentManager;
|
||||||
|
import buttondevteam.discordplugin.*;
|
||||||
|
import buttondevteam.discordplugin.broadcaster.GeneralEventBroadcasterModule;
|
||||||
|
import buttondevteam.lib.TBMCSystemChatEvent;
|
||||||
|
import buttondevteam.lib.chat.Channel;
|
||||||
|
import io.netty.util.collection.LongObjectHashMap;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.experimental.var;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import sx.blah.discord.handle.obj.IChannel;
|
||||||
|
import sx.blah.discord.handle.obj.IMessage;
|
||||||
|
import sx.blah.discord.handle.obj.IUser;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class MCChatUtils {
|
||||||
|
/**
|
||||||
|
* May contain P<DiscordID> as key for public chat
|
||||||
|
*/
|
||||||
|
public static final HashMap<String, HashMap<IChannel, DiscordSender>> UnconnectedSenders = new HashMap<>();
|
||||||
|
public static final HashMap<String, HashMap<IChannel, DiscordConnectedPlayer>> ConnectedSenders = new HashMap<>();
|
||||||
|
/**
|
||||||
|
* May contain P<DiscordID> as key for public chat
|
||||||
|
*/
|
||||||
|
public static final HashMap<String, HashMap<IChannel, DiscordPlayerSender>> OnlineSenders = new HashMap<>();
|
||||||
|
static @Nullable LastMsgData lastmsgdata;
|
||||||
|
static LongObjectHashMap<IMessage> lastmsgfromd = new LongObjectHashMap<>(); // Last message sent by a Discord user, used for clearing checkmarks
|
||||||
|
|
||||||
|
public static void updatePlayerList() {
|
||||||
|
if (notEnabled()) return;
|
||||||
|
DPUtils.performNoWait(() -> {
|
||||||
|
if (lastmsgdata != null)
|
||||||
|
updatePL(lastmsgdata);
|
||||||
|
MCChatCustom.lastmsgCustom.forEach(MCChatUtils::updatePL);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean notEnabled() {
|
||||||
|
return !ComponentManager.isEnabled(MinecraftChatModule.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void updatePL(LastMsgData lmd) {
|
||||||
|
String topic = lmd.channel.getTopic();
|
||||||
|
if (topic == null || topic.length() == 0)
|
||||||
|
topic = ".\n----\nMinecraft chat\n----\n.";
|
||||||
|
String[] s = topic.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(", "));
|
||||||
|
lmd.channel.changeTopic(String.join("\n----\n", s));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends DiscordSenderBase> T addSender(HashMap<String, HashMap<IChannel, T>> senders,
|
||||||
|
IUser user, T sender) {
|
||||||
|
return addSender(senders, user.getStringID(), sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends DiscordSenderBase> T addSender(HashMap<String, HashMap<IChannel, T>> senders,
|
||||||
|
String did, T sender) {
|
||||||
|
var map = senders.get(did);
|
||||||
|
if (map == null)
|
||||||
|
map = new HashMap<>();
|
||||||
|
map.put(sender.getChannel(), sender);
|
||||||
|
senders.put(did, map);
|
||||||
|
return sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends DiscordSenderBase> T getSender(HashMap<String, HashMap<IChannel, T>> senders,
|
||||||
|
IChannel channel, IUser user) {
|
||||||
|
var map = senders.get(user.getStringID());
|
||||||
|
if (map != null)
|
||||||
|
return map.get(channel);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends DiscordSenderBase> T removeSender(HashMap<String, HashMap<IChannel, T>> senders,
|
||||||
|
IChannel channel, IUser user) {
|
||||||
|
var map = senders.get(user.getStringID());
|
||||||
|
if (map != null)
|
||||||
|
return map.remove(channel);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void forAllMCChat(Consumer<IChannel> action) {
|
||||||
|
if (notEnabled()) return;
|
||||||
|
action.accept(DiscordPlugin.chatchannel);
|
||||||
|
for (LastMsgData data : MCChatPrivate.lastmsgPerUser)
|
||||||
|
action.accept(data.channel);
|
||||||
|
// lastmsgCustom.forEach(cc -> action.accept(cc.channel)); - Only send relevant messages to custom chat
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For custom and all MC chat
|
||||||
|
*
|
||||||
|
* @param action The action to act
|
||||||
|
* @param toggle The toggle to check
|
||||||
|
* @param hookmsg Whether the message is also sent from the hook
|
||||||
|
*/
|
||||||
|
public static void forCustomAndAllMCChat(Consumer<IChannel> action, @Nullable ChannelconBroadcast toggle, boolean hookmsg) {
|
||||||
|
if (notEnabled()) return;
|
||||||
|
if (!GeneralEventBroadcasterModule.isHooked() || !hookmsg)
|
||||||
|
forAllMCChat(action);
|
||||||
|
final Consumer<MCChatCustom.CustomLMD> customLMDConsumer = cc -> action.accept(cc.channel);
|
||||||
|
if (toggle == null)
|
||||||
|
MCChatCustom.lastmsgCustom.forEach(customLMDConsumer);
|
||||||
|
else
|
||||||
|
MCChatCustom.lastmsgCustom.stream().filter(cc -> (cc.toggles & toggle.flag) != 0).forEach(customLMDConsumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do the {@code action} for each custom chat the {@code sender} have access to and has that broadcast type enabled.
|
||||||
|
*
|
||||||
|
* @param action The action to do
|
||||||
|
* @param sender The sender to check perms of or null to send to all that has it toggled
|
||||||
|
* @param toggle The toggle to check or null to send to all allowed
|
||||||
|
*/
|
||||||
|
public static void forAllowedCustomMCChat(Consumer<IChannel> action, @Nullable CommandSender sender, @Nullable ChannelconBroadcast toggle) {
|
||||||
|
if (notEnabled()) return;
|
||||||
|
MCChatCustom.lastmsgCustom.stream().filter(clmd -> {
|
||||||
|
//new TBMCChannelConnectFakeEvent(sender, clmd.mcchannel).shouldSendTo(clmd.dcp) - Thought it was this simple hehe - Wait, it *should* be this simple
|
||||||
|
if (toggle != null && (clmd.toggles & toggle.flag) == 0)
|
||||||
|
return false; //If null then allow
|
||||||
|
if (sender == null)
|
||||||
|
return true;
|
||||||
|
return clmd.groupID.equals(clmd.mcchannel.getGroupID(sender));
|
||||||
|
}).forEach(cc -> action.accept(cc.channel)); //TODO: Send error messages on channel connect
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do the {@code action} for each custom chat the {@code sender} have access to and has that broadcast type enabled.
|
||||||
|
*
|
||||||
|
* @param action The action to do
|
||||||
|
* @param sender The sender to check perms of or null to send to all that has it toggled
|
||||||
|
* @param toggle The toggle to check or null to send to all allowed
|
||||||
|
* @param hookmsg Whether the message is also sent from the hook
|
||||||
|
*/
|
||||||
|
public static void forAllowedCustomAndAllMCChat(Consumer<IChannel> action, @Nullable CommandSender sender, @Nullable ChannelconBroadcast toggle, boolean hookmsg) {
|
||||||
|
if (notEnabled()) return;
|
||||||
|
if (!GeneralEventBroadcasterModule.isHooked() || !hookmsg)
|
||||||
|
forAllMCChat(action);
|
||||||
|
forAllowedCustomMCChat(action, sender, toggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Consumer<IChannel> send(String message) {
|
||||||
|
return ch -> DiscordPlugin.sendMessageToChannel(ch, DPUtils.sanitizeString(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void forAllowedMCChat(Consumer<IChannel> action, TBMCSystemChatEvent event) {
|
||||||
|
if (notEnabled()) return;
|
||||||
|
if (event.getChannel().isGlobal())
|
||||||
|
action.accept(DiscordPlugin.chatchannel);
|
||||||
|
for (LastMsgData data : MCChatPrivate.lastmsgPerUser)
|
||||||
|
if (event.shouldSendTo(getSender(data.channel, data.user)))
|
||||||
|
action.accept(data.channel);
|
||||||
|
MCChatCustom.lastmsgCustom.stream().filter(clmd -> {
|
||||||
|
if ((clmd.toggles & ChannelconBroadcast.BROADCAST.flag) == 0)
|
||||||
|
return false;
|
||||||
|
return event.shouldSendTo(clmd.dcp);
|
||||||
|
}).map(clmd -> clmd.channel).forEach(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will find the best sender to use: if the player is online, use that, if not but connected then use that etc.
|
||||||
|
*/
|
||||||
|
static DiscordSenderBase getSender(IChannel channel, final IUser author) {
|
||||||
|
//noinspection OptionalGetWithoutIsPresent
|
||||||
|
return Stream.<Supplier<Optional<DiscordSenderBase>>>of( // https://stackoverflow.com/a/28833677/2703239
|
||||||
|
() -> Optional.ofNullable(getSender(OnlineSenders, channel, author)), // Find first non-null
|
||||||
|
() -> Optional.ofNullable(getSender(ConnectedSenders, channel, author)), // This doesn't support the public chat, but it'll always return null for it
|
||||||
|
() -> Optional.ofNullable(getSender(UnconnectedSenders, channel, author)), //
|
||||||
|
() -> Optional.of(addSender(UnconnectedSenders, author,
|
||||||
|
new DiscordSender(author, channel)))).map(Supplier::get).filter(Optional::isPresent).map(Optional::get).findFirst().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the last message, so it will start a new one instead of appending to it.
|
||||||
|
* This is used when someone (even the bot) sends a message to the channel.
|
||||||
|
*
|
||||||
|
* @param channel The channel to reset in - the process is slightly different for the public, private and custom chats
|
||||||
|
*/
|
||||||
|
public static void resetLastMessage(IChannel channel) {
|
||||||
|
if (notEnabled()) return;
|
||||||
|
if (channel.getLongID() == DiscordPlugin.chatchannel.getLongID()) {
|
||||||
|
(lastmsgdata == null ? lastmsgdata = new LastMsgData(DiscordPlugin.chatchannel, null)
|
||||||
|
: lastmsgdata).message = null;
|
||||||
|
return;
|
||||||
|
} // Don't set the whole object to null, the player and channel information should be preserved
|
||||||
|
for (LastMsgData data : channel.isPrivate() ? MCChatPrivate.lastmsgPerUser : MCChatCustom.lastmsgCustom) {
|
||||||
|
if (data.channel.getLongID() == channel.getLongID()) {
|
||||||
|
data.message = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//If it gets here, it's sending a message to a non-chat channel
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public static class LastMsgData {
|
||||||
|
public IMessage message;
|
||||||
|
public long time;
|
||||||
|
public String content;
|
||||||
|
public final IChannel channel;
|
||||||
|
public Channel mcchannel;
|
||||||
|
public final IUser user;
|
||||||
|
}
|
||||||
|
}
|
153
src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java
Normal file
153
src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
package buttondevteam.discordplugin.mcchat;
|
||||||
|
|
||||||
|
import buttondevteam.discordplugin.*;
|
||||||
|
import buttondevteam.discordplugin.commands.ConnectCommand;
|
||||||
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
|
import buttondevteam.lib.TBMCSystemChatEvent;
|
||||||
|
import buttondevteam.lib.player.*;
|
||||||
|
import com.earth2me.essentials.CommandSource;
|
||||||
|
import lombok.val;
|
||||||
|
import net.ess3.api.events.AfkStatusChangeEvent;
|
||||||
|
import net.ess3.api.events.MuteStatusChangeEvent;
|
||||||
|
import net.ess3.api.events.NickChangeEvent;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.event.player.PlayerKickEvent;
|
||||||
|
import org.bukkit.event.player.PlayerLoginEvent;
|
||||||
|
import org.bukkit.event.player.PlayerLoginEvent.Result;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
import org.bukkit.event.server.BroadcastMessageEvent;
|
||||||
|
import sx.blah.discord.handle.obj.IRole;
|
||||||
|
import sx.blah.discord.handle.obj.IUser;
|
||||||
|
import sx.blah.discord.util.DiscordException;
|
||||||
|
import sx.blah.discord.util.MissingPermissionsException;
|
||||||
|
|
||||||
|
class MCListener implements Listener {
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public void onPlayerLogin(PlayerLoginEvent e) {
|
||||||
|
if (e.getResult() != Result.ALLOWED)
|
||||||
|
return;
|
||||||
|
MCChatUtils.ConnectedSenders.values().stream().flatMap(v -> v.values().stream()) //Only private mcchat should be in ConnectedSenders
|
||||||
|
.filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny()
|
||||||
|
.ifPresent(dcp -> buttondevteam.discordplugin.listeners.MCListener.callEventExcludingSome(new PlayerQuitEvent(dcp, "")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
|
public void onPlayerJoin(TBMCPlayerJoinEvent e) {
|
||||||
|
if (e.getPlayer() instanceof DiscordConnectedPlayer)
|
||||||
|
return; // Don't show the joined message for the fake player
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, () -> {
|
||||||
|
final Player p = e.getPlayer();
|
||||||
|
DiscordPlayer dp = e.GetPlayer().getAs(DiscordPlayer.class);
|
||||||
|
if (dp != null) {
|
||||||
|
val user = DiscordPlugin.dc.getUserByID(Long.parseLong(dp.getDiscordID()));
|
||||||
|
MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID(),
|
||||||
|
new DiscordPlayerSender(user, user.getOrCreatePMChannel(), p));
|
||||||
|
MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID(),
|
||||||
|
new DiscordPlayerSender(user, DiscordPlugin.chatchannel, p)); //Stored per-channel
|
||||||
|
}
|
||||||
|
if (ConnectCommand.WaitingToConnect.containsKey(e.GetPlayer().PlayerName().get())) {
|
||||||
|
IUser user = DiscordPlugin.dc
|
||||||
|
.getUserByID(Long.parseLong(ConnectCommand.WaitingToConnect.get(e.GetPlayer().PlayerName().get())));
|
||||||
|
p.sendMessage("§bTo connect with the Discord account @" + user.getName() + "#" + user.getDiscriminator()
|
||||||
|
+ " do /discord accept");
|
||||||
|
p.sendMessage("§bIf it wasn't you, do /discord decline");
|
||||||
|
}
|
||||||
|
final String message = e.GetPlayer().PlayerName().get() + " joined the game";
|
||||||
|
MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(message), e.getPlayer(), ChannelconBroadcast.JOINLEAVE, true);
|
||||||
|
MCChatListener.ListC = 0;
|
||||||
|
ChromaBot.getInstance().updatePlayerList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public void onPlayerLeave(TBMCPlayerQuitEvent e) {
|
||||||
|
if (e.getPlayer() instanceof DiscordConnectedPlayer)
|
||||||
|
return; // Only care about real users
|
||||||
|
MCChatUtils.OnlineSenders.entrySet()
|
||||||
|
.removeIf(entry -> entry.getValue().entrySet().stream().anyMatch(p -> p.getValue().getUniqueId().equals(e.getPlayer().getUniqueId())));
|
||||||
|
Bukkit.getScheduler().runTask(DiscordPlugin.plugin,
|
||||||
|
() -> MCChatUtils.ConnectedSenders.values().stream().flatMap(v -> v.values().stream())
|
||||||
|
.filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny()
|
||||||
|
.ifPresent(dcp -> buttondevteam.discordplugin.listeners.MCListener.callEventExcludingSome(new PlayerJoinEvent(dcp, ""))));
|
||||||
|
Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin,
|
||||||
|
ChromaBot.getInstance()::updatePlayerList, 5);
|
||||||
|
final String message = e.GetPlayer().PlayerName().get() + " left the game";
|
||||||
|
MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(message), e.getPlayer(), ChannelconBroadcast.JOINLEAVE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public void onPlayerKick(PlayerKickEvent e) {
|
||||||
|
/*if (!DiscordPlugin.hooked && !e.getReason().equals("The server is restarting")
|
||||||
|
&& !e.getReason().equals("Server closed")) // The leave messages errored with the previous setup, I could make it wait since I moved it here, but instead I have a special
|
||||||
|
MCChatListener.forAllowedCustomAndAllMCChat(e.getPlayer().getName() + " left the game"); // message for this - Oh wait this doesn't even send normally because of the hook*/
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.LOW)
|
||||||
|
public void onPlayerDeath(PlayerDeathEvent e) {
|
||||||
|
MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(e.getDeathMessage()), e.getEntity(), ChannelconBroadcast.DEATH, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerAFK(AfkStatusChangeEvent e) {
|
||||||
|
final Player base = e.getAffected().getBase();
|
||||||
|
if (e.isCancelled() || !base.isOnline())
|
||||||
|
return;
|
||||||
|
final String msg = base.getDisplayName()
|
||||||
|
+ " is " + (e.getValue() ? "now" : "no longer") + " AFK.";
|
||||||
|
MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(msg), base, ChannelconBroadcast.AFK, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerMute(MuteStatusChangeEvent e) {
|
||||||
|
try {
|
||||||
|
DPUtils.performNoWait(() -> {
|
||||||
|
final IRole role = DiscordPlugin.dc.getRoleByID(164090010461667328L);
|
||||||
|
final CommandSource source = e.getAffected().getSource();
|
||||||
|
if (!source.isPlayer())
|
||||||
|
return;
|
||||||
|
final DiscordPlayer p = TBMCPlayerBase.getPlayer(source.getPlayer().getUniqueId(), TBMCPlayer.class)
|
||||||
|
.getAs(DiscordPlayer.class);
|
||||||
|
if (p == null) return;
|
||||||
|
final IUser user = DiscordPlugin.dc.getUserByID(
|
||||||
|
Long.parseLong(p.getDiscordID()));
|
||||||
|
if (e.getValue())
|
||||||
|
user.addRole(role);
|
||||||
|
else
|
||||||
|
user.removeRole(role);
|
||||||
|
DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, (e.getValue() ? "M" : "Unm") + "uted user: " + user.getName());
|
||||||
|
});
|
||||||
|
} catch (DiscordException | MissingPermissionsException ex) {
|
||||||
|
TBMCCoreAPI.SendException("Failed to give/take Muted role to player " + e.getAffected().getName() + "!",
|
||||||
|
ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onChatSystemMessage(TBMCSystemChatEvent event) {
|
||||||
|
MCChatUtils.forAllowedMCChat(MCChatUtils.send(event.getMessage()), event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onBroadcastMessage(BroadcastMessageEvent event) {
|
||||||
|
MCChatUtils.forCustomAndAllMCChat(MCChatUtils.send(event.getMessage()), ChannelconBroadcast.BROADCAST, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onYEEHAW(TBMCYEEHAWEvent event) { //TODO: Inherit from the chat event base to have channel support
|
||||||
|
String name = event.getSender() instanceof Player ? ((Player) event.getSender()).getDisplayName()
|
||||||
|
: event.getSender().getName();
|
||||||
|
//Channel channel = ChromaGamerBase.getFromSender(event.getSender()).channel().get(); - TODO
|
||||||
|
MCChatUtils.forAllMCChat(MCChatUtils.send(name + " <:YEEHAW:" + DiscordPlugin.mainServer.getEmojiByName("YEEHAW").getStringID() + ">s"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onNickChange(NickChangeEvent event) {
|
||||||
|
MCChatUtils.updatePlayerList();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package buttondevteam.discordplugin.mcchat;
|
||||||
|
|
||||||
|
import buttondevteam.discordplugin.DiscordPlugin;
|
||||||
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
public class MinecraftChatModule extends Component {
|
||||||
|
private @Getter MCChatListener listener;
|
||||||
|
|
||||||
|
public MCChatListener getListener() { //It doesn't want to generate
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void enable() {
|
||||||
|
listener = new MCChatListener();
|
||||||
|
DiscordPlugin.dc.getDispatcher().registerListener(listener);
|
||||||
|
TBMCCoreAPI.RegisterEventsForExceptions(listener, getPlugin());
|
||||||
|
TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(), getPlugin());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void disable() {
|
||||||
|
//These get undone if restarting/resetting - it will ignore events if disabled
|
||||||
|
} //TODO: Use ComponentManager.isEnabled() at other places too, instead of SafeMode
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ package buttondevteam.discordplugin.mccommands;
|
||||||
|
|
||||||
import buttondevteam.discordplugin.DiscordPlayer;
|
import buttondevteam.discordplugin.DiscordPlayer;
|
||||||
import buttondevteam.discordplugin.commands.ConnectCommand;
|
import buttondevteam.discordplugin.commands.ConnectCommand;
|
||||||
import buttondevteam.discordplugin.listeners.MCChatListener;
|
import buttondevteam.discordplugin.mcchat.MCChatUtils;
|
||||||
import buttondevteam.lib.chat.CommandClass;
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
import buttondevteam.lib.player.ChromaGamerBase;
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
import buttondevteam.lib.player.TBMCPlayer;
|
import buttondevteam.lib.player.TBMCPlayer;
|
||||||
|
@ -35,7 +35,7 @@ public class AcceptMCCommand extends DiscordMCCommandBase {
|
||||||
dp.save();
|
dp.save();
|
||||||
mcp.save();
|
mcp.save();
|
||||||
ConnectCommand.WaitingToConnect.remove(player.getName());
|
ConnectCommand.WaitingToConnect.remove(player.getName());
|
||||||
MCChatListener.UnconnectedSenders.remove(did); //Remove all unconnected, will be recreated where needed
|
MCChatUtils.UnconnectedSenders.remove(did); //Remove all unconnected, will be recreated where needed
|
||||||
player.sendMessage("§bAccounts connected.");
|
player.sendMessage("§bAccounts connected.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue