diff --git a/src/main/java/kamkeel/CmdClone.java b/src/main/java/kamkeel/CmdClone.java new file mode 100644 index 000000000..028aee2ca --- /dev/null +++ b/src/main/java/kamkeel/CmdClone.java @@ -0,0 +1,309 @@ +package kamkeel; + +import java.util.List; + +import foxz.utils.Utils; +import net.minecraft.block.Block; +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.command.NumberInvalidException; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityList; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import noppes.npcs.controllers.ServerCloneController; +import noppes.npcs.entity.EntityNPCInterface; + +public class CmdClone extends CommandKamkeelBase { + + @Override + public String getCommandName() { + return "clone"; + } + + @Override + public String getDescription() { + return "Clone operation (server side)"; + } + + @SubCommand( + desc = "Add NPC(s) to clone storage", + usage = " [clonedname]", + permission = 4 + ) + public void add(ICommandSender sender, String[] args) { + int tab = 0; + try{ + tab = Integer.parseInt(args[1]); + } + catch(NumberFormatException ex){ + + } + + int x = sender.getPlayerCoordinates().posX; + int y = sender.getPlayerCoordinates().posY; + int z = sender.getPlayerCoordinates().posZ; + List list = getEntities(EntityNPCInterface.class, sender.getEntityWorld(), x, y, z, 80); + for (EntityNPCInterface npc : list) { + if (npc.display.getName().equalsIgnoreCase(args[0])) { + String name = npc.display.getName(); + if (args.length > 2) { + name = args[2]; + } + NBTTagCompound compound = new NBTTagCompound(); + if(!npc.writeToNBTOptional(compound)) + return; + ServerCloneController.Instance.addClone(compound, name, tab); + } + } + } + + @SubCommand( + desc = "List NPC from clone storage", + usage = "", + permission = 2 + ) + public void list(ICommandSender sender, String[] args) { + sendMessage(sender, "--- Stored NPCs --- (server side)"); + int tab = 0; + try{ + tab = Integer.parseInt(args[0]); + } + catch(NumberFormatException ex){ + + } + for (String name : ServerCloneController.Instance.getClones(tab)) { + sendMessage(sender, name); + } + sendMessage(sender, "------------------------------------"); + } + + @SubCommand( + desc = "Remove NPC from clone storage", + usage = " ", + permission = 4 + ) + public void del(ICommandSender sender, String[] args) throws CommandException { + String nametodel = args[0]; + int tab = 0; + try{ + tab = Integer.parseInt(args[1]); + } + catch(NumberFormatException ex){ + + } + boolean deleted = false; + for(String name : ServerCloneController.Instance.getClones(tab)){ + if(nametodel.equalsIgnoreCase(name)){ + ServerCloneController.Instance.removeClone(name, tab); + deleted = true; + break; + } + } + if (!ServerCloneController.Instance.removeClone(nametodel, tab)) { + throw new CommandException(String.format("Npc '%s' wasn't found", nametodel)); + } + } + + @SubCommand( + desc = "Spawn cloned NPC", + usage = " [[world:]x,y,z]] [newname]", + permission = 2 + ) + public void spawn(ICommandSender sender, String[] args) throws CommandException { + String name = args[0].replaceAll("%", " "); // if name of npc separed by space, user must use % in place of space + int tab = 0; + try{ + tab = Integer.parseInt(args[1]); + } + catch(NumberFormatException ex){ + + } + String newname=null; + NBTTagCompound compound = ServerCloneController.Instance.getCloneData(sender, name, tab); + if(compound == null){ + sendMessage(sender, "Unknown npc"); + return; + } + World world = sender.getEntityWorld(); + double posX = sender.getPlayerCoordinates().posX; + double posY = sender.getPlayerCoordinates().posY; + double posZ = sender.getPlayerCoordinates().posZ; + + if(args.length > 2){ + String location = args[2]; + String[] par; + if (location.contains(":")){ + par = location.split(":"); + location = par[1]; + world = Utils.getWorld(par[0]); + if (world == null){ + throw new CommandException(String.format("'%s' is an unknown world", par[0])); + } + } + + if (location.contains(",")){ + par = location.split(","); + if (par.length != 3){ + sendMessage(sender, "Location need be x,y,z"); + return; + } + try{ + posX = CommandBase.func_110666_a(sender, posX, par[0]); + posY = CommandBase.func_110665_a(sender, posY, par[1].trim(), 0, 0); + posZ = CommandBase.func_110666_a(sender, posZ, par[2]); + } catch(NumberFormatException ex){ + sendMessage(sender, "Location should be in numbers"); + return; + } + if (args.length > 3){ + newname = args[3]; + } + } else { + newname = location; + } + } + + if (posX == 0 && posY == 0 && posZ == 0){//incase it was called from the console and not pos was given + sendMessage(sender, "Location needed"); + return; + } + + Entity entity = EntityList.createEntityFromNBT(compound, world); + entity.setPosition(posX + 0.5, posY + 1, posZ + 0.5); + if(entity instanceof EntityNPCInterface){ + EntityNPCInterface npc = (EntityNPCInterface) entity; + npc.ai.startPos = new int[]{MathHelper.floor_double(posX), MathHelper.floor_double(posY), MathHelper.floor_double(posZ)}; + if(newname != null && !newname.isEmpty()) + npc.display.name = newname.replaceAll("%", " "); // like name, newname must use % in place of space to keep a logical way + } + world.spawnEntityInWorld(entity); + } + + @SubCommand( + desc = "Spawn cloned NPC", + usage = " [[world:]x,y,z]] [newname]", + permission = 2 + ) + public void grid(ICommandSender sender, String[] args) throws CommandException { + String name = args[0].replaceAll("%", " "); // if name of npc separed by space, user must use % in place of space + int tab = 0; + try{ + tab = Integer.parseInt(args[1]); + } + catch(NumberFormatException ex){ + + } + + int width, height; + try{ + width = Integer.parseInt(args[2]); + height = Integer.parseInt(args[3]); + } + catch(NumberFormatException ex){ + sendMessage(sender, "length or width was not a number"); + return; + } + + + String newname=null; + NBTTagCompound compound = ServerCloneController.Instance.getCloneData(sender, name, tab); + if(compound == null){ + sendMessage(sender, "Unknown npc"); + return; + } + World world = sender.getEntityWorld(); + double posX = sender.getPlayerCoordinates().posX; + double posY = sender.getPlayerCoordinates().posY; + double posZ = sender.getPlayerCoordinates().posZ; + + if(args.length > 4){ + String location = args[4]; + String[] par; + if (location.contains(":")){ + par = location.split(":"); + location = par[1]; + world = Utils.getWorld(par[0]); + if (world == null){ + throw new CommandException(String.format("'%s' is an unknown world", par[0])); + } + } + + if (location.contains(",")){ + par = location.split(","); + if (par.length != 3){ + sendMessage(sender, "Location need be x,y,z"); + return; + } + try{ + posX = CommandBase.func_110666_a(sender, posX, par[0]); + posY = CommandBase.func_110665_a(sender, posY, par[1].trim(), 0, 0); + posZ = CommandBase.func_110666_a(sender, posZ, par[2]); + } catch(NumberFormatException ex){ + sendMessage(sender, "Location should be in numbers"); + return; + } + if (args.length > 5){ + newname = args[5]; + } + } else { + newname = location; + } + } + + if (posX == 0 && posY == 0 && posZ == 0){//incase it was called from the console and not pos was given + sendMessage(sender, "Location needed"); + return; + } + + for(int x = 0; x < width; x++){ + for(int z = 0; z < height; z++){ + Entity entity = EntityList.createEntityFromNBT(compound, world); + int xx = MathHelper.floor_double(posX) + x; + int yy = Math.max(MathHelper.floor_double(posY) - 2, 1); + int zz = MathHelper.floor_double(posZ) + z; + + for(int y = 0; y < 10; y++){ + Block b = world.getBlock(xx, yy + y, zz); + Block b2 = world.getBlock(xx, yy + y + 1, zz); + if(b != null && (b2 == null || b2.getCollisionBoundingBoxFromPool(world, xx, yy + y + 1, zz) == null)){ + yy += y; + break; + } + } + entity.setPosition(posX + 0.5 + x, yy + 1, posZ + 0.5 + z); + if(entity instanceof EntityNPCInterface){ + EntityNPCInterface npc = (EntityNPCInterface) entity; + npc.ai.startPos = new int[]{xx, yy, zz}; + if(newname != null && !newname.isEmpty()) + npc.display.name = newname.replaceAll("%", " "); // like name, newname must use % in place of space to keep a logical way + } + world.spawnEntityInWorld(entity); + } + } + return; + } + + public World getWorld(String t){ + WorldServer[] ws=MinecraftServer.getServer().worldServers; + for (WorldServer w:ws){ + if (w!=null){ + if ((w.provider.dimensionId + "").equalsIgnoreCase(t)){ + return w; + } + } + } + return null; + } + + public List getEntities(Class cls, World world, int x, int y, int z, int range) { + AxisAlignedBB bb = AxisAlignedBB.getBoundingBox(x, y, z, x + 1, y + 1, z + 1).expand(range, range, range); + List list = world.getEntitiesWithinAABB(cls, bb); + return list; + } +} diff --git a/src/main/java/kamkeel/CmdConfig.java b/src/main/java/kamkeel/CmdConfig.java new file mode 100644 index 000000000..44651bf46 --- /dev/null +++ b/src/main/java/kamkeel/CmdConfig.java @@ -0,0 +1,201 @@ +package kamkeel; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockIce; +import net.minecraft.block.BlockLeavesBase; +import net.minecraft.block.BlockVine; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.ResourceLocation; +import noppes.npcs.CustomNpcs; +import noppes.npcs.Server; +import noppes.npcs.config.ConfigMain; +import noppes.npcs.constants.EnumPacketClient; +import noppes.npcs.controllers.ChunkController; + +import java.util.Arrays; +import java.util.Set; + +public class CmdConfig extends CommandKamkeelBase { + + + @Override + public String getCommandName() { + return "config"; + } + + @Override + public String getDescription() { + return "Some config things you can set"; + } + + @SubCommand( + desc = "Disable/Enable the natural leaves decay", + usage = "[true/false]", + permission = 4 + ) + public void leavesdecay(ICommandSender sender, String[] args){ + if(args.length == 0){ + sendMessage(sender, "LeavesDecay: " + ConfigMain.LeavesDecayEnabled); + } + else{ + ConfigMain.LeavesDecayEnabled = Boolean.parseBoolean(args[0]); + ConfigMain.LeavesDecayEnabledProperty.set(ConfigMain.LeavesDecayEnabled); + if(ConfigMain.config.hasChanged()){ + ConfigMain.config.save(); + } + Set names = Block.blockRegistry.getKeys(); + for(ResourceLocation name : names){ + Block block = (Block) Block.blockRegistry.getObject(name); + if(block instanceof BlockLeavesBase){ + block.setTickRandomly(ConfigMain.LeavesDecayEnabled); + } + } + sendMessage(sender, "LeavesDecay is now " + ConfigMain.LeavesDecayEnabled); + } + } + + @SubCommand( + desc = "Disable/Enable the vines growing", + usage = "[true/false]", + permission = 4 + ) + public void vinegrowth(ICommandSender sender, String[] args){ + if(args.length == 0){ + sendMessage(sender, "VineGrowth: " + ConfigMain.VineGrowthEnabled); + } + else{ + ConfigMain.VineGrowthEnabled = Boolean.parseBoolean(args[0]); + ConfigMain.VineGrowthEnabledProperty.set(ConfigMain.VineGrowthEnabled); + if(ConfigMain.config.hasChanged()){ + ConfigMain.config.save(); + } + Set names = Block.blockRegistry.getKeys(); + for(ResourceLocation name : names){ + Block block = (Block) Block.blockRegistry.getObject(name); + if(block instanceof BlockVine){ + block.setTickRandomly(ConfigMain.VineGrowthEnabled); + } + } + sendMessage(sender, "VineGrowth is now " + ConfigMain.VineGrowthEnabled); + } + } + + @SubCommand( + desc = "Disable/Enable the ice melting", + usage = "[true/false]", + permission = 4 + ) + public void icemelts(ICommandSender sender, String[] args){ + if(args.length == 0){ + sendMessage(sender, "IceMelts: " + ConfigMain.IceMeltsEnabled); + } + else{ + ConfigMain.IceMeltsEnabled = Boolean.parseBoolean(args[0]); + ConfigMain.IceMeltsEnabledProperty.set(ConfigMain.IceMeltsEnabled); + if(ConfigMain.config.hasChanged()){ + ConfigMain.config.save(); + } + Set names = Block.blockRegistry.getKeys(); + for(ResourceLocation name : names){ + Block block = (Block) Block.blockRegistry.getObject(name); + if(block instanceof BlockIce){ + block.setTickRandomly(ConfigMain.IceMeltsEnabled); + } + } + sendMessage(sender, "IceMelts is now " + ConfigMain.IceMeltsEnabled); + } + } + + @SubCommand( + desc = "Disable/Enable guns shooting", + usage = "[true/false]", + permission = 4 + ) + public void guns(ICommandSender sender, String[] args){ + if(args.length == 0){ + sendMessage(sender, "GunsEnabled: " + ConfigMain.GunsEnabled); + } + else{ + ConfigMain.GunsEnabled = Boolean.parseBoolean(args[0]); + ConfigMain.GunsEnabledProperty.set(ConfigMain.GunsEnabled); + if(ConfigMain.config.hasChanged()){ + ConfigMain.config.save(); + } + sendMessage(sender, "GunsEnabled is now " + ConfigMain.GunsEnabled); + } + } + + @SubCommand( + desc = "Freezes/Unfreezes npcs", + usage = "[true/false]", + permission = 4 + ) + public void freezenpcs(ICommandSender sender, String[] args){ + if(args.length == 0){ + sendMessage(sender, "Frozen NPCs: " + CustomNpcs.FreezeNPCs); + } + else{ + CustomNpcs.FreezeNPCs = Boolean.parseBoolean(args[0]); + sendMessage(sender, "FrozenNPCs is now " + CustomNpcs.FreezeNPCs); + } + } + + @SubCommand( + desc = "Set how many active chunkloaders you can have", + usage = "", + permission = 4 + ) + public void chunkloaders(ICommandSender sender, String[] args) throws CommandException{ + if(args.length == 0){ + sendMessage(sender, "ChunkLoaders: " + ChunkController.instance.size() + "/" + ConfigMain.ChunkLoaders); + } + else{ + try{ + ConfigMain.ChunkLoaders = Integer.parseInt(args[0]); + } + catch(NumberFormatException ex){ + throw new CommandException("Did not get a number: " + args[0]); + } + ConfigMain.ChunkLoadersProperty.set(ConfigMain.ChunkLoaders); + if(ConfigMain.config.hasChanged()){ + ConfigMain.config.save(); + } + + int size = ChunkController.instance.size(); + if(size > ConfigMain.ChunkLoaders){ + ChunkController.instance.unload(size - ConfigMain.ChunkLoaders); + sendMessage(sender, size - ConfigMain.ChunkLoaders + " chunksloaders unloaded"); + } + sendMessage(sender, "ChunkLoaders: " + ChunkController.instance.size() + "/" + ConfigMain.ChunkLoaders); + } + } + + @SubCommand( + desc = "Get/Set font", + usage = "[type] [size]", + permission = 4 + ) + public void font(ICommandSender sender, String[] args){ + if(!(sender instanceof EntityPlayerMP)) + return; + int size = 18; + if(args.length > 1){ + try{ + size = Integer.parseInt(args[args.length - 1]); + args = Arrays.copyOfRange(args, 0, args.length - 1); + } + catch(Exception e){ + + } + } + String font = ""; + for(int i = 0; i < args.length; i++){ + font += " " + args[i]; + } + Server.sendData((EntityPlayerMP)sender, EnumPacketClient.CONFIG, 0, font.trim(), size); + } + +} + diff --git a/src/main/java/kamkeel/CmdDialog.java b/src/main/java/kamkeel/CmdDialog.java new file mode 100644 index 000000000..257653c11 --- /dev/null +++ b/src/main/java/kamkeel/CmdDialog.java @@ -0,0 +1,112 @@ +package kamkeel; + +import java.util.List; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayer; +import noppes.npcs.NoppesUtilServer; +import noppes.npcs.client.EntityUtil; +import noppes.npcs.controllers.DialogController; + +import noppes.npcs.controllers.PlayerDataController; +import noppes.npcs.controllers.data.Dialog; +import noppes.npcs.controllers.data.DialogOption; +import noppes.npcs.controllers.data.PlayerData; +import noppes.npcs.entity.EntityDialogNpc; + +public class CmdDialog extends CommandKamkeelBase { + + @Override + public String getCommandName() { + return "dialog"; + } + + @Override + public String getDescription() { + return "Dialog operations"; + } + + @SubCommand( + desc = "force read", + usage = " " + ) + public void read(ICommandSender sender, String args[]) throws CommandException{ + String playername=args[0]; + int diagid; + try { + diagid = Integer.parseInt(args[1]); + } catch (NumberFormatException ex) { + throw new CommandException("DialogID must be an integer: " + args[1]); + } + List data = PlayerDataController.instance.getPlayersData(sender, playername); + if (data.isEmpty()) { + throw new CommandException("Unknown player: " + playername); + } + for(PlayerData playerdata : data){ + playerdata.dialogData.dialogsRead.add(diagid); + playerdata.saveNBTData(null); + } + } + + @SubCommand( + desc = "force unread dialog", + usage = " " + ) + public void unread(ICommandSender sender, String args[]) throws CommandException{ + String playername=args[0]; + int diagid; + try { + diagid = Integer.parseInt(args[1]); + } catch (NumberFormatException ex) { + throw new CommandException("DialogID must be an integer: " + args[1]); + } + List data = PlayerDataController.instance.getPlayersData(sender, playername); + if (data.isEmpty()) { + throw new CommandException("Unknown player: " + playername); + } + for(PlayerData playerdata : data){ + playerdata.dialogData.dialogsRead.remove(diagid); + playerdata.saveNBTData(null); + } + } + @SubCommand( + desc="reload dialogs from disk", + permission = 4 + ) + public void reload(ICommandSender sender, String args[]){ + new DialogController(); + } + + @SubCommand( + desc="show dialog", + usage=" " + ) + public void show(ICommandSender sender, String args[]) throws CommandException{ + EntityPlayer player = CommandBase.getPlayer(sender, args[0]); + if(player == null){ + throw new CommandException("Unknown player: " + args[0]); + } + + int diagid; + try { + diagid = Integer.parseInt(args[1]); + } catch (NumberFormatException ex) { + throw new CommandException("DialogID must be an integer: " + args[1]); + } + Dialog dialog = DialogController.instance.dialogs.get(diagid); + if(dialog == null){ + throw new CommandException("Unknown dialog id: " + args[1]); + } + + EntityDialogNpc npc = new EntityDialogNpc(sender.getEntityWorld()); + npc.display.setName(args[2]); + EntityUtil.Copy(player, npc); + DialogOption option = new DialogOption(); + option.dialogId = diagid; + option.title = dialog.title; + npc.dialogs.put(0, option); + NoppesUtilServer.openDialog(player, npc, dialog, 0); + } +} diff --git a/src/main/java/kamkeel/CmdFaction.java b/src/main/java/kamkeel/CmdFaction.java new file mode 100644 index 000000000..89df8f0bc --- /dev/null +++ b/src/main/java/kamkeel/CmdFaction.java @@ -0,0 +1,144 @@ +package kamkeel; + +import java.util.Arrays; +import java.util.List; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import noppes.npcs.controllers.FactionController; +import noppes.npcs.controllers.PlayerDataController; +import noppes.npcs.controllers.data.Faction; +import noppes.npcs.controllers.data.PlayerData; +import noppes.npcs.controllers.data.PlayerFactionData; + +public class CmdFaction extends CommandKamkeelBase { + + public Faction selectedFaction; + public List data; + + + @Override + public String getCommandName() { + return "faction"; + } + + @Override + public String getDescription() { + return "Faction operations"; + } + + @Override + public String getUsage() { + return " "; + } + + @Override + public boolean runSubCommands(){ + return false; + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + String playername = args[0]; + String factionname = args[1]; + + data = PlayerDataController.instance.getPlayersData(sender, playername); + if (data.isEmpty()) { + throw new CommandException("Unknown player: " + playername); + } + + try{ + selectedFaction = FactionController.getInstance().getFaction(Integer.parseInt(factionname)); + } + catch(NumberFormatException e){ + selectedFaction = FactionController.getInstance().getFactionFromName(factionname); + } + + if (selectedFaction == null) { + throw new CommandException("Unknown faction: " + factionname); + } + + processSubCommand(sender, args[2], Arrays.copyOfRange(args, 3, args.length)); + + for(PlayerData playerdata : data){ + playerdata.saveNBTData(null); + } + } + + @SubCommand( + desc = "Add points", + usage = "" + ) + public void add(ICommandSender sender, String[] args) throws CommandException { + int points; + try { + points = Integer.parseInt(args[0]); + } catch (NumberFormatException ex) { + throw new CommandException("Must be an integer: " + args[0]); + } + int factionid = this.selectedFaction.id; + + for(PlayerData playerdata : data){ + PlayerFactionData playerfactiondata = playerdata.factionData; + playerfactiondata.increasePoints(factionid, points, playerdata.player); + } + } + + @SubCommand( + desc = "Substract points", + usage = "" + ) + public void subtract(ICommandSender sender, String[] args) throws CommandException { + int points; + try { + points = Integer.parseInt(args[0]); + } catch (NumberFormatException ex) { + throw new CommandException("Must be an integer: " + args[0]); + } + int factionid = this.selectedFaction.id; + for(PlayerData playerdata : data){ + PlayerFactionData playerfactiondata = playerdata.factionData; + playerfactiondata.increasePoints(factionid, -points, playerdata.player); + } + } + + @SubCommand(desc = "Reset points to default") + public void reset(ICommandSender sender, String[] args) { + for(PlayerData playerdata : data){ + playerdata.factionData.factionData.put(this.selectedFaction.id, this.selectedFaction.defaultPoints); + } + } + + @SubCommand( + desc = "Set points", + usage = "" + ) + public void set(ICommandSender sender, String[] args) throws CommandException { + int points; + try { + points = Integer.parseInt(args[0]); + } catch (NumberFormatException ex) { + throw new CommandException("Must be an integer: " + args[0]); + } + for(PlayerData playerdata : data){ + PlayerFactionData playerfactiondata = playerdata.factionData; + playerfactiondata.factionData.put(this.selectedFaction.id,points); + } + } + + @SubCommand(desc = "Drop relationship") + public void drop(ICommandSender sender, String[] args){ + for(PlayerData playerdata : data){ + playerdata.factionData.factionData.remove(this.selectedFaction.id); + } + } + + @Override + public List addTabCompletionOptions(ICommandSender par1, String[] args) { + if(args.length == 3){ + return CommandBase.getListOfStringsMatchingLastWord(args, new String[]{"add", "subtract", "set", "reset", "drop", "create"}); + } + return null; + } +} diff --git a/src/main/java/kamkeel/CmdHelp.java b/src/main/java/kamkeel/CmdHelp.java new file mode 100644 index 000000000..566d27574 --- /dev/null +++ b/src/main/java/kamkeel/CmdHelp.java @@ -0,0 +1,66 @@ +package kamkeel; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Map.Entry; + +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentTranslation; + +public class CmdHelp extends CommandKamkeelBase{ + private CommandKamkeel parent; + + public CmdHelp(CommandKamkeel parent){ + this.parent = parent; + } + + @Override + public String getCommandName() { + return "help"; + } + + @Override + public String getDescription() { + return "help [command]"; + } + + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if(args.length == 0){ + sendMessage(sender, "------Kamkeel Commands------"); + for(Entry entry : parent.map.entrySet()){ + sendMessage(sender, entry.getKey() + ": " + entry.getValue().getCommandUsage(sender)); + } + return; + } + + CommandKamkeelBase command = parent.getCommand(args); + if(command == null) + throw new CommandException("Unknown command " + args[0]); + + if(command.subcommands.isEmpty()){ + sender.addChatMessage(new ChatComponentTranslation(command.getCommandUsage(sender))); + return; + } + + Method m = null; + if(args.length > 1){ + m = command.subcommands.get(args[1].toLowerCase()); + } + if(m == null){ + sendMessage(sender, "------" + command.getCommandName() + " SubCommands------"); + for(Entry entry : command.subcommands.entrySet()){ + sender.addChatMessage(new ChatComponentTranslation(entry.getKey() + ": " + entry.getValue().getAnnotation(SubCommand.class).desc())); + } + } + else{ + sendMessage(sender, "------" + command.getCommandName() + "." + args[1].toLowerCase() + " Command------"); + SubCommand sc = m.getAnnotation(SubCommand.class); + sender.addChatMessage(new ChatComponentTranslation(sc.desc())); + if(!sc.usage().isEmpty()) + sender.addChatMessage(new ChatComponentTranslation("Usage: " + sc.usage())); + } + } +} diff --git a/src/main/java/kamkeel/CmdNPC.java b/src/main/java/kamkeel/CmdNPC.java new file mode 100644 index 000000000..c87dcf7d4 --- /dev/null +++ b/src/main/java/kamkeel/CmdNPC.java @@ -0,0 +1,218 @@ +package kamkeel; + +import java.util.Arrays; +import java.util.List; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.command.NumberInvalidException; +import net.minecraft.command.PlayerNotFoundException; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; +import noppes.npcs.NoppesUtilServer; +import noppes.npcs.constants.EnumGuiType; +import noppes.npcs.entity.EntityCustomNpc; +import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.roles.RoleCompanion; +import noppes.npcs.roles.RoleFollower; + +public class CmdNPC extends CommandKamkeelBase { + + public EntityNPCInterface selectedNpc; + + + @Override + public String getCommandName() { + return "npc"; + } + + @Override + public String getDescription() { + return "NPC operation"; + } + + @Override + public String getUsage() { + return " "; + } + + @Override + public boolean runSubCommands(){ + return false; + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + String npcname = args[0].replace("%", " "); + String command = args[1]; + args = Arrays.copyOfRange(args, 2, args.length); + if(command.equalsIgnoreCase("create")){ + processSubCommand(sender, command, new String[]{args[0], npcname}); + return; + } + + int x = sender.getPlayerCoordinates().posX; + int y = sender.getPlayerCoordinates().posY; + int z = sender.getPlayerCoordinates().posZ; + List list = getEntities(EntityNPCInterface.class, sender.getEntityWorld(), x, y, z, 80); + for (EntityNPCInterface npc : list) { + String name = npc.display.getName().replace(" ", "_"); + if (name.equalsIgnoreCase(npcname)){ + if(selectedNpc == null || selectedNpc.getDistanceSq(x, y, z) > npc.getDistanceSq(x, y, z)) + selectedNpc = npc; + } + } + if(selectedNpc == null) + throw new CommandException("Npc " + npcname + " was not found"); + + processSubCommand(sender, command, args); + selectedNpc = null; + + } + + @SubCommand( + desc = "Set Home (respawn place)", + usage = "[x] [y] [z]" + ) + public void home(ICommandSender sender, String[] args) { + double posX = sender.getPlayerCoordinates().posX; + double posY = sender.getPlayerCoordinates().posY; + double posZ = sender.getPlayerCoordinates().posZ; + + if(args.length == 3){ + posX = CommandBase.func_110666_a(sender, selectedNpc.posX, args[0]); + posY = CommandBase.func_110665_a(sender, selectedNpc.posY, args[1].trim(), 0, 0); + posZ = CommandBase.func_110666_a(sender, selectedNpc.posZ, args[2]); + } + + selectedNpc.ai.startPos = new int[]{MathHelper.floor_double(posX), MathHelper.floor_double(posY), MathHelper.floor_double(posZ)}; + } + + @SubCommand( + desc = "Set NPC visibility", + usage = "[true/false/semi]" + ) + public void visible(ICommandSender sender, String[] args){ + if(args.length < 1) + return; + boolean bo = args[0].equalsIgnoreCase("true"); + boolean semi = args[0].equalsIgnoreCase("semi"); + + int current = selectedNpc.display.visible; + if(semi) + selectedNpc.display.visible = 2; + else if(bo) + selectedNpc.display.visible = 0; + else + selectedNpc.display.visible = 1; + + if(current != selectedNpc.display.visible) + selectedNpc.updateClient = true; + + } + + @SubCommand(desc = "Delete an NPC") + public void delete(ICommandSender sender, String[] args){ + selectedNpc.delete(); + } + + @SubCommand( + desc = "Sets the owner of an follower/companion", + usage = "[player]" + ) + public void owner(ICommandSender sender, String[] args){ + if(args.length < 1){ + EntityPlayer player = null; + if(selectedNpc.roleInterface instanceof RoleFollower) + player = ((RoleFollower)selectedNpc.roleInterface).owner; + + if(selectedNpc.roleInterface instanceof RoleCompanion) + player = ((RoleCompanion)selectedNpc.roleInterface).owner; + + if(player == null) + sendMessage(sender, "No owner"); + else + sendMessage(sender, "Owner is: " + player.getDisplayName()); + } + else{ + EntityPlayerMP player = null; + try { + player = CommandBase.getPlayer(sender, args[0]); + } catch (PlayerNotFoundException e) { + + } + if(selectedNpc.roleInterface instanceof RoleFollower) + ((RoleFollower)selectedNpc.roleInterface).setOwner(player); + + if(selectedNpc.roleInterface instanceof RoleCompanion) + ((RoleCompanion)selectedNpc.roleInterface).setOwner(player); + } + } + + + @SubCommand( + desc = "Set NPC name", + usage = "[name]" + ) + public void name(ICommandSender sender, String[] args){ + if(args.length < 1) + return; + + String name = args[0]; + for(int i = 1; i < args.length; i++){ + name += " " + args[i]; + } + + if(!selectedNpc.display.getName().equals(name)){ + selectedNpc.display.setName(name); + selectedNpc.updateClient = true; + } + } + + @SubCommand( + desc = "Creates an NPC", + usage = "[name]" + ) + public void create(ICommandSender sender, String[] args) { + EntityPlayerMP player = (EntityPlayerMP) sender; + World pw = player.getEntityWorld(); + EntityCustomNpc npc = new EntityCustomNpc(pw); + if(args.length > 0) + npc.display.name = args[0]; + npc.setPositionAndRotation(player.posX, player.posY, player.posZ, player.cameraYaw, player.cameraPitch); + npc.ai.startPos = new int[]{MathHelper.floor_double(player.posX),MathHelper.floor_double(player.posY),MathHelper.floor_double(player.posZ)}; + pw.spawnEntityInWorld(npc); + npc.setHealth(npc.getMaxHealth()); + NoppesUtilServer.sendOpenGui(player, EnumGuiType.MainMenuDisplay, npc); + } + + + @Override + public List addTabCompletionOptions(ICommandSender par1, String[] args) { + if(args.length == 2){ + return CommandBase.getListOfStringsMatchingLastWord(args, new String[]{"create", "home", "visible", "delete", "owner", "name"}); + } + if(args.length == 3 && args[1].equalsIgnoreCase("owner")){ + return CommandBase.getListOfStringsMatchingLastWord(args, MinecraftServer.getServer().getAllUsernames()); + } + + return null; + } + + @Override + public int getRequiredPermissionLevel(){ + return 4; + } + + public List getEntities(Class cls, World world, int x, int y, int z, int range) { + AxisAlignedBB bb = AxisAlignedBB.getBoundingBox(x, y, z, x + 1, y + 1, z + 1).expand(range, range, range); + List list = world.getEntitiesWithinAABB(cls, bb); + return list; + } +} diff --git a/src/main/java/kamkeel/CmdQuest.java b/src/main/java/kamkeel/CmdQuest.java new file mode 100644 index 000000000..3dae99138 --- /dev/null +++ b/src/main/java/kamkeel/CmdQuest.java @@ -0,0 +1,155 @@ +package kamkeel; + +import java.util.List; + +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayerMP; +import noppes.npcs.Server; +import noppes.npcs.constants.EnumPacketClient; +import noppes.npcs.controllers.DialogController; +import noppes.npcs.controllers.PlayerDataController; +import noppes.npcs.controllers.QuestController; +import noppes.npcs.controllers.data.PlayerData; +import noppes.npcs.controllers.data.Quest; +import noppes.npcs.controllers.data.QuestData; + +public class CmdQuest extends CommandKamkeelBase { + + @Override + public String getCommandName() { + return "quest"; + } + + @Override + public String getDescription() { + return "Quest operations"; + } + + @SubCommand( + desc = "Start a quest", + usage = " " + ) + public void start(ICommandSender sender, String[] args) throws CommandException { + String playername = args[0]; + int questid; + try { + questid = Integer.parseInt(args[1]); + } catch (NumberFormatException ex) { + throw new CommandException("QuestID must be an integer: " + args[1]); + } + + List data = PlayerDataController.instance.getPlayersData(sender, playername); + + if (data.isEmpty()) { + throw new CommandException("Unknown player: " + playername); + } + + Quest quest = QuestController.instance.quests.get(questid); + if (quest == null){ + throw new CommandException("Unknown QuestID: " + questid); + } + + for(PlayerData playerdata : data){ + QuestData questdata = new QuestData(quest); + playerdata.questData.activeQuests.put(questid, questdata); + playerdata.saveNBTData(null); + Server.sendData((EntityPlayerMP)playerdata.player, EnumPacketClient.MESSAGE, "quest.newquest", quest.title); + Server.sendData((EntityPlayerMP)playerdata.player, EnumPacketClient.CHAT, "quest.newquest", ": ", quest.title); + } + } + + @SubCommand( + desc = "Finish a quest", + usage = " " + ) + public void finish(ICommandSender sender, String args[]) throws CommandException{ + String playername=args[0]; + int questid; + try { + questid = Integer.parseInt(args[1]); + } + catch (NumberFormatException ex) { + throw new CommandException("QuestID must be an integer: " + args[1]); + } + + List data = PlayerDataController.instance.getPlayersData(sender, playername); + if (data.isEmpty()) { + throw new CommandException(String.format("Unknow player '%s'", playername)); + } + + Quest quest = QuestController.instance.quests.get(questid); + if (quest == null){ + throw new CommandException("Unknown QuestID: " + questid); + } + for(PlayerData playerdata : data){ + playerdata.questData.finishedQuests.put(questid, System.currentTimeMillis()); + playerdata.saveNBTData(null); + } + } + + @SubCommand( + desc = "Stop a started quest", + usage = " " + ) + public void stop(ICommandSender sender, String[] args) throws CommandException { + String playername=args[0]; + int questid; + try { + questid = Integer.parseInt(args[1]); + } catch (NumberFormatException ex) { + throw new CommandException("QuestID must be an integer: " + args[1]); + } + List data = PlayerDataController.instance.getPlayersData(sender, playername); + if (data.isEmpty()) { + throw new CommandException(String.format("Unknow player '%s'", playername)); + } + Quest quest = QuestController.instance.quests.get(questid); + if (quest == null){ + throw new CommandException("Unknown QuestID: " + questid); + } + for(PlayerData playerdata : data){ + playerdata.questData.activeQuests.remove(questid); + playerdata.saveNBTData(null); + } + } + + @SubCommand( + desc = "Removes a quest from finished and active quests", + usage = " " + ) + public void remove(ICommandSender sender, String[] args) throws CommandException { + String playername=args[0]; + int questid; + try { + questid = Integer.parseInt(args[1]); + } catch (NumberFormatException ex) { + throw new CommandException("QuestID must be an integer: " + args[1]); + } + + List data = PlayerDataController.instance.getPlayersData(sender, playername); + if (data.isEmpty()) { + throw new CommandException(String.format("Unknown player '%s'", playername)); + } + + Quest quest = QuestController.instance.quests.get(questid); + if (quest == null){ + throw new CommandException(String.format("Unknown QuestID")); + } + + for(PlayerData playerdata : data){ + playerdata.questData.activeQuests.remove(questid); + playerdata.questData.finishedQuests.remove(questid); + playerdata.saveNBTData(null); + } + } + + @SubCommand( + desc="reload quests from disk", + permission = 4 + ) + public void reload(ICommandSender sender, String args[]){ + new DialogController(); + } +} + diff --git a/src/main/java/kamkeel/CmdScript.java b/src/main/java/kamkeel/CmdScript.java new file mode 100644 index 000000000..21528869f --- /dev/null +++ b/src/main/java/kamkeel/CmdScript.java @@ -0,0 +1,42 @@ +package kamkeel; + +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.ChatComponentTranslation; +import noppes.npcs.controllers.ScriptController; + + +public class CmdScript extends CommandKamkeelBase { + + @SubCommand(desc = "Reload scripts and saved data from disks script folder.") + public Boolean reload(ICommandSender sender, String args[]) { + ScriptController.Instance.loadCategories(); + + if(ScriptController.Instance.loadPlayerScripts()) + sendMessage(sender, "Reload player scripts successfully"); + else + sendMessage(sender, "Failed reloading player scripts"); + + if(ScriptController.Instance.loadForgeScripts()) + sendMessage(sender, "Reload forge scripts successfully"); + else + sendMessage(sender, "Failed reloading forge scripts"); + + if(ScriptController.Instance.loadStoredData()) + sendMessage(sender, "Reload stored data successfully"); + else + sendMessage(sender, "Failed reloading stored data"); + return true; + + } + + @Override + public String getCommandName() { + return "script"; + } + + @Override + public String getDescription() { + return "Commands for scripts"; + } +} diff --git a/src/main/java/kamkeel/CmdSlay.java b/src/main/java/kamkeel/CmdSlay.java new file mode 100644 index 000000000..437005130 --- /dev/null +++ b/src/main/java/kamkeel/CmdSlay.java @@ -0,0 +1,144 @@ +package kamkeel; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.boss.EntityDragon; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.item.EntityXPOrb; +import net.minecraft.entity.monster.EntityGhast; +import net.minecraft.entity.monster.EntityMob; +import net.minecraft.entity.passive.EntityAnimal; +import net.minecraft.entity.passive.EntityHorse; +import net.minecraft.entity.passive.EntityTameable; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.ChatComponentTranslation; +import noppes.npcs.entity.EntityNPCInterface; + +public class CmdSlay extends CommandKamkeelBase { + public Map> SlayMap = new LinkedHashMap>(); + + public CmdSlay(){ + SlayMap.clear(); + + SlayMap.put("all",EntityLivingBase.class); + SlayMap.put("mobs",EntityMob.class); + SlayMap.put("animals", EntityAnimal.class); + SlayMap.put("items", EntityItem.class); + SlayMap.put("xporbs", EntityXPOrb.class); + SlayMap.put("npcs", EntityNPCInterface.class); + + HashMap> list = new HashMap>(EntityList.stringToClassMapping); + for(String name : list.keySet()){ + Class cls = list.get(name); + if(EntityNPCInterface.class.isAssignableFrom(cls)) + continue; + if(!EntityLivingBase.class.isAssignableFrom(cls)) + continue; + SlayMap.put(name.toLowerCase(), list.get(name)); + } + + SlayMap.remove("monster"); + SlayMap.remove("mob"); + } + + @Override + public String getCommandName() { + return "slay"; + } + + @Override + public String getDescription() { + return "Kills given entity within range. Also has all, mobs, animal options. Can have multiple types"; + } + + @Override + public String getUsage(){ + return ".. [range]"; + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + EntityPlayerMP player = (EntityPlayerMP) sender; + ArrayList> toDelete = new ArrayList>(); + boolean deleteNPCs = false; + for(String delete : args){ + delete = delete.toLowerCase(); + Class cls = SlayMap.get(delete); + if(cls != null) + toDelete.add(cls); + if(delete.equals("mobs")){ + toDelete.add(EntityGhast.class); + toDelete.add(EntityDragon.class); + } + if(delete.equals("npcs")) + deleteNPCs = true; + } + int count = 0; + int range = 120; + try{ + range = Integer.parseInt(args[args.length - 1]); + } + catch(NumberFormatException ex){ + + } + AxisAlignedBB box = player.boundingBox.expand(range, range, range); + List list = sender.getEntityWorld().getEntitiesWithinAABB(EntityLivingBase.class, box); + + for(Entity entity : list){ + if(entity instanceof EntityPlayer) + continue; + if(entity instanceof EntityTameable && ((EntityTameable)entity).isTamed()) + continue; + if(entity instanceof EntityNPCInterface && !deleteNPCs) + continue; + if(delete(entity,toDelete)) + count++; + } + if(toDelete.contains(EntityXPOrb.class)){ + list = sender.getEntityWorld().getEntitiesWithinAABB(EntityXPOrb.class, box); + for(Entity entity : list){ + entity.isDead = true; + count++; + } + } + if(toDelete.contains(EntityItem.class)){ + list = sender.getEntityWorld().getEntitiesWithinAABB(EntityItem.class, box); + for(Entity entity : list){ + entity.isDead = true; + count++; + } + } + + sender.addChatMessage(new ChatComponentTranslation(count + " entities deleted")); + } + + private boolean delete(Entity entity, ArrayList> toDelete) { + for(Class delete : toDelete){ + if(delete == EntityAnimal.class && (entity instanceof EntityHorse)){ + continue; + } + if(delete.isAssignableFrom(entity.getClass())){ + entity.isDead = true; + return true; + } + } + return false; + } + + @Override + public List addTabCompletionOptions(ICommandSender sender, String[] args){ + return CommandBase.getListOfStringsMatchingLastWord(args, SlayMap.keySet().toArray(new String[SlayMap.size()])); + } +} diff --git a/src/main/java/kamkeel/CommandKamkeel.java b/src/main/java/kamkeel/CommandKamkeel.java new file mode 100644 index 000000000..2524d9d72 --- /dev/null +++ b/src/main/java/kamkeel/CommandKamkeel.java @@ -0,0 +1,100 @@ +package kamkeel; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.math.BlockPos; +import noppes.npcs.scripted.CustomNPCsException; + +public class CommandKamkeel extends CommandBase{ + + public Map map = new HashMap(); + public CmdHelp help = new CmdHelp(this); + + public CommandKamkeel(){ + registerCommand(help); + registerCommand(new CmdScript()); + registerCommand(new CmdSlay()); + registerCommand(new CmdQuest()); + registerCommand(new CmdDialog()); + registerCommand(new CmdFaction()); + registerCommand(new CmdNPC()); + registerCommand(new CmdClone()); + registerCommand(new CmdConfig()); + } + + public void registerCommand(CommandKamkeelBase command){ + String name = command.getCommandName().toLowerCase(); + if(map.containsKey(name)) + throw new CustomNPCsException("Already a subcommand with the name: " + name); + map.put(name, command); + } + + @Override + public String getCommandName() { + return "kamkeel"; + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return "Use as /kamkeel subcommand"; + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if(args.length == 0){ + help.processCommand(sender, args); + return; + } + + CommandKamkeelBase command = getCommand(args); + if(command == null) + throw new CommandException("Unknown command " + args[0]); + + args = Arrays.copyOfRange(args, 1, args.length); + if(command.subcommands.isEmpty() || !command.runSubCommands()){ + if(!sender.canCommandSenderUseCommand(command.getRequiredPermissionLevel(), "commands.kamkeel." + command.getCommandName().toLowerCase())) + throw new CommandException("You are not allowed to use this command: " + command); + command.canRun(sender, command.getUsage(), args); + command.processCommand(sender, args); + return; + } + + if(args.length == 0){ + help.processCommand(sender, new String[]{command.getCommandName()}); + return; + } + + command.processSubCommand(sender, args[0], Arrays.copyOfRange(args, 1, args.length)); + } + + @Override + public List addTabCompletionOptions(ICommandSender sender, String[] args){ + if(args.length == 1) + return new ArrayList(map.keySet()); + CommandKamkeelBase command = getCommand(args); + if(command == null) + return null; + if(args.length == 2 && command.runSubCommands()) + return new ArrayList(command.subcommands.keySet()); + return command.addTabCompletionOptions(sender, Arrays.copyOfRange(args, 1, args.length)); + } + + public CommandKamkeelBase getCommand(String[] args){ + if(args.length == 0) + return null; + return map.get(args[0].toLowerCase()); + } + + @Override + public int getRequiredPermissionLevel(){ + return 2; + } +} + diff --git a/src/main/java/kamkeel/CommandKamkeelBase.java b/src/main/java/kamkeel/CommandKamkeelBase.java new file mode 100644 index 000000000..2701fee54 --- /dev/null +++ b/src/main/java/kamkeel/CommandKamkeelBase.java @@ -0,0 +1,114 @@ +package kamkeel; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentTranslation; + +public abstract class CommandKamkeelBase extends CommandBase{ + public Map subcommands = new HashMap(); + + public CommandKamkeelBase(){ + for (Method m : this.getClass().getDeclaredMethods()) { + SubCommand sc = m.getAnnotation(SubCommand.class); + if (sc != null) { + String name = sc.name(); + if (name.equals("")) + name = m.getName(); + subcommands.put(name.toLowerCase(), m); + } + } + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return getDescription(); + } + + public abstract String getDescription(); + + /** + * @return Should return a string in the format of [arg4] where <> is a required parameter and [] optional + */ + public String getUsage(){ + return ""; + } + + public boolean runSubCommands(){ + return !subcommands.isEmpty(); + } + + protected void sendMessage(ICommandSender sender, String message, Object... obs) { + sender.addChatMessage(new ChatComponentTranslation(message, obs)); + } + + @Retention(value = RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface SubCommand { + + String name() default ""; + + /** + * @return Should return a string in the format of [arg4] where <> is a required parameter and [] optional + */ + String usage() default ""; + + String desc(); + + int permission() default 2; + } + + public void processSubCommand(ICommandSender sender, String command, String[] args) throws CommandException { + Method m = subcommands.get(command.toLowerCase()); + if(m == null) + throw new CommandException("Unknown subcommand " + command); + + SubCommand sc = m.getAnnotation(SubCommand.class); + if(!sender.canCommandSenderUseCommand(sc.permission(), "commands.noppes." + getCommandName().toLowerCase() + "." + command.toLowerCase())) + throw new CommandException("You are not allowed to use this command: " + command); + + canRun(sender, sc.usage(), args); + try { + m.invoke(this, sender, args); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void canRun(ICommandSender sender, String usage, String[] args) throws CommandException{ + String[] np = usage.split(" "); + List required = new ArrayList(); + for(int i = 0; i < np.length; i++){ + String command = np[i]; + if(command.startsWith("<")){ + required.add(command); + } + if(command.equals("") && args.length > i){ + CommandBase.getPlayer(sender, args[i]); //throws PlayerNotFoundException if no player is found + } + + } + if (args.length < required.size()) { + throw new CommandException("Missing parameter: " + required.get(args.length)); + } + } + + public int getRequiredPermissionLevel(){ + return 2; + } +} \ No newline at end of file