diff --git a/pom.xml b/pom.xml
index 3c1de6e..4b4d005 100755
--- a/pom.xml
+++ b/pom.xml
@@ -114,6 +114,10 @@
Reactor-Tools
https://repo.spring.io/milestone
-->
+
+ papermc
+ https://papermc.io/repo/repository/maven-public/
+
@@ -141,6 +145,12 @@
1.14.4-R0.1-SNAPSHOT
provided
+
+ com.destroystokyo.paper
+ paper
+ 1.16.3-R0.1-SNAPSHOT
+ provided
+
com.discord4j
@@ -201,10 +211,11 @@
master-SNAPSHOT
provided
+
org.mockito
mockito-core
- 3.0.0
+ 3.5.10
org.mockito
diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java
index 0c983cc..f99bcbd 100755
--- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java
+++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java
@@ -35,6 +35,7 @@ import lombok.val;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
+import org.mockito.internal.util.MockUtil;
import reactor.core.publisher.Mono;
import java.awt.*;
@@ -101,6 +102,17 @@ public class DiscordPlugin extends ButtonPlugin {
return getIConfig().getData("inviteLink", "");
}
+ @Override
+ public void onLoad() { //Needed by ServerWatcher
+ var thread = Thread.currentThread();
+ getLogger().info("Setting context class loader for " + thread);
+ var cl = thread.getContextClassLoader();
+ thread.setContextClassLoader(getClassLoader());
+ MockUtil.isMock(null); //Load MockUtil to load Mockito plugins
+ getLogger().info("Restoring context class loader");
+ thread.setContextClassLoader(cl);
+ }
+
@Override
public void pluginEnable() {
try {
diff --git a/src/main/java/buttondevteam/discordplugin/playerfaker/ServerWatcher.java b/src/main/java/buttondevteam/discordplugin/playerfaker/ServerWatcher.java
index ed63c2e..bb039f7 100644
--- a/src/main/java/buttondevteam/discordplugin/playerfaker/ServerWatcher.java
+++ b/src/main/java/buttondevteam/discordplugin/playerfaker/ServerWatcher.java
@@ -1,12 +1,14 @@
package buttondevteam.discordplugin.playerfaker;
import buttondevteam.discordplugin.mcchat.MCChatUtils;
+import com.destroystokyo.paper.profile.CraftPlayerProfile;
import lombok.RequiredArgsConstructor;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.mockito.Mockito;
+import java.lang.reflect.Modifier;
import java.util.*;
public class ServerWatcher {
@@ -19,8 +21,17 @@ public class ServerWatcher {
serverField.setAccessible(true);
if (enable) {
var serverClass = Bukkit.getServer().getClass();
- var mock = Mockito.mock(serverClass, Mockito.withSettings()
- .stubOnly().defaultAnswer(invocation -> {
+ //var mockMaker = new InlineByteBuddyMockMaker();
+ //System.setProperty("net.bytebuddy.experimental", "true");
+ /*try {
+ var resources = cl.getResources("mockito-extensions/" + MockMaker.class.getName());
+ System.out.println("Found resources: " + resources);
+ Iterables.toIterable(resources).forEach(resource -> System.out.println("Resource: " + resource));
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to load " + MockMaker.class, e);
+ }*/
+ var settings = Mockito.withSettings().stubOnly()
+ .defaultAnswer(invocation -> {
var method = invocation.getMethod();
int pc = method.getParameterCount();
Player player = null;
@@ -38,18 +49,34 @@ public class ServerWatcher {
break;
case "getOnlinePlayers":
if (playerList == null) {
- @SuppressWarnings("unchecked") var list = (List) invocation.callRealMethod();
+ @SuppressWarnings("unchecked") var list = (List) method.invoke(origServer, invocation.getArguments());
playerList = new AppendListView<>(list, fakePlayers);
}
return playerList;
+ case "createProfile": //Paper's method, casts the player to a CraftPlayer
+ if (pc == 2) {
+ UUID uuid = invocation.getArgument(0);
+ String name = invocation.getArgument(1);
+ player = uuid != null ? MCChatUtils.LoggedInPlayers.get(uuid) : null;
+ if (player == null && name != null)
+ player = MCChatUtils.LoggedInPlayers.values().stream()
+ .filter(dcp -> dcp.getName().equalsIgnoreCase(name)).findAny().orElse(null);
+ if (player != null)
+ return new CraftPlayerProfile(player.getUniqueId(), player.getName());
+ }
+ break;
}
if (player != null)
return player;
- return invocation.callRealMethod();
- }));
+ return method.invoke(origServer, invocation.getArguments());
+ });
+ //var mock = mockMaker.createMock(settings, MockHandlerFactory.createMockHandler(settings));
+ //thread.setContextClassLoader(cl);
+ var mock = Mockito.mock(serverClass, settings);
var originalServer = serverField.get(null);
for (var field : serverClass.getFields()) //Copy public fields, private fields aren't accessible directly anyways
- field.set(mock, field.get(originalServer));
+ if (!Modifier.isFinal(field.getModifiers()) && !Modifier.isStatic(field.getModifiers()))
+ field.set(mock, field.get(originalServer));
serverField.set(null, mock);
origServer = (Server) originalServer;
} else if (origServer != null)
diff --git a/src/main/java/buttondevteam/discordplugin/playerfaker/VanillaCommandListener15.java b/src/main/java/buttondevteam/discordplugin/playerfaker/VanillaCommandListener15.java
index e0ea99b..66dc935 100644
--- a/src/main/java/buttondevteam/discordplugin/playerfaker/VanillaCommandListener15.java
+++ b/src/main/java/buttondevteam/discordplugin/playerfaker/VanillaCommandListener15.java
@@ -79,7 +79,7 @@ public class VanillaCommandListener15
var server = Bukkit.getServer();
var cmap = (SimpleCommandMap) server.getClass().getMethod("getCommandMap").invoke(server);
val cmd = cmap.getCommand(cmdstr.split(" ")[0].toLowerCase());
- if (!(dsender instanceof Player) || !vcwcl.isAssignableFrom(cmd.getClass()))
+ if (!(dsender instanceof Player) || cmd == null || !vcwcl.isAssignableFrom(cmd.getClass()))
return Bukkit.dispatchCommand(dsender, cmdstr); // Unconnected users are treated well in vanilla cmds
if (!(dsender instanceof IMCPlayer))
diff --git a/src/main/resources/mockito-extensions/org.mockito.plugins.MockMaker b/src/main/resources/mockito-extensions/org.mockito.plugins.MockMaker
index ca6ee9c..7da34da 100644
--- a/src/main/resources/mockito-extensions/org.mockito.plugins.MockMaker
+++ b/src/main/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -1 +1 @@
-mock-maker-inline
\ No newline at end of file
+org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker
\ No newline at end of file