>>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, (MessageChannel) DiscordPlugin.dc.getChannelById(channel).block())))).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(Channel channel) {
- if (notEnabled()) return;
- if (channel.getId().asLong() == module.chatChannel().get().asLong()) {
- (lastmsgdata == null ? lastmsgdata = new LastMsgData(module.chatChannelMono().block(), 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 instanceof PrivateChannel ? MCChatPrivate.lastmsgPerUser : MCChatCustom.lastmsgCustom) {
- if (data.channel.getId().asLong() == channel.getId().asLong()) {
- data.message = null;
- return;
- }
- }
- //If it gets here, it's sending a message to a non-chat channel
- }
-
- public static void addStaticExcludedPlugin(Class extends Event> event, String plugin) {
- staticExcludedPlugins.compute(event, (e, hs) -> hs == null
- ? Sets.newHashSet(plugin)
- : (hs.add(plugin) ? hs : hs));
- }
-
- public static void callEventExcludingSome(Event event) {
- if (notEnabled()) return;
- val second = staticExcludedPlugins.get(event.getClass());
- String[] first = module.excludedPlugins().get();
- String[] both = second == null ? first
- : Arrays.copyOf(first, first.length + second.size());
- int i = first.length;
- if (second != null)
- for (String plugin : second)
- both[i++] = plugin;
- callEventExcluding(event, false, both);
- }
-
- /**
- * Calls an event with the given details.
- *
- * This method only synchronizes when the event is not asynchronous.
- *
- * @param event Event details
- * @param only Flips the operation and includes the listed plugins
- * @param plugins The plugins to exclude. Not case sensitive.
- */
- @SuppressWarnings("WeakerAccess")
- 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);
- }
- }
- }
-
- private static void fireEventExcluding(Event event, boolean only, String... plugins) {
- HandlerList handlers = event.getHandlers(); // Code taken from SimplePluginManager in Spigot-API
- RegisteredListener[] listeners = handlers.getRegisteredListeners();
- val server = Bukkit.getServer();
-
- for (RegisteredListener registration : listeners) {
- if (!registration.getPlugin().isEnabled()
- || Arrays.stream(plugins).anyMatch(p -> only ^ p.equalsIgnoreCase(registration.getPlugin().getName())))
- 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);
- }
- }
- }
-
- /**
- * Call it from an async thread.
- */
- public static void callLoginEvents(DiscordConnectedPlayer dcp) {
- Consumer> loginFail = kickMsg -> {
- dcp.sendMessage("Minecraft chat disabled, as the login failed: " + kickMsg.get());
- MCChatPrivate.privateMCChat(dcp.getChannel(), false, dcp.getUser(), dcp.getChromaUser());
- }; //Probably also happens if the user is banned or so
- val event = new AsyncPlayerPreLoginEvent(dcp.getName(), InetAddress.getLoopbackAddress(), dcp.getUniqueId());
- callEventExcludingSome(event);
- if (event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
- loginFail.accept(event::getKickMessage);
- return;
- }
- Bukkit.getScheduler().runTask(DiscordPlugin.plugin, () -> {
- val ev = new PlayerLoginEvent(dcp, "localhost", InetAddress.getLoopbackAddress());
- callEventExcludingSome(ev);
- if (ev.getResult() != PlayerLoginEvent.Result.ALLOWED) {
- loginFail.accept(ev::getKickMessage);
- return;
- }
- callEventExcludingSome(new PlayerJoinEvent(dcp, ""));
- dcp.setLoggedIn(true);
- DPUtils.getLogger().info(dcp.getName() + " (" + dcp.getUniqueId() + ") logged in from Discord");
- });
- }
-
- /**
- * Only calls the events if the player is actually logged in
- *
- * @param dcp The player
- * @param needsSync Whether we're in an async thread
- */
- public static void callLogoutEvent(DiscordConnectedPlayer dcp, boolean needsSync) {
- if (!dcp.isLoggedIn()) return;
- val event = new PlayerQuitEvent(dcp, "");
- if (needsSync) callEventSync(event);
- else callEventExcludingSome(event);
- dcp.setLoggedIn(false);
- DPUtils.getLogger().info(dcp.getName() + " (" + dcp.getUniqueId() + ") logged out from Discord");
- }
-
- static void callEventSync(Event event) {
- Bukkit.getScheduler().runTask(DiscordPlugin.plugin, () -> callEventExcludingSome(event));
- }
-
- @RequiredArgsConstructor
- public static class LastMsgData {
- public Message message;
- public long time;
- public String content;
- public final MessageChannel channel;
- public buttondevteam.core.component.channel.Channel mcchannel;
- public final User user;
- }
-}
diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java
deleted file mode 100644
index 50843e6..0000000
--- a/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java
+++ /dev/null
@@ -1,185 +0,0 @@
-package buttondevteam.discordplugin.mcchat;
-
-import buttondevteam.discordplugin.*;
-import buttondevteam.lib.TBMCSystemChatEvent;
-import buttondevteam.lib.architecture.ConfigData;
-import buttondevteam.lib.player.TBMCPlayer;
-import buttondevteam.lib.player.TBMCPlayerBase;
-import buttondevteam.lib.player.TBMCYEEHAWEvent;
-import com.earth2me.essentials.CommandSource;
-import discord4j.core.object.entity.Role;
-import discord4j.core.object.util.Snowflake;
-import lombok.RequiredArgsConstructor;
-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.*;
-import org.bukkit.event.player.PlayerLoginEvent.Result;
-import org.bukkit.event.server.BroadcastMessageEvent;
-import org.bukkit.event.server.TabCompleteEvent;
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-import java.util.Optional;
-
-@RequiredArgsConstructor
-class MCListener implements Listener {
- private final MinecraftChatModule module;
-
- @EventHandler(priority = EventPriority.HIGHEST)
- public void onPlayerLogin(PlayerLoginEvent e) {
- if (e.getResult() != Result.ALLOWED)
- return;
- if (e.getPlayer() instanceof DiscordConnectedPlayer)
- 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 -> MCChatUtils.callLogoutEvent(dcp, false));
- }
-
- @EventHandler(priority = EventPriority.MONITOR)
- public void onPlayerJoin(PlayerJoinEvent 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 = TBMCPlayerBase.getPlayer(p.getUniqueId(), TBMCPlayer.class).getAs(DiscordPlayer.class);
- if (dp != null) {
- DiscordPlugin.dc.getUserById(Snowflake.of(dp.getDiscordID())).flatMap(user -> user.getPrivateChannel().flatMap(chan -> module.chatChannelMono().flatMap(cc -> {
- MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID(),
- new DiscordPlayerSender(user, chan, p));
- MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID(),
- new DiscordPlayerSender(user, cc, p)); //Stored per-channel
- return Mono.empty();
- }))).subscribe();
- }
- final String message = e.getJoinMessage();
- if (message != null && message.trim().length() > 0)
- MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(message), e.getPlayer(), ChannelconBroadcast.JOINLEAVE, true);
- ChromaBot.getInstance().updatePlayerList();
- });
- }
-
- @EventHandler(priority = EventPriority.MONITOR)
- public void onPlayerLeave(PlayerQuitEvent 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().runTaskAsynchronously(DiscordPlugin.plugin,
- () -> MCChatUtils.ConnectedSenders.values().stream().flatMap(v -> v.values().stream())
- .filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny()
- .ifPresent(MCChatUtils::callLoginEvents));
- Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin,
- ChromaBot.getInstance()::updatePlayerList, 5);
- final String message = e.getQuitMessage();
- if (message != null && message.trim().length() > 0)
- 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);
- }
-
- private ConfigData> muteRole() {
- return DPUtils.roleData(module.getConfig(), "muteRole", "Muted");
- }
-
- @EventHandler
- public void onPlayerMute(MuteStatusChangeEvent e) {
- final Mono role = muteRole().get();
- if (role == null) return;
- 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;
- DPUtils.ignoreError(DiscordPlugin.dc.getUserById(Snowflake.of(p.getDiscordID()))
- .flatMap(user -> user.asMember(DiscordPlugin.mainServer.getId()))
- .flatMap(user -> role.flatMap(r -> {
- if (e.getValue())
- user.addRole(r.getId());
- else
- user.removeRole(r.getId());
- val modlog = module.modlogChannel().get();
- String msg = (e.getValue() ? "M" : "Unm") + "uted user: " + user.getUsername() + "#" + user.getDiscriminator();
- DPUtils.getLogger().info(msg);
- if (modlog != null)
- return modlog.flatMap(ch -> ch.createMessage(msg));
- return Mono.empty();
- }))).subscribe();
- }
-
- @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
- DiscordPlugin.mainServer.getEmojis().filter(e -> "YEEHAW".equals(e.getName()))
- .take(1).singleOrEmpty().map(Optional::of).defaultIfEmpty(Optional.empty()).subscribe(yeehaw ->
- MCChatUtils.forAllMCChat(MCChatUtils.send(name + (yeehaw.map(guildEmoji -> " <:YEEHAW:" + guildEmoji.getId().asString() + ">s").orElse(" YEEHAWs")))));
- }
-
- @EventHandler
- public void onNickChange(NickChangeEvent event) {
- MCChatUtils.updatePlayerList();
- }
-
- @EventHandler
- public void onTabComplete(TabCompleteEvent event) {
- int i = event.getBuffer().lastIndexOf(' ');
- String t = event.getBuffer().substring(i + 1); //0 if not found
- //System.out.println("Last token: " + t);
- if (!t.startsWith("@"))
- return;
- String token = t.substring(1);
- //System.out.println("Token: " + token);
- val x = DiscordPlugin.mainServer.getMembers()
- .flatMap(m -> Flux.just(m.getUsername(), m.getNickname().orElse("")))
- .filter(s -> s.startsWith(token))
- .map(s -> "@" + s)
- .doOnNext(event.getCompletions()::add).blockLast();
- //System.out.println("Finished - last: " + x);
- }
-
- @EventHandler
- public void onCommandSend(PlayerCommandSendEvent event) {
- event.getCommands().add("g");
- }
-}
diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java b/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java
deleted file mode 100644
index 1018ba8..0000000
--- a/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java
+++ /dev/null
@@ -1,170 +0,0 @@
-package buttondevteam.discordplugin.mcchat;
-
-import buttondevteam.core.MainPlugin;
-import buttondevteam.core.component.channel.Channel;
-import buttondevteam.discordplugin.DPUtils;
-import buttondevteam.discordplugin.DiscordConnectedPlayer;
-import buttondevteam.discordplugin.DiscordPlugin;
-import buttondevteam.discordplugin.playerfaker.perm.LPInjector;
-import buttondevteam.lib.TBMCCoreAPI;
-import buttondevteam.lib.TBMCSystemChatEvent;
-import buttondevteam.lib.architecture.Component;
-import buttondevteam.lib.architecture.ConfigData;
-import buttondevteam.lib.architecture.ReadOnlyConfigData;
-import com.google.common.collect.Lists;
-import discord4j.core.object.entity.MessageChannel;
-import discord4j.core.object.util.Snowflake;
-import lombok.Getter;
-import lombok.val;
-import org.bukkit.Bukkit;
-import reactor.core.publisher.Mono;
-
-import java.util.ArrayList;
-import java.util.Objects;
-import java.util.UUID;
-import java.util.stream.Collectors;
-
-/**
- * Provides Minecraft chat connection to Discord. Commands may be used either in a public chat (limited) or in a DM.
- */
-public class MinecraftChatModule extends Component {
- private @Getter MCChatListener listener;
-
- /**
- * A list of commands that can be used in public chats - Warning: Some plugins will treat players as OPs, always test before allowing a command!
- */
- public ConfigData> whitelistedCommands() {
- return getConfig().getData("whitelistedCommands", () -> Lists.newArrayList("list", "u", "shrug", "tableflip", "unflip", "mwiki",
- "yeehaw", "lenny", "rp", "plugins"));
- }
-
- /**
- * The channel to use as the public Minecraft chat - everything public gets broadcasted here
- */
- public ReadOnlyConfigData chatChannel() {
- return DPUtils.snowflakeData(getConfig(), "chatChannel", 0L);
- }
-
- public Mono chatChannelMono() {
- return DPUtils.getMessageChannel(chatChannel().getPath(), chatChannel().get());
- }
-
- /**
- * The channel where the plugin can log when it mutes a player on Discord because of a Minecraft mute
- */
- public ReadOnlyConfigData> modlogChannel() {
- return DPUtils.channelData(getConfig(), "modlogChannel");
- }
-
- /**
- * The plugins to exclude from fake player events used for the 'mcchat' command - some plugins may crash, add them here
- */
- public ConfigData excludedPlugins() {
- return getConfig().getData("excludedPlugins", new String[]{"ProtocolLib", "LibsDisguises", "JourneyMapServer"});
- }
-
- /**
- * If this setting is on then players logged in through the 'mcchat' command will be able to teleport using plugin commands.
- * They can then use commands like /tpahere to teleport others to that place.
- * If this is off, then teleporting will have no effect.
- */
- public ConfigData allowFakePlayerTeleports() {
- return getConfig().getData("allowFakePlayerTeleports", false);
- }
-
- /**
- * If this is on, each chat channel will have a player list in their description.
- * It only gets added if there's no description yet or there are (at least) two lines of "----" following each other.
- * Note that it will replace everything between the first and last "----" but it will only detect exactly four dashes.
- * So if you want to use dashes for something else in the description, make sure it's either less or more dashes in one line.
- */
- public ConfigData showPlayerListOnDC() {
- return getConfig().getData("showPlayerListOnDC", true);
- }
-
- /**
- * This setting controls whether custom chat connections can be created (existing connections will always work).
- * Custom chat connections can be created using the channelcon command and they allow players to display town chat in a Discord channel for example.
- * See the channelcon command for more details.
- */
- public ConfigData allowCustomChat() {
- return getConfig().getData("allowCustomChat", true);
- }
-
- /**
- * This setting allows you to control if players can DM the bot to log on the server from Discord.
- * This allows them to both chat and perform any command they can in-game.
- */
- public ConfigData allowPrivateChat() {
- return getConfig().getData("allowPrivateChat", true);
- }
-
- /**
- * If set, message authors appearing on Discord will link to this URL. A 'type' and 'id' parameter will be added with the user's platform (Discord, Minecraft, ...) and ID.
- */
- public ConfigData profileURL() {
- return getConfig().getData("profileURL", "");
- }
-
- @Override
- protected void enable() {
- if (DPUtils.disableIfConfigErrorRes(this, chatChannel(), chatChannelMono()))
- return;
- /*clientID = DiscordPlugin.dc.getApplicationInfo().blockOptional().map(info->info.getId().asString())
- .orElse("Unknown"); //Need to block because otherwise it may not be set in time*/
- listener = new MCChatListener(this);
- TBMCCoreAPI.RegisterEventsForExceptions(listener, getPlugin());
- TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(this), getPlugin());//These get undone if restarting/resetting - it will ignore events if disabled
- getPlugin().getManager().registerCommand(new MCChatCommand(this));
- getPlugin().getManager().registerCommand(new ChannelconCommand(this));
-
- val chcons = getConfig().getConfig().getConfigurationSection("chcons");
- if (chcons == null) //Fallback to old place
- getConfig().getConfig().getRoot().getConfigurationSection("chcons");
- if (chcons != null) {
- val chconkeys = chcons.getKeys(false);
- for (val chconkey : chconkeys) {
- val chcon = chcons.getConfigurationSection(chconkey);
- val mcch = Channel.getChannels().filter(ch -> ch.ID.equals(chcon.getString("mcchid"))).findAny();
- val ch = DiscordPlugin.dc.getChannelById(Snowflake.of(chcon.getLong("chid"))).block();
- val did = chcon.getLong("did");
- val user = DiscordPlugin.dc.getUserById(Snowflake.of(did)).block();
- val groupid = chcon.getString("groupid");
- val toggles = chcon.getInt("toggles");
- val brtoggles = chcon.getStringList("brtoggles");
- if (!mcch.isPresent() || ch == null || user == null || groupid == null)
- continue;
- Bukkit.getScheduler().runTask(getPlugin(), () -> { //<-- Needed because of occasional ConcurrentModificationExceptions when creating the player (PermissibleBase)
- val dcp = DiscordConnectedPlayer.create(user, (MessageChannel) ch, UUID.fromString(chcon.getString("mcuid")), chcon.getString("mcname"), this);
- MCChatCustom.addCustomChat((MessageChannel) ch, groupid, mcch.get(), user, dcp, toggles, brtoggles.stream().map(TBMCSystemChatEvent.BroadcastTarget::get).filter(Objects::nonNull).collect(Collectors.toSet()));
- });
- }
- }
-
- try {
- new LPInjector(MainPlugin.Instance);
- } catch (Exception e) {
- TBMCCoreAPI.SendException("Failed to init LuckPerms injector", e);
- } catch (NoClassDefFoundError e) {
- getPlugin().getLogger().info("No LuckPerms, not injecting");
- }
- }
-
- @Override
- protected void disable() {
- val chcons = MCChatCustom.getCustomChats();
- val chconsc = getConfig().getConfig().createSection("chcons");
- for (val chcon : chcons) {
- val chconc = chconsc.createSection(chcon.channel.getId().asString());
- chconc.set("mcchid", chcon.mcchannel.ID);
- chconc.set("chid", chcon.channel.getId().asLong());
- chconc.set("did", chcon.user.getId().asLong());
- chconc.set("mcuid", chcon.dcp.getUniqueId().toString());
- chconc.set("mcname", chcon.dcp.getName());
- chconc.set("groupid", chcon.groupID);
- chconc.set("toggles", chcon.toggles);
- chconc.set("brtoggles", chcon.brtoggles.stream().map(TBMCSystemChatEvent.BroadcastTarget::getName).collect(Collectors.toList()));
- }
- MCChatListener.stop(true);
- }
-}
diff --git a/src/main/java/buttondevteam/discordplugin/mccommands/AcceptMCCommand.java b/src/main/java/buttondevteam/discordplugin/mccommands/AcceptMCCommand.java
new file mode 100755
index 0000000..13b3095
--- /dev/null
+++ b/src/main/java/buttondevteam/discordplugin/mccommands/AcceptMCCommand.java
@@ -0,0 +1,43 @@
+package buttondevteam.discordplugin.mccommands;
+
+import buttondevteam.discordplugin.DiscordPlayer;
+import buttondevteam.discordplugin.commands.ConnectCommand;
+import buttondevteam.discordplugin.listeners.MCChatListener;
+import buttondevteam.lib.chat.CommandClass;
+import buttondevteam.lib.player.ChromaGamerBase;
+import buttondevteam.lib.player.TBMCPlayer;
+import buttondevteam.lib.player.TBMCPlayerBase;
+import org.bukkit.entity.Player;
+
+@CommandClass(modOnly = false, path = "accept")
+public class AcceptMCCommand extends DiscordMCCommandBase {
+
+ @Override
+ public String[] GetHelpText(String alias) {
+ return new String[] { //
+ "§6---- Accept Discord connection ----", //
+ "Accept a pending connection between your Discord and Minecraft account.", //
+ "To start the connection process, do §b/connect §r in the #bot channel on Discord", //
+ "Usage: /" + alias + " accept" //
+ };
+ }
+
+ @Override
+ public boolean OnCommand(Player player, String alias, String[] args) {
+ String did = ConnectCommand.WaitingToConnect.get(player.getName());
+ if (did == null) {
+ player.sendMessage("§cYou don't have a pending connection to Discord.");
+ return true;
+ }
+ DiscordPlayer dp = ChromaGamerBase.getUser(did, DiscordPlayer.class);
+ TBMCPlayer mcp = TBMCPlayerBase.getPlayer(player.getUniqueId(), TBMCPlayer.class);
+ dp.connectWith(mcp);
+ dp.save();
+ mcp.save();
+ ConnectCommand.WaitingToConnect.remove(player.getName());
+ MCChatListener.UnconnectedSenders.remove(did);
+ player.sendMessage("§bAccounts connected.");
+ return true;
+ }
+
+}
diff --git a/src/main/java/buttondevteam/discordplugin/mccommands/DeclineMCCommand.java b/src/main/java/buttondevteam/discordplugin/mccommands/DeclineMCCommand.java
new file mode 100755
index 0000000..831ad89
--- /dev/null
+++ b/src/main/java/buttondevteam/discordplugin/mccommands/DeclineMCCommand.java
@@ -0,0 +1,31 @@
+package buttondevteam.discordplugin.mccommands;
+
+import buttondevteam.discordplugin.commands.ConnectCommand;
+import buttondevteam.lib.chat.CommandClass;
+import org.bukkit.entity.Player;
+
+@CommandClass(modOnly = false, path = "decline")
+public class DeclineMCCommand extends DiscordMCCommandBase {
+
+ @Override
+ public String[] GetHelpText(String alias) {
+ return new String[] { //
+ "§6---- Decline Discord connection ----", //
+ "Decline a pending connection between your Discord and Minecraft account.", //
+ "To start the connection process, do §b/connect §r in the #bot channel on Discord", //
+ "Usage: /" + alias + " decline" //
+ };
+ }
+
+ @Override
+ public boolean OnCommand(Player player, String alias, String[] args) {
+ String did = ConnectCommand.WaitingToConnect.remove(player.getName());
+ if (did == null) {
+ player.sendMessage("§cYou don't have a pending connection to Discord.");
+ return true;
+ }
+ player.sendMessage("§bPending connection declined.");
+ return true;
+ }
+
+}
diff --git a/src/main/java/buttondevteam/discordplugin/mccommands/DiscordMCCommand.java b/src/main/java/buttondevteam/discordplugin/mccommands/DiscordMCCommand.java
deleted file mode 100644
index 61d9d6b..0000000
--- a/src/main/java/buttondevteam/discordplugin/mccommands/DiscordMCCommand.java
+++ /dev/null
@@ -1,146 +0,0 @@
-package buttondevteam.discordplugin.mccommands;
-
-import buttondevteam.discordplugin.DPUtils;
-import buttondevteam.discordplugin.DiscordPlayer;
-import buttondevteam.discordplugin.DiscordPlugin;
-import buttondevteam.discordplugin.DiscordSenderBase;
-import buttondevteam.discordplugin.commands.ConnectCommand;
-import buttondevteam.discordplugin.commands.VersionCommand;
-import buttondevteam.discordplugin.mcchat.MCChatUtils;
-import buttondevteam.lib.chat.Command2;
-import buttondevteam.lib.chat.CommandClass;
-import buttondevteam.lib.chat.ICommand2MC;
-import buttondevteam.lib.player.ChromaGamerBase;
-import buttondevteam.lib.player.TBMCPlayer;
-import buttondevteam.lib.player.TBMCPlayerBase;
-import org.bukkit.Bukkit;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import reactor.core.publisher.Mono;
-
-import java.lang.reflect.Method;
-
-@CommandClass(path = "discord", helpText = {
- "Discord",
- "This command allows performing Discord-related actions."
-})
-public class DiscordMCCommand extends ICommand2MC {
- @Command2.Subcommand
- public boolean accept(Player player) {
- if (checkSafeMode(player)) return true;
- String did = ConnectCommand.WaitingToConnect.get(player.getName());
- if (did == null) {
- player.sendMessage("§cYou don't have a pending connection to Discord.");
- return true;
- }
- DiscordPlayer dp = ChromaGamerBase.getUser(did, DiscordPlayer.class);
- TBMCPlayer mcp = TBMCPlayerBase.getPlayer(player.getUniqueId(), TBMCPlayer.class);
- dp.connectWith(mcp);
- dp.save();
- mcp.save();
- ConnectCommand.WaitingToConnect.remove(player.getName());
- MCChatUtils.UnconnectedSenders.remove(did); //Remove all unconnected, will be recreated where needed
- player.sendMessage("§bAccounts connected.");
- return true;
- }
-
- @Command2.Subcommand
- public boolean decline(Player player) {
- if (checkSafeMode(player)) return true;
- String did = ConnectCommand.WaitingToConnect.remove(player.getName());
- if (did == null) {
- player.sendMessage("§cYou don't have a pending connection to Discord.");
- return true;
- }
- player.sendMessage("§bPending connection declined.");
- return true;
- }
-
- @Command2.Subcommand(permGroup = Command2.Subcommand.MOD_GROUP, helpText = {
- "Reload Discord plugin",
- "Reloads the config. To apply some changes, you may need to also run /discord reset."
- })
- public void reload(CommandSender sender) {
- if (DiscordPlugin.plugin.tryReloadConfig())
- sender.sendMessage("§bConfig reloaded.");
- else
- sender.sendMessage("§cFailed to reload config.");
- }
-
- public static boolean resetting = false;
-
- @Command2.Subcommand(permGroup = Command2.Subcommand.MOD_GROUP, helpText = {
- "Reset ChromaBot", //
- "This command disables and then enables the plugin." //
- })
- public void reset(CommandSender sender) {
- Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, () -> {
- if (!DiscordPlugin.plugin.tryReloadConfig()) {
- sender.sendMessage("§cFailed to reload config so not resetting. Check the console.");
- return;
- }
- resetting = true; //Turned off after sending enable message (ReadyEvent)
- sender.sendMessage("§bDisabling DiscordPlugin...");
- Bukkit.getPluginManager().disablePlugin(DiscordPlugin.plugin);
- if (!(sender instanceof DiscordSenderBase)) //Sending to Discord errors
- sender.sendMessage("§bEnabling DiscordPlugin...");
- Bukkit.getPluginManager().enablePlugin(DiscordPlugin.plugin);
- if (!(sender instanceof DiscordSenderBase)) //Sending to Discord errors
- sender.sendMessage("§bReset finished!");
- });
- }
-
- @Command2.Subcommand(helpText = {
- "Version command",
- "Prints the plugin version"
- })
- public void version(CommandSender sender) {
- sender.sendMessage(VersionCommand.getVersion());
- }
-
- @Command2.Subcommand(helpText = {
- "Invite",
- "Shows an invite link to the server"
- })
- public void invite(CommandSender sender) {
- if (checkSafeMode(sender)) return;
- String invi = DiscordPlugin.plugin.inviteLink().get();
- if (invi.length() > 0) {
- sender.sendMessage("§bInvite link: " + invi);
- return;
- }
- DiscordPlugin.mainServer.getInvites().limitRequest(1)
- .switchIfEmpty(Mono.fromRunnable(() -> sender.sendMessage("§cNo invites found for the server.")))
- .subscribe(inv -> {
- sender.sendMessage("§bInvite link: https://discord.gg/" + inv.getCode());
- }, e -> sender.sendMessage("§cThe invite link is not set and the bot has no permission to get it."));
- }
-
- @Override
- public String[] getHelpText(Method method, Command2.Subcommand ann) {
- switch (method.getName()) {
- case "accept":
- return new String[]{ //
- "Accept Discord connection", //
- "Accept a pending connection between your Discord and Minecraft account.", //
- "To start the connection process, do §b/connect §r in the " + DPUtils.botmention() + " channel on Discord", //
- };
- case "decline":
- return new String[]{ //
- "Decline Discord connection", //
- "Decline a pending connection between your Discord and Minecraft account.", //
- "To start the connection process, do §b/connect §r in the " + DPUtils.botmention() + " channel on Discord", //
- };
- default:
- return super.getHelpText(method, ann);
- }
- }
-
- private boolean checkSafeMode(CommandSender sender) {
- if (DiscordPlugin.SafeMode) {
- sender.sendMessage("§cThe plugin isn't initialized. Check console for details.");
- return true;
- }
- return false;
- }
-}
diff --git a/src/main/java/buttondevteam/discordplugin/mccommands/DiscordMCCommandBase.java b/src/main/java/buttondevteam/discordplugin/mccommands/DiscordMCCommandBase.java
new file mode 100755
index 0000000..5edbafe
--- /dev/null
+++ b/src/main/java/buttondevteam/discordplugin/mccommands/DiscordMCCommandBase.java
@@ -0,0 +1,9 @@
+package buttondevteam.discordplugin.mccommands;
+
+import buttondevteam.lib.chat.CommandClass;
+import buttondevteam.lib.chat.PlayerCommandBase;
+
+@CommandClass(modOnly = false, path = "discord")
+public abstract class DiscordMCCommandBase extends PlayerCommandBase {
+
+}
diff --git a/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordEntity.java b/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordEntity.java
new file mode 100755
index 0000000..6ce85f8
--- /dev/null
+++ b/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordEntity.java
@@ -0,0 +1,300 @@
+package buttondevteam.discordplugin.playerfaker;
+
+import buttondevteam.discordplugin.DiscordSenderBase;
+import lombok.Getter;
+import lombok.Setter;
+import org.bukkit.*;
+import org.bukkit.block.PistonMoveReaction;
+import org.bukkit.entity.Entity;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
+import org.bukkit.metadata.MetadataValue;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.util.Vector;
+import sx.blah.discord.handle.obj.IChannel;
+import sx.blah.discord.handle.obj.IUser;
+
+import java.util.*;
+
+@Getter
+@Setter
+@SuppressWarnings("deprecated")
+public abstract class DiscordEntity extends DiscordSenderBase implements Entity {
+ protected DiscordEntity(IUser user, IChannel channel, int entityId, UUID uuid) {
+ super(user, channel);
+ this.entityId = entityId;
+ uniqueId = uuid;
+ }
+
+ private HashMap metadata = new HashMap();
+
+ private Location location = new Location(Bukkit.getWorlds().get(0), 0, 0, 0);
+ private Vector velocity;
+ private final int entityId;
+ private EntityDamageEvent lastDamageCause;
+ private final Set scoreboardTags = new HashSet();
+ private final UUID uniqueId;
+
+ @Override
+ public void setMetadata(String metadataKey, MetadataValue newMetadataValue) {
+ metadata.put(metadataKey, newMetadataValue);
+ }
+
+ @Override
+ public List getMetadata(String metadataKey) {
+ return Arrays.asList(metadata.get(metadataKey)); // Who needs multiple data anyways
+ }
+
+ @Override
+ public boolean hasMetadata(String metadataKey) {
+ return metadata.containsKey(metadataKey);
+ }
+
+ @Override
+ public void removeMetadata(String metadataKey, Plugin owningPlugin) {
+ metadata.remove(metadataKey);
+ }
+
+ @Override
+ public Location getLocation(Location loc) {
+ if (loc != null) {
+ loc.setWorld(getWorld());
+ loc.setX(location.getX());
+ loc.setY(location.getY());
+ loc.setZ(location.getZ());
+ loc.setYaw(location.getYaw());
+ loc.setPitch(location.getPitch());
+ }
+
+ return loc;
+ }
+
+ @Override
+ public double getHeight() {
+ return 0;
+ }
+
+ @Override
+ public double getWidth() {
+ return 0;
+ }
+
+ @Override
+ public boolean isOnGround() {
+ return false;
+ }
+
+ @Override
+ public World getWorld() {
+ return location.getWorld();
+ }
+
+ @Override
+ public boolean teleport(Location location) {
+ this.location = location;
+ return true;
+ }
+
+ @Override
+ public boolean teleport(Location location, TeleportCause cause) {
+ this.location = location;
+ return true;
+ }
+
+ @Override
+ public boolean teleport(Entity destination) {
+ this.location = destination.getLocation();
+ return true;
+ }
+
+ @Override
+ public boolean teleport(Entity destination, TeleportCause cause) {
+ this.location = destination.getLocation();
+ return true;
+ }
+
+ @Override
+ public List getNearbyEntities(double x, double y, double z) {
+ return Arrays.asList();
+ }
+
+ @Override
+ public int getFireTicks() {
+ return 0;
+ }
+
+ @Override
+ public int getMaxFireTicks() {
+ return 0;
+ }
+
+ @Override
+ public void setFireTicks(int ticks) {
+ }
+
+ @Override
+ public void remove() {
+ }
+
+ @Override
+ public boolean isDead() { // Impossible to kill
+ return false;
+ }
+
+ @Override
+ public boolean isValid() {
+ return true;
+ }
+
+ @Override
+ public Server getServer() {
+ return Bukkit.getServer();
+ }
+
+ @Override
+ public Entity getPassenger() {
+ return null;
+ }
+
+ @Override
+ public boolean setPassenger(Entity passenger) {
+ return false;
+ }
+
+ @Override
+ public List getPassengers() {
+ return Arrays.asList();
+ }
+
+ @Override
+ public boolean addPassenger(Entity passenger) {
+ return false;
+ }
+
+ @Override
+ public boolean removePassenger(Entity passenger) { // Don't support passengers
+ return false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return true;
+ }
+
+ @Override
+ public boolean eject() {
+ return false;
+ }
+
+ @Override
+ public float getFallDistance() {
+ return 0;
+ }
+
+ @Override
+ public void setFallDistance(float distance) {
+ }
+
+ @Override
+ public int getTicksLived() {
+ return 1;
+ }
+
+ @Override
+ public void setTicksLived(int value) {
+ }
+
+ @Override
+ public void playEffect(EntityEffect type) {
+ }
+
+ @Override
+ public boolean isInsideVehicle() {
+ return false;
+ }
+
+ @Override
+ public boolean leaveVehicle() {
+ return false;
+ }
+
+ @Override
+ public Entity getVehicle() { // Don't support vehicles
+ return null;
+ }
+
+ @Override
+ public void setCustomNameVisible(boolean flag) {
+ }
+
+ @Override
+ public boolean isCustomNameVisible() {
+ return true;
+ }
+
+ @Override
+ public void setGlowing(boolean flag) {
+ }
+
+ @Override
+ public boolean isGlowing() {
+ return false;
+ }
+
+ @Override
+ public void setInvulnerable(boolean flag) {
+ }
+
+ @Override
+ public boolean isInvulnerable() {
+ return true;
+ }
+
+ @Override
+ public boolean isSilent() {
+ return true;
+ }
+
+ @Override
+ public void setSilent(boolean flag) {
+ }
+
+ @Override
+ public boolean hasGravity() {
+ return false;
+ }
+
+ @Override
+ public void setGravity(boolean gravity) {
+ }
+
+ @Override
+ public int getPortalCooldown() {
+ return 0;
+ }
+
+ @Override
+ public void setPortalCooldown(int cooldown) {
+ }
+
+ @Override
+ public boolean addScoreboardTag(String tag) {
+ return scoreboardTags.add(tag);
+ }
+
+ @Override
+ public boolean removeScoreboardTag(String tag) {
+ return scoreboardTags.remove(tag);
+ }
+
+ @Override
+ public PistonMoveReaction getPistonMoveReaction() {
+ return PistonMoveReaction.IGNORE;
+ }
+
+ @Override
+ public Entity.Spigot spigot() {
+ return new Entity.Spigot();
+ }
+
+}
diff --git a/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordFakePlayer.java b/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordFakePlayer.java
new file mode 100755
index 0000000..c5b2c5c
--- /dev/null
+++ b/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordFakePlayer.java
@@ -0,0 +1,716 @@
+package buttondevteam.discordplugin.playerfaker;
+
+import buttondevteam.discordplugin.DiscordPlugin;
+import lombok.Getter;
+import lombok.experimental.Delegate;
+import org.bukkit.*;
+import org.bukkit.advancement.Advancement;
+import org.bukkit.advancement.AdvancementProgress;
+import org.bukkit.conversations.Conversation;
+import org.bukkit.conversations.ConversationAbandonedEvent;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+import org.bukkit.event.player.AsyncPlayerChatEvent;
+import org.bukkit.map.MapView;
+import org.bukkit.permissions.PermissibleBase;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.scoreboard.Scoreboard;
+import sx.blah.discord.handle.obj.IChannel;
+import sx.blah.discord.handle.obj.IUser;
+
+import java.net.InetSocketAddress;
+import java.util.*;
+
+public class DiscordFakePlayer extends DiscordHumanEntity implements Player {
+ protected DiscordFakePlayer(IUser user, IChannel channel, int entityId, UUID uuid, String mcname) {
+ super(user, channel, entityId, uuid);
+ perm = new PermissibleBase(Bukkit.getOfflinePlayer(uuid));
+ name = mcname;
+ }
+
+ @Delegate
+ private PermissibleBase perm;
+
+ private @Getter String name;
+
+ @Override
+ public EntityType getType() {
+ return EntityType.PLAYER;
+ }
+
+ @Override
+ public String getCustomName() {
+ return user.getName();
+ }
+
+ @Override
+ public void setCustomName(String name) {
+ }
+
+ @Override
+ public boolean isConversing() {
+
+ return false;
+ }
+
+ @Override
+ public void acceptConversationInput(String input) {
+ }
+
+ @Override
+ public boolean beginConversation(Conversation conversation) {
+ return false;
+ }
+
+ @Override
+ public void abandonConversation(Conversation conversation) {
+ }
+
+ @Override
+ public void abandonConversation(Conversation conversation, ConversationAbandonedEvent details) {
+ }
+
+ @Override
+ public boolean isOnline() {
+ return true;// Let's pretend
+ }
+
+ @Override
+ public boolean isBanned() {
+ return false;
+ }
+
+ @Override
+ public boolean isWhitelisted() {
+ return true;
+ }
+
+ @Override
+ public void setWhitelisted(boolean value) {
+ }
+
+ @Override
+ public Player getPlayer() {
+ return this;
+ }
+
+ @Override
+ public long getFirstPlayed() {
+ return 0;
+ }
+
+ @Override
+ public long getLastPlayed() {
+ return 0;
+ }
+
+ @Override
+ public boolean hasPlayedBefore() {
+ return false;
+ }
+
+ @Override
+ public Map serialize() {
+ return new HashMap<>();
+ }
+
+ @Override
+ public void sendPluginMessage(Plugin source, String channel, byte[] message) {
+ }
+
+ @Override
+ public Set getListeningPluginChannels() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public String getDisplayName() {
+ return user.getDisplayName(DiscordPlugin.mainServer);
+ }
+
+ @Override
+ public void setDisplayName(String name) {
+ }
+
+ @Override
+ public String getPlayerListName() {
+ return getName();
+ }
+
+ @Override
+ public void setPlayerListName(String name) {
+ }
+
+ @Override
+ public void setCompassTarget(Location loc) {
+ }
+
+ @Override
+ public Location getCompassTarget() {
+ return new Location(Bukkit.getWorlds().get(0), 0, 0, 0);
+ }
+
+ @Override
+ public InetSocketAddress getAddress() {
+ return null;
+ }
+
+ @Override
+ public void sendRawMessage(String message) {
+ sendMessage(message);
+ }
+
+ @Override
+ public void kickPlayer(String message) {
+ }
+
+ @Override
+ public void chat(String msg) {
+ Bukkit.getPluginManager()
+ .callEvent(new AsyncPlayerChatEvent(true, this, msg, new HashSet<>(Bukkit.getOnlinePlayers())));
+ }
+
+ @Override
+ public boolean performCommand(String command) {
+ return Bukkit.getServer().dispatchCommand(this, command);
+ }
+
+ @Override
+ public boolean isSneaking() {
+ return false;
+ }
+
+ @Override
+ public void setSneaking(boolean sneak) {
+ }
+
+ @Override
+ public boolean isSprinting() {
+ return false;
+ }
+
+ @Override
+ public void setSprinting(boolean sprinting) {
+ }
+
+ @Override
+ public void saveData() {
+ }
+
+ @Override
+ public void loadData() {
+ }
+
+ @Override
+ public void setSleepingIgnored(boolean isSleeping) {
+ }
+
+ @Override
+ public boolean isSleepingIgnored() {
+ return false;
+ }
+
+ @Override
+ public void playNote(Location loc, byte instrument, byte note) {
+ }
+
+ @Override
+ public void playNote(Location loc, Instrument instrument, Note note) {
+ }
+
+ @Override
+ public void playSound(Location location, Sound sound, float volume, float pitch) {
+ }
+
+ @Override
+ public void playSound(Location location, String sound, float volume, float pitch) {
+ }
+
+ @Override
+ public void playSound(Location location, Sound sound, SoundCategory category, float volume, float pitch) {
+ }
+
+ @Override
+ public void playSound(Location location, String sound, SoundCategory category, float volume, float pitch) {
+ }
+
+ @Override
+ public void stopSound(Sound sound) {
+ }
+
+ @Override
+ public void stopSound(String sound) {
+ }
+
+ @Override
+ public void stopSound(Sound sound, SoundCategory category) {
+ }
+
+ @Override
+ public void stopSound(String sound, SoundCategory category) {
+ }
+
+ @Override
+ public void playEffect(Location loc, Effect effect, int data) {
+ }
+
+ @Override
+ public void playEffect(Location loc, Effect effect, T data) {
+ }
+
+ @Override
+ public void sendBlockChange(Location loc, Material material, byte data) {
+ }
+
+ @Override
+ public boolean sendChunkChange(Location loc, int sx, int sy, int sz, byte[] data) {
+ return false;
+ }
+
+ @Override
+ public void sendBlockChange(Location loc, int material, byte data) {
+ }
+
+ @Override
+ public void sendSignChange(Location loc, String[] lines) throws IllegalArgumentException {
+ }
+
+ @Override
+ public void sendMap(MapView map) {
+ }
+
+ @Override
+ public void updateInventory() {
+ }
+
+ @Override
+ public void awardAchievement(@SuppressWarnings("deprecation") Achievement achievement) {
+ }
+
+ @Override
+ public void removeAchievement(@SuppressWarnings("deprecation") Achievement achievement) {
+ }
+
+ @Override
+ public boolean hasAchievement(@SuppressWarnings("deprecation") Achievement achievement) {
+ return false;
+ }
+
+ @Override
+ public void incrementStatistic(Statistic statistic) throws IllegalArgumentException {
+ }
+
+ @Override
+ public void decrementStatistic(Statistic statistic) throws IllegalArgumentException {
+ }
+
+ @Override
+ public void incrementStatistic(Statistic statistic, int amount) throws IllegalArgumentException {
+
+ }
+
+ @Override
+ public void decrementStatistic(Statistic statistic, int amount) throws IllegalArgumentException {
+
+ }
+
+ @Override
+ public void setStatistic(Statistic statistic, int newValue) throws IllegalArgumentException {
+
+ }
+
+ @Override
+ public int getStatistic(Statistic statistic) throws IllegalArgumentException {
+
+ return 0;
+ }
+
+ @Override
+ public void incrementStatistic(Statistic statistic, Material material) throws IllegalArgumentException {
+
+ }
+
+ @Override
+ public void decrementStatistic(Statistic statistic, Material material) throws IllegalArgumentException {
+
+ }
+
+ @Override
+ public int getStatistic(Statistic statistic, Material material) throws IllegalArgumentException {
+
+ return 0;
+ }
+
+ @Override
+ public void incrementStatistic(Statistic statistic, Material material, int amount) throws IllegalArgumentException {
+
+ }
+
+ @Override
+ public void decrementStatistic(Statistic statistic, Material material, int amount) throws IllegalArgumentException {
+
+ }
+
+ @Override
+ public void setStatistic(Statistic statistic, Material material, int newValue) throws IllegalArgumentException {
+
+ }
+
+ @Override
+ public void incrementStatistic(Statistic statistic, EntityType entityType) throws IllegalArgumentException {
+
+ }
+
+ @Override
+ public void decrementStatistic(Statistic statistic, EntityType entityType) throws IllegalArgumentException {
+
+ }
+
+ @Override
+ public int getStatistic(Statistic statistic, EntityType entityType) throws IllegalArgumentException {
+
+ return 0;
+ }
+
+ @Override
+ public void incrementStatistic(Statistic statistic, EntityType entityType, int amount)
+ throws IllegalArgumentException {
+
+ }
+
+ @Override
+ public void decrementStatistic(Statistic statistic, EntityType entityType, int amount) {
+
+ }
+
+ @Override
+ public void setStatistic(Statistic statistic, EntityType entityType, int newValue) {
+
+ }
+
+ @Override
+ public void setPlayerTime(long time, boolean relative) {
+
+ }
+
+ @Override
+ public long getPlayerTime() {
+
+ return 0;
+ }
+
+ @Override
+ public long getPlayerTimeOffset() {
+
+ return 0;
+ }
+
+ @Override
+ public boolean isPlayerTimeRelative() {
+
+ return false;
+ }
+
+ @Override
+ public void resetPlayerTime() {
+
+ }
+
+ @Override
+ public void setPlayerWeather(WeatherType type) {
+
+ }
+
+ @Override
+ public WeatherType getPlayerWeather() {
+
+ return null;
+ }
+
+ @Override
+ public void resetPlayerWeather() {
+
+ }
+
+ @Override
+ public void giveExp(int amount) {
+
+ }
+
+ @Override
+ public void giveExpLevels(int amount) {
+
+ }
+
+ @Override
+ public float getExp() {
+
+ return 0;
+ }
+
+ @Override
+ public void setExp(float exp) {
+
+ }
+
+ @Override
+ public int getLevel() {
+
+ return 0;
+ }
+
+ @Override
+ public void setLevel(int level) {
+
+ }
+
+ @Override
+ public int getTotalExperience() {
+
+ return 0;
+ }
+
+ @Override
+ public void setTotalExperience(int exp) {
+
+ }
+
+ @Override
+ public float getExhaustion() {
+
+ return 0;
+ }
+
+ @Override
+ public void setExhaustion(float value) {
+
+ }
+
+ @Override
+ public float getSaturation() {
+
+ return 0;
+ }
+
+ @Override
+ public void setSaturation(float value) {
+
+ }
+
+ @Override
+ public int getFoodLevel() {
+
+ return 0;
+ }
+
+ @Override
+ public void setFoodLevel(int value) {
+
+ }
+
+ @Override
+ public Location getBedSpawnLocation() {
+ return null;
+ }
+
+ @Override
+ public void setBedSpawnLocation(Location location) {
+ }
+
+ @Override
+ public void setBedSpawnLocation(Location location, boolean force) {
+ }
+
+ @Override
+ public boolean getAllowFlight() {
+ return false;
+ }
+
+ @Override
+ public void setAllowFlight(boolean flight) {
+ }
+
+ @Override
+ public void hidePlayer(Player player) {
+ }
+
+ @Override
+ public void showPlayer(Player player) {
+ }
+
+ @Override
+ public boolean canSee(Player player) { // Nobody can see them
+ return false;
+ }
+
+ @Override
+ public boolean isFlying() {
+ return false;
+ }
+
+ @Override
+ public void setFlying(boolean value) {
+ }
+
+ @Override
+ public void setFlySpeed(float value) throws IllegalArgumentException {
+ }
+
+ @Override
+ public void setWalkSpeed(float value) throws IllegalArgumentException {
+ }
+
+ @Override
+ public float getFlySpeed() {
+ return 0;
+ }
+
+ @Override
+ public float getWalkSpeed() {
+ return 0;
+ }
+
+ @Override
+ public void setTexturePack(String url) {
+ }
+
+ @Override
+ public void setResourcePack(String url) {
+ }
+
+ @Override
+ public void setResourcePack(String url, byte[] hash) {
+ }
+
+ @Override
+ public Scoreboard getScoreboard() {
+ return null;
+ }
+
+ @Override
+ public void setScoreboard(Scoreboard scoreboard) throws IllegalArgumentException, IllegalStateException {
+ }
+
+ @Override
+ public boolean isHealthScaled() {
+ return false;
+ }
+
+ @Override
+ public void setHealthScaled(boolean scale) {
+ }
+
+ @Override
+ public void setHealthScale(double scale) throws IllegalArgumentException {
+ }
+
+ @Override
+ public double getHealthScale() {
+ return 1;
+ }
+
+ @Override
+ public Entity getSpectatorTarget() {
+ return null;
+ }
+
+ @Override
+ public void setSpectatorTarget(Entity entity) {
+ }
+
+ @Override
+ public void sendTitle(String title, String subtitle) {
+ }
+
+ @Override
+ public void sendTitle(String title, String subtitle, int fadeIn, int stay, int fadeOut) {
+ }
+
+ @Override
+ public void resetTitle() {
+ }
+
+ @Override
+ public void spawnParticle(Particle particle, Location location, int count) {
+ }
+
+ @Override
+ public void spawnParticle(Particle particle, double x, double y, double z, int count) {
+
+ }
+
+ @Override
+ public void spawnParticle(Particle particle, Location location, int count, T data) {
+
+ }
+
+ @Override
+ public void spawnParticle(Particle particle, double x, double y, double z, int count, T data) {
+
+ }
+
+ @Override
+ public void spawnParticle(Particle particle, Location location, int count, double offsetX, double offsetY,
+ double offsetZ) {
+
+ }
+
+ @Override
+ public void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX,
+ double offsetY, double offsetZ) {
+
+ }
+
+ @Override
+ public void spawnParticle(Particle particle, Location location, int count, double offsetX, double offsetY,
+ double offsetZ, T data) {
+
+ }
+
+ @Override
+ public void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX,
+ double offsetY, double offsetZ, T data) {
+
+ }
+
+ @Override
+ public void spawnParticle(Particle particle, Location location, int count, double offsetX, double offsetY,
+ double offsetZ, double extra) {
+
+ }
+
+ @Override
+ public void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX,
+ double offsetY, double offsetZ, double extra) {
+
+ }
+
+ @Override
+ public void spawnParticle(Particle particle, Location location, int count, double offsetX, double offsetY,
+ double offsetZ, double extra, T data) {
+
+ }
+
+ @Override
+ public void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX,
+ double offsetY, double offsetZ, double extra, T data) {
+
+ }
+
+ @Override
+ public AdvancementProgress getAdvancementProgress(Advancement advancement) { // TODO: Test
+ return null;
+ }
+
+ @Override
+ public String getLocale() {
+
+ return null;
+ }
+
+ @Override
+ public Player.Spigot spigot() {
+ return new Player.Spigot();
+ }
+}
diff --git a/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordHumanEntity.java b/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordHumanEntity.java
new file mode 100755
index 0000000..c1522f1
--- /dev/null
+++ b/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordHumanEntity.java
@@ -0,0 +1,167 @@
+package buttondevteam.discordplugin.playerfaker;
+
+import org.bukkit.GameMode;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.HumanEntity;
+import org.bukkit.entity.Villager;
+import org.bukkit.inventory.*;
+import org.bukkit.inventory.InventoryView.Property;
+import sx.blah.discord.handle.obj.IChannel;
+import sx.blah.discord.handle.obj.IUser;
+
+import java.util.UUID;
+
+public abstract class DiscordHumanEntity extends DiscordLivingEntity implements HumanEntity {
+ protected DiscordHumanEntity(IUser user, IChannel channel, int entityId, UUID uuid) {
+ super(user, channel, entityId, uuid);
+ }
+
+ private PlayerInventory inv = new DiscordPlayerInventory(this);
+
+ @Override
+ public PlayerInventory getInventory() {
+ return inv;
+ }
+
+ private Inventory enderchest = new DiscordInventory(this);
+
+ @Override
+ public Inventory getEnderChest() {
+ return enderchest;
+ }
+
+ @Override
+ public MainHand getMainHand() {
+ return MainHand.RIGHT;
+ }
+
+ @Override
+ public boolean setWindowProperty(Property prop, int value) {
+ return false;
+ }
+
+ @Override
+ public InventoryView getOpenInventory() { // TODO: Test
+ return null;
+ }
+
+ @Override
+ public InventoryView openInventory(Inventory inventory) {
+ return null;
+ }
+
+ @Override
+ public InventoryView openWorkbench(Location location, boolean force) {
+ return null;
+ }
+
+ @Override
+ public InventoryView openEnchanting(Location location, boolean force) {
+ return null;
+ }
+
+ @Override
+ public void openInventory(InventoryView inventory) {
+ }
+
+ @Override
+ public InventoryView openMerchant(Villager trader, boolean force) {
+ return null;
+ }
+
+ @Override
+ public InventoryView openMerchant(Merchant merchant, boolean force) {
+ return null;
+ }
+
+ @Override
+ public void closeInventory() {
+ }
+
+ @Override
+ public ItemStack getItemInHand() { // TODO: Test all ItemStack methods
+ return null;
+ }
+
+ @Override
+ public void setItemInHand(ItemStack item) {
+ }
+
+ @Override
+ public ItemStack getItemOnCursor() {
+ return null;
+ }
+
+ @Override
+ public void setItemOnCursor(ItemStack item) {
+ }
+
+ @Override
+ public boolean hasCooldown(Material material) {
+ return false;
+ }
+
+ @Override
+ public int getCooldown(Material material) {
+ return 0;
+ }
+
+ @Override
+ public void setCooldown(Material material, int ticks) {
+ }
+
+ @Override
+ public boolean isSleeping() {
+ return false;
+ }
+
+ @Override
+ public int getSleepTicks() {
+ return 0;
+ }
+
+ @Override
+ public GameMode getGameMode() {
+ return GameMode.SPECTATOR;
+ }
+
+ @Override
+ public void setGameMode(GameMode mode) {
+ }
+
+ @Override
+ public boolean isBlocking() {
+ return false;
+ }
+
+ @Override
+ public boolean isHandRaised() {
+ return false;
+ }
+
+ @Override
+ public int getExpToLevel() {
+ return 0;
+ }
+
+ @Override
+ public Entity getShoulderEntityLeft() {
+ return null;
+ }
+
+ @Override
+ public void setShoulderEntityLeft(Entity entity) {
+ }
+
+ @Override
+ public Entity getShoulderEntityRight() {
+ return null;
+ }
+
+ @Override
+ public void setShoulderEntityRight(Entity entity) {
+ }
+
+}
diff --git a/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordInventory.java b/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordInventory.java
old mode 100644
new mode 100755
index ab22f52..a97f715
--- a/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordInventory.java
+++ b/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordInventory.java
@@ -1,110 +1,110 @@
package buttondevteam.discordplugin.playerfaker;
-import lombok.Getter;
-import lombok.Setter;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
-import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class DiscordInventory implements Inventory {
- private ItemStack[] items = new ItemStack[27];
- private List itemStacks = Arrays.asList(items);
- @Getter
- @Setter
- public int maxStackSize;
- private static ItemStack emptyStack = new ItemStack(Material.AIR, 0);
+ public DiscordInventory(DiscordHumanEntity holder) {
+ this.holder = holder;
+ }
@Override
public int getSize() {
- return items.length;
+ return 0;
+ }
+
+ @Override
+ public int getMaxStackSize() {
+ return 0;
+ }
+
+ @Override
+ public void setMaxStackSize(int size) {
}
@Override
public String getName() {
- return "Discord inventory";
+ return "Player inventory";
}
@Override
public ItemStack getItem(int index) {
- if (index >= items.length)
- return emptyStack;
- else
- return items[index];
+ return null;
}
@Override
- public void setItem(int index, ItemStack item) {
- if (index < items.length)
- items[index] = item;
- }
-
- @Override
- public HashMap addItem(ItemStack... items) throws IllegalArgumentException {
- return IntStream.range(0, items.length).collect(HashMap::new, (map, i) -> map.put(i, items[i]), HashMap::putAll); //Pretend that we can't add anything
+ public HashMap addItem(ItemStack... items) throws IllegalArgumentException { // Can't add anything
+ return new HashMap<>(
+ IntStream.range(0, items.length).mapToObj(i -> i).collect(Collectors.toMap(i -> i, i -> items[i])));
}
@Override
public HashMap removeItem(ItemStack... items) throws IllegalArgumentException {
- return IntStream.range(0, items.length).collect(HashMap::new, (map, i) -> map.put(i, items[i]), HashMap::putAll); //Pretend that we can't add anything
+ return new HashMap<>(
+ IntStream.range(0, items.length).mapToObj(i -> i).collect(Collectors.toMap(i -> i, i -> items[i])));
}
@Override
public ItemStack[] getContents() {
- return items;
+ return new ItemStack[0];
}
@Override
public void setContents(ItemStack[] items) throws IllegalArgumentException {
- this.items = items;
+ if (items.length > 0)
+ throw new IllegalArgumentException("This inventory does not support items");
}
@Override
public ItemStack[] getStorageContents() {
- return items;
+ return new ItemStack[0];
}
@Override
public void setStorageContents(ItemStack[] items) throws IllegalArgumentException {
- this.items = items;
+ if (items.length > 0)
+ throw new IllegalArgumentException("This inventory does not support items");
}
- @SuppressWarnings("deprecation")
@Override
public boolean contains(int materialId) {
- return itemStacks.stream().anyMatch(is -> is.getType().getId() == materialId);
+ return false;
}
@Override
public boolean contains(Material material) throws IllegalArgumentException {
- return itemStacks.stream().anyMatch(is -> is.getType() == material);
+ return false;
}
@Override
public boolean contains(ItemStack item) {
- return itemStacks.stream().anyMatch(is -> is.getType() == item.getType() && is.getAmount() == item.getAmount());
+ return false;
}
- @SuppressWarnings("deprecation")
@Override
public boolean contains(int materialId, int amount) {
- return itemStacks.stream().anyMatch(is -> is.getType().getId() == materialId && is.getAmount() == amount);
+ return false;
}
@Override
public boolean contains(Material material, int amount) throws IllegalArgumentException {
- return itemStacks.stream().anyMatch(is -> is.getType() == material && is.getAmount() == amount);
+ return false;
}
@Override
- public boolean contains(ItemStack item, int amount) { //Not correct implementation but whatever
- return itemStacks.stream().anyMatch(is -> is.getType() == item.getType() && is.getAmount() == amount);
+ public boolean contains(ItemStack item, int amount) {
+ return false;
}
@Override
@@ -161,48 +161,52 @@ public class DiscordInventory implements Inventory {
@Override
public void clear(int index) {
- if (index < items.length)
- items[index] = null;
}
@Override
public void clear() {
- Arrays.fill(items, null);
}
@Override
public List getViewers() {
- return Collections.emptyList();
+ return new ArrayList<>(0);
}
@Override
public String getTitle() {
- return "Discord inventory";
+ return "Player inventory";
}
@Override
public InventoryType getType() {
- return InventoryType.CHEST;
+ return InventoryType.PLAYER;
}
- @Override
- public InventoryHolder getHolder() {
- return null;
- }
+ private ListIterator iterator = new ArrayList(0).listIterator();
- @SuppressWarnings("NullableProblems")
@Override
public ListIterator iterator() {
- return itemStacks.listIterator();
+ return iterator;
}
@Override
public ListIterator iterator(int index) {
- return itemStacks.listIterator(index);
+ return iterator;
}
@Override
public Location getLocation() {
- return null;
+ return holder.getLocation();
+ }
+
+ @Override
+ public void setItem(int index, ItemStack item) {
+ }
+
+ private HumanEntity holder;
+
+ @Override
+ public HumanEntity getHolder() {
+ return holder;
}
}
diff --git a/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordLivingEntity.java b/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordLivingEntity.java
new file mode 100755
index 0000000..f261de4
--- /dev/null
+++ b/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordLivingEntity.java
@@ -0,0 +1,297 @@
+package buttondevteam.discordplugin.playerfaker;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.attribute.Attribute;
+import org.bukkit.attribute.AttributeInstance;
+import org.bukkit.block.Block;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Projectile;
+import org.bukkit.inventory.EntityEquipment;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+import org.bukkit.util.Vector;
+import sx.blah.discord.handle.obj.IChannel;
+import sx.blah.discord.handle.obj.IUser;
+
+import java.util.*;
+
+public abstract class DiscordLivingEntity extends DiscordEntity implements LivingEntity {
+
+ protected DiscordLivingEntity(IUser user, IChannel channel, int entityId, UUID uuid) {
+ super(user, channel, entityId, uuid);
+ }
+
+ private @Getter EntityEquipment equipment = new DiscordEntityEquipment(this);
+
+ @Getter
+ @Setter
+ private static class DiscordEntityEquipment implements EntityEquipment {
+
+ private float leggingsDropChance;
+ private ItemStack leggings;
+ private float itemInOffHandDropChance;
+ private ItemStack itemInOffHand;
+ private float itemInMainHandDropChance;
+ private ItemStack itemInMainHand;
+ private float itemInHandDropChance;
+ private ItemStack itemInHand;
+ private float helmetDropChance;
+ private ItemStack helmet;
+ private float chestplateDropChance;
+ private ItemStack chestplate;
+ private float bootsDropChance;
+ private ItemStack boots;
+ private ItemStack[] armorContents = new ItemStack[0]; // TODO
+ private final Entity holder;
+
+ public DiscordEntityEquipment(Entity holder) {
+ this.holder = holder;
+ }
+
+ @Override
+ public void clear() {
+ armorContents = new ItemStack[0];
+ }
+ }
+
+ @Override
+ public AttributeInstance getAttribute(Attribute attribute) { // We don't support any attributes
+ return null;
+ }
+
+ @Override
+ public void damage(double amount) {
+ }
+
+ @Override
+ public void damage(double amount, Entity source) {
+ }
+
+ @Override
+ public double getHealth() {
+ return getMaxHealth();
+ }
+
+ @Override
+ public void setHealth(double health) {
+ }
+
+ @Override
+ public double getMaxHealth() {
+ return 100;
+ }
+
+ @Override
+ public void setMaxHealth(double health) {
+ }
+
+ @Override
+ public void resetMaxHealth() {
+ }
+
+ @Override
+ public T launchProjectile(Class extends T> projectile) {
+ return null;
+ }
+
+ @Override
+ public T launchProjectile(Class extends T> projectile, Vector velocity) {
+ return null;
+ }
+
+ @Override
+ public double getEyeHeight() {
+ return 0;
+ }
+
+ @Override
+ public double getEyeHeight(boolean ignoreSneaking) {
+ return 0;
+ }
+
+ @Override
+ public Location getEyeLocation() {
+ return getLocation();
+ }
+
+ @Override
+ public List getLineOfSight(Set transparent, int maxDistance) {
+ return Arrays.asList();
+ }
+
+ @Override
+ public Block getTargetBlock(HashSet transparent, int maxDistance) {
+ return null;
+ }
+
+ @Override
+ public Block getTargetBlock(Set transparent, int maxDistance) {
+ return null;
+ }
+
+ @Override
+ public List getLastTwoTargetBlocks(HashSet transparent, int maxDistance) {
+ return Arrays.asList();
+ }
+
+ @Override
+ public List getLastTwoTargetBlocks(Set transparent, int maxDistance) {
+ return Arrays.asList();
+ }
+
+ @Override
+ public int getRemainingAir() {
+ return 100;
+ }
+
+ @Override
+ public void setRemainingAir(int ticks) {
+ }
+
+ @Override
+ public int getMaximumAir() {
+ return 100;
+ }
+
+ @Override
+ public void setMaximumAir(int ticks) {
+ }
+
+ @Override
+ public int getMaximumNoDamageTicks() {
+ return 100;
+ }
+
+ @Override
+ public void setMaximumNoDamageTicks(int ticks) {
+ }
+
+ @Override
+ public double getLastDamage() {
+ return 0;
+ }
+
+ @Override
+ public void setLastDamage(double damage) {
+ }
+
+ @Override
+ public int getNoDamageTicks() {
+ return 100;
+ }
+
+ @Override
+ public void setNoDamageTicks(int ticks) {
+ }
+
+ @Override
+ public Player getKiller() {
+ return null;
+ }
+
+ @Override
+ public boolean addPotionEffect(PotionEffect effect) {
+ return false;
+ }
+
+ @Override
+ public boolean addPotionEffect(PotionEffect effect, boolean force) {
+ return false;
+ }
+
+ @Override
+ public boolean addPotionEffects(Collection effects) {
+ return false;
+ }
+
+ @Override
+ public boolean hasPotionEffect(PotionEffectType type) {
+ return false;
+ }
+
+ @Override
+ public PotionEffect getPotionEffect(PotionEffectType type) {
+ return null;
+ }
+
+ @Override
+ public void removePotionEffect(PotionEffectType type) {
+ }
+
+ @Override
+ public Collection getActivePotionEffects() {
+ return Arrays.asList();
+ }
+
+ @Override
+ public boolean hasLineOfSight(Entity other) {
+ return false;
+ }
+
+ @Override
+ public boolean getRemoveWhenFarAway() {
+ return false;
+ }
+
+ @Override
+ public void setRemoveWhenFarAway(boolean remove) {
+ }
+
+ @Override
+ public void setCanPickupItems(boolean pickup) {
+ }
+
+ @Override
+ public boolean getCanPickupItems() {
+ return false;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ return false;
+ }
+
+ @Override
+ public Entity getLeashHolder() throws IllegalStateException {
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean setLeashHolder(Entity holder) {
+ return false;
+ }
+
+ @Override
+ public boolean isGliding() {
+ return false;
+ }
+
+ @Override
+ public void setGliding(boolean gliding) {
+ }
+
+ @Override
+ public void setAI(boolean ai) {
+ }
+
+ @Override
+ public boolean hasAI() {
+ return false;
+ }
+
+ @Override
+ public void setCollidable(boolean collidable) {
+ }
+
+ @Override
+ public boolean isCollidable() {
+ return false;
+ }
+
+}
diff --git a/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordPlayerInventory.java b/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordPlayerInventory.java
new file mode 100755
index 0000000..447cbcd
--- /dev/null
+++ b/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordPlayerInventory.java
@@ -0,0 +1,105 @@
+package buttondevteam.discordplugin.playerfaker;
+
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.PlayerInventory;
+
+public class DiscordPlayerInventory extends DiscordInventory implements PlayerInventory {
+ public DiscordPlayerInventory(DiscordHumanEntity holder) {
+ super(holder);
+ }
+
+ @Override
+ public ItemStack[] getArmorContents() {
+ return new ItemStack[0];
+ }
+
+ @Override
+ public ItemStack[] getExtraContents() {
+ return new ItemStack[0];
+ }
+
+ @Override
+ public ItemStack getHelmet() {
+ return null;
+ }
+
+ @Override
+ public ItemStack getChestplate() {
+ return null;
+ }
+
+ @Override
+ public ItemStack getLeggings() {
+ return null;
+ }
+
+ @Override
+ public ItemStack getBoots() {
+ return null;
+ }
+
+ @Override
+ public void setArmorContents(ItemStack[] items) {
+ }
+
+ @Override
+ public void setExtraContents(ItemStack[] items) {
+ }
+
+ @Override
+ public void setHelmet(ItemStack helmet) {
+ }
+
+ @Override
+ public void setChestplate(ItemStack chestplate) {
+ }
+
+ @Override
+ public void setLeggings(ItemStack leggings) {
+ }
+
+ @Override
+ public void setBoots(ItemStack boots) {
+ }
+
+ @Override
+ public ItemStack getItemInMainHand() {
+ return null;
+ }
+
+ @Override
+ public void setItemInMainHand(ItemStack item) {
+ }
+
+ @Override
+ public ItemStack getItemInOffHand() {
+ return null;
+ }
+
+ @Override
+ public void setItemInOffHand(ItemStack item) {
+ }
+
+ @Override
+ public ItemStack getItemInHand() {
+ return null;
+ }
+
+ @Override
+ public void setItemInHand(ItemStack stack) {
+ }
+
+ @Override
+ public int getHeldItemSlot() {
+ return 0;
+ }
+
+ @Override
+ public void setHeldItemSlot(int slot) {
+ }
+
+ @Override
+ public int clear(int id, int data) {
+ return 0;
+ }
+}
diff --git a/src/main/java/buttondevteam/discordplugin/playerfaker/VCMDWrapper.java b/src/main/java/buttondevteam/discordplugin/playerfaker/VCMDWrapper.java
deleted file mode 100644
index 4bcf5eb..0000000
--- a/src/main/java/buttondevteam/discordplugin/playerfaker/VCMDWrapper.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package buttondevteam.discordplugin.playerfaker;
-
-import buttondevteam.discordplugin.DiscordSenderBase;
-import buttondevteam.discordplugin.IMCPlayer;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import org.bukkit.Bukkit;
-import org.bukkit.entity.Player;
-
-@RequiredArgsConstructor
-public class VCMDWrapper {
- @Getter //Needed to mock the player
- private final Object listener;
-
- /**
- * This constructor will only send raw vanilla messages to the sender in plain text.
- *
- * @param player The Discord sender player (the wrapper)
- */
- public static > Object createListener(T player) {
- return createListener(player, null);
- }
-
- /**
- * This constructor will send both raw vanilla messages to the sender in plain text and forward the raw message to the provided player.
- *
- * @param player The Discord sender player (the wrapper)
- * @param bukkitplayer The Bukkit player to send the raw message to
- */
- public static > Object createListener(T player, Player bukkitplayer) {
- String mcpackage = Bukkit.getServer().getClass().getPackage().getName();
- if (mcpackage.contains("1_12"))
- return bukkitplayer == null ? new VanillaCommandListener<>(player) : new VanillaCommandListener<>(player, bukkitplayer);
- else if (mcpackage.contains("1_14"))
- return bukkitplayer == null ? new VanillaCommandListener14<>(player) : new VanillaCommandListener14<>(player, bukkitplayer);
- else
- return null;
- }
-}
diff --git a/src/main/java/buttondevteam/discordplugin/playerfaker/VanillaCommandListener.java b/src/main/java/buttondevteam/discordplugin/playerfaker/VanillaCommandListener.java
index c12a308..29f3a13 100755
--- a/src/main/java/buttondevteam/discordplugin/playerfaker/VanillaCommandListener.java
+++ b/src/main/java/buttondevteam/discordplugin/playerfaker/VanillaCommandListener.java
@@ -87,7 +87,7 @@ public class VanillaCommandListener>
if (!vcmd.testPermission(sender))
return true;
- ICommandListener icommandlistener = (ICommandListener) sender.getVanillaCmdListener().getListener();
+ ICommandListener icommandlistener = sender.getVanillaCmdListener();
String[] args = cmdstr.split(" ");
args = Arrays.copyOfRange(args, 1, args.length);
try {
diff --git a/src/main/java/buttondevteam/discordplugin/playerfaker/VanillaCommandListener14.java b/src/main/java/buttondevteam/discordplugin/playerfaker/VanillaCommandListener14.java
deleted file mode 100644
index fbaf958..0000000
--- a/src/main/java/buttondevteam/discordplugin/playerfaker/VanillaCommandListener14.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package buttondevteam.discordplugin.playerfaker;
-
-import buttondevteam.discordplugin.DiscordSenderBase;
-import buttondevteam.discordplugin.IMCPlayer;
-import lombok.Getter;
-import lombok.val;
-import net.minecraft.server.v1_14_R1.*;
-import org.bukkit.Bukkit;
-import org.bukkit.command.CommandSender;
-import org.bukkit.craftbukkit.v1_14_R1.CraftServer;
-import org.bukkit.craftbukkit.v1_14_R1.CraftWorld;
-import org.bukkit.craftbukkit.v1_14_R1.command.ProxiedNativeCommandSender;
-import org.bukkit.craftbukkit.v1_14_R1.command.VanillaCommandWrapper;
-import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
-import org.bukkit.entity.Player;
-
-import java.util.Arrays;
-
-public class VanillaCommandListener14> implements ICommandListener {
- private @Getter T player;
- private Player bukkitplayer;
-
- /**
- * This constructor will only send raw vanilla messages to the sender in plain text.
- *
- * @param player The Discord sender player (the wrapper)
- */
- public VanillaCommandListener14(T player) {
- this.player = player;
- this.bukkitplayer = null;
- }
-
- /**
- * This constructor will send both raw vanilla messages to the sender in plain text and forward the raw message to the provided player.
- *
- * @param player The Discord sender player (the wrapper)
- * @param bukkitplayer The Bukkit player to send the raw message to
- */
- public VanillaCommandListener14(T player, Player bukkitplayer) {
- this.player = player;
- this.bukkitplayer = bukkitplayer;
- if (!(bukkitplayer instanceof CraftPlayer))
- throw new ClassCastException("bukkitplayer must be a Bukkit player!");
- }
-
- @Override
- public void sendMessage(IChatBaseComponent arg0) {
- player.sendMessage(arg0.getString());
- if (bukkitplayer != null)
- ((CraftPlayer) bukkitplayer).getHandle().sendMessage(arg0);
- }
-
- @Override
- public boolean shouldSendSuccess() {
- return true;
- }
-
- @Override
- public boolean shouldSendFailure() {
- return true;
- }
-
- @Override
- public boolean shouldBroadcastCommands() {
- return true; //Broadcast to in-game admins
- }
-
- @Override
- public CommandSender getBukkitSender(CommandListenerWrapper commandListenerWrapper) {
- return player;
- }
-
- public static boolean runBukkitOrVanillaCommand(DiscordSenderBase dsender, String cmdstr) {
- val cmd = ((CraftServer) Bukkit.getServer()).getCommandMap().getCommand(cmdstr.split(" ")[0].toLowerCase());
- if (!(dsender instanceof Player) || !(cmd instanceof VanillaCommandWrapper))
- return Bukkit.dispatchCommand(dsender, cmdstr); // Unconnected users are treated well in vanilla cmds
-
- if (!(dsender instanceof IMCPlayer))
- throw new ClassCastException(
- "dsender needs to implement IMCPlayer to use vanilla commands as it implements Player.");
-
- IMCPlayer> sender = (IMCPlayer>) dsender; // Don't use val on recursive interfaces :P
-
- val vcmd = (VanillaCommandWrapper) cmd;
- if (!vcmd.testPermission(sender))
- return true;
-
- val world = ((CraftWorld) Bukkit.getWorlds().get(0)).getHandle();
- ICommandListener icommandlistener = (ICommandListener) sender.getVanillaCmdListener().getListener();
- val wrapper = new CommandListenerWrapper(icommandlistener, new Vec3D(0, 0, 0),
- new Vec2F(0, 0), world, 0, sender.getName(),
- new ChatComponentText(sender.getName()), world.getMinecraftServer(), null);
- val pncs = new ProxiedNativeCommandSender(wrapper, sender, sender);
- String[] args = cmdstr.split(" ");
- args = Arrays.copyOfRange(args, 1, args.length);
- try {
- return vcmd.execute(pncs, cmd.getLabel(), args);
- } catch (CommandException commandexception) {
- // Taken from CommandHandler
- ChatMessage chatmessage = new ChatMessage(commandexception.getMessage(), commandexception.a());
- chatmessage.getChatModifier().setColor(EnumChatFormat.RED);
- icommandlistener.sendMessage(chatmessage);
- }
- return true;
- }
-}
diff --git a/src/main/java/buttondevteam/discordplugin/playerfaker/perm/LPInjector.java b/src/main/java/buttondevteam/discordplugin/playerfaker/perm/LPInjector.java
deleted file mode 100644
index 802accf..0000000
--- a/src/main/java/buttondevteam/discordplugin/playerfaker/perm/LPInjector.java
+++ /dev/null
@@ -1,240 +0,0 @@
-package buttondevteam.discordplugin.playerfaker.perm;
-
-import buttondevteam.core.MainPlugin;
-import buttondevteam.discordplugin.DiscordConnectedPlayer;
-import buttondevteam.discordplugin.mcchat.MCChatUtils;
-import buttondevteam.lib.TBMCCoreAPI;
-import me.lucko.luckperms.bukkit.LPBukkitBootstrap;
-import me.lucko.luckperms.bukkit.LPBukkitPlugin;
-import me.lucko.luckperms.bukkit.inject.dummy.DummyPermissibleBase;
-import me.lucko.luckperms.bukkit.inject.permissible.LPPermissible;
-import me.lucko.luckperms.bukkit.listeners.BukkitConnectionListener;
-import me.lucko.luckperms.common.config.ConfigKeys;
-import me.lucko.luckperms.common.locale.message.Message;
-import me.lucko.luckperms.common.model.User;
-import org.bukkit.Bukkit;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.EventPriority;
-import org.bukkit.event.Listener;
-import org.bukkit.event.player.PlayerLoginEvent;
-import org.bukkit.event.player.PlayerQuitEvent;
-import org.bukkit.permissions.PermissibleBase;
-import org.bukkit.permissions.PermissionAttachment;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-public final class LPInjector implements Listener { //Disable login event for LuckPerms
- private LPBukkitPlugin plugin;
- private BukkitConnectionListener connectionListener;
- private Set deniedLogin;
- private Field detectedCraftBukkitOfflineMode;
- private Method printCraftBukkitOfflineModeError;
- private Field PERMISSIBLE_BASE_ATTACHMENTS_FIELD;
- private Method convertAndAddAttachments;
- private Method getActive;
- private Method setOldPermissible;
- private Method getOldPermissible;
-
- public LPInjector(MainPlugin mp) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException {
- LPBukkitBootstrap bs = (LPBukkitBootstrap) Bukkit.getPluginManager().getPlugin("LuckPerms");
- Field field = LPBukkitBootstrap.class.getDeclaredField("plugin");
- field.setAccessible(true);
- plugin = (LPBukkitPlugin) field.get(bs);
- MCChatUtils.addStaticExcludedPlugin(PlayerLoginEvent.class, "LuckPerms");
- MCChatUtils.addStaticExcludedPlugin(PlayerQuitEvent.class, "LuckPerms");
-
- field = LPBukkitPlugin.class.getDeclaredField("connectionListener");
- field.setAccessible(true);
- connectionListener = (BukkitConnectionListener) field.get(plugin);
- field = connectionListener.getClass().getDeclaredField("deniedLogin");
- field.setAccessible(true);
- //noinspection unchecked
- deniedLogin = (Set) field.get(connectionListener);
- field = connectionListener.getClass().getDeclaredField("detectedCraftBukkitOfflineMode");
- field.setAccessible(true);
- detectedCraftBukkitOfflineMode = field;
- printCraftBukkitOfflineModeError = connectionListener.getClass().getDeclaredMethod("printCraftBukkitOfflineModeError");
- printCraftBukkitOfflineModeError.setAccessible(true);
-
- //PERMISSIBLE_FIELD = DiscordFakePlayer.class.getDeclaredField("perm");
- //PERMISSIBLE_FIELD.setAccessible(true); //Hacking my own plugin, while we're at it
- PERMISSIBLE_BASE_ATTACHMENTS_FIELD = PermissibleBase.class.getDeclaredField("attachments");
- PERMISSIBLE_BASE_ATTACHMENTS_FIELD.setAccessible(true);
-
- convertAndAddAttachments = LPPermissible.class.getDeclaredMethod("convertAndAddAttachments", Collection.class);
- convertAndAddAttachments.setAccessible(true);
- getActive = LPPermissible.class.getDeclaredMethod("getActive");
- getActive.setAccessible(true);
- setOldPermissible = LPPermissible.class.getDeclaredMethod("setOldPermissible", PermissibleBase.class);
- setOldPermissible.setAccessible(true);
- getOldPermissible = LPPermissible.class.getDeclaredMethod("getOldPermissible");
- getOldPermissible.setAccessible(true);
-
- TBMCCoreAPI.RegisterEventsForExceptions(this, mp);
- }
-
-
- //Code copied from LuckPerms - me.lucko.luckperms.bukkit.listeners.BukkitConnectionListener
- @EventHandler(priority = EventPriority.LOWEST)
- public void onPlayerLogin(PlayerLoginEvent e) {
- /* Called when the player starts logging into the server.
- At this point, the users data should be present and loaded. */
-
- if (!(e.getPlayer() instanceof DiscordConnectedPlayer))
- return; //Normal players must be handled by the plugin
-
- final DiscordConnectedPlayer player = (DiscordConnectedPlayer) e.getPlayer();
-
- if (plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) {
- plugin.getLogger().info("Processing login for " + player.getUniqueId() + " - " + player.getName());
- }
-
- final User user = plugin.getUserManager().getIfLoaded(player.getUniqueId());
-
- /* User instance is null for whatever reason. Could be that it was unloaded between asyncpre and now. */
- if (user == null) {
- deniedLogin.add(player.getUniqueId());
-
- if (!connectionListener.getUniqueConnections().contains(player.getUniqueId())) {
-
- plugin.getLogger().warn("User " + player.getUniqueId() + " - " + player.getName() +
- " doesn't have data pre-loaded, they have never been processed during pre-login in this session." +
- " - denying login.");
-
- try {
- if ((Boolean) detectedCraftBukkitOfflineMode.get(connectionListener)) {
- printCraftBukkitOfflineModeError.invoke(connectionListener);
- e.disallow(PlayerLoginEvent.Result.KICK_OTHER, Message.LOADING_STATE_ERROR_CB_OFFLINE_MODE.asString(plugin.getLocaleManager()));
- return;
- }
- } catch (IllegalAccessException | InvocationTargetException ex) {
- ex.printStackTrace();
- }
-
- } else {
- plugin.getLogger().warn("User " + player.getUniqueId() + " - " + player.getName() +
- " doesn't currently have data pre-loaded, but they have been processed before in this session." +
- " - denying login.");
- }
-
- e.disallow(PlayerLoginEvent.Result.KICK_OTHER, Message.LOADING_STATE_ERROR.asString(plugin.getLocaleManager()));
- return;
- }
-
- // User instance is there, now we can inject our custom Permissible into the player.
- // Care should be taken at this stage to ensure that async tasks which manipulate bukkit data check that the player is still online.
- try {
- // get the existing PermissibleBase held by the player
- PermissibleBase oldPermissible = player.getPerm();
-
- // Make a new permissible for the user
- LPPermissible lpPermissible = new LPPermissible(player, user, plugin);
-
- // Inject into the player
- inject(player, lpPermissible, oldPermissible);
-
- } catch (Throwable t) {
- plugin.getLogger().warn("Exception thrown when setting up permissions for " +
- player.getUniqueId() + " - " + player.getName() + " - denying login.");
- t.printStackTrace();
-
- e.disallow(PlayerLoginEvent.Result.KICK_OTHER, Message.LOADING_SETUP_ERROR.asString(plugin.getLocaleManager()));
- return;
- }
-
- plugin.refreshAutoOp(player, true);
- }
-
- // Wait until the last priority to unload, so plugins can still perform permission checks on this event
- @EventHandler(priority = EventPriority.MONITOR)
- public void onPlayerQuit(PlayerQuitEvent e) {
- if (!(e.getPlayer() instanceof DiscordConnectedPlayer))
- return;
-
- final DiscordConnectedPlayer player = (DiscordConnectedPlayer) e.getPlayer();
-
- connectionListener.handleDisconnect(player.getUniqueId());
-
- // perform unhooking from bukkit objects 1 tick later.
- // this allows plugins listening after us on MONITOR to still have intact permissions data
- this.plugin.getBootstrap().getServer().getScheduler().runTaskLaterAsynchronously(this.plugin.getBootstrap(), () -> {
- // Remove the custom permissible
- try {
- uninject(player, true);
- } catch (Exception ex) {
- ex.printStackTrace();
- }
-
- // Handle auto op
- if (this.plugin.getConfiguration().get(ConfigKeys.AUTO_OP)) {
- player.setOp(false);
- }
-
- // remove their contexts cache
- this.plugin.getContextManager().onPlayerQuit(player);
- }, 1L);
- }
-
- //me.lucko.luckperms.bukkit.inject.permissible.PermissibleInjector
- private void inject(DiscordConnectedPlayer player, LPPermissible newPermissible, PermissibleBase oldPermissible) throws IllegalAccessException, InvocationTargetException {
-
- // seems we have already injected into this player.
- if (oldPermissible instanceof LPPermissible) {
- throw new IllegalStateException("LPPermissible already injected into player " + player.toString());
- }
-
- // Move attachments over from the old permissible
-
- //noinspection unchecked
- List attachments = (List) PERMISSIBLE_BASE_ATTACHMENTS_FIELD.get(oldPermissible);
-
- convertAndAddAttachments.invoke(newPermissible, attachments);
- attachments.clear();
- oldPermissible.clearPermissions();
-
- // Setup the new permissible
- ((AtomicBoolean) getActive.invoke(newPermissible)).set(true);
- setOldPermissible.invoke(newPermissible, oldPermissible);
-
- // inject the new instance
- player.setPerm(newPermissible);
- }
-
- private void uninject(DiscordConnectedPlayer player, boolean dummy) throws Exception {
-
- // gets the players current permissible.
- PermissibleBase permissible = player.getPerm();
-
- // only uninject if the permissible was a luckperms one.
- if (permissible instanceof LPPermissible) {
- LPPermissible lpPermissible = ((LPPermissible) permissible);
-
- // clear all permissions
- lpPermissible.clearPermissions();
-
- // set to inactive
- ((AtomicBoolean) getActive.invoke(lpPermissible)).set(false);
-
- // handle the replacement permissible.
- if (dummy) {
- // just inject a dummy class. this is used when we know the player is about to quit the server.
- player.setPerm(DummyPermissibleBase.INSTANCE);
-
- } else {
- PermissibleBase newPb = (PermissibleBase) getOldPermissible.invoke(lpPermissible);
- if (newPb == null) {
- newPb = new PermissibleBase(player);
- }
-
- player.setPerm(newPb);
- }
- }
- }
-}
diff --git a/src/main/java/buttondevteam/discordplugin/role/GameRoleModule.java b/src/main/java/buttondevteam/discordplugin/role/GameRoleModule.java
deleted file mode 100644
index d666a13..0000000
--- a/src/main/java/buttondevteam/discordplugin/role/GameRoleModule.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package buttondevteam.discordplugin.role;
-
-import buttondevteam.core.ComponentManager;
-import buttondevteam.discordplugin.DPUtils;
-import buttondevteam.discordplugin.DiscordPlugin;
-import buttondevteam.lib.TBMCCoreAPI;
-import buttondevteam.lib.architecture.Component;
-import buttondevteam.lib.architecture.ReadOnlyConfigData;
-import discord4j.core.event.domain.role.RoleCreateEvent;
-import discord4j.core.event.domain.role.RoleDeleteEvent;
-import discord4j.core.event.domain.role.RoleEvent;
-import discord4j.core.event.domain.role.RoleUpdateEvent;
-import discord4j.core.object.entity.MessageChannel;
-import discord4j.core.object.entity.Role;
-import lombok.val;
-import org.bukkit.Bukkit;
-import reactor.core.publisher.Mono;
-
-import java.awt.*;
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * Automatically collects roles with a certain color (the second to last in the upper row - #95a5a6).
- * Users can add these roles to themselves using the /role Discord command.
- */
-public class GameRoleModule extends Component {
- public List GameRoles;
-
- @Override
- protected void enable() {
- getPlugin().getManager().registerCommand(new RoleCommand(this));
- GameRoles = DiscordPlugin.mainServer.getRoles().filterWhen(r -> isGameRole(r, false)).map(Role::getName).collect(Collectors.toList()).block();
- }
-
- @Override
- protected void disable() {
-
- }
-
- /**
- * The channel where the bot logs when it detects a role change that results in a new game role or one being removed.
- */
- private ReadOnlyConfigData> logChannel() {
- return DPUtils.channelData(getConfig(), "logChannel");
- }
-
- public static void handleRoleEvent(RoleEvent roleEvent) {
- val grm = ComponentManager.getIfEnabled(GameRoleModule.class);
- if (grm == null) return;
- val GameRoles = grm.GameRoles;
- val logChannel = grm.logChannel().get();
- if (roleEvent instanceof RoleCreateEvent) {
- Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, () -> {
- Role role=((RoleCreateEvent) roleEvent).getRole();
- grm.isGameRole(role, false).flatMap(b -> {
- if (!b)
- return Mono.empty(); //Deleted or not a game role
- GameRoles.add(role.getName());
- if (logChannel != null)
- return logChannel.flatMap(ch -> ch.createMessage("Added " + role.getName() + " as game role. If you don't want this, change the role's color from the game role color."));
- return Mono.empty();
- }).subscribe();
- }, 100);
- } else if (roleEvent instanceof RoleDeleteEvent) {
- Role role=((RoleDeleteEvent) roleEvent).getRole().orElse(null);
- if(role==null) return;
- if (GameRoles.remove(role.getName()) && logChannel != null)
- logChannel.flatMap(ch -> ch.createMessage("Removed " + role.getName() + " as a game role.")).subscribe();
- } else if (roleEvent instanceof RoleUpdateEvent) {
- val event = (RoleUpdateEvent) roleEvent;
- if(!event.getOld().isPresent()) {
- DPUtils.getLogger().warning("Old role not stored, cannot update game role!");
- return;
- }
- Role or=event.getOld().get();
- grm.isGameRole(event.getCurrent(), true).flatMap(b -> {
- if (!b) {
- if (GameRoles.remove(or.getName()) && logChannel != null)
- return logChannel.flatMap(ch -> ch.createMessage("Removed " + or.getName() + " as a game role because it's color changed."));
- } else {
- if (GameRoles.contains(or.getName()) && or.getName().equals(event.getCurrent().getName()))
- return Mono.empty();
- boolean removed = GameRoles.remove(or.getName()); //Regardless of whether it was a game role
- GameRoles.add(event.getCurrent().getName()); //Add it because it has no color
- if (logChannel != null) {
- if (removed)
- return logChannel.flatMap(ch -> ch.createMessage("Changed game role from " + or.getName() + " to " + event.getCurrent().getName() + "."));
- else
- return logChannel.flatMap(ch -> ch.createMessage("Added " + event.getCurrent().getName() + " as game role because it has the color of one."));
- }
- }
- return Mono.empty();
- }).subscribe();
- }
- }
-
- private Mono isGameRole(Role r, boolean debugMC) {
- boolean debug = debugMC && r.getName().equalsIgnoreCase("Minecraft");
- if (debug) TBMCCoreAPI.sendDebugMessage("Checking if Minecraft is a game role...");
- if (r.getGuildId().asLong() != DiscordPlugin.mainServer.getId().asLong()) {
- if (debug) TBMCCoreAPI.sendDebugMessage("Not in the main server: " + r.getGuildId().asString());
- return Mono.just(false); //Only allow on the main server
- }
- val rc = new Color(149, 165, 166, 0);
- if (debug) TBMCCoreAPI.sendDebugMessage("Game role color: " + rc + " - MC color: " + r.getColor());
- return Mono.just(r.getColor().equals(rc))
- .doAfterSuccessOrError((b, e) -> {
- if (debug) TBMCCoreAPI.sendDebugMessage("1. b: " + b + " - e: " + e);
- }).filter(b -> b).flatMap(b ->
- DiscordPlugin.dc.getSelf().flatMap(u -> u.asMember(DiscordPlugin.mainServer.getId()))
- .doAfterSuccessOrError((m, e) -> {
- if (debug) TBMCCoreAPI.sendDebugMessage("2. m: " + m.getDisplayName() + " e: " + e);
- }).flatMap(m -> m.hasHigherRoles(Collections.singleton(r)))) //Below one of our roles
- .doAfterSuccessOrError((b, e) -> {
- if (debug) TBMCCoreAPI.sendDebugMessage("3. b: " + b + " - e: " + e);
- }).defaultIfEmpty(false);
- }
-}
diff --git a/src/main/java/buttondevteam/discordplugin/role/RoleCommand.java b/src/main/java/buttondevteam/discordplugin/role/RoleCommand.java
deleted file mode 100755
index d484ef2..0000000
--- a/src/main/java/buttondevteam/discordplugin/role/RoleCommand.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package buttondevteam.discordplugin.role;
-
-import buttondevteam.discordplugin.DiscordPlugin;
-import buttondevteam.discordplugin.commands.Command2DCSender;
-import buttondevteam.discordplugin.commands.ICommand2DC;
-import buttondevteam.lib.TBMCCoreAPI;
-import buttondevteam.lib.chat.Command2;
-import buttondevteam.lib.chat.CommandClass;
-import discord4j.core.object.entity.Role;
-import lombok.val;
-import reactor.core.publisher.Mono;
-
-import java.util.List;
-
-@CommandClass
-public class RoleCommand extends ICommand2DC {
-
- private GameRoleModule grm;
-
- RoleCommand(GameRoleModule grm) {
- this.grm = grm;
- }
-
- @Command2.Subcommand(helpText = {
- "Add role",
- "This command adds a role to your account."
- })
- public boolean add(Command2DCSender sender, @Command2.TextArg String rolename) {
- final Role role = checkAndGetRole(sender, rolename);
- if (role == null)
- return true;
- try {
- sender.getMessage().getAuthorAsMember()
- .flatMap(m -> m.addRole(role.getId()).switchIfEmpty(Mono.fromRunnable(() -> sender.sendMessage("added role."))))
- .subscribe();
- } catch (Exception e) {
- TBMCCoreAPI.SendException("Error while adding role!", e);
- sender.sendMessage("an error occured while adding the role.");
- }
- return true;
- }
-
- @Command2.Subcommand(helpText = {
- "Remove role",
- "This command removes a role from your account."
- })
- public boolean remove(Command2DCSender sender, @Command2.TextArg String rolename) {
- final Role role = checkAndGetRole(sender, rolename);
- if (role == null)
- return true;
- try {
- sender.getMessage().getAuthorAsMember()
- .flatMap(m -> m.removeRole(role.getId()).switchIfEmpty(Mono.fromRunnable(() -> sender.sendMessage("removed role."))))
- .subscribe();
- } catch (Exception e) {
- TBMCCoreAPI.SendException("Error while removing role!", e);
- sender.sendMessage("an error occured while removing the role.");
- }
- return true;
- }
-
- @Command2.Subcommand
- public void list(Command2DCSender sender) {
- var sb = new StringBuilder();
- boolean b = false;
- for (String role : (Iterable) grm.GameRoles.stream().sorted()::iterator) {
- sb.append(role);
- if (!b)
- for (int j = 0; j < Math.max(1, 20 - role.length()); j++)
- sb.append(" ");
- else
- sb.append("\n");
- b = !b;
- }
- if (sb.charAt(sb.length() - 1) != '\n')
- sb.append('\n');
- sender.sendMessage("list of roles:\n```\n" + sb + "```");
- }
-
- private Role checkAndGetRole(Command2DCSender sender, String rolename) {
- String rname = rolename;
- if (!grm.GameRoles.contains(rolename)) { //If not found as-is, correct case
- val orn = grm.GameRoles.stream().filter(r -> r.equalsIgnoreCase(rolename)).findAny();
- if (!orn.isPresent()) {
- sender.sendMessage("that role cannot be found.");
- list(sender);
- return null;
- }
- rname = orn.get();
- }
- val frname = rname;
- final List