package com.sijobe.spc.hooks;
import com.sijobe.spc.command.MultipleCommands;
import com.sijobe.spc.core.Constants;
import com.sijobe.spc.core.PlayerMP;
import com.sijobe.spc.core.SPCLoader;
import com.sijobe.spc.util.DynamicClassLoader;
import com.sijobe.spc.util.FontColour;
import com.sijobe.spc.worldedit.WorldEditEvents;
import com.sijobe.spc.wrapper.CommandBase;
import com.sijobe.spc.wrapper.CommandManager;
import com.sijobe.spc.wrapper.Player;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
/**
* Initialises SPC by adding the commands to the system. The class is
* dynamically loaded by the HookManager when hooks of type PlayerMP are
* loaded, this is done by the Minecraft class EntityPlayerMP when it is
* first referenced using static invokes.
*
* @author simo_415
* @version 1.0
*/
public class InitialiseCommands extends PlayerMP {
/**
* When Minecraft has properly loaded a welcome message is sent, this value
* says whether the message has been sent or not
*/
public static List<String> WELCOME_FLAG = new ArrayList<String>();
/**
* Tells the class whether the commands have been loaded
*/
private static boolean IS_LOADED = false;
/**
* The welcome message to send
*/
private static final String WELCOME_MESSAGE = FontColour.GREY +
"Single Player Commands (" + Constants.VERSION + ") - " + FontColour.ORANGE + "http://bit.ly/spcmod";
/**
* Pending messages
*/
private static final List<String> pendingMessages = new ArrayList<String>();
public InitialiseCommands() {
loadCommands();
}
@Override
public void onTick(Player player) {
// Send the welcome message
if (IS_LOADED && !WELCOME_FLAG.contains(player.getPlayerName())) {
sendStartupMessage(player);
WELCOME_FLAG.add(player.getPlayerName());
}
if(pendingMessages.size() > 0) {
for(String msg : pendingMessages) {
player.sendChatMessage(msg);
}
pendingMessages.clear();
}
}
/**
* Sends the startup message when the mod has loaded
*/
private void sendStartupMessage(Player player) {
player.sendChatMessage(WELCOME_MESSAGE);
}
/**
* Loads standard and multiple commands into the game. This method is run
* as a thread to keep execution time to a minimum.
*/
private void loadCommands() {
(new Thread() {
@Override
public void run() {
// Load all classes on classpath
SPCLoader.load();
// Load Commands Sets
loadMultipleCommands();
try {
if(com.sijobe.spc.worldedit.WorldEditCommandSet.getCurrentInstance() == null) {
Class.forName("com.sk89q.worldedit.WorldEdit");
System.out.println("SPCommands: Forcing command re-load.");
loadMultipleCommands();
}
} catch (Throwable t) {
WorldEditEvents.disableHandleEvents();
pendingMessages.add("WorldEdit.jar not found in .minecraft/bin - WE unavailable.");
}
// Load Standard Commands
loadStandardCommands();
IS_LOADED = true;
}
}).start();
}
/**
* Loads the standard commands that have been loaded by the JRE
*/
private void loadStandardCommands() {
List<Class<com.sijobe.spc.command.StandardCommand>> commands = DynamicClassLoader.getClasses(com.sijobe.spc.command.StandardCommand.class);
for (Class<com.sijobe.spc.command.StandardCommand> command : commands) {
if (Modifier.isAbstract(command.getModifiers())) {
continue;
}
try {
com.sijobe.spc.command.StandardCommand cmd = command.newInstance();
if (!cmd.isEnabled()) {
continue;
}
if (doesCommandExist(cmd)) { // TODO: review this
System.out.println("Overwriting existing command named: " + cmd.getName());
}
CommandManager.registerCommand(cmd);
} catch (Exception e) {
System.err.println("There was an issue initialising class " +
command.getName() + ". Verify that the class is setup correctly.");
e.printStackTrace();
}
}
}
/**
* Loads the multiple commands that have been loaded by the JRE
*/
private void loadMultipleCommands() {
List<Class<com.sijobe.spc.command.MultipleCommands>> sets = DynamicClassLoader.getClasses(com.sijobe.spc.command.MultipleCommands.class);
for (Class<com.sijobe.spc.command.MultipleCommands> command : sets) {
if (Modifier.isAbstract(command.getModifiers())) {
continue;
}
try {
Constructor<com.sijobe.spc.command.MultipleCommands> constructor = command.getConstructor(String.class);
MultipleCommands instance = constructor.newInstance((String)null);
String commandNames[] = instance.getCommands();
if (commandNames == null) {
continue;
}
for (String name : commandNames) {
com.sijobe.spc.command.MultipleCommands cmd = constructor.newInstance(name);
if (!cmd.isEnabled()) {
continue;
}
if (doesCommandExist(cmd)) {
System.out.println("Overwriting existing command named: " + cmd.getName());
}
CommandManager.registerCommand(cmd);
}
} catch (Throwable e) {
System.err.println("Failed to load " + command.getName());
// e.printStackTrace();
}
}
}
/**
* Checks if the specified command (or alias) name already exist in
* Minecraft. If any of them exist then true is returned, if none of them
* exist then false is returned.
*
* @param command - The command to check
* @return True if command already exists, false otherwise.
*/
public static boolean doesCommandExist(CommandBase command) {
if (CommandManager.doesCommandExist(command.getCommandName())) {
return true;
}
if (command.getAliases() != null) {
for (String alias : command.getAliases()) {
if (CommandManager.doesCommandExist(alias)) {
return true;
}
}
}
return false;
}
}