Last active
March 31, 2016 20:09
-
-
Save sirsavary/8e803824c20e1b2e2c00fa3c18d8d265 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @Mod.EventHandler | |
| @SideOnly(Side.SERVER) | |
| public void serverStart(FMLServerStartingEvent event) | |
| { | |
| if (INSTANCE == null) INSTANCE = this; | |
| if (SERVER == null) SERVER = event.getServer(); | |
| if (COMMAND == null) COMMAND = new WBCommand(); | |
| // Load (or create new) config files | |
| Config.load(false); | |
| // our one real command, though it does also have aliases "wb" and "worldborder" | |
| event.registerServerCommand(COMMAND); | |
| DynMapFeatures.registerListener(); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [16:00:43] [Server thread/ERROR] [FML/]: Caught exception from WorldBorder | |
| java.lang.AbstractMethodError | |
| at net.minecraft.command.CommandHandler.func_71560_a(CommandHandler.java:128) ~[j.class:?] | |
| at net.minecraftforge.fml.common.event.FMLServerStartingEvent.registerServerCommand(FMLServerStartingEvent.java:52) ~[FMLServerStartingEvent.class:?] | |
| at com.wimbli.WorldBorder.WorldBorder.serverStart(WorldBorder.java:69) ~[WorldBorder.class:?] | |
| at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_73] | |
| at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_73] | |
| at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_73] | |
| at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_73] | |
| at net.minecraftforge.fml.common.FMLModContainer.handleModStateEvent(FMLModContainer.java:560) ~[forge-1.8.9-11.15.1.1722-universal.jar:?] | |
| at sun.reflect.GeneratedMethodAccessor11.invoke(Unknown Source) ~[?:?] | |
| at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_73] | |
| at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_73] | |
| at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) ~[minecraft_server.1.8.9.jar:?] | |
| at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) ~[minecraft_server.1.8.9.jar:?] | |
| at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) ~[minecraft_server.1.8.9.jar:?] | |
| at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) ~[minecraft_server.1.8.9.jar:?] | |
| at com.google.common.eventbus.EventBus.post(EventBus.java:275) ~[minecraft_server.1.8.9.jar:?] | |
| at net.minecraftforge.fml.common.LoadController.sendEventToModContainer(LoadController.java:211) ~[forge-1.8.9-11.15.1.1722-universal.jar:?] | |
| at net.minecraftforge.fml.common.LoadController.propogateStateMessage(LoadController.java:189) ~[forge-1.8.9-11.15.1.1722-universal.jar:?] | |
| at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_73] | |
| at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_73] | |
| at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_73] | |
| at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_73] | |
| at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) ~[minecraft_server.1.8.9.jar:?] | |
| at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) ~[minecraft_server.1.8.9.jar:?] | |
| at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) ~[minecraft_server.1.8.9.jar:?] | |
| at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) ~[minecraft_server.1.8.9.jar:?] | |
| at com.google.common.eventbus.EventBus.post(EventBus.java:275) ~[minecraft_server.1.8.9.jar:?] | |
| at net.minecraftforge.fml.common.LoadController.distributeStateMessage(LoadController.java:118) [LoadController.class:?] | |
| at net.minecraftforge.fml.common.Loader.serverStarting(Loader.java:787) [Loader.class:?] | |
| at net.minecraftforge.fml.common.FMLCommonHandler.handleServerStarting(FMLCommonHandler.java:284) [FMLCommonHandler.class:?] | |
| at net.minecraft.server.dedicated.DedicatedServer.func_71197_b(DedicatedServer.java:281) [ko.class:?] | |
| at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:441) [MinecraftServer.class:?] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.wimbli.WorldBorder.cmd; | |
| import com.wimbli.WorldBorder.forge.Util; | |
| import net.minecraft.command.ICommandSender; | |
| import net.minecraft.entity.player.EntityPlayerMP; | |
| import net.minecraft.util.EnumChatFormatting; | |
| import java.util.ArrayList; | |
| import java.util.List; | |
| public abstract class WBCmd | |
| { | |
| /* | |
| * Primary variables, should be set as needed in constructors for the subclassed commands | |
| */ | |
| // command name, command permission; normally the same thing | |
| public String name = ""; | |
| public String permission = null; | |
| // whether command can accept a world name before itself | |
| public boolean hasWorldNameInput = false; | |
| public boolean consoleRequiresWorldName = true; | |
| // minimum and maximum number of accepted parameters | |
| public int minParams = 0; | |
| public int maxParams = 9999; | |
| // help/explanation text to be shown after command example(s) for this command | |
| public String helpText = null; | |
| /* | |
| * The guts of the command run in here; needs to be overriden in the subclassed commands | |
| */ | |
| public abstract void execute(ICommandSender sender, EntityPlayerMP player, List<String> params, String worldName); | |
| /* | |
| * This is an optional override, used to provide some extra command status info, like the currently set value | |
| */ | |
| public void cmdStatus(ICommandSender sender) {} | |
| /* | |
| * Helper variables and methods | |
| */ | |
| // color values for strings | |
| public final static String C_CMD = EnumChatFormatting.AQUA.toString(); // main commands | |
| public final static String C_DESC = EnumChatFormatting.WHITE.toString(); // command descriptions | |
| public final static String C_ERR = EnumChatFormatting.RED.toString(); // errors / notices | |
| public final static String C_HEAD = EnumChatFormatting.YELLOW.toString(); // command listing header | |
| public final static String C_OPT = EnumChatFormatting.DARK_GREEN.toString(); // optional values | |
| public final static String C_REQ = EnumChatFormatting.GREEN.toString(); // required values | |
| // colorized root command, for console and for player | |
| public final static String CMD_C = C_CMD + "wb "; | |
| public final static String CMD_P = C_CMD + "/wb "; | |
| // list of command examples for this command to be displayed as usage reference, separate between players and console | |
| // ... these generally should be set indirectly using addCmdExample() within the constructor for each command class | |
| public List<String> cmdExamplePlayer = new ArrayList<String>(); | |
| public List<String> cmdExampleConsole = new ArrayList<String>(); | |
| // much like the above, but used for displaying command list from root /wb command, listing all commands | |
| public final static List<String> cmdExamplesConsole = new ArrayList<String>(48); // 48 command capacity, 6 full pages | |
| public final static List<String> cmdExamplesPlayer = new ArrayList<String>(48); // still, could need to increase later | |
| // add command examples for use the default "/wb" command list and for internal usage reference, formatted and colorized | |
| public void addCmdExample(String example) | |
| { | |
| addCmdExample(example, true, true, true); | |
| } | |
| public void addCmdExample(String example, boolean forPlayer, boolean forConsole, boolean prefix) | |
| { | |
| // go ahead and colorize required "<>" and optional "[]" parameters, extra command words, and description | |
| example = example.replace("<", C_REQ+"<").replace("[", C_OPT+"[").replace("^", C_CMD).replace("- ", C_DESC+"- "); | |
| // all "{}" are replaced by "[]" (optional) for player, "<>" (required) for console | |
| if (forPlayer) | |
| { | |
| String exampleP = (prefix ? CMD_P : "") + example.replace("{", C_OPT + "[").replace("}", "]"); | |
| cmdExamplePlayer.add(exampleP); | |
| cmdExamplesPlayer.add(exampleP); | |
| } | |
| if (forConsole) | |
| { | |
| String exampleC = (prefix ? CMD_C : "") + example.replace("{", C_REQ + "<").replace("}", ">"); | |
| cmdExampleConsole.add(exampleC); | |
| cmdExamplesConsole.add(exampleC); | |
| } | |
| } | |
| // return root command formatted for player or console, based on sender | |
| public String cmd(ICommandSender sender) | |
| { | |
| return (sender instanceof EntityPlayerMP) ? CMD_P : CMD_C; | |
| } | |
| // formatted and colorized text, intended for marking command name | |
| public String commandEmphasized(String text) | |
| { | |
| return C_CMD + EnumChatFormatting.UNDERLINE + text + EnumChatFormatting.RESET + " "; | |
| } | |
| // returns green "enabled" or red "disabled" text | |
| public String enabledColored(boolean enabled) | |
| { | |
| return enabled ? C_REQ+"enabled" : C_ERR+"disabled"; | |
| } | |
| // formatted and colorized command name, optionally prefixed with "[world]" (for player) / "<world>" (for console) | |
| public String nameEmphasized() | |
| { | |
| return commandEmphasized(name); | |
| } | |
| public String nameEmphasizedW() | |
| { | |
| return "{world} " + nameEmphasized(); | |
| } | |
| // send command example message(s) and other helpful info | |
| public void sendCmdHelp(ICommandSender sender) | |
| { | |
| for (String example : ((sender instanceof EntityPlayerMP) ? cmdExamplePlayer : cmdExampleConsole)) | |
| { | |
| Util.chat(sender, example); | |
| } | |
| cmdStatus(sender); | |
| if (helpText != null && !helpText.isEmpty()) | |
| Util.chat(sender, C_DESC + helpText); | |
| } | |
| // send error message followed by command example message(s) | |
| public void sendErrorAndHelp(ICommandSender sender, String error) | |
| { | |
| Util.chat(sender, C_ERR + error); | |
| sendCmdHelp(sender); | |
| } | |
| // interpret string as boolean value (yes/no, true/false, on/off, +/-, 1/0) | |
| public boolean strAsBool(String str) | |
| { | |
| str = str.toLowerCase(); | |
| return str.startsWith("y") || str.startsWith("t") || str.startsWith("on") || str.startsWith("+") || str.startsWith("1"); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.wimbli.WorldBorder; | |
| import com.google.common.collect.Lists; | |
| import com.mojang.authlib.GameProfile; | |
| import com.wimbli.WorldBorder.cmd.*; | |
| import com.wimbli.WorldBorder.forge.Log; | |
| import com.wimbli.WorldBorder.forge.Util; | |
| import net.minecraft.command.CommandBase; | |
| import net.minecraft.command.ICommand; | |
| import net.minecraft.command.ICommandSender; | |
| import net.minecraft.entity.player.EntityPlayerMP; | |
| import net.minecraft.server.MinecraftServer; | |
| import net.minecraft.server.dedicated.DedicatedServer; | |
| import net.minecraft.server.management.UserListOps; | |
| import net.minecraft.server.management.UserListOpsEntry; | |
| import net.minecraft.util.BlockPos; | |
| import javax.annotation.Nonnull; | |
| import java.util.*; | |
| public class WBCommand implements ICommand | |
| { | |
| static final String NAME = "wborder"; | |
| static final List ALIASES = Arrays.asList(NAME, "wb", "worldborder"); | |
| // map of all sub-commands with the command name (string) for quick reference | |
| public Map<String, WBCmd> subCommands = new LinkedHashMap<>(); | |
| // ref. list of the commands which can have a world name in front of the command itself (ex. /wb _world_ radius 100) | |
| private Set<String> subCommandsWithWorldNames = new LinkedHashSet<>(); | |
| private ArrayList<String> subCommandNames = null; | |
| /** | |
| * Checks the server's registered commands in case any other commands override | |
| * WorldBorder's. Will print errors to the log if conflicts found. | |
| */ | |
| public static void checkRegistrations(MinecraftServer server) | |
| { | |
| List<String> valid = new ArrayList<>( ALIASES.size() ); | |
| List<String> conflict = new ArrayList<>( ALIASES.size() ); | |
| Map commands = server.getCommandManager().getCommands(); | |
| for (Object o : ALIASES) | |
| { | |
| String name = (String) o; | |
| Object value = commands.get(name); | |
| if (value == null) | |
| Log.error("Null handler for '/%s'! Please report this", name); | |
| else if (value instanceof WBCommand) | |
| valid.add("/" + name); | |
| else | |
| conflict.add( | |
| String.format( "/%s (from %s)", name, value.getClass().getName() ) | |
| ); | |
| } | |
| if (valid.size() == 0) | |
| { | |
| Log.error("All WorldBorder commands are being handled elsewhere:"); | |
| for (String c : conflict) Log.error("* %s", c); | |
| Log.error("It may be that another mod is attempting to provide world " + | |
| "border functionality. Consider removing or disabling that mod to " + | |
| "allow WorldBorder-Forge to work properly."); | |
| } | |
| else if (conflict.size() > 0) | |
| { | |
| Log.warn("The following WorldBorder commands are being handled elsewhere:"); | |
| for (String c : conflict) Log.warn("* %s", c); | |
| Log.warn("It may be that another mod is attempting to provide world " + | |
| "border functionality. Consider removing or disabling that mod to " + | |
| "allow WorldBorder-Forge to work. Alternatively, try these commands:"); | |
| for (String v : valid) Log.warn("* %s", v); | |
| } | |
| } | |
| // constructor | |
| public WBCommand () | |
| { | |
| addCmd(new CmdHelp()); // 1 example | |
| addCmd(new CmdSet()); // 4 examples for player, 3 for console | |
| addCmd(new CmdRadius()); // 1 | |
| addCmd(new CmdList()); // 1 | |
| //----- 8 per page of examples | |
| addCmd(new CmdShape()); // 2 | |
| addCmd(new CmdClear()); // 2 | |
| addCmd(new CmdFill()); // 1 | |
| addCmd(new CmdTrim()); // 1 | |
| //----- | |
| addCmd(new CmdWshape()); // 3 | |
| //----- | |
| addCmd(new CmdDynmap()); // 1 | |
| addCmd(new CmdDynmapmsg()); // 1 | |
| addCmd(new CmdFillautosave()); // 1 | |
| //----- | |
| addCmd(new CmdReload()); // 1 | |
| // this is the default command, which shows command example pages; should be last just in case | |
| addCmd(new CmdCommands()); | |
| } | |
| private void addCmd(WBCmd cmd) | |
| { | |
| subCommands.put(cmd.name, cmd); | |
| if (cmd.hasWorldNameInput) | |
| subCommandsWithWorldNames.add(cmd.name); | |
| } | |
| @Override | |
| public void processCommand(ICommandSender sender, String[] split) | |
| { | |
| EntityPlayerMP player = sender instanceof EntityPlayerMP | |
| ? (EntityPlayerMP) sender | |
| : null; | |
| ArrayList<String> params = Lists.newArrayList(split); | |
| String worldName = null; | |
| // is second parameter the command and first parameter a world name? | |
| if (params.size() > 1 && !subCommands.containsKey(params.get(0)) && subCommandsWithWorldNames.contains(params.get(1))) | |
| worldName = params.get(0); | |
| // no command specified? show command examples / help | |
| if (params.isEmpty()) | |
| params.add(0, "commands"); | |
| // determined the command name | |
| String cmdName = (worldName == null) ? params.get(0).toLowerCase() : params.get(1).toLowerCase(); | |
| // remove command name and (if there) world name from front of param array | |
| params.remove(0); | |
| if (worldName != null) | |
| params.remove(0); | |
| // make sure command is recognized, default to showing command examples / help if not; also check for specified page number | |
| if (!subCommands.containsKey(cmdName)) | |
| { | |
| int page = (player == null) ? 0 : 1; | |
| try | |
| { | |
| page = Integer.parseInt(cmdName); | |
| } | |
| catch(NumberFormatException ignored) | |
| { | |
| Util.chat(sender, WBCmd.C_ERR + "Command not recognized. Showing command list."); | |
| } | |
| cmdName = "commands"; | |
| params.add(0, Integer.toString(page)); | |
| } | |
| WBCmd subCommand = subCommands.get(cmdName); | |
| // if command requires world name when run by console, make sure that's in place | |
| if (player == null && subCommand.hasWorldNameInput && subCommand.consoleRequiresWorldName && worldName == null) | |
| { | |
| Util.chat(sender, WBCmd.C_ERR + "This command requires a world to be specified if run by the console."); | |
| subCommand.sendCmdHelp(sender); | |
| return; | |
| } | |
| // make sure valid number of parameters has been provided | |
| if (params.size() < subCommand.minParams || params.size() > subCommand.maxParams) | |
| { | |
| if (subCommand.maxParams == 0) | |
| Util.chat(sender, WBCmd.C_ERR + "This command does not accept any parameters."); | |
| else | |
| Util.chat(sender, WBCmd.C_ERR + "You have not provided a valid number of parameters."); | |
| subCommand.sendCmdHelp(sender); | |
| return; | |
| } | |
| // execute command | |
| subCommand.execute(sender, player, params, worldName); | |
| } | |
| public ArrayList<String> getCommandNames() | |
| { | |
| if (subCommandNames != null) | |
| return subCommandNames; | |
| subCommandNames = new ArrayList<>( subCommands.keySet() ); | |
| // Remove "commands" as it's not normally shown or run like other commands | |
| subCommandNames.remove("commands"); | |
| Collections.sort(subCommandNames); | |
| return subCommandNames; | |
| } | |
| @Override | |
| public String getCommandName() | |
| { | |
| return NAME; | |
| } | |
| @Override | |
| public String getCommandUsage(ICommandSender sender) | |
| { | |
| return "/wborder help [n]"; | |
| } | |
| @Override | |
| public List getCommandAliases() | |
| { | |
| return ALIASES; | |
| } | |
| @Override | |
| public boolean isUsernameIndex(String[] args, int idx) | |
| { | |
| return false; | |
| } | |
| @Override | |
| public boolean canCommandSenderUseCommand(ICommandSender sender) | |
| { | |
| if (sender instanceof DedicatedServer) | |
| return true; | |
| EntityPlayerMP player = (EntityPlayerMP) sender; | |
| GameProfile profile = player.getGameProfile(); | |
| UserListOps oppedPlayers = WorldBorder.SERVER | |
| .getConfigurationManager() | |
| .getOppedPlayers(); | |
| // Level 2 (out of 4) have general access to game-changing commands | |
| // TODO: Make this a configuration option | |
| return oppedPlayers.func_183026_b(profile); | |
| } | |
| @Override | |
| public List<String> addTabCompletionOptions(ICommandSender iCommandSender, String[] args, BlockPos blockPos) { | |
| if (args.length <= 1) | |
| return CommandBase.getListOfStringsMatchingLastWord(args, getCommandNames()); | |
| String[] players = WorldBorder.SERVER.getAllUsernames(); | |
| return CommandBase.getListOfStringsMatchingLastWord(args, players); | |
| } | |
| @Override | |
| public int compareTo(ICommand o) { | |
| ICommand command = (ICommand) o; | |
| return command.getCommandName().compareTo( getCommandName() ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment