Command handling improvement, PLW work

More correct fallback for command handling
Getting closer to finish PlayerListWatcher
This commit is contained in:
Norbi Peti 2019-08-23 01:58:47 +02:00
parent 42e91409c7
commit c456b24333
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
3 changed files with 68 additions and 48 deletions

View file

@ -12,7 +12,7 @@ public class GeneralEventBroadcasterModule extends Component<DiscordPlugin> {
@Override @Override
protected void enable() { protected void enable() {
try { try {
PlayerListWatcher.hookUp(); PlayerListWatcher.hookUpDown(true);
DPUtils.getLogger().info("Finished hooking into the player list"); DPUtils.getLogger().info("Finished hooking into the player list");
hooked = true; hooked = true;
} catch (Exception e) { } catch (Exception e) {
@ -27,7 +27,7 @@ public class GeneralEventBroadcasterModule extends Component<DiscordPlugin> {
protected void disable() { protected void disable() {
try { try {
if (!hooked) return; if (!hooked) return;
if (PlayerListWatcher.hookDown()) if (PlayerListWatcher.hookUpDown(false))
DPUtils.getLogger().info("Finished unhooking the player list!"); DPUtils.getLogger().info("Finished unhooking the player list!");
else else
DPUtils.getLogger().info("Didn't have the player list hooked."); DPUtils.getLogger().info("Didn't have the player list hooked.");

View file

@ -1,8 +1,8 @@
package buttondevteam.discordplugin.broadcaster; package buttondevteam.discordplugin.broadcaster;
import buttondevteam.lib.TBMCCoreAPI;
import lombok.val; import lombok.val;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_12_R1.CraftServer;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock; import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer; import org.mockito.stubbing.Answer;
@ -53,57 +53,75 @@ public class PlayerListWatcher {
} }
}*/ }*/
static void hookUp() throws Exception { static boolean hookUpDown(boolean up) throws Exception {
val csc = Bukkit.getServer().getClass(); val csc = Bukkit.getServer().getClass();
Field conf = csc.getDeclaredField("console"); Field conf = csc.getDeclaredField("console");
conf.setAccessible(true); conf.setAccessible(true);
val server = conf.get(Bukkit.getServer()); val server = conf.get(Bukkit.getServer());
val nms = server.getClass().getPackage().getName(); val nms = server.getClass().getPackage().getName();
val dplc = Class.forName(nms + ".DedicatedPlayerList"); val dplc = Class.forName(nms + ".DedicatedPlayerList");
mock = Mockito.mock(dplc, new Answer() { // Cannot call super constructor val currentPL = server.getClass().getMethod("getPlayerList").invoke(server);
@Override if (up) {
public Object answer(InvocationOnMock invocation) throws Throwable { mock = Mockito.mock(dplc, new Answer() { // Cannot call super constructor
return invocation.getMethod().invoke(plist, invocation.getArguments()); @Override
} public Object answer(InvocationOnMock invocation) throws Throwable {
}); if (!invocation.getMethod().getName().equals("sendMessage"))
plist = server.getClass().getMethod("getPlayerList").invoke(server); return invocation.getMethod().invoke(plist, invocation.getArguments());
try { val args = invocation.getArguments();
Field mpf = mock.getClass().getField("maxPlayers"); val params = invocation.getMethod().getParameterTypes();
mpf.setAccessible(true); if (params.length == 0) {
Field modf = mpf.getClass().getDeclaredField("modifiers"); TBMCCoreAPI.SendException("Found a strange method",
modf.setAccessible(true); new Exception("Found a sendMessage() method without arguments."));
modf.set(mpf, mpf.getModifiers() & ~Modifier.FINAL); return null;
mpf.set(mock, mpf.get(plist)); }
} catch (NoSuchFieldException ignored) { if (params[0].getSimpleName().equals("IChatBaseComponent[]"))
//The field no longer exists on 1.14 for (val arg : (Object[]) args[0])
} sendMessage(arg, true);
Field plf = mock.getClass().getField("players"); else if (params[0].getSimpleName().equals("IChatBaseComponent"))
plf.setAccessible(true); if (params.length > 1 && params[1].getSimpleName().equalsIgnoreCase("boolean"))
Field modf = plf.getClass().getDeclaredField("modifiers"); sendMessage(args[0], (Boolean) args[1]);
modf.setAccessible(true); else
modf.set(plf, plf.getModifiers() & ~Modifier.FINAL); sendMessage(args[0], true);
plf.set(mock, plf.get(plist)); else
try { TBMCCoreAPI.SendException("Found a method with interesting params",
server.getClass().getMethod("a", dplc).invoke(server, mock); new Exception("Found a sendMessage(" + params[0].getSimpleName() + ") method"));
} catch (NoSuchMethodException e) { return null;
server.getClass().getMethod("a", Class.forName(server.getClass().getPackage().getName() + ".PlayerList")).invoke(server, mock); }
}
Field pllf = CraftServer.class.getDeclaredField("playerList");
pllf.setAccessible(true);
pllf.set(Bukkit.getServer(), mock);
}
static boolean hookDown() throws Exception { private void sendMessage(Object chatComponent, boolean system) {
/*Field conf = CraftServer.class.getDeclaredField("console"); //TODO
conf.setAccessible(true); }
val server = (MinecraftServer) conf.get(Bukkit.getServer()); });
val plist = (DedicatedPlayerList) server.getPlayerList(); plist = currentPL;
if (!(plist instanceof PlayerListWatcher)) try {
return false; Field mpf = mock.getClass().getField("maxPlayers");
server.a(((PlayerListWatcher) plist).plist); mpf.setAccessible(true);
Field pllf = CraftServer.class.getDeclaredField("playerList"); Field modf = mpf.getClass().getDeclaredField("modifiers");
modf.setAccessible(true);
modf.set(mpf, mpf.getModifiers() & ~Modifier.FINAL);
mpf.set(mock, mpf.get(plist));
} catch (NoSuchFieldException ignored) {
//The field no longer exists on 1.14
}
Field plf = mock.getClass().getField("players");
plf.setAccessible(true);
Field modf = plf.getClass().getDeclaredField("modifiers");
modf.setAccessible(true);
modf.set(plf, plf.getModifiers() & ~Modifier.FINAL);
plf.set(mock, plf.get(plist));
} else {
if (!(mock instanceof PlayerListWatcher))
return false;
}
try {
server.getClass().getMethod("a", dplc).invoke(server, up ? mock : plist);
} catch (NoSuchMethodException e) {
server.getClass().getMethod("a", Class.forName(server.getClass().getPackage().getName() + ".PlayerList"))
.invoke(server, up ? mock : plist);
}
Field pllf = csc.getDeclaredField("playerList");
pllf.setAccessible(true); pllf.setAccessible(true);
pllf.set(Bukkit.getServer(), ((PlayerListWatcher) plist).plist);*/ pllf.set(Bukkit.getServer(), up ? mock : plist);
return true; return true;
} }
} }

View file

@ -347,10 +347,12 @@ public class MCChatListener implements Listener {
VanillaCommandListener.runBukkitOrVanillaCommand(dsender, cmd); VanillaCommandListener.runBukkitOrVanillaCommand(dsender, cmd);
else if (mcpackage.contains("1_14")) else if (mcpackage.contains("1_14"))
VanillaCommandListener14.runBukkitOrVanillaCommand(dsender, cmd); VanillaCommandListener14.runBukkitOrVanillaCommand(dsender, cmd);
else
Bukkit.dispatchCommand(dsender, cmd);
} catch (NoClassDefFoundError e) { } catch (NoClassDefFoundError e) {
Bukkit.dispatchCommand(dsender, cmd); TBMCCoreAPI.SendException("A class is not found when trying to run command " + cmd + "!", e);
} }
Bukkit.getLogger().info(dsender.getName() + " issued command from Discord: /" + cmdlowercased); Bukkit.getLogger().info(dsender.getName() + " issued command from Discord: /" + cmd);
if (clmd != null) if (clmd != null)
channel.set(chtmp); channel.set(chtmp);
}); });