Add Torch client mod. Currently supports dialogs and notifications.
Add dialog output to !longhelp Add !notify command Silently inserts mod into session when client connects, server admins don't need to do anything to enable it.
This commit is contained in:
72
Torch.Mod/Messages/DialogMessage.cs
Normal file
72
Torch.Mod/Messages/DialogMessage.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ProtoBuf;
|
||||
using Sandbox.ModAPI;
|
||||
|
||||
namespace Torch.Mod.Messages
|
||||
{
|
||||
/// Dialogs are structured as follows
|
||||
///
|
||||
/// _____________________________________
|
||||
/// | Title |
|
||||
/// --------------------------------------
|
||||
/// | Prefix Subtitle |
|
||||
/// --------------------------------------
|
||||
/// | ________________________________ |
|
||||
/// | | Content | |
|
||||
/// | --------------------------------- |
|
||||
/// | ____________ |
|
||||
/// | | ButtonText | |
|
||||
/// | -------------- |
|
||||
/// --------------------------------------
|
||||
///
|
||||
/// Button has a callback on click option,
|
||||
/// but can't serialize that, so ¯\_(ツ)_/¯
|
||||
[ProtoContract]
|
||||
public class DialogMessage : MessageBase
|
||||
{
|
||||
[ProtoMember(201)]
|
||||
public string Title;
|
||||
[ProtoMember(202)]
|
||||
public string Subtitle;
|
||||
[ProtoMember(203)]
|
||||
public string Prefix;
|
||||
[ProtoMember(204)]
|
||||
public string Content;
|
||||
[ProtoMember(205)]
|
||||
public string ButtonText;
|
||||
|
||||
public DialogMessage()
|
||||
{ }
|
||||
|
||||
public DialogMessage(string title, string subtitle, string content)
|
||||
{
|
||||
Title = title;
|
||||
Subtitle = subtitle;
|
||||
Content = content;
|
||||
Prefix = String.Empty;
|
||||
}
|
||||
|
||||
public DialogMessage(string title = null, string prefix = null, string subtitle = null, string content = null, string buttonText = null)
|
||||
{
|
||||
Title = title;
|
||||
Subtitle = subtitle;
|
||||
Prefix = prefix ?? String.Empty;
|
||||
Content = content;
|
||||
ButtonText = buttonText;
|
||||
}
|
||||
|
||||
public override void ProcessClient()
|
||||
{
|
||||
MyAPIGateway.Utilities.ShowMissionScreen(Title, Prefix, Subtitle, Content, null, ButtonText);
|
||||
}
|
||||
|
||||
public override void ProcessServer()
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
}
|
50
Torch.Mod/Messages/MessageBase.cs
Normal file
50
Torch.Mod/Messages/MessageBase.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ProtoBuf;
|
||||
|
||||
namespace Torch.Mod.Messages
|
||||
{
|
||||
#region Includes
|
||||
[ProtoInclude(1, typeof(DialogMessage))]
|
||||
[ProtoInclude(2, typeof(NotificationMessage))]
|
||||
#endregion
|
||||
|
||||
[ProtoContract]
|
||||
public abstract class MessageBase
|
||||
{
|
||||
[ProtoMember(101)]
|
||||
public ulong SenderId;
|
||||
|
||||
public abstract void ProcessClient();
|
||||
public abstract void ProcessServer();
|
||||
|
||||
//members below not serialized, they're just metadata about the intended target(s) of this message
|
||||
internal MessageTarget TargetType;
|
||||
internal ulong Target;
|
||||
internal ulong[] Ignore;
|
||||
internal byte[] CompressedData;
|
||||
}
|
||||
|
||||
public enum MessageTarget
|
||||
{
|
||||
/// <summary>
|
||||
/// Send to Target
|
||||
/// </summary>
|
||||
Single,
|
||||
/// <summary>
|
||||
/// Send to Server
|
||||
/// </summary>
|
||||
Server,
|
||||
/// <summary>
|
||||
/// Send to all Clients (only valid from server)
|
||||
/// </summary>
|
||||
AllClients,
|
||||
/// <summary>
|
||||
/// Send to all except those steam ID listed in Ignore
|
||||
/// </summary>
|
||||
AllExcept,
|
||||
}
|
||||
}
|
39
Torch.Mod/Messages/NotificationMessage.cs
Normal file
39
Torch.Mod/Messages/NotificationMessage.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using ProtoBuf;
|
||||
using Sandbox.ModAPI;
|
||||
|
||||
namespace Torch.Mod.Messages
|
||||
{
|
||||
[ProtoContract]
|
||||
public class NotificationMessage : MessageBase
|
||||
{
|
||||
[ProtoMember(201)]
|
||||
public string Message;
|
||||
[ProtoMember(202)]
|
||||
public string Font;
|
||||
[ProtoMember(203)]
|
||||
public int DisappearTimeMs;
|
||||
|
||||
public NotificationMessage()
|
||||
{ }
|
||||
|
||||
public NotificationMessage(string message, int disappearTimeMs, string font)
|
||||
{
|
||||
Message = message;
|
||||
DisappearTimeMs = disappearTimeMs;
|
||||
Font = font;
|
||||
}
|
||||
|
||||
public override void ProcessClient()
|
||||
{
|
||||
MyAPIGateway.Utilities.ShowNotification(Message, DisappearTimeMs, Font);
|
||||
}
|
||||
|
||||
public override void ProcessServer()
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
}
|
198
Torch.Mod/ModCommunication.cs
Normal file
198
Torch.Mod/ModCommunication.cs
Normal file
@@ -0,0 +1,198 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Sandbox.ModAPI;
|
||||
using Torch.Mod.Messages;
|
||||
using VRage;
|
||||
using VRage.Game.ModAPI;
|
||||
using VRage.Utils;
|
||||
using Task = ParallelTasks.Task;
|
||||
|
||||
namespace Torch.Mod
|
||||
{
|
||||
public static class ModCommunication
|
||||
{
|
||||
public const ushort NET_ID = 4352;
|
||||
private static bool _closing;
|
||||
private static ConcurrentQueue<MessageBase> _outgoing;
|
||||
private static ConcurrentQueue<byte[]> _incoming;
|
||||
private static List<IMyPlayer> _playerCache;
|
||||
private static FastResourceLock _lock;
|
||||
private static Task _task;
|
||||
|
||||
public static void Register()
|
||||
{
|
||||
MyLog.Default.WriteLineAndConsole("TORCH MOD: Registering mod communication.");
|
||||
_outgoing = new ConcurrentQueue<MessageBase>();
|
||||
_incoming = new ConcurrentQueue<byte[]>();
|
||||
_playerCache = new List<IMyPlayer>();
|
||||
_lock = new FastResourceLock();
|
||||
|
||||
|
||||
MyAPIGateway.Multiplayer.RegisterMessageHandler(NET_ID, MessageHandler);
|
||||
//background thread to handle de/compression and processing
|
||||
_task = MyAPIGateway.Parallel.StartBackground(DoProcessing);
|
||||
MyLog.Default.WriteLineAndConsole("TORCH MOD: Mod communication registered successfully.");
|
||||
}
|
||||
|
||||
public static void Unregister()
|
||||
{
|
||||
MyLog.Default.WriteLineAndConsole("TORCH MOD: Unregistering mod communication.");
|
||||
MyAPIGateway.Multiplayer.UnregisterMessageHandler(NET_ID, MessageHandler);
|
||||
_closing = true;
|
||||
ReleaseLock();
|
||||
_task.Wait();
|
||||
}
|
||||
|
||||
private static void MessageHandler(byte[] bytes)
|
||||
{
|
||||
_incoming.Enqueue(bytes);
|
||||
ReleaseLock();
|
||||
}
|
||||
|
||||
public static void DoProcessing()
|
||||
{
|
||||
while (!_closing)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] incoming;
|
||||
while (_incoming.TryDequeue(out incoming))
|
||||
{
|
||||
MessageBase m;
|
||||
try
|
||||
{
|
||||
var o = MyCompression.Decompress(incoming);
|
||||
m = MyAPIGateway.Utilities.SerializeFromBinary<MessageBase>(o);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MyLog.Default.WriteLineAndConsole($"TORCH MOD: Failed to deserialize message! {ex}");
|
||||
continue;
|
||||
}
|
||||
if (MyAPIGateway.Multiplayer.IsServer)
|
||||
m.ProcessServer();
|
||||
else
|
||||
m.ProcessClient();
|
||||
}
|
||||
|
||||
if (!_outgoing.IsEmpty)
|
||||
{
|
||||
List<MessageBase> tosend = new List<MessageBase>(_outgoing.Count);
|
||||
MessageBase outMessage;
|
||||
while (_outgoing.TryDequeue(out outMessage))
|
||||
{
|
||||
var b = MyAPIGateway.Utilities.SerializeToBinary(outMessage);
|
||||
outMessage.CompressedData = MyCompression.Compress(b);
|
||||
tosend.Add(outMessage);
|
||||
}
|
||||
|
||||
MyAPIGateway.Utilities.InvokeOnGameThread(() =>
|
||||
{
|
||||
MyAPIGateway.Players.GetPlayers(_playerCache);
|
||||
foreach (var outgoing in tosend)
|
||||
{
|
||||
switch (outgoing.TargetType)
|
||||
{
|
||||
case MessageTarget.Single:
|
||||
MyAPIGateway.Multiplayer.SendMessageTo(NET_ID, outgoing.CompressedData, outgoing.Target);
|
||||
break;
|
||||
case MessageTarget.Server:
|
||||
MyAPIGateway.Multiplayer.SendMessageToServer(NET_ID, outgoing.CompressedData);
|
||||
break;
|
||||
case MessageTarget.AllClients:
|
||||
foreach (var p in _playerCache)
|
||||
{
|
||||
if (p.SteamUserId == MyAPIGateway.Multiplayer.MyId)
|
||||
continue;
|
||||
MyAPIGateway.Multiplayer.SendMessageTo(NET_ID, outgoing.CompressedData, p.SteamUserId);
|
||||
}
|
||||
break;
|
||||
case MessageTarget.AllExcept:
|
||||
foreach (var p in _playerCache)
|
||||
{
|
||||
if (p.SteamUserId == MyAPIGateway.Multiplayer.MyId || outgoing.Ignore.Contains(p.SteamUserId))
|
||||
continue;
|
||||
MyAPIGateway.Multiplayer.SendMessageTo(NET_ID, outgoing.CompressedData, p.SteamUserId);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
_playerCache.Clear();
|
||||
});
|
||||
}
|
||||
|
||||
AcquireLock();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MyLog.Default.WriteLineAndConsole($"TORCH MOD: Exception occurred in communication thread! {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
MyLog.Default.WriteLineAndConsole("TORCH MOD: COMMUNICATION THREAD: EXIT SIGNAL RECIEVED!");
|
||||
//exit signal received. Clean everything and GTFO
|
||||
_outgoing = null;
|
||||
_incoming = null;
|
||||
_playerCache = null;
|
||||
_lock = null;
|
||||
}
|
||||
|
||||
public static void SendMessageTo(MessageBase message, ulong target)
|
||||
{
|
||||
if (!MyAPIGateway.Multiplayer.IsServer)
|
||||
throw new Exception("Only server can send targeted messages");
|
||||
message.Target = target;
|
||||
message.TargetType = MessageTarget.Single;
|
||||
MyLog.Default.WriteLineAndConsole($"Sending message of type {message.GetType().FullName}");
|
||||
_outgoing.Enqueue(message);
|
||||
ReleaseLock();
|
||||
}
|
||||
|
||||
public static void SendMessageToClients(MessageBase message)
|
||||
{
|
||||
if (!MyAPIGateway.Multiplayer.IsServer)
|
||||
throw new Exception("Only server can send targeted messages");
|
||||
message.TargetType = MessageTarget.AllClients;
|
||||
_outgoing.Enqueue(message);
|
||||
ReleaseLock();
|
||||
}
|
||||
|
||||
public static void SendMessageExcept(MessageBase message, params ulong[] ignoredUsers)
|
||||
{
|
||||
if (MyAPIGateway.Multiplayer.IsServer)
|
||||
throw new Exception("Only server can send targeted messages");
|
||||
message.TargetType = MessageTarget.AllExcept;
|
||||
message.Ignore = ignoredUsers;
|
||||
_outgoing.Enqueue(message);
|
||||
ReleaseLock();
|
||||
}
|
||||
|
||||
public static void SendMessageToServer(MessageBase message)
|
||||
{
|
||||
message.TargetType = MessageTarget.Server;
|
||||
_outgoing.Enqueue(message);
|
||||
ReleaseLock();
|
||||
}
|
||||
|
||||
private static void ReleaseLock()
|
||||
{
|
||||
while(!_lock.TryAcquireExclusive())
|
||||
_lock.ReleaseExclusive();
|
||||
_lock.ReleaseExclusive();
|
||||
}
|
||||
|
||||
private static void AcquireLock()
|
||||
{
|
||||
ReleaseLock();
|
||||
_lock.AcquireExclusive();
|
||||
_lock.AcquireExclusive();
|
||||
}
|
||||
}
|
||||
}
|
18
Torch.Mod/Torch.Mod.projitems
Normal file
18
Torch.Mod/Torch.Mod.projitems
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
<HasSharedItems>true</HasSharedItems>
|
||||
<SharedGUID>3ce4d2e9-b461-4f19-8233-f87e0dfddd74</SharedGUID>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
<Import_RootNamespace>Torch.Mod</Import_RootNamespace>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\NotificationMessage.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\DialogMessage.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\MessageBase.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ModCommunication.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)TorchModCore.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
13
Torch.Mod/Torch.Mod.shproj
Normal file
13
Torch.Mod/Torch.Mod.shproj
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>3ce4d2e9-b461-4f19-8233-f87e0dfddd74</ProjectGuid>
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
|
||||
<PropertyGroup />
|
||||
<Import Project="Torch.Mod.projitems" Label="Shared" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
|
||||
</Project>
|
30
Torch.Mod/TorchModCore.cs
Normal file
30
Torch.Mod/TorchModCore.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VRage.Game.Components;
|
||||
|
||||
namespace Torch.Mod
|
||||
{
|
||||
[MySessionComponentDescriptor(MyUpdateOrder.AfterSimulation)]
|
||||
public class TorchModCore : MySessionComponentBase
|
||||
{
|
||||
public const long MOD_ID = 1406994352;
|
||||
private static bool _init;
|
||||
|
||||
public override void UpdateAfterSimulation()
|
||||
{
|
||||
if (_init)
|
||||
return;
|
||||
|
||||
_init = true;
|
||||
ModCommunication.Register();
|
||||
}
|
||||
|
||||
protected override void UnloadData()
|
||||
{
|
||||
ModCommunication.Unregister();
|
||||
}
|
||||
}
|
||||
}
|
@@ -18,6 +18,7 @@ using Torch.API;
|
||||
using Torch.API.Managers;
|
||||
using Torch.API.Session;
|
||||
using Torch.Commands;
|
||||
using Torch.Mod;
|
||||
using Torch.Server.Commands;
|
||||
using Torch.Server.Managers;
|
||||
using Torch.Utils;
|
||||
@@ -174,10 +175,14 @@ namespace Torch.Server
|
||||
{
|
||||
_watchdog?.Dispose();
|
||||
_watchdog = null;
|
||||
ModCommunication.Unregister();
|
||||
}
|
||||
|
||||
if (newState == TorchSessionState.Loaded)
|
||||
{
|
||||
CurrentSession.Managers.GetManager<CommandManager>().RegisterCommandModule(typeof(WhitelistCommands));
|
||||
ModCommunication.Register();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
28
Torch.sln
28
Torch.sln
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27004.2010
|
||||
VisualStudioVersion = 15.0.26430.14
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch", "Torch\Torch.csproj", "{7E01635C-3B67-472E-BCD6-C5539564F214}"
|
||||
EndProject
|
||||
@@ -27,41 +27,60 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Versioning", "Versioning",
|
||||
Versioning\AssemblyVersion.cs = Versioning\AssemblyVersion.cs
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Torch.Mod", "Torch.Mod\Torch.Mod.shproj", "{3CE4D2E9-B461-4F19-8233-F87E0DFDDD74}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(Performance) = preSolution
|
||||
HasPerformanceSessions = true
|
||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||
Torch.Mod\Torch.Mod.projitems*{3ce4d2e9-b461-4f19-8233-f87e0dfddd74}*SharedItemsImports = 13
|
||||
Torch.Mod\Torch.Mod.projitems*{7e01635c-3b67-472e-bcd6-c5539564f214}*SharedItemsImports = 4
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7E01635C-3B67-472E-BCD6-C5539564F214}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{7E01635C-3B67-472E-BCD6-C5539564F214}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{7E01635C-3B67-472E-BCD6-C5539564F214}.Debug|x64.Build.0 = Debug|x64
|
||||
{7E01635C-3B67-472E-BCD6-C5539564F214}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{7E01635C-3B67-472E-BCD6-C5539564F214}.Release|x64.ActiveCfg = Release|x64
|
||||
{7E01635C-3B67-472E-BCD6-C5539564F214}.Release|x64.Build.0 = Release|x64
|
||||
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Debug|x64.Build.0 = Debug|x64
|
||||
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Release|x64.ActiveCfg = Release|x64
|
||||
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Release|x64.Build.0 = Release|x64
|
||||
{E36DF745-260B-4956-A2E8-09F08B2E7161}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{E36DF745-260B-4956-A2E8-09F08B2E7161}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E36DF745-260B-4956-A2E8-09F08B2E7161}.Debug|x64.Build.0 = Debug|x64
|
||||
{E36DF745-260B-4956-A2E8-09F08B2E7161}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{E36DF745-260B-4956-A2E8-09F08B2E7161}.Release|x64.ActiveCfg = Release|x64
|
||||
{E36DF745-260B-4956-A2E8-09F08B2E7161}.Release|x64.Build.0 = Release|x64
|
||||
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Debug|x64.Build.0 = Debug|x64
|
||||
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Release|x64.ActiveCfg = Release|x64
|
||||
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Release|x64.Build.0 = Release|x64
|
||||
{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}.Debug|x64.Build.0 = Debug|x64
|
||||
{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}.Release|x64.ActiveCfg = Release|x64
|
||||
{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}.Release|x64.Build.0 = Release|x64
|
||||
{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}.Debug|x64.Build.0 = Debug|x64
|
||||
{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}.Release|x64.ActiveCfg = Release|x64
|
||||
{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}.Release|x64.Build.0 = Release|x64
|
||||
{632E78C0-0DAC-4B71-B411-2F1B333CC310}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{632E78C0-0DAC-4B71-B411-2F1B333CC310}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{632E78C0-0DAC-4B71-B411-2F1B333CC310}.Debug|x64.Build.0 = Debug|x64
|
||||
{632E78C0-0DAC-4B71-B411-2F1B333CC310}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{632E78C0-0DAC-4B71-B411-2F1B333CC310}.Release|x64.ActiveCfg = Release|x64
|
||||
{632E78C0-0DAC-4B71-B411-2F1B333CC310}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
@@ -74,4 +93,7 @@ Global
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {BB51D91F-958D-4B63-A897-3C40642ACD3E}
|
||||
EndGlobalSection
|
||||
GlobalSection(Performance) = preSolution
|
||||
HasPerformanceSessions = true
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@@ -17,6 +17,8 @@ using Torch.API.Managers;
|
||||
using Torch.API.Session;
|
||||
using Torch.Commands.Permissions;
|
||||
using Torch.Managers;
|
||||
using Torch.Mod;
|
||||
using Torch.Mod.Messages;
|
||||
using VRage.Game.ModAPI;
|
||||
|
||||
namespace Torch.Commands
|
||||
@@ -75,7 +77,7 @@ namespace Torch.Commands
|
||||
}
|
||||
}
|
||||
|
||||
[Command("longhelp", "Get verbose help. Will send a long message, check the Comms tab.")]
|
||||
[Command("longhelp", "Get verbose help. Will send a long message in a dialog window.")]
|
||||
[Permission(MyPromoteLevel.None)]
|
||||
public void LongHelp()
|
||||
{
|
||||
@@ -107,13 +109,20 @@ namespace Torch.Commands
|
||||
}
|
||||
else
|
||||
{
|
||||
var sb = new StringBuilder("Available commands:\n");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var command in commandManager.Commands.WalkTree())
|
||||
{
|
||||
if (command.IsCommand)
|
||||
sb.AppendLine($"{command.Command.SyntaxHelp}\n {command.Command.HelpText}");
|
||||
}
|
||||
Context.Respond(sb.ToString());
|
||||
|
||||
if (!Context.SentBySelf)
|
||||
{
|
||||
var m = new DialogMessage("Torch Help", subtitle: "Available commands:", content: sb.ToString());
|
||||
ModCommunication.SendMessageTo(m, Context.Player.SteamUserId);
|
||||
}
|
||||
else
|
||||
Context.Respond($"Available commands: {sb}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,6 +178,13 @@ namespace Torch.Commands
|
||||
});
|
||||
}
|
||||
|
||||
[Command("notify", "Shows a message as a notification in the middle of all players' screens.")]
|
||||
[Permission(MyPromoteLevel.Admin)]
|
||||
public void Notify(string message, int disappearTimeMs = 2000, string font = "White")
|
||||
{
|
||||
ModCommunication.SendMessageToClients(new NotificationMessage(message, disappearTimeMs, font));
|
||||
}
|
||||
|
||||
[Command("restart cancel", "Cancel a pending restart.")]
|
||||
public void CancelRestart()
|
||||
{
|
||||
|
29
Torch/Patches/SessionDownloadPatch.cs
Normal file
29
Torch/Patches/SessionDownloadPatch.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Sandbox.Game.World;
|
||||
using Torch.Managers.PatchManager;
|
||||
using Torch.Mod;
|
||||
using VRage.Game;
|
||||
|
||||
namespace Torch.Patches
|
||||
{
|
||||
[PatchShim]
|
||||
internal class SessionDownloadPatch
|
||||
{
|
||||
internal static void Patch(PatchContext context)
|
||||
{
|
||||
context.GetPattern(typeof(MySession).GetMethod(nameof(MySession.GetWorld))).Suffixes.Add(typeof(SessionDownloadPatch).GetMethod(nameof(SuffixGetWorld), BindingFlags.Static | BindingFlags.NonPublic));
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
private static void SuffixGetWorld(ref MyObjectBuilder_World __result)
|
||||
{
|
||||
if (!__result.Checkpoint.Mods.Any(m => m.PublishedFileId == TorchModCore.MOD_ID))
|
||||
__result.Checkpoint.Mods.Add(new MyObjectBuilder_Checkpoint.ModItem(TorchModCore.MOD_ID));
|
||||
}
|
||||
}
|
||||
}
|
@@ -209,6 +209,7 @@
|
||||
<Compile Include="Patches\GameAnalyticsPatch.cs" />
|
||||
<Compile Include="Patches\GameStatePatchShim.cs" />
|
||||
<Compile Include="Patches\ObjectFactoryInitPatch.cs" />
|
||||
<Compile Include="Patches\SessionDownloadPatch.cs" />
|
||||
<Compile Include="Patches\TorchAsyncSaving.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Collections\KeyTree.cs" />
|
||||
@@ -318,6 +319,7 @@
|
||||
<ItemGroup>
|
||||
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
|
||||
</ItemGroup>
|
||||
<Import Project="..\Torch.Mod\Torch.Mod.projitems" Label="Shared" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(SolutionDir)\TransformOnBuild.targets" />
|
||||
</Project>
|
Reference in New Issue
Block a user