Merge pull request #42 from Maldark/master

Add async /save command for admins+ and server console.
This commit is contained in:
John Michael Gross
2017-07-06 16:04:36 -07:00
committed by GitHub
6 changed files with 98 additions and 13 deletions

View File

@@ -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.
/// </summary>
void Stop();
/// <summary>
/// Initializes a save of the game.
/// </summary>
/// <param name="callerId">Id of the player who initiated the save.</param>
void Save(long callerId);
/// <summary>
/// Initialize the Torch instance.

View File

@@ -219,5 +219,41 @@ namespace Torch.Server
{
}
/// <inheritdoc/>
public override void Save(long callerId)
{
base.SaveGameAsync((statusCode) => SaveCompleted(statusCode, callerId));
}
/// <summary>
/// Callback for when save has finished.
/// </summary>
/// <param name="statusCode">Return code of the save operation</param>
/// <param name="callerId">Caller of the save operation</param>
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;
}
}
}
}

View File

@@ -67,5 +67,16 @@ namespace Torch.Commands
Context.Respond("Stopping server.");
Context.Torch.Stop();
}
/// <summary>
/// Initializes a save of the game.
/// Caller id defaults to 0 in the case of triggering the chat command from server.
/// </summary>
[Command("save", "Saves the game.")]
public void Save()
{
Context.Respond("Saving game.");
Context.Torch.Save(Context.Player?.IdentityId ?? 0);
}
}
}
}

13
Torch/SaveGameStatus.cs Normal file
View File

@@ -0,0 +1,13 @@
namespace Torch
{
/// <summary>
/// Describes the possible outcomes when attempting to save the game progress.
/// </summary>
public enum SaveGameStatus : byte
{
Success = 0,
SaveInProgress = 1,
GameNotReady = 2,
TimedOut = 3
};
}

View File

@@ -146,6 +146,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="ChatMessage.cs" />
<Compile Include="SaveGameStatus.cs" />
<Compile Include="Collections\KeyTree.cs" />
<Compile Include="Collections\ObservableDictionary.cs" />
<Compile Include="Collections\RollingAverage.cs" />

View File

@@ -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<SaveGameStatus> 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);
}
/// <inheritdoc />
/// <inheritdoc/>
public virtual void Save(long callerId)
{
}
/// <inheritdoc
public virtual void Start()
{