Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
414 changes: 4 additions & 410 deletions Essentials/Commands/CleanupModule.cs

Large diffs are not rendered by default.

66 changes: 66 additions & 0 deletions Essentials/Conditions/Condition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using System.Reflection;
using Sandbox.Game.Entities;
using Torch.Commands;

namespace Essentials.Conditions
{
public class Condition
{
public string Command;
public string InvertCommand;
public string HelpText;
private MethodInfo _method;
public readonly ParameterInfo Parameter;

public Condition(MethodInfo evalMethod, ConditionAttribute attribute)
{
Command = attribute.Command;
InvertCommand = attribute.InvertCommand;
HelpText = attribute.HelpText;
_method = evalMethod;
if (_method.ReturnType != typeof(bool))
throw new TypeLoadException("Condition does not return a bool!");
var p = _method.GetParameters();
if (p.Length < 1 || p[0].ParameterType != typeof(MyCubeGrid))
throw new TypeLoadException("Condition does not accept MyCubeGrid as first parameter");
if (p.Length > 2)
throw new TypeLoadException("Condition can only have two parameters");
if (p.Length == 1)
Parameter = null;
else
Parameter = p[1];
}

public bool? Evaluate(MyCubeGrid grid, string arg, bool invert, CommandContext context)
{
bool result;
if (!string.IsNullOrEmpty(arg) && Parameter == null)
{
context.Respond($"Condition does not accept an argument. Cannot continue!");
return null;
}
if (string.IsNullOrEmpty(arg) && Parameter != null && !Parameter.HasDefaultValue)
{
context.Respond($"Condition requires an argument! {Parameter.ParameterType.Name}: {Parameter.Name} Not supplied, cannot continue!");
return null;
}
if (Parameter != null && !string.IsNullOrEmpty(arg))
{
if (!arg.TryConvert(Parameter.ParameterType, out object val))
{
context.Respond($"Could not parse argument!");
return null;
}

result = (bool)_method.Invoke(null, new[] { grid, val });
}
else
{
result = (bool)_method.Invoke(null, new object[] { grid });
}

return result != invert;
}
}
}
19 changes: 19 additions & 0 deletions Essentials/Conditions/ConditionAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;

namespace Essentials
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class ConditionAttribute : Attribute
{
public string Command;
public string InvertCommand;
public string HelpText;

public ConditionAttribute(string command, string invertCommand = null, string helpText = null)
{
Command = command;
InvertCommand = invertCommand;
HelpText = helpText;
}
}
}
10 changes: 10 additions & 0 deletions Essentials/Conditions/ConditionModule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;

namespace Essentials
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class ConditionModule : Attribute
{

}
}
163 changes: 163 additions & 0 deletions Essentials/Conditions/ConditionsChecker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Essentials.Conditions;
using Sandbox.Game.Entities;
using Torch.Commands;

namespace Essentials.Commands
{
public static class ConditionsChecker
{
private static List<Condition> _conditionLookup;

public static void Init()
{
_conditionLookup = new List<Condition>();

var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany((x) =>
{
try
{
return x.GetTypes();
}
catch (Exception e) // ignored
{
return new Type[0];
}
}).Where(t => t.IsDefined(typeof(ConditionModule)));

foreach (var type in types)
{
var methods = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
foreach (var m in methods)
{
var a = m.GetCustomAttribute<ConditionAttribute>();
if (a == null)
continue;

var c = new Condition(m, a);

_conditionLookup.Add(c);
}
}
}

public static List<Condition> GetAllConditions()
{
return _conditionLookup;
}

public static IEnumerable<MyCubeGrid> ScanConditions(CommandContext context, IReadOnlyList<string> args)
{
var conditions = new List<Func<MyCubeGrid, bool?>>();

for (var i = 0; i < args.Count; i++)
{
string parameter;
if (i + 1 >= args.Count)
{
parameter = null;
}
else
{
parameter = args[i + 1];
}

var arg = args[i];

if (parameter != null)
{
//parameter is the name of a command. Assume this command requires no parameters
if (_conditionLookup.Any(c => parameter.Equals(c.Command, StringComparison.CurrentCultureIgnoreCase) || parameter.Equals(c.InvertCommand, StringComparison.CurrentCultureIgnoreCase)))
{
parameter = null;
}
//next string is a parameter, so pass it to the condition and skip it next loop
else
i++;
}

bool found = false;

foreach (var condition in _conditionLookup)
{
if (arg.Equals(condition.Command, StringComparison.CurrentCultureIgnoreCase))
{
conditions.Add(g => condition.Evaluate(g, parameter, false, context));
found = true;
break;
}
else if (arg.Equals(condition.InvertCommand, StringComparison.CurrentCultureIgnoreCase))
{
conditions.Add(g => condition.Evaluate(g, parameter, true, context));
found = true;
break;
}
}
if (!found)
{
context.Respond($"Unknown argument '{arg}'");
return new List<MyCubeGrid>();
}
}

//default scan to find grids without pilots
if (!args.Contains("haspilot", StringComparer.CurrentCultureIgnoreCase))
conditions.Add(g => !ConditionsImplementations.Piloted(g));


var resultList = new List<MyCubeGrid>();
Parallel.ForEach(MyCubeGridGroups.Static.Logical.Groups, (group) =>
{
//if (group.Nodes.All(grid => conditions.TrueForAll(func => func(grid.NodeData))))
bool res = true;
foreach (var node in group.Nodes)
{
if (node.NodeData.Projector != null)
continue;

foreach (var c in conditions)
{
bool? r = c.Invoke(node.NodeData);
if (r == null)
{
return;
}

if (r == true)
{
continue;
}

res = false;
break;
}

if (!res)
{
break;
}
}

if (res)
{
lock (resultList)
{
foreach (var grid in group.Nodes.Where(x => x.NodeData.Projector == null))
{
resultList.Add(grid.NodeData);
}
}
}

});

return resultList;
}

}
}
Loading