@@ -13,11 +13,11 @@ import {
13
13
ThreadEvent ,
14
14
Variable ,
15
15
} from '@vscode/debugadapter' ;
16
+ import { commands , FileSystemWatcher , QuickPickItem , QuickPickOptions , workspace , window } from 'vscode' ;
16
17
import { DebugProtocol } from '@vscode/debugprotocol' ;
17
18
import { LogOutputEvent , LogLevel } from '@vscode/debugadapter/lib/logger' ;
18
19
import { MessageStreamParser } from './MessageStreamParser' ;
19
20
import { SourceMaps } from './SourceMaps' ;
20
- import { FileSystemWatcher , window , workspace , commands } from 'vscode' ;
21
21
import * as path from 'path' ;
22
22
import * as fs from 'fs' ;
23
23
import { isUUID } from './Utils' ;
@@ -33,6 +33,17 @@ interface ModuleMapping {
33
33
[ moduleName : string ] : string ;
34
34
}
35
35
36
+ interface PluginDetails {
37
+ name : string ;
38
+ module_uuid : string ;
39
+ }
40
+
41
+ interface ProtocolCapabilities {
42
+ type : string ;
43
+ version : number ;
44
+ plugins : PluginDetails [ ] ;
45
+ }
46
+
36
47
// Interface for specific launch arguments.
37
48
// See package.json for schema.
38
49
interface IAttachRequestArguments extends DebugProtocol . AttachRequestArguments {
@@ -49,10 +60,33 @@ interface IAttachRequestArguments extends DebugProtocol.AttachRequestArguments {
49
60
targetModuleUuid ?: string ;
50
61
}
51
62
63
+ class TargetPluginItem implements QuickPickItem {
64
+ public label : string ;
65
+ public detail : string ;
66
+ public targetModuleId : string ;
67
+
68
+ constructor ( pluginDetails : PluginDetails ) {
69
+ this . label = pluginDetails . name ;
70
+ this . detail = 'Script module uuid ' + pluginDetails . module_uuid ;
71
+ this . targetModuleId = pluginDetails . module_uuid ;
72
+ }
73
+ }
74
+
75
+ // protocol version history
76
+ // 1 - initial version
77
+ // 2 - add targetModuleUuid to protocol event
78
+ // 3 - add array of plugins and target module ids to incoming protocol event
79
+ enum ProtcolVersion {
80
+ Initial = 1 ,
81
+ SupportTargetModuleUuid = 2 ,
82
+ SupportTargetSelection = 3 ,
83
+ }
84
+
52
85
// The Debug Adapter for 'minecraft-js'
53
86
//
54
87
export class Session extends DebugSession {
55
- private static DEBUGGER_PROTOCOL_VERSION = 2 ;
88
+ private static DEBUGGER_PROTOCOL_VERSION = ProtcolVersion . SupportTargetSelection ;
89
+
56
90
private static CONNECTION_RETRY_ATTEMPTS = 5 ;
57
91
private static CONNECTION_RETRY_WAIT_MS = 2000 ;
58
92
@@ -132,13 +166,7 @@ export class Session extends DebugSession {
132
166
this . sendErrorResponse ( response , 1001 , `Failed to attach to Minecraft, invalid port "${ args . inputPort } ".` ) ;
133
167
return ;
134
168
}
135
-
136
- if ( ! args . targetModuleUuid || args . targetModuleUuid === '' || ! isUUID ( args . targetModuleUuid ) ) {
137
- this . showNotification (
138
- 'Launch config module target (targetModuleUuid) is not a valid uuid. This should be set to the script module uuid from your manifest.json. Omitting this may cause problems when multiple Minecraft Add-Ons are active.' ,
139
- LogLevel . Warn
140
- ) ;
141
- } else {
169
+ if ( args . targetModuleUuid && isUUID ( args . targetModuleUuid ) ) {
142
170
this . _targetModuleUuid = args . targetModuleUuid . toLowerCase ( ) ;
143
171
}
144
172
@@ -477,7 +505,19 @@ export class Session extends DebugSession {
477
505
//
478
506
}
479
507
480
- private onConnectionComplete ( ) {
508
+ private onConnectionComplete ( targetModuleUuid ?: string ) {
509
+ this . _targetModuleUuid = targetModuleUuid ;
510
+
511
+ // respond with protocol version and chosen debugee target
512
+ this . sendDebuggeeMessage ( {
513
+ type : 'protocol' ,
514
+ version : Session . DEBUGGER_PROTOCOL_VERSION ,
515
+ target_module_uuid : targetModuleUuid ,
516
+ } ) ;
517
+
518
+ // show notifications for source map issues
519
+ this . checkSourceFilePaths ( ) ;
520
+
481
521
// success
482
522
this . showNotification ( 'Success! Debugger is now connected.' , LogLevel . Log ) ;
483
523
@@ -620,8 +660,10 @@ export class Session extends DebugSession {
620
660
this . sendEvent ( new ThreadEvent ( eventMessage . reason , eventMessage . thread ) ) ;
621
661
} else if ( eventMessage . type === 'PrintEvent' ) {
622
662
this . handlePrintEvent ( eventMessage . message , eventMessage . logLevel ) ;
663
+ } else if ( eventMessage . type === 'NotificationEvent' ) {
664
+ this . showNotification ( eventMessage . message , eventMessage . logLevel ) ;
623
665
} else if ( eventMessage . type === 'ProtocolEvent' ) {
624
- this . handleProtocolEvent ( eventMessage ) ;
666
+ this . handleProtocolEvent ( eventMessage as ProtocolCapabilities ) ;
625
667
} else if ( eventMessage . type === 'StatEvent2' ) {
626
668
this . _statsProvider2 . setStats ( eventMessage as StatMessageModel ) ;
627
669
}
@@ -688,24 +730,66 @@ export class Session extends DebugSession {
688
730
// ------------------------------------------------------------------------
689
731
690
732
// the final client event before connection is complete
691
- private handleProtocolEvent ( protocolCapabilities : any ) {
733
+ private handleProtocolEvent ( protocolCapabilities : ProtocolCapabilities ) {
692
734
//
693
735
// handle protocol capabilities here...
694
736
// can fail connection on errors
695
737
//
696
738
if ( Session . DEBUGGER_PROTOCOL_VERSION < protocolCapabilities . version ) {
697
739
this . terminateSession ( 'protocol mismatch. Update Debugger Extension.' , LogLevel . Error ) ;
698
740
} else {
699
- this . sendDebuggeeMessage ( {
700
- type : 'protocol' ,
701
- version : Session . DEBUGGER_PROTOCOL_VERSION ,
702
- target_module_uuid : this . _targetModuleUuid ,
703
- } ) ;
704
-
705
- this . checkSourceFilePaths ( ) ;
741
+ if ( protocolCapabilities . version == ProtcolVersion . SupportTargetModuleUuid ) {
742
+ this . onConnectionComplete ( this . _targetModuleUuid ) ;
743
+ } else if ( protocolCapabilities . version == ProtcolVersion . SupportTargetSelection ) {
744
+ if ( ! protocolCapabilities . plugins || protocolCapabilities . plugins . length === 0 ) {
745
+ this . terminateSession ( 'protocol error. No Minecraft Add-Ons found.' , LogLevel . Error ) ;
746
+ return ;
747
+ } else if ( this . _targetModuleUuid ) {
748
+ const isValidTarget = protocolCapabilities . plugins . some (
749
+ plugin => plugin . module_uuid === this . _targetModuleUuid
750
+ ) ;
751
+ if ( isValidTarget ) {
752
+ this . onConnectionComplete ( this . _targetModuleUuid ) ;
753
+ return ;
754
+ } else {
755
+ this . showNotification (
756
+ `Minecraft Add-On script module not found with targetModuleUuid ${ this . _targetModuleUuid } specified in launch.json. Prompting for debug target.` ,
757
+ LogLevel . Warn
758
+ ) ;
759
+ }
760
+ } else if ( protocolCapabilities . plugins . length === 1 ) {
761
+ this . onConnectionComplete ( protocolCapabilities . plugins [ 0 ] . module_uuid ) ;
762
+ return ;
763
+ } else {
764
+ this . showNotification (
765
+ 'The targetModuleUuid in launch.json is not set to a valid uuid. Set this to a script module uuid (manifest.json) to avoid the selection prompt.' ,
766
+ LogLevel . Warn
767
+ ) ;
768
+ }
706
769
707
- // success
708
- this . onConnectionComplete ( ) ;
770
+ //
771
+ // Could not connect automatically, prompt user to select target.
772
+ //
773
+ const items : TargetPluginItem [ ] = protocolCapabilities . plugins . map (
774
+ plugin => new TargetPluginItem ( plugin )
775
+ ) ;
776
+ const options : QuickPickOptions = {
777
+ title : 'Choose the Minecraft Add-On to debug' ,
778
+ ignoreFocusOut : true ,
779
+ } ;
780
+ window . showQuickPick ( items , options ) . then ( value => {
781
+ if ( ! value ) {
782
+ this . terminateSession (
783
+ 'could not determine target Minecraft Add-On. You must specify the targetModuleUuid.' ,
784
+ LogLevel . Error
785
+ ) ;
786
+ } else {
787
+ this . onConnectionComplete ( value ?. targetModuleId ) ;
788
+ }
789
+ } ) ;
790
+ } else {
791
+ this . terminateSession ( 'protocol unsupported. Update Debugger Extension.' , LogLevel . Error ) ;
792
+ }
709
793
}
710
794
}
711
795
0 commit comments