Home > database >  How to create a class with a customizable codeblock?
How to create a class with a customizable codeblock?

Time:05-31

I am currently trying to make a console for my game, and decided making a class called Command which can then be used to create commands easily was a good idea. I made the class but of course these classes are going to do vastly different thing, as such I was thinking of making a property which would basically act like a function, aka I could construct a command with properties commandName, arguments and then the customizable code block which would then be executed upon writing the command. How would I go about this?

public class Command : MonoBehaviour
{
    string inputCommand;
    int arguments;

    void execution()
    {
      //this is where to codeblock to be executed upon typing the command would go
    }
}

Edit: I made what seems to be progress but still can't seem to get it right. Also each action needs to be able to have different amounts of arguments (for example "runes.add" needs an integer for runes to add and "updatestore" needs none). Any help would be greatly appreciated

public class Command : MonoBehaviour
{
    public string InputCommand { get; set; }
    public int Arguments { get; set; }
    public Action ExecuteAction { get; set; }

}

public class Commands
{
    public List<Command> commandCollection = new List<Command>()
    {
        new Command()
        {
            InputCommand = "",
            Arguments = 1,
            ExecuteAction = new Action(()=>{code to execute goes here})
        }
    };
}

CodePudding user response:

First of all, you shouldn't derive Command from MonoBehaviour if you want to construct Command with object constructor (not Instantiate).

I think you should make abstract Command class and create commands as classes derived from Command class.

Also what you call "code block" can be done using polymorphism.

So, what you need to do:

  1. Create Command class
public abstract class Command
{
    public abstract void Execute(string[] args);
}

Execute method is abstract so we can override realisation of this method in subclasses. This methods takes an array of command arguments as the parameter.

  1. Create some test commands
public class TestCommand : Command
{
    public override void Execute(string[] args)
    {
        Debug.Log("Test command invoked, passed parameters count: "   args.Length);
    }
}
  1. Create CommandRegistry class (it's your Commands class)
public class CommandRegistry
{
    private Dictionary<string, Command> _commands;
    
    public CommandRegistry()
    {
        _commands = new Dictionary<string, Command>();
    }

    public void RegisterCommand(string name, Command command)
    {
        // You should also check here if command already exists 
        if(_commands.ContainsKey(name))
        {
                // Print error here or throw an exception
                return;
        }

        _commands[name] = command;
    }

    public void RegisterAllCommands()
    {
        // Add here every new command to register it
        RegisterCommand("test", new TestCommand());
    }

    // Returns false if command not found
    public bool ExecuteCommand(string commandName, string[] args)
    { 
        if(_commands.ContainsKey(commandName) == false)
            return false;

        _commands[commandName].Execute(args);
        return true;
    }
}

That's it. You need to call ExecuteCommand method to execute a command and pass a name and arguments of the command.

You should check argument count inside a Command.Execute method.

Also if you need to access your game methods/fields (for example to add runes) you should provide static access to this fields/methods or create something like CommandContext class (or GameContext).

An instance of this class will be passed to every command and it contains references to objects that can do things like adding runes.

Then you will need to add a new parameter (CommandContext) to GameRegistry.ExecuteCommand and Command.Execute method.

  • Related