package com.sijobe.spc.wrapper;
import com.sijobe.spc.command.Command;
import com.sijobe.spc.core.Constants;
import com.sijobe.spc.util.CommandBlockHelper;
import com.sijobe.spc.util.FontColour;
import com.sijobe.spc.util.Settings;
import com.sijobe.spc.util.SettingsManager;
import com.sijobe.spc.validation.Parameters;
import com.sijobe.spc.validation.ValidationException;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.minecraft.src.ChatMessageComponent;
import net.minecraft.src.EntityPlayerMP;
import net.minecraft.src.ICommandSender;
/**
* Provides a base class for all custom commands to extend. All non-abstract
* classes that extend this class should either specify the Command annotation
* or overwrite the getName() method.
*
* TODO: Work out how to handle multiple threads
*
* @author simo_415
* @version 1.3
*/
public abstract class CommandBase extends net.minecraft.src.CommandBase {
/**
* A map containing all settings managers that have been loaded for worlds
*/
private static Map<String, SettingsManager> MANAGER = new HashMap<String, SettingsManager>();
/**
* The Command annotation of the class that contains command attributes.
*/
private final Command annotation;
/**
* Initialises the instance and sets the command annotation (if it exists)
*/
public CommandBase() {
annotation = this.getClass().getAnnotation(Command.class);
}
/**
* @see net.minecraft.src.ICommand#getCommandName()
*/
@Override
public String getCommandName() {
return getName();
}
/**
* Returns the name of the command
*
* @return The name of the command
*/
public String getName() {
if (annotation != null) {
return annotation.name();
}
assert false : "getName() : Command name is null";
return null;
}
/**
* Return whether the specified command parameter index is a username parameter.
*/
@Override
public boolean isUsernameIndex(String[] par1, int par2)
{
if(getName().equals("gamemode")) {
return par2 == 1;
} else if(getName().equals("difficulty")) {
return false;
} else if(getName().equals("help")) {
return false;
} else if(getName().equals("time")) {
return false;
} else if(getName().equals("weather")) {
return false;
} else {
return par2 == 0;
}
}
/**
* @see net.minecraft.src.ICommand#processCommand(net.minecraft.src.ICommandSender, java.lang.String[])
*/
@Override
public void processCommand(final ICommandSender sender, String[] args) {
if(!isEnabled() || CommandBlockHelper.handleCommand(getName(), sender, args)) {
return;
}
CommandSender csender = new CommandSender(sender);
if(sender.getCommandSenderName().equals("@")) {
if(args.length >= 1) {
if(getName().equals("sudo")) {
args[0] = func_82359_c(sender, args[0]).getCommandSenderName();
} else {
String cmd = getCommandName();
for(String part : args) {
cmd += " " + part;
}
cmd = cmd.trim();
System.out.println("SPC/CommandBlock: " + cmd);
EntityPlayerMP player;
try {
player = func_82359_c(sender, args[0]);
} catch (net.minecraft.src.PlayerNotFoundException pnfe) {
System.out.println("SPC/CommandBlock: Warning - " + getCommandName() + " is a player command.");
throw pnfe;
}
csender = new CommandSender(player);
String[] newArgs = new String[args.length - 1];
for(int i = 1; i < args.length; i++) {
newArgs[i-1] = args[i];
}
args = newArgs;
}
} else {
System.err.println("SPC/CommandBlock: Skipping cmd - " + getName());
return;
}
}
try {
List<?> params = getParameters().validate(args);
execute(csender,params);
} catch (ValidationException v) {
if (v.getMessage() == null) {
sendChatMessage(sender, FontColour.RED + "Usage: " + getUsage(csender));
} else {
sendChatMessage(sender, FontColour.RED + "Error: " + v.getMessage());
}
} catch (CommandException e) {
sendChatMessage(sender, FontColour.RED + e.getMessage());
} catch (Exception e) {
e.printStackTrace();
sendChatMessage(sender, FontColour.RED + e.getMessage());
}
}
private void sendChatMessage(ICommandSender sender, String message) {
sender.sendChatToPlayer(ChatMessageComponent.func_111066_d(message));
}
/**
* Runs the current command using the specified parameters and under the
* provided sender. The parameters have already been validated using the
* parameter validators
*
* @param sender - The sender that ran the command
* @param params - The parameters provided with the command
* @throws CommandException - When there is an issue with the command that
* was run
*/
public abstract void execute(CommandSender sender, List<?> params) throws CommandException;
/**
* @see net.minecraft.src.CommandBase#getCommandUsage(net.minecraft.src.ICommandSender)
*/
@Override
public String getCommandUsage(ICommandSender par1ICommandSender) {
return getUsage(new CommandSender(par1ICommandSender));
}
/**
* Returns a String on the correct syntax for the current command
*
* @param sender - The sender that ran the command
* @return The syntax of the command
*/
public String getUsage(CommandSender sender) {
try {
return "/" + getName() + " " + getParameters().getUsage();
} catch (Exception e) {
//return super.getCommandUsage(sender.getMinecraftISender());
return "";
}
}
/**
* @see net.minecraft.src.CommandBase#getCommandAliases()
*/
@Override
public List<String> getCommandAliases() {
return getAliases();
}
/**
* Provides a list of aliases to the current command
*
* @return The list of aliases
*/
public List<String> getAliases() {
if (annotation != null) {
return Arrays.asList(annotation.alias());
}
return null;
}
/**
* @see net.minecraft.src.CommandBase#canCommandSenderUseCommand(net.minecraft.src.ICommandSender)
*/
@Override
public boolean canCommandSenderUseCommand(ICommandSender par1ICommandSender) {
return hasPermission(new CommandSender(par1ICommandSender));
}
/**
* Checks if the current sender that used the command has the necessary
* permission to run the command.
*
* @param sender - The sender that ran the command
* @return True is returned when the sender can run the command
*/
public boolean hasPermission(CommandSender sender) {
return sender.canUseCommand(getName());
}
/**
* @see net.minecraft.src.CommandBase#addTabCompletionOptions(net.minecraft.src.ICommandSender, java.lang.String[])
*/
@Override
public List<String> addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
return getTabCompletionOptions(new CommandSender(par1ICommandSender),par2ArrayOfStr);
}
/**
* Gets a list of available tab completion options based on the current
* sender and the current parameters
*
* @return A list of available tab completion options
*/
public List<String> getTabCompletionOptions(CommandSender sender, String[] param) { // TODO: Use Parameters to get completion options
return null;
}
/**
* Gets the player entity that is associated with the entity that ran the
* command
*
* @param sender - The sender of the command
* @return The associated player object, or null if the sender is not a player
*/
public static Player getSenderAsPlayer(CommandSender sender) {
if (sender.isPlayer()) {
return new Player(getCommandSenderAsPlayer(sender.getMinecraftISender()));
}
return null;
}
/**
* Provides a description of what the command actually does
*
* @return The description of the command
*/
public String getDescription() {
if (annotation != null) {
return annotation.description();
}
return null;
}
/**
* Provides an example of how to use the command
*
* @return The example of the command
*/
public String getExample() {
if (annotation != null) {
return annotation.example();
}
return null;
}
/**
* Provides a video of what the command actually does
*
* @return A video URL showing what the command does
*/
public String getVideoURL() {
if (annotation != null) {
return annotation.videoURL();
}
return null;
}
/**
* Returns a boolean value specifying whether the command is enabled or not.
* A disabled command will not be able to be run by any user, including
* operators.
*
* @return True when the command is enabled, false otherwise
*/
public boolean isEnabled() {
if (annotation != null) {
return annotation.enabled();
}
return true;
}
/**
* Returns the parameters of the command. This is used to validate the input
* parameters before they reach the execute method of the command. This
* provides consistent behaviour with less repetitive coding required.
*
* For no validation and unlimited parameters use Parameters.DEFAULT
*
* @return The parameters that are used in this command
*/
public Parameters getParameters() {
return Parameters.DEFAULT;
}
/**
* Gets the settings for the specified player in the correct world.
*
* @param player - The player to retrieve the settings for
* @return The settings associated with the user
*/
public static Settings loadSettings(Player player) {
if (player == null) {
return null;
}
String directoryName = MinecraftServer.getDirectoryName();
SettingsManager manager = MANAGER.get(directoryName);
if (manager == null) {
File spcPlayers = new File(MinecraftServer.getWorldDirectory(), "spc/players");
if (!spcPlayers.exists()) {
spcPlayers.mkdirs();
}
manager = new SettingsManager(spcPlayers, Constants.DEFAULT_SETTINGS);
MANAGER.put(directoryName, manager);
}
return manager.load(player.getPlayerName());
}
/**
* Saves the settings for the specified player
*
* @param player - The player to save the settings for
* @return True if the settings get saved successfully, false otherwise
*/
public static boolean saveSettings(Player player) {
if (player == null) {
return false;
}
SettingsManager manager = MANAGER.get(MinecraftServer.getDirectoryName());
if (manager != null) {
return manager.save(player.getPlayerName());
}
return false;
}
}