Skip to content

Instantly share code, notes, and snippets.

@sirsavary
Last active March 31, 2016 20:09
Show Gist options
  • Select an option

  • Save sirsavary/8e803824c20e1b2e2c00fa3c18d8d265 to your computer and use it in GitHub Desktop.

Select an option

Save sirsavary/8e803824c20e1b2e2c00fa3c18d8d265 to your computer and use it in GitHub Desktop.
@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();
}
[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:?]
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");
}
}
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