Create CommandBuilder

This commit is contained in:
NGnius (Graham) 2020-05-01 14:50:55 -04:00
parent 934b542ea1
commit 5cb27b05c0
5 changed files with 249 additions and 8 deletions

View file

@ -0,0 +1,181 @@
using System;
using Svelto.ECS;
using GamecraftModdingAPI.Utility;
namespace GamecraftModdingAPI.Commands
{
/// <summary>
/// Custom Command builder.
/// </summary>
public class CommandBuilder
{
private string name;
private string description;
private short parameterCount;
private ICustomCommandEngine commandEngine;
/// <summary>
/// Create a new command builder.
/// </summary>
public CommandBuilder()
{
name = "";
description = null;
parameterCount = -1;
}
/// <summary>
/// Create and return a command builder.
/// </summary>
/// <returns>The builder.</returns>
public static CommandBuilder Builder()
{
return new CommandBuilder();
}
/// <summary>
/// Create a new command builder.
/// </summary>
/// <param name="name">The command name.</param>
/// <param name="description">The command description (shown in help).</param>
public CommandBuilder(string name, string description = null)
{
this.name = name;
this.description = description;
parameterCount = -1;
}
/// <summary>
/// Create and return a command builder.
/// If name and description are provided, this is equivalent to <code>Builder().Name(name).Description(description)</code>
/// </summary>
/// <param name="name">The command name.</param>
/// <param name="description">The command description (shown in help).</param>
/// <returns>The builder.</returns>
public static CommandBuilder Builder(string name, string description = null)
{
return new CommandBuilder(name, description);
}
/// <summary>
/// Name the command.
/// </summary>
/// <returns>The builder.</returns>
/// <param name="name">The command name.</param>
public CommandBuilder Name(string name)
{
this.name = name;
return this;
}
/// <summary>
/// Describe the command.
/// </summary>
/// <returns>The builder.</returns>
/// <param name="description">The command description (shown in help).</param>
public CommandBuilder Description(string description)
{
this.description = description;
return this;
}
/// <summary>
/// Set the action the command performs.
/// </summary>
/// <returns>The builder.</returns>
/// <param name="action">The action to perform when the command is called.</param>
public CommandBuilder Action(Action action)
{
parameterCount = 0;
commandEngine = new SimpleCustomCommandEngine(action, name, description);
return this;
}
/// <summary>
/// Set the action the command performs.
/// </summary>
/// <returns>The builder.</returns>
/// <param name="action">The action to perform when the command is called.</param>
/// <typeparam name="A">The 1st parameter's type.</typeparam>
public CommandBuilder Action<A>(Action<A> action)
{
parameterCount = 1;
commandEngine = new SimpleCustomCommandEngine<A>(action, name, description);
return this;
}
/// <summary>
/// Set the action the command performs.
/// </summary>
/// <returns>The builder.</returns>
/// <param name="action">The action to perform when the command is called.</param>
/// <typeparam name="A">The 1st parameter's type.</typeparam>
/// <typeparam name="B">The 2nd parameter's type.</typeparam>
public CommandBuilder Action<A,B>(Action<A,B> action)
{
parameterCount = 2;
commandEngine = new SimpleCustomCommandEngine<A,B>(action, name, description);
return this;
}
/// <summary>
/// Set the action the command performs.
/// </summary>
/// <returns>The builder.</returns>
/// <param name="action">The action to perform when the command is called.</param>
/// <typeparam name="A">The 1st parameter's type.</typeparam>
/// <typeparam name="B">The 2nd parameter's type.</typeparam>
/// <typeparam name="C">The 3rd parameter's type.</typeparam>
public CommandBuilder Action<A,B,C>(Action<A,B,C> action)
{
parameterCount = 3;
commandEngine = new SimpleCustomCommandEngine<A,B,C>(action, name, description);
return this;
}
/// <summary>
/// Build the command.
/// </summary>
/// <returns>The built command.</returns>
/// <param name="register">Automatically register the command with CommandManager.AddCommand()?</param>
public ICustomCommandEngine Build(bool register = true)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new InvalidOperationException("Command name must be defined before Build() is called");
}
if (commandEngine == null)
{
throw new InvalidOperationException("Command action must be defined before Build() is called");
}
if (string.IsNullOrWhiteSpace(description))
{
Logging.LogWarning($"Command {name} was built without a description");
}
if (register)
{
CommandManager.AddCommand(commandEngine);
Logging.MetaDebugLog($"Command {FullName()} was automatically registered");
}
return commandEngine;
}
/// <summary>
/// Get the full command name, in the form [name]::[description]::[# of parameters]
/// </summary>
/// <returns>The name.</returns>
public string FullName()
{
if (string.IsNullOrWhiteSpace(description))
{
return name + "::" + parameterCount;
}
return name + "::" + description + "::" + parameterCount;
}
}
}

View file

@ -22,6 +22,10 @@ namespace GamecraftModdingAPI.Commands
public static void AddCommand(ICustomCommandEngine engine)
{
if (ExistsCommand(engine))
{
Logging.LogWarning($"Command {engine.Name} already exists!");
}
_customCommands[engine.Name] = engine;
if (_lastEngineRoot != null)
{

View file

@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Version>0.2.2</Version>
<Version>1.0.0</Version>
<Authors>Exmods</Authors>
<PackageLicenseExpression>GNU General Public Licence 3+</PackageLicenseExpression>
<PackageProjectUrl>https://git.exmods.org/modtainers/GamecraftModdingAPI</PackageProjectUrl>

View file

@ -81,8 +81,67 @@ namespace GamecraftModdingAPI.Tests
// debug/test commands
if (Dependency.Hell("ExtraCommands"))
{
CommandManager.AddCommand(new SimpleCustomCommandEngine(() => { UnityEngine.Application.Quit(); },
"Exit", "Close Gamecraft without any prompts"));
CommandBuilder.Builder()
.Name("Exit")
.Description("Close Gamecraft immediately, without any prompts")
.Action(() => { UnityEngine.Application.Quit(); })
.Build();
CommandBuilder.Builder()
.Name("SetFOV")
.Description("Set the player camera's field of view")
.Action((float d) => { UnityEngine.Camera.main.fieldOfView = d; })
.Build();
CommandBuilder.Builder()
.Name("MoveLastBlock")
.Description("Move the most-recently-placed block, and any connected blocks by the given offset")
.Action((float x, float y, float z) => {
bool success = GamecraftModdingAPI.Blocks.Movement.MoveConnectedBlocks(
GamecraftModdingAPI.Blocks.BlockIdentifiers.LatestBlockID,
new Unity.Mathematics.float3(x, y, z));
if (!success)
{
GamecraftModdingAPI.Utility.Logging.CommandLogError("Blocks can only be moved in Build mode!");
}
}).Build();
CommandBuilder.Builder()
.Name("PlaceAluminium")
.Description("Place a block of aluminium at the given coordinates")
.Action((float x, float y, float z) => { Blocks.Placement.PlaceBlock(Blocks.BlockIDs.AluminiumCube, new Unity.Mathematics.float3(x, y, z)); })
.Build();
System.Random random = new System.Random(); // for command below
CommandBuilder.Builder()
.Name("RandomizeSignalsInputs")
.Description("Do the thing")
.Action(() => {
if (!GameState.IsSimulationMode())
{
Logging.CommandLogError("You must be in simulation mode for this to work!");
return;
}
Tasks.Repeatable task = new Tasks.Repeatable(
() => {
uint count = 0;
EGID[] eBlocks = Blocks.Signals.GetElectricBlocks();
for (uint i = 0u; i < eBlocks.Length; i++)
{
uint[] ids = Blocks.Signals.GetSignalIDs(eBlocks[i]);
for (uint j = 0u; j < ids.Length; j++)
{
Blocks.Signals.SetSignalByID(ids[j], (float)random.NextDouble());
count++;
}
}
Logging.MetaDebugLog($"Did the thing on {count} inputs");
},
() => { return GameState.IsSimulationMode(); });
Tasks.Scheduler.Schedule(task);
}).Build();
/*
CommandManager.AddCommand(new SimpleCustomCommandEngine<float>((float d) => { UnityEngine.Camera.main.fieldOfView = d; },
"SetFOV", "Set the player camera's field of view"));
CommandManager.AddCommand(new SimpleCustomCommandEngine<float, float, float>(
@ -98,10 +157,6 @@ namespace GamecraftModdingAPI.Tests
CommandManager.AddCommand(new SimpleCustomCommandEngine<float, float, float>(
(x, y, z) => { Blocks.Placement.PlaceBlock(Blocks.BlockIDs.AluminiumCube, new Unity.Mathematics.float3(x, y, z)); },
"PlaceAluminium", "Place a block of aluminium at the given coordinates"));
Analytics.DeltaDNAHelper.PlayerLifetimeParameters plp = new Analytics.DeltaDNAHelper.PlayerLifetimeParameters();
CommandManager.AddCommand(new SimpleCustomCommandEngine<string>(
(s) => { Analytics.DeltaDNAHelper.SendActionCompletedEvent(in plp, s.Replace(", ", " ")); },
"SendAnalyticsAction", "Send an analytics action"));
System.Random random = new System.Random(); // for command below
CommandManager.AddCommand(new SimpleCustomCommandEngine(
() => {
@ -127,6 +182,7 @@ namespace GamecraftModdingAPI.Tests
() => { return GameState.IsSimulationMode(); });
Tasks.Scheduler.Schedule(task);
}, "RandomizeSignalsInputs", "Do the thing"));
*/
}
// dependency test

View file

@ -38,7 +38,7 @@ PROJECT_NAME = "GamecraftModdingAPI"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = "v0.2.2"
PROJECT_NUMBER = "v1.0.0"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a