Jump to content

Recommended Posts

Posted

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!

  • Replies 83
  • Created
  • Last Reply

Top Posters In This Topic

Posted

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.

Posted

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!

Posted

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.

Posted

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!

Posted

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.

Posted

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!

Posted

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.

Posted

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!

Posted

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.

Posted

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.

Posted

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!

Posted

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.

Posted

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!

Posted

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.

Posted

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!

Posted

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.

Posted

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.

Posted

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!

Posted

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.

Posted

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements




×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.