mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2024-12-22 09:08:03 +01:00
Boom! NMS is gone! (Again) Will it come back?
Used reflection to get the command map from the server instead of using the NMS call. Also, more importantly, this commit enables CompositeCommands to auto-register their top-level command in the constructor. No need to separately obtain the command manager object. Yes, easy API. :-)
This commit is contained in:
parent
9b0992c30d
commit
452311fb69
2
pom.xml
2
pom.xml
@ -67,7 +67,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mockito</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
<artifactId>mockito-all</artifactId>
|
<artifactId>mockito-all</artifactId>
|
||||||
<version>1.9.5</version>
|
<version>1.10.19</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -21,8 +21,6 @@ import us.tastybento.bskyblock.listeners.PanelListener;
|
|||||||
import us.tastybento.bskyblock.managers.AddonsManager;
|
import us.tastybento.bskyblock.managers.AddonsManager;
|
||||||
import us.tastybento.bskyblock.managers.CommandsManager;
|
import us.tastybento.bskyblock.managers.CommandsManager;
|
||||||
import us.tastybento.bskyblock.managers.LocalesManager;
|
import us.tastybento.bskyblock.managers.LocalesManager;
|
||||||
import us.tastybento.bskyblock.util.Util;
|
|
||||||
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main BSkyBlock class - provides an island minigame in the sky
|
* Main BSkyBlock class - provides an island minigame in the sky
|
||||||
@ -66,8 +64,8 @@ public class BSkyBlock extends JavaPlugin implements BSBModule {
|
|||||||
|
|
||||||
// Set up commands
|
// Set up commands
|
||||||
commandsManager = new CommandsManager();
|
commandsManager = new CommandsManager();
|
||||||
commandsManager.registerCommand(this, new IslandCommand());
|
new IslandCommand();
|
||||||
commandsManager.registerCommand(this, new AdminCommand());
|
new AdminCommand();
|
||||||
|
|
||||||
// These items have to be loaded when the server has done 1 tick.
|
// These items have to be loaded when the server has done 1 tick.
|
||||||
// Note Worlds are not loaded this early, so any Locations or World reference will be null
|
// Note Worlds are not loaded this early, so any Locations or World reference will be null
|
||||||
@ -206,16 +204,6 @@ public class BSkyBlock extends JavaPlugin implements BSBModule {
|
|||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NMSAbstraction getNMSHandler() {
|
|
||||||
NMSAbstraction nmsHandler = null;
|
|
||||||
try {
|
|
||||||
nmsHandler = Util.getNMSHandler();
|
|
||||||
} catch(Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return nmsHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandsManager getCommandsManager() {
|
public CommandsManager getCommandsManager() {
|
||||||
return commandsManager;
|
return commandsManager;
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,28 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||||||
* @param string - aliases for this command
|
* @param string - aliases for this command
|
||||||
*/
|
*/
|
||||||
public CompositeCommand(String label, String... string) {
|
public CompositeCommand(String label, String... string) {
|
||||||
|
super(label);
|
||||||
|
if (DEBUG)
|
||||||
|
Bukkit.getLogger().info("DEBUG: top level command registering..." + label);
|
||||||
|
this.setAliases(new ArrayList<>(Arrays.asList(string)));
|
||||||
|
this.parent = null;
|
||||||
|
setUsage("");
|
||||||
|
this.subCommandLevel = 0; // Top level
|
||||||
|
this.subCommands = new LinkedHashMap<>();
|
||||||
|
// Register command if it is not already registered
|
||||||
|
if (getPlugin().getCommand(label) == null) {
|
||||||
|
getPlugin().getCommandsManager().registerCommand(getPlugin(), this);
|
||||||
|
}
|
||||||
|
this.setup();
|
||||||
|
if (!this.getSubCommand("help").isPresent() && !label.equals("help"))
|
||||||
|
new DefaultHelpCommand(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used only for testing....
|
||||||
|
*/
|
||||||
|
public CompositeCommand(BSkyBlock plugin, String label, String... string) {
|
||||||
super(label);
|
super(label);
|
||||||
this.setAliases(new ArrayList<>(Arrays.asList(string)));
|
this.setAliases(new ArrayList<>(Arrays.asList(string)));
|
||||||
this.parent = null;
|
this.parent = null;
|
||||||
|
@ -11,18 +11,19 @@ public class AdminCommand extends CompositeCommand {
|
|||||||
|
|
||||||
public AdminCommand() {
|
public AdminCommand() {
|
||||||
super(Settings.ADMINCOMMAND, "bsb");
|
super(Settings.ADMINCOMMAND, "bsb");
|
||||||
this.setPermission(Settings.PERMPREFIX + "admin.*");
|
|
||||||
this.setOnlyPlayer(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setup() {
|
public void setup() {
|
||||||
|
this.setPermission(Settings.PERMPREFIX + "admin.*");
|
||||||
|
this.setOnlyPlayer(false);
|
||||||
|
this.setDescription("admin.help.description");
|
||||||
new AdminVersionCommand(this);
|
new AdminVersionCommand(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(User user, List<String> args) {
|
public boolean execute(User user, List<String> args) {
|
||||||
return true;
|
return this.getSubCommand("help").get().execute(user, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,6 @@ public class IslandCommand extends CompositeCommand {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(User user, List<String> args) {
|
public boolean execute(User user, List<String> args) {
|
||||||
user.sendLegacyMessage("You successfully did /is !");
|
|
||||||
if (!getPlugin().getIslands().hasIsland(user.getUniqueId())) {
|
if (!getPlugin().getIslands().hasIsland(user.getUniqueId())) {
|
||||||
return this.getSubCommand("create").get().execute(user, args);
|
return this.getSubCommand("create").get().execute(user, args);
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,25 @@
|
|||||||
package us.tastybento.bskyblock.managers;
|
package us.tastybento.bskyblock.managers;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandMap;
|
||||||
|
|
||||||
import us.tastybento.bskyblock.BSkyBlock;
|
|
||||||
import us.tastybento.bskyblock.api.BSBModule;
|
import us.tastybento.bskyblock.api.BSBModule;
|
||||||
|
|
||||||
public final class CommandsManager {
|
public final class CommandsManager {
|
||||||
|
|
||||||
|
private static final boolean DEBUG = false;
|
||||||
private Map<BSBModule, List<Command>> commands = new LinkedHashMap<>();
|
private Map<BSBModule, List<Command>> commands = new LinkedHashMap<>();
|
||||||
|
|
||||||
public void registerCommand(BSBModule module, Command command) {
|
public void registerCommand(BSBModule module, Command command) {
|
||||||
|
if (DEBUG)
|
||||||
|
Bukkit.getLogger().info("DEBUG: registering command for " + module.getIdentifier() + " - " + command.getLabel());
|
||||||
List<Command> cmds = new ArrayList<>();
|
List<Command> cmds = new ArrayList<>();
|
||||||
if (commands.containsKey(module)) {
|
if (commands.containsKey(module)) {
|
||||||
cmds = commands.get(module);
|
cmds = commands.get(module);
|
||||||
@ -22,17 +27,36 @@ public final class CommandsManager {
|
|||||||
|
|
||||||
cmds.add(command);
|
cmds.add(command);
|
||||||
commands.put(module, cmds);
|
commands.put(module, cmds);
|
||||||
BSkyBlock.getInstance().getNMSHandler().getServerCommandMap().register(command.getLabel(), command);
|
// Use reflection to obtain the commandMap method in Bukkit's server. It used to be visible, but isn't anymore.
|
||||||
|
try{
|
||||||
|
Field commandMapField = Bukkit.getServer().getClass().getDeclaredField("commandMap");
|
||||||
|
commandMapField.setAccessible(true);
|
||||||
|
CommandMap commandMap = (CommandMap) commandMapField.get(Bukkit.getServer());
|
||||||
|
commandMap.register(command.getLabel(), command);
|
||||||
|
}
|
||||||
|
catch(Exception exception){
|
||||||
|
Bukkit.getLogger().severe("Bukkit server commandMap method is not there! This means no commands can be registered!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unregisterCommand(Command command) {
|
public void unregisterCommand(Command command) {
|
||||||
|
// TODO - is this ever going to be used?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all of the commands for this
|
||||||
|
* @param module
|
||||||
|
* @return list of commands
|
||||||
|
*/
|
||||||
public List<Command> getCommands(BSBModule module) {
|
public List<Command> getCommands(BSBModule module) {
|
||||||
return commands.get(module);
|
return commands.get(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the command with the label
|
||||||
|
* @param label
|
||||||
|
* @return the command or null if it is not there
|
||||||
|
*/
|
||||||
public Command getCommand(String label) {
|
public Command getCommand(String label) {
|
||||||
for (List<Command> cmds : commands.values()) {
|
for (List<Command> cmds : commands.values()) {
|
||||||
for (Command cmd : cmds) {
|
for (Command cmd : cmds) {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package us.tastybento.bskyblock.util;
|
package us.tastybento.bskyblock.util;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
@ -30,7 +29,6 @@ import us.tastybento.bskyblock.BSkyBlock;
|
|||||||
import us.tastybento.bskyblock.api.commands.User;
|
import us.tastybento.bskyblock.api.commands.User;
|
||||||
import us.tastybento.bskyblock.config.Settings;
|
import us.tastybento.bskyblock.config.Settings;
|
||||||
import us.tastybento.bskyblock.generators.IslandWorld;
|
import us.tastybento.bskyblock.generators.IslandWorld;
|
||||||
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A set of utility methods
|
* A set of utility methods
|
||||||
@ -42,7 +40,6 @@ public class Util {
|
|||||||
private static BSkyBlock plugin = BSkyBlock.getInstance();
|
private static BSkyBlock plugin = BSkyBlock.getInstance();
|
||||||
|
|
||||||
private static String serverVersion = null;
|
private static String serverVersion = null;
|
||||||
private static NMSAbstraction nmsHandler = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the server version
|
* Returns the server version
|
||||||
@ -56,38 +53,6 @@ public class Util {
|
|||||||
return serverVersion;
|
return serverVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks what version the server is running and picks the appropriate NMS handler, or fallback
|
|
||||||
* @return NMSAbstraction class
|
|
||||||
* @throws ClassNotFoundException
|
|
||||||
* @throws IllegalArgumentException
|
|
||||||
* @throws SecurityException
|
|
||||||
* @throws InstantiationException
|
|
||||||
* @throws IllegalAccessException
|
|
||||||
* @throws InvocationTargetException
|
|
||||||
* @throws NoSuchMethodException
|
|
||||||
*/
|
|
||||||
public static NMSAbstraction getNMSHandler() throws ClassNotFoundException, IllegalArgumentException,
|
|
||||||
SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException,
|
|
||||||
NoSuchMethodException {
|
|
||||||
String pluginPackageName = plugin.getClass().getPackage().getName();
|
|
||||||
String version = getServerVersion();
|
|
||||||
Class<?> clazz;
|
|
||||||
try {
|
|
||||||
clazz = Class.forName(pluginPackageName + ".util.nms." + version + ".NMSHandler");
|
|
||||||
} catch (Exception e) {
|
|
||||||
plugin.getLogger().info("No NMS Handler found for " + version + ", falling back to Bukkit API.");
|
|
||||||
clazz = Class.forName(pluginPackageName + ".util.nms.fallback.NMSHandler");
|
|
||||||
}
|
|
||||||
// Check if we have a NMSAbstraction implementing class at that location.
|
|
||||||
if (NMSAbstraction.class.isAssignableFrom(clazz)) {
|
|
||||||
if (nmsHandler == null) nmsHandler = (NMSAbstraction) clazz.getConstructor().newInstance();
|
|
||||||
return nmsHandler;
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("Class " + clazz.getName() + " does not implement NMSAbstraction");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a serialized location to a Location. Returns null if string is
|
* Converts a serialized location to a Location. Returns null if string is
|
||||||
* empty
|
* empty
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
package us.tastybento.bskyblock.util.nms;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandMap;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public interface NMSAbstraction {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send an action bar message to player
|
|
||||||
* @param player
|
|
||||||
* @param message
|
|
||||||
*/
|
|
||||||
void sendActionBar(Player player, String message);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the active {@link org.bukkit.command.CommandMap} of the Server.
|
|
||||||
* It is used by the {@link us.tastybento.bskyblock.api.commands.CompositeCommand} to register itself.
|
|
||||||
* @return the active CommandMap of the server
|
|
||||||
*/
|
|
||||||
CommandMap getServerCommandMap();
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package us.tastybento.bskyblock.util.nms.fallback;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandMap;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
|
|
||||||
|
|
||||||
public class NMSHandler implements NMSAbstraction {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendActionBar(Player player, String message) {
|
|
||||||
//TODO use /title command
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandMap getServerCommandMap() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
package us.tastybento.bskyblock.util.nms.v1_12_R1;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.command.CommandMap;
|
|
||||||
import org.bukkit.craftbukkit.v1_12_R1.CraftServer;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
|
|
||||||
|
|
||||||
public class NMSHandler implements NMSAbstraction {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendActionBar(Player player, String message) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandMap getServerCommandMap() {
|
|
||||||
return ((CraftServer) Bukkit.getServer()).getCommandMap();
|
|
||||||
}
|
|
||||||
}
|
|
@ -25,6 +25,7 @@ import org.junit.BeforeClass;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import us.tastybento.bskyblock.BSkyBlock;
|
||||||
import us.tastybento.bskyblock.api.commands.CompositeCommand;
|
import us.tastybento.bskyblock.api.commands.CompositeCommand;
|
||||||
import us.tastybento.bskyblock.api.commands.User;
|
import us.tastybento.bskyblock.api.commands.User;
|
||||||
import us.tastybento.bskyblock.api.events.IslandBaseEvent;
|
import us.tastybento.bskyblock.api.events.IslandBaseEvent;
|
||||||
@ -36,11 +37,10 @@ public class TestBSkyBlock {
|
|||||||
private final UUID playerUUID = UUID.randomUUID();
|
private final UUID playerUUID = UUID.randomUUID();
|
||||||
private static CommandSender sender;
|
private static CommandSender sender;
|
||||||
private static Player player;
|
private static Player player;
|
||||||
|
private static BSkyBlock plugin;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void setUp() {
|
public static void setUp() {
|
||||||
|
|
||||||
//Plugin plugin = mock(Plugin.class);
|
|
||||||
//Mockito.doReturn(plugin).when(BSkyBlock.getPlugin());
|
//Mockito.doReturn(plugin).when(BSkyBlock.getPlugin());
|
||||||
//Mockito.when().thenReturn(plugin);
|
//Mockito.when().thenReturn(plugin);
|
||||||
World world = mock(World.class);
|
World world = mock(World.class);
|
||||||
@ -58,8 +58,9 @@ public class TestBSkyBlock {
|
|||||||
player = mock(Player.class);
|
player = mock(Player.class);
|
||||||
Mockito.when(player.hasPermission(Settings.PERMPREFIX + "default.permission")).thenReturn(true);
|
Mockito.when(player.hasPermission(Settings.PERMPREFIX + "default.permission")).thenReturn(true);
|
||||||
|
|
||||||
|
plugin = mock(BSkyBlock.class);
|
||||||
|
//Mockito.when(plugin.getServer()).thenReturn(server);
|
||||||
|
|
||||||
//Mockito.doReturn(Logger.getAnonymousLogger()).when(plugin.getLogger());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -140,7 +141,7 @@ public class TestBSkyBlock {
|
|||||||
private class TestCommand extends CompositeCommand {
|
private class TestCommand extends CompositeCommand {
|
||||||
|
|
||||||
public TestCommand() {
|
public TestCommand() {
|
||||||
super("test", "t", "tt");
|
super(plugin, "test", "t", "tt");
|
||||||
this.setParameters("test.params");
|
this.setParameters("test.params");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,7 +244,7 @@ public class TestBSkyBlock {
|
|||||||
private class Test3ArgsCommand extends CompositeCommand {
|
private class Test3ArgsCommand extends CompositeCommand {
|
||||||
|
|
||||||
public Test3ArgsCommand() {
|
public Test3ArgsCommand() {
|
||||||
super("args", "");
|
super(plugin, "args", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user