@@ -2,7 +2,7 @@ import * as dgram from 'dgram';
22import  *  as  net  from  'net' ; 
33import  {  UnityBinaryManager ,  UnityDetectionEvent  }  from  './unityBinaryManager' ; 
44import  {  logWithLimit  }  from  './utils' ; 
5- import  {  EventEmitter  }  from  './eventEmitter' ; 
5+ import  {  EventEmitter ,   VoidEventEmitter  }  from  './eventEmitter' ; 
66import  {  wait  }  from  './asyncUtils' ; 
77
88export  enum  MessageType  { 
@@ -68,6 +68,11 @@ export interface TestAdaptorContainer {
6868    TestAdaptors : TestAdaptor [ ] ; 
6969} 
7070
71+ export  interface  TestListRetrievedData  { 
72+     testMode : 'EditMode'  |  'PlayMode' ; 
73+     testContainer : TestAdaptorContainer ; 
74+ } 
75+ 
7176export  enum  TestStatusAdaptor  { 
7277    Passed  =  0 , 
7378    Skipped  =  1 , 
@@ -166,11 +171,7 @@ export class UnityMessagingClient {
166171     */ 
167172    private  unityAddress : string  =  '127.0.0.1' ; 
168173
169-     /** 
170-      * Map of message type handlers for processing incoming Unity messages 
171-      * @private  
172-      */ 
173-     private  messageHandlers : Map < MessageType ,  ( message : UnityMessage )  =>  void >  =  new  Map ( ) ; 
174+ 
174175
175176    /** 
176177     * Rate limiting configuration - maps MessageType to minimum interval in milliseconds 
@@ -316,6 +317,48 @@ export class UnityMessagingClient {
316317     */ 
317318    public  readonly  onErrorMessage  =  new  EventEmitter < string > ( ) ; 
318319
320+     /** 
321+      * Event emitter for test list retrieved messages 
322+      * @public  
323+      */ 
324+     public  readonly  onTestListRetrieved  =  new  EventEmitter < TestListRetrievedData > ( ) ; 
325+ 
326+     /** 
327+      * Event emitter for test started messages 
328+      * @public  
329+      */ 
330+     public  readonly  onTestStarted  =  new  EventEmitter < TestAdaptorContainer > ( ) ; 
331+ 
332+     /** 
333+      * Event emitter for test finished messages 
334+      * @public  
335+      */ 
336+     public  readonly  onTestFinished  =  new  EventEmitter < TestResultAdaptorContainer > ( ) ; 
337+ 
338+     /** 
339+      * Event emitter for test run started messages 
340+      * @public  
341+      */ 
342+     public  readonly  onRunStarted  =  new  VoidEventEmitter ( ) ; 
343+ 
344+     /** 
345+      * Event emitter for test run finished messages 
346+      * @public  
347+      */ 
348+     public  readonly  onRunFinished  =  new  VoidEventEmitter ( ) ; 
349+ 
350+     /** 
351+      * Event emitter for execute tests confirmation messages 
352+      * @public  
353+      */ 
354+     public  readonly  onExecuteTests  =  new  EventEmitter < string > ( ) ; 
355+ 
356+     /** 
357+      * Event emitter for compilation finished messages 
358+      * @public  
359+      */ 
360+     public  readonly  onCompilationFinished  =  new  VoidEventEmitter ( ) ; 
361+ 
319362    constructor ( unityBinaryManager : UnityBinaryManager )  { 
320363        this . unityBinaryManager  =  unityBinaryManager ; 
321364        this . setupSocket ( ) ; 
@@ -590,10 +633,16 @@ export class UnityMessagingClient {
590633    } 
591634
592635    /** 
593-      * Register message handler for specific message type 
636+      * Helper method to safely parse JSON strings 
637+      * @param  value The string value to parse 
638+      * @returns  Parsed object or the original string if parsing fails 
594639     */ 
595-     onMessage ( type : MessageType ,  handler : ( message : UnityMessage )  =>  void ) : void { 
596-         this . messageHandlers . set ( type ,  handler ) ; 
640+     private  tryParseJson < T > ( value : string ) : T  |  string  { 
641+         try  { 
642+             return  JSON . parse ( value )  as  T ; 
643+         }  catch  { 
644+             return  value ; 
645+         } 
597646    } 
598647
599648    /** 
@@ -617,62 +666,109 @@ export class UnityMessagingClient {
617666            console . log ( `UnityMessagingClient: Received message - Type: ${ message . type } ${ MessageType [ message . type ]  ||  'Unknown' } ${ message . value }  ) ; 
618667        } 
619668
620-         // Handle Unity online/offline state changes 
621-         let  messageHandledInternally  =  false ; 
622- 
623-         if  ( message . type  ===  MessageType . Online )  { 
624-             messageHandledInternally  =  true ; 
625-             console . log ( 'UnityMessagingClient: Unity online' ) ; 
626-             this . isUnityOnline  =  true ; 
627-             this . onOnlineStatus . emit ( true ) ; 
628- 
629-             this . handleFirstResponse ( ) ; 
630-         }  else  if  ( message . type  ===  MessageType . Offline )  { 
631-             messageHandledInternally  =  true ; 
632-             console . log ( 'UnityMessagingClient: Unity went offline' ) ; 
633-             this . isUnityOnline  =  false ; 
634-             this . onOnlineStatus . emit ( false ) ; 
635-         }  else  if  ( message . type  ===  MessageType . Pong )  { 
636-             messageHandledInternally  =  true ; 
637-             // Pong response indicates Unity is online and responding 
638-             if  ( ! this . isUnityOnline )  { 
639-                 console . log ( 'UnityMessagingClient: Unity online (pong received)' ) ; 
669+         switch  ( message . type )  { 
670+             case  MessageType . Online :
671+                 console . log ( 'UnityMessagingClient: Unity online' ) ; 
640672                this . isUnityOnline  =  true ; 
641673                this . onOnlineStatus . emit ( true ) ; 
642- 
643-             } 
644-             this . handleFirstResponse ( ) ; 
645-         }  else  if  ( message . type  ===  MessageType . PackageName )  { 
646-             messageHandledInternally  =  true ; 
647-             if  ( message . value )  { 
648-                 this . packageName  =  message . value ; 
649-                 console . log ( `UnityMessagingClient: Detected Unity package: ${ this . packageName }  ) ; 
674+                 this . handleFirstResponse ( ) ; 
675+                 break ; 
676+             case  MessageType . Offline :
677+                 console . log ( 'UnityMessagingClient: Unity went offline' ) ; 
678+                 this . isUnityOnline  =  false ; 
679+                 this . onOnlineStatus . emit ( false ) ; 
680+                 break ; 
681+             case  MessageType . Pong :
682+                 // Pong response indicates Unity is online and responding 
683+                 if  ( ! this . isUnityOnline )  { 
684+                     console . log ( 'UnityMessagingClient: Unity online (pong received)' ) ; 
685+                     this . isUnityOnline  =  true ; 
686+                     this . onOnlineStatus . emit ( true ) ; 
687+                 } 
688+                 this . handleFirstResponse ( ) ; 
689+                 break ; 
690+             case  MessageType . PackageName :
691+                 if  ( message . value )  { 
692+                     this . packageName  =  message . value ; 
693+                     console . log ( `UnityMessagingClient: Detected Unity package: ${ this . packageName }  ) ; 
694+                 } 
695+                 break ; 
696+             case  MessageType . Info :
697+                 this . onInfoMessage . emit ( message . value ) ; 
698+                 break ; 
699+             case  MessageType . Warning :
700+                 this . onWarningMessage . emit ( message . value ) ; 
701+                 break ; 
702+             case  MessageType . Error :
703+                 this . onErrorMessage . emit ( message . value ) ; 
704+                 break ; 
705+             case  MessageType . IsPlaying : { 
706+                 const  isPlaying  =  message . value  ===  'true' ; 
707+                 console . log ( `UnityMessagingClient: Unity play mode changed - IsPlaying: ${ isPlaying }  ) ; 
708+                 this . isUnityEditorPlaying  =  isPlaying ; 
709+                 this . onPlayStatus . emit ( isPlaying ) ; 
710+                 break ; 
650711            } 
651-         }  else  if  ( message . type  ===  MessageType . Info )  { 
652-             messageHandledInternally  =  true ; 
653-             this . onInfoMessage . emit ( message . value ) ; 
654-         }  else  if  ( message . type  ===  MessageType . Warning )  { 
655-             messageHandledInternally  =  true ; 
656-             this . onWarningMessage . emit ( message . value ) ; 
657-         }  else  if  ( message . type  ===  MessageType . Error )  { 
658-             messageHandledInternally  =  true ; 
659-             this . onErrorMessage . emit ( message . value ) ; 
660-         }  else  if  ( message . type  ===  MessageType . IsPlaying )  { 
661-             messageHandledInternally  =  true ; 
662-             const  isPlaying  =  message . value  ===  'true' ; 
663-             console . log ( `UnityMessagingClient: Unity play mode changed - IsPlaying: ${ isPlaying }  ) ; 
664-             this . isUnityEditorPlaying  =  isPlaying ; 
665-             this . onPlayStatus . emit ( isPlaying ) ; 
666-         }  else  if  ( message . type  ===  MessageType . Tcp )  { 
667-             messageHandledInternally  =  true ; 
668-             this . handleTcpMessage ( message ) ; 
669-         } 
670- 
671-         const  handler  =  this . messageHandlers . get ( message . type ) ; 
672-         if  ( handler )  { 
673-             handler ( message ) ; 
674-         }  else  if  ( ! messageHandledInternally )  { 
675-             console . log ( `UnityMessagingClient: No handler registered for message type ${ message . type } ${ MessageType [ message . type ]  ||  'Unknown' }  ) ; 
712+             case  MessageType . Tcp :
713+                 this . handleTcpMessage ( message ) ; 
714+                 break ; 
715+             case  MessageType . TestListRetrieved :
716+                 if  ( this . onTestListRetrieved . hasListeners )  { 
717+                     // Parse TestListRetrieved format: "TestMode:JsonData" 
718+                     const  colonIndex  =  message . value . indexOf ( ':' ) ; 
719+                     if  ( colonIndex  >  0 )  { 
720+                         const  testMode  =  message . value . substring ( 0 ,  colonIndex ) ; 
721+                         const  jsonData  =  message . value . substring ( colonIndex  +  1 ) ; 
722+                         const  testData  =  this . tryParseJson < TestAdaptorContainer > ( jsonData ) ; 
723+                         if  ( typeof  testData  ===  'object' )  { 
724+                               // Emit with proper type structure 
725+                               this . onTestListRetrieved . emit ( { 
726+                                   testMode : testMode  as  'EditMode'  |  'PlayMode' , 
727+                                   testContainer : testData 
728+                               } ) ; 
729+                           } 
730+                     } 
731+                 } 
732+                 break ; 
733+             case  MessageType . TestStarted :
734+                 if  ( this . onTestStarted . hasListeners )  { 
735+                     const  testContainer  =  this . tryParseJson < TestAdaptorContainer > ( message . value ) ; 
736+                     if  ( typeof  testContainer  ===  'object' )  { 
737+                         this . onTestStarted . emit ( testContainer ) ; 
738+                     } 
739+                 } 
740+                 break ; 
741+             case  MessageType . TestFinished :
742+                 if  ( this . onTestFinished . hasListeners )  { 
743+                     const  testResult  =  this . tryParseJson < TestResultAdaptorContainer > ( message . value ) ; 
744+                     if  ( typeof  testResult  ===  'object' )  { 
745+                         this . onTestFinished . emit ( testResult ) ; 
746+                     } 
747+                 } 
748+                 break ; 
749+             case  MessageType . RunStarted :
750+                 if  ( this . onRunStarted . hasListeners )  { 
751+                     this . onRunStarted . emit ( ) ; 
752+                 } 
753+                 break ; 
754+             case  MessageType . RunFinished :
755+                 if  ( this . onRunFinished . hasListeners )  { 
756+                     this . onRunFinished . emit ( ) ; 
757+                 } 
758+                 break ; 
759+             case  MessageType . ExecuteTests :
760+                 if  ( this . onExecuteTests . hasListeners )  { 
761+                     this . onExecuteTests . emit ( message . value ) ; 
762+                 } 
763+                 break ; 
764+             case  MessageType . CompilationFinished :
765+                 if  ( this . onCompilationFinished . hasListeners )  { 
766+                     this . onCompilationFinished . emit ( ) ; 
767+                 } 
768+                 break ; 
769+             default :
770+                 console . log ( `UnityMessagingClient: No handler for message type ${ message . type } ${ MessageType [ message . type ]  ||  'Unknown' }  ) ; 
771+                 break ; 
676772        } 
677773    } 
678774
0 commit comments