April 16, 20169 yr Author I tested your implementation and it works exactly what I was think off, but I do have a question about it. How do I make help usage use a different header? The default ones says /help instead of /tetracraft help . Also, how do I make my admin command enter in the commands with the tab button? The code is this: package novaviper.tetracraft.common.command; import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; import net.minecraft.command.WrongUsageException; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.WorldServer; import net.minecraftforge.fml.server.FMLServerHandler; import novaviper.tetracraft.common.command.modifers.*; import novaviper.tetracraft.common.entity.EntityModTameable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Created by NovaViper on 4/14/2016. * Class Purpose: */ public class CommandAdmin extends CommandBase { @Override public String getCommandName() { return "admin"; } @Override public List getCommandAliases() { return Arrays.<String>asList(new String[] {"a", "*"}); } @Override public String getCommandUsage(ICommandSender sender) { return String.format("commands.tetracraft:admin.usage"); } /** * Return the required permission level for this command. */ @Override public int getRequiredPermissionLevel() { return 4; } private boolean getCommand(String paramIn, String name) { return paramIn.equalsIgnoreCase(name); } @Override public void execute(MinecraftServer server, ICommandSender sender, String[] params) throws CommandException { if (sender instanceof EntityPlayerMP) { EntityPlayerMP player = (EntityPlayerMP) sender; if (params.length < 1 || params[0].isEmpty()) { throw new WrongUsageException(getCommandUsage(sender)); } // last parameter, optional boolean global = params[params.length - 1].equalsIgnoreCase("global") || params[params.length - 1].equalsIgnoreCase("g") || params[params.length - 1].equalsIgnoreCase("all") || params[params.length - 1].equalsIgnoreCase("a"); String command = params[0]; if (getCommand(command, "tame") || getCommand(command, "t")) { applyModifier(sender, new TameModifier(player), global); } else if (getCommand(command, "heal") || getCommand(command, "hp")) { applyModifier(sender, new HealthModifier(player), global); } else if (getCommand(command, "stage") || getCommand(command, "st")) { if (params.length < 2) { throw new WrongUsageException(getCommandUsage(sender)); } String parameter = params[1]; if (parameter.equalsIgnoreCase("baby") || parameter.equalsIgnoreCase("b")) { applyModifier(sender, new AgeModifier(player, -24000), global); } else if (parameter.equalsIgnoreCase("adult") || parameter.equalsIgnoreCase("a")) { applyModifier(sender, new AgeModifier(player, 1), global); } } else if (getCommand(command, "purge") || getCommand(command, "p")) { if (params.length < 2) { throw new WrongUsageException(getCommandUsage(sender)); } String parameter = params[1]; if (parameter.equalsIgnoreCase("tamed") || parameter.equalsIgnoreCase("t")) { applyModifier(sender, new PurgeModifier(player, false, "tamed"), global); } else if (parameter.equalsIgnoreCase("all") || parameter.equalsIgnoreCase("a")) { applyModifier(sender, new PurgeModifier(player, true, "all"), true); } else if (parameter.equalsIgnoreCase("wild") || parameter.equalsIgnoreCase("w")) { applyModifier(sender, new PurgeModifier(player, false, "wild"), global); } } else if (getCommand(command, "gender") || getCommand(command, "g")) { if (params.length < 2) { throw new WrongUsageException(getCommandUsage(sender)); } String parameter = params[1]; if (parameter.equalsIgnoreCase("male") || parameter.equalsIgnoreCase("m")) { applyModifier(sender, new GenderModifier(player, true), global); } else if (parameter.equalsIgnoreCase("female") || parameter.equalsIgnoreCase("f")) { applyModifier(sender, new GenderModifier(player, false), global); } } else { throw new CommandException(getCommandUsage(sender)); } } } private boolean getArgs(String[] args, String name) { return args[0].equalsIgnoreCase(name); } /** * Adds the strings available in this command to the given list of tab * completion options. */ @Override public List<String> getTabCompletionOptions(MinecraftServer server, ICommandSender sender, String[] args, BlockPos pos) { boolean argLength = args.length == 2; return args.length == 1 ? getListOfStringsMatchingLastWord(args, new String[] {}) : (argLength && getArgs(args, "stage") || getArgs(args, "s") ? getListOfStringsMatchingLastWord(args, new String[] { "baby", "adult" }) : (argLength && getArgs(args, "purge") || getArgs(args, "p") ? getListOfStringsMatchingLastWord(args, new String[] { "tamed", "wild", "all" }) : null)); } private void applyModifier(ICommandSender sender, EntityModifier modifier, boolean global) throws CommandException { if (!global && sender instanceof EntityPlayerMP) { EntityPlayerMP player = getCommandSenderAsPlayer(sender); double range = 64; AxisAlignedBB aabb = new AxisAlignedBB(player.posX - 1, player.posY - 1, player.posZ - 1, player.posX + 1, player.posY + 1, player.posZ + 1); aabb = aabb.expand(range, range, range); List<Entity> entities = player.worldObj.getEntitiesWithinAABB(EntityModTameable.class, aabb); Entity closestEntity = null; float minPlayerDist = Float.MAX_VALUE; // get closest entity for (int i = 0; i < entities.size(); i++) { Entity entity = entities.get(i); float playerDist = entity.getDistanceToEntity(player); if (entity.getDistanceToEntity(player) < minPlayerDist) { closestEntity = entity; minPlayerDist = playerDist; } } if (closestEntity == null) { throw new CommandException("commands.tetracraft:admin.notameable"); } else { modifier.modify((EntityModTameable)closestEntity); } } else { // scan all entities on all dimensions MinecraftServer server = FMLServerHandler.instance().getServer(); for (WorldServer worldServer : server.worldServers) { List<Entity> entities = worldServer.loadedEntityList; for (int i = 0; i < entities.size(); i++) { Entity entity = entities.get(i); if (!(entity instanceof EntityModTameable)) { continue; } modifier.modify((EntityModTameable)entity); } } } } public interface EntityModifier { public void modify(EntityModTameable entity); } } Main Developer and Owner of Zero Quest Visit the Wiki for more information If I helped anyone, please give me a applaud and a thank you!
April 16, 20169 yr To change the header, you'll need to override CommandHelp#execute to do exactly the same thing as the super method but use your translation keys instead of the vanilla ones. To get tab completion working for the sub-commands of the admin sub-command, pass the possible command names as the second argument of getListOfStringsMatchingLastWord instead of an empty array when there's a single argument. CommandBase.getListOfStringsMatchingLastWord(String[], String...) is a vararg method, you don't need to explicitly create the String array for the second argument. Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
April 17, 20169 yr Author Thanks! I had to play around with the CommandBase.getListOfStringsMatchingLastWord(String[], String...) a little bit because it was a bit hard to understand with the ? : booleans but I did the if else and got it work. But I have one more question with the sub commands, how do I make the commands not sort? I want the Aliases to line up together like this: help, h, ?, version, v, admin, a , * Instead of this: help, a, v, h, admin, *, version, ? Main Developer and Owner of Zero Quest Visit the Wiki for more information If I helped anyone, please give me a applaud and a thank you!
April 17, 20169 yr You'll need to create a Map<String, ICommand> field in SubCommandHandler and set it to a new LinkedHashMap (a HashMap that preserves insertion order). Override CommandHandler#registerCommand to add the command's name and aliases to this map (like the super method does for its own map) and then return the result of calling the super method. Override CommandHandler#getTabCompletionOptions to do the same thing as the super method, but iterate through your map instead. This should tab-complete sub-command names and their aliases in the order they were registered or returned from ICommand#getCommandAliases , respectively. Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
April 17, 20169 yr Author I did what you said but now the subcommands aren't registered package novaviper.tetracraft.common.command; import com.google.common.collect.Lists; import net.minecraft.command.*; import net.minecraft.server.MinecraftServer; import net.minecraft.util.math.BlockPos; import novaviper.tetracraft.common.command.interfaces.ISubCommandManager; import novaviper.tetracraft.common.init.ModCommands; import novaviper.tetracraft.common.init.TetraCraft; import javax.annotation.Nullable; import java.util.*; /** * Created by NovaViper on 4/15/2016. * Class Purpose: A command with sub-commands * Credit goes to Choonster */ public class CommandTetraCraft extends CommandBase { /** * The {@link ISubCommandManager} that manages the sub-commands of this command. */ private final SubCommandHandler subCommandHandler; public CommandTetraCraft(MinecraftServer server) { subCommandHandler = new SubCommandHandler(server); } /** * Join the arguments array into a single string. * * @param args The arguments * @return The joined string */ private static String joinArgs(String[] args) { return String.join(" ", (CharSequence[]) args); } /** * Return a copy of the array with the first string removed. * <p> * Copied from {@link CommandHandler#dropFirstString}. * * @param input The original array * @return The new array */ private static String[] dropFirstString(String[] input) { String[] output = new String[input.length - 1]; System.arraycopy(input, 1, output, 0, input.length - 1); return output; } /** * Gets the name of the command */ @Override public String getCommandName() { return "tetracraft"; } @Override public List<String> getCommandAliases() { return Arrays.<String>asList(new String[] {"tcraft", "tc", "TETRACRAFT", "TCRAFT", "TC"}); } /** * Gets the usage string for the command. * * @param sender The command sender * @return The command usage */ @Override public String getCommandUsage(ICommandSender sender) { return "commands.tetracraft.usage"; } /** * Callback for when the command is executed * * @param server The Minecraft server instance * @param sender The source of the command invocation * @param args The arguments that were passed */ @Override public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { subCommandHandler.executeCommand(sender, joinArgs(args)); } @Override public List<String> getTabCompletionOptions(MinecraftServer server, ICommandSender sender, String[] args, BlockPos pos) { return subCommandHandler.getTabCompletionOptions(sender, joinArgs(args), pos); } /** * Return whether the specified command parameter index is a username parameter. */ @Override public boolean isUsernameIndex(String[] args, int index) { final ICommand subCommand = subCommandHandler.getCommand(args[0]); return index > 0 && subCommand != null && subCommand.isUsernameIndex(dropFirstString(args), index - 1); } /** * Handler for the sub-commands of this command. */ private static class SubCommandHandler extends CommandHandler implements ISubCommandManager { private final MinecraftServer server; public Map<String, ICommand> commandsMap = new LinkedHashMap(); private SubCommandHandler(MinecraftServer server) { this.server = server; ModCommands.registerSubCommands(this); } @Override protected MinecraftServer getServer() { return server; } @Override public ICommand registerCommand(ICommand command) { super.registerCommand(command); this.commandsMap.put(command.getCommandName(), command); for (String s : command.getCommandAliases()) { ICommand icommand = (ICommand)this.commandsMap.get(s); if (icommand == null || !icommand.getCommandName().equals(s)) { this.commandsMap.put(s, command); } } return command; } @Override public List<String> getTabCompletionOptions(ICommandSender sender, String input, BlockPos pos) { String[] astring = input.split(" ", -1); String s = astring[0]; if (astring.length == 1) { List<String> list = Lists.<String>newArrayList(); for (Map.Entry<String, ICommand> entry : this.commandsMap.entrySet()) { if (CommandBase.doesStringStartWith(s, (String)entry.getKey()) && ((ICommand)entry.getValue()).checkPermission(this.getServer(), sender)) { list.add(entry.getKey()); } } return list; } else { if (astring.length > 1) { ICommand icommand = (ICommand)this.commandsMap.get(s); if (icommand != null && icommand.checkPermission(this.getServer(), sender)) { return icommand.getTabCompletionOptions(this.getServer(), sender, dropFirstString(astring), pos); } } return Collections.<String>emptyList(); } } /** * Get the command with the specified name. * * @param commandName The command name * @return The command, or null if there isn't one */ @Nullable public ICommand getCommand(String commandName) { return getCommands().get(commandName); } } } UPDATE: I fixed the commands registering, I had to add the super method. Main Developer and Owner of Zero Quest Visit the Wiki for more information If I helped anyone, please give me a applaud and a thank you!
April 17, 20169 yr Author I also don't want the help menu to sort the commands either. How do I fix that? Main Developer and Owner of Zero Quest Visit the Wiki for more information If I helped anyone, please give me a applaud and a thank you!
April 17, 20169 yr I also don't want the help menu to sort the commands either. How do I fix that? Create a LinkedHashSet<ICommand> and populate it in your override of CommandHandler#registerCommand (like the super method does for its set). Override CommandHandler#getPossibleCommands to do the same thing as the super method, but with your set instead. In your override of CommandHelp#getSortedPossibleCommands , return the command list without sorting it. You can see my implementation here and here. Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
April 17, 20169 yr Author Thanks Choonster! Main Developer and Owner of Zero Quest Visit the Wiki for more information If I helped anyone, please give me a applaud and a thank you!
April 17, 20169 yr Author Hey Choonster, I got an issue with the admin commands, I get this error whenever I use the global optional parameter with the commands (it affects all of the mod tameable entities, which I make change that to all the entities in my mod instead of just the tameable ones): [18:34:58] [server thread/WARN]: Couldn't process command: 'admin gender female g' java.lang.NullPointerException at novaviper.tetracraft.common.command.CommandAdmin.applyModifier(CommandAdmin.java:155) ~[CommandAdmin.class:?] at novaviper.tetracraft.common.command.CommandAdmin.execute(CommandAdmin.java:94) ~[CommandAdmin.class:?] at net.minecraft.command.CommandHandler.tryExecute(CommandHandler.java:107) [CommandHandler.class:?] at net.minecraft.command.CommandHandler.executeCommand(CommandHandler.java:86) [CommandHandler.class:?] at novaviper.tetracraft.common.command.CommandTetraCraft.execute(CommandTetraCraft.java:88) [CommandTetraCraft.class:?] at net.minecraft.command.CommandHandler.tryExecute(CommandHandler.java:107) [CommandHandler.class:?] at net.minecraft.command.CommandHandler.executeCommand(CommandHandler.java:86) [CommandHandler.class:?] at net.minecraft.network.NetHandlerPlayServer.handleSlashCommand(NetHandlerPlayServer.java:957) [NetHandlerPlayServer.class:?] at net.minecraft.network.NetHandlerPlayServer.processChatMessage(NetHandlerPlayServer.java:933) [NetHandlerPlayServer.class:?] at net.minecraft.network.play.client.CPacketChatMessage.processPacket(CPacketChatMessage.java:47) [CPacketChatMessage.class:?] at net.minecraft.network.play.client.CPacketChatMessage.processPacket(CPacketChatMessage.java: [CPacketChatMessage.class:?] at net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:15) [PacketThreadUtil$1.class:?] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_77] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_77] at net.minecraft.util.Util.runTask(Util.java:23) [util.class:?] at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:738) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:683) [MinecraftServer.class:?] at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:155) [integratedServer.class:?] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:532) [MinecraftServer.class:?] at java.lang.Thread.run(Thread.java:745) [?:1.8.0_77] [18:34:58] [Client thread/INFO]: [CHAT] An unknown error occurred while attempting to perform this command Source code for the command package novaviper.tetracraft.common.command; import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; import net.minecraft.command.WrongUsageException; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.WorldServer; import net.minecraftforge.fml.server.FMLServerHandler; import novaviper.tetracraft.common.command.modifers.*; import novaviper.tetracraft.common.entity.EntityModTameable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Created by NovaViper on 4/14/2016. * Class Purpose: */ public class CommandAdmin extends CommandBase { @Override public String getCommandName() { return "admin"; } @Override public List getCommandAliases() { return Arrays.<String>asList(new String[] {"a", "*"}); } @Override public String getCommandUsage(ICommandSender sender) { return String.format("commands.tetracraft:admin.usage"); } /** * Return the required permission level for this command. */ @Override public int getRequiredPermissionLevel() { return 4; } private boolean getCommand(String paramIn, String name) { return paramIn.equalsIgnoreCase(name); } @Override public void execute(MinecraftServer server, ICommandSender sender, String[] params) throws CommandException { if (sender instanceof EntityPlayerMP) { EntityPlayerMP player = (EntityPlayerMP) sender; if (params.length < 1 || params[0].isEmpty()) { throw new WrongUsageException(getCommandUsage(sender)); } // last parameter, optional boolean global = params[params.length - 1].equalsIgnoreCase("global") || params[params.length - 1].equalsIgnoreCase("g") || params[params.length - 1].equalsIgnoreCase("all") || params[params.length - 1].equalsIgnoreCase("a"); String command = params[0]; if (getCommand(command, "tame") || getCommand(command, "t")) { applyModifier(sender, new TameModifier(player), global); } else if (getCommand(command, "heal") || getCommand(command, "hp")) { applyModifier(sender, new HealthModifier(player), global); } else if (getCommand(command, "age") || getCommand(command, "a")) { if (params.length < 2) { throw new WrongUsageException(getCommandUsage(sender)); } String parameter = params[1]; if (parameter.equalsIgnoreCase("baby") || parameter.equalsIgnoreCase("b")) { applyModifier(sender, new AgeModifier(player, -24000), global); } else if (parameter.equalsIgnoreCase("adult") || parameter.equalsIgnoreCase("a")) { applyModifier(sender, new AgeModifier(player, 1), global); } } else if (getCommand(command, "gender") || getCommand(command, "g")) { if (params.length < 2) { throw new WrongUsageException(getCommandUsage(sender)); } String parameter = params[1]; if (parameter.equalsIgnoreCase("male") || parameter.equalsIgnoreCase("m")) { applyModifier(sender, new GenderModifier(player, true), global); } else if (parameter.equalsIgnoreCase("female") || parameter.equalsIgnoreCase("f")) { applyModifier(sender, new GenderModifier(player, false), global); } } else { throw new CommandException(getCommandUsage(sender)); } } } private boolean getArgs(String[] args, String name) { return args[0].equalsIgnoreCase(name); } /** * Adds the strings available in this command to the given list of tab * completion options. */ @Override public List<String> getTabCompletionOptions(MinecraftServer server, ICommandSender sender, String[] args, BlockPos pos) { if (args.length == 1) { //If the command name is filled, then list the sub commands return getListOfStringsMatchingLastWord(args, new String[] { "tame", "t", "heal", "hp", "age", "a", "gender", "g"}); } else if (args.length == 2) {//If the following sub-commands are filled, then fill their arguments if (args[0].equalsIgnoreCase("age") || args[0].equalsIgnoreCase("a")) { return getListOfStringsMatchingLastWord(args, new String[] { "baby", "adult" }); } else if (args[0].equalsIgnoreCase("gender") || args[0].equalsIgnoreCase("gender")) { return getListOfStringsMatchingLastWord(args, new String[] { "male", "female" }); } } return null; } private void applyModifier(ICommandSender sender, EntityModifier modifier, boolean global) throws CommandException { if (!global && sender instanceof EntityPlayerMP) { EntityPlayerMP player = getCommandSenderAsPlayer(sender); double range = 64; AxisAlignedBB aabb = new AxisAlignedBB(player.posX - 1, player.posY - 1, player.posZ - 1, player.posX + 1, player.posY + 1, player.posZ + 1); aabb = aabb.expand(range, range, range); List<Entity> entities = player.worldObj.getEntitiesWithinAABB(EntityModTameable.class, aabb); Entity closestEntity = null; float minPlayerDist = Float.MAX_VALUE; // get closest entity for (int i = 0; i < entities.size(); i++) { Entity entity = entities.get(i); float playerDist = entity.getDistanceToEntity(player); if (entity.getDistanceToEntity(player) < minPlayerDist) { closestEntity = entity; minPlayerDist = playerDist; } } if (closestEntity == null) { throw new CommandException("commands.tetracraft:admin.notameable"); } else { modifier.modify((EntityModTameable)closestEntity); } } else { // scan all entities on all dimensions MinecraftServer server = FMLServerHandler.instance().getServer(); for (WorldServer worldServer : server.worldServers) { List<Entity> entities = worldServer.loadedEntityList; for (int i = 0; i < entities.size(); i++) { Entity entity = entities.get(i); if (!(entity instanceof EntityModTameable)) { continue; } modifier.modify((EntityModTameable)entity); } } } } public interface EntityModifier { public void modify(EntityModTameable entity); } } Main Developer and Owner of Zero Quest Visit the Wiki for more information If I helped anyone, please give me a applaud and a thank you!
April 17, 20169 yr Author Also, how do I get the status of the Forge Version Checker just for my mod? Main Developer and Owner of Zero Quest Visit the Wiki for more information If I helped anyone, please give me a applaud and a thank you!
April 18, 20169 yr Hey Choonster, I got an issue with the admin commands, I get this error whenever I use the global optional parameter with the commands (it affects all of the mod tameable entities, which I make change that to all the entities in my mod instead of just the tameable ones): I suggest you set a breakpoint on line 155 of CommandAdmin , run the game in debug mode, use the command and then look at the debugger to see what's null . It looks like it's probably the MinecraftServer you get from FMLServerHandler . In 1.9, Minecraft is slowly moving away from MinecraftServer being a singleton since there's no static field in the class itself storing the instance and World has a getMinecraftServer method to get the world's server. For this reason, I suggest you use the MinecraftServer provided to the command rather than using FMLServerHandler (which still assumes there's only one MinecraftServer instance). Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
April 18, 20169 yr Author Hey Choonster, I got an issue with the admin commands, I get this error whenever I use the global optional parameter with the commands (it affects all of the mod tameable entities, which I make change that to all the entities in my mod instead of just the tameable ones): I suggest you set a breakpoint on line 155 of CommandAdmin , run the game in debug mode, use the command and then look at the debugger to see what's null . It looks like it's probably the MinecraftServer you get from FMLServerHandler . In 1.9, Minecraft is slowly moving away from MinecraftServer being a singleton since there's no static field in the class itself storing the instance and World has a getMinecraftServer method to get the world's server. For this reason, I suggest you use the MinecraftServer provided to the command rather than using FMLServerHandler (which still assumes there's only one MinecraftServer instance). I was trying to use MinecraftServer but I can't get the instance of it and yeah, thats what the error is talking about, the MineraftServer being null. Main Developer and Owner of Zero Quest Visit the Wiki for more information If I helped anyone, please give me a applaud and a thank you!
April 18, 20169 yr Also, how do I get the status of the Forge Version Checker just for my mod? Use ForgeVersion.getResult to get the CheckResult of the version check for the specified ModContainer . FMLCommonHandler#findContainerFor will return the ModContainer for the specified mod ID or instance. Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
April 18, 20169 yr I was trying to use MinecraftServer but I can't get the instance of it and yeah, thats what the error is talking about, the MineraftServer being null. ICommand#execute has a MinecraftServer argument, pass this to your applyModifier method. Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
April 18, 20169 yr Author Also, how do I get the status of the Forge Version Checker just for my mod? Use ForgeVersion.getResult to get the CheckResult of the version check for the specified ModContainer . FMLCommonHandler#findContainerFor will return the ModContainer for the specified mod ID or instance. I was trying to use MinecraftServer but I can't get the instance of it and yeah, thats what the error is talking about, the MineraftServer being null. ICommand#execute has a MinecraftServer argument, pass this to your applyModifier method. Thanks! That fixed that error and got the version to display, I have another question though (Sorry for asking so many), I want the header of the help command to have gold seperators (---) and leave the rest of the text dark green. So far I got this: Code int l = Math.min((k + 1) * 7, list.size()); TextComponentTranslation textcomponenttranslation1 = ChatHelper.getChatComponentTranslation(TextFormatting.GOLD + "--- "+"commands.tetracraft:help.header" + TextFormatting.GOLD + " ---", new Object[] {Integer.valueOf(k + 1), Integer.valueOf(j + 1)}); textcomponenttranslation1.getStyle().setColor(TextFormatting.DARK_GREEN); sender.addChatMessage(textcomponenttranslation1); Lang File commands.tetracraft:help.header=Help page %d/%d (/tetracraft help <page>) Main Developer and Owner of Zero Quest Visit the Wiki for more information If I helped anyone, please give me a applaud and a thank you!
April 18, 20169 yr Thanks! That fixed that error and got the version to display, I have another question though (Sorry for asking so many), I want the header of the help command to have gold seperators (---) and leave the rest of the text dark green. So far I got this: Create the TextComponentTranslation for the translated part of the header message with the page numbers as format arguments and set its colour to green. Create another TextComponentTranslation with the dashes and a formatting placeholder ( %s ) for the translated part with the first TextComponentTranslation as a format argument and set its colour to gold. Send this second TextComponentTranslation to the command sender as a chat message. Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
April 19, 20169 yr Author Thanks! That worked! Main Developer and Owner of Zero Quest Visit the Wiki for more information If I helped anyone, please give me a applaud and a thank you!
April 19, 20169 yr Author Hey Choonster, do you know anything about custom animations? I've been trying to figure out how to make such methods. Also, what do I do with the Entity Property I made? Main Developer and Owner of Zero Quest Visit the Wiki for more information If I helped anyone, please give me a applaud and a thank you!
April 19, 20169 yr Hey Choonster, do you know anything about custom animations? I've been trying to figure out how to make such methods. Also, what do I do with the Entity Property I made? I know very little about rendering, I can't help you with animations. Use your EntityProperty in the properties section of an entity_properties conditional in your loot table JSON, like the on_fire property is used in the pig's loot table. Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
April 19, 20169 yr Author Hey Choonster, do you know anything about custom animations? I've been trying to figure out how to make such methods. Also, what do I do with the Entity Property I made? I know very little about rendering, I can't help you with animations. Use your EntityProperty in the properties section of an entity_properties conditional in your loot table JSON, like the on_fire property is used in the pig's loot table. Do you know anyone that can make animations? Also I still can't get the entity to drop items, not sure why it isn't dropping them Main Developer and Owner of Zero Quest Visit the Wiki for more information If I helped anyone, please give me a applaud and a thank you!
April 19, 20169 yr Do you know anyone that can make animations? Also I still can't get the entity to drop items, not sure why it isn't dropping them Not personally, but Jabelar has a tutorial on complex entity models with animation here. I can't really help you with your issues unless you give me something to work with. I need to see the entity, the loot table file, any custom loot table classes used in it (e.g. properties, conditions) and the loot table registration. Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
April 19, 20169 yr Animations for a Block, an Entity, or something else? They are all somewhat different, although similar. To animate something, all you need are 'key frames', i.e. the important reference poses that you will be moving through. The more key frames you have, the better your animation will look, but you can't have more than one frame per render tick, so the length of your animation will limit that, and you usually don't need that many key frames. The minimum you can get away with is 2 key frames - the start pose and the end pose - as well as the number of ticks you want the action to take, and then each tick you interpolate between the end and start frames to get the current frame's angles etc. It's really simple in concept, but also can be quite complicated. BobMowzie has some good video tutorials on and . Even if you choose not to use the 3rd-party libraries that he does, you can still learn a lot about the concepts. Here is by Jabelar about animating, and below is an example of code I use for animating entities, using my own custom-built framework: // create the animation frames once protected final ImmutableList<IAnimation> DEATH_ANIMATION = new ImmutableList.Builder<IAnimation>() .add(new AnimationTargetPoint(stem2, RotationAxis.X, 16F, 0, 15)) .add(new AnimationTargetPoint(stem2, RotationAxis.Y, -4F, 0, 7).setAllowInversion(false)) .add(new AnimationTargetPoint(stem2, RotationAxis.Y, 11F, 8, 15).setAllowInversion(false)) .add(new AnimationTargetPoint(stem2, RotationAxis.Z, -6F, 0, 15).setAllowInversion(false)) .add(new AnimationTargetAngle(stem2, RotationAxis.Y, 15.0F, 0, 15, true)) .add(new AnimationTargetAngle(stem2, RotationAxis.X, -15.0F, 0, 15, true).setAllowInversion(false)) .add(new AnimationTargetAngle(stem2, RotationAxis.Z, -60.0F, 0, 15, true)) .add(new AnimationTargetAngle(stem3, RotationAxis.X, 40.0F, 0, 15, true).setAllowInversion(false)) .add(new AnimationTargetAngle(head_base, RotationAxis.Z, 20.0F, 0, 8, true)) .add(new AnimationTargetAngle(head_base, RotationAxis.Z, -20.0F, 15, 18, true)) .add(new AnimationTargetAngle(mouth_base_lower, RotationAxis.X, -30.0F, 0, 12, true).setAllowInversion(false)) .add(new AnimationTargetAngle(mouth_base_lower, RotationAxis.X, -60.0F, 12, 15, true).setAllowInversion(false)) .add(new AnimationTargetAngle(mouth_base_upper, RotationAxis.X, -60.0F, 0, 12, true).setAllowInversion(false)) .add(new AnimationTargetAngle(mouth_base_upper, RotationAxis.X, -40.0F, 12, 15, true).setAllowInversion(false)) .add(new AnimationWave.AnimationWaveSin(RotationAxis.Z, 0.25F, 0.85F, 1.0F, tongue_base, tongue_mid, tongue_tip)) .build(); // applying the animation during the ModelBase#setLivingAnimations method: // note that the final parameter can be true to play the animation in the opposite direction IAnimation.Helper.applyAnimation(DEATH_ANIMATION, entity.deathTime, partialTick, 1.0F, 1.0F, 0.0F, false); Obviously there is a lot more that goes into it than just that, but it gives you an idea. You also have to consider that any of your Entity fields that you need to use to trigger / control the animation must be synced to the client. I typically use #setEntityState and #handleHealthUpdate to set animation flags, but you can use custom packets as well. http://i.imgur.com/NdrFdld.png[/img]
April 19, 20169 yr Author Do you know anyone that can make animations? Also I still can't get the entity to drop items, not sure why it isn't dropping them Not personally, but Jabelar has a tutorial on complex entity models with animation here. I can't really help you with your issues unless you give me something to work with. I need to see the entity, the loot table file, any custom loot table classes used in it (e.g. properties, conditions) and the loot table registration. The Source code is here Main Developer and Owner of Zero Quest Visit the Wiki for more information If I helped anyone, please give me a applaud and a thank you!
April 19, 20169 yr The resource path of your loot table's ResourceLocation must relative to assets/<domain>/loot_tables. You register a loot table for tetracraft:terrakon , but there is no assets/tetracraft/loot_tables/terrakon.json file. The actual path is assets/tetracraft/loot_tables/entities/terrakon.json, so register your loot table as tetracraft:entities/terrakon . Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
April 19, 20169 yr Author The resource path of your loot table's ResourceLocation must relative to assets/<domain>/loot_tables. You register a loot table for tetracraft:terrakon , but there is no assets/tetracraft/loot_tables/terrakon.json file. The actual path is assets/tetracraft/loot_tables/entities/terrakon.json, so register your loot table as tetracraft:entities/terrakon . Thanks! Now the entity is dropping items! Main Developer and Owner of Zero Quest Visit the Wiki for more information If I helped anyone, please give me a applaud and a thank you!
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.