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) + { + + } + + ///