Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

namespace RegressionGames.ClientDashboard
{

/// <summary>
/// Starts and stops RGTcpServer, handles and sends messages to and from connected clients
/// </summary>
Expand All @@ -26,10 +25,16 @@ public class RGTcpManager : MonoBehaviour
{
// the last active sequence that was sent to the client
private static BotSegmentsPlaybackController m_botSegmentsPlaybackController;
private static BotSequence m_startPlayingSequence = null;
private static ActiveSequence m_activeSequence = null;
private static ReplayToolbarManager m_replayToolbarManager;

private static List<AvailableBotSequence> m_availableBotSequences = new ();
private static List<BotSequenceEntry> m_availableBotSegments = new();

private static ActiveSequence m_activeSequence = null;
private static BotSequence m_startPlayingSequence = null;
private static BotSegmentList m_startPlayingSegment = null;
private static bool m_shouldStopReplay = false;


public void Start()
{
Expand All @@ -52,6 +57,7 @@ public void Start()
RGTcpServer.ProcessClientMessage += ProcessClientMessage;
RGTcpServer.Start();
StartCoroutine(RGSequenceManager.ResolveSequenceFiles(ProcessAndSendSequences));
ProcessAndSendSegments();
}

/// <summary>
Expand All @@ -73,17 +79,43 @@ private void Update()
SendActiveSequence();
}

// check if we need to start playing a sequence
// check if we need to start playing a sequence or segment
if (m_startPlayingSequence != null)
{
var botManager = RGBotManager.GetInstance();
if (botManager != null)
if (activeSequence == null)
{
var botManager = RGBotManager.GetInstance();
if (botManager != null)
{
botManager.OnBeginPlaying();
}
m_replayToolbarManager.selectedReplayFilePath = null;
m_startPlayingSequence.Play();
}
m_startPlayingSequence = null;
m_startPlayingSegment = null;
m_shouldStopReplay = false;
}
else if (m_startPlayingSegment != null)
{
if (activeSequence == null)
{
botManager.OnBeginPlaying();
var botManager = RGBotManager.GetInstance();
if (botManager != null)
{
botManager.OnBeginPlaying();
}
m_botSegmentsPlaybackController.SetDataContainer(new BotSegmentsPlaybackContainer(m_startPlayingSegment.segments));
m_botSegmentsPlaybackController.Play();
}
m_replayToolbarManager.selectedReplayFilePath = null;
m_startPlayingSequence.Play();
m_startPlayingSequence = null;
m_startPlayingSegment = null;
m_shouldStopReplay = false;
}
else if (m_shouldStopReplay)
{
m_replayToolbarManager.StopReplay();
m_shouldStopReplay = false;
}
}

Expand Down Expand Up @@ -120,6 +152,7 @@ private static void DidReloadScripts()

var it = RGSequenceManager.ResolveSequenceFiles(ProcessAndSendSequences);
while(it.MoveNext()){}
ProcessAndSendSegments();
}

/// <summary>
Expand Down Expand Up @@ -170,6 +203,7 @@ private static void OnClientHandshake(TcpClient client)
{
SendActiveSequence();
SendAvailableSequences();
SendAvailableSegments();
}

/// <summary>
Expand All @@ -185,11 +219,23 @@ private static void ProcessClientMessage(TcpClient client, TcpMessage message)
}
case TcpMessageType.PlaySequence:
{
var playSequenceData = (PlaySequenceTcpMessageData) message.payload;
var playSequenceData = (PlayResourceTcpMessageData) message.payload;
var botSequence = BotSequence.LoadSequenceJsonFromPath(playSequenceData.resourcePath);
m_startPlayingSequence = botSequence.Item3;
break;
}
case TcpMessageType.PlaySegment:
{
var playSegmentData = (PlayResourceTcpMessageData) message.payload;
var segmentList = BotSequence.CreateBotSegmentListForPath(playSegmentData.resourcePath, out var sessId);
m_startPlayingSegment = segmentList;
break;
}
case TcpMessageType.StopReplay:
{
m_shouldStopReplay = true;
break;
}
}
}

Expand All @@ -207,6 +253,12 @@ private static void ProcessAndSendSequences(IDictionary<string, (string, BotSequ
SendAvailableSequences();
}

private static void ProcessAndSendSegments()
{
m_availableBotSegments = BotSegment.LoadAllSegments().Values.Select(seg => seg.Item2).ToList();
SendAvailableSegments();
}

/// <summary>
/// Returns the active bot sequence, if there is one
/// </summary>
Expand Down Expand Up @@ -261,6 +313,19 @@ private static void SendAvailableSequences([CanBeNull] TcpClient client = null)
RGTcpServer.QueueMessage(message, client);
}

private static void SendAvailableSegments([CanBeNull] TcpClient client = null)
{
var message = new TcpMessage
{
type = TcpMessageType.AvailableSegments,
payload = new AvailableSegmentsTcpMessageData
{
availableSegments = m_availableBotSegments
}
};
RGTcpServer.QueueMessage(message, client);
}

private static void SendActiveSequence([CanBeNull] TcpClient client = null)
{
var message = new TcpMessage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using RegressionGames.RemoteOrchestration.Models;
using RegressionGames.RemoteOrchestration.Types;
using RegressionGames.StateRecorder;
using RegressionGames.StateRecorder.BotSegments.Models;
using RegressionGames.StateRecorder.JsonConverters;

namespace RegressionGames.ClientDashboard
Expand All @@ -17,17 +18,22 @@ public enum TcpMessageType

Ping,

// client requests to play a sequence with the given resourcePath
// client requests to play a resource with the given resourcePath
PlaySequence,
PlaySegment,

// stops any currently-running sequence/segments
StopReplay,

// =====================
// server -> client
// =====================

Pong,

// info about the available sequences for this game instance
// info about the available file-based resources for this game instance
AvailableSequences,
AvailableSegments,

// info about the currently-running sequence (or segment)
ActiveSequence,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Future (non-blocking), I have a task to create a status manager to better isolate the current status of which segment we're on, what the current error state is, whether exploration is active, and the current exploration error state. We'll want to be able to sync that to the client, but I wanted to put this comment here for visibility into what is coming

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, would love to adopt Addison's mockups into this dashboard. We have a lot more freedom here to show detailed information about the current segment, progression through a sequence, any errors, etc.

Expand Down Expand Up @@ -124,7 +130,53 @@ public override string ToString()
}

[Serializable]
public class PlaySequenceTcpMessageData : ITcpMessageData
public class AvailableSegmentsTcpMessageData : ITcpMessageData
{
public List<BotSequenceEntry> availableSegments;

public void WriteToStringBuilder(StringBuilder stringBuilder)
{
stringBuilder.Append("{\"availableSegments\":[");
var availableSegmentsCount = availableSegments.Count;
for (var i = 0; i < availableSegmentsCount; i++)
{
// a lot of the fields on BotSequenceEntry are not written to string builder
// so pick what we need for the dashboard here...
var currentSegment = availableSegments[i];

stringBuilder.Append("{\"apiVersion\":");
IntJsonConverter.WriteToStringBuilder(stringBuilder, currentSegment.apiVersion);

// not normally serialized
stringBuilder.Append(",\"resourcePath\":");
StringJsonConverter.WriteToStringBuilder(stringBuilder, currentSegment.resourcePath);
stringBuilder.Append(",\"type\":");
StringJsonConverter.WriteToStringBuilder(stringBuilder, currentSegment.type.ToString());
stringBuilder.Append(",\"name\":");
StringJsonConverter.WriteToStringBuilder(stringBuilder, currentSegment.name);
stringBuilder.Append(",\"description\":");
StringJsonConverter.WriteToStringBuilder(stringBuilder, currentSegment.description);

stringBuilder.Append("}");

if (i + 1 < availableSegmentsCount)
{
stringBuilder.Append(",");
}
}
stringBuilder.Append("]}");
}

public override string ToString()
{
StringBuilder sb = new StringBuilder(1000);
WriteToStringBuilder(sb);
return sb.ToString();
}
}

[Serializable]
public class PlayResourceTcpMessageData : ITcpMessageData
{
public string resourcePath;

Expand All @@ -142,4 +194,5 @@ public override string ToString()
return sb.ToString();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
{
case TcpMessageType.Ping:
case TcpMessageType.Pong:
case TcpMessageType.StopReplay:
case TcpMessageType.CloseConnection:
// these messages have no payload
break;
Expand All @@ -31,8 +32,12 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
case TcpMessageType.AvailableSequences:
payload = jObject["payload"].ToObject<AvailableSequencesTcpMessageData>(serializer);
break;
case TcpMessageType.AvailableSegments:
payload = jObject["payload"].ToObject<AvailableSegmentsTcpMessageData>(serializer);
break;
case TcpMessageType.PlaySequence:
payload = jObject["payload"].ToObject<PlaySequenceTcpMessageData>(serializer);
case TcpMessageType.PlaySegment:
payload = jObject["payload"].ToObject<PlayResourceTcpMessageData>(serializer);
break;
default:
throw new JsonSerializationException($"Unsupported TcpMessage type: '{message.type}'");
Expand Down
Loading