Skip to content

Commit

Permalink
Improve console commands (#1354)
Browse files Browse the repository at this point in the history
* Refactor Command

* Shorten some commands

* Refactor commands

* Fix little bug

* Make comments

* Replace structs with records

* Delete unecessary scripts

* Move IsExternalInit

* do stuff

* Change usage of hurt command

---------

Co-authored-by: Mechar418 <[email protected]>
  • Loading branch information
iamteapot422 and iamteapot422 authored Dec 1, 2023
1 parent 63eeeab commit 5ece8c0
Show file tree
Hide file tree
Showing 25 changed files with 347 additions and 707 deletions.
7 changes: 7 additions & 0 deletions Assets/Scripts/SS3D/Core/IsExternalInit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace System.Runtime.CompilerServices
{
/// <summary>
/// Necessary for Unity to use init and record, since it's only available in .NET 5
/// </summary>
public class IsExternalInit {}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using SS3D.Systems.Inventory.Containers;
using FishNet.Connection;
using SS3D.Permissions;
using System;

namespace SS3D.Systems.IngameConsoleSystem.Commands
{
Expand All @@ -18,73 +19,60 @@ namespace SS3D.Systems.IngameConsoleSystem.Commands
/// </summary>
public class AddHandCommand : Command
{
public override string LongDescription => "add (ckey) [(position) (rotation)]\n Position and rotation are float arrays and written as x y z";
public override string ShortDescription => "add hand to user";
public override string ShortDescription => "Add hand to user";
public override string Usage => "(ckey) [(position) (rotation)] \nPosition and rotation are float arrays and written as x y z";
public override ServerRoleTypes AccessLevel => ServerRoleTypes.Administrator;

public override CommandType Type => CommandType.Server;

private record CalculatedValues(Player Player, Entity Entity, Vector3 Position, Vector3 Rotation) : ICalculatedValues;

public override string Perform(string[] args, NetworkConnection conn)
{
CheckArgsResponse checkArgsResponse = CheckArgs(args);
if (checkArgsResponse.IsValid == false)
return checkArgsResponse.InvalidArgs;

string ckey = args[0];

// default transform for hand.
Vector3 position = new Vector3(0.5f, 0.7f, 0);
Vector3 rotation = new Vector3(-50, -270, 90);

if (args.Length > 1)
{
position = new Vector3(float.Parse(args[1]), float.Parse(args[2]), float.Parse(args[3]));
rotation = new Vector3(float.Parse(args[4]), float.Parse(args[5]), float.Parse(args[6]));
}

Player Player = Subsystems.Get<PlayerSystem>().GetPlayer(ckey);
Entity entity = Subsystems.Get<EntitySystem>().GetSpawnedEntity(Player);

if (!ReceiveCheckResponse(args, out CheckArgsResponse response, out CalculatedValues values)) return response.InvalidArgs;

GameObject leftHandPrefab = Assets.Get<GameObject>((int)AssetDatabases.BodyParts, (int)BodyPartsIds.HumanHandLeft);
GameObject leftHandObject = GameObject.Instantiate(leftHandPrefab, entity.transform);
leftHandObject.transform.localPosition = position;
leftHandObject.transform.localEulerAngles = rotation;

Hand leftHand = leftHandObject.GetComponent<Hand>();
InstanceFinder.ServerManager.Spawn(leftHandObject, Player.Owner);

Hands hands = entity.GetComponent<Hands>();
HumanInventory inventory = entity.GetComponent<HumanInventory>();
inventory.TryAddContainer(leftHandObject.GetComponent<AttachedContainer>());
hands.AddHand(leftHand);
GameObject leftHandObject = GameObject.Instantiate(leftHandPrefab, values.Entity.transform);
leftHandObject.transform.localPosition = values.Position;
leftHandObject.transform.localEulerAngles = values.Rotation;
InstanceFinder.ServerManager.Spawn(leftHandObject, values.Player.Owner);
values.Entity.GetComponent<HumanInventory>().TryAddContainer(leftHandObject.GetComponent<AttachedContainer>());
values.Entity.GetComponent<Hands>().AddHand(leftHandObject.GetComponent<Hand>());

return "hand added";
}
protected override CheckArgsResponse CheckArgs(string[] args)
{
CheckArgsResponse response = new CheckArgsResponse();
if (args.Length != 1 && args.Length != 7)
{
response.IsValid = false;
response.InvalidArgs = "Invalid number of arguments";
return response;
}
CheckArgsResponse response = new();
if (args.Length != 1 && args.Length != 7) return response.MakeInvalid("Invalid number of arguments");

string ckey = args[0];
Player player = Subsystems.Get<PlayerSystem>().GetPlayer(ckey);
if (player == null)
if (player == null) return response.MakeInvalid("This player doesn't exist");

Entity entity = Subsystems.Get<EntitySystem>().GetSpawnedEntity(player);
if (entity == null) return response.MakeInvalid("This entity doesn't exist");

Vector3 position;
Vector3 rotation;
if (args.Length > 1)
{
response.IsValid = false;
response.InvalidArgs = "This player doesn't exist";
return response;
try
{
position = new(float.Parse(args[1]), float.Parse(args[2]), float.Parse(args[3]));
rotation = new(float.Parse(args[4]), float.Parse(args[5]), float.Parse(args[6]));
}
catch (FormatException)
{
return response.MakeInvalid("Incorrect position/rotation format");
}
}
Entity entityToKill = Subsystems.Get<EntitySystem>().GetSpawnedEntity(player);
if (entityToKill == null)
else
{
response.IsValid = false;
response.InvalidArgs = "This entity doesn't exist";
return response;
position = new(0.5f, 0.7f, 0);
rotation = new(-50, -270, 90);
}
response.IsValid = true;
return response;

return response.MakeValid(new CalculatedValues(player, entity, position, rotation));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,51 +8,30 @@ namespace SS3D.Systems.IngameConsoleSystem.Commands
{
public class ChangePermsCommand : Command
{
public override string LongDescription => "changeperms (user ckey) (required role)";
public override string ShortDescription => "Change user permission";
public override string Usage => "(user ckey) (required role)";
public override ServerRoleTypes AccessLevel => ServerRoleTypes.Administrator;

public override CommandType Type => CommandType.Server;

private record CalculatedValues(string Ckey, ServerRoleTypes Role) : ICalculatedValues;

public override string Perform(string[] args, NetworkConnection conn = null)
{
CheckArgsResponse checkArgsResponse = CheckArgs(args);
if (checkArgsResponse.IsValid == false)
return checkArgsResponse.InvalidArgs;
string ckey = args[0];
string role = args[1];
ServerRoleTypes foundRole = FindRole(role);
Subsystems.Get<PermissionSystem>().ChangeUserPermission(ckey, foundRole);
return "Done";
if (!ReceiveCheckResponse(args, out CheckArgsResponse response, out CalculatedValues values)) return response.InvalidArgs;

Subsystems.Get<PermissionSystem>().ChangeUserPermission(values.Ckey, values.Role);
return "Permission changed to " + args[1];
}

protected override CheckArgsResponse CheckArgs(string[] args)
{
CheckArgsResponse response = new CheckArgsResponse();
if (args.Length != 2)
{
response.IsValid = false;
response.InvalidArgs = "Invalid number of arguments";
return response;
}
CheckArgsResponse response = new();
if (args.Length != 2) return response.MakeInvalid("Invalid number of arguments");

string ckey = args[0];
bool isFound = Subsystems.Get<PermissionSystem>().TryGetUserRole(ckey, out _);
if (!isFound)
{
response.IsValid = false;
response.InvalidArgs = "Ckey doesn't have any permissions";
return response;
}

string role = args[1];
if (FindRole(role) == ServerRoleTypes.None)
{
response.IsValid = false;
response.InvalidArgs = "Role doesn't exist";
return response;
}
response.IsValid = true;
return response;
ServerRoleTypes role = FindRole(args[1]);
if (role == ServerRoleTypes.None) return response.MakeInvalid("Role doesn't exist");

return response.MakeValid(new CalculatedValues(args[0], role));
}

private ServerRoleTypes FindRole(string name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,45 @@ protected struct CheckArgsResponse
{
public bool IsValid;
public string InvalidArgs;
public ICalculatedValues CalculatedValues;
public CheckArgsResponse MakeInvalid(string invalidArgs)
{
InvalidArgs = invalidArgs;
IsValid = false;
return this;
}
public CheckArgsResponse MakeValid(ICalculatedValues calculatedValues)
{
CalculatedValues = calculatedValues;
IsValid = true;
return this;
}
}
/// <summary>
/// Struct to transfer calculated values between CheckArgs and Perform methods
/// </summary>
protected interface ICalculatedValues { }

/// <summary>
/// Is the command going to be executed server or client side ?
/// </summary>
public abstract CommandType Type { get; }

/// <summary>
/// Desription, that will be shown after "help" command
/// </summary>
public abstract string ShortDescription { get; }

public abstract string LongDescription { get; }
/// <summary>
/// Detailed description of the command. Will be shown after "help (command name)" command
/// </summary>
public virtual string LongDescription => ShortDescription;

/// <summary>
/// how to use the command.
/// Syntax for writing usage: arguments in () - necessary; [] - optional; {} - list of arguments with undefined size
/// </summary>
public virtual string Usage => "";

/// <summary>
/// The requested role to be able to perform this command.
Expand All @@ -39,5 +68,16 @@ protected struct CheckArgsResponse
/// </summary>
protected abstract CheckArgsResponse CheckArgs(string[] args);
protected const string WrongArgsText = "Wrong args. Type \"(command) help\"";

/// <summary>
/// Store CheckArgs response and get if response is valid.
/// </summary>
/// <returns>If respons is valid</returns>
protected bool ReceiveCheckResponse<T>(string[] args, out CheckArgsResponse response, out T calculatedValues) where T: ICalculatedValues
{
response = CheckArgs(args);
calculatedValues = (T)response.CalculatedValues;
return response.IsValid;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,71 +9,40 @@ namespace SS3D.Systems.IngameConsoleSystem.Commands
{
public class DestroyBodyPartCommand : Command
{
public override string LongDescription => "Destroy a given body part, unattached from a player. \n " +
"Usage : destroybodypart [game object name]";
public override string LongDescription => "Destroy a given body part, unattached from a player";
public override string ShortDescription => "Hit me daddy";
public override string Usage => "(game object name)";
public override ServerRoleTypes AccessLevel => ServerRoleTypes.Administrator;
public override CommandType Type => CommandType.Server;

private record CalculatedValues(IEnumerable<BodyPart> BodyParts) : ICalculatedValues;

[Server]
public override string Perform(string[] args, NetworkConnection conn = null)
{
CheckArgsResponse checkArgsResponse = CheckArgs(args);
if (checkArgsResponse.IsValid == false)
return checkArgsResponse.InvalidArgs;
if (!ReceiveCheckResponse(args, out CheckArgsResponse response, out CalculatedValues values)) return response.InvalidArgs;

string gameObjectName = args[0];

GameObject go = GameObject.Find(gameObjectName);
IEnumerable<BodyPart> bodyParts = go.GetComponentsInChildren<BodyPart>().Where(x => x.gameObject.name == gameObjectName);
BodyPart bodyPart = bodyParts.First();

bodyPart.InflictDamageToAllLayer(new Health.DamageTypeQuantity(Health.DamageType.Heat, 10000000000));
values.BodyParts.First().InflictDamageToAllLayer(new (Health.DamageType.Heat, 10000000000));
return "BodyPart hurt";
}

[Server]
protected override CheckArgsResponse CheckArgs(string[] args)
{
CheckArgsResponse response = new();

CheckArgsResponse response = new CheckArgsResponse();

if (args.Length != 1)
{
response.IsValid = false;
response.InvalidArgs = "Invalid number of arguments";
return response;
}

if (args.Length != 1) return response.MakeInvalid("Invalid number of arguments");

string gameObjectName = args[0];

GameObject go = GameObject.Find(gameObjectName);
if (go == null)
{
response.IsValid = false;
response.InvalidArgs = "No bodypart with this name";
return response;
}

IEnumerable<BodyPart> bodyParts = go.GetComponentsInChildren<BodyPart>().Where(x => x.gameObject.name == gameObjectName);
if (go == null) return response.MakeInvalid("No bodypart with this name");

if (bodyParts.Count() == 0)
{
response.IsValid = false;
response.InvalidArgs = "No bodypart with this name";
return response;
}
BodyPart[] bodyParts = go.GetComponentsInChildren<BodyPart>().Where(x => x.gameObject.name == gameObjectName).ToArray();
if (!bodyParts.Any()) return response.MakeInvalid("No bodypart with this name");

if (bodyParts.Count() != 1)
{
response.IsValid = false;
response.InvalidArgs = "Multiple body parts with the same name, ambiguous command";
return response;
}
if (bodyParts.Length != 1) return response.MakeInvalid("Multiple body parts with the same name, ambiguous command");

response.IsValid = true;
return response;
return response.MakeValid(new CalculatedValues(bodyParts));
}
}
}
Expand Down
Loading

0 comments on commit 5ece8c0

Please sign in to comment.