@@ -23,6 +23,9 @@ public class ActivityWatcher : IDisposable
2323 private const string GameInactivityTimeoutEntry = "[FLog::Network] Sending disconnect with reason: 1" ;
2424 private const string GameConnectionLostEntry = "[FLog::Network] Lost connection with reason : Lost connection to the game server, please reconnect" ;
2525
26+ private const string StudioPlaceOpenEntry = "[FLog::PlaceManager] Start to open place" ;
27+ private const string StudioPlaceCloseEntry = "[FLog::PlaceManager] PlaceManager::closeCurrentPlayDoc" ;
28+
2629 private const string GameJoiningEntryPattern = @"! Joining game '([0-9a-f\-]{36})' place ([0-9]+) at ([0-9\.]+)" ;
2730 private const string GameJoiningPrivateServerPattern = @"""accessCode"":""([0-9a-f\-]{36})""" ;
2831 private const string GameJoiningUniversePattern = @"universeid:([0-9]+).*userid:([0-9]+)" ;
@@ -41,6 +44,8 @@ public class ActivityWatcher : IDisposable
4144 public event EventHandler < string > ? OnLogEntry ;
4245 public event EventHandler ? OnGameJoin ;
4346 public event EventHandler ? OnGameLeave ;
47+ public event EventHandler ? OnStudioPlaceOpened ;
48+ public event EventHandler ? OnStudioPlaceClosed ;
4449 public event EventHandler ? OnLogOpen ;
4550 public event EventHandler ? OnAppClose ;
4651 public event EventHandler < Message > ? OnRPCMessage ;
@@ -55,6 +60,7 @@ public class ActivityWatcher : IDisposable
5560 public string LogLocation = null ! ;
5661
5762 public bool InGame = false ;
63+ public bool InStudioPlace = false ;
5864 public bool InRobloxStudio = false ;
5965
6066 public ActivityData Data { get ; private set ; } = new ( ) ;
@@ -194,72 +200,92 @@ private void ProcessStudioLogEntry(string logMessage)
194200 InRobloxStudio = true ;
195201 }
196202
197- if ( logMessage . StartsWith ( StudioMessageEntry ) )
203+ if ( ! InStudioPlace )
198204 {
199- var match = Regex . Match ( logMessage , StudioMessagePattern ) ;
200-
201- if ( match . Groups . Count != 2 )
205+ if ( logMessage . Contains ( StudioPlaceOpenEntry ) )
202206 {
203- App . Logger . WriteLine ( LOG_IDENT , "Failed to parse Studio RPC message" ) ;
204- return ;
205- }
206-
207- string studioMessage = match . Groups [ 1 ] . Value ;
208- App . Logger . WriteLine ( LOG_IDENT , $ "Studio RPC: { studioMessage } ") ;
207+ InStudioPlace = true ;
208+ App . Logger . WriteLine ( LOG_IDENT , "Studio place opened" ) ;
209209
210- if ( studioMessage . Contains ( "| Workspace: Game" ) )
211- {
212- App . Logger . WriteLine ( LOG_IDENT , "Ignoring message because workspace is 'Game'" ) ;
213- return ;
210+ OnStudioPlaceOpened ? . Invoke ( this , EventArgs . Empty ) ;
214211 }
212+ }
213+ else if ( InStudioPlace )
214+ {
215+ if ( logMessage . Contains ( StudioPlaceCloseEntry ) )
216+ {
217+ App . Logger . WriteLine ( LOG_IDENT , "Studio place closed" ) ;
218+ InStudioPlace = false ;
215219
216- string workspace = "" ;
217- string activityState = studioMessage ;
218- bool testing = false ;
219- string scriptType = "developing" ;
220-
221- string [ ] parts = studioMessage . Split ( new [ ] { " | " } , StringSplitOptions . None ) ;
222-
223- foreach ( string part in parts )
220+ OnStudioPlaceClosed ? . Invoke ( this , EventArgs . Empty ) ;
221+ }
222+ else if ( logMessage . StartsWith ( StudioMessageEntry ) )
224223 {
225- if ( part . StartsWith ( "Workspace:" ) )
226- {
227- workspace = part . Substring ( 10 ) . Trim ( ) ;
228- }
229- else if ( part . StartsWith ( "Testing:" ) )
224+ var match = Regex . Match ( logMessage , StudioMessagePattern ) ;
225+
226+ if ( match . Groups . Count != 2 )
230227 {
231- string testingStr = part . Substring ( 8 ) . Trim ( ) ;
232- testing = testingStr . Equals ( "True" , StringComparison . OrdinalIgnoreCase ) ;
228+ App . Logger . WriteLine ( LOG_IDENT , "Failed to parse Studio RPC message" ) ;
229+ return ;
233230 }
234- else if ( part . StartsWith ( "Type:" ) )
231+
232+ string studioMessage = match . Groups [ 1 ] . Value ;
233+ App . Logger . WriteLine ( LOG_IDENT , $ "Studio RPC: { studioMessage } ") ;
234+
235+ if ( studioMessage . Contains ( "| Workspace: Game" ) )
235236 {
236- scriptType = part . Substring ( 5 ) . Trim ( ) ;
237+ App . Logger . WriteLine ( LOG_IDENT , "Ignoring message because workspace is 'Game'" ) ;
238+ return ;
237239 }
238- else if ( ! part . Contains ( "Workspace:" ) && ! part . Contains ( "Testing:" ) && ! part . Contains ( "Type:" ) )
240+
241+ string workspace = "" ;
242+ string activityState = studioMessage ;
243+ bool testing = false ;
244+ string scriptType = "developing" ;
245+
246+ string [ ] parts = studioMessage . Split ( new [ ] { " | " } , StringSplitOptions . None ) ;
247+
248+ foreach ( string part in parts )
239249 {
240- activityState = part . Trim ( ) ;
250+ if ( part . StartsWith ( "Workspace:" ) )
251+ {
252+ workspace = part . Substring ( 10 ) . Trim ( ) ;
253+ }
254+ else if ( part . StartsWith ( "Testing:" ) )
255+ {
256+ string testingStr = part . Substring ( 8 ) . Trim ( ) ;
257+ testing = testingStr . Equals ( "True" , StringComparison . OrdinalIgnoreCase ) ;
258+ }
259+ else if ( part . StartsWith ( "Type:" ) )
260+ {
261+ scriptType = part . Substring ( 5 ) . Trim ( ) ;
262+ }
263+ else if ( ! part . Contains ( "Workspace:" ) && ! part . Contains ( "Testing:" ) && ! part . Contains ( "Type:" ) )
264+ {
265+ activityState = part . Trim ( ) ;
266+ }
241267 }
242- }
243268
244- var studioRpc = new StudioMessage
245- {
246- Data = new StudioRichPresence
269+ var studioRpc = new StudioMessage
247270 {
248- Details = activityState ,
249- State = ! string . IsNullOrEmpty ( workspace ) ? $ "Workspace: { workspace } " : null ! ,
250- TimestampStart = ( ulong ) DateTimeOffset . UtcNow . ToUnixTimeSeconds ( ) ,
251- Testing = testing ,
252- ScriptType = scriptType
253- }
254- } ;
271+ Data = new StudioRichPresence
272+ {
273+ Details = activityState ,
274+ State = ! string . IsNullOrEmpty ( workspace ) ? $ "Workspace: { workspace } " : null ! ,
275+ TimestampStart = ( ulong ) DateTimeOffset . UtcNow . ToUnixTimeSeconds ( ) ,
276+ Testing = testing ,
277+ ScriptType = scriptType
278+ }
279+ } ;
255280
256- string json = JsonSerializer . Serialize ( studioRpc ) ;
257- var rpcMessage = JsonSerializer . Deserialize < Message > ( json ) ;
281+ string json = JsonSerializer . Serialize ( studioRpc ) ;
282+ var rpcMessage = JsonSerializer . Deserialize < Message > ( json ) ;
258283
259- if ( rpcMessage != null )
260- {
261- OnRPCMessage ? . Invoke ( this , rpcMessage ) ;
262- App . Logger . WriteLine ( LOG_IDENT , $ "Sent Studio RPC: Details: { activityState } | Type: { scriptType } | Testing: { testing } ") ;
284+ if ( rpcMessage != null )
285+ {
286+ OnRPCMessage ? . Invoke ( this , rpcMessage ) ;
287+ App . Logger . WriteLine ( LOG_IDENT , $ "Sent Studio RPC: Details: { activityState } | Type: { scriptType } | Testing: { testing } ") ;
288+ }
263289 }
264290 }
265291 }
0 commit comments