Get command system working, permissions system and ModAPI extensions in progress
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using VRage.Game;
|
||||
using VRage.Game.ModAPI;
|
||||
|
||||
namespace Torch.API
|
||||
{
|
||||
@@ -12,7 +14,9 @@ namespace Torch.API
|
||||
Dictionary<ulong, IPlayer> Players { get; }
|
||||
List<IChatItem> Chat { get; }
|
||||
void SendMessage(string message);
|
||||
void SendMessage(string message, long playerId, string author = "Server", string font = MyFontEnum.Blue);
|
||||
void KickPlayer(ulong id);
|
||||
void BanPlayer(ulong id, bool banned = true);
|
||||
IMyPlayer GetPlayerBySteamId(ulong id);
|
||||
}
|
||||
}
|
@@ -8,7 +8,7 @@ namespace Torch.API
|
||||
public interface IPluginManager : IEnumerable<ITorchPlugin>
|
||||
{
|
||||
void UpdatePlugins();
|
||||
void LoadPlugins();
|
||||
void Init();
|
||||
void UnloadPlugins();
|
||||
}
|
||||
}
|
@@ -11,6 +11,7 @@ namespace Torch.API
|
||||
event Action SessionLoaded;
|
||||
IMultiplayer Multiplayer { get; }
|
||||
IPluginManager Plugins { get; }
|
||||
Version Version { get; }
|
||||
void Invoke(Action action);
|
||||
void InvokeBlocking(Action action);
|
||||
Task InvokeAsync(Action action);
|
||||
|
39
Torch.API/ModAPI/Ingame/GridExtensions.cs
Normal file
39
Torch.API/ModAPI/Ingame/GridExtensions.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Sandbox.Game.Entities.Blocks;
|
||||
using Sandbox.ModAPI.Ingame;
|
||||
using VRage.Game.ModAPI.Ingame;
|
||||
|
||||
namespace Torch.API.ModAPI.Ingame
|
||||
{
|
||||
public static class GridExtensions
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static class PistonExtensions
|
||||
{
|
||||
public static IMyCubeGrid GetConnectedGrid(this IMyPistonBase pistonBase)
|
||||
{
|
||||
if (!pistonBase.IsAttached)
|
||||
return null;
|
||||
|
||||
return ((Sandbox.ModAPI.IMyPistonBase)pistonBase).TopGrid;
|
||||
}
|
||||
}
|
||||
|
||||
public static class RotorExtensions
|
||||
{
|
||||
public static IMyCubeGrid GetConnectedGrid(this IMyMotorStator rotorBase)
|
||||
{
|
||||
if (!rotorBase.IsAttached)
|
||||
return null;
|
||||
|
||||
return ((Sandbox.ModAPI.IMyMotorStator)rotorBase).RotorGrid;
|
||||
}
|
||||
}
|
||||
}
|
13
Torch.API/ModAPI/TorchAPI.cs
Normal file
13
Torch.API/ModAPI/TorchAPI.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Torch.API.ModAPI
|
||||
{
|
||||
public static class TorchAPI
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@@ -38,6 +38,24 @@
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="Sandbox.Common">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\Sandbox.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Sandbox.Game">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\Sandbox.Game.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Sandbox.Graphics">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\Sandbox.Graphics.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SpaceEngineers.Game">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\SpaceEngineers.Game.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SpaceEngineers.ObjectBuilders">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\SpaceEngineers.ObjectBuilders.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SpaceEngineers.ObjectBuilders.XmlSerializers">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\SpaceEngineers.ObjectBuilders.XmlSerializers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
@@ -55,11 +73,41 @@
|
||||
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="VRage.Audio">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Audio.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="VRage.Game">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Game.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="VRage.Game.XmlSerializers">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Game.XmlSerializers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="VRage.Input">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Input.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="VRage.Library, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Library.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="VRage.Math">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Math.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="VRage.Native">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Native.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="VRage.OpenVRWrapper">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.OpenVRWrapper.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="VRage.Render">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Render.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="VRage.Render11">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Render11.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="VRage.Scripting">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Scripting.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ConnectionState.cs" />
|
||||
@@ -70,6 +118,8 @@
|
||||
<Compile Include="ITorchPlugin.cs" />
|
||||
<Compile Include="IServerControls.cs" />
|
||||
<Compile Include="ITorchBase.cs" />
|
||||
<Compile Include="ModAPI\Ingame\GridExtensions.cs" />
|
||||
<Compile Include="ModAPI\TorchAPI.cs" />
|
||||
<Compile Include="PluginAttribute.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration.Install;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -34,6 +36,18 @@ namespace Torch.Server
|
||||
|
||||
if (args.FirstOrDefault() == "-svcinstall")
|
||||
{
|
||||
/* Working on installing the service properly instead of with sc.exe
|
||||
_log.Info("Installing service");
|
||||
var installer = new TorchServiceInstaller();
|
||||
installer.Context = new InstallContext(Path.Combine(Directory.GetCurrentDirectory(), "svclog.log"), null);
|
||||
installer.Context.Parameters.Add("name", "Torch DS");
|
||||
installer.Install(new Hashtable
|
||||
{
|
||||
{"name", "Torch DS"}
|
||||
|
||||
});
|
||||
_log.Info("Service Installed");*/
|
||||
|
||||
var runArgs = string.Join(" ", args.Skip(1));
|
||||
_log.Info($"Installing Torch as a service with arguments '{runArgs}'");
|
||||
var startInfo = new ProcessStartInfo
|
||||
|
@@ -27,14 +27,22 @@ namespace Torch.Server
|
||||
{
|
||||
public Thread GameThread { get; private set; }
|
||||
public bool IsRunning { get; private set; }
|
||||
public bool IsService { get; set; }
|
||||
public bool IsService { get; }
|
||||
public string InstancePath { get; private set; }
|
||||
public string InstanceName { get; }
|
||||
|
||||
public event Action SessionLoading;
|
||||
|
||||
private readonly AutoResetEvent _stopHandle = new AutoResetEvent(false);
|
||||
|
||||
internal TorchServer()
|
||||
internal TorchServer(string instanceName = null)
|
||||
{
|
||||
if (instanceName != null)
|
||||
{
|
||||
IsService = true;
|
||||
InstanceName = instanceName;
|
||||
}
|
||||
|
||||
MySession.OnLoading += OnSessionLoading;
|
||||
}
|
||||
|
||||
@@ -59,6 +67,8 @@ namespace Torch.Server
|
||||
};
|
||||
var gameVersion = MyPerGameSettings.BasicGameInfo.GameVersion;
|
||||
MyFinalBuildConstants.APP_VERSION = gameVersion ?? 0;
|
||||
|
||||
InstancePath = InstanceName != null ? GetInstancePath(true, InstanceName) : GetInstancePath();
|
||||
}
|
||||
|
||||
private void OnSessionLoading()
|
||||
@@ -87,7 +97,7 @@ namespace Torch.Server
|
||||
Environment.SetEnvironmentVariable("SteamAppId", MyPerServerSettings.AppId.ToString());
|
||||
|
||||
Log.Trace("Invoking RunMain");
|
||||
try { Reflection.InvokeStaticMethod(typeof(DedicatedServer), "RunMain", "Torch", null, IsService, true); }
|
||||
try { Reflection.InvokeStaticMethod(typeof(DedicatedServer), "RunMain", InstanceName, InstancePath, false, true); }
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
@@ -131,6 +141,14 @@ namespace Torch.Server
|
||||
IsRunning = false;
|
||||
}
|
||||
|
||||
private string GetInstancePath(bool isService = false, string instanceName = "Torch")
|
||||
{
|
||||
if (isService)
|
||||
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), MyPerServerSettings.GameDSName, instanceName);
|
||||
|
||||
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), MyPerServerSettings.GameDSName);
|
||||
}
|
||||
|
||||
private void CleanupProfilers()
|
||||
{
|
||||
typeof(MyRenderProfiler).GetField("m_threadProfiler", BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, null);
|
||||
|
@@ -12,7 +12,7 @@ namespace Torch.Server
|
||||
class TorchService : ServiceBase
|
||||
{
|
||||
public const string Name = "Torch (SEDS)";
|
||||
private readonly TorchServer _server = new TorchServer();
|
||||
private TorchServer _server;
|
||||
private static Logger _log = LogManager.GetLogger("Torch");
|
||||
|
||||
public TorchService()
|
||||
@@ -30,9 +30,9 @@ namespace Torch.Server
|
||||
protected override void OnStart(string[] args)
|
||||
{
|
||||
base.OnStart(args);
|
||||
_server = new TorchServer("Torch");
|
||||
_server.Init();
|
||||
_server.RunArgs = args;
|
||||
_server.IsService = true;
|
||||
Task.Run(() => _server.Start());
|
||||
}
|
||||
|
||||
|
@@ -11,7 +11,7 @@ using System.Threading.Tasks;
|
||||
namespace Torch.Server
|
||||
{
|
||||
[RunInstaller(true)]
|
||||
class TorchServiceInstaller : Installer
|
||||
public class TorchServiceInstaller : Installer
|
||||
{
|
||||
private ServiceInstaller _serviceInstaller;
|
||||
|
||||
|
@@ -8,7 +8,7 @@ namespace Torch.Commands
|
||||
{
|
||||
public class CategoryAttribute : Attribute
|
||||
{
|
||||
public string[] Path { get; }
|
||||
public List<string> Path { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies where to add the class's commands in the command tree.
|
||||
@@ -16,7 +16,7 @@ namespace Torch.Commands
|
||||
/// <param name="path">Command path, e.g. "/admin config" -> "admin, config"</param>
|
||||
public CategoryAttribute(params string[] path)
|
||||
{
|
||||
Path = path;
|
||||
Path = path.Select(i => i.ToLower()).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Torch.API;
|
||||
@@ -12,7 +13,7 @@ namespace Torch.Commands
|
||||
public string Description { get; }
|
||||
public string HelpText { get; }
|
||||
public Type Module { get; }
|
||||
public string[] Path { get; }
|
||||
public List<string> Path { get; } = new List<string>();
|
||||
public ITorchPlugin Plugin { get; }
|
||||
private readonly MethodInfo _method;
|
||||
|
||||
@@ -31,16 +32,13 @@ namespace Torch.Commands
|
||||
|
||||
_method = commandMethod;
|
||||
Module = commandMethod.DeclaringType;
|
||||
var path = commandAttribute.Path;
|
||||
|
||||
if (moduleAttribute != null)
|
||||
{
|
||||
var modPath = moduleAttribute.Path;
|
||||
var comPath = commandAttribute.Path;
|
||||
path = new string[modPath.Length + comPath.Length];
|
||||
modPath.CopyTo(path, 0);
|
||||
comPath.CopyTo(path, modPath.Length);
|
||||
Path.AddRange(moduleAttribute.Path);
|
||||
}
|
||||
Path = path;
|
||||
Path.AddRange(commandAttribute.Path);
|
||||
|
||||
Name = commandAttribute.Name;
|
||||
Description = commandAttribute.Description;
|
||||
HelpText = commandAttribute.HelpText;
|
||||
@@ -50,7 +48,7 @@ namespace Torch.Commands
|
||||
{
|
||||
var moduleInstance = (CommandModule)Activator.CreateInstance(Module);
|
||||
moduleInstance.Context = context;
|
||||
_method.Invoke(moduleInstance, new object[0]);
|
||||
_method.Invoke(moduleInstance, null);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Torch.Commands
|
||||
{
|
||||
@@ -7,14 +9,16 @@ namespace Torch.Commands
|
||||
public string Name { get; }
|
||||
public string Description { get; }
|
||||
public string HelpText { get; }
|
||||
public string[] Path { get; }
|
||||
public List<string> Path { get; } = new List<string>();
|
||||
|
||||
public CommandAttribute(string name, string description = "", string helpText = "", params string[] path)
|
||||
public CommandAttribute(string name, string description = "", string helpText = null, params string[] path)
|
||||
{
|
||||
Name = name;
|
||||
Description = description;
|
||||
HelpText = helpText;
|
||||
Path = path.Length > 0 ? path : new [] {name.ToLower()};
|
||||
HelpText = helpText ?? description;
|
||||
|
||||
Path.AddRange(path.Select(x => x.ToLower()));
|
||||
Path.Add(name.ToLower());
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,36 +1,34 @@
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Torch.API;
|
||||
using VRage.Game;
|
||||
using VRage.Game.ModAPI;
|
||||
|
||||
namespace Torch.Commands
|
||||
{
|
||||
public struct CommandContext
|
||||
public class CommandContext
|
||||
{
|
||||
public ITorchPlugin Plugin { get; }
|
||||
public ITorchBase Torch { get; }
|
||||
public IMyPlayer Player { get; }
|
||||
public string[] Args { get; }
|
||||
public List<string> Args { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Splits the argument by single words and quoted blocks.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public CommandContext(ITorchBase torch, ITorchPlugin plugin, IMyPlayer player, params string[] args)
|
||||
public CommandContext(ITorchBase torch, ITorchPlugin plugin, IMyPlayer player, List<string> args = null)
|
||||
{
|
||||
Torch = torch;
|
||||
Plugin = plugin;
|
||||
Player = player;
|
||||
Args = args;
|
||||
Args = args ?? new List<string>();
|
||||
}
|
||||
|
||||
/*
|
||||
var split = Regex.Split(Args, "(\"[^\"]+\"|\\S+)");
|
||||
for (var i = 0; i < split.Length; i++)
|
||||
public void Respond(string message, string sender = "Server", string font = MyFontEnum.Blue)
|
||||
{
|
||||
split[i] = Regex.Replace(split[i], "\"", "");
|
||||
}
|
||||
|
||||
return split;*/
|
||||
Torch.Multiplayer.SendMessage(message, Player.PlayerID, sender, font);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,47 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using NLog;
|
||||
using Torch.API;
|
||||
using Torch.Managers;
|
||||
using VRage.Game.ModAPI;
|
||||
using VRage.Network;
|
||||
|
||||
namespace Torch.Commands
|
||||
{
|
||||
public class PermissionGroup
|
||||
{
|
||||
public List<ulong> Members { get; }
|
||||
public List<Permission> Permissions { get; }
|
||||
}
|
||||
|
||||
public class PermissionUser
|
||||
{
|
||||
public ulong SteamID { get; }
|
||||
public List<PermissionGroup> Groups { get; }
|
||||
public List<Permission> Permissions { get; }
|
||||
}
|
||||
|
||||
public class Permission
|
||||
{
|
||||
public string[] Path { get; }
|
||||
public bool Allow { get; }
|
||||
}
|
||||
|
||||
public class CommandManager
|
||||
{
|
||||
public ITorchBase Torch { get; }
|
||||
public char Prefix { get; set; }
|
||||
|
||||
public Dictionary<string, Command> Commands { get; } = new Dictionary<string, Command>();
|
||||
public CommandTree Commands { get; set; } = new CommandTree();
|
||||
private Logger _log = LogManager.GetLogger(nameof(CommandManager));
|
||||
private readonly ITorchBase _torch;
|
||||
private readonly ChatManager _chatManager = ChatManager.Instance;
|
||||
|
||||
public CommandManager(ITorchBase torch, char prefix = '/')
|
||||
{
|
||||
Torch = torch;
|
||||
_torch = torch;
|
||||
Prefix = prefix;
|
||||
_chatManager.MessageRecieved += HandleCommand;
|
||||
RegisterCommandModule(typeof(TorchCommands));
|
||||
}
|
||||
|
||||
public bool HasPermission(ulong steamId, Command command)
|
||||
{
|
||||
_log.Warn("Command permissions not implemented");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -50,39 +39,72 @@ namespace Torch.Commands
|
||||
return command.Length > 1 && command[0] == Prefix;
|
||||
}
|
||||
|
||||
public void RegisterPluginCommands(ITorchPlugin plugin)
|
||||
public void RegisterCommandModule(Type moduleType, ITorchPlugin plugin = null)
|
||||
{
|
||||
var assembly = plugin.GetType().Assembly;
|
||||
foreach (var type in assembly.ExportedTypes)
|
||||
{
|
||||
if (!type.IsSubclassOf(typeof(CommandModule)))
|
||||
continue;
|
||||
if (!moduleType.IsSubclassOf(typeof(CommandModule)))
|
||||
return;
|
||||
|
||||
foreach (var method in type.GetMethods())
|
||||
foreach (var method in moduleType.GetMethods())
|
||||
{
|
||||
var commandAttrib = method.GetCustomAttribute<CommandAttribute>();
|
||||
if (commandAttrib == null)
|
||||
continue;
|
||||
|
||||
var command = new Command(plugin, method);
|
||||
_log.Info($"Registering command '{string.Join(".", command.Path)}' from plugin '{plugin.Name}'");
|
||||
}
|
||||
var cmdPath = string.Join(".", command.Path);
|
||||
_log.Info($"Registering command '{cmdPath}'");
|
||||
|
||||
if (!Commands.AddCommand(command))
|
||||
_log.Error($"Command path {cmdPath} is already registered.");
|
||||
}
|
||||
}
|
||||
|
||||
public void HandleCommand(string command, ulong steamId = 0)
|
||||
public void RegisterPluginCommands(ITorchPlugin plugin)
|
||||
{
|
||||
if (!IsCommand(command))
|
||||
var assembly = plugin.GetType().Assembly;
|
||||
foreach (var type in assembly.ExportedTypes)
|
||||
{
|
||||
RegisterCommandModule(type, plugin);
|
||||
}
|
||||
}
|
||||
|
||||
public void HandleCommand(ChatMsg msg, ref bool sendToOthers)
|
||||
{
|
||||
if (msg.Text.Length < 1 || msg.Text[0] != Prefix)
|
||||
return;
|
||||
|
||||
var cmdNameEnd = command.Length - command.IndexOf(" ", StringComparison.InvariantCultureIgnoreCase);
|
||||
var cmdName = command.Substring(1, cmdNameEnd);
|
||||
if (!Commands.ContainsKey(cmdName))
|
||||
sendToOthers = false;
|
||||
|
||||
var player = _torch.Multiplayer.GetPlayerBySteamId(msg.Author);
|
||||
if (player == null)
|
||||
{
|
||||
_log.Error($"Command {msg.Text} invoked by nonexistant player");
|
||||
return;
|
||||
}
|
||||
|
||||
var cmdText = new string(msg.Text.Skip(1).ToArray());
|
||||
var split = Regex.Matches(cmdText, "(\"[^\"]+\"|\\S+)").Cast<Match>().Select(x => x.ToString().Replace("\"", "")).ToList();
|
||||
|
||||
if (split.Count == 0)
|
||||
return;
|
||||
|
||||
string arg = "";
|
||||
if (command.Length > cmdNameEnd + 1)
|
||||
arg = command.Substring(cmdNameEnd + 1);
|
||||
var command = Commands.ParseCommand(split, out List<string> args);
|
||||
|
||||
if (command != null)
|
||||
{
|
||||
var cmdPath = string.Join(".", command.Path);
|
||||
|
||||
if (!HasPermission(msg.Author, command))
|
||||
{
|
||||
_log.Info($"{player.DisplayName} tried to use command {cmdPath} without permission");
|
||||
return;
|
||||
}
|
||||
|
||||
_log.Trace($"Invoking {cmdPath} for player {player.DisplayName}");
|
||||
var context = new CommandContext(_torch, command.Plugin, player, args);
|
||||
command.Invoke(context);
|
||||
_log.Info($"Player {player.DisplayName} ran command '{msg.Text}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,29 +3,42 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VRage.Collections;
|
||||
using VRage.Library.Collections;
|
||||
|
||||
namespace Torch.Commands
|
||||
{
|
||||
public class CommandTree
|
||||
{
|
||||
private Dictionary<string, Node> RootNodes { get; } = new Dictionary<string, Node>();
|
||||
public DictionaryReader<string, CommandNode> Root { get; }
|
||||
private readonly Dictionary<string, CommandNode> _root = new Dictionary<string, CommandNode>();
|
||||
|
||||
public CommandTree()
|
||||
{
|
||||
Root = new DictionaryReader<string, CommandNode>(_root);
|
||||
}
|
||||
|
||||
public bool AddCommand(Command command)
|
||||
{
|
||||
var root = command.Path.First();
|
||||
var node = RootNodes.ContainsKey(root) ? RootNodes[root] : new Node(root);
|
||||
|
||||
for (var i = 1; i < command.Path.Length; i++)
|
||||
if (!_root.ContainsKey(root))
|
||||
{
|
||||
_root.Add(root, new CommandNode(root));
|
||||
}
|
||||
|
||||
var node = _root[root];
|
||||
|
||||
for (var i = 1; i < command.Path.Count; i++)
|
||||
{
|
||||
var current = command.Path[i];
|
||||
if (node.Nodes.ContainsKey(current))
|
||||
if (node.Subcommands.ContainsKey(current))
|
||||
{
|
||||
node = node.Nodes[current];
|
||||
node = node.Subcommands[current];
|
||||
continue;
|
||||
}
|
||||
|
||||
var newNode = new Node(current);
|
||||
var newNode = new CommandNode(current);
|
||||
node.AddNode(newNode);
|
||||
node = newNode;
|
||||
}
|
||||
@@ -37,59 +50,119 @@ namespace Torch.Commands
|
||||
return true;
|
||||
}
|
||||
|
||||
public Command ParseCommand(ulong steamId, string[] command, out string[] args)
|
||||
/// <summary>
|
||||
/// Get a command node from the tree.
|
||||
/// </summary>
|
||||
/// <param name="path">Path to the command node.</param>
|
||||
/// <param name="commandNode"></param>
|
||||
/// <returns>The index of the first argument in the path or -1 if the node doesn't exist.</returns>
|
||||
public int GetNode(List<string> path, out CommandNode commandNode)
|
||||
{
|
||||
args = new string[0];
|
||||
var root = command.First();
|
||||
if (!RootNodes.ContainsKey(root))
|
||||
return null;
|
||||
commandNode = null;
|
||||
var root = path.FirstOrDefault();
|
||||
if (root == null)
|
||||
return -1;
|
||||
|
||||
var node = RootNodes[root];
|
||||
for (var i = 1; i < command.Length; i++)
|
||||
if (!_root.ContainsKey(root))
|
||||
return -1;
|
||||
|
||||
var node = _root[root];
|
||||
var i = 1;
|
||||
for (; i < path.Count; i++)
|
||||
{
|
||||
var current = command[i];
|
||||
if (node.Nodes.ContainsKey(current))
|
||||
var current = path[i];
|
||||
if (node.Subcommands.ContainsKey(current))
|
||||
{
|
||||
node = node.Nodes[current];
|
||||
continue;
|
||||
node = node.Subcommands[current];
|
||||
}
|
||||
}
|
||||
|
||||
args = new string[command.Length - i];
|
||||
Array.Copy(command, i, args, 0, args.Length);
|
||||
commandNode = node;
|
||||
return path.Count - i + 1;
|
||||
}
|
||||
|
||||
if (!node.IsCommand)
|
||||
return null;
|
||||
|
||||
public Command ParseCommand(List<string> path, out List<string> args)
|
||||
{
|
||||
args = new List<string>();
|
||||
var skip = GetNode(path, out CommandNode node);
|
||||
args.AddRange(path.Skip(skip));
|
||||
return node.Command;
|
||||
}
|
||||
|
||||
private class Node
|
||||
|
||||
public string GetTreeString()
|
||||
{
|
||||
public Dictionary<string, Node> Nodes { get; } = new Dictionary<string, Node>();
|
||||
var indent = 0;
|
||||
var sb = new StringBuilder();
|
||||
foreach (var node in _root)
|
||||
{
|
||||
DebugNode(node.Value, sb, ref indent);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private void DebugNode(CommandNode commandNode, StringBuilder sb, ref int indent)
|
||||
{
|
||||
sb.AppendLine(new string(' ', indent) + commandNode.Name);
|
||||
indent += 2;
|
||||
|
||||
foreach (var n in commandNode.Subcommands)
|
||||
{
|
||||
DebugNode(n.Value, sb, ref indent);
|
||||
}
|
||||
|
||||
indent -= 2;
|
||||
}
|
||||
|
||||
public class CommandNode
|
||||
{
|
||||
public CommandNode Parent { get; private set; }
|
||||
public DictionaryReader<string, CommandNode> Subcommands { get; }
|
||||
private readonly Dictionary<string, CommandNode> _subcommands = new Dictionary<string, CommandNode>();
|
||||
|
||||
public string Name { get; }
|
||||
public Command Command { get; set; }
|
||||
public bool IsCommand => Command != null;
|
||||
public bool IsEmpty => !IsCommand && Nodes.Count == 0;
|
||||
public bool IsEmpty => !IsCommand && _subcommands.Count == 0;
|
||||
|
||||
public Node(string name, Command command = null)
|
||||
public CommandNode(string name)
|
||||
{
|
||||
Subcommands = new DictionaryReader<string, CommandNode>(_subcommands);
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public CommandNode(Command command)
|
||||
{
|
||||
Name = command.Name;
|
||||
Command = command;
|
||||
}
|
||||
|
||||
public void AddNode(Node node)
|
||||
public bool TryGetChild(string name, out CommandNode node)
|
||||
{
|
||||
Nodes.Add(node.Name, node);
|
||||
}
|
||||
return Subcommands.TryGetValue(name, out node);
|
||||
}
|
||||
|
||||
public enum InvokeResult
|
||||
public List<string> GetPath()
|
||||
{
|
||||
Success,
|
||||
NoCommand,
|
||||
NoPermission
|
||||
var path = new List<string> {Name};
|
||||
if (Parent != null)
|
||||
path.InsertRange(0, Parent.GetPath());
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public void AddNode(CommandNode commandNode)
|
||||
{
|
||||
commandNode.Parent = this;
|
||||
_subcommands.Add(commandNode.Name, commandNode);
|
||||
}
|
||||
|
||||
public void RemoveNode(CommandNode commandNode)
|
||||
{
|
||||
commandNode.Parent = null;
|
||||
_subcommands.Remove(commandNode.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
19
Torch/Commands/DefaultPermissionAttribute.cs
Normal file
19
Torch/Commands/DefaultPermissionAttribute.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VRage.Game.ModAPI;
|
||||
|
||||
namespace Torch.Commands
|
||||
{
|
||||
public class DefaultPermissionAttribute : Attribute
|
||||
{
|
||||
public MyPromoteLevel Level { get; }
|
||||
|
||||
public DefaultPermissionAttribute(MyPromoteLevel level)
|
||||
{
|
||||
Level = level;
|
||||
}
|
||||
}
|
||||
}
|
73
Torch/Commands/Permissions/PermissonsSystem.cs
Normal file
73
Torch/Commands/Permissions/PermissonsSystem.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Sandbox.Game.World;
|
||||
using VRage.Game.ModAPI;
|
||||
|
||||
namespace Torch.Commands.Permissions
|
||||
{
|
||||
public class PermissionGroup
|
||||
{
|
||||
public List<ulong> Members { get; }
|
||||
public List<Permission> Permissions { get; }
|
||||
|
||||
public void AddMember(PermissionUser user)
|
||||
{
|
||||
Members.Add(user.SteamID);
|
||||
user.Groups.Add(this);
|
||||
}
|
||||
|
||||
public void RemoveMember(PermissionUser user)
|
||||
{
|
||||
user.Groups.Remove(this);
|
||||
Members.Remove(user.SteamID);
|
||||
}
|
||||
}
|
||||
|
||||
public class PermissionUser
|
||||
{
|
||||
public ulong SteamID { get; }
|
||||
public List<PermissionGroup> Groups { get; }
|
||||
public List<Permission> Permissions { get; }
|
||||
|
||||
public void AddToGroup(PermissionGroup group)
|
||||
{
|
||||
group.Members.Add(SteamID);
|
||||
Groups.Add(group);
|
||||
}
|
||||
|
||||
public void RemoveFromGroup(PermissionGroup group)
|
||||
{
|
||||
group.Members.Remove(SteamID);
|
||||
Groups.Remove(group);
|
||||
}
|
||||
|
||||
public void HasPermission()
|
||||
{
|
||||
var promoteLevel = MySession.Static.GetUserPromoteLevel(SteamID);
|
||||
}
|
||||
}
|
||||
|
||||
public class Permission
|
||||
{
|
||||
public string[] Path { get; }
|
||||
public bool Allow { get; }
|
||||
public Dictionary<string, Permission> Children { get; } = new Dictionary<string, Permission>();
|
||||
}
|
||||
|
||||
public class PermissonsSystem
|
||||
{
|
||||
public Dictionary<string, PermissionGroup> Groups { get; } = new Dictionary<string, PermissionGroup>();
|
||||
public Dictionary<long, PermissionUser> Users { get; } = new Dictionary<long, PermissionUser>();
|
||||
|
||||
public void GenerateDefaultGroups()
|
||||
{
|
||||
foreach (var name in Enum.GetNames(typeof(MyPromoteLevel)))
|
||||
{
|
||||
Groups.Add(name, new PermissionGroup());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
68
Torch/Commands/TorchCommands.cs
Normal file
68
Torch/Commands/TorchCommands.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Torch.Managers;
|
||||
|
||||
namespace Torch.Commands
|
||||
{
|
||||
public class TorchCommands : CommandModule
|
||||
{
|
||||
[Command("dbgcmd")]
|
||||
public void Dbgcmd()
|
||||
{
|
||||
var commandManager = ((PluginManager)Context.Torch.Plugins).Commands;
|
||||
Console.WriteLine(commandManager.Commands.GetTreeString());
|
||||
}
|
||||
|
||||
[Command("help", "Displays help for a command")]
|
||||
public void Help()
|
||||
{
|
||||
var commandManager = ((PluginManager)Context.Torch.Plugins).Commands;
|
||||
commandManager.Commands.GetNode(Context.Args, out CommandTree.CommandNode node);
|
||||
|
||||
if (node != null)
|
||||
{
|
||||
var command = node.Command;
|
||||
var children = node.Subcommands.Select(x => x.Key);
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if (command != null)
|
||||
sb.AppendLine(command.HelpText);
|
||||
|
||||
if (children.Any())
|
||||
sb.AppendLine($"Subcommands: {string.Join(", ", children)}");
|
||||
|
||||
Context.Respond(sb.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
var topNodeNames = commandManager.Commands.Root.Select(x => x.Key);
|
||||
Context.Respond($"Top level commands: {string.Join(", ", topNodeNames)}");
|
||||
}
|
||||
}
|
||||
|
||||
[Command("ver", "Shows the running Torch version.")]
|
||||
public void Version()
|
||||
{
|
||||
var ver = Context.Torch.Version;
|
||||
Context.Respond($"Torch version: {ver}");
|
||||
}
|
||||
|
||||
[Command("plugins", "Lists the currently loaded plugins.")]
|
||||
public void Plugins()
|
||||
{
|
||||
var plugins = Context.Torch.Plugins.Select(p => p.Name);
|
||||
Context.Respond($"Loaded plugins: {string.Join(", ", plugins)}");
|
||||
}
|
||||
|
||||
[Command("stop", "Stops the server.")]
|
||||
public void Stop()
|
||||
{
|
||||
Context.Respond("Stopping server.");
|
||||
Context.Torch.Stop();
|
||||
}
|
||||
}
|
||||
}
|
@@ -11,7 +11,7 @@ namespace Torch.Managers
|
||||
{
|
||||
public class ChatManager
|
||||
{
|
||||
public ChatManager()
|
||||
private ChatManager()
|
||||
{
|
||||
NetworkManager.Instance.RegisterNetworkHandlers(new ChatIntercept());
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@ using VRage.Library.Collections;
|
||||
using VRage.Network;
|
||||
using VRage.Utils;
|
||||
|
||||
namespace Torch
|
||||
namespace Torch.Managers
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a proxy to the game's multiplayer-related functions.
|
||||
@@ -38,13 +38,11 @@ namespace Torch
|
||||
public event Action<IPlayer> PlayerLeft;
|
||||
public event Action<IChatItem> MessageReceived;
|
||||
|
||||
//public MTObservableCollection<MyPlayer> PlayersView { get; } = new MTObservableCollection<MyPlayer>();
|
||||
//public MTObservableCollection<ChatItem> ChatView { get; } = new MTObservableCollection<ChatItem>();
|
||||
public List<IChatItem> Chat { get; } = new List<IChatItem>();
|
||||
public Dictionary<ulong, IPlayer> Players { get; } = new Dictionary<ulong, IPlayer>();
|
||||
public Player LocalPlayer { get; private set; }
|
||||
private readonly ITorchBase _torch;
|
||||
private static Logger _log = LogManager.GetLogger("Torch");
|
||||
private static Logger _log = LogManager.GetLogger(nameof(MultiplayerManager));
|
||||
private Dictionary<MyPlayer.PlayerId, MyPlayer> _onlinePlayers;
|
||||
|
||||
internal MultiplayerManager(ITorchBase torch)
|
||||
@@ -53,11 +51,11 @@ namespace Torch
|
||||
_torch.SessionLoaded += OnSessionLoaded;
|
||||
}
|
||||
|
||||
public void KickPlayer(ulong steamId) => _torch.InvokeAsync(() => MyMultiplayer.Static.KickClient(steamId));
|
||||
public void KickPlayer(ulong steamId) => _torch.Invoke(() => MyMultiplayer.Static.KickClient(steamId));
|
||||
|
||||
public void BanPlayer(ulong steamId, bool banned = true)
|
||||
{
|
||||
_torch.InvokeAsync(() =>
|
||||
_torch.Invoke(() =>
|
||||
{
|
||||
MyMultiplayer.Static.BanClient(steamId, banned);
|
||||
if (_gameOwnerIds.ContainsKey(steamId))
|
||||
@@ -65,19 +63,29 @@ namespace Torch
|
||||
});
|
||||
}
|
||||
|
||||
public IMyPlayer GetPlayerByDisplayName(string displayName)
|
||||
{
|
||||
return _onlinePlayers.FirstOrDefault(x => x.Value.DisplayName == displayName).Value;
|
||||
}
|
||||
|
||||
public IMyPlayer GetPlayerBySteamId(ulong steamId)
|
||||
{
|
||||
_onlinePlayers.TryGetValue(new MyPlayer.PlayerId(steamId), out MyPlayer p);
|
||||
return p;
|
||||
}
|
||||
|
||||
public void SendMessage(string message)
|
||||
{
|
||||
SendMessage(message, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a message in chat.
|
||||
/// </summary>
|
||||
public void SendMessage(string message)
|
||||
public void SendMessage(string message, long playerId, string author = "Server", string font = MyFontEnum.Blue)
|
||||
{
|
||||
MyMultiplayer.Static.SendChatMessage(message);
|
||||
//ChatView.Add(new ChatItem(LocalPlayer, message));
|
||||
var msg = new ScriptedChatMsg {Author = author, Font = font, Target = playerId, Text = message};
|
||||
MyMultiplayerBase.SendScriptedChatMessage(ref msg);
|
||||
}
|
||||
|
||||
private void OnSessionLoaded()
|
||||
@@ -156,6 +164,8 @@ namespace Torch
|
||||
private HashSet<ulong> _waitingForGroup;
|
||||
private HashSet<ulong> _waitingForFriends;
|
||||
private Dictionary<ulong, ulong> _gameOwnerIds = new Dictionary<ulong, ulong>();
|
||||
private IMultiplayer _multiplayerImplementation;
|
||||
|
||||
/// <summary>
|
||||
/// Removes Keen's hooks into some Steam events so we have full control over client authentication
|
||||
/// </summary>
|
@@ -14,13 +14,13 @@ namespace Torch.Managers
|
||||
{
|
||||
public class NetworkManager
|
||||
{
|
||||
public NetworkManager()
|
||||
private NetworkManager()
|
||||
{
|
||||
if (ReflectionUnitTest())
|
||||
InitNetworkIntercept();
|
||||
}
|
||||
|
||||
private static Logger _log = LogManager.GetLogger("Torch");
|
||||
private static Logger _log = LogManager.GetLogger(nameof(NetworkManager));
|
||||
private static NetworkManager _instance;
|
||||
public static NetworkManager Instance => _instance ?? (_instance = new NetworkManager());
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace Torch.Managers
|
||||
|
||||
//PrintDebug();
|
||||
|
||||
//ApplicationLog.Info("Initialized network intercept!");
|
||||
_log.Debug("Initialized network intercept");
|
||||
}
|
||||
|
||||
#region Network Intercept
|
||||
@@ -100,8 +100,8 @@ namespace Torch.Managers
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error(ex);
|
||||
//ApplicationLog.Error(ex, "~Error processing event!");
|
||||
_log.Fatal(ex);
|
||||
_log.Fatal(ex, "~Error processing event!");
|
||||
//crash after logging, bad things could happen if we continue on with bad data
|
||||
throw;
|
||||
}
|
||||
@@ -175,8 +175,8 @@ namespace Torch.Managers
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error(ex);
|
||||
//ApplicationLog.Error(ex, "Error when returning control to game server!");
|
||||
_log.Fatal(ex);
|
||||
_log.Fatal(ex, "Error when returning control to game server!");
|
||||
//crash after logging, bad things could happen if we continue on with bad data
|
||||
throw;
|
||||
}
|
||||
@@ -191,7 +191,7 @@ namespace Torch.Managers
|
||||
if (item.GetType().FullName == handlerType)
|
||||
{
|
||||
//if (ExtenderOptions.IsDebugging)
|
||||
// ApplicationLog.BaseLog.Error("Network handler already registered! " + handlerType);
|
||||
_log.Error("Network handler already registered! " + handlerType);
|
||||
toRemove.Add(item);
|
||||
}
|
||||
}
|
||||
|
@@ -14,11 +14,12 @@ using Sandbox;
|
||||
using Sandbox.ModAPI;
|
||||
using Torch.API;
|
||||
using Torch.Commands;
|
||||
using Torch.Managers;
|
||||
using VRage.Plugins;
|
||||
using VRage.Collections;
|
||||
using VRage.Library.Collections;
|
||||
|
||||
namespace Torch
|
||||
namespace Torch.Managers
|
||||
{
|
||||
public class PluginManager : IPluginManager
|
||||
{
|
||||
@@ -28,13 +29,15 @@ namespace Torch
|
||||
|
||||
private readonly List<ITorchPlugin> _plugins = new List<ITorchPlugin>();
|
||||
private readonly PluginUpdater _updater;
|
||||
private readonly CommandManager _commands;
|
||||
public CommandManager Commands { get; private set; }
|
||||
|
||||
public float LastUpdateMs => _lastUpdateMs;
|
||||
private volatile float _lastUpdateMs;
|
||||
|
||||
public PluginManager(ITorchBase torch)
|
||||
{
|
||||
_torch = torch;
|
||||
_updater = new PluginUpdater(this);
|
||||
_commands = new CommandManager(_torch);
|
||||
|
||||
if (!Directory.Exists(PluginDir))
|
||||
Directory.CreateDirectory(PluginDir);
|
||||
@@ -42,6 +45,9 @@ namespace Torch
|
||||
InitUpdater();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the plugin updater plugin to VRage's plugin system.
|
||||
/// </summary>
|
||||
private void InitUpdater()
|
||||
{
|
||||
var fieldName = "m_plugins";
|
||||
@@ -52,11 +58,20 @@ namespace Torch
|
||||
pluginList.Add(_updater);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates loaded plugins in parallel.
|
||||
/// </summary>
|
||||
public void UpdatePlugins()
|
||||
{
|
||||
var s = Stopwatch.StartNew();
|
||||
Parallel.ForEach(_plugins, p => p.Update());
|
||||
s.Stop();
|
||||
_lastUpdateMs = (float)s.Elapsed.TotalMilliseconds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unloads all plugins.
|
||||
/// </summary>
|
||||
public void UnloadPlugins()
|
||||
{
|
||||
foreach (var plugin in _plugins)
|
||||
@@ -66,10 +81,13 @@ namespace Torch
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load and create instances of all plugins in the <see cref="PluginDir"/> folder.
|
||||
/// Loads and creates instances of all plugins in the <see cref="PluginDir"/> folder.
|
||||
/// </summary>
|
||||
public void LoadPlugins()
|
||||
public void Init()
|
||||
{
|
||||
var network = NetworkManager.Instance;
|
||||
Commands = new CommandManager(_torch);
|
||||
|
||||
_log.Info("Loading plugins");
|
||||
var pluginsPath = Path.Combine(Directory.GetCurrentDirectory(), PluginDir);
|
||||
var dlls = Directory.GetFiles(pluginsPath, "*.dll", SearchOption.AllDirectories);
|
||||
@@ -91,7 +109,7 @@ namespace Torch
|
||||
_log.Info($"Loading plugin {plugin.Name} ({plugin.Version})");
|
||||
_plugins.Add(plugin);
|
||||
|
||||
_commands.RegisterPluginCommands(plugin);
|
||||
Commands.RegisterPluginCommands(plugin);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -132,6 +150,7 @@ namespace Torch
|
||||
private class PluginUpdater : IPlugin
|
||||
{
|
||||
private readonly IPluginManager _manager;
|
||||
|
||||
public PluginUpdater(IPluginManager manager)
|
||||
{
|
||||
_manager = manager;
|
||||
@@ -139,7 +158,7 @@ namespace Torch
|
||||
|
||||
public void Init(object obj)
|
||||
{
|
||||
_manager.LoadPlugins();
|
||||
_manager.Init();
|
||||
}
|
||||
|
||||
public void Update()
|
40
Torch/Managers/ScriptingManager.cs
Normal file
40
Torch/Managers/ScriptingManager.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Torch.API;
|
||||
using Torch.API.ModAPI.Ingame;
|
||||
using VRage.Scripting;
|
||||
|
||||
namespace Torch.Managers
|
||||
{
|
||||
public class ScriptingManager
|
||||
{
|
||||
private MyScriptWhitelist _whitelist;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
_whitelist = MyScriptCompiler.Static.Whitelist;
|
||||
MyScriptCompiler.Static.AddConditionalCompilationSymbols("TORCH");
|
||||
MyScriptCompiler.Static.AddReferencedAssemblies(typeof(ITorchBase).Assembly.Location);
|
||||
MyScriptCompiler.Static.AddImplicitIngameNamespacesFromTypes(typeof(GridExtensions));
|
||||
|
||||
/*
|
||||
//dump whitelist
|
||||
var whitelist = new StringBuilder();
|
||||
foreach (var pair in MyScriptCompiler.Static.Whitelist.GetWhitelist())
|
||||
{
|
||||
var split = pair.Key.Split(',');
|
||||
whitelist.AppendLine("|-");
|
||||
whitelist.AppendLine($"|{pair.Value} || {split[0]} || {split[1]}");
|
||||
}
|
||||
Log.Info(whitelist);*/
|
||||
}
|
||||
|
||||
public void UnwhitelistType(Type t)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@@ -16,20 +16,27 @@ namespace Torch
|
||||
{
|
||||
public static class SteamHelper
|
||||
{
|
||||
private static Thread _callbackThread;
|
||||
private static Logger _log = LogManager.GetLogger("Torch");
|
||||
private static CancellationTokenSource _tokenSource = new CancellationTokenSource();
|
||||
private static CancellationToken _cancelToken;
|
||||
private static Logger _log = LogManager.GetLogger(nameof(SteamHelper));
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
_callbackThread = new Thread(() =>
|
||||
_cancelToken = _tokenSource.Token;
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
while (true)
|
||||
while (!_cancelToken.IsCancellationRequested)
|
||||
{
|
||||
SteamAPI.Instance.RunCallbacks();
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
}) {Name = "SteamAPICallbacks"};
|
||||
_callbackThread.Start();
|
||||
});
|
||||
}
|
||||
|
||||
public static void StopCallbackLoop()
|
||||
{
|
||||
_tokenSource.Cancel();
|
||||
}
|
||||
|
||||
public static MySteamWorkshop.SubscribedItem GetItemInfo(ulong itemId)
|
||||
@@ -55,7 +62,7 @@ namespace Torch
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.Warn($"Failed to get item info for {itemId}");
|
||||
_log.Error($"Failed to get item info for {itemId}");
|
||||
}
|
||||
|
||||
mre.Set();
|
||||
@@ -78,7 +85,7 @@ namespace Torch
|
||||
if (!b && result.Details.Result == Result.OK)
|
||||
details = result.Details;
|
||||
else
|
||||
_log.Warn($"Failed to get item details for {itemId}");
|
||||
_log.Error($"Failed to get item details for {itemId}");
|
||||
|
||||
re.Set();
|
||||
});
|
||||
|
@@ -152,11 +152,15 @@
|
||||
<Compile Include="Commands\CommandContext.cs" />
|
||||
<Compile Include="Commands\CommandManager.cs" />
|
||||
<Compile Include="Commands\CommandTree.cs" />
|
||||
<Compile Include="Commands\DefaultPermissionAttribute.cs" />
|
||||
<Compile Include="Commands\Permissions\PermissonsSystem.cs" />
|
||||
<Compile Include="Commands\TorchCommands.cs" />
|
||||
<Compile Include="Managers\ChatManager.cs" />
|
||||
<Compile Include="Managers\NetworkManager\NetworkHandlerBase.cs" />
|
||||
<Compile Include="Managers\NetworkManager\NetworkManager.cs" />
|
||||
<Compile Include="MultiplayerManager.cs" />
|
||||
<Compile Include="Managers\MultiplayerManager.cs" />
|
||||
<Compile Include="Reflection.cs" />
|
||||
<Compile Include="Managers\ScriptingManager.cs" />
|
||||
<Compile Include="TorchBase.cs" />
|
||||
<Compile Include="Player.cs" />
|
||||
<Compile Include="Collections\PlayerInfoCache.cs" />
|
||||
@@ -169,7 +173,7 @@
|
||||
<Compile Include="SteamHelper.cs" />
|
||||
<Compile Include="Extensions\StringExtensions.cs" />
|
||||
<Compile Include="ViewModels\ViewModel.cs" />
|
||||
<Compile Include="PluginManager.cs" />
|
||||
<Compile Include="Managers\PluginManager.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ViewModels\PluginViewModel.cs" />
|
||||
</ItemGroup>
|
||||
|
@@ -3,12 +3,15 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NLog;
|
||||
using Sandbox;
|
||||
using Sandbox.ModAPI;
|
||||
using Torch.API;
|
||||
using Torch.Managers;
|
||||
using VRage.Scripting;
|
||||
|
||||
namespace Torch
|
||||
@@ -22,6 +25,7 @@ namespace Torch
|
||||
[Obsolete]
|
||||
public static ITorchBase Instance { get; private set; }
|
||||
protected static Logger Log = LogManager.GetLogger("Torch");
|
||||
public Version Version { get; protected set; }
|
||||
public string[] RunArgs { get; set; }
|
||||
public IPluginManager Plugins { get; protected set; }
|
||||
public IMultiplayer Multiplayer { get; protected set; }
|
||||
@@ -41,6 +45,7 @@ namespace Torch
|
||||
|
||||
Instance = this;
|
||||
|
||||
Version = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
RunArgs = new string[0];
|
||||
Plugins = new PluginManager(this);
|
||||
Multiplayer = new MultiplayerManager(this);
|
||||
@@ -116,9 +121,6 @@ namespace Torch
|
||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
||||
|
||||
_init = true;
|
||||
MyScriptCompiler.Static.AddConditionalCompilationSymbols("TORCH");
|
||||
MyScriptCompiler.Static.AddReferencedAssemblies(typeof(ITorchBase).Assembly.Location);
|
||||
MyScriptCompiler.Static.AddReferencedAssemblies(typeof(TorchBase).Assembly.Location);
|
||||
}
|
||||
|
||||
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||
|
Reference in New Issue
Block a user