diff --git a/Torch.API/ITorchBase.cs b/Torch.API/ITorchBase.cs
index 2eecdba..a43aa89 100644
--- a/Torch.API/ITorchBase.cs
+++ b/Torch.API/ITorchBase.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -74,6 +74,12 @@ namespace Torch.API
/// Stop the Torch instance.
///
void Stop();
+
+ ///
+ /// Initializes a save of the game.
+ ///
+ /// Id of the player who initiated the save.
+ void Save(long callerId);
///
/// Initialize the Torch instance.
diff --git a/Torch.Server/TorchServer.cs b/Torch.Server/TorchServer.cs
index 9429a22..813d413 100644
--- a/Torch.Server/TorchServer.cs
+++ b/Torch.Server/TorchServer.cs
@@ -219,5 +219,41 @@ namespace Torch.Server
{
}
+
+ ///
+ public override void Save(long callerId)
+ {
+ base.SaveGameAsync((statusCode) => SaveCompleted(statusCode, callerId));
+ }
+
+ ///
+ /// Callback for when save has finished.
+ ///
+ /// Return code of the save operation
+ /// Caller of the save operation
+ private void SaveCompleted(SaveGameStatus statusCode, long callerId)
+ {
+ switch (statusCode)
+ {
+ case SaveGameStatus.Success:
+ Log.Info("Save completed.");
+ Multiplayer.SendMessage("Saved game.", playerId: callerId);
+ break;
+ case SaveGameStatus.SaveInProgress:
+ Log.Error("Save failed, a save is already in progress.");
+ Multiplayer.SendMessage("Save failed, a save is already in progress.", playerId: callerId, font: MyFontEnum.Red);
+ break;
+ case SaveGameStatus.GameNotReady:
+ Log.Error("Save failed, game was not ready.");
+ Multiplayer.SendMessage("Save failed, game was not ready.", playerId: callerId, font: MyFontEnum.Red);
+ break;
+ case SaveGameStatus.TimedOut:
+ Log.Error("Save failed, save timed out.");
+ Multiplayer.SendMessage("Save failed, save timed out.", playerId: callerId, font: MyFontEnum.Red);
+ break;
+ default:
+ break;
+ }
+ }
}
}
diff --git a/Torch/Commands/TorchCommands.cs b/Torch/Commands/TorchCommands.cs
index 08cae6b..5643ce2 100644
--- a/Torch/Commands/TorchCommands.cs
+++ b/Torch/Commands/TorchCommands.cs
@@ -67,5 +67,16 @@ namespace Torch.Commands
Context.Respond("Stopping server.");
Context.Torch.Stop();
}
+
+ ///
+ /// Initializes a save of the game.
+ /// Caller id defaults to 0 in the case of triggering the chat command from server.
+ ///
+ [Command("save", "Saves the game.")]
+ public void Save()
+ {
+ Context.Respond("Saving game.");
+ Context.Torch.Save(Context.Player?.IdentityId ?? 0);
+ }
}
-}
+}
\ No newline at end of file
diff --git a/Torch/SaveGameStatus.cs b/Torch/SaveGameStatus.cs
new file mode 100644
index 0000000..0309212
--- /dev/null
+++ b/Torch/SaveGameStatus.cs
@@ -0,0 +1,13 @@
+namespace Torch
+{
+ ///
+ /// Describes the possible outcomes when attempting to save the game progress.
+ ///
+ public enum SaveGameStatus : byte
+ {
+ Success = 0,
+ SaveInProgress = 1,
+ GameNotReady = 2,
+ TimedOut = 3
+ };
+}
diff --git a/Torch/Torch.csproj b/Torch/Torch.csproj
index ea93410..b61f3c8 100644
--- a/Torch/Torch.csproj
+++ b/Torch/Torch.csproj
@@ -146,6 +146,7 @@
+
diff --git a/Torch/TorchBase.cs b/Torch/TorchBase.cs
index ddb996a..3f461ae 100644
--- a/Torch/TorchBase.cs
+++ b/Torch/TorchBase.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@@ -123,10 +123,24 @@ namespace Torch
return true;
}
- public async Task SaveGameAsync()
+ public bool IsOnGameThread()
+ {
+ return Thread.CurrentThread.ManagedThreadId == MySandboxGame.Static.UpdateThread.ManagedThreadId;
+ }
+
+ public async Task SaveGameAsync(Action callback)
{
Log.Info("Saving game");
- if (MySandboxGame.IsGameReady && !MyAsyncSaving.InProgress && Sync.IsServer && !(MySession.Static.LocalCharacter?.IsDead ?? true))
+
+ if (!MySandboxGame.IsGameReady)
+ {
+ callback?.Invoke(SaveGameStatus.GameNotReady);
+ }
+ else if(MyAsyncSaving.InProgress)
+ {
+ callback?.Invoke(SaveGameStatus.SaveInProgress);
+ }
+ else
{
using (var e = new AutoResetEvent(false))
{
@@ -139,17 +153,15 @@ namespace Torch
await Task.Run(() =>
{
if (e.WaitOne(60000))
+ {
+ callback?.Invoke(SaveGameStatus.Success);
return;
-
- Log.Error("Save failed!");
- Multiplayer.SendMessage("Save timed out!", "Error");
+ }
+
+ callback?.Invoke(SaveGameStatus.TimedOut);
}).ConfigureAwait(false);
}
}
- else
- {
- Log.Error("Cannot save");
- }
}
#region Game Actions
@@ -293,7 +305,13 @@ namespace Torch
pluginList.Add(this);
}
- ///
+ ///
+ public virtual void Save(long callerId)
+ {
+
+ }
+
+ ///