@px-lsp/protocol 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -674
- package/README.md +25 -25
- package/dist/calendar.d.ts +71 -0
- package/dist/calendar.js +182 -0
- package/dist/calendarFile.d.ts +26 -0
- package/dist/calendarFile.js +109 -0
- package/dist/calendarLoc.d.ts +60 -0
- package/dist/calendarLoc.js +101 -0
- package/dist/configDir.d.ts +17 -0
- package/dist/configDir.js +79 -0
- package/dist/descriptorMod.d.ts +21 -0
- package/dist/descriptorMod.js +61 -5
- package/dist/kinds.d.ts +72 -0
- package/dist/kinds.js +186 -0
- package/dist/protocol.d.ts +661 -4
- package/dist/protocol.js +159 -2
- package/dist/workshopMeta.d.ts +40 -0
- package/dist/workshopMeta.js +146 -0
- package/package.json +1 -1
- package/src/arrays.ts +16 -16
- package/src/calendar.ts +183 -0
- package/src/calendarFile.ts +81 -0
- package/src/calendarLoc.ts +159 -0
- package/src/configDir.ts +47 -0
- package/src/constants.ts +12 -12
- package/src/descriptorMetadata.ts +101 -101
- package/src/descriptorMod.ts +414 -354
- package/src/errorLogParser.ts +136 -136
- package/src/fsWalk.ts +126 -126
- package/src/kinds.ts +205 -0
- package/src/locProperties.ts +43 -43
- package/src/locRefs.ts +38 -38
- package/src/modName.ts +18 -18
- package/src/protocol.ts +2156 -1459
- package/src/regex.ts +19 -19
- package/src/suppression.ts +178 -178
- package/src/tigerParser.ts +79 -79
- package/src/translationCore.ts +140 -140
- package/src/types.ts +90 -90
- package/src/workshopMeta.ts +127 -0
package/src/protocol.ts
CHANGED
|
@@ -1,1459 +1,2156 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Custom LSP protocol between client and server: method names and payload
|
|
3
|
-
* shapes. Everything crossing the process boundary is declared here so both
|
|
4
|
-
* sides compile against one source of truth. docs/PROTOCOL.md documents the
|
|
5
|
-
* contract for non-VSCode clients; treat changes here as API changes.
|
|
6
|
-
*
|
|
7
|
-
* No `vscode` / `vscode-languageserver` imports: plain wire types only.
|
|
8
|
-
*/
|
|
9
|
-
// Referenced only from the {@link IndexStats} doc link below, which ESLint's
|
|
10
|
-
// unused-vars analysis does not see.
|
|
11
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
12
|
-
import type { IndexStats } from "./types";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
*
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
*
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
*
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
*
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
export
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
*
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
export
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
export interface
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
file?: string;
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
line
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
name: string;
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
line
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
/**
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
/**
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
/**
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
/**
|
|
427
|
-
|
|
428
|
-
/**
|
|
429
|
-
|
|
430
|
-
/**
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
/**
|
|
458
|
-
|
|
459
|
-
/**
|
|
460
|
-
*
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
/**
|
|
466
|
-
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
/**
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
/**
|
|
632
|
-
|
|
633
|
-
/**
|
|
634
|
-
|
|
635
|
-
/**
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
/**
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
/**
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
/**
|
|
665
|
-
|
|
666
|
-
/**
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
/**
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
/**
|
|
719
|
-
*
|
|
720
|
-
*
|
|
721
|
-
*
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
*
|
|
731
|
-
*
|
|
732
|
-
*
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
export interface
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
/**
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
/**
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
/**
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
/**
|
|
848
|
-
|
|
849
|
-
/**
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
/** The
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
/**
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
/**
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
*
|
|
927
|
-
*
|
|
928
|
-
*
|
|
929
|
-
*
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
};
|
|
1007
|
-
/**
|
|
1008
|
-
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
/**
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
*
|
|
1083
|
-
*
|
|
1084
|
-
*
|
|
1085
|
-
*
|
|
1086
|
-
*
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
/**
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
*/
|
|
1126
|
-
export
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
}
|
|
1137
|
-
export interface
|
|
1138
|
-
/**
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
|
-
/**
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
/**
|
|
1166
|
-
|
|
1167
|
-
/**
|
|
1168
|
-
|
|
1169
|
-
/**
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
*
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
export interface
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
}
|
|
1218
|
-
export interface
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
*
|
|
1237
|
-
*
|
|
1238
|
-
*
|
|
1239
|
-
*
|
|
1240
|
-
*
|
|
1241
|
-
*
|
|
1242
|
-
*
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
*
|
|
1246
|
-
*
|
|
1247
|
-
*
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
*/
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
export
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
/**
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
export interface
|
|
1304
|
-
/**
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
/**
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
/**
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
export interface
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
*/
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
/**
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
/**
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
/** The
|
|
1451
|
-
|
|
1452
|
-
/**
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Custom LSP protocol between client and server: method names and payload
|
|
3
|
+
* shapes. Everything crossing the process boundary is declared here so both
|
|
4
|
+
* sides compile against one source of truth. docs/PROTOCOL.md documents the
|
|
5
|
+
* contract for non-VSCode clients; treat changes here as API changes.
|
|
6
|
+
*
|
|
7
|
+
* No `vscode` / `vscode-languageserver` imports: plain wire types only.
|
|
8
|
+
*/
|
|
9
|
+
// Referenced only from the {@link IndexStats} doc link below, which ESLint's
|
|
10
|
+
// unused-vars analysis does not see.
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
12
|
+
import type { IndexStats } from "./types";
|
|
13
|
+
import type { DefSource } from "./types";
|
|
14
|
+
|
|
15
|
+
/** Resolved extension settings, computed client-side (path validation, Steam
|
|
16
|
+
* detection fallbacks, workspace-folder default) and pushed to the server. */
|
|
17
|
+
export interface ParadoxSettings {
|
|
18
|
+
/** Game profile id; absent/unknown ids fall back to the server's default
|
|
19
|
+
* game. Detected client-side per workspace (descriptor file, else setting). */
|
|
20
|
+
gameId?: string;
|
|
21
|
+
gamePath: string | null;
|
|
22
|
+
logsPath: string | null;
|
|
23
|
+
modPath: string | null;
|
|
24
|
+
/** Parent/dependency mod roots (load order, base first) indexed as source "parent"
|
|
25
|
+
*, the submod / compatibility-patch workflow. */
|
|
26
|
+
parentPaths: string[];
|
|
27
|
+
/** Workspace mod roots (subset of parentPaths): mods the user is EDITING in
|
|
28
|
+
* this workspace, so they get the mod treatment, reference indexing and
|
|
29
|
+
* reference diagnostics, on top of the parent definition scan. */
|
|
30
|
+
workspaceMods?: string[];
|
|
31
|
+
locLanguage: string;
|
|
32
|
+
/** Show inferred scope after scope-changing block openers (off by default). */
|
|
33
|
+
scopeInlayHints: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* How much a hover shows. `standard` applies every cap in the design;
|
|
36
|
+
* `compact` drops prose and examples; `full` lifts the example cap and shows
|
|
37
|
+
* every distinct meaning.
|
|
38
|
+
*/
|
|
39
|
+
hoverDetail?: "compact" | "standard" | "full";
|
|
40
|
+
/** Custom era calendar (total-conversion mods): how script dates display in
|
|
41
|
+
* game. Absent = no calendar features. Shape: calendar.ts `CalendarSetting`;
|
|
42
|
+
* the server sanitizes it on intake, so clients may pass raw JSON. */
|
|
43
|
+
calendar?: import("./calendar").CalendarSetting;
|
|
44
|
+
/** Our diagnostic codes to suppress everywhere. */
|
|
45
|
+
diagnosticsIgnore: string[];
|
|
46
|
+
/** Glob patterns (workspace-relative paths) whose diagnostics are suppressed. */
|
|
47
|
+
diagnosticsIgnorePatterns: string[];
|
|
48
|
+
/** When false (default) mod-only: never diagnose files under the game path. */
|
|
49
|
+
diagnosticsVanilla: boolean;
|
|
50
|
+
/** `px.trace.perf`: wall clock for every request, rescan, index change and
|
|
51
|
+
* scan phase into the output channel. Off by default (perf campaign §A2). */
|
|
52
|
+
tracePerf?: boolean;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* What the connected client can do beyond plain LSP. Every capability is
|
|
57
|
+
* independent and off by default, so a bare client gets the degraded shape
|
|
58
|
+
* without declaring anything and a rich client opts in to exactly the parts
|
|
59
|
+
* it implements.
|
|
60
|
+
*/
|
|
61
|
+
export interface ParadoxClientCapabilities {
|
|
62
|
+
/**
|
|
63
|
+
* The client renders the sanitized `<span style="color:var(--vscode-*)">`
|
|
64
|
+
* markup in hover markdown (VSCode theme variables). Default false: hover
|
|
65
|
+
* cards are plain markdown, with the same content.
|
|
66
|
+
*/
|
|
67
|
+
hoverHtml?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* The command ids the client registers, from {@link clientCommands}. The
|
|
70
|
+
* server emits `command:` links and command-carrying code actions ONLY for
|
|
71
|
+
* ids listed here; for the rest it falls back to plain text or a real
|
|
72
|
+
* WorkspaceEdit. Default: none.
|
|
73
|
+
*/
|
|
74
|
+
commands?: string[];
|
|
75
|
+
/**
|
|
76
|
+
* The client watches the mod tree itself and pushes
|
|
77
|
+
* {@link modFileChangedNotification}. The server then does NOT register its
|
|
78
|
+
* own `workspace/didChangeWatchedFiles` watcher. Default false: the server
|
|
79
|
+
* registers one whenever the client supports dynamic registration.
|
|
80
|
+
*/
|
|
81
|
+
ownFileWatcher?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* The client's hover renderer navigates `file:` links, so provenance lines
|
|
84
|
+
* ("where is this defined") may be markdown links. Default false: the same
|
|
85
|
+
* `file.txt:12` label is rendered as plain text, which reads correctly in a
|
|
86
|
+
* client that would otherwise show a dead link.
|
|
87
|
+
*
|
|
88
|
+
* Note that `textDocument.completion.completionItem.snippetSupport` — the
|
|
89
|
+
* other axis an embedder should declare — is a STANDARD LSP capability, not
|
|
90
|
+
* one of these: send it in the initialize params, not here.
|
|
91
|
+
*/
|
|
92
|
+
fileLinks?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* The client renders `$(codicon)` theme icons in hover markdown, i.e. it sets
|
|
95
|
+
* `supportThemeIcons` on the MarkdownString. Default false, and the default
|
|
96
|
+
* matters: a client without it prints the literal text `$(symbol-method)`,
|
|
97
|
+
* which is worse than the plain `■` it would otherwise get. Implies
|
|
98
|
+
* {@link ParadoxClientCapabilities.hoverHtml} is respected for colour.
|
|
99
|
+
*/
|
|
100
|
+
hoverIcons?: boolean;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** initializationOptions passed at LanguageClient start. All fields optional:
|
|
104
|
+
* the server has fail-soft fallbacks for bare clients. */
|
|
105
|
+
export interface ParadoxInitOptions {
|
|
106
|
+
/** Server-side cache directory (the extension's global storage path). */
|
|
107
|
+
storageDir?: string;
|
|
108
|
+
/** What this client can do; see {@link ParadoxClientCapabilities}. Absent
|
|
109
|
+
* fields default to off (the plain-LSP-client shape). */
|
|
110
|
+
client?: ParadoxClientCapabilities;
|
|
111
|
+
/**
|
|
112
|
+
* @deprecated Send {@link ParadoxInitOptions.client} instead. `true` is an
|
|
113
|
+
* alias for `{ hoverHtml: true, commands: <every id in clientCommands>,
|
|
114
|
+
* ownFileWatcher: true, fileLinks: true }` plus snippet support (what the
|
|
115
|
+
* VSCode extension declared before the capabilities object existed);
|
|
116
|
+
* false/absent means all-off. Ignored when `client` is present.
|
|
117
|
+
*/
|
|
118
|
+
clientCommands?: boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Root holding the bundled per-game data directories: the server reads
|
|
121
|
+
* `<dataDir>/<gameId>/wikidocs/` and `<dataDir>/<gameId>/freqs.json`.
|
|
122
|
+
* Normally omitted: the server uses `data/` next to its own bundle. Set it
|
|
123
|
+
* when the data ships apart from the server bundle (an embedder unpacking
|
|
124
|
+
* both separately). Re-resolved against the new `gameId` whenever the game
|
|
125
|
+
* changes, so it stays profile-correct.
|
|
126
|
+
*/
|
|
127
|
+
dataDir?: string;
|
|
128
|
+
/**
|
|
129
|
+
* @deprecated Send {@link ParadoxInitOptions.dataDir} instead. Overrides the
|
|
130
|
+
* wikidocs/ folder ALONE, freqs.json still comes from `dataDir`/the bundle,
|
|
131
|
+
* and, being one fixed folder, it does NOT follow a `gameId` change.
|
|
132
|
+
*/
|
|
133
|
+
wikidocsDir?: string;
|
|
134
|
+
settings?: ParadoxSettings;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ---- client command ids ----------------------------------------------------
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Client commands the server references in code actions and hover links (part
|
|
141
|
+
* of the wire contract: a client that implements one must register exactly
|
|
142
|
+
* this id and list it in {@link ParadoxClientCapabilities.commands}). They
|
|
143
|
+
* carry the "px." prefix: these are public extension command ids with shipped
|
|
144
|
+
* default keybindings. The prefix was renamed in the Paradox Toolkit rebrand
|
|
145
|
+
* and no fallback to the old ids is registered.
|
|
146
|
+
*/
|
|
147
|
+
export const clientCommands = {
|
|
148
|
+
editLocalization: "px.editLocalization",
|
|
149
|
+
openLocalizationSideBySide: "px.openLocalizationSideBySide",
|
|
150
|
+
showReferences: "px.showReferences",
|
|
151
|
+
showExamplesWiki: "px.showExamplesWiki",
|
|
152
|
+
} as const;
|
|
153
|
+
|
|
154
|
+
/** Every id in {@link clientCommands}: what a fully capable client registers. */
|
|
155
|
+
export const allClientCommandIds: string[] = Object.values(clientCommands);
|
|
156
|
+
|
|
157
|
+
// ---- client -> server ------------------------------------------------------
|
|
158
|
+
|
|
159
|
+
/** Notification: settings changed; payload {@link ParadoxSettings}. */
|
|
160
|
+
export const configChangedNotification = "paradox/configChanged";
|
|
161
|
+
|
|
162
|
+
/** Notification: a mod file changed on disk; payload {@link ModFileChangeParams}. */
|
|
163
|
+
export const modFileChangedNotification = "paradox/modFileChanged";
|
|
164
|
+
export interface ModFileChangeParams {
|
|
165
|
+
/** Absolute filesystem path (not a URI). */
|
|
166
|
+
fsPath: string;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** Request: re-parse script_docs logs; payload {@link ReloadDocsParams} -> {@link ReloadDocsResult}. */
|
|
170
|
+
export const reloadDocsRequest = "paradox/reloadDocs";
|
|
171
|
+
export interface ReloadDocsParams {
|
|
172
|
+
force: boolean;
|
|
173
|
+
}
|
|
174
|
+
export interface ReloadDocsResult {
|
|
175
|
+
tokens: number;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** Request: index statistics; no payload -> {@link IndexStats}. */
|
|
179
|
+
export const indexStatsRequest = "paradox/indexStats";
|
|
180
|
+
|
|
181
|
+
/** Request: look up localization entries for a key; {@link LookupLocParams} -> {@link LocEntryInfo}[].
|
|
182
|
+
* Mod entries shadow vanilla ones (the full list is returned, mod first). */
|
|
183
|
+
export const lookupLocRequest = "paradox/lookupLoc";
|
|
184
|
+
export interface LookupLocParams {
|
|
185
|
+
key: string;
|
|
186
|
+
}
|
|
187
|
+
export interface LocEntryInfo {
|
|
188
|
+
file: string;
|
|
189
|
+
/** 0-based. */
|
|
190
|
+
line: number;
|
|
191
|
+
source: "vanilla" | "parent" | "mod";
|
|
192
|
+
value?: string;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Request: a localization value as the PLAYER reads it;
|
|
197
|
+
* {@link LocTextParams} -> {@link LocTextResult}.
|
|
198
|
+
*
|
|
199
|
+
* {@link lookupLocRequest} answers the value verbatim, which is what an editor
|
|
200
|
+
* needs. A panel that SHOWS the value needs the sentence: the games write a
|
|
201
|
+
* culture parameter as `"The [GetTrait('rough_terrain_expert').GetName(
|
|
202
|
+
* GetNullCharacter )] Commander Trait is more common"` (145 of the 280
|
|
203
|
+
* parameter values with a real call take that one shape), and a modder reading
|
|
204
|
+
* a form must not be shown the brackets.
|
|
205
|
+
*
|
|
206
|
+
* Everything the renderer knows is DERIVED: the words come from the loc index
|
|
207
|
+
* (mod entries shadow the game's), the kind a `Get<Something>('name')` chain
|
|
208
|
+
* names comes from the definition index, and the loc key that kind's names take
|
|
209
|
+
* comes from the active profile's schema. No table of function names, so a
|
|
210
|
+
* workspace of any of the games gets the same behavior from its own schema.
|
|
211
|
+
*/
|
|
212
|
+
export const locTextRequest = "paradox/locText";
|
|
213
|
+
export interface LocTextParams extends ModScopedParams {
|
|
214
|
+
keys: string[];
|
|
215
|
+
}
|
|
216
|
+
export interface LocTextValue {
|
|
217
|
+
/** The value verbatim, exactly as {@link lookupLocRequest} answers it. */
|
|
218
|
+
raw: string;
|
|
219
|
+
/** The same value as plain text: markup stripped, datafunctions resolved. */
|
|
220
|
+
text: string;
|
|
221
|
+
/** False when any part of the value stayed a word for something unresolved. */
|
|
222
|
+
resolved: boolean;
|
|
223
|
+
}
|
|
224
|
+
export interface LocTextResult {
|
|
225
|
+
/** Loc key -> its rendering. A key the loc index cannot find is ABSENT. */
|
|
226
|
+
values: Record<string, LocTextValue>;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// ---- server -> client ------------------------------------------------------
|
|
230
|
+
|
|
231
|
+
/** Notification: data health for the status bar; payload {@link StatusPayload}. */
|
|
232
|
+
export const statusNotification = "paradox/status";
|
|
233
|
+
export interface StatusPayload {
|
|
234
|
+
tokens: number;
|
|
235
|
+
tokensFromScriptDocs: boolean;
|
|
236
|
+
/** True when the script_docs tokens came from the BUNDLED dump snapshot
|
|
237
|
+
* (data/<gameId>/script_docs) rather than the user's own dump. */
|
|
238
|
+
tokensFromBundledDumps?: boolean;
|
|
239
|
+
definitions: number;
|
|
240
|
+
/** Tokens the bundled wiki added that script_docs did not have. The wiki is
|
|
241
|
+
* merged even when the user has their own dump, but its real contribution is
|
|
242
|
+
* usage examples; the extra NAMES are mostly deprecated API. */
|
|
243
|
+
tokensWikiOnly?: number;
|
|
244
|
+
/** True while a (re)scan is running. */
|
|
245
|
+
indexing: boolean;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/** Notification: the definition index changed (debounced server-side); no payload.
|
|
249
|
+
* Overview views re-query on this signal. */
|
|
250
|
+
export const indexChangedNotification = "paradox/indexChanged";
|
|
251
|
+
|
|
252
|
+
/** Notification: a long-running server phase started or finished; payload
|
|
253
|
+
* {@link ProgressPayload}. The status bar lists what is still loading, so a
|
|
254
|
+
* cold workspace says which step it is on instead of looking idle. No
|
|
255
|
+
* percentages: the phases are coarse and the client only shows their state. */
|
|
256
|
+
export const progressNotification = "paradox/progress";
|
|
257
|
+
export interface ProgressPayload {
|
|
258
|
+
/** Stable phase id, so a "done" can find the "start" it belongs to. */
|
|
259
|
+
phase: string;
|
|
260
|
+
state: "start" | "done";
|
|
261
|
+
/** Human-readable label for the phase, sent with "start". */
|
|
262
|
+
detail?: string;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// ---- overview suite (Phase 4) ------------------------------------------------
|
|
266
|
+
|
|
267
|
+
/** Shared param for the mod-scoped overview requests: restrict the result to
|
|
268
|
+
* one workspace mod (absolute root path). Absent/null = all workspace mods. */
|
|
269
|
+
export interface ModScopedParams {
|
|
270
|
+
modRoot?: string | null;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/** Request: mod content inventory; {@link ModScopedParams} -> {@link ModOverview}. */
|
|
274
|
+
export const modOverviewRequest = "paradox/modOverview";
|
|
275
|
+
export interface OverviewDef {
|
|
276
|
+
name: string;
|
|
277
|
+
file: string;
|
|
278
|
+
line: number;
|
|
279
|
+
/**
|
|
280
|
+
* The loc-resolved display name, when the kind's loc pattern resolves to one
|
|
281
|
+
* ({@link EventVocabularyItem.label}). Set by {@link definitionFormRequest}
|
|
282
|
+
* only, so a creator listing what the mod already has can show the player's
|
|
283
|
+
* word for it; absent everywhere else.
|
|
284
|
+
*/
|
|
285
|
+
label?: string;
|
|
286
|
+
/**
|
|
287
|
+
* Where the definition comes from. Set by {@link definitionFormRequest} only,
|
|
288
|
+
* whose list includes the game's and a dependency's definitions (a creator
|
|
289
|
+
* opens one to duplicate or override it) and must say which is which; absent
|
|
290
|
+
* everywhere else, where every definition listed is the mod's own.
|
|
291
|
+
*/
|
|
292
|
+
source?: "vanilla" | "parent" | "mod";
|
|
293
|
+
}
|
|
294
|
+
export interface OverviewKind {
|
|
295
|
+
kind: string;
|
|
296
|
+
count: number;
|
|
297
|
+
/** Capped list (first N alphabetically); `count` is the real total. */
|
|
298
|
+
defs: OverviewDef[];
|
|
299
|
+
}
|
|
300
|
+
export interface ModOverview {
|
|
301
|
+
kinds: OverviewKind[];
|
|
302
|
+
totalDefs: number;
|
|
303
|
+
totalRefs: number;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/** Request: localization coverage; {@link ModScopedParams} -> {@link LocCoverage}[]. */
|
|
307
|
+
export const locCoverageRequest = "paradox/locCoverage";
|
|
308
|
+
export interface LocIssue {
|
|
309
|
+
key: string;
|
|
310
|
+
file?: string;
|
|
311
|
+
/** 0-based. */
|
|
312
|
+
line?: number;
|
|
313
|
+
/** For untranslated: the source-language text. */
|
|
314
|
+
value?: string;
|
|
315
|
+
}
|
|
316
|
+
export interface LocCoverage {
|
|
317
|
+
language: string;
|
|
318
|
+
defined: number;
|
|
319
|
+
/** Referenced by mod script / required by schema but not defined anywhere. */
|
|
320
|
+
missing: LocIssue[];
|
|
321
|
+
/** Defined in the mod but never referenced and not overriding vanilla. */
|
|
322
|
+
orphaned: LocIssue[];
|
|
323
|
+
/** Value identical to the source language (only for non-source languages). */
|
|
324
|
+
untranslated: LocIssue[];
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/** Request: override/conflict map; {@link ModScopedParams} -> {@link OverrideInfo}[]. */
|
|
328
|
+
export const overridesRequest = "paradox/overrides";
|
|
329
|
+
export interface OverrideSite {
|
|
330
|
+
source: "vanilla" | "parent" | "mod";
|
|
331
|
+
/** Display label: the owning mod's descriptor name when known, else `source`. */
|
|
332
|
+
label?: string;
|
|
333
|
+
file: string;
|
|
334
|
+
line: number;
|
|
335
|
+
}
|
|
336
|
+
export interface OverrideInfo {
|
|
337
|
+
name: string;
|
|
338
|
+
kind: string;
|
|
339
|
+
mod: OverrideSite;
|
|
340
|
+
shadowed: OverrideSite[];
|
|
341
|
+
/** Folder rule: script is last-in-wins, GUI is first-in-wins. */
|
|
342
|
+
rule: "LIOS" | "FIOS";
|
|
343
|
+
winner: "mod" | "other";
|
|
344
|
+
note?: string;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/** Request: full event detail for the graph inspector; {@link EventDetailParams} -> {@link EventDetail} | null. */
|
|
348
|
+
export const eventDetailRequest = "paradox/eventDetail";
|
|
349
|
+
export interface EventDetailParams {
|
|
350
|
+
id: string;
|
|
351
|
+
}
|
|
352
|
+
/** A localizable field: key, resolved text, and (for mod entries) the editable site. */
|
|
353
|
+
export interface EventLocField {
|
|
354
|
+
key: string;
|
|
355
|
+
text?: string;
|
|
356
|
+
/** Present only when the entry lives in the mod (in-place editable). */
|
|
357
|
+
file?: string;
|
|
358
|
+
line?: number;
|
|
359
|
+
/** The value comes from a dynamic block (first_valid / triggered_desc), not a plain key. */
|
|
360
|
+
dynamic?: boolean;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* One flattened line of a rendered block: enough to print an event's logic
|
|
364
|
+
* back as readable pseudo-script without the client re-parsing anything.
|
|
365
|
+
*/
|
|
366
|
+
export interface EventScriptLine {
|
|
367
|
+
/** Nesting depth inside the rendered block (0 = a direct child). */
|
|
368
|
+
depth: number;
|
|
369
|
+
/** The statement without indentation: `key = value`, `key = {`, `}`, or a bare scalar. */
|
|
370
|
+
text: string;
|
|
371
|
+
/** 0-based source line. */
|
|
372
|
+
line: number;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* A reference inside a block that hands control to another event or on_action:
|
|
377
|
+
* the step-into edge of an event walkthrough. Collected from the schema's
|
|
378
|
+
* event/on_action reference fields (`trigger_event`, `on_action`, `events`,
|
|
379
|
+
* `random_events`, …), so a game profile that names them differently is
|
|
380
|
+
* covered without a hard-coded key list.
|
|
381
|
+
*/
|
|
382
|
+
export interface EventStepTarget {
|
|
383
|
+
/** The key that produced the reference (`trigger_event`, `on_action`, …). */
|
|
384
|
+
via: string;
|
|
385
|
+
/** Referenced event id / on_action name, exactly as written. */
|
|
386
|
+
name: string;
|
|
387
|
+
/** What the index says `name` is. "unknown" = not indexed; say so, do not guess. */
|
|
388
|
+
kind: "event" | "on_action" | "unknown";
|
|
389
|
+
/** 0-based line of the reference, in the file that contains it (for a
|
|
390
|
+
* {@link EventStepTarget.fires} entry that is the on_action's own file). */
|
|
391
|
+
line: number;
|
|
392
|
+
/** Definition site, when the name is indexed. */
|
|
393
|
+
file?: string;
|
|
394
|
+
defLine?: number;
|
|
395
|
+
/** Definition sites of that kind, when more than one. on_actions merge
|
|
396
|
+
* across files (a mod extending a vanilla on_action), so `fires` reflects
|
|
397
|
+
* only the site at {@link EventStepTarget.file}. */
|
|
398
|
+
defCount?: number;
|
|
399
|
+
/**
|
|
400
|
+
* on_action targets only: what that on_action itself fires, read from its own
|
|
401
|
+
* definition. Empty when the definition names nothing. Absent when there was
|
|
402
|
+
* nothing to read: the name is not an indexed on_action, its file could not
|
|
403
|
+
* be parsed, or this target already IS one level deep (resolution stops
|
|
404
|
+
* there, so a self-chaining pair cannot recurse).
|
|
405
|
+
*/
|
|
406
|
+
fires?: EventStepTarget[];
|
|
407
|
+
/** Real target count before `fires` was capped. */
|
|
408
|
+
firesTotal?: number;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* A scalar `key = value` written directly in an event body or an option body,
|
|
413
|
+
* with the line it sits on, so an editor can rewrite it in place instead of
|
|
414
|
+
* re-parsing the file. Blocks are not fields: they are `sections` / `options`.
|
|
415
|
+
*/
|
|
416
|
+
export interface EventFieldInfo {
|
|
417
|
+
key: string;
|
|
418
|
+
value: string;
|
|
419
|
+
/** 0-based source line. */
|
|
420
|
+
line: number;
|
|
421
|
+
/** The value was written in quotes and must be rewritten that way. */
|
|
422
|
+
quoted?: boolean;
|
|
423
|
+
}
|
|
424
|
+
export interface EventSectionInfo {
|
|
425
|
+
name: string;
|
|
426
|
+
/** 0-based line of the section key. */
|
|
427
|
+
line: number;
|
|
428
|
+
/** Top-level keys inside the section (capped). */
|
|
429
|
+
keys: string[];
|
|
430
|
+
/** The section rendered as pseudo-script, capped (`totalLines` is the truth). */
|
|
431
|
+
lines: EventScriptLine[];
|
|
432
|
+
totalLines: number;
|
|
433
|
+
/** Events / on_actions this section hands control to, capped. */
|
|
434
|
+
targets: EventStepTarget[];
|
|
435
|
+
/** Real target count before `targets` was capped. */
|
|
436
|
+
targetsTotal: number;
|
|
437
|
+
}
|
|
438
|
+
/** A gate block (trigger / ai_chance) rendered for in-place editing. */
|
|
439
|
+
export interface EventGateInfo {
|
|
440
|
+
/** 0-based line of the block's key. */
|
|
441
|
+
line: number;
|
|
442
|
+
lines: EventScriptLine[];
|
|
443
|
+
totalLines: number;
|
|
444
|
+
}
|
|
445
|
+
export interface EventOptionInfo {
|
|
446
|
+
line: number;
|
|
447
|
+
/** Line the option's first statement may be inserted before (0-based). */
|
|
448
|
+
bodyLine: number;
|
|
449
|
+
/** Scalar keys written in the option body, editable in place. */
|
|
450
|
+
fields: EventFieldInfo[];
|
|
451
|
+
name?: EventLocField;
|
|
452
|
+
effectKeys: string[];
|
|
453
|
+
hasTrigger: boolean;
|
|
454
|
+
hasAiChance: boolean;
|
|
455
|
+
/** The option's own trigger block, rendered, when it has one. */
|
|
456
|
+
trigger?: EventGateInfo;
|
|
457
|
+
/** The option's ai_chance block, rendered, when it has one. */
|
|
458
|
+
aiChance?: EventGateInfo;
|
|
459
|
+
/** The option's effects rendered as pseudo-script (name/trigger/ai_chance/
|
|
460
|
+
* ai_value dropped: they gate the option, they are not its effect), capped. */
|
|
461
|
+
lines: EventScriptLine[];
|
|
462
|
+
totalLines: number;
|
|
463
|
+
/** Events / on_actions this option hands control to, capped. */
|
|
464
|
+
targets: EventStepTarget[];
|
|
465
|
+
/** Real target count before `targets` was capped. */
|
|
466
|
+
targetsTotal: number;
|
|
467
|
+
}
|
|
468
|
+
export interface EventRefInfo {
|
|
469
|
+
name: string;
|
|
470
|
+
kind: "saved_scope" | "variable" | "scripted_effect" | "scripted_trigger" | "script_value" | "event";
|
|
471
|
+
/** First use inside the event, 0-based. */
|
|
472
|
+
line: number;
|
|
473
|
+
defFile?: string;
|
|
474
|
+
defLine?: number;
|
|
475
|
+
/** Number of definition/save sites. */
|
|
476
|
+
defCount?: number;
|
|
477
|
+
}
|
|
478
|
+
export interface EventDetail {
|
|
479
|
+
id: string;
|
|
480
|
+
file: string;
|
|
481
|
+
line: number;
|
|
482
|
+
/** Line of the event's closing brace (option-scaffold insertion point). */
|
|
483
|
+
endLine: number;
|
|
484
|
+
/** Line a new top-level statement may be inserted before (0-based). */
|
|
485
|
+
bodyLine: number;
|
|
486
|
+
/** Scalar keys written at the event's top level, editable in place. */
|
|
487
|
+
fields: EventFieldInfo[];
|
|
488
|
+
type?: string;
|
|
489
|
+
hidden?: boolean;
|
|
490
|
+
theme?: string;
|
|
491
|
+
title?: EventLocField;
|
|
492
|
+
desc?: EventLocField;
|
|
493
|
+
/** The event's third displayed string in the games whose events have one
|
|
494
|
+
* (top-level `flavor`); absent everywhere else. */
|
|
495
|
+
flavor?: EventLocField;
|
|
496
|
+
sections: EventSectionInfo[];
|
|
497
|
+
options: EventOptionInfo[];
|
|
498
|
+
refs: EventRefInfo[];
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Request: the searchable catalog behind the Examples Wiki;
|
|
503
|
+
* `null` -> {@link ExampleWikiIndex}.
|
|
504
|
+
*
|
|
505
|
+
* One compact row per name the server knows about, so a client can filter and
|
|
506
|
+
* rank the whole vocabulary without asking again. Everything expensive (the
|
|
507
|
+
* full documentation, the usage block, the vanilla sites) is left to
|
|
508
|
+
* {@link exampleWikiEntryRequest}.
|
|
509
|
+
*/
|
|
510
|
+
export const exampleWikiRequest = "paradox/exampleWiki";
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* What an Examples Wiki row is. The first four are engine tokens from
|
|
514
|
+
* script_docs or the wiki tables; the next three are `[ ... ]` datafunctions:
|
|
515
|
+
* a global (`GetPlayer`), a member of a data type (`Character.GetName`), and
|
|
516
|
+
* a data type itself (`Character`). The next seven are the variable and list
|
|
517
|
+
* names the definition index found in the indexed script itself, one kind per
|
|
518
|
+
* storage class ({@link exampleWikiVariableKinds}). The last two are the script
|
|
519
|
+
* grammar the game documents nowhere ({@link exampleWikiVocabularyKinds}): the
|
|
520
|
+
* glue keywords (`limit`, `NOT`, `base`) and the scope words (`root`, `prev`).
|
|
521
|
+
*/
|
|
522
|
+
export type ExampleWikiKind =
|
|
523
|
+
| "trigger"
|
|
524
|
+
| "effect"
|
|
525
|
+
| "event_target"
|
|
526
|
+
| "modifier"
|
|
527
|
+
| "datafn_global"
|
|
528
|
+
| "datafn_member"
|
|
529
|
+
| "data_type"
|
|
530
|
+
| "keyword"
|
|
531
|
+
| "scope_word"
|
|
532
|
+
| "variable"
|
|
533
|
+
| "local_variable"
|
|
534
|
+
| "global_variable"
|
|
535
|
+
| "variable_list"
|
|
536
|
+
| "local_variable_list"
|
|
537
|
+
| "global_variable_list"
|
|
538
|
+
| "list";
|
|
539
|
+
|
|
540
|
+
/** The {@link ExampleWikiKind}s whose rows come from the definition index. */
|
|
541
|
+
export const exampleWikiVariableKinds: ExampleWikiKind[] = [
|
|
542
|
+
"variable",
|
|
543
|
+
"local_variable",
|
|
544
|
+
"global_variable",
|
|
545
|
+
"variable_list",
|
|
546
|
+
"local_variable_list",
|
|
547
|
+
"global_variable_list",
|
|
548
|
+
"list",
|
|
549
|
+
];
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* The {@link ExampleWikiKind}s whose rows are script grammar rather than a
|
|
553
|
+
* name from a dump or an index. One filter chip covers both.
|
|
554
|
+
*/
|
|
555
|
+
export const exampleWikiVocabularyKinds: ExampleWikiKind[] = ["keyword", "scope_word"];
|
|
556
|
+
|
|
557
|
+
export interface ExampleWikiEntry {
|
|
558
|
+
/** Display and lookup name; a member carries its owner (`Character.GetName`). */
|
|
559
|
+
name: string;
|
|
560
|
+
kind: ExampleWikiKind;
|
|
561
|
+
/** Owning data type of a member row; absent on every other kind. */
|
|
562
|
+
owner?: string;
|
|
563
|
+
/** First sentence of the documentation, capped; empty when undocumented. */
|
|
564
|
+
shortDoc: string;
|
|
565
|
+
/** Times vanilla uses the name. 0 means "not counted", not "never used". */
|
|
566
|
+
count: number;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
export interface ExampleWikiIndex {
|
|
570
|
+
/** Every row, most-used first. */
|
|
571
|
+
entries: ExampleWikiEntry[];
|
|
572
|
+
/** Plain sentences naming where the rows came from, for an About line. */
|
|
573
|
+
sources: string[];
|
|
574
|
+
/** True when the rows do NOT come from the user's own script_docs dump, so
|
|
575
|
+
* a client can suggest running `script_docs` in the game console. */
|
|
576
|
+
needsScriptDocs: boolean;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* Request: everything the toolkit knows about ONE Examples Wiki row;
|
|
581
|
+
* {@link ExampleWikiEntryParams} -> {@link ExampleWikiDetail} | null.
|
|
582
|
+
*
|
|
583
|
+
* `null` means the name is not in the catalog. Vanilla example sites are
|
|
584
|
+
* searched on demand and come back as absolute paths, so a client can open
|
|
585
|
+
* the file at the line without resolving anything itself.
|
|
586
|
+
*/
|
|
587
|
+
export const exampleWikiEntryRequest = "paradox/exampleWikiEntry";
|
|
588
|
+
export interface ExampleWikiEntryParams {
|
|
589
|
+
name: string;
|
|
590
|
+
kind: ExampleWikiKind;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/** One place in the game or mod files that uses the name. */
|
|
594
|
+
export interface ExampleWikiSite {
|
|
595
|
+
/** The line as written, trimmed and capped. */
|
|
596
|
+
text: string;
|
|
597
|
+
/** Absolute path. */
|
|
598
|
+
file: string;
|
|
599
|
+
/** 1-based line number. */
|
|
600
|
+
line: number;
|
|
601
|
+
/**
|
|
602
|
+
* The lines around the site as written, dedented and capped, with the `line`
|
|
603
|
+
* line among them. Absent when the file could not be read.
|
|
604
|
+
*/
|
|
605
|
+
context?: string[];
|
|
606
|
+
/** 1-based line number of `context[0]`; absent with `context`. */
|
|
607
|
+
contextStart?: number;
|
|
608
|
+
/** What the site does with the name ("set", "read"); absent when it only uses it. */
|
|
609
|
+
label?: string;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
export interface ExampleWikiDetail {
|
|
613
|
+
name: string;
|
|
614
|
+
kind: ExampleWikiKind;
|
|
615
|
+
owner?: string;
|
|
616
|
+
count: number;
|
|
617
|
+
/** Full documentation prose; empty when nothing documents the name. */
|
|
618
|
+
doc: string;
|
|
619
|
+
/** Scopes an engine token works in; empty when unknown. */
|
|
620
|
+
scopes: string[];
|
|
621
|
+
/** The token's remaining script_docs metadata lines, verbatim. */
|
|
622
|
+
traits?: string;
|
|
623
|
+
/** The `usage:` example block from script_docs or the wiki, verbatim. */
|
|
624
|
+
usage?: string;
|
|
625
|
+
/** Datafunction return type; absent when unknown. */
|
|
626
|
+
ret?: string;
|
|
627
|
+
/** Datafunction argument types, when the dump recorded them. */
|
|
628
|
+
args?: string[];
|
|
629
|
+
/** A datafunction is either read like a field or called with parentheses. */
|
|
630
|
+
callKind?: "promote" | "function";
|
|
631
|
+
/** Literal arguments vanilla passes, most used first. */
|
|
632
|
+
literals: string[];
|
|
633
|
+
/** Literals found before the list was capped. */
|
|
634
|
+
literalsTotal: number;
|
|
635
|
+
/** Members of a data type, or nothing on other kinds. */
|
|
636
|
+
members: string[];
|
|
637
|
+
membersTotal: number;
|
|
638
|
+
/** Datafunctions that return this data type. */
|
|
639
|
+
producers: string[];
|
|
640
|
+
producersTotal: number;
|
|
641
|
+
/** What a variable holds, in words ("character", "list of title", "unknown"). */
|
|
642
|
+
valueType?: string;
|
|
643
|
+
/** Top-level definitions a variable is set inside, most sites first. */
|
|
644
|
+
containers?: string[];
|
|
645
|
+
/** Containers found before the list was capped. */
|
|
646
|
+
containersTotal?: number;
|
|
647
|
+
/** Vanilla uses, capped; empty when the search found none. */
|
|
648
|
+
examples: ExampleWikiSite[];
|
|
649
|
+
/** Why the example list looks the way it does, in one sentence. */
|
|
650
|
+
examplesNote?: string;
|
|
651
|
+
/**
|
|
652
|
+
* What can be written FROM each scope this token produces, one entry per
|
|
653
|
+
* `output: S` scope. Present only on a token that declares one; every list
|
|
654
|
+
* is derived from the declared scopes of the other catalog rows.
|
|
655
|
+
*/
|
|
656
|
+
fromScope?: ExampleWikiFromScope[];
|
|
657
|
+
/** Where the facts above come from, in one sentence. */
|
|
658
|
+
provenance: string;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
/** Names usable once a token has moved the scope to {@link scope}, most used
|
|
662
|
+
* first. Each list is capped; the `*Total` is what was found before the cap. */
|
|
663
|
+
export interface ExampleWikiFromScope {
|
|
664
|
+
/** The produced scope word, as the game's own docs write it ("faith"). */
|
|
665
|
+
scope: string;
|
|
666
|
+
/** Triggers whose declared scopes include this one. */
|
|
667
|
+
triggers: string[];
|
|
668
|
+
triggersTotal: number;
|
|
669
|
+
/** Effects whose declared scopes include this one. */
|
|
670
|
+
effects: string[];
|
|
671
|
+
effectsTotal: number;
|
|
672
|
+
/** Event targets that take this scope as input. */
|
|
673
|
+
targets: string[];
|
|
674
|
+
targetsTotal: number;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/** Request: GUI widget tree for a .gui document; {@link GuiTreeParams} -> {@link GuiTree}. */
|
|
678
|
+
export const guiTreeRequest = "paradox/guiTree";
|
|
679
|
+
export interface GuiTreeParams {
|
|
680
|
+
/** For display only; the text is authoritative. */
|
|
681
|
+
uri: string;
|
|
682
|
+
text: string;
|
|
683
|
+
}
|
|
684
|
+
export interface GuiTreeNode {
|
|
685
|
+
/** Widget type or declaration header (window, flowcontainer, "template NAME"…). */
|
|
686
|
+
key: string;
|
|
687
|
+
/** name = "..." when present. */
|
|
688
|
+
name?: string;
|
|
689
|
+
/** For `type x = base { }` / tagged blocks: the base widget type. */
|
|
690
|
+
base?: string;
|
|
691
|
+
/** using = template references. */
|
|
692
|
+
using?: string[];
|
|
693
|
+
/** decl = template/types/type/blockoverride/block headers; state = animation states. */
|
|
694
|
+
kind: "widget" | "state" | "decl";
|
|
695
|
+
/** 0-based line of the key. */
|
|
696
|
+
line: number;
|
|
697
|
+
children: GuiTreeNode[];
|
|
698
|
+
}
|
|
699
|
+
export interface GuiTree {
|
|
700
|
+
nodes: GuiTreeNode[];
|
|
701
|
+
/** Total node count across all depths. */
|
|
702
|
+
count: number;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/**
|
|
706
|
+
* Request: rendered GUI layout for a .gui document;
|
|
707
|
+
* {@link GuiLayoutParams} -> {@link GuiLayoutResult}. Rectangles come from
|
|
708
|
+
* the measured layout engine (docs/gui-designer/spec.md), with
|
|
709
|
+
* templates/types resolved against the vanilla + mod gui tree.
|
|
710
|
+
*/
|
|
711
|
+
export const guiLayoutRequest = "paradox/guiLayout";
|
|
712
|
+
export interface GuiLayoutParams {
|
|
713
|
+
/** For display only; the text is authoritative. */
|
|
714
|
+
uri: string;
|
|
715
|
+
text: string;
|
|
716
|
+
/** Conditional-visibility preview mode; absent = `showAll`. */
|
|
717
|
+
visibility?: GuiVisibilityOptions;
|
|
718
|
+
/**
|
|
719
|
+
* `resolve` (default): textbox keys show their localized value and
|
|
720
|
+
* `[datafunctions]` their knowable text, and sizes follow. `raw`: the
|
|
721
|
+
* `text =` value verbatim, as the file has it.
|
|
722
|
+
*/
|
|
723
|
+
loc?: "resolve" | "raw";
|
|
724
|
+
/** Modder-supplied preview text per `[...]` expression (the `.<game>modding/gui-preview-values.json` table). */
|
|
725
|
+
previewValues?: Record<string, string>;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/**
|
|
729
|
+
* How the layout treats a CONDITIONALLY visible widget, one whose `visible`
|
|
730
|
+
* holds an expression a static preview cannot evaluate (`visible =
|
|
731
|
+
* "[GetPlayer.IsAI]"`). A literal `visible = no` is deterministic and always
|
|
732
|
+
* collapses; `visible = yes` always shows. Neither is a check.
|
|
733
|
+
*/
|
|
734
|
+
export type GuiVisibilityMode = "showAll" | "hideAll" | "evaluate";
|
|
735
|
+
export interface GuiVisibilityOptions {
|
|
736
|
+
mode: GuiVisibilityMode;
|
|
737
|
+
/**
|
|
738
|
+
* `evaluate` only: per-check assignments. The KEY is the `visible` value
|
|
739
|
+
* exactly as authored, minus its quotes (`[GetPlayer.IsAI]`). The source
|
|
740
|
+
* string is the only identity a static preview has, so two widgets written
|
|
741
|
+
* with the same condition share one toggle, and a key stays stable across
|
|
742
|
+
* edits that do not touch the condition. A check with no assignment behaves
|
|
743
|
+
* as `showAll` (shown).
|
|
744
|
+
*/
|
|
745
|
+
checks?: Record<string, boolean>;
|
|
746
|
+
}
|
|
747
|
+
/** A conditional `visible` the layout met, for building a toggle UI. */
|
|
748
|
+
export interface GuiVisibilityCheck {
|
|
749
|
+
/** The condition source string, the key {@link GuiVisibilityOptions.checks} takes. */
|
|
750
|
+
key: string;
|
|
751
|
+
/** Widgets carrying this condition in this document. */
|
|
752
|
+
count: number;
|
|
753
|
+
/** True when THIS run resolved the check to hidden. */
|
|
754
|
+
hidden: boolean;
|
|
755
|
+
}
|
|
756
|
+
/** Server-side wall clock of one `paradox/guiLayout`, for a stats line. */
|
|
757
|
+
export interface GuiLayoutTimings {
|
|
758
|
+
/** Parsing the document and collecting its own template/type declarations. */
|
|
759
|
+
parseMs: number;
|
|
760
|
+
/** Building the cross-file template/type store; 0 on a cache hit. */
|
|
761
|
+
defsMs: number;
|
|
762
|
+
/** Building the widget tree and arranging every rect. */
|
|
763
|
+
layoutMs: number;
|
|
764
|
+
/** The whole request, server side. */
|
|
765
|
+
totalMs: number;
|
|
766
|
+
}
|
|
767
|
+
export interface GuiLayoutFill {
|
|
768
|
+
texture?: string;
|
|
769
|
+
/** rgba 0..1, straight sRGB multiply (rendered = round(v*255)). */
|
|
770
|
+
color?: [number, number, number, number];
|
|
771
|
+
/**
|
|
772
|
+
* Nine-slice border widths [left, top, right, bottom] in texture pixels
|
|
773
|
+
* (from `spriteborder`/`spriteborder_<side>`). The values as authored;
|
|
774
|
+
* `mode` says whether they apply.
|
|
775
|
+
*/
|
|
776
|
+
border?: [number, number, number, number];
|
|
777
|
+
/**
|
|
778
|
+
* How to draw the texture. Nine-slicing needs BOTH a `Cornered*` spriteType
|
|
779
|
+
* AND a non-zero border; a border alone is ignored and the whole texture
|
|
780
|
+
* stretches. `nineslice-*` = corners unscaled, edges and centre tiled or
|
|
781
|
+
* stretched per the suffix; `tile` = repeat the whole texture.
|
|
782
|
+
*/
|
|
783
|
+
mode?: "stretch" | "tile" | "nineslice-stretch" | "nineslice-tile";
|
|
784
|
+
/** `framesize = { w h }` cell size when the texture is a frame sheet. */
|
|
785
|
+
framesize?: [number, number];
|
|
786
|
+
/** `alpha = x`: the fill's opacity, 0..1 (absent = 1). */
|
|
787
|
+
alpha?: number;
|
|
788
|
+
/**
|
|
789
|
+
* `modify_texture` with `blend_mode = alphamultiply`: a texture whose alpha
|
|
790
|
+
* multiplies the fill's, stretched over the rect. Listed in `textures` like
|
|
791
|
+
* any other path. Other blend modes are not carried.
|
|
792
|
+
*/
|
|
793
|
+
mask?: string;
|
|
794
|
+
/** `fittype = centercrop`: cover the rect and crop to the centre instead of stretching. */
|
|
795
|
+
fit?: "centercrop";
|
|
796
|
+
/**
|
|
797
|
+
* 1-based frame index into that sheet, row-major over the cols x rows grid
|
|
798
|
+
* (cols = texW/w). Out-of-range values clamp to the first or last cell.
|
|
799
|
+
*/
|
|
800
|
+
frame?: number;
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* One piece of what a textbox shows. `loc`: a localization key the index
|
|
804
|
+
* resolved (or not: `resolved` false shows the key itself). `datafn`: a
|
|
805
|
+
* `[...]` expression; resolved through `Localize`/`Concept` or the modder's
|
|
806
|
+
* preview values, else shown as its last chain segment with `resolved` false.
|
|
807
|
+
* `source` is the key or the expression without brackets.
|
|
808
|
+
*/
|
|
809
|
+
export interface GuiTextSegment {
|
|
810
|
+
text: string;
|
|
811
|
+
kind: "literal" | "loc" | "datafn";
|
|
812
|
+
source: string;
|
|
813
|
+
resolved: boolean;
|
|
814
|
+
}
|
|
815
|
+
export interface GuiLayoutText {
|
|
816
|
+
/** What is measured and drawn (resolved when the request asked for it). */
|
|
817
|
+
text: string;
|
|
818
|
+
/** The raw `text =` value; differs from `text` when something resolved. */
|
|
819
|
+
raw?: string;
|
|
820
|
+
segments?: GuiTextSegment[];
|
|
821
|
+
fontsize: number;
|
|
822
|
+
offsetX: number;
|
|
823
|
+
offsetY: number;
|
|
824
|
+
lines: string[];
|
|
825
|
+
color?: [number, number, number, number];
|
|
826
|
+
}
|
|
827
|
+
export interface GuiLayoutNode {
|
|
828
|
+
key: string;
|
|
829
|
+
name?: string;
|
|
830
|
+
rect: { x: number; y: number; w: number; h: number };
|
|
831
|
+
/** Scrollarea viewport: children are clipped to the rect. */
|
|
832
|
+
clip: boolean;
|
|
833
|
+
bg?: GuiLayoutFill;
|
|
834
|
+
fill?: GuiLayoutFill;
|
|
835
|
+
text?: GuiLayoutText;
|
|
836
|
+
/** 0-based line of the instance statement in the requested document. */
|
|
837
|
+
line?: number;
|
|
838
|
+
/** Placed via anchor+position rules (position honored -> draggable). */
|
|
839
|
+
positioned: boolean;
|
|
840
|
+
/**
|
|
841
|
+
* `line` is the widget's own statement in this document (safe to edit);
|
|
842
|
+
* false for children spliced from type definitions.
|
|
843
|
+
*/
|
|
844
|
+
editable: boolean;
|
|
845
|
+
/** Raw `position = { x y }` source values, when present. */
|
|
846
|
+
srcPosition?: [number, number];
|
|
847
|
+
/** Raw `size = { w h }` source values, when present. */
|
|
848
|
+
srcSize?: [number, number];
|
|
849
|
+
/**
|
|
850
|
+
* The widget's index among its parent body's REORDER SIBLINGS: exactly the
|
|
851
|
+
* index a `reorder`, `insert` or `delete` op counts (see {@link GuiSourceOp}).
|
|
852
|
+
* Those are the body's DECLARATIONS, which include the `blockoverride` /
|
|
853
|
+
* `block` / `template` entries a preview never shows, so a client that ranks
|
|
854
|
+
* the widgets it can see is off by one per intervening declaration.
|
|
855
|
+
*
|
|
856
|
+
* Absent whenever no index names the node: a template- or type-spliced child,
|
|
857
|
+
* a datamodel ghost, the contents of a named slot, and a scrollarea's
|
|
858
|
+
* pass-through children, whose ranks count a body their drawn parent does not
|
|
859
|
+
* own. Absent means "not addressable by index"; do not fall back to counting.
|
|
860
|
+
*/
|
|
861
|
+
srcIndex?: number;
|
|
862
|
+
/**
|
|
863
|
+
* Placeholder copy of a datamodel item template (the list has no runtime
|
|
864
|
+
* rows in a static preview). The renderer draws it at reduced opacity; it is
|
|
865
|
+
* never editable. Presentation only, not a measured layout rule.
|
|
866
|
+
*/
|
|
867
|
+
ghost?: boolean;
|
|
868
|
+
/**
|
|
869
|
+
* The widget's `onclick` value as authored, minus its quotes, when it has
|
|
870
|
+
* one. A static preview cannot run it; a client's interact mode reads the
|
|
871
|
+
* `GetVariableSystem.*` calls out of it to drive the visibility checks, and
|
|
872
|
+
* names the rest as what the game would run.
|
|
873
|
+
*/
|
|
874
|
+
onclick?: string;
|
|
875
|
+
/** The widget's `tooltip` value as authored (a loc key or a [datafunction]), when it has one. */
|
|
876
|
+
tooltip?: string;
|
|
877
|
+
/**
|
|
878
|
+
* A root that is a `type name = base { }` DECLARATION laid out as one
|
|
879
|
+
* instance of itself. Set only on roots, and only for a document that
|
|
880
|
+
* instantiates nothing at top level, the shape whole panels are written in
|
|
881
|
+
* by the games whose engine instantiates a window by name from code. The
|
|
882
|
+
* declaration header is not editable; the children under it are ordinary
|
|
883
|
+
* statements of the document and are.
|
|
884
|
+
*/
|
|
885
|
+
declared?: boolean;
|
|
886
|
+
children: GuiLayoutNode[];
|
|
887
|
+
}
|
|
888
|
+
export interface GuiLayoutResult {
|
|
889
|
+
nodes: GuiLayoutNode[];
|
|
890
|
+
/** Distinct texture paths referenced anywhere in the tree (mod-relative). */
|
|
891
|
+
textures: string[];
|
|
892
|
+
/** Total node count across all depths. */
|
|
893
|
+
nodeCount: number;
|
|
894
|
+
/** How many .gui files fed the template/type store (0 = no game path). */
|
|
895
|
+
defsFiles: number;
|
|
896
|
+
/**
|
|
897
|
+
* Every conditional `visible` the layout met, key-sorted. Reported in ALL
|
|
898
|
+
* modes, `showAll` included, so a client can build the toggle UI before the
|
|
899
|
+
* user has switched mode.
|
|
900
|
+
*/
|
|
901
|
+
visibilityChecks: GuiVisibilityCheck[];
|
|
902
|
+
/** Per-stage wall clock of this request. */
|
|
903
|
+
timings: GuiLayoutTimings;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
/**
|
|
907
|
+
* Request: the properties of ONE widget, as the layout engine resolved them;
|
|
908
|
+
* {@link GuiWidgetInfoParams} -> {@link GuiWidgetInfo}, null when the line
|
|
909
|
+
* carries no widget of its own (a node spliced in from a template or a type has
|
|
910
|
+
* no source here, the same answer `guiSourceEdit` refuses with).
|
|
911
|
+
*
|
|
912
|
+
* This is the designer inspector's READ side. It is a separate request rather
|
|
913
|
+
* than a field on {@link GuiLayoutNode} because it is per-SELECTION data: a
|
|
914
|
+
* vanilla window lays out 500+ widgets and carrying every widget's expanded
|
|
915
|
+
* property list on every layout push would multiply the payload for rows one
|
|
916
|
+
* widget at a time is ever shown.
|
|
917
|
+
*/
|
|
918
|
+
export const guiWidgetInfoRequest = "paradox/guiWidgetInfo";
|
|
919
|
+
export interface GuiWidgetInfoParams {
|
|
920
|
+
/** For display only; the text is authoritative. */
|
|
921
|
+
uri: string;
|
|
922
|
+
text: string;
|
|
923
|
+
/** 0-based line of the widget's own statement (`GuiLayoutNode.line`). */
|
|
924
|
+
line: number;
|
|
925
|
+
/**
|
|
926
|
+
* Also answer "why is it here": run the layout with an explanation trace on
|
|
927
|
+
* and return {@link GuiWidgetInfo.placement}. Off by default because it costs
|
|
928
|
+
* a full layout of the document; the trace itself is what the flag gates, so
|
|
929
|
+
* an ordinary `paradox/guiLayout` never pays for it.
|
|
930
|
+
*/
|
|
931
|
+
placement?: boolean;
|
|
932
|
+
}
|
|
933
|
+
/** One step of the chain a property was spliced through. */
|
|
934
|
+
export interface GuiWidgetOrigin {
|
|
935
|
+
kind: "type" | "template";
|
|
936
|
+
/** The type or template name, as `expandWidget` resolved it. */
|
|
937
|
+
name: string;
|
|
938
|
+
}
|
|
939
|
+
export interface GuiWidgetProperty {
|
|
940
|
+
key: string;
|
|
941
|
+
/**
|
|
942
|
+
* The value as authored, rendered from the tokens: a quoted scalar keeps its
|
|
943
|
+
* quotes, a block reads `{ a b }`. Blocks come from other files whose text
|
|
944
|
+
* the store does not keep, so this is a rendering, not a byte copy.
|
|
945
|
+
*/
|
|
946
|
+
value: string;
|
|
947
|
+
/**
|
|
948
|
+
* Definitions the entry was spliced through, INNERMOST first (`[template
|
|
949
|
+
* PxDeco, type px_card]` = a template used inside a type). Empty means the
|
|
950
|
+
* property is authored in the widget's own body, which is the only case
|
|
951
|
+
* `setProperties` rewrites in place.
|
|
952
|
+
*/
|
|
953
|
+
origin: GuiWidgetOrigin[];
|
|
954
|
+
/**
|
|
955
|
+
* The values this key SHADOWED, in expansion order (base-most first), so the
|
|
956
|
+
* last entry is the one this row directly overrides. Present only when the
|
|
957
|
+
* key was assigned more than once, which is exactly when the inspector can
|
|
958
|
+
* say "this overrides `{ 100 50 }` from type px_card". Absent otherwise.
|
|
959
|
+
*/
|
|
960
|
+
overrides?: GuiWidgetOverride[];
|
|
961
|
+
}
|
|
962
|
+
/** A value a later assignment of the same key replaced. */
|
|
963
|
+
export interface GuiWidgetOverride {
|
|
964
|
+
/** Rendered the same way {@link GuiWidgetProperty.value} is. */
|
|
965
|
+
value: string;
|
|
966
|
+
/** Where the replaced value came from; empty = the widget's own body. */
|
|
967
|
+
origin: GuiWidgetOrigin[];
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
/**
|
|
971
|
+
* One contribution to a widget's final origin, in engine order. The `dx`/`dy`
|
|
972
|
+
* of the terms sum to the rect's `x`/`y` exactly (see spec.md B1-B/C/D:
|
|
973
|
+
* `x = parent.x + parentanchor.fx*parent.w - widgetanchor.fx*w + position.x`).
|
|
974
|
+
*/
|
|
975
|
+
export interface GuiPlacementTerm {
|
|
976
|
+
kind: "parentOrigin" | "parentanchor" | "widgetanchor" | "position";
|
|
977
|
+
/**
|
|
978
|
+
* The authored spec behind the term (`bottom|right`, `{ -30 -30 }`). Absent
|
|
979
|
+
* on `parentOrigin`, which is the parent's rect rather than a property, and
|
|
980
|
+
* on a `widgetanchor` that was never written (it mirrors `parentanchor`,
|
|
981
|
+
* B1-B/C), there `source` names the anchor it mirrored.
|
|
982
|
+
*/
|
|
983
|
+
source?: string;
|
|
984
|
+
dx: number;
|
|
985
|
+
dy: number;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
/**
|
|
989
|
+
* The layout container that assigned a rect outright. The engine DROPS an
|
|
990
|
+
* authored `position` on such a child and logs "Widget cannot have a position
|
|
991
|
+
* in a layout" (probe 2026-08-02, parity-checklist L23), which is the single
|
|
992
|
+
* most common "why is my widget not where I put it".
|
|
993
|
+
*/
|
|
994
|
+
export interface GuiPlacedBy {
|
|
995
|
+
/** The parent's widget key (`hbox`, `flowcontainer`, `fixedgridbox`, …). */
|
|
996
|
+
key: string;
|
|
997
|
+
name?: string;
|
|
998
|
+
layout: "box" | "flow" | "grid";
|
|
999
|
+
/** The `position` the engine dropped, when the widget authored one. */
|
|
1000
|
+
droppedPosition?: [number, number];
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
/** Why a widget's rect is where it is. */
|
|
1004
|
+
export interface GuiPlacement {
|
|
1005
|
+
/** The final rect, the same one `GuiLayoutNode.rect` carries. */
|
|
1006
|
+
rect: { x: number; y: number; w: number; h: number };
|
|
1007
|
+
/** What the terms are measured against: the parent's content rect, or the
|
|
1008
|
+
* viewport for a root widget. */
|
|
1009
|
+
parentRect: { x: number; y: number; w: number; h: number };
|
|
1010
|
+
/**
|
|
1011
|
+
* The anchor terms, summing to the rect origin. EMPTY when `placedBy` is
|
|
1012
|
+
* set: a layout container computes the slot, so there is no anchor sum to
|
|
1013
|
+
* show.
|
|
1014
|
+
*/
|
|
1015
|
+
terms: GuiPlacementTerm[];
|
|
1016
|
+
placedBy?: GuiPlacedBy;
|
|
1017
|
+
/**
|
|
1018
|
+
* The innermost clipping ancestor (a scrollarea viewport, or any widget with
|
|
1019
|
+
* `scissor = yes`), when one clips this widget. The rect is the clip rect,
|
|
1020
|
+
* NOT the intersection: the geometry is true and the renderer clips.
|
|
1021
|
+
*/
|
|
1022
|
+
clippedBy?: { key: string; name?: string; rect: { x: number; y: number; w: number; h: number } };
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
/**
|
|
1026
|
+
* A texture the widget draws, with its frame-sheet grid when it is one. The
|
|
1027
|
+
* sheet's pixel size comes from the DDS header alone (128 bytes read, no
|
|
1028
|
+
* decode); `columns`/`rows`/`cell` need it, so they are absent when the file
|
|
1029
|
+
* does not resolve under the configured roots.
|
|
1030
|
+
*
|
|
1031
|
+
* The grid is driven by `framesize`, the property the vanilla gui trees
|
|
1032
|
+
* actually carry (both harvested titles ship it; neither ships `noofframes`).
|
|
1033
|
+
*/
|
|
1034
|
+
export interface GuiTextureInfo {
|
|
1035
|
+
/** The path as authored, mod-relative, the way the engine reads it. */
|
|
1036
|
+
path: string;
|
|
1037
|
+
/** Which fill it belongs to. */
|
|
1038
|
+
source: "fill" | "background";
|
|
1039
|
+
/** Absolute file it resolved to: mod, then parent mods (last first), then the game. */
|
|
1040
|
+
file?: string;
|
|
1041
|
+
/** Sheet pixel size from the DDS header. */
|
|
1042
|
+
width?: number;
|
|
1043
|
+
height?: number;
|
|
1044
|
+
/** `framesize = { w h }`: the grid's cell size. */
|
|
1045
|
+
framesize?: [number, number];
|
|
1046
|
+
/** Grid shape, row-major: floor(width/cellW) x floor(height/cellH). */
|
|
1047
|
+
columns?: number;
|
|
1048
|
+
rows?: number;
|
|
1049
|
+
/** The 1-based frame the widget shows (`frame`, default 1), clamped to the grid. */
|
|
1050
|
+
frame?: number;
|
|
1051
|
+
/** That frame's cell in texture pixels. */
|
|
1052
|
+
cell?: { x: number; y: number; w: number; h: number };
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
export interface GuiWidgetInfo {
|
|
1056
|
+
key: string;
|
|
1057
|
+
name?: string;
|
|
1058
|
+
/** The base-type chain the key resolves through, derived-most first. */
|
|
1059
|
+
typeChain: string[];
|
|
1060
|
+
/**
|
|
1061
|
+
* Effective properties in expansion order, last-in-wins per key: exactly the
|
|
1062
|
+
* values the engine laid the widget out with, so the inspector cannot show a
|
|
1063
|
+
* row the canvas did not use.
|
|
1064
|
+
*/
|
|
1065
|
+
properties: GuiWidgetProperty[];
|
|
1066
|
+
/**
|
|
1067
|
+
* Textures the widget draws (its own fill first, then its background), with
|
|
1068
|
+
* frame-sheet geometry. `[]` when it draws none; absent only from a server
|
|
1069
|
+
* that predates the field.
|
|
1070
|
+
*/
|
|
1071
|
+
textures?: GuiTextureInfo[];
|
|
1072
|
+
/**
|
|
1073
|
+
* Why the widget's rect is where it is. Present only when the request asked
|
|
1074
|
+
* for it (`placement: true`) AND the layout actually reached the widget: a
|
|
1075
|
+
* declaration inside a `tooltipwidget` or a subtree the engine skips has a
|
|
1076
|
+
* source line but no rect.
|
|
1077
|
+
*/
|
|
1078
|
+
placement?: GuiPlacement;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
* Request: what a `.gui` document reaches on the SCRIPT side;
|
|
1083
|
+
* {@link GuiDependenciesParams} -> {@link GuiDependenciesResult}. The forward
|
|
1084
|
+
* half of the dependency surface; the reverse (script definition -> the .gui
|
|
1085
|
+
* paths using it) is `paradox/dependencies` with `guiUses: true`, so both
|
|
1086
|
+
* directions come out of the same scripted_gui link.
|
|
1087
|
+
*/
|
|
1088
|
+
export const guiDependenciesRequest = "paradox/guiDependencies";
|
|
1089
|
+
export interface GuiDependenciesParams {
|
|
1090
|
+
/** For display only; the text is authoritative. */
|
|
1091
|
+
uri: string;
|
|
1092
|
+
text: string;
|
|
1093
|
+
/**
|
|
1094
|
+
* Restrict the answer to one widget's SOURCE subtree, addressed by the
|
|
1095
|
+
* 0-based line of its own statement (`GuiLayoutNode.line`). Absent = the
|
|
1096
|
+
* whole document. A line carrying no widget answers with empty lists.
|
|
1097
|
+
*/
|
|
1098
|
+
line?: number;
|
|
1099
|
+
}
|
|
1100
|
+
/** A scripted_gui the document calls, and what it hands control to. */
|
|
1101
|
+
export interface GuiScriptedGuiRow {
|
|
1102
|
+
name: string;
|
|
1103
|
+
/** Definition site; absent when the index has no scripted_gui by that name. */
|
|
1104
|
+
file?: string;
|
|
1105
|
+
line?: number;
|
|
1106
|
+
/** 0-based lines in the REQUESTED document that call it. */
|
|
1107
|
+
callLines: number[];
|
|
1108
|
+
/** Call sites across every `.gui` file the layout store scanned. */
|
|
1109
|
+
uses: number;
|
|
1110
|
+
/** Events / on_actions the scripted_gui's own blocks hand control to. */
|
|
1111
|
+
chains: GuiEventChain[];
|
|
1112
|
+
}
|
|
1113
|
+
/** An event or on_action a scripted_gui reaches, and how. */
|
|
1114
|
+
export interface GuiEventChain {
|
|
1115
|
+
name: string;
|
|
1116
|
+
kind: "event" | "on_action";
|
|
1117
|
+
file?: string;
|
|
1118
|
+
line?: number;
|
|
1119
|
+
/**
|
|
1120
|
+
* The scripted effects traversed to get there, outermost first. Empty =
|
|
1121
|
+
* "directly"; `["effect_a", "effect_b"]` renders as "via effect_a -> effect_b".
|
|
1122
|
+
*/
|
|
1123
|
+
via: string[];
|
|
1124
|
+
}
|
|
1125
|
+
/** A localization key the document names, checked against the loc index. */
|
|
1126
|
+
export interface GuiLocRow {
|
|
1127
|
+
key: string;
|
|
1128
|
+
/** The gui property that named it (`text`, `tooltip`). */
|
|
1129
|
+
prop: string;
|
|
1130
|
+
/** 0-based line in the requested document. */
|
|
1131
|
+
line: number;
|
|
1132
|
+
/** No `loc_key` definition anywhere in the index. */
|
|
1133
|
+
missing: boolean;
|
|
1134
|
+
/** The resolved text, when the index has one. */
|
|
1135
|
+
value?: string;
|
|
1136
|
+
}
|
|
1137
|
+
export interface GuiDependenciesResult {
|
|
1138
|
+
/** The widget the answer is scoped to; absent for a whole-document answer. */
|
|
1139
|
+
widget?: { key: string; name?: string; line: number };
|
|
1140
|
+
scriptedGuis: GuiScriptedGuiRow[];
|
|
1141
|
+
locKeys: GuiLocRow[];
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
/**
|
|
1145
|
+
* Request: the widget names a designer palette may offer for THIS document;
|
|
1146
|
+
* {@link GuiVocabularyParams} -> {@link GuiVocabularyResult}.
|
|
1147
|
+
*
|
|
1148
|
+
* Every name is harvested, never listed by hand: the bundled per-game widget
|
|
1149
|
+
* schema (`data/<game>/guiSchema.json`, built from the vanilla `gui/` tree)
|
|
1150
|
+
* plus the requested document's own `template` and `type` declarations. A
|
|
1151
|
+
* palette entry is therefore always a widget the game knows.
|
|
1152
|
+
*/
|
|
1153
|
+
export const guiVocabularyRequest = "paradox/guiVocabulary";
|
|
1154
|
+
export interface GuiVocabularyParams {
|
|
1155
|
+
/** For display only; the text is authoritative. */
|
|
1156
|
+
uri: string;
|
|
1157
|
+
text: string;
|
|
1158
|
+
}
|
|
1159
|
+
export interface GuiVocabularyEntry {
|
|
1160
|
+
name: string;
|
|
1161
|
+
/** `builtin` = the vanilla harvest; `type`/`template` = this document declares it. */
|
|
1162
|
+
kind: "builtin" | "type" | "template";
|
|
1163
|
+
/** How many times the vanilla gui tree writes it (`builtin` only). */
|
|
1164
|
+
count?: number;
|
|
1165
|
+
/** The base widget key a `type` derives from. */
|
|
1166
|
+
base?: string;
|
|
1167
|
+
/** Declared in the requested document itself. */
|
|
1168
|
+
local?: boolean;
|
|
1169
|
+
/**
|
|
1170
|
+
* The vanilla tree writes widgets inside it, so it can hold children: what a
|
|
1171
|
+
* "wrap in a container" menu offers. Derived from the harvest's own child
|
|
1172
|
+
* counts, not from a list of container names.
|
|
1173
|
+
*/
|
|
1174
|
+
container?: boolean;
|
|
1175
|
+
}
|
|
1176
|
+
export interface GuiVocabularyResult {
|
|
1177
|
+
/**
|
|
1178
|
+
* The document's own declarations first, then the harvested types by vanilla
|
|
1179
|
+
* usage. Capped; `total` gives the real count, so a UI states what it hid.
|
|
1180
|
+
*/
|
|
1181
|
+
entries: GuiVocabularyEntry[];
|
|
1182
|
+
total: number;
|
|
1183
|
+
/**
|
|
1184
|
+
* Widget type -> the property names the harvest saw on it, most used first
|
|
1185
|
+
* and capped: what an inspector's add-property row completes from. Only the
|
|
1186
|
+
* types THIS DOCUMENT names are here (the keys it writes blocks under, plus
|
|
1187
|
+
* the bases of its own `type X = base` declarations), because the harvest
|
|
1188
|
+
* holds hundreds of types and this answer is re-asked after every layout.
|
|
1189
|
+
* The server always sends it (empty for a game with no harvest); it is
|
|
1190
|
+
* optional only so older recorded responses stay type-valid.
|
|
1191
|
+
*/
|
|
1192
|
+
properties?: Record<string, string[]>;
|
|
1193
|
+
/**
|
|
1194
|
+
* The vanilla tree's most-used property names overall, most used first and
|
|
1195
|
+
* capped: the fallback ranking for a widget whose type the harvest has never
|
|
1196
|
+
* seen, so completion still offers something real rather than nothing.
|
|
1197
|
+
*/
|
|
1198
|
+
commonProperties?: string[];
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
/**
|
|
1202
|
+
* Render-ready previews of palette entries: one instance of each entry laid
|
|
1203
|
+
* out in a synthetic document that keeps the requested document's own
|
|
1204
|
+
* declarations (so a local template previews with its real base). The
|
|
1205
|
+
* result is an ordinary node tree the client draws with the same painter as
|
|
1206
|
+
* the canvas. Entries a synthetic document cannot stand up (nothing to show,
|
|
1207
|
+
* zero size, a type the store lacks) come back with `node: null` and a
|
|
1208
|
+
* `reason`. Capped per request (GUI_PREVIEW_MAX); ask for the visible page.
|
|
1209
|
+
*/
|
|
1210
|
+
export const guiPreviewRequest = "paradox/guiPreview";
|
|
1211
|
+
export const GUI_PREVIEW_MAX = 48;
|
|
1212
|
+
export interface GuiPreviewEntry {
|
|
1213
|
+
name: string;
|
|
1214
|
+
/** `raw`: `fragment` is `.gui` text (a saved component) laid out as is. */
|
|
1215
|
+
kind: "builtin" | "type" | "template" | "raw";
|
|
1216
|
+
fragment?: string;
|
|
1217
|
+
}
|
|
1218
|
+
export interface GuiPreviewParams {
|
|
1219
|
+
/** For display only; the text is authoritative. */
|
|
1220
|
+
uri: string;
|
|
1221
|
+
text: string;
|
|
1222
|
+
entries: GuiPreviewEntry[];
|
|
1223
|
+
}
|
|
1224
|
+
export interface GuiPreview {
|
|
1225
|
+
name: string;
|
|
1226
|
+
node: GuiLayoutNode | null;
|
|
1227
|
+
/** Texture paths the node tree references (mod-relative). */
|
|
1228
|
+
textures: string[];
|
|
1229
|
+
reason?: string;
|
|
1230
|
+
}
|
|
1231
|
+
export interface GuiPreviewResult {
|
|
1232
|
+
previews: GuiPreview[];
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
/**
|
|
1236
|
+
* Preview values read out of a save game, so a designer draws
|
|
1237
|
+
* `[GetPlayer.GetName]` as "Great Britain" instead of a placeholder chip.
|
|
1238
|
+
*
|
|
1239
|
+
* `values` is keyed by datafunction chain WITHOUT brackets, exactly the shape
|
|
1240
|
+
* {@link GuiLayoutParams.previewValues} takes, so a client hands the answer
|
|
1241
|
+
* straight back to the next layout request. A chain the save has no field for
|
|
1242
|
+
* is absent: a preview shows what is knowable and never invents a value.
|
|
1243
|
+
*
|
|
1244
|
+
* The server streams the file and parses only the few blocks it needs (a big
|
|
1245
|
+
* campaign runs ~115 MB), and caches the answer per file and mtime.
|
|
1246
|
+
* Ironman and binary saves are refused with `error` set; melting them is a
|
|
1247
|
+
* different tool.
|
|
1248
|
+
*/
|
|
1249
|
+
export const guiSaveValuesRequest = "paradox/guiSaveValues";
|
|
1250
|
+
export interface GuiSaveValuesParams {
|
|
1251
|
+
/** Absolute path to the save file. */
|
|
1252
|
+
path: string;
|
|
1253
|
+
}
|
|
1254
|
+
export interface GuiSaveValuesResult {
|
|
1255
|
+
/** Datafunction chain without brackets -> display text. */
|
|
1256
|
+
values: Record<string, string>;
|
|
1257
|
+
/** What the values came from, for a UI to name the save it is showing. */
|
|
1258
|
+
source: {
|
|
1259
|
+
/** The campaign's name as the save's meta data states it. */
|
|
1260
|
+
name: string;
|
|
1261
|
+
/** The in-game date, already formatted ("21 January 1836"). */
|
|
1262
|
+
date: string;
|
|
1263
|
+
/** The game the values were read for. */
|
|
1264
|
+
game: string;
|
|
1265
|
+
};
|
|
1266
|
+
/** Set when the save cannot be read (ironman, binary, unreadable). */
|
|
1267
|
+
error?: string;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
/**
|
|
1271
|
+
* Request: source edits for a `.gui` designer gesture;
|
|
1272
|
+
* {@link GuiSourceEditParams} -> {@link GuiSourceEditResult}, null when the
|
|
1273
|
+
* request itself makes no sense (an unknown op). The server never writes: it
|
|
1274
|
+
* returns offsets into the text it was handed and the host applies them, which
|
|
1275
|
+
* keeps undo, dirty state and the live preview in the editor (EMBEDDING.md,
|
|
1276
|
+
* host-owns-text).
|
|
1277
|
+
*
|
|
1278
|
+
* Every edit is surgical, over the exact span the source model recorded, so
|
|
1279
|
+
* untouched bytes stay byte-identical: comments, CRLF, tabs-vs-spaces and
|
|
1280
|
+
* single-line bodies all survive a write.
|
|
1281
|
+
*/
|
|
1282
|
+
export const guiSourceEditRequest = "paradox/guiSourceEdit";
|
|
1283
|
+
export interface GuiSourceEditParams {
|
|
1284
|
+
/** For display only; the text is authoritative. */
|
|
1285
|
+
uri: string;
|
|
1286
|
+
/** Authoritative document text every offset refers to. */
|
|
1287
|
+
text: string;
|
|
1288
|
+
/** One op. Mutually exclusive with {@link ops}; sending both answers null. */
|
|
1289
|
+
op?: GuiSourceOp;
|
|
1290
|
+
/**
|
|
1291
|
+
* A BATCH: several ops computed against this one text and answered as one
|
|
1292
|
+
* edit set, which is what makes a multi-widget gesture one document change
|
|
1293
|
+
* and one undo step. Every op gets a verdict of its own in
|
|
1294
|
+
* {@link GuiSourceEditResult.results}, so a refusal is per op and the rest
|
|
1295
|
+
* still apply. Order matters: the ops are computed in the order given, and a
|
|
1296
|
+
* later one whose bytes a earlier one already changes is refused rather than
|
|
1297
|
+
* silently dropped.
|
|
1298
|
+
*/
|
|
1299
|
+
ops?: GuiSourceOp[];
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
/** One surgical replacement: replace `[start, end)` with `newText`. */
|
|
1303
|
+
export interface GuiTextEdit {
|
|
1304
|
+
/** UTF-16 offsets into the request text. */
|
|
1305
|
+
start: number;
|
|
1306
|
+
end: number;
|
|
1307
|
+
newText: string;
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
/**
|
|
1311
|
+
* What to do. `line` is the 0-based line of the target widget's own statement,
|
|
1312
|
+
* the same `line` {@link GuiLayoutNode} reports; a node with no line of its own
|
|
1313
|
+
* (spliced in from a template or a type) has no source to edit and is refused.
|
|
1314
|
+
* `index` counts SOURCE children, not the template-expanded ones a preview
|
|
1315
|
+
* shows; out of range appends.
|
|
1316
|
+
*/
|
|
1317
|
+
export type GuiSourceOp =
|
|
1318
|
+
/** Set or (with a null value) remove properties on one widget. */
|
|
1319
|
+
| { kind: "setProperties"; line: number; properties: { key: string; value: string | null }[] }
|
|
1320
|
+
/** Move a source child of the widget on `line` from one index to another. */
|
|
1321
|
+
| { kind: "reorder"; line: number; from: number; to: number }
|
|
1322
|
+
| { kind: "insert"; line: number; widget: GuiNewWidget; index?: number }
|
|
1323
|
+
/** Paste `.gui` text as a child, re-indented for the destination. */
|
|
1324
|
+
| { kind: "insertRaw"; line: number; fragment: string; index?: number }
|
|
1325
|
+
| { kind: "delete"; line: number }
|
|
1326
|
+
/** Copy the widget in as its own next sibling, optionally renamed. */
|
|
1327
|
+
| { kind: "duplicate"; line: number; name?: string }
|
|
1328
|
+
/** Wrap the widgets on `lines` (siblings) in a fresh container. */
|
|
1329
|
+
| { kind: "wrap"; lines: number[]; container: GuiNewWidget }
|
|
1330
|
+
/** Read-only: the widget's block, verbatim, for a clipboard. */
|
|
1331
|
+
| { kind: "blockText"; line: number };
|
|
1332
|
+
|
|
1333
|
+
/** A declaration to write: `type = { properties }`, properties in order. */
|
|
1334
|
+
export interface GuiNewWidget {
|
|
1335
|
+
type: string;
|
|
1336
|
+
properties?: [string, string][];
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
/**
|
|
1340
|
+
* For a single `op`, exactly one of `edits` and `refused` is present. A refusal
|
|
1341
|
+
* is an ANSWER, not an error: it names why the gesture would not do what it
|
|
1342
|
+
* looks like it does (a box owns its children's slots, a content-sized type
|
|
1343
|
+
* ignores an explicit size, a type definition other files use). `warning` rides
|
|
1344
|
+
* along with a write that went ahead but is only half honoured.
|
|
1345
|
+
*
|
|
1346
|
+
* For a BATCH (`ops`), `results` is present with one entry per op in the same
|
|
1347
|
+
* order, `edits` is every applied op's edits together (apply them as ONE
|
|
1348
|
+
* change), and `warning` joins the warnings. Top-level `refused` then names
|
|
1349
|
+
* only a whole-request failure (a document that does not parse, an empty
|
|
1350
|
+
* batch): a per-op refusal lives in its own entry and does not stop the others.
|
|
1351
|
+
*/
|
|
1352
|
+
export interface GuiSourceEditResult {
|
|
1353
|
+
edits?: GuiTextEdit[];
|
|
1354
|
+
refused?: string;
|
|
1355
|
+
warning?: string;
|
|
1356
|
+
/** `blockText` only: the copied block. */
|
|
1357
|
+
blockText?: string;
|
|
1358
|
+
/** Batch only: one verdict per requested op, in request order. */
|
|
1359
|
+
results?: GuiSourceOpResult[];
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
/** One op's own answer inside a batch. */
|
|
1363
|
+
export interface GuiSourceOpResult {
|
|
1364
|
+
/** Why this op wrote nothing. The others in the batch still applied. */
|
|
1365
|
+
refused?: string;
|
|
1366
|
+
/** This op wrote, and is only half honoured. */
|
|
1367
|
+
warning?: string;
|
|
1368
|
+
/** This op's contribution to the combined `edits`; empty when it wrote nothing. */
|
|
1369
|
+
edits: GuiTextEdit[];
|
|
1370
|
+
/** `blockText` only: the copied block. */
|
|
1371
|
+
blockText?: string;
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
/**
|
|
1375
|
+
* Request: text edit for a preview interaction (drag / property change);
|
|
1376
|
+
* {@link GuiWidgetEditParams} -> {@link GuiWidgetEditResult} (null when the
|
|
1377
|
+
* widget or property cannot be edited). The client applies the offsets via
|
|
1378
|
+
* WorkspaceEdit so undo and the live preview loop stay in the editor.
|
|
1379
|
+
*
|
|
1380
|
+
* @deprecated Use {@link guiSourceEditRequest} with a `setProperties` op. This
|
|
1381
|
+
* is a thin alias over the same core, kept for hosts already wired to it: it
|
|
1382
|
+
* can only write the `position`/`size` pair and returns one edit or null, so a
|
|
1383
|
+
* refusal reaches the caller as a bare null with no reason attached.
|
|
1384
|
+
*/
|
|
1385
|
+
export const guiWidgetEditRequest = "paradox/guiWidgetEdit";
|
|
1386
|
+
export interface GuiWidgetEditParams {
|
|
1387
|
+
uri: string;
|
|
1388
|
+
/** Authoritative document text the offsets refer to. */
|
|
1389
|
+
text: string;
|
|
1390
|
+
/** 0-based line of the widget's instance statement (GuiLayoutNode.line). */
|
|
1391
|
+
line: number;
|
|
1392
|
+
/** Pair property to set. */
|
|
1393
|
+
property: "position" | "size";
|
|
1394
|
+
values: [number, number];
|
|
1395
|
+
}
|
|
1396
|
+
export interface GuiWidgetEditResult {
|
|
1397
|
+
/** UTF-16 offsets into the request text. */
|
|
1398
|
+
start: number;
|
|
1399
|
+
end: number;
|
|
1400
|
+
newText: string;
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
/** Request: event graph; {@link EventGraphParams} -> {@link EventGraph}. */
|
|
1404
|
+
export const eventGraphRequest = "paradox/eventGraph";
|
|
1405
|
+
export interface EventGraphParams {
|
|
1406
|
+
/** Focus definition (event id / on_action name); with namespace, either works. */
|
|
1407
|
+
root?: string;
|
|
1408
|
+
/** Restrict to an event namespace. */
|
|
1409
|
+
namespace?: string;
|
|
1410
|
+
/** Restrict to one workspace mod (absolute root path). */
|
|
1411
|
+
modRoot?: string | null;
|
|
1412
|
+
maxNodes?: number;
|
|
1413
|
+
/** Also read each mod event's `theme`. Off by default: it costs one parse per
|
|
1414
|
+
* event file, and only a client that draws the theme's art needs it. */
|
|
1415
|
+
themes?: boolean;
|
|
1416
|
+
/**
|
|
1417
|
+
* Leave out every definition that has no edge in the answer. ON by default
|
|
1418
|
+
* (absent = true): the pruned definitions are dropped before their cards
|
|
1419
|
+
* are read, so a mod with hundreds of standalone events stays cheap. `root`
|
|
1420
|
+
* is always kept. Send `false` to see the whole namespace, edges or not.
|
|
1421
|
+
*/
|
|
1422
|
+
connectedOnly?: boolean;
|
|
1423
|
+
}
|
|
1424
|
+
/**
|
|
1425
|
+
* One row of a mod event's card, in EXECUTION order (immediate, then the
|
|
1426
|
+
* options, then after) rather than file order. `line` is the join key an edge
|
|
1427
|
+
* uses to anchor at the row that fires it ({@link EventGraphEdge.fromLine}).
|
|
1428
|
+
*/
|
|
1429
|
+
export interface EventGraphStep {
|
|
1430
|
+
phase: "immediate" | "option" | "after";
|
|
1431
|
+
/** Option ordinal within the event, 0-based. */
|
|
1432
|
+
index?: number;
|
|
1433
|
+
/** The option's localized text, when resolvable. */
|
|
1434
|
+
text?: string;
|
|
1435
|
+
/** 0-based line of the step's key in the event's file. */
|
|
1436
|
+
line: number;
|
|
1437
|
+
}
|
|
1438
|
+
export interface EventGraphNode {
|
|
1439
|
+
id: string;
|
|
1440
|
+
kind: string;
|
|
1441
|
+
source: "vanilla" | "parent" | "mod";
|
|
1442
|
+
file?: string;
|
|
1443
|
+
line?: number;
|
|
1444
|
+
/** Localized title (best-effort: <id>.t / <id>_t / <id>.title lookups). */
|
|
1445
|
+
title?: string;
|
|
1446
|
+
/** The event's declared `theme`, when the request asked for themes. */
|
|
1447
|
+
theme?: string;
|
|
1448
|
+
/** How many `option` blocks this definition has (mod-side definitions only). */
|
|
1449
|
+
options?: number;
|
|
1450
|
+
/** The first keys of its `trigger` block, e.g. `is_adult, has_trait…`; absent = no trigger. */
|
|
1451
|
+
triggerSummary?: string;
|
|
1452
|
+
/** How many other nodes of this graph it fires; absent when it fires none. */
|
|
1453
|
+
fires?: number;
|
|
1454
|
+
/** The card's rows (mod events only), capped; {@link EventGraphNode.options} is the true count. */
|
|
1455
|
+
steps?: EventGraphStep[];
|
|
1456
|
+
}
|
|
1457
|
+
export interface EventGraphEdge {
|
|
1458
|
+
from: string;
|
|
1459
|
+
to: string;
|
|
1460
|
+
/** The referencing field (trigger_event, events, on_actions...). */
|
|
1461
|
+
via: string;
|
|
1462
|
+
/** Where in the source event the reference sits: an option's text, or immediate/after/… */
|
|
1463
|
+
label?: string;
|
|
1464
|
+
/** The block the reference sits in, normalized (option/immediate/after/effect/…). */
|
|
1465
|
+
phase?: string;
|
|
1466
|
+
/** 0-based line of that block's key: matches a step's `line` on the source node. */
|
|
1467
|
+
fromLine?: number;
|
|
1468
|
+
/** The trigger_event delay at this site, pre-rendered short: "30d", "7–14d", "2mo", "1y". */
|
|
1469
|
+
delay?: string;
|
|
1470
|
+
/** random_events weight at this site (raw script number). */
|
|
1471
|
+
weight?: number;
|
|
1472
|
+
}
|
|
1473
|
+
/**
|
|
1474
|
+
* What a query box may offer: the whole mod-side vocabulary of the graph, NOT
|
|
1475
|
+
* the ids this particular query selected. It is the same pass that collects the
|
|
1476
|
+
* mod's graph definitions, so a client gets it without a second request.
|
|
1477
|
+
*/
|
|
1478
|
+
export interface EventGraphSuggestions {
|
|
1479
|
+
/** Mod-side event / on_action / decision ids, sorted, capped at 2000. */
|
|
1480
|
+
ids: string[];
|
|
1481
|
+
/** The event namespaces those ids belong to, sorted. */
|
|
1482
|
+
namespaces: string[];
|
|
1483
|
+
}
|
|
1484
|
+
export interface EventGraph {
|
|
1485
|
+
nodes: EventGraphNode[];
|
|
1486
|
+
edges: EventGraphEdge[];
|
|
1487
|
+
truncated: boolean;
|
|
1488
|
+
/** Absent from servers that predate it; a client must tolerate that. */
|
|
1489
|
+
suggestions?: EventGraphSuggestions;
|
|
1490
|
+
/**
|
|
1491
|
+
* Set only when the graph is empty AND the server knows why: the queried
|
|
1492
|
+
* namespace/root exists, but outside what the graph shows (another workspace
|
|
1493
|
+
* mod when a focus filter is on, a dependency mod, or vanilla). One
|
|
1494
|
+
* user-readable sentence; absent = the generic "nothing found" story.
|
|
1495
|
+
*/
|
|
1496
|
+
emptyReason?: string;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
/**
|
|
1500
|
+
* Request: the value sets an event editor may offer; {@link EventVocabularyParams}
|
|
1501
|
+
* to {@link EventVocabularyResult}.
|
|
1502
|
+
*
|
|
1503
|
+
* Everything in the answer is DERIVED: the key lists come from the active
|
|
1504
|
+
* profile's structure table, the field value sets from the schema's reference
|
|
1505
|
+
* fields resolved through the definition index, and the effect/trigger lists
|
|
1506
|
+
* from the user's script_docs (or the bundled wiki fallback). Nothing here is a
|
|
1507
|
+
* hand-written name list, so a game patch that adds a theme or an effect shows
|
|
1508
|
+
* up without a release.
|
|
1509
|
+
*/
|
|
1510
|
+
/**
|
|
1511
|
+
* Request: the illustration an event theme puts behind its window;
|
|
1512
|
+
* {@link EventBannerParams} to {@link EventBannerResult}.
|
|
1513
|
+
*
|
|
1514
|
+
* Resolved through the game's own two hops (event_themes -> event_backgrounds),
|
|
1515
|
+
* taking the last `background` block that carries no `trigger`, which is the
|
|
1516
|
+
* file's own unconditional fallback. `texture` is the engine's mod-relative
|
|
1517
|
+
* path, exactly as a `.gui` file would spell it, so a client resolves it with
|
|
1518
|
+
* the same mod-then-game lookup it uses for any other texture. A theme that
|
|
1519
|
+
* resolves to nothing answers `reason` instead: the caller is expected to say
|
|
1520
|
+
* so rather than draw a picture that is not the event's.
|
|
1521
|
+
*/
|
|
1522
|
+
export const eventBannerRequest = "paradox/eventBanner";
|
|
1523
|
+
export interface EventBannerParams {
|
|
1524
|
+
/** Theme name as the event writes it (`theme = intrigue`). */
|
|
1525
|
+
theme: string;
|
|
1526
|
+
}
|
|
1527
|
+
export interface EventBannerResult {
|
|
1528
|
+
theme: string;
|
|
1529
|
+
/** Mod-relative texture path, absent when nothing resolved. */
|
|
1530
|
+
texture?: string;
|
|
1531
|
+
/** Why nothing resolved. Present exactly when `texture` is absent. */
|
|
1532
|
+
reason?: string;
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
export const eventVocabularyRequest = "paradox/eventVocabulary";
|
|
1536
|
+
export interface EventVocabularyParams {
|
|
1537
|
+
/** Restrict definition-backed value sets to one workspace mod (plus vanilla). */
|
|
1538
|
+
modRoot?: string | null;
|
|
1539
|
+
}
|
|
1540
|
+
/** One offerable value with the one-line docs an editor shows beside it. */
|
|
1541
|
+
export interface EventVocabularyItem {
|
|
1542
|
+
value: string;
|
|
1543
|
+
/** Documentation, capped. Empty when the source has none; never invented. */
|
|
1544
|
+
doc?: string;
|
|
1545
|
+
/** Dimmer right-hand label: where the value comes from (mod / vanilla / a kind). */
|
|
1546
|
+
hint?: string;
|
|
1547
|
+
/**
|
|
1548
|
+
* The name the PLAYER reads: the loc value of the kind's first loc pattern
|
|
1549
|
+
* with `$` replaced by the definition name (`trait_$` -> `trait_brave` ->
|
|
1550
|
+
* "Brave"). Set by {@link definitionFormRequest} only, and absent when
|
|
1551
|
+
* nothing resolves, so a client shows the key rather than an invented word.
|
|
1552
|
+
*/
|
|
1553
|
+
label?: string;
|
|
1554
|
+
/**
|
|
1555
|
+
* The family this definition belongs to, when one folder holds several and
|
|
1556
|
+
* the schema entry names the key that says so (`type = ethos` in
|
|
1557
|
+
* common/culture/pillars). Set by {@link definitionFormRequest} only, so a
|
|
1558
|
+
* creator can draw one picker per family; absent everywhere else.
|
|
1559
|
+
*/
|
|
1560
|
+
group?: string;
|
|
1561
|
+
}
|
|
1562
|
+
/** Caps: an editor lists a page at a time, and these ride on every open. */
|
|
1563
|
+
export const EVENT_VOCABULARY_MAX_TOKENS = 600;
|
|
1564
|
+
export const EVENT_VOCABULARY_MAX_VALUES = 400;
|
|
1565
|
+
|
|
1566
|
+
/**
|
|
1567
|
+
* Most values {@link DefinitionFormKey.sampled} carries, and the point past
|
|
1568
|
+
* which a key is taken to have no value SET at all (a key whose value differs
|
|
1569
|
+
* per definition is a free field, not a list to offer).
|
|
1570
|
+
*/
|
|
1571
|
+
export const DEFINITION_FORM_MAX_SAMPLED = 80;
|
|
1572
|
+
|
|
1573
|
+
/**
|
|
1574
|
+
* How long a block body {@link DefinitionFormKey.example} may be. A placeholder
|
|
1575
|
+
* is read at a glance, and the shortest bodies a game writes for a block key
|
|
1576
|
+
* (a trait's `triggered_opinion`, a culture's `parameters`) fit well inside
|
|
1577
|
+
* this; a longer one is cut with an ellipsis rather than dropped, because half
|
|
1578
|
+
* a real body still says what the key wants.
|
|
1579
|
+
*/
|
|
1580
|
+
export const DEFINITION_FORM_MAX_EXAMPLE = 120;
|
|
1581
|
+
|
|
1582
|
+
/**
|
|
1583
|
+
* Request: the value set a VALUE belongs to, resolved through the definition
|
|
1584
|
+
* index; {@link EventValueOptionsParams} -> {@link EventValueOptionsResult} |
|
|
1585
|
+
* null. The static vocabulary maps a KEY to its values, which only works where
|
|
1586
|
+
* the schema knows the key's context (an event's or option's own fields). Deep
|
|
1587
|
+
* inside an effect tree the same key name means something else (`type` in
|
|
1588
|
+
* `random_secret` is a secret, not an event type), so there the editor asks
|
|
1589
|
+
* about the value it already has: `secret_cultivator` is an indexed `secret`,
|
|
1590
|
+
* and the answer is every secret the index knows. Null = the value resolves to
|
|
1591
|
+
* nothing enumerable; the editor falls back to a free input.
|
|
1592
|
+
*/
|
|
1593
|
+
export const eventValueOptionsRequest = "paradox/eventValueOptions";
|
|
1594
|
+
export interface EventValueOptionsParams {
|
|
1595
|
+
value: string;
|
|
1596
|
+
/** Restrict mod-side entries to one workspace mod (plus vanilla/parents). */
|
|
1597
|
+
modRoot?: string | null;
|
|
1598
|
+
}
|
|
1599
|
+
export interface EventValueOptionsResult {
|
|
1600
|
+
/** The definition kind the value resolved to (trait, secret, faith…). */
|
|
1601
|
+
kind: string;
|
|
1602
|
+
/** Every indexed definition of that kind, mod entries first, capped. */
|
|
1603
|
+
items: EventVocabularyItem[];
|
|
1604
|
+
}
|
|
1605
|
+
export interface EventVocabularyResult {
|
|
1606
|
+
/** Keys valid at an event's top level, most used first. */
|
|
1607
|
+
eventKeys: EventVocabularyItem[];
|
|
1608
|
+
/** Keys valid inside an `option` block, most used first. */
|
|
1609
|
+
optionKeys: EventVocabularyItem[];
|
|
1610
|
+
/**
|
|
1611
|
+
* Key to the values that key accepts, for the keys whose value set is known:
|
|
1612
|
+
* a declared enumeration, or a reference field resolved through the index
|
|
1613
|
+
* (`theme` gives every indexed event_theme). Keys with a free value are absent.
|
|
1614
|
+
*/
|
|
1615
|
+
values: Record<string, EventVocabularyItem[]>;
|
|
1616
|
+
/** Effect tokens, most used first, capped at EVENT_VOCABULARY_MAX_TOKENS. */
|
|
1617
|
+
effects: EventVocabularyItem[];
|
|
1618
|
+
/** Trigger tokens, same ordering and cap. */
|
|
1619
|
+
triggers: EventVocabularyItem[];
|
|
1620
|
+
/** Saved scopes the mod writes (`save_scope_as`), sorted. */
|
|
1621
|
+
savedScopes: EventVocabularyItem[];
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
/**
|
|
1625
|
+
* Request: dependency explorer for any indexed definition;
|
|
1626
|
+
* {@link DependenciesParams} -> {@link DependenciesResult}. Cursor-driven
|
|
1627
|
+
* (uri + position) or by name (optionally disambiguated by kind).
|
|
1628
|
+
*/
|
|
1629
|
+
export const dependenciesRequest = "paradox/dependencies";
|
|
1630
|
+
export interface DependenciesParams {
|
|
1631
|
+
/** Resolve the definition under this cursor position. */
|
|
1632
|
+
uri?: string;
|
|
1633
|
+
position?: { line: number; character: number };
|
|
1634
|
+
/** Fallback: look the definition up by name (optionally by kind). */
|
|
1635
|
+
name?: string;
|
|
1636
|
+
kind?: string;
|
|
1637
|
+
/**
|
|
1638
|
+
* Also resolve {@link DependenciesResult.guiUses}: the `.gui` call sites that
|
|
1639
|
+
* reach this definition through a scripted_gui. Off by default, it walks the
|
|
1640
|
+
* scripted_gui definitions that any .gui file calls, which the plain
|
|
1641
|
+
* dependency answer does not need.
|
|
1642
|
+
*/
|
|
1643
|
+
guiUses?: boolean;
|
|
1644
|
+
}
|
|
1645
|
+
export interface DependencyDef {
|
|
1646
|
+
name: string;
|
|
1647
|
+
kind: string;
|
|
1648
|
+
file: string;
|
|
1649
|
+
/** 0-based. */
|
|
1650
|
+
line: number;
|
|
1651
|
+
}
|
|
1652
|
+
export interface DependencyItem {
|
|
1653
|
+
name: string;
|
|
1654
|
+
file: string;
|
|
1655
|
+
/** 0-based. */
|
|
1656
|
+
line: number;
|
|
1657
|
+
}
|
|
1658
|
+
export interface DependencyGroup {
|
|
1659
|
+
kind: string;
|
|
1660
|
+
items: DependencyItem[];
|
|
1661
|
+
}
|
|
1662
|
+
export interface DependenciesResult {
|
|
1663
|
+
/** The resolved definition, or null when nothing matches the cursor/name. */
|
|
1664
|
+
def: DependencyDef | null;
|
|
1665
|
+
/** Mod definitions/sites that reference `def` (mod files only; vanilla
|
|
1666
|
+
* references aren't indexed, AD-4). Grouped by the containing definition's
|
|
1667
|
+
* kind, else by file. */
|
|
1668
|
+
dependents: DependencyGroup[];
|
|
1669
|
+
/** Named definitions referenced inside `def`'s block, grouped by target kind. */
|
|
1670
|
+
dependencies: DependencyGroup[];
|
|
1671
|
+
/**
|
|
1672
|
+
* The GUI side of the same question, present only when `guiUses` was asked
|
|
1673
|
+
* for: which `.gui` files reach `def`, and through which scripted_gui. `[]`
|
|
1674
|
+
* is the honest "none found"; the field is absent when it was not requested.
|
|
1675
|
+
*/
|
|
1676
|
+
guiUses?: GuiUseSite[];
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
/**
|
|
1680
|
+
* One `.gui` call site that reaches a script definition. The link is always a
|
|
1681
|
+
* scripted_gui: `.gui` invokes script through `GetScriptedGui('name')` and
|
|
1682
|
+
* nothing else, so the path is `file:line -> scripted_gui -> [effects] -> def`.
|
|
1683
|
+
*/
|
|
1684
|
+
export interface GuiUseSite {
|
|
1685
|
+
/** Absolute path of the `.gui` file holding the call. */
|
|
1686
|
+
file: string;
|
|
1687
|
+
/** 0-based line of the `GetScriptedGui(...)` call. */
|
|
1688
|
+
line: number;
|
|
1689
|
+
/** The scripted_gui the call names. */
|
|
1690
|
+
scriptedGui: string;
|
|
1691
|
+
/**
|
|
1692
|
+
* The scripted effects between that scripted_gui and the definition,
|
|
1693
|
+
* outermost first. Empty means the scripted_gui's own blocks name it
|
|
1694
|
+
* ("directly"); `["effect_a", "effect_b"]` renders as
|
|
1695
|
+
* "via effect_a -> effect_b".
|
|
1696
|
+
*/
|
|
1697
|
+
via: string[];
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
/**
|
|
1701
|
+
* Request: the code snippets a host can offer for one open script document;
|
|
1702
|
+
* {@link SnippetsParams} -> {@link SnippetsResult}. Answers for OPEN script
|
|
1703
|
+
* documents only (the server reads the client's text, not the disk); a document
|
|
1704
|
+
* it does not know answers with an EMPTY list, never an error.
|
|
1705
|
+
*
|
|
1706
|
+
* Two sources, neither hand-written. The definition and child-block skeletons
|
|
1707
|
+
* are the measured shape of the document folder's own definition kind (at least
|
|
1708
|
+
* half of the game's definitions of that kind carry each key, in the median
|
|
1709
|
+
* order they hold there). The token entries are the block form of the `usage:`
|
|
1710
|
+
* example the game's own script_docs dump ships for an engine trigger or effect,
|
|
1711
|
+
* filtered to the block the cursor sits in.
|
|
1712
|
+
*
|
|
1713
|
+
* Every entry carries BOTH insert forms, exactly like completion does: `snippet`
|
|
1714
|
+
* for a host that expands `${1:…}` tabstops, `plain` for one that does not.
|
|
1715
|
+
*/
|
|
1716
|
+
export const snippetsRequest = "paradox/snippets";
|
|
1717
|
+
export interface SnippetsParams {
|
|
1718
|
+
uri: string;
|
|
1719
|
+
/** 0-based, as in LSP. Decides which engine block templates fit. */
|
|
1720
|
+
position: { line: number; character: number };
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
/** One offer, ready to insert at the cursor. */
|
|
1724
|
+
export interface SnippetItem {
|
|
1725
|
+
/**
|
|
1726
|
+
* Stable id: the definition kind (`event`), the kind and its child block
|
|
1727
|
+
* (`event.option`), or the engine token (`if`) — plus `<token>.full` when the
|
|
1728
|
+
* token's example marks fields optional and an all-fields form follows it.
|
|
1729
|
+
* Suitable as a picker key.
|
|
1730
|
+
*/
|
|
1731
|
+
id: string;
|
|
1732
|
+
/** Reads as what it inserts: "new event", "option block", "if". */
|
|
1733
|
+
label: string;
|
|
1734
|
+
/** Provenance, with the measurement behind it. */
|
|
1735
|
+
detail: string;
|
|
1736
|
+
/**
|
|
1737
|
+
* `definition` = a whole definition of the document's kind, including the
|
|
1738
|
+
* file header line when the document declares none; `block` = one child block
|
|
1739
|
+
* of that kind; `token` = an engine trigger/effect's own dumped example.
|
|
1740
|
+
*/
|
|
1741
|
+
form: "definition" | "block" | "token";
|
|
1742
|
+
/** `${1:…}` tabstop form. */
|
|
1743
|
+
snippet: string;
|
|
1744
|
+
/** The same shape free of `${`, for hosts without snippet expansion. */
|
|
1745
|
+
plain: string;
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
export interface SnippetsResult {
|
|
1749
|
+
/** Skeletons first (definition, then its child blocks), then engine tokens. */
|
|
1750
|
+
snippets: SnippetItem[];
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
/**
|
|
1754
|
+
* Request: the inferred scope chain at a cursor position;
|
|
1755
|
+
* {@link ScopeAtParams} -> {@link ScopeAtResult} | null. Answers for OPEN
|
|
1756
|
+
* script documents only (the server reads the client's text, not the disk);
|
|
1757
|
+
* null means "not open / not a script document", which a status bar renders as
|
|
1758
|
+
* nothing rather than as an error.
|
|
1759
|
+
*
|
|
1760
|
+
* This is a read-out of the same inference completion, hover and inlay hints
|
|
1761
|
+
* run at a position: it ranks and annotates, never diagnoses, and never
|
|
1762
|
+
* asserts more than the derived link tables actually say.
|
|
1763
|
+
*/
|
|
1764
|
+
export const scopeAtRequest = "paradox/scopeAt";
|
|
1765
|
+
export interface ScopeAtParams {
|
|
1766
|
+
uri: string;
|
|
1767
|
+
/** 0-based, as in LSP. */
|
|
1768
|
+
position: { line: number; character: number };
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
/** One resolved step of the walk from the root scope down to the cursor. */
|
|
1772
|
+
export interface ScopeChainStep {
|
|
1773
|
+
/**
|
|
1774
|
+
* The key that produced the step: a link (`liege`), an iterator
|
|
1775
|
+
* (`every_vassal`), `root`/`prev`, a `scope:x` / `var:x` anchor, or a data
|
|
1776
|
+
* link abbreviated as `culture:…`. Absent on the FIRST step only, which is
|
|
1777
|
+
* the enclosing definition's root scope and comes from no key.
|
|
1778
|
+
*/
|
|
1779
|
+
entryKeyword?: string;
|
|
1780
|
+
/** Scopes after this step; empty = unknown. */
|
|
1781
|
+
scopes: string[];
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
/** A saved scope visible in the document, with the type it resolves to. */
|
|
1785
|
+
export interface SavedScopeInfo {
|
|
1786
|
+
name: string;
|
|
1787
|
+
/** Scopes the name resolves to; empty = unknown. */
|
|
1788
|
+
scopes: string[];
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
export interface ScopeAtResult {
|
|
1792
|
+
/**
|
|
1793
|
+
* Scopes at the position. A SET, not one name: a link or iterator with
|
|
1794
|
+
* several documented output scopes stays ambiguous instead of guessing, and
|
|
1795
|
+
* an EMPTY array means unknown, which is a first-class answer here. Render
|
|
1796
|
+
* several as `a|b` and none as "unknown".
|
|
1797
|
+
*/
|
|
1798
|
+
scopes: string[];
|
|
1799
|
+
/** The walk, outermost (root) first, one entry per scope-changing step. */
|
|
1800
|
+
chain: ScopeChainStep[];
|
|
1801
|
+
/**
|
|
1802
|
+
* Saved scopes visible in the document, name-sorted: every `save_scope_as` /
|
|
1803
|
+
* `save_scope_value_as` site in the file plus the engine-provided ambient
|
|
1804
|
+
* scopes of its definition kind. NOT flow-sensitive, a save further down
|
|
1805
|
+
* the file is listed too, matching what completion and hover already offer.
|
|
1806
|
+
*/
|
|
1807
|
+
savedScopes: SavedScopeInfo[];
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
// ---- content creators --------------------------------------------------------
|
|
1811
|
+
|
|
1812
|
+
/**
|
|
1813
|
+
* Request: everything a visual creator needs to draw a form for one definition
|
|
1814
|
+
* kind; {@link DefinitionFormParams} -> {@link DefinitionForm} | null (null =
|
|
1815
|
+
* the active game's schema has no such kind, which is the honest answer for a
|
|
1816
|
+
* client asking about content this game does not have).
|
|
1817
|
+
*
|
|
1818
|
+
* Nothing in the answer is hand-written for the creator: the folder, the loc
|
|
1819
|
+
* key patterns and the icon folder come from the schema table, the keys from
|
|
1820
|
+
* the harvested `_*.info` structures, the option lists from the definition
|
|
1821
|
+
* index (the same resolver {@link eventValueOptionsRequest} answers with) and
|
|
1822
|
+
* `existing` from the same index walk {@link modOverviewRequest} does. A game
|
|
1823
|
+
* patch that adds a key or a value changes the form without a release.
|
|
1824
|
+
*/
|
|
1825
|
+
export const definitionFormRequest = "paradox/definitionForm";
|
|
1826
|
+
export interface DefinitionFormParams {
|
|
1827
|
+
/** Definition kind, as the schema table spells it ("trait"). */
|
|
1828
|
+
kind: string;
|
|
1829
|
+
/** Load this definition into `current` (edit rather than create). */
|
|
1830
|
+
name?: string;
|
|
1831
|
+
/** Restrict mod-side entries to one workspace mod (plus vanilla/parents). */
|
|
1832
|
+
modRoot?: string | null;
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
/** One key of a definition body, with what is known about the values it takes. */
|
|
1836
|
+
export interface DefinitionFormKey {
|
|
1837
|
+
key: string;
|
|
1838
|
+
/** The game's own one-line documentation, capped. Absent when it has none. */
|
|
1839
|
+
doc?: string;
|
|
1840
|
+
/** Coarse value hint from the schema: `loc`, `bool`, `block`, `enum:a|b|c`. */
|
|
1841
|
+
values?: string;
|
|
1842
|
+
/** Vanilla usage count from the harvest, the order the keys arrive in. */
|
|
1843
|
+
freq?: number;
|
|
1844
|
+
/**
|
|
1845
|
+
* Definition kinds this key's value names, when the profile says so. The
|
|
1846
|
+
* lists live in {@link DefinitionForm.options}, keyed by kind, so several
|
|
1847
|
+
* keys naming the same kind share one list.
|
|
1848
|
+
*/
|
|
1849
|
+
refKinds?: string[];
|
|
1850
|
+
/**
|
|
1851
|
+
* The values the indexed definitions of this kind actually write for this
|
|
1852
|
+
* key, most used first, for keys no definition index can answer (a culture's
|
|
1853
|
+
* `clothing_gfx` names an art set, not a definition). Measured from the game
|
|
1854
|
+
* and mod files the server has indexed, at request time, so a patch changes
|
|
1855
|
+
* the list without a release; absent when the key has no refKinds-free value
|
|
1856
|
+
* set of at most {@link DEFINITION_FORM_MAX_SAMPLED} entries, which is the
|
|
1857
|
+
* honest answer for a key whose value is different in every definition.
|
|
1858
|
+
*/
|
|
1859
|
+
sampled?: string[];
|
|
1860
|
+
/**
|
|
1861
|
+
* The literal the indexed definitions of this kind write most often for this
|
|
1862
|
+
* key: a real value, so a form can show it as the input's placeholder
|
|
1863
|
+
* instead of inventing one. Unlike {@link sampled} it counts numbers and
|
|
1864
|
+
* quoted text too (quotes stripped), and it survives the cap, so a key whose
|
|
1865
|
+
* value differs in every definition still has an example.
|
|
1866
|
+
*
|
|
1867
|
+
* A key whose value is a BLOCK gets the most written body instead, collapsed
|
|
1868
|
+
* onto one line and capped at {@link DEFINITION_FORM_MAX_EXAMPLE}
|
|
1869
|
+
* characters, so a script field has a placeholder too.
|
|
1870
|
+
*
|
|
1871
|
+
* A key whose value set is already stated (`bool`, `enum:`) carries an
|
|
1872
|
+
* example as well, though no {@link sampled}: a dropdown showing the value
|
|
1873
|
+
* the game itself writes says more than one reading "not set".
|
|
1874
|
+
*/
|
|
1875
|
+
example?: string;
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
export interface DefinitionForm {
|
|
1879
|
+
kind: string;
|
|
1880
|
+
/** Schema path the definition is written into, e.g. `common/traits`. */
|
|
1881
|
+
folder: string;
|
|
1882
|
+
/**
|
|
1883
|
+
* Every loc key the game reads for this kind, `$` being the definition name
|
|
1884
|
+
* (`trait_$_desc`). The full set a form should offer, not the conservative
|
|
1885
|
+
* `requiredLoc` subset a diagnostic is allowed to demand.
|
|
1886
|
+
*/
|
|
1887
|
+
locPatterns: string[];
|
|
1888
|
+
/** Where the game looks for this kind's icon, e.g. `gfx/interface/icons/traits`. */
|
|
1889
|
+
iconFolder?: string;
|
|
1890
|
+
/** Top-level keys, harvest order (most used first), curated keys ahead. */
|
|
1891
|
+
keys: DefinitionFormKey[];
|
|
1892
|
+
/** Named sub-blocks with their own keys, when the harvest has them. */
|
|
1893
|
+
blocks?: Record<string, DefinitionFormKey[]>;
|
|
1894
|
+
/** Ref kind -> every indexed definition of it, mod entries first, capped. */
|
|
1895
|
+
options: Record<string, EventVocabularyItem[]>;
|
|
1896
|
+
/**
|
|
1897
|
+
* Trigger name -> the values that trigger accepts, for the handful of
|
|
1898
|
+
* triggers a no-code condition builder offers rows for (`has_dlc_feature`,
|
|
1899
|
+
* `has_game_rule`, `scripted_trigger`). Which triggers those are, and where
|
|
1900
|
+
* each list comes from, is the game profile's own table; the values
|
|
1901
|
+
* themselves are read from what the server already holds (the trigger's own
|
|
1902
|
+
* script_docs entry, the definition index), never written for the creator.
|
|
1903
|
+
* A trigger with no resolvable list is ABSENT rather than empty, so a client
|
|
1904
|
+
* offers a free input instead of a picker with nothing in it.
|
|
1905
|
+
*/
|
|
1906
|
+
conditions?: Record<string, EventVocabularyItem[]>;
|
|
1907
|
+
/** The modifier vocabulary, most used first: what a modifier row may offer. */
|
|
1908
|
+
modifiers: { name: string; doc?: string }[];
|
|
1909
|
+
/** Definitions of this kind the mod already has (modRoot or every workspace mod). */
|
|
1910
|
+
existing: OverviewDef[];
|
|
1911
|
+
/** The definition `params.name` asked for, when it is indexed. */
|
|
1912
|
+
current?: {
|
|
1913
|
+
file: string;
|
|
1914
|
+
/** 0-based. */
|
|
1915
|
+
line: number;
|
|
1916
|
+
source: DefSource;
|
|
1917
|
+
/** The block verbatim, `name = { ... }`, exactly as the file has it. */
|
|
1918
|
+
text: string;
|
|
1919
|
+
};
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
/**
|
|
1923
|
+
* Request: text edits that write a definition into a script file;
|
|
1924
|
+
* {@link DefinitionEditParams} -> {@link DefinitionEditResult}. The script
|
|
1925
|
+
* sibling of {@link guiSourceEditRequest}, over the same span model, and with
|
|
1926
|
+
* the same division of labour: the server never writes, it returns offsets
|
|
1927
|
+
* into the text it was handed and the host applies them as ONE
|
|
1928
|
+
* `WorkspaceEdit`, which keeps undo and dirty state in the editor.
|
|
1929
|
+
*
|
|
1930
|
+
* Offsets are UTF-16 into `params.text` (the document text, with no BOM, the
|
|
1931
|
+
* way an editor delivers it), computed against that one text and applied
|
|
1932
|
+
* end-first. Every edit is surgical, so a file's other definitions, its
|
|
1933
|
+
* comments, its CRLF and its indentation stay byte-identical.
|
|
1934
|
+
*/
|
|
1935
|
+
export const definitionEditRequest = "paradox/definitionEdit";
|
|
1936
|
+
export interface DefinitionEditParams {
|
|
1937
|
+
/** For display only; the text is authoritative. */
|
|
1938
|
+
uri: string;
|
|
1939
|
+
/** Authoritative document text every offset refers to. */
|
|
1940
|
+
text: string;
|
|
1941
|
+
/** Computed in order against the one text and answered as one edit set. */
|
|
1942
|
+
ops: DefinitionOp[];
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
export type DefinitionOp =
|
|
1946
|
+
/**
|
|
1947
|
+
* Set or (with a null value) remove keys on the top-level definition `name`.
|
|
1948
|
+
* `value` is raw script text: `2`, `{ craven }`, `"quoted"`.
|
|
1949
|
+
*/
|
|
1950
|
+
| { op: "setProperties"; name: string; properties: { key: string; value: string | null }[] }
|
|
1951
|
+
/**
|
|
1952
|
+
* Write the whole `name = { ... }` block: replaces the top-level block of
|
|
1953
|
+
* that name, or appends it after a blank separator line when the file has
|
|
1954
|
+
* none.
|
|
1955
|
+
*/
|
|
1956
|
+
| { op: "upsertBlock"; name: string; text: string };
|
|
1957
|
+
|
|
1958
|
+
export interface DefinitionEditResult {
|
|
1959
|
+
/** Every applied op's edits together. Apply the whole set as ONE change. */
|
|
1960
|
+
edits: GuiTextEdit[];
|
|
1961
|
+
/** One verdict per requested op, in request order; `refused` names why it wrote nothing. */
|
|
1962
|
+
ops: { refused?: string }[];
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
/**
|
|
1966
|
+
* Request: how the GAME prints each modifier; {@link ModifierFormatsParams} ->
|
|
1967
|
+
* {@link ModifierFormatsResult} | null (null = the active profile names no
|
|
1968
|
+
* formats source, or the game folder is not configured).
|
|
1969
|
+
*
|
|
1970
|
+
* A creator that lets a modder add `monthly_income = 0.5` has to show what the
|
|
1971
|
+
* player will see, and the player sees "[gold_i] +0.50 Monthly Income" in
|
|
1972
|
+
* green. None of that is written here: the flags come from the game's own
|
|
1973
|
+
* `common/modifier_definition_formats/` (documented by `_definitions.info`
|
|
1974
|
+
* there), every word comes from the loc index, and every icon comes from the
|
|
1975
|
+
* `texticon` blocks of the game's `gui/texticons.gui`. A modifier no format
|
|
1976
|
+
* block names gets the file's documented defaults, so the answer covers every
|
|
1977
|
+
* modifier token the server knows rather than only the formatted ones.
|
|
1978
|
+
*/
|
|
1979
|
+
export const modifierFormatsRequest = "paradox/modifierFormats";
|
|
1980
|
+
export interface ModifierFormatsParams extends ModScopedParams {
|
|
1981
|
+
/**
|
|
1982
|
+
* Loc keys to render as parts too, through the same texticon chain the
|
|
1983
|
+
* prefixes take. A client that prints a line of the game's own UI (a cost
|
|
1984
|
+
* line such as `"[prestige_i] $VALUE|0$"`) asks for the key and gets its
|
|
1985
|
+
* icon and text back; a key the loc index cannot resolve is absent.
|
|
1986
|
+
*/
|
|
1987
|
+
lines?: string[];
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
/**
|
|
1991
|
+
* One piece of a prefix or suffix: a word, or a texticon. `[gold_i]` in a loc
|
|
1992
|
+
* value resolves through `game_concept_gold_i` = `"@gold_icon!"` to the
|
|
1993
|
+
* `texticon` block naming the sprite, which is what an icon part carries.
|
|
1994
|
+
*/
|
|
1995
|
+
export type FormatPart =
|
|
1996
|
+
{ text: string } | { icon: { texture: string; uv?: [number, number, number, number] } };
|
|
1997
|
+
|
|
1998
|
+
/** How one modifier is printed, straight out of the game's own format files. */
|
|
1999
|
+
export interface ModifierFormat {
|
|
2000
|
+
/** The player's word for the modifier, loc-resolved; the key title-cased when it has none. */
|
|
2001
|
+
label: string;
|
|
2002
|
+
/** Digits after the point. The file's documented default is 2. */
|
|
2003
|
+
decimals: number;
|
|
2004
|
+
/** Scale the value by 100 and print a `%`. */
|
|
2005
|
+
percent?: boolean;
|
|
2006
|
+
/** Print a `%` without scaling: the value already is one. */
|
|
2007
|
+
alreadyPercent?: boolean;
|
|
2008
|
+
/** Which direction is good for the player. The file's documented default is `bad`. */
|
|
2009
|
+
color: "good" | "neutral" | "bad";
|
|
2010
|
+
/** `no_difference_sign`: print the number without a leading `+`/`-`. */
|
|
2011
|
+
noSign?: boolean;
|
|
2012
|
+
/** The game does not show this modifier at all. */
|
|
2013
|
+
hidden?: boolean;
|
|
2014
|
+
/** Drawn before the number (`[gold_i]`). */
|
|
2015
|
+
prefix?: FormatPart[];
|
|
2016
|
+
/** Drawn after the number (`/month`). */
|
|
2017
|
+
suffix?: FormatPart[];
|
|
2018
|
+
/** Used in place of `suffix` for negative values, when the game defines one. */
|
|
2019
|
+
negativeSuffix?: FormatPart[];
|
|
2020
|
+
}
|
|
2021
|
+
|
|
2022
|
+
export interface ModifierFormatsResult {
|
|
2023
|
+
/** Modifier name -> its format. Every modifier token the server knows. */
|
|
2024
|
+
formats: Record<string, ModifierFormat>;
|
|
2025
|
+
/** Loc key -> its parts, for each `lines` entry the loc index resolved. */
|
|
2026
|
+
lines?: Record<string, FormatPart[]>;
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
/**
|
|
2030
|
+
* Request: a dynasty as a family tree; {@link DynastyTreeParams} ->
|
|
2031
|
+
* {@link DynastyTreeResult}.
|
|
2032
|
+
*
|
|
2033
|
+
* Two answers behind one method. Without `dynasty` the result is the picker
|
|
2034
|
+
* list: every dynasty the index knows, mod entries first. With `dynasty` it is
|
|
2035
|
+
* that dynasty's houses and members, read out of the game's own
|
|
2036
|
+
* `history/characters` files.
|
|
2037
|
+
*
|
|
2038
|
+
* Everything is DERIVED: the folders come from the active profile's schema
|
|
2039
|
+
* (`dynasty`, `dynasty_house`, `character` kinds), the members from the
|
|
2040
|
+
* character blocks themselves, the display names from the loc index. A profile
|
|
2041
|
+
* whose schema has no `dynasty` kind answers `supported: false` and empty
|
|
2042
|
+
* lists, which is what a client shows instead of an empty tree.
|
|
2043
|
+
*/
|
|
2044
|
+
export const dynastyTreeRequest = "paradox/dynastyTree";
|
|
2045
|
+
export interface DynastyTreeParams extends ModScopedParams {
|
|
2046
|
+
/** A dynasty id: answer that dynasty's houses and members instead of the list. */
|
|
2047
|
+
dynasty?: string;
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
/** One dynasty, as the picker lists it. */
|
|
2051
|
+
export interface DynastySummary {
|
|
2052
|
+
/** The block's own key, which is what a character's `dynasty = ` names. */
|
|
2053
|
+
id: string;
|
|
2054
|
+
/** The `name = ` value, a loc key (`dynn_Karling`). */
|
|
2055
|
+
nameKey: string;
|
|
2056
|
+
/** The loc text when the server can resolve it, else `nameKey` itself. */
|
|
2057
|
+
name: string;
|
|
2058
|
+
culture?: string;
|
|
2059
|
+
source: DefSource;
|
|
2060
|
+
file: string;
|
|
2061
|
+
/** 0-based. */
|
|
2062
|
+
line: number;
|
|
2063
|
+
/** Characters whose `dynasty`, or whose house's dynasty, is this one. */
|
|
2064
|
+
characterCount: number;
|
|
2065
|
+
houseCount: number;
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
/** One house of a dynasty (`house_karling = { name = … dynasty = 25061 }`). */
|
|
2069
|
+
export interface DynastyHouse {
|
|
2070
|
+
id: string;
|
|
2071
|
+
nameKey: string;
|
|
2072
|
+
name: string;
|
|
2073
|
+
/** The dynasty id the house belongs to. */
|
|
2074
|
+
dynasty: string;
|
|
2075
|
+
source: DefSource;
|
|
2076
|
+
file: string;
|
|
2077
|
+
/** 0-based. */
|
|
2078
|
+
line: number;
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
/**
|
|
2082
|
+
* The character-level skill keys, in the order a client shows them. MEASURED
|
|
2083
|
+
* over the vanilla `history/characters` corpus (2026-09-03): stewardship 8 964,
|
|
2084
|
+
* martial 8 940, diplomacy 8 908, intrigue 8 892, learning 495, prowess 150.
|
|
2085
|
+
*/
|
|
2086
|
+
export const DYNASTY_SKILLS = [
|
|
2087
|
+
"diplomacy",
|
|
2088
|
+
"martial",
|
|
2089
|
+
"stewardship",
|
|
2090
|
+
"intrigue",
|
|
2091
|
+
"learning",
|
|
2092
|
+
"prowess",
|
|
2093
|
+
] as const;
|
|
2094
|
+
|
|
2095
|
+
/**
|
|
2096
|
+
* One character of `history/characters`. Dates are the game's own
|
|
2097
|
+
* `Y.M.D` strings, taken from the dated block that carries the `birth`/`death`
|
|
2098
|
+
* statement.
|
|
2099
|
+
*/
|
|
2100
|
+
export interface DynastyCharacter {
|
|
2101
|
+
/** The block's own key: numeric in vanilla, but `han_1234` shapes exist too. */
|
|
2102
|
+
id: string;
|
|
2103
|
+
/** The `name = ` value, a plain string in history, not a loc key. */
|
|
2104
|
+
name: string;
|
|
2105
|
+
female: boolean;
|
|
2106
|
+
dynasty?: string;
|
|
2107
|
+
/** `dynasty_house = `; a character carries the house OR the dynasty, not both. */
|
|
2108
|
+
house?: string;
|
|
2109
|
+
father?: string;
|
|
2110
|
+
mother?: string;
|
|
2111
|
+
culture?: string;
|
|
2112
|
+
religion?: string;
|
|
2113
|
+
/** `Y.M.D` of the dated block holding `birth`. */
|
|
2114
|
+
birth?: string;
|
|
2115
|
+
death?: string;
|
|
2116
|
+
/**
|
|
2117
|
+
* `dna = `, the portrait DNA name, without the quotes the file may put
|
|
2118
|
+
* around it (350 of 438 vanilla statements write it bare).
|
|
2119
|
+
*/
|
|
2120
|
+
dna?: string;
|
|
2121
|
+
/**
|
|
2122
|
+
* The skills the block sets, keyed by {@link DYNASTY_SKILLS}. A skill the
|
|
2123
|
+
* block does not name is absent, which is not the same as zero: the game
|
|
2124
|
+
* rolls one it was not given.
|
|
2125
|
+
*/
|
|
2126
|
+
skills?: Record<string, number>;
|
|
2127
|
+
traits: string[];
|
|
2128
|
+
/** Ids this character is married to (`add_spouse`), in file order. */
|
|
2129
|
+
spouses: string[];
|
|
2130
|
+
/**
|
|
2131
|
+
* Set when the character belongs to ANOTHER dynasty and is only in the
|
|
2132
|
+
* answer because a member names them as a parent or a spouse. A client draws
|
|
2133
|
+
* them, but the tree is not theirs.
|
|
2134
|
+
*/
|
|
2135
|
+
external?: true;
|
|
2136
|
+
source: DefSource;
|
|
2137
|
+
file: string;
|
|
2138
|
+
/** 0-based. */
|
|
2139
|
+
line: number;
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
export interface DynastyTreeResult {
|
|
2143
|
+
/** False when the active profile's schema has no `dynasty` kind. */
|
|
2144
|
+
supported: boolean;
|
|
2145
|
+
/** The picker list. Empty when `params.dynasty` asked for one dynasty. */
|
|
2146
|
+
dynasties: DynastySummary[];
|
|
2147
|
+
/** Present exactly when `params.dynasty` named a dynasty the index knows. */
|
|
2148
|
+
dynasty?: DynastySummary;
|
|
2149
|
+
houses?: DynastyHouse[];
|
|
2150
|
+
/** Members plus the external parents and spouses they name. */
|
|
2151
|
+
characters?: DynastyCharacter[];
|
|
2152
|
+
/** Largest numeric character id across game and mods, plus one. */
|
|
2153
|
+
nextCharacterId?: string;
|
|
2154
|
+
/** Largest numeric dynasty id across game and mods, plus one. */
|
|
2155
|
+
nextDynastyId?: string;
|
|
2156
|
+
}
|