diff --git a/pom.xml b/pom.xml
index fdc1d53..9fed5ae 100755
--- a/pom.xml
+++ b/pom.xml
@@ -1,45 +1,45 @@
- 4.0.0
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ 4.0.0
- com.github.TBMCPlugins
- DiscordPlugin
- master-SNAPSHOT
- jar
+ com.github.TBMCPlugins
+ DiscordPlugin
+ master-SNAPSHOT
+ jar
- DiscordPlugin
- http://maven.apache.org
+ DiscordPlugin
+ http://maven.apache.org
-
-
- src/main/java
-
-
- src
-
- **/*.java
-
-
-
- src/main/resources
-
- *.properties
- *.yml
- *.csv
- *.txt
-
- true
-
-
- DiscordPlugin
-
-
- maven-compiler-plugin
- 3.6.2
-
- 1.8
- 1.8
+
+
+ src/main/java
+
+
+ src
+
+ **/*.java
+
+
+
+ src/main/resources
+
+ *.properties
+ *.yml
+ *.csv
+ *.txt
+
+ true
+
+
+ DiscordPlugin
+
+
+ maven-compiler-plugin
+ 3.6.2
+
+ 1.8
+ 1.8
-
-
-
- org.apache.maven.plugins
- maven-shade-plugin
- 2.4.2
-
-
- package
-
- shade
-
-
-
-
- org.spigotmc:spigot-api
- com.github.TBMCPlugins.ButtonCore:ButtonCore
- net.ess3:Essentials
-
-
- true
-
-
-
-
-
- org.apache.maven.plugins
- maven-resources-plugin
- 3.0.1
-
-
- copy
- compile
-
- copy-resources
-
-
- target
-
-
- resources
-
-
-
-
-
-
-
-
- maven-surefire-plugin
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
2.4.2
-
- false
-
-
-
-
-
+
+
+ package
+
+ shade
+
+
+
+
+ org.spigotmc:spigot-api
+ com.github.TBMCPlugins.ButtonCore:ButtonCore
+ net.ess3:Essentials
+
+
+ true
+
+
+ io.netty
+ buttondevteam.discordplugin.io.netty
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ 3.0.1
+
+
+ copy
+ compile
+
+ copy-resources
+
+
+ target
+
+
+ resources
+
+
+
+
+
+
+
+
+ maven-surefire-plugin
+ 2.4.2
+
+ false
+
+
+
+
+
-
- UTF-8
+
+ UTF-8
master
-
+
-
-
- spigot-repo
- https://hub.spigotmc.org/nexus/content/repositories/snapshots/
-
-
- jcenter
- http://jcenter.bintray.com
-
-
- jitpack.io
- https://jitpack.io
-
+
+
+ spigot-repo
+ https://hub.spigotmc.org/nexus/content/repositories/snapshots/
+
+
+ jcenter
+ http://jcenter.bintray.com
+
+
+ jitpack.io
+ https://jitpack.io
+
-
- Essentials
- http://repo.ess3.net/content/repositories/essrel/
-
-
- projectlombok.org
- http://projectlombok.org/mavenrepo
-
+
+ Essentials
+ http://repo.ess3.net/content/repositories/essrel/
+
+
+ projectlombok.org
+ http://projectlombok.org/mavenrepo
+
-
+
-
-
- junit
- junit
- 3.8.1
- test
-
-
- org.spigotmc
- spigot-api
- 1.12-R0.1-SNAPSHOT
- provided
-
-
- org.spigotmc
- spigot
- 1.12.2-R0.1-SNAPSHOT
- provided
-
-
+
+
+ junit
+ junit
+ 3.8.1
+ test
+
+
+ org.spigotmc
+ spigot-api
+ 1.12-R0.1-SNAPSHOT
+ provided
+
+
+ org.spigotmc
+ spigot
+ 1.12.2-R0.1-SNAPSHOT
+ provided
+
+
com.discord4j
discord4j-core
3.0.5
-
-
- org.slf4j
- slf4j-jdk14
- 1.7.21
-
-
- com.github.TBMCPlugins.ButtonCore
- ButtonCore
- ${branch}-SNAPSHOT
- provided
-
-
- com.github.milkbowl
- VaultAPI
- master-SNAPSHOT
- provided
-
-
- net.ess3
- Essentials
- 2.13.1
+
+
+ org.slf4j
+ slf4j-jdk14
+ 1.7.21
+
+
+ com.github.TBMCPlugins.ButtonCore
+ ButtonCore
+ ${branch}-SNAPSHOT
provided
-
-
-
- org.projectlombok
- lombok
- 1.16.16
- provided
-
+
+
+ com.github.milkbowl
+ VaultAPI
+ master-SNAPSHOT
+ provided
+
+
+ net.ess3
+ Essentials
+ 2.13.1
+ provided
+
+
+
+ org.projectlombok
+ lombok
+ 1.16.16
+ provided
+
-
-
- org.objenesis
- objenesis
- 2.6
- test
-
-
- com.vdurmont
- emoji-java
- 4.0.0
-
+
+
+ org.objenesis
+ objenesis
+ 2.6
+ test
+
+
+ com.vdurmont
+ emoji-java
+ 4.0.0
+
-
+
+ com.github.lucko
+ LuckPerms
+ v4.4
+ provided
+
+
-
-
- ci
-
-
- env.TRAVIS_BRANCH
-
-
-
-
- ${env.TRAVIS_BRANCH}
-
-
-
+
+
+ ci
+
+
+ env.TRAVIS_BRANCH
+
+
+
+
+ ${env.TRAVIS_BRANCH}
+
+
+
diff --git a/src/main/java/buttondevteam/discordplugin/DiscordConnectedPlayer.java b/src/main/java/buttondevteam/discordplugin/DiscordConnectedPlayer.java
index de96b18..6e30a53 100755
--- a/src/main/java/buttondevteam/discordplugin/DiscordConnectedPlayer.java
+++ b/src/main/java/buttondevteam/discordplugin/DiscordConnectedPlayer.java
@@ -6,15 +6,19 @@ import buttondevteam.discordplugin.playerfaker.VanillaCommandListener;
import discord4j.core.object.entity.MessageChannel;
import discord4j.core.object.entity.User;
import lombok.Getter;
+import lombok.Setter;
import java.util.UUID;
public class DiscordConnectedPlayer extends DiscordFakePlayer implements IMCPlayer {
private static int nextEntityId = 10000;
private @Getter VanillaCommandListener vanillaCmdListener;
+ @Getter
+ @Setter
+ private boolean loggedIn = false;
public DiscordConnectedPlayer(User user, MessageChannel channel, UUID uuid, String mcname, MinecraftChatModule module) {
- super(user, channel, nextEntityId++, uuid, mcname ,module);
+ super(user, channel, nextEntityId++, uuid, mcname, module);
vanillaCmdListener = new VanillaCommandListener<>(this);
}
diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java
index e43bf74..344ecf5 100644
--- a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java
+++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatPrivate.java
@@ -3,15 +3,12 @@ package buttondevteam.discordplugin.mcchat;
import buttondevteam.core.ComponentManager;
import buttondevteam.discordplugin.DiscordConnectedPlayer;
import buttondevteam.discordplugin.DiscordPlayer;
-import buttondevteam.discordplugin.DiscordPlugin;
import buttondevteam.lib.player.TBMCPlayer;
import discord4j.core.object.entity.MessageChannel;
import discord4j.core.object.entity.PrivateChannel;
import discord4j.core.object.entity.User;
import lombok.val;
import org.bukkit.Bukkit;
-import org.bukkit.event.Event;
-import org.bukkit.event.player.PlayerQuitEvent;
import java.util.ArrayList;
@@ -32,11 +29,14 @@ public class MCChatPrivate {
val sender = new DiscordConnectedPlayer(user, channel, mcp.getUUID(), op.getName(), mcm);
MCChatUtils.addSender(MCChatUtils.ConnectedSenders, user, sender);
if (p == null)// Player is offline - If the player is online, that takes precedence
- MCListener.callLoginEvents(sender);
+ MCChatUtils.callLoginEvents(sender);
} else {
val sender = MCChatUtils.removeSender(MCChatUtils.ConnectedSenders, channel.getId(), user);
- if (p == null)// Player is offline - If the player is online, that takes precedence
- callEventSync(new PlayerQuitEvent(sender, ""));
+ assert sender != null;
+ if (p == null // Player is offline - If the player is online, that takes precedence
+ && sender.isLoggedIn()) //Don't call the quit event if login failed
+ MCChatUtils.callLogoutEvent(sender, true);
+ sender.setLoggedIn(false);
}
} // ---- PermissionsEx warning is normal on logout ----
if (!start)
@@ -60,11 +60,8 @@ public class MCChatPrivate {
for (val entry : MCChatUtils.ConnectedSenders.entrySet())
for (val valueEntry : entry.getValue().entrySet())
if (MCChatUtils.getSender(MCChatUtils.OnlineSenders, valueEntry.getKey(), valueEntry.getValue().getUser()) == null) //If the player is online then the fake player was already logged out
- MCChatUtils.callEventExcludingSome(new PlayerQuitEvent(valueEntry.getValue(), "")); //This is sync
+ MCChatUtils.callLogoutEvent(valueEntry.getValue(), false); //This is sync
MCChatUtils.ConnectedSenders.clear();
}
- private static void callEventSync(Event event) {
- Bukkit.getScheduler().runTask(DiscordPlugin.plugin, () -> MCChatUtils.callEventExcludingSome(event));
- }
}
diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatUtils.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatUtils.java
index bd516c2..cbccc0d 100644
--- a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatUtils.java
+++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatUtils.java
@@ -5,6 +5,7 @@ import buttondevteam.discordplugin.*;
import buttondevteam.discordplugin.broadcaster.GeneralEventBroadcasterModule;
import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.TBMCSystemChatEvent;
+import com.google.common.collect.Sets;
import discord4j.core.object.entity.*;
import discord4j.core.object.util.Snowflake;
import io.netty.util.collection.LongObjectHashMap;
@@ -15,14 +16,20 @@ import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.event.player.PlayerLoginEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.AuthorNagException;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredListener;
import reactor.core.publisher.Mono;
import javax.annotation.Nullable;
+import java.net.InetAddress;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -43,6 +50,7 @@ public class MCChatUtils {
static @Nullable LastMsgData lastmsgdata;
static LongObjectHashMap lastmsgfromd = new LongObjectHashMap<>(); // Last message sent by a Discord user, used for clearing checkmarks
private static MinecraftChatModule module;
+ private static HashMap, HashSet> staticExcludedPlugins = new HashMap<>();
public static void updatePlayerList() {
if (notEnabled()) return;
@@ -74,19 +82,19 @@ public class MCChatUtils {
if (s.length < 3)
return;
s[0] = Bukkit.getOnlinePlayers().size() + " player" + (Bukkit.getOnlinePlayers().size() != 1 ? "s" : "")
- + " online";
+ + " online";
s[s.length - 1] = "Players: " + Bukkit.getOnlinePlayers().stream()
- .map(p -> DPUtils.sanitizeString(p.getDisplayName())).collect(Collectors.joining(", "));
+ .map(p -> DPUtils.sanitizeString(p.getDisplayName())).collect(Collectors.joining(", "));
((TextChannel) lmd.channel).edit(tce -> tce.setTopic(String.join("\n----\n", s)).setReason("Player list update")).subscribe(); //Don't wait
}
public static T addSender(HashMap> senders,
- User user, T sender) {
+ User user, T sender) {
return addSender(senders, user.getId().asString(), sender);
}
public static T addSender(HashMap> senders,
- String did, T sender) {
+ String did, T sender) {
var map = senders.get(did);
if (map == null)
map = new HashMap<>();
@@ -96,7 +104,7 @@ public class MCChatUtils {
}
public static T getSender(HashMap> senders,
- Snowflake channel, User user) {
+ Snowflake channel, User user) {
var map = senders.get(user.getId().asString());
if (map != null)
return map.get(channel);
@@ -104,7 +112,7 @@ public class MCChatUtils {
}
public static T removeSender(HashMap> senders,
- Snowflake channel, User user) {
+ Snowflake channel, User user) {
var map = senders.get(user.getId().asString());
if (map != null)
return map.remove(channel);
@@ -195,11 +203,11 @@ public class MCChatUtils {
static DiscordSenderBase getSender(Snowflake channel, final User author) {
//noinspection OptionalGetWithoutIsPresent
return Stream.>>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();
+ () -> 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();
}
/**
@@ -213,7 +221,7 @@ public class MCChatUtils {
System.out.println("Reset last message");
if (channel.getId().asLong() == module.chatChannel().get().asLong()) {
(lastmsgdata == null ? lastmsgdata = new LastMsgData(module.chatChannelMono().block(), null)
- : lastmsgdata).message = null;
+ : lastmsgdata).message = null;
System.out.println("Reset done: public chat");
return;
} // Don't set the whole object to null, the player and channel information should be preserved
@@ -227,9 +235,23 @@ public class MCChatUtils {
//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;
- callEventExcluding(event, false, module.excludedPlugins().get());
+ 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);
}
/**
@@ -290,6 +312,50 @@ public class MCChatUtils {
}
}
+ /**
+ * 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);
+ });
+ }
+
+ /**
+ * 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);
+ }
+
+ static void callEventSync(Event event) {
+ Bukkit.getScheduler().runTask(DiscordPlugin.plugin, () -> callEventExcludingSome(event));
+ }
+
@RequiredArgsConstructor
public static class LastMsgData {
public Message message;
diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java
index 279cc04..fe68342 100644
--- a/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java
+++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java
@@ -18,12 +18,12 @@ 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.PlayerKickEvent;
+import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerLoginEvent.Result;
import org.bukkit.event.server.BroadcastMessageEvent;
import reactor.core.publisher.Mono;
-import java.net.InetAddress;
import java.util.Objects;
@RequiredArgsConstructor
@@ -38,7 +38,7 @@ class MCListener implements Listener {
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.callEventExcludingSome(new PlayerQuitEvent(dcp, "")));
+ .ifPresent(dcp -> MCChatUtils.callLogoutEvent(dcp, false));
}
@EventHandler(priority = EventPriority.LOWEST)
@@ -70,30 +70,13 @@ class MCListener implements Listener {
Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin,
() -> MCChatUtils.ConnectedSenders.values().stream().flatMap(v -> v.values().stream())
.filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny()
- .ifPresent(MCListener::callLoginEvents));
+ .ifPresent(MCChatUtils::callLoginEvents));
Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin,
ChromaBot.getInstance()::updatePlayerList, 5);
final String message = e.GetPlayer().PlayerName().get() + " left the game";
MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(message), e.getPlayer(), ChannelconBroadcast.JOINLEAVE, true);
}
- /**
- * Call it from an async thread.
- */
- public static void callLoginEvents(DiscordConnectedPlayer dcp) {
- val event = new AsyncPlayerPreLoginEvent(dcp.getName(), InetAddress.getLoopbackAddress(), dcp.getUniqueId());
- MCChatUtils.callEventExcludingSome(event);
- if (event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED)
- return;
- Bukkit.getScheduler().runTask(DiscordPlugin.plugin, () -> {
- val ev = new PlayerLoginEvent(dcp, "localhost", InetAddress.getLoopbackAddress());
- MCChatUtils.callEventExcludingSome(ev);
- if (ev.getResult() != Result.ALLOWED)
- return;
- MCChatUtils.callEventExcludingSome(new PlayerJoinEvent(dcp, ""));
- });
- }
-
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerKick(PlayerKickEvent e) {
/*if (!DiscordPlugin.hooked && !e.getReason().equals("The server is restarting")
diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java b/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java
index b4f8ec6..9e9bfd3 100644
--- a/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java
+++ b/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java
@@ -1,9 +1,11 @@
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;
@@ -106,6 +108,12 @@ public class MinecraftChatModule extends Component {
});
}
}
+
+ try {
+ new LPInjector(MainPlugin.Instance);
+ } catch (Exception e) {
+ TBMCCoreAPI.SendException("Failed to init LuckPerms injector", e);
+ }
}
@Override
diff --git a/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordFakePlayer.java b/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordFakePlayer.java
index f197c84..6879155 100755
--- a/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordFakePlayer.java
+++ b/src/main/java/buttondevteam/discordplugin/playerfaker/DiscordFakePlayer.java
@@ -5,6 +5,7 @@ import buttondevteam.discordplugin.mcchat.MinecraftChatModule;
import discord4j.core.object.entity.MessageChannel;
import discord4j.core.object.entity.User;
import lombok.Getter;
+import lombok.Setter;
import lombok.experimental.Delegate;
import org.bukkit.*;
import org.bukkit.advancement.Advancement;
@@ -17,6 +18,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.map.MapView;
import org.bukkit.permissions.PermissibleBase;
+import org.bukkit.permissions.ServerOperator;
import org.bukkit.plugin.Plugin;
import org.bukkit.scoreboard.Scoreboard;
@@ -26,693 +28,706 @@ import java.util.*;
@SuppressWarnings("deprecation")
public class DiscordFakePlayer extends DiscordHumanEntity implements Player {
protected DiscordFakePlayer(User user, MessageChannel channel, int entityId, UUID uuid, String mcname, MinecraftChatModule module) {
- super(user, channel, entityId, uuid, module);
- 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.getUsername();
- }
-
- @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 Objects.requireNonNull(user.asMember(DiscordPlugin.mainServer.getId()).block()).getDisplayName();
- }
-
- @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) {
- }
+ super(user, channel, entityId, uuid, module);
+ origPerm = perm = new PermissibleBase(basePlayer = Bukkit.getOfflinePlayer(uuid));
+ name = mcname;
+ }
+
+ @Delegate(excludes = ServerOperator.class)
+ private PermissibleBase origPerm;
+
+ private @Getter String name;
+
+ private @Getter OfflinePlayer basePlayer;
+
+ @Getter
+ @Setter
+ private PermissibleBase perm;
+
+ public void setOp(boolean value) { //CraftPlayer-compatible implementation
+ this.origPerm.setOp(value);
+ this.perm.recalculatePermissions();
+ }
+
+ public boolean isOp() { return this.origPerm.isOp(); }
+
+ @Override
+ public EntityType getType() {
+ return EntityType.PLAYER;
+ }
+
+ @Override
+ public String getCustomName() {
+ return user.getUsername();
+ }
+
+ @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 Objects.requireNonNull(user.asMember(DiscordPlugin.mainServer.getId()).block()).getDisplayName();
+ }
+
+ @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, 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, 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 playSound(Location location, String sound, SoundCategory category, float volume, float pitch) {
+ }
- @Override
- public void stopSound(Sound sound) {
- }
+ @Override
+ public void stopSound(Sound sound) {
+ }
- @Override
- public void stopSound(String sound) {
- }
+ @Override
+ public void stopSound(String sound) {
+ }
- @Override
- public void stopSound(Sound sound, SoundCategory category) {
- }
+ @Override
+ public void stopSound(Sound sound, SoundCategory category) {
+ }
- @Override
- public void stopSound(String 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, int data) {
+ }
- @Override
- public void playEffect(Location loc, Effect effect, T data) {
- }
+ @Override
+ public void playEffect(Location loc, Effect effect, T data) {
+ }
- @Override
- public void sendBlockChange(Location loc, Material material, byte 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 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 sendBlockChange(Location loc, int material, byte data) {
+ }
- @Override
- public void sendSignChange(Location loc, String[] lines) throws IllegalArgumentException {
- }
+ @Override
+ public void sendSignChange(Location loc, String[] lines) throws IllegalArgumentException {
+ }
- @Override
- public void sendMap(MapView map) {
- }
+ @Override
+ public void sendMap(MapView map) {
+ }
- @Override
- public void updateInventory() {
- }
+ @Override
+ public void updateInventory() {
+ }
- @Override
- public void awardAchievement(@SuppressWarnings("deprecation") Achievement achievement) {
- }
+ @Override
+ public void awardAchievement(@SuppressWarnings("deprecation") Achievement achievement) {
+ }
- @Override
- public void removeAchievement(@SuppressWarnings("deprecation") Achievement achievement) {
- }
+ @Override
+ public void removeAchievement(@SuppressWarnings("deprecation") Achievement achievement) {
+ }
- @Override
- public boolean hasAchievement(@SuppressWarnings("deprecation") Achievement achievement) {
- return false;
- }
+ @Override
+ public boolean hasAchievement(@SuppressWarnings("deprecation") Achievement achievement) {
+ return false;
+ }
- @Override
- public void incrementStatistic(Statistic statistic) throws IllegalArgumentException {
- }
+ @Override
+ public void incrementStatistic(Statistic statistic) throws IllegalArgumentException {
+ }
- @Override
- public void decrementStatistic(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 incrementStatistic(Statistic statistic, int amount) throws IllegalArgumentException {
- }
+ }
- @Override
- public void decrementStatistic(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 void setStatistic(Statistic statistic, int newValue) throws IllegalArgumentException {
- }
+ }
- @Override
- public int getStatistic(Statistic statistic) throws IllegalArgumentException {
+ @Override
+ public int getStatistic(Statistic statistic) throws IllegalArgumentException {
- return 0;
- }
+ return 0;
+ }
- @Override
- public void incrementStatistic(Statistic statistic, Material material) throws IllegalArgumentException {
+ @Override
+ public void incrementStatistic(Statistic statistic, Material material) throws IllegalArgumentException {
- }
+ }
- @Override
- public void decrementStatistic(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 {
+ @Override
+ public int getStatistic(Statistic statistic, Material material) throws IllegalArgumentException {
- return 0;
- }
+ return 0;
+ }
- @Override
- public void incrementStatistic(Statistic statistic, Material material, int amount) throws IllegalArgumentException {
+ @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 decrementStatistic(Statistic statistic, Material material, int amount) throws IllegalArgumentException {
- }
+ }
- @Override
- public void setStatistic(Statistic statistic, Material material, int newValue) 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 incrementStatistic(Statistic statistic, EntityType entityType) throws IllegalArgumentException {
- }
+ }
- @Override
- public void decrementStatistic(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 {
+ @Override
+ public int getStatistic(Statistic statistic, EntityType entityType) throws IllegalArgumentException {
- return 0;
- }
+ return 0;
+ }
- @Override
- public void incrementStatistic(Statistic statistic, EntityType entityType, int amount)
- throws IllegalArgumentException {
+ @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 decrementStatistic(Statistic statistic, EntityType entityType, int amount) {
- }
+ }
- @Override
- public void setStatistic(Statistic statistic, EntityType entityType, int newValue) {
+ @Override
+ public void setStatistic(Statistic statistic, EntityType entityType, int newValue) {
- }
+ }
- @Override
- public void setPlayerTime(long time, boolean relative) {
+ @Override
+ public void setPlayerTime(long time, boolean relative) {
- }
+ }
- @Override
- public long getPlayerTime() {
+ @Override
+ public long getPlayerTime() {
- return 0;
- }
+ return 0;
+ }
- @Override
- public long getPlayerTimeOffset() {
+ @Override
+ public long getPlayerTimeOffset() {
- return 0;
- }
+ return 0;
+ }
- @Override
- public boolean isPlayerTimeRelative() {
+ @Override
+ public boolean isPlayerTimeRelative() {
- return false;
- }
+ return false;
+ }
- @Override
- public void resetPlayerTime() {
+ @Override
+ public void resetPlayerTime() {
- }
+ }
- @Override
- public void setPlayerWeather(WeatherType type) {
+ @Override
+ public void setPlayerWeather(WeatherType type) {
- }
+ }
- @Override
- public WeatherType getPlayerWeather() {
+ @Override
+ public WeatherType getPlayerWeather() {
- return null;
- }
+ return null;
+ }
- @Override
- public void resetPlayerWeather() {
+ @Override
+ public void resetPlayerWeather() {
- }
+ }
- @Override
- public void giveExp(int amount) {
+ @Override
+ public void giveExp(int amount) {
- }
+ }
- @Override
- public void giveExpLevels(int amount) {
+ @Override
+ public void giveExpLevels(int amount) {
- }
+ }
- @Override
- public float getExp() {
+ @Override
+ public float getExp() {
- return 0;
- }
+ return 0;
+ }
- @Override
- public void setExp(float exp) {
+ @Override
+ public void setExp(float exp) {
- }
+ }
- @Override
- public int getLevel() {
+ @Override
+ public int getLevel() {
- return 0;
- }
+ return 0;
+ }
- @Override
- public void setLevel(int level) {
+ @Override
+ public void setLevel(int level) {
- }
+ }
- @Override
- public int getTotalExperience() {
+ @Override
+ public int getTotalExperience() {
- return 0;
- }
+ return 0;
+ }
- @Override
- public void setTotalExperience(int exp) {
+ @Override
+ public void setTotalExperience(int exp) {
- }
+ }
- @Override
- public float getExhaustion() {
+ @Override
+ public float getExhaustion() {
- return 0;
- }
+ return 0;
+ }
- @Override
- public void setExhaustion(float value) {
+ @Override
+ public void setExhaustion(float value) {
- }
+ }
- @Override
- public float getSaturation() {
+ @Override
+ public float getSaturation() {
- return 0;
- }
+ return 0;
+ }
- @Override
- public void setSaturation(float value) {
+ @Override
+ public void setSaturation(float value) {
- }
+ }
- @Override
- public int getFoodLevel() {
+ @Override
+ public int getFoodLevel() {
- return 0;
- }
+ return 0;
+ }
- @Override
- public void setFoodLevel(int value) {
+ @Override
+ public void setFoodLevel(int value) {
- }
+ }
- @Override
- public Location getBedSpawnLocation() {
- return null;
- }
+ @Override
+ public Location getBedSpawnLocation() {
+ return null;
+ }
- @Override
- public void setBedSpawnLocation(Location location) {
- }
+ @Override
+ public void setBedSpawnLocation(Location location) {
+ }
- @Override
- public void setBedSpawnLocation(Location location, boolean force) {
- }
+ @Override
+ public void setBedSpawnLocation(Location location, boolean force) {
+ }
- @Override
- public boolean getAllowFlight() {
- return false;
- }
+ @Override
+ public boolean getAllowFlight() {
+ return false;
+ }
- @Override
- public void setAllowFlight(boolean flight) {
- }
+ @Override
+ public void setAllowFlight(boolean flight) {
+ }
- @Override
- public void hidePlayer(Player player) {
- }
+ @Override
+ public void hidePlayer(Player player) {
+ }
- @Override
- public void showPlayer(Player player) {
- }
+ @Override
+ public void showPlayer(Player player) {
+ }
- @Override
- public boolean canSee(Player player) { // Nobody can see them
- return false;
- }
+ @Override
+ public boolean canSee(Player player) { // Nobody can see them
+ return false;
+ }
- @Override
- public boolean isFlying() {
- return false;
- }
+ @Override
+ public boolean isFlying() {
+ return false;
+ }
- @Override
- public void setFlying(boolean value) {
- }
+ @Override
+ public void setFlying(boolean value) {
+ }
- @Override
- public void setFlySpeed(float value) throws IllegalArgumentException {
- }
+ @Override
+ public void setFlySpeed(float value) throws IllegalArgumentException {
+ }
- @Override
- public void setWalkSpeed(float value) throws IllegalArgumentException {
- }
+ @Override
+ public void setWalkSpeed(float value) throws IllegalArgumentException {
+ }
- @Override
- public float getFlySpeed() {
- return 0;
- }
+ @Override
+ public float getFlySpeed() {
+ return 0;
+ }
- @Override
- public float getWalkSpeed() {
- return 0;
- }
+ @Override
+ public float getWalkSpeed() {
+ return 0;
+ }
- @Override
- public void setTexturePack(String url) {
- }
+ @Override
+ public void setTexturePack(String url) {
+ }
- @Override
- public void setResourcePack(String url) {
- }
+ @Override
+ public void setResourcePack(String url) {
+ }
- @Override
- public void setResourcePack(String url, byte[] hash) {
- }
+ @Override
+ public void setResourcePack(String url, byte[] hash) {
+ }
- @Override
- public Scoreboard getScoreboard() {
- return null;
- }
+ @Override
+ public Scoreboard getScoreboard() {
+ return null;
+ }
- @Override
- public void setScoreboard(Scoreboard scoreboard) throws IllegalArgumentException, IllegalStateException {
- }
+ @Override
+ public void setScoreboard(Scoreboard scoreboard) throws IllegalArgumentException, IllegalStateException {
+ }
- @Override
- public boolean isHealthScaled() {
- return false;
- }
+ @Override
+ public boolean isHealthScaled() {
+ return false;
+ }
- @Override
- public void setHealthScaled(boolean scale) {
- }
+ @Override
+ public void setHealthScaled(boolean scale) {
+ }
- @Override
- public void setHealthScale(double scale) throws IllegalArgumentException {
- }
+ @Override
+ public void setHealthScale(double scale) throws IllegalArgumentException {
+ }
- @Override
- public double getHealthScale() {
- return 1;
- }
+ @Override
+ public double getHealthScale() {
+ return 1;
+ }
- @Override
- public Entity getSpectatorTarget() {
- return null;
- }
+ @Override
+ public Entity getSpectatorTarget() {
+ return null;
+ }
- @Override
- public void setSpectatorTarget(Entity entity) {
- }
+ @Override
+ public void setSpectatorTarget(Entity entity) {
+ }
- @Override
- public void sendTitle(String title, String subtitle) {
- }
+ @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 sendTitle(String title, String subtitle, int fadeIn, int stay, int fadeOut) {
+ }
- @Override
- public void resetTitle() {
- }
+ @Override
+ public void resetTitle() {
+ }
- @Override
- public void spawnParticle(Particle particle, Location location, int count) {
- }
+ @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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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 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 AdvancementProgress getAdvancementProgress(Advancement advancement) { // TODO: Test
+ return null;
+ }
- @Override
- public String getLocale() {
+ @Override
+ public String getLocale() {
- return null;
- }
+ return null;
+ }
- @Override
- public Player.Spigot spigot() {
- return new Player.Spigot();
- }
+ @Override
+ public Player.Spigot spigot() {
+ return new Player.Spigot();
+ }
}
diff --git a/src/main/java/buttondevteam/discordplugin/playerfaker/perm/LPInjector.java b/src/main/java/buttondevteam/discordplugin/playerfaker/perm/LPInjector.java
new file mode 100644
index 0000000..de5a84b
--- /dev/null
+++ b/src/main/java/buttondevteam/discordplugin/playerfaker/perm/LPInjector.java
@@ -0,0 +1,240 @@
+package buttondevteam.discordplugin.playerfaker.perm;
+
+import buttondevteam.core.MainPlugin;
+import buttondevteam.discordplugin.mcchat.MCChatUtils;
+import buttondevteam.discordplugin.playerfaker.DiscordFakePlayer;
+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 DiscordFakePlayer))
+ return; //Normal players must be handled by the plugin
+
+ final DiscordFakePlayer player = (DiscordFakePlayer) 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 DiscordFakePlayer))
+ return;
+
+ final DiscordFakePlayer player = (DiscordFakePlayer) 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(DiscordFakePlayer 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(DiscordFakePlayer 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);
+ }
+ }
+ }
+}