@uemcp/server 1.9.0 → 1.10.0
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/dist/index.mjs +2022 -241
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -372,7 +372,13 @@ const TOOL_METADATA = {
|
|
|
372
372
|
add_sequence_binding: mutates("sequence", "add_sequence_binding"),
|
|
373
373
|
add_sequence_keys: mutates("sequence", "add_sequence_keys"),
|
|
374
374
|
add_sequence_track: mutates("sequence", "add_sequence_track"),
|
|
375
|
+
add_state_tree_component: mutates("ai", "add_state_tree_component"),
|
|
375
376
|
add_state_tree_state: mutates("ai", "add_state_tree_state"),
|
|
377
|
+
add_stimuli_source: mutates("ai", "add_stimuli_source", [
|
|
378
|
+
"noise",
|
|
379
|
+
"sound",
|
|
380
|
+
"source"
|
|
381
|
+
]),
|
|
376
382
|
add_widget: mutates("ui", "add_widget"),
|
|
377
383
|
analyze_trace: readOnly("core", void 0, [
|
|
378
384
|
"profile",
|
|
@@ -416,6 +422,11 @@ const TOOL_METADATA = {
|
|
|
416
422
|
"screenshot"
|
|
417
423
|
]),
|
|
418
424
|
compile_blueprint: idempotentMutates("blueprint", "compile_blueprint"),
|
|
425
|
+
configure_ai_perception: mutates("ai", "configure_ai_perception", [
|
|
426
|
+
"sight",
|
|
427
|
+
"hearing",
|
|
428
|
+
"senses"
|
|
429
|
+
]),
|
|
419
430
|
connect_pins: mutates("blueprint", "connect_pins"),
|
|
420
431
|
control_blueprint_debugger: mutates("blueprint", "control_blueprint_debugger", [
|
|
421
432
|
"step",
|
|
@@ -424,6 +435,17 @@ const TOOL_METADATA = {
|
|
|
424
435
|
]),
|
|
425
436
|
convert_to_nanite: idempotentMutates("asset", "convert_to_nanite"),
|
|
426
437
|
cook_content: mutates("build", void 0, ["cook", "platform"]),
|
|
438
|
+
create_ai_controller: mutates("ai", "create_ai_controller", [
|
|
439
|
+
"ai controller",
|
|
440
|
+
"brain",
|
|
441
|
+
"possess"
|
|
442
|
+
]),
|
|
443
|
+
create_ai_node_class: mutates("build", void 0, [
|
|
444
|
+
"state tree",
|
|
445
|
+
"behavior tree",
|
|
446
|
+
"eqs",
|
|
447
|
+
"scaffold"
|
|
448
|
+
]),
|
|
427
449
|
create_anim_blueprint: mutates("anim", "create_anim_blueprint"),
|
|
428
450
|
create_asset: mutates("asset", "create_asset"),
|
|
429
451
|
create_attribute_set: mutates("gas", "create_attribute_set"),
|
|
@@ -462,6 +484,12 @@ const TOOL_METADATA = {
|
|
|
462
484
|
create_sound_cue: mutates("audio", "create_sound_cue"),
|
|
463
485
|
create_state_tree: mutates("ai", "create_state_tree"),
|
|
464
486
|
create_struct: mutates("blueprint", "create_struct"),
|
|
487
|
+
create_team_agent_class: mutates("build", void 0, [
|
|
488
|
+
"team",
|
|
489
|
+
"attitude",
|
|
490
|
+
"affiliation",
|
|
491
|
+
"scaffold"
|
|
492
|
+
]),
|
|
465
493
|
create_widget_blueprint: mutates("ui", "create_widget_blueprint"),
|
|
466
494
|
delete_asset: destroys("asset", "delete_asset"),
|
|
467
495
|
delete_data_table: destroys("asset", "delete_data_table"),
|
|
@@ -476,6 +504,11 @@ const TOOL_METADATA = {
|
|
|
476
504
|
]),
|
|
477
505
|
duplicate_actor: mutates("level", "duplicate_actor"),
|
|
478
506
|
duplicate_asset: mutates("asset", "duplicate_asset"),
|
|
507
|
+
edit_eqs_query: mutates("ai", "edit_eqs_query", [
|
|
508
|
+
"test",
|
|
509
|
+
"generator",
|
|
510
|
+
"score"
|
|
511
|
+
]),
|
|
479
512
|
enable_toolset: idempotentMutates("core", void 0, [
|
|
480
513
|
"toolset",
|
|
481
514
|
"tools",
|
|
@@ -518,6 +551,7 @@ const TOOL_METADATA = {
|
|
|
518
551
|
get_asset_dependencies: readOnly("asset", "get_asset_dependencies"),
|
|
519
552
|
get_asset_metadata: readOnly("core", "get_asset_metadata"),
|
|
520
553
|
get_asset_property: readOnly("asset", "get_asset_property"),
|
|
554
|
+
get_behavior_tree: readOnly("ai", "get_behavior_tree"),
|
|
521
555
|
get_blueprint_compile_errors: readOnly("blueprint", "get_blueprint_compile_errors", [
|
|
522
556
|
"error",
|
|
523
557
|
"broken",
|
|
@@ -532,6 +566,11 @@ const TOOL_METADATA = {
|
|
|
532
566
|
get_blueprint_graph: readOnly("blueprint", "get_blueprint_graph"),
|
|
533
567
|
get_blueprint_summary: readOnly("blueprint", "get_blueprint_summary"),
|
|
534
568
|
get_build_job_status: readOnly("level", "get_build_job_status"),
|
|
569
|
+
get_bt_runtime_state: mutates("ai", "get_bt_runtime_state", [
|
|
570
|
+
"pie",
|
|
571
|
+
"runtime",
|
|
572
|
+
"debug"
|
|
573
|
+
]),
|
|
535
574
|
get_cdo_defaults: readOnly("core", "get_cdo_defaults"),
|
|
536
575
|
get_class_reflection: readOnly("core", "get_class_reflection", [
|
|
537
576
|
"uclass",
|
|
@@ -554,6 +593,7 @@ const TOOL_METADATA = {
|
|
|
554
593
|
get_create_class_status: readOnly("build", "get_create_class_status"),
|
|
555
594
|
get_current_level: readOnly("core", "get_current_level"),
|
|
556
595
|
get_editor_state: readOnly("core", "get_editor_state"),
|
|
596
|
+
get_eqs_query: readOnly("ai", "get_eqs_query"),
|
|
557
597
|
get_import_job_status: readOnly("asset", "get_import_job_status"),
|
|
558
598
|
get_net_stats: readOnly("test", "get_net_stats", [
|
|
559
599
|
"network",
|
|
@@ -568,6 +608,7 @@ const TOOL_METADATA = {
|
|
|
568
608
|
get_render_job_status: readOnly("sequence", "get_render_job_status"),
|
|
569
609
|
get_source_control_job_status: readOnly("asset", "get_source_control_job_status"),
|
|
570
610
|
get_source_control_status: readOnly("asset", "get_source_control_status"),
|
|
611
|
+
get_state_tree: readOnly("ai", "get_state_tree"),
|
|
571
612
|
get_stat_snapshot: readOnly("core", "stat_snapshot", [
|
|
572
613
|
"fps",
|
|
573
614
|
"performance",
|
|
@@ -588,6 +629,7 @@ const TOOL_METADATA = {
|
|
|
588
629
|
"enhanced input"
|
|
589
630
|
]),
|
|
590
631
|
launch_on_device: reachesOutside("test", false, "launch_on_device"),
|
|
632
|
+
link_state_tree_state: mutates("ai", "link_state_tree_state", ["subtree", "linked"]),
|
|
591
633
|
list_actors: readOnly("core", "list_actors"),
|
|
592
634
|
list_asset_factories: readOnly("asset", "list_asset_factories"),
|
|
593
635
|
list_automation_tests: readOnly("test", "list_automation_tests"),
|
|
@@ -645,6 +687,11 @@ const TOOL_METADATA = {
|
|
|
645
687
|
"unreal"
|
|
646
688
|
]),
|
|
647
689
|
run_editor_commandlet: mutates("build"),
|
|
690
|
+
run_eqs_query: readOnly("ai", "run_eqs_query", [
|
|
691
|
+
"query",
|
|
692
|
+
"score",
|
|
693
|
+
"items"
|
|
694
|
+
]),
|
|
648
695
|
run_geometry_script: mutates("level", "run_geometry_script"),
|
|
649
696
|
run_pcg_generate: mutates("fx", "run_pcg_generate"),
|
|
650
697
|
save_asset: idempotentMutates("asset", "save_asset"),
|
|
@@ -678,6 +725,8 @@ const TOOL_METADATA = {
|
|
|
678
725
|
set_pin_default: idempotentMutates("blueprint", "set_pin_default"),
|
|
679
726
|
set_post_process_settings: idempotentMutates("fx", "set_post_process_settings"),
|
|
680
727
|
set_project_settings: idempotentMutates("core", "set_project_settings"),
|
|
728
|
+
set_state_tree_considerations: mutates("ai", "set_state_tree_considerations", ["utility", "score"]),
|
|
729
|
+
set_state_tree_globals: mutates("ai", "set_state_tree_globals", ["evaluator", "global task"]),
|
|
681
730
|
set_view_mode: idempotentMutates("level", "set_view_mode"),
|
|
682
731
|
set_viewport_camera: idempotentMutates("level", "set_viewport_camera"),
|
|
683
732
|
set_widget_slot: idempotentMutates("ui", "set_widget_slot"),
|
|
@@ -703,6 +752,11 @@ const TOOL_METADATA = {
|
|
|
703
752
|
"tail"
|
|
704
753
|
]),
|
|
705
754
|
toggle_show_flags: idempotentMutates("level", "toggle_show_flags"),
|
|
755
|
+
trace_state_tree: mutates("ai", "trace_state_tree", [
|
|
756
|
+
"pie",
|
|
757
|
+
"runtime",
|
|
758
|
+
"brain"
|
|
759
|
+
]),
|
|
706
760
|
trigger_hot_reload: mutates("build", "start_hot_reload"),
|
|
707
761
|
trigger_live_compile: mutates("build", "start_live_compile", ["live coding", "recompile"]),
|
|
708
762
|
undo: mutates("core", "undo"),
|
|
@@ -1443,6 +1497,15 @@ const createdUserAssetResponseFields = {
|
|
|
1443
1497
|
version: z.literal(2)
|
|
1444
1498
|
};
|
|
1445
1499
|
const instancedObjectParamsSchema = z.record(z.string().trim().min(1).max(128), z.string().max(BRIDGE_FACTORY_OPTION_VALUE_MAX_CHARS)).refine((value) => Object.keys(value).length <= 32, { message: `An instanced object carries at most ${String(32)} params.` }).default({});
|
|
1500
|
+
const BRIDGE_AI_REPORT_STATES = ["reported", "unsupported"];
|
|
1501
|
+
const BRIDGE_AI_RUNTIME_STATES = [
|
|
1502
|
+
"reported",
|
|
1503
|
+
"not_running",
|
|
1504
|
+
"unsupported"
|
|
1505
|
+
];
|
|
1506
|
+
const aiReportStateSchema = z.enum(BRIDGE_AI_REPORT_STATES);
|
|
1507
|
+
const aiRuntimeStateSchema = z.enum(BRIDGE_AI_RUNTIME_STATES);
|
|
1508
|
+
const aiParamsSchema = z.record(z.string(), z.string());
|
|
1446
1509
|
//#endregion
|
|
1447
1510
|
//#region src/protocol/logs.ts
|
|
1448
1511
|
const BRIDGE_SUBSCRIBE_LOGS_REQUEST_TYPE = "subscribe_logs";
|
|
@@ -7082,7 +7145,7 @@ const BRIDGE_STATE_TREE_TRANSITION_TRIGGERS = [
|
|
|
7082
7145
|
];
|
|
7083
7146
|
const blackboardKeyTypeSchema = z.enum(BRIDGE_BLACKBOARD_KEY_TYPES);
|
|
7084
7147
|
const blackboardKeyModeSchema = z.enum(BRIDGE_BLACKBOARD_KEY_MODES);
|
|
7085
|
-
const eqsTestPurposeSchema = z.enum(BRIDGE_EQS_TEST_PURPOSES);
|
|
7148
|
+
const eqsTestPurposeSchema$1 = z.enum(BRIDGE_EQS_TEST_PURPOSES);
|
|
7086
7149
|
const stateTreeSchemaSchema = z.enum(BRIDGE_STATE_TREE_SCHEMAS);
|
|
7087
7150
|
const stateTreeStateTypeSchema = z.enum(BRIDGE_STATE_TREE_STATE_TYPES);
|
|
7088
7151
|
const stateTreeTransitionTriggerSchema = z.enum(BRIDGE_STATE_TREE_TRANSITION_TRIGGERS);
|
|
@@ -7128,7 +7191,7 @@ const bridgeEqsGeneratorSchema = z.object({
|
|
|
7128
7191
|
});
|
|
7129
7192
|
const bridgeEqsTestSchema = z.object({
|
|
7130
7193
|
params: eqsParamsSchema.default({}),
|
|
7131
|
-
purpose: eqsTestPurposeSchema.default("filter_and_score"),
|
|
7194
|
+
purpose: eqsTestPurposeSchema$1.default("filter_and_score"),
|
|
7132
7195
|
testClass: assetPathSchema
|
|
7133
7196
|
});
|
|
7134
7197
|
const bridgeCreateEqsQueryRequestSchema = z.object({
|
|
@@ -7276,230 +7339,846 @@ function createBridgeAddStateTreeStateRequest(assetPath, states, options = {}, r
|
|
|
7276
7339
|
});
|
|
7277
7340
|
}
|
|
7278
7341
|
//#endregion
|
|
7279
|
-
//#region src/protocol/
|
|
7280
|
-
const
|
|
7281
|
-
const
|
|
7282
|
-
const
|
|
7283
|
-
const
|
|
7284
|
-
const
|
|
7285
|
-
const
|
|
7286
|
-
|
|
7287
|
-
"
|
|
7288
|
-
"
|
|
7289
|
-
"
|
|
7290
|
-
"
|
|
7291
|
-
"
|
|
7342
|
+
//#region src/protocol/stateTree.ts
|
|
7343
|
+
const BRIDGE_GET_STATE_TREE_REQUEST_TYPE = "get_state_tree";
|
|
7344
|
+
const BRIDGE_SET_STATE_TREE_GLOBALS_REQUEST_TYPE = "set_state_tree_globals";
|
|
7345
|
+
const BRIDGE_SET_STATE_TREE_CONSIDERATIONS_REQUEST_TYPE = "set_state_tree_considerations";
|
|
7346
|
+
const BRIDGE_LINK_STATE_TREE_STATE_REQUEST_TYPE = "link_state_tree_state";
|
|
7347
|
+
const BRIDGE_ADD_STATE_TREE_COMPONENT_REQUEST_TYPE = "add_state_tree_component";
|
|
7348
|
+
const BRIDGE_TRACE_STATE_TREE_REQUEST_TYPE = "trace_state_tree";
|
|
7349
|
+
const BRIDGE_STATE_TREE_SELECTION_BEHAVIORS = [
|
|
7350
|
+
"none",
|
|
7351
|
+
"try_enter_state",
|
|
7352
|
+
"try_select_children_in_order",
|
|
7353
|
+
"try_select_children_at_random",
|
|
7354
|
+
"try_select_children_with_highest_utility",
|
|
7355
|
+
"try_select_children_at_random_weighted_by_utility",
|
|
7356
|
+
"try_follow_transitions"
|
|
7292
7357
|
];
|
|
7293
|
-
const
|
|
7294
|
-
const
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
"
|
|
7299
|
-
"
|
|
7358
|
+
const BRIDGE_STATE_TREE_GLOBAL_KINDS = ["evaluator", "global_task"];
|
|
7359
|
+
const BRIDGE_STATE_TREE_GLOBAL_MODES = ["merge", "replace"];
|
|
7360
|
+
const BRIDGE_STATE_TREE_LINK_TYPES = ["linked_state", "linked_asset"];
|
|
7361
|
+
const BRIDGE_STATE_TREE_COMPONENT_KINDS = ["state_tree", "state_tree_ai"];
|
|
7362
|
+
const BRIDGE_STATE_TREE_TRACE_ACTIONS = [
|
|
7363
|
+
"start",
|
|
7364
|
+
"stop",
|
|
7365
|
+
"poll"
|
|
7300
7366
|
];
|
|
7301
|
-
const
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
const
|
|
7309
|
-
const
|
|
7310
|
-
|
|
7311
|
-
|
|
7367
|
+
const BRIDGE_STATE_TREE_TRACE_KINDS = [
|
|
7368
|
+
"state_entered",
|
|
7369
|
+
"state_exited",
|
|
7370
|
+
"transition_taken",
|
|
7371
|
+
"task_completed",
|
|
7372
|
+
"condition_evaluated"
|
|
7373
|
+
];
|
|
7374
|
+
const stateTreeSelectionBehaviorSchema = z.enum(BRIDGE_STATE_TREE_SELECTION_BEHAVIORS);
|
|
7375
|
+
const stateTreeGlobalKindSchema = z.enum(BRIDGE_STATE_TREE_GLOBAL_KINDS);
|
|
7376
|
+
const stateTreeGlobalModeSchema = z.enum(BRIDGE_STATE_TREE_GLOBAL_MODES);
|
|
7377
|
+
const stateTreeLinkTypeSchema = z.enum(BRIDGE_STATE_TREE_LINK_TYPES);
|
|
7378
|
+
const stateTreeComponentKindSchema = z.enum(BRIDGE_STATE_TREE_COMPONENT_KINDS);
|
|
7379
|
+
const stateTreeTraceActionSchema = z.enum(BRIDGE_STATE_TREE_TRACE_ACTIONS);
|
|
7380
|
+
const stateTreeTraceKindSchema = z.enum(BRIDGE_STATE_TREE_TRACE_KINDS);
|
|
7381
|
+
const bridgeGetStateTreeRequestSchema = z.object({
|
|
7382
|
+
assetPath: assetPathSchema,
|
|
7383
|
+
requestId: requestIdSchema,
|
|
7384
|
+
type: z.literal(BRIDGE_GET_STATE_TREE_REQUEST_TYPE),
|
|
7385
|
+
version: z.literal(2)
|
|
7312
7386
|
});
|
|
7313
|
-
const
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7387
|
+
const bridgeStateTreeNodeReportSchema = z.object({
|
|
7388
|
+
id: z.string(),
|
|
7389
|
+
nodeClass: z.string(),
|
|
7390
|
+
params: aiParamsSchema
|
|
7391
|
+
});
|
|
7392
|
+
const bridgeStateTreeTransitionReportSchema = z.object({
|
|
7393
|
+
eventTag: z.string().optional(),
|
|
7394
|
+
id: z.string(),
|
|
7395
|
+
targetStateName: z.string().optional(),
|
|
7396
|
+
targetType: z.string(),
|
|
7397
|
+
trigger: z.string()
|
|
7398
|
+
});
|
|
7399
|
+
const bridgeStateTreeParameterReportSchema = z.object({
|
|
7400
|
+
name: z.string(),
|
|
7401
|
+
type: z.string(),
|
|
7402
|
+
value: z.string()
|
|
7403
|
+
});
|
|
7404
|
+
const bridgeStateTreeStateReportSchema = z.object({
|
|
7405
|
+
considerations: z.array(bridgeStateTreeNodeReportSchema).max(8),
|
|
7406
|
+
utilityWeight: z.number(),
|
|
7407
|
+
enterConditions: z.array(bridgeStateTreeNodeReportSchema).max(8),
|
|
7408
|
+
id: z.string(),
|
|
7409
|
+
linkedAssetPath: z.string().optional(),
|
|
7410
|
+
linkedStateName: z.string().optional(),
|
|
7411
|
+
name: z.string(),
|
|
7412
|
+
parameters: z.array(bridgeStateTreeParameterReportSchema).max(16),
|
|
7413
|
+
parametersId: z.string().optional(),
|
|
7414
|
+
parentId: z.string().optional(),
|
|
7415
|
+
selectionBehavior: z.string(),
|
|
7416
|
+
stateType: z.string(),
|
|
7417
|
+
tasks: z.array(bridgeStateTreeNodeReportSchema).max(8),
|
|
7418
|
+
transitions: z.array(bridgeStateTreeTransitionReportSchema).max(8)
|
|
7419
|
+
});
|
|
7420
|
+
const bridgeStateTreeBindingReportSchema = z.object({
|
|
7421
|
+
sourcePath: z.string(),
|
|
7422
|
+
sourceStructId: z.string(),
|
|
7423
|
+
targetPath: z.string(),
|
|
7424
|
+
targetStructId: z.string()
|
|
7425
|
+
});
|
|
7426
|
+
const bridgeGetStateTreeSuccessResponseSchema = z.object({
|
|
7427
|
+
assetPath: z.string(),
|
|
7428
|
+
bindings: z.array(bridgeStateTreeBindingReportSchema).max(128),
|
|
7429
|
+
compiled: z.boolean(),
|
|
7430
|
+
evaluators: z.array(bridgeStateTreeNodeReportSchema).max(16),
|
|
7431
|
+
globalTasks: z.array(bridgeStateTreeNodeReportSchema).max(16),
|
|
7432
|
+
message: nonEmptyStringSchema.optional(),
|
|
7433
|
+
ok: z.literal(true),
|
|
7434
|
+
parameters: z.array(bridgeStateTreeParameterReportSchema).max(16),
|
|
7435
|
+
parametersId: z.string().optional(),
|
|
7318
7436
|
requestId: requestIdSchema,
|
|
7319
|
-
|
|
7320
|
-
|
|
7437
|
+
schemaClass: z.string(),
|
|
7438
|
+
state: aiReportStateSchema,
|
|
7439
|
+
stateCount: z.number().int().min(0),
|
|
7440
|
+
states: z.array(bridgeStateTreeStateReportSchema).max(128),
|
|
7441
|
+
truncated: z.boolean(),
|
|
7442
|
+
type: z.literal(BRIDGE_GET_STATE_TREE_REQUEST_TYPE),
|
|
7321
7443
|
version: z.literal(2)
|
|
7322
7444
|
});
|
|
7323
|
-
const
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
objectClassPath: assetPathSchema.optional()
|
|
7328
|
-
}).superRefine((binding, ctx) => {
|
|
7329
|
-
if (binding.bindingKind === "possessable" && binding.actorPath === void 0) {
|
|
7330
|
-
ctx.addIssue({
|
|
7331
|
-
code: z.ZodIssueCode.custom,
|
|
7332
|
-
message: "A possessable binding must name the actorPath it possesses.",
|
|
7333
|
-
path: ["actorPath"]
|
|
7334
|
-
});
|
|
7335
|
-
return;
|
|
7336
|
-
}
|
|
7337
|
-
if (binding.bindingKind === "spawnable" && binding.actorPath === void 0 && binding.objectClassPath === void 0) ctx.addIssue({
|
|
7338
|
-
code: z.ZodIssueCode.custom,
|
|
7339
|
-
message: "A spawnable binding needs a template, so it must carry actorPath or objectClassPath.",
|
|
7340
|
-
path: ["objectClassPath"]
|
|
7341
|
-
});
|
|
7445
|
+
const bridgeStateTreeGlobalNodeSchema = z.object({
|
|
7446
|
+
kind: stateTreeGlobalKindSchema,
|
|
7447
|
+
nodeClass: assetPathSchema,
|
|
7448
|
+
params: eqsParamsSchema.default({})
|
|
7342
7449
|
});
|
|
7343
|
-
const
|
|
7450
|
+
const bridgeSetStateTreeGlobalsRequestSchema = z.object({
|
|
7344
7451
|
assetPath: assetPathSchema,
|
|
7345
|
-
|
|
7452
|
+
compile: z.boolean().default(true),
|
|
7453
|
+
mode: stateTreeGlobalModeSchema.default("merge"),
|
|
7454
|
+
nodes: z.array(bridgeStateTreeGlobalNodeSchema).max(16).default([]),
|
|
7346
7455
|
requestId: requestIdSchema,
|
|
7347
|
-
type: z.literal(
|
|
7456
|
+
type: z.literal(BRIDGE_SET_STATE_TREE_GLOBALS_REQUEST_TYPE),
|
|
7348
7457
|
version: z.literal(2)
|
|
7349
7458
|
});
|
|
7350
|
-
const
|
|
7459
|
+
const bridgeSetStateTreeGlobalsSuccessResponseSchema = z.object({
|
|
7460
|
+
...authoringBatchResponseFields,
|
|
7461
|
+
compileMessages: z.array(z.string()).max(25),
|
|
7462
|
+
compiled: z.boolean(),
|
|
7463
|
+
evaluatorCount: z.number().int().min(0),
|
|
7464
|
+
globalTaskCount: z.number().int().min(0),
|
|
7465
|
+
type: z.literal(BRIDGE_SET_STATE_TREE_GLOBALS_REQUEST_TYPE)
|
|
7466
|
+
});
|
|
7467
|
+
const bridgeStateTreeConsiderationSchema = z.object({
|
|
7468
|
+
nodeClass: assetPathSchema,
|
|
7469
|
+
params: eqsParamsSchema.default({})
|
|
7470
|
+
});
|
|
7471
|
+
const bridgeStateTreeConsiderationTargetSchema = z.object({
|
|
7472
|
+
considerations: z.array(bridgeStateTreeConsiderationSchema).max(8).default([]),
|
|
7473
|
+
selectionBehavior: stateTreeSelectionBehaviorSchema.optional(),
|
|
7474
|
+
stateName: userTypeIdentifierSchema,
|
|
7475
|
+
weight: z.number().min(0).max(1e3).default(1)
|
|
7476
|
+
});
|
|
7477
|
+
const bridgeSetStateTreeConsiderationsRequestSchema = z.object({
|
|
7351
7478
|
assetPath: assetPathSchema,
|
|
7352
|
-
|
|
7353
|
-
propertyPath: propertyPathSchema.optional(),
|
|
7479
|
+
compile: z.boolean().default(true),
|
|
7354
7480
|
requestId: requestIdSchema,
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
trackKind: sequenceTrackKindSchema,
|
|
7358
|
-
type: z.literal(BRIDGE_ADD_SEQUENCE_TRACK_REQUEST_TYPE),
|
|
7481
|
+
states: z.array(bridgeStateTreeConsiderationTargetSchema).min(1).max(32),
|
|
7482
|
+
type: z.literal(BRIDGE_SET_STATE_TREE_CONSIDERATIONS_REQUEST_TYPE),
|
|
7359
7483
|
version: z.literal(2)
|
|
7360
7484
|
});
|
|
7361
|
-
const
|
|
7362
|
-
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
|
|
7485
|
+
const bridgeSetStateTreeConsiderationsSuccessResponseSchema = z.object({
|
|
7486
|
+
...authoringBatchResponseFields,
|
|
7487
|
+
compileMessages: z.array(z.string()).max(25),
|
|
7488
|
+
compiled: z.boolean(),
|
|
7489
|
+
supported: z.boolean(),
|
|
7490
|
+
supportedVersions: z.array(z.string()).max(16),
|
|
7491
|
+
type: z.literal(BRIDGE_SET_STATE_TREE_CONSIDERATIONS_REQUEST_TYPE)
|
|
7492
|
+
});
|
|
7493
|
+
const bridgeStateTreeLinkSchema = z.object({
|
|
7494
|
+
linkType: stateTreeLinkTypeSchema,
|
|
7495
|
+
linkedAssetPath: assetPathSchema.optional(),
|
|
7496
|
+
parameterOverrides: eqsParamsSchema.default({}),
|
|
7497
|
+
stateName: userTypeIdentifierSchema,
|
|
7498
|
+
targetStateName: userTypeIdentifierSchema.optional()
|
|
7499
|
+
}).superRefine((link, ctx) => {
|
|
7500
|
+
if (link.linkType === "linked_asset" && link.linkedAssetPath === void 0) ctx.addIssue({
|
|
7368
7501
|
code: z.ZodIssueCode.custom,
|
|
7369
|
-
message:
|
|
7370
|
-
path: ["
|
|
7502
|
+
message: "A 'linked_asset' link must name its linkedAssetPath.",
|
|
7503
|
+
path: ["linkedAssetPath"]
|
|
7371
7504
|
});
|
|
7372
|
-
if (
|
|
7505
|
+
if (link.linkType === "linked_state" && link.targetStateName === void 0) ctx.addIssue({
|
|
7373
7506
|
code: z.ZodIssueCode.custom,
|
|
7374
|
-
message: "A
|
|
7375
|
-
path: ["
|
|
7507
|
+
message: "A 'linked_state' link must name its targetStateName.",
|
|
7508
|
+
path: ["targetStateName"]
|
|
7376
7509
|
});
|
|
7377
7510
|
});
|
|
7378
|
-
const
|
|
7379
|
-
arriveTangent: z.number().optional(),
|
|
7380
|
-
interpolation: sequenceInterpolationSchema.default("auto"),
|
|
7381
|
-
leaveTangent: z.number().optional(),
|
|
7382
|
-
time: z.number(),
|
|
7383
|
-
value: z.number()
|
|
7384
|
-
});
|
|
7385
|
-
const bridgeAddSequenceKeysRequestSchema = z.object({
|
|
7511
|
+
const bridgeLinkStateTreeStateRequestSchema = z.object({
|
|
7386
7512
|
assetPath: assetPathSchema,
|
|
7387
|
-
|
|
7388
|
-
|
|
7389
|
-
keys: z.array(bridgeSequenceKeySchema).min(1).max(128),
|
|
7513
|
+
compile: z.boolean().default(true),
|
|
7514
|
+
links: z.array(bridgeStateTreeLinkSchema).min(1).max(16),
|
|
7390
7515
|
requestId: requestIdSchema,
|
|
7391
|
-
|
|
7392
|
-
trackName: boundedStringSchema,
|
|
7393
|
-
type: z.literal(BRIDGE_ADD_SEQUENCE_KEYS_REQUEST_TYPE),
|
|
7516
|
+
type: z.literal(BRIDGE_LINK_STATE_TREE_STATE_REQUEST_TYPE),
|
|
7394
7517
|
version: z.literal(2)
|
|
7395
7518
|
});
|
|
7396
|
-
const
|
|
7397
|
-
...createdUserAssetResponseFields,
|
|
7398
|
-
displayRate: bridgeSequenceFrameRateSchema,
|
|
7399
|
-
durationInFrames: z.number().int().min(0),
|
|
7400
|
-
tickResolution: bridgeSequenceFrameRateSchema,
|
|
7401
|
-
type: z.literal(BRIDGE_CREATE_LEVEL_SEQUENCE_REQUEST_TYPE)
|
|
7402
|
-
});
|
|
7403
|
-
const bridgeAddSequenceBindingSuccessResponseSchema = z.object({
|
|
7519
|
+
const bridgeLinkStateTreeStateSuccessResponseSchema = z.object({
|
|
7404
7520
|
...authoringBatchResponseFields,
|
|
7405
|
-
|
|
7521
|
+
compileMessages: z.array(z.string()).max(25),
|
|
7522
|
+
compiled: z.boolean(),
|
|
7523
|
+
type: z.literal(BRIDGE_LINK_STATE_TREE_STATE_REQUEST_TYPE)
|
|
7406
7524
|
});
|
|
7407
|
-
const
|
|
7408
|
-
|
|
7525
|
+
const bridgeAddStateTreeComponentRequestSchema = z.object({
|
|
7526
|
+
blueprintPath: assetPathSchema,
|
|
7527
|
+
componentKind: stateTreeComponentKindSchema.default("state_tree"),
|
|
7528
|
+
componentName: userTypeIdentifierSchema.optional(),
|
|
7529
|
+
requestId: requestIdSchema,
|
|
7530
|
+
startLogicAutomatically: z.boolean().default(true),
|
|
7531
|
+
stateTreePath: assetPathSchema,
|
|
7532
|
+
type: z.literal(BRIDGE_ADD_STATE_TREE_COMPONENT_REQUEST_TYPE),
|
|
7533
|
+
version: z.literal(2)
|
|
7534
|
+
});
|
|
7535
|
+
const bridgeAddStateTreeComponentSuccessResponseSchema = z.object({
|
|
7536
|
+
blueprintPath: z.string(),
|
|
7537
|
+
componentClass: z.string(),
|
|
7538
|
+
componentName: z.string(),
|
|
7409
7539
|
message: nonEmptyStringSchema.optional(),
|
|
7410
7540
|
ok: z.literal(true),
|
|
7411
7541
|
packageDirty: z.boolean(),
|
|
7412
7542
|
requestId: requestIdSchema,
|
|
7413
|
-
|
|
7414
|
-
state:
|
|
7415
|
-
|
|
7416
|
-
trackName: z.string(),
|
|
7417
|
-
type: z.literal(BRIDGE_ADD_SEQUENCE_TRACK_REQUEST_TYPE),
|
|
7543
|
+
schemaClass: z.string(),
|
|
7544
|
+
state: aiReportStateSchema,
|
|
7545
|
+
type: z.literal(BRIDGE_ADD_STATE_TREE_COMPONENT_REQUEST_TYPE),
|
|
7418
7546
|
version: z.literal(2)
|
|
7419
7547
|
});
|
|
7420
|
-
const
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7548
|
+
const bridgeTraceStateTreeRequestSchema = z.object({
|
|
7549
|
+
action: stateTreeTraceActionSchema,
|
|
7550
|
+
actorPath: assetPathSchema.optional(),
|
|
7551
|
+
maxEvents: z.number().int().min(1).max(200).default(50),
|
|
7552
|
+
requestId: requestIdSchema,
|
|
7553
|
+
type: z.literal(BRIDGE_TRACE_STATE_TREE_REQUEST_TYPE),
|
|
7554
|
+
version: z.literal(2)
|
|
7555
|
+
});
|
|
7556
|
+
const bridgeStateTreeTraceEventSchema = z.object({
|
|
7557
|
+
detail: z.string().optional(),
|
|
7558
|
+
kind: stateTreeTraceKindSchema,
|
|
7559
|
+
stateName: z.string().optional(),
|
|
7560
|
+
timestampSeconds: z.number().min(0)
|
|
7561
|
+
});
|
|
7562
|
+
const bridgeTraceStateTreeSuccessResponseSchema = z.object({
|
|
7563
|
+
action: stateTreeTraceActionSchema,
|
|
7564
|
+
droppedCount: z.number().int().min(0),
|
|
7565
|
+
eventCount: z.number().int().min(0),
|
|
7566
|
+
events: z.array(bridgeStateTreeTraceEventSchema).max(200),
|
|
7424
7567
|
message: nonEmptyStringSchema.optional(),
|
|
7425
7568
|
ok: z.literal(true),
|
|
7426
|
-
|
|
7569
|
+
recording: z.boolean(),
|
|
7427
7570
|
requestId: requestIdSchema,
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
type: z.literal(BRIDGE_ADD_SEQUENCE_KEYS_REQUEST_TYPE),
|
|
7571
|
+
state: aiRuntimeStateSchema,
|
|
7572
|
+
type: z.literal(BRIDGE_TRACE_STATE_TREE_REQUEST_TYPE),
|
|
7431
7573
|
version: z.literal(2)
|
|
7432
7574
|
});
|
|
7433
|
-
const
|
|
7434
|
-
const
|
|
7435
|
-
const
|
|
7436
|
-
const
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
packagePath,
|
|
7575
|
+
const bridgeGetStateTreeResponseSchema = z.union([bridgeGetStateTreeSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
7576
|
+
const bridgeSetStateTreeGlobalsResponseSchema = z.union([bridgeSetStateTreeGlobalsSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
7577
|
+
const bridgeSetStateTreeConsiderationsResponseSchema = z.union([bridgeSetStateTreeConsiderationsSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
7578
|
+
const bridgeLinkStateTreeStateResponseSchema = z.union([bridgeLinkStateTreeStateSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
7579
|
+
const bridgeAddStateTreeComponentResponseSchema = z.union([bridgeAddStateTreeComponentSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
7580
|
+
const bridgeTraceStateTreeResponseSchema = z.union([bridgeTraceStateTreeSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
7581
|
+
function createBridgeGetStateTreeRequest(assetPath, requestId = randomUUID()) {
|
|
7582
|
+
return bridgeGetStateTreeRequestSchema.parse({
|
|
7583
|
+
assetPath,
|
|
7443
7584
|
requestId,
|
|
7444
|
-
|
|
7445
|
-
type: BRIDGE_CREATE_LEVEL_SEQUENCE_REQUEST_TYPE,
|
|
7585
|
+
type: BRIDGE_GET_STATE_TREE_REQUEST_TYPE,
|
|
7446
7586
|
version: 2
|
|
7447
7587
|
});
|
|
7448
7588
|
}
|
|
7449
|
-
function
|
|
7450
|
-
return
|
|
7589
|
+
function createBridgeSetStateTreeGlobalsRequest(assetPath, nodes, options = {}, requestId = randomUUID()) {
|
|
7590
|
+
return bridgeSetStateTreeGlobalsRequestSchema.parse({
|
|
7451
7591
|
assetPath,
|
|
7452
|
-
|
|
7592
|
+
compile: options.compile,
|
|
7593
|
+
mode: options.mode,
|
|
7594
|
+
nodes,
|
|
7453
7595
|
requestId,
|
|
7454
|
-
type:
|
|
7596
|
+
type: BRIDGE_SET_STATE_TREE_GLOBALS_REQUEST_TYPE,
|
|
7455
7597
|
version: 2
|
|
7456
7598
|
});
|
|
7457
7599
|
}
|
|
7458
|
-
function
|
|
7459
|
-
return
|
|
7600
|
+
function createBridgeSetStateTreeConsiderationsRequest(assetPath, states, options = {}, requestId = randomUUID()) {
|
|
7601
|
+
return bridgeSetStateTreeConsiderationsRequestSchema.parse({
|
|
7460
7602
|
assetPath,
|
|
7461
|
-
|
|
7462
|
-
propertyPath: options.propertyPath,
|
|
7603
|
+
compile: options.compile,
|
|
7463
7604
|
requestId,
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
trackKind,
|
|
7467
|
-
type: BRIDGE_ADD_SEQUENCE_TRACK_REQUEST_TYPE,
|
|
7605
|
+
states,
|
|
7606
|
+
type: BRIDGE_SET_STATE_TREE_CONSIDERATIONS_REQUEST_TYPE,
|
|
7468
7607
|
version: 2
|
|
7469
7608
|
});
|
|
7470
7609
|
}
|
|
7471
|
-
function
|
|
7472
|
-
return
|
|
7610
|
+
function createBridgeLinkStateTreeStateRequest(assetPath, links, options = {}, requestId = randomUUID()) {
|
|
7611
|
+
return bridgeLinkStateTreeStateRequestSchema.parse({
|
|
7473
7612
|
assetPath,
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
keys,
|
|
7613
|
+
compile: options.compile,
|
|
7614
|
+
links,
|
|
7477
7615
|
requestId,
|
|
7478
|
-
|
|
7479
|
-
|
|
7480
|
-
|
|
7616
|
+
type: BRIDGE_LINK_STATE_TREE_STATE_REQUEST_TYPE,
|
|
7617
|
+
version: 2
|
|
7618
|
+
});
|
|
7619
|
+
}
|
|
7620
|
+
function createBridgeAddStateTreeComponentRequest(blueprintPath, stateTreePath, options = {}, requestId = randomUUID()) {
|
|
7621
|
+
return bridgeAddStateTreeComponentRequestSchema.parse({
|
|
7622
|
+
blueprintPath,
|
|
7623
|
+
componentKind: options.componentKind,
|
|
7624
|
+
componentName: options.componentName,
|
|
7625
|
+
requestId,
|
|
7626
|
+
startLogicAutomatically: options.startLogicAutomatically,
|
|
7627
|
+
stateTreePath,
|
|
7628
|
+
type: BRIDGE_ADD_STATE_TREE_COMPONENT_REQUEST_TYPE,
|
|
7629
|
+
version: 2
|
|
7630
|
+
});
|
|
7631
|
+
}
|
|
7632
|
+
function createBridgeTraceStateTreeRequest(action, options = {}, requestId = randomUUID()) {
|
|
7633
|
+
return bridgeTraceStateTreeRequestSchema.parse({
|
|
7634
|
+
action,
|
|
7635
|
+
actorPath: options.actorPath,
|
|
7636
|
+
maxEvents: options.maxEvents,
|
|
7637
|
+
requestId,
|
|
7638
|
+
type: BRIDGE_TRACE_STATE_TREE_REQUEST_TYPE,
|
|
7481
7639
|
version: 2
|
|
7482
7640
|
});
|
|
7483
7641
|
}
|
|
7484
7642
|
//#endregion
|
|
7485
|
-
//#region src/protocol/
|
|
7486
|
-
const
|
|
7487
|
-
const
|
|
7488
|
-
const
|
|
7489
|
-
const
|
|
7490
|
-
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
const
|
|
7495
|
-
|
|
7496
|
-
|
|
7497
|
-
|
|
7498
|
-
|
|
7499
|
-
|
|
7500
|
-
|
|
7501
|
-
|
|
7502
|
-
|
|
7643
|
+
//#region src/protocol/perception.ts
|
|
7644
|
+
const BRIDGE_CREATE_AI_CONTROLLER_REQUEST_TYPE = "create_ai_controller";
|
|
7645
|
+
const BRIDGE_CONFIGURE_AI_PERCEPTION_REQUEST_TYPE = "configure_ai_perception";
|
|
7646
|
+
const BRIDGE_ADD_STIMULI_SOURCE_REQUEST_TYPE = "add_stimuli_source";
|
|
7647
|
+
const BRIDGE_AI_BRAIN_KINDS = [
|
|
7648
|
+
"behavior_tree",
|
|
7649
|
+
"state_tree",
|
|
7650
|
+
"none"
|
|
7651
|
+
];
|
|
7652
|
+
const BRIDGE_AI_AUTO_POSSESS_MODES = [
|
|
7653
|
+
"disabled",
|
|
7654
|
+
"placed_in_world",
|
|
7655
|
+
"spawned",
|
|
7656
|
+
"placed_in_world_or_spawned"
|
|
7657
|
+
];
|
|
7658
|
+
const BRIDGE_AI_SENSE_KINDS = [
|
|
7659
|
+
"sight",
|
|
7660
|
+
"hearing",
|
|
7661
|
+
"damage",
|
|
7662
|
+
"team",
|
|
7663
|
+
"touch",
|
|
7664
|
+
"prediction"
|
|
7665
|
+
];
|
|
7666
|
+
const BRIDGE_AI_SENSE_MODES = ["set", "remove"];
|
|
7667
|
+
const aiBrainKindSchema = z.enum(BRIDGE_AI_BRAIN_KINDS);
|
|
7668
|
+
const aiAutoPossessModeSchema = z.enum(BRIDGE_AI_AUTO_POSSESS_MODES);
|
|
7669
|
+
const aiSenseKindSchema = z.enum(BRIDGE_AI_SENSE_KINDS);
|
|
7670
|
+
const aiSenseModeSchema = z.enum(BRIDGE_AI_SENSE_MODES);
|
|
7671
|
+
const bridgeCreateAiControllerRequestFieldsSchema = z.object({
|
|
7672
|
+
addPerception: z.boolean().default(false),
|
|
7673
|
+
assetName: assetNameSchema,
|
|
7674
|
+
autoPossess: aiAutoPossessModeSchema.default("placed_in_world_or_spawned"),
|
|
7675
|
+
behaviorTreePath: assetPathSchema.optional(),
|
|
7676
|
+
blackboardPath: assetPathSchema.optional(),
|
|
7677
|
+
brainKind: aiBrainKindSchema.default("behavior_tree"),
|
|
7678
|
+
packagePath: contentPathSchema,
|
|
7679
|
+
parentClass: assetPathSchema.optional(),
|
|
7680
|
+
pawnClassPath: assetPathSchema.optional(),
|
|
7681
|
+
requestId: requestIdSchema,
|
|
7682
|
+
stateTreePath: assetPathSchema.optional(),
|
|
7683
|
+
type: z.literal(BRIDGE_CREATE_AI_CONTROLLER_REQUEST_TYPE),
|
|
7684
|
+
version: z.literal(2)
|
|
7685
|
+
});
|
|
7686
|
+
const bridgeCreateAiControllerRequestSchema = bridgeCreateAiControllerRequestFieldsSchema.superRefine((request, ctx) => {
|
|
7687
|
+
if (request.brainKind === "behavior_tree" && request.behaviorTreePath === void 0) ctx.addIssue({
|
|
7688
|
+
code: z.ZodIssueCode.custom,
|
|
7689
|
+
message: "A 'behavior_tree' brain must name its behaviorTreePath.",
|
|
7690
|
+
path: ["behaviorTreePath"]
|
|
7691
|
+
});
|
|
7692
|
+
if (request.brainKind === "state_tree" && request.stateTreePath === void 0) ctx.addIssue({
|
|
7693
|
+
code: z.ZodIssueCode.custom,
|
|
7694
|
+
message: "A 'state_tree' brain must name its stateTreePath.",
|
|
7695
|
+
path: ["stateTreePath"]
|
|
7696
|
+
});
|
|
7697
|
+
});
|
|
7698
|
+
const bridgeCreateAiControllerSuccessResponseSchema = z.object({
|
|
7699
|
+
...createdUserAssetResponseFields,
|
|
7700
|
+
autoPossess: z.string(),
|
|
7701
|
+
brainKind: aiBrainKindSchema,
|
|
7702
|
+
pawnClassPath: z.string().optional(),
|
|
7703
|
+
perceptionAdded: z.boolean(),
|
|
7704
|
+
type: z.literal(BRIDGE_CREATE_AI_CONTROLLER_REQUEST_TYPE),
|
|
7705
|
+
warnings: z.array(z.string()).max(16)
|
|
7706
|
+
});
|
|
7707
|
+
const bridgeAiSenseConfigSchema = z.object({
|
|
7708
|
+
detectEnemies: z.boolean().default(true),
|
|
7709
|
+
detectFriendlies: z.boolean().default(false),
|
|
7710
|
+
detectNeutrals: z.boolean().default(false),
|
|
7711
|
+
mode: aiSenseModeSchema.default("set"),
|
|
7712
|
+
params: eqsParamsSchema.default({}),
|
|
7713
|
+
senseKind: aiSenseKindSchema
|
|
7714
|
+
});
|
|
7715
|
+
const bridgeConfigureAiPerceptionRequestSchema = z.object({
|
|
7716
|
+
blueprintPath: assetPathSchema,
|
|
7717
|
+
componentName: userTypeIdentifierSchema.optional(),
|
|
7718
|
+
dominantSense: aiSenseKindSchema.optional(),
|
|
7719
|
+
requestId: requestIdSchema,
|
|
7720
|
+
senses: z.array(bridgeAiSenseConfigSchema).min(1).max(8),
|
|
7721
|
+
type: z.literal(BRIDGE_CONFIGURE_AI_PERCEPTION_REQUEST_TYPE),
|
|
7722
|
+
version: z.literal(2)
|
|
7723
|
+
});
|
|
7724
|
+
const bridgeConfigureAiPerceptionSuccessResponseSchema = z.object({
|
|
7725
|
+
...authoringBatchResponseFields,
|
|
7726
|
+
componentName: z.string(),
|
|
7727
|
+
senseCount: z.number().int().min(0),
|
|
7728
|
+
type: z.literal(BRIDGE_CONFIGURE_AI_PERCEPTION_REQUEST_TYPE)
|
|
7729
|
+
});
|
|
7730
|
+
const bridgeAddStimuliSourceRequestSchema = z.object({
|
|
7731
|
+
autoRegisterAsSource: z.boolean().default(true),
|
|
7732
|
+
blueprintPath: assetPathSchema,
|
|
7733
|
+
componentName: userTypeIdentifierSchema.optional(),
|
|
7734
|
+
requestId: requestIdSchema,
|
|
7735
|
+
senses: z.array(aiSenseKindSchema).min(1).max(8),
|
|
7736
|
+
type: z.literal(BRIDGE_ADD_STIMULI_SOURCE_REQUEST_TYPE),
|
|
7737
|
+
version: z.literal(2)
|
|
7738
|
+
});
|
|
7739
|
+
const bridgeAddStimuliSourceSuccessResponseSchema = z.object({
|
|
7740
|
+
blueprintPath: z.string(),
|
|
7741
|
+
componentName: z.string(),
|
|
7742
|
+
message: nonEmptyStringSchema.optional(),
|
|
7743
|
+
ok: z.literal(true),
|
|
7744
|
+
packageDirty: z.boolean(),
|
|
7745
|
+
registeredSenses: z.array(z.string()).max(8),
|
|
7746
|
+
requestId: requestIdSchema,
|
|
7747
|
+
state: aiReportStateSchema,
|
|
7748
|
+
type: z.literal(BRIDGE_ADD_STIMULI_SOURCE_REQUEST_TYPE),
|
|
7749
|
+
version: z.literal(2)
|
|
7750
|
+
});
|
|
7751
|
+
const bridgeCreateAiControllerResponseSchema = z.union([bridgeCreateAiControllerSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
7752
|
+
const bridgeConfigureAiPerceptionResponseSchema = z.union([bridgeConfigureAiPerceptionSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
7753
|
+
const bridgeAddStimuliSourceResponseSchema = z.union([bridgeAddStimuliSourceSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
7754
|
+
function createBridgeCreateAiControllerRequest(assetName, packagePath, options = {}, requestId = randomUUID()) {
|
|
7755
|
+
return bridgeCreateAiControllerRequestSchema.parse({
|
|
7756
|
+
addPerception: options.addPerception,
|
|
7757
|
+
assetName,
|
|
7758
|
+
autoPossess: options.autoPossess,
|
|
7759
|
+
behaviorTreePath: options.behaviorTreePath,
|
|
7760
|
+
blackboardPath: options.blackboardPath,
|
|
7761
|
+
brainKind: options.brainKind,
|
|
7762
|
+
packagePath,
|
|
7763
|
+
parentClass: options.parentClass,
|
|
7764
|
+
pawnClassPath: options.pawnClassPath,
|
|
7765
|
+
requestId,
|
|
7766
|
+
stateTreePath: options.stateTreePath,
|
|
7767
|
+
type: BRIDGE_CREATE_AI_CONTROLLER_REQUEST_TYPE,
|
|
7768
|
+
version: 2
|
|
7769
|
+
});
|
|
7770
|
+
}
|
|
7771
|
+
function createBridgeConfigureAiPerceptionRequest(blueprintPath, senses, options = {}, requestId = randomUUID()) {
|
|
7772
|
+
return bridgeConfigureAiPerceptionRequestSchema.parse({
|
|
7773
|
+
blueprintPath,
|
|
7774
|
+
componentName: options.componentName,
|
|
7775
|
+
dominantSense: options.dominantSense,
|
|
7776
|
+
requestId,
|
|
7777
|
+
senses,
|
|
7778
|
+
type: BRIDGE_CONFIGURE_AI_PERCEPTION_REQUEST_TYPE,
|
|
7779
|
+
version: 2
|
|
7780
|
+
});
|
|
7781
|
+
}
|
|
7782
|
+
function createBridgeAddStimuliSourceRequest(blueprintPath, senses, options = {}, requestId = randomUUID()) {
|
|
7783
|
+
return bridgeAddStimuliSourceRequestSchema.parse({
|
|
7784
|
+
autoRegisterAsSource: options.autoRegisterAsSource,
|
|
7785
|
+
blueprintPath,
|
|
7786
|
+
componentName: options.componentName,
|
|
7787
|
+
requestId,
|
|
7788
|
+
senses,
|
|
7789
|
+
type: BRIDGE_ADD_STIMULI_SOURCE_REQUEST_TYPE,
|
|
7790
|
+
version: 2
|
|
7791
|
+
});
|
|
7792
|
+
}
|
|
7793
|
+
//#endregion
|
|
7794
|
+
//#region src/protocol/eqs.ts
|
|
7795
|
+
const eqsTestPurposeSchema = z.enum(BRIDGE_EQS_TEST_PURPOSES);
|
|
7796
|
+
const BRIDGE_GET_EQS_QUERY_REQUEST_TYPE = "get_eqs_query";
|
|
7797
|
+
const BRIDGE_EDIT_EQS_QUERY_REQUEST_TYPE = "edit_eqs_query";
|
|
7798
|
+
const BRIDGE_RUN_EQS_QUERY_REQUEST_TYPE = "run_eqs_query";
|
|
7799
|
+
const BRIDGE_EQS_RUN_MODES = [
|
|
7800
|
+
"single_result",
|
|
7801
|
+
"random_best_25_percent",
|
|
7802
|
+
"random_best_5_percent",
|
|
7803
|
+
"all_matching"
|
|
7804
|
+
];
|
|
7805
|
+
const BRIDGE_EQS_TEST_OPERATIONS = [
|
|
7806
|
+
"add",
|
|
7807
|
+
"update",
|
|
7808
|
+
"remove",
|
|
7809
|
+
"move"
|
|
7810
|
+
];
|
|
7811
|
+
const eqsRunModeSchema = z.enum(BRIDGE_EQS_RUN_MODES);
|
|
7812
|
+
const eqsTestOperationSchema = z.enum(BRIDGE_EQS_TEST_OPERATIONS);
|
|
7813
|
+
const bridgeGetEqsQueryRequestSchema = z.object({
|
|
7814
|
+
assetPath: assetPathSchema,
|
|
7815
|
+
requestId: requestIdSchema,
|
|
7816
|
+
type: z.literal(BRIDGE_GET_EQS_QUERY_REQUEST_TYPE),
|
|
7817
|
+
version: z.literal(2)
|
|
7818
|
+
});
|
|
7819
|
+
const bridgeEqsTestReportSchema = z.object({
|
|
7820
|
+
params: aiParamsSchema,
|
|
7821
|
+
purpose: z.string(),
|
|
7822
|
+
testClass: z.string(),
|
|
7823
|
+
testIndex: z.number().int().min(0)
|
|
7824
|
+
});
|
|
7825
|
+
const bridgeEqsOptionReportSchema = z.object({
|
|
7826
|
+
generatorClass: z.string(),
|
|
7827
|
+
generatorParams: aiParamsSchema,
|
|
7828
|
+
optionIndex: z.number().int().min(0),
|
|
7829
|
+
tests: z.array(bridgeEqsTestReportSchema).max(16)
|
|
7830
|
+
});
|
|
7831
|
+
const bridgeGetEqsQuerySuccessResponseSchema = z.object({
|
|
7832
|
+
assetPath: z.string(),
|
|
7833
|
+
eqsEnabled: z.boolean(),
|
|
7834
|
+
message: nonEmptyStringSchema.optional(),
|
|
7835
|
+
ok: z.literal(true),
|
|
7836
|
+
options: z.array(bridgeEqsOptionReportSchema).max(8),
|
|
7837
|
+
requestId: requestIdSchema,
|
|
7838
|
+
state: aiReportStateSchema,
|
|
7839
|
+
truncated: z.boolean(),
|
|
7840
|
+
type: z.literal(BRIDGE_GET_EQS_QUERY_REQUEST_TYPE),
|
|
7841
|
+
version: z.literal(2)
|
|
7842
|
+
});
|
|
7843
|
+
const bridgeEqsTestEditSchema = z.object({
|
|
7844
|
+
operation: eqsTestOperationSchema,
|
|
7845
|
+
params: eqsParamsSchema.default({}),
|
|
7846
|
+
purpose: eqsTestPurposeSchema.optional(),
|
|
7847
|
+
testClass: assetPathSchema.optional(),
|
|
7848
|
+
testIndex: z.number().int().min(0).max(15).optional(),
|
|
7849
|
+
toIndex: z.number().int().min(0).max(16).optional()
|
|
7850
|
+
}).superRefine((edit, ctx) => {
|
|
7851
|
+
if (edit.operation === "add" && edit.testClass === void 0) ctx.addIssue({
|
|
7852
|
+
code: z.ZodIssueCode.custom,
|
|
7853
|
+
message: "An 'add' test edit must name its testClass.",
|
|
7854
|
+
path: ["testClass"]
|
|
7855
|
+
});
|
|
7856
|
+
if (edit.operation !== "add" && edit.testIndex === void 0) ctx.addIssue({
|
|
7857
|
+
code: z.ZodIssueCode.custom,
|
|
7858
|
+
message: `A '${edit.operation}' test edit must name the testIndex it addresses.`,
|
|
7859
|
+
path: ["testIndex"]
|
|
7860
|
+
});
|
|
7861
|
+
if (edit.operation === "move" && edit.toIndex === void 0) ctx.addIssue({
|
|
7862
|
+
code: z.ZodIssueCode.custom,
|
|
7863
|
+
message: "A 'move' test edit must name its toIndex.",
|
|
7864
|
+
path: ["toIndex"]
|
|
7865
|
+
});
|
|
7866
|
+
});
|
|
7867
|
+
const bridgeEditEqsQueryRequestSchema = z.object({
|
|
7868
|
+
assetPath: assetPathSchema,
|
|
7869
|
+
generatorClass: assetPathSchema.optional(),
|
|
7870
|
+
generatorParams: eqsParamsSchema.optional(),
|
|
7871
|
+
optionIndex: z.number().int().min(0).max(7).default(0),
|
|
7872
|
+
requestId: requestIdSchema,
|
|
7873
|
+
tests: z.array(bridgeEqsTestEditSchema).max(16).default([]),
|
|
7874
|
+
type: z.literal(BRIDGE_EDIT_EQS_QUERY_REQUEST_TYPE),
|
|
7875
|
+
version: z.literal(2)
|
|
7876
|
+
});
|
|
7877
|
+
const bridgeEditEqsQuerySuccessResponseSchema = z.object({
|
|
7878
|
+
...authoringBatchResponseFields,
|
|
7879
|
+
generatorClass: z.string(),
|
|
7880
|
+
testCount: z.number().int().min(0),
|
|
7881
|
+
type: z.literal(BRIDGE_EDIT_EQS_QUERY_REQUEST_TYPE)
|
|
7882
|
+
});
|
|
7883
|
+
const bridgeRunEqsQueryRequestFieldsSchema = z.object({
|
|
7884
|
+
assetPath: assetPathSchema,
|
|
7885
|
+
maxItems: z.number().int().min(1).max(64).default(25),
|
|
7886
|
+
querierActorPath: assetPathSchema.optional(),
|
|
7887
|
+
querierLocation: bridgeVectorSchema.optional(),
|
|
7888
|
+
requestId: requestIdSchema,
|
|
7889
|
+
runMode: eqsRunModeSchema.default("all_matching"),
|
|
7890
|
+
type: z.literal(BRIDGE_RUN_EQS_QUERY_REQUEST_TYPE),
|
|
7891
|
+
version: z.literal(2)
|
|
7892
|
+
});
|
|
7893
|
+
const bridgeRunEqsQueryRequestSchema = bridgeRunEqsQueryRequestFieldsSchema.refine((request) => request.querierActorPath !== void 0 || request.querierLocation !== void 0, {
|
|
7894
|
+
message: "A run_eqs_query request must name either a querierActorPath or a querierLocation.",
|
|
7895
|
+
path: ["querierActorPath"]
|
|
7896
|
+
});
|
|
7897
|
+
const bridgeEqsItemTestScoreSchema = z.object({
|
|
7898
|
+
score: z.number(),
|
|
7899
|
+
testClass: z.string(),
|
|
7900
|
+
testIndex: z.number().int().min(0)
|
|
7901
|
+
});
|
|
7902
|
+
const bridgeEqsResultItemSchema = z.object({
|
|
7903
|
+
actorPath: z.string().optional(),
|
|
7904
|
+
index: z.number().int().min(0),
|
|
7905
|
+
location: bridgeVectorSchema,
|
|
7906
|
+
score: z.number(),
|
|
7907
|
+
testScores: z.array(bridgeEqsItemTestScoreSchema).max(16)
|
|
7908
|
+
});
|
|
7909
|
+
const bridgeRunEqsQuerySuccessResponseSchema = z.object({
|
|
7910
|
+
assetPath: z.string(),
|
|
7911
|
+
itemCount: z.number().int().min(0),
|
|
7912
|
+
items: z.array(bridgeEqsResultItemSchema).max(64),
|
|
7913
|
+
message: nonEmptyStringSchema.optional(),
|
|
7914
|
+
ok: z.literal(true),
|
|
7915
|
+
requestId: requestIdSchema,
|
|
7916
|
+
runMode: eqsRunModeSchema,
|
|
7917
|
+
state: aiReportStateSchema,
|
|
7918
|
+
type: z.literal(BRIDGE_RUN_EQS_QUERY_REQUEST_TYPE),
|
|
7919
|
+
version: z.literal(2),
|
|
7920
|
+
winningItemIndex: z.number().int().min(0).optional()
|
|
7921
|
+
});
|
|
7922
|
+
const bridgeGetEqsQueryResponseSchema = z.union([bridgeGetEqsQuerySuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
7923
|
+
const bridgeEditEqsQueryResponseSchema = z.union([bridgeEditEqsQuerySuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
7924
|
+
const bridgeRunEqsQueryResponseSchema = z.union([bridgeRunEqsQuerySuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
7925
|
+
function createBridgeGetEqsQueryRequest(assetPath, requestId = randomUUID()) {
|
|
7926
|
+
return bridgeGetEqsQueryRequestSchema.parse({
|
|
7927
|
+
assetPath,
|
|
7928
|
+
requestId,
|
|
7929
|
+
type: BRIDGE_GET_EQS_QUERY_REQUEST_TYPE,
|
|
7930
|
+
version: 2
|
|
7931
|
+
});
|
|
7932
|
+
}
|
|
7933
|
+
function createBridgeEditEqsQueryRequest(assetPath, options = {}, requestId = randomUUID()) {
|
|
7934
|
+
return bridgeEditEqsQueryRequestSchema.parse({
|
|
7935
|
+
assetPath,
|
|
7936
|
+
generatorClass: options.generatorClass,
|
|
7937
|
+
generatorParams: options.generatorParams,
|
|
7938
|
+
optionIndex: options.optionIndex,
|
|
7939
|
+
requestId,
|
|
7940
|
+
tests: options.tests,
|
|
7941
|
+
type: BRIDGE_EDIT_EQS_QUERY_REQUEST_TYPE,
|
|
7942
|
+
version: 2
|
|
7943
|
+
});
|
|
7944
|
+
}
|
|
7945
|
+
function createBridgeRunEqsQueryRequest(assetPath, options = {}, requestId = randomUUID()) {
|
|
7946
|
+
return bridgeRunEqsQueryRequestSchema.parse({
|
|
7947
|
+
assetPath,
|
|
7948
|
+
maxItems: options.maxItems,
|
|
7949
|
+
querierActorPath: options.querierActorPath,
|
|
7950
|
+
querierLocation: options.querierLocation,
|
|
7951
|
+
requestId,
|
|
7952
|
+
runMode: options.runMode,
|
|
7953
|
+
type: BRIDGE_RUN_EQS_QUERY_REQUEST_TYPE,
|
|
7954
|
+
version: 2
|
|
7955
|
+
});
|
|
7956
|
+
}
|
|
7957
|
+
//#endregion
|
|
7958
|
+
//#region src/protocol/sequencer.ts
|
|
7959
|
+
const BRIDGE_CREATE_LEVEL_SEQUENCE_REQUEST_TYPE = "create_level_sequence";
|
|
7960
|
+
const BRIDGE_ADD_SEQUENCE_BINDING_REQUEST_TYPE = "add_sequence_binding";
|
|
7961
|
+
const BRIDGE_ADD_SEQUENCE_TRACK_REQUEST_TYPE = "add_sequence_track";
|
|
7962
|
+
const BRIDGE_ADD_SEQUENCE_KEYS_REQUEST_TYPE = "add_sequence_keys";
|
|
7963
|
+
const BRIDGE_SEQUENCE_BINDING_KINDS = ["possessable", "spawnable"];
|
|
7964
|
+
const BRIDGE_SEQUENCE_TRACK_KINDS = [
|
|
7965
|
+
"transform",
|
|
7966
|
+
"skeletal_animation",
|
|
7967
|
+
"camera_cut",
|
|
7968
|
+
"audio",
|
|
7969
|
+
"visibility",
|
|
7970
|
+
"property"
|
|
7971
|
+
];
|
|
7972
|
+
const BRIDGE_SEQUENCE_TIME_UNITS = ["frames", "seconds"];
|
|
7973
|
+
const BRIDGE_SEQUENCE_INTERPOLATIONS = [
|
|
7974
|
+
"auto",
|
|
7975
|
+
"user",
|
|
7976
|
+
"break",
|
|
7977
|
+
"linear",
|
|
7978
|
+
"constant"
|
|
7979
|
+
];
|
|
7980
|
+
const BRIDGE_SEQUENCE_MAX_FRAME_RATE = 24e4;
|
|
7981
|
+
const BRIDGE_SEQUENCE_MAX_FRAME = 1e7;
|
|
7982
|
+
const sequenceBindingKindSchema = z.enum(BRIDGE_SEQUENCE_BINDING_KINDS);
|
|
7983
|
+
const sequenceTrackKindSchema = z.enum(BRIDGE_SEQUENCE_TRACK_KINDS);
|
|
7984
|
+
const sequenceTimeUnitSchema = z.enum(BRIDGE_SEQUENCE_TIME_UNITS);
|
|
7985
|
+
const sequenceInterpolationSchema = z.enum(BRIDGE_SEQUENCE_INTERPOLATIONS);
|
|
7986
|
+
const sequenceBindingIdSchema = z.string().trim().min(1).max(64);
|
|
7987
|
+
const sequenceFrameSchema = z.number().int().min(-1e7).max(BRIDGE_SEQUENCE_MAX_FRAME);
|
|
7988
|
+
const bridgeSequenceFrameRateSchema = z.object({
|
|
7989
|
+
denominator: z.number().int().min(1).max(BRIDGE_SEQUENCE_MAX_FRAME_RATE),
|
|
7990
|
+
numerator: z.number().int().min(1).max(BRIDGE_SEQUENCE_MAX_FRAME_RATE)
|
|
7991
|
+
});
|
|
7992
|
+
const bridgeCreateLevelSequenceRequestSchema = z.object({
|
|
7993
|
+
assetName: assetNameSchema,
|
|
7994
|
+
displayRate: bridgeSequenceFrameRateSchema.optional(),
|
|
7995
|
+
durationInFrames: z.number().int().min(1).max(BRIDGE_SEQUENCE_MAX_FRAME).optional(),
|
|
7996
|
+
packagePath: contentPathSchema,
|
|
7997
|
+
requestId: requestIdSchema,
|
|
7998
|
+
tickResolution: bridgeSequenceFrameRateSchema.optional(),
|
|
7999
|
+
type: z.literal(BRIDGE_CREATE_LEVEL_SEQUENCE_REQUEST_TYPE),
|
|
8000
|
+
version: z.literal(2)
|
|
8001
|
+
});
|
|
8002
|
+
const bridgeSequenceBindingSchema = z.object({
|
|
8003
|
+
actorPath: actorPathSchema.optional(),
|
|
8004
|
+
bindingKind: sequenceBindingKindSchema,
|
|
8005
|
+
name: boundedStringSchema.optional(),
|
|
8006
|
+
objectClassPath: assetPathSchema.optional()
|
|
8007
|
+
}).superRefine((binding, ctx) => {
|
|
8008
|
+
if (binding.bindingKind === "possessable" && binding.actorPath === void 0) {
|
|
8009
|
+
ctx.addIssue({
|
|
8010
|
+
code: z.ZodIssueCode.custom,
|
|
8011
|
+
message: "A possessable binding must name the actorPath it possesses.",
|
|
8012
|
+
path: ["actorPath"]
|
|
8013
|
+
});
|
|
8014
|
+
return;
|
|
8015
|
+
}
|
|
8016
|
+
if (binding.bindingKind === "spawnable" && binding.actorPath === void 0 && binding.objectClassPath === void 0) ctx.addIssue({
|
|
8017
|
+
code: z.ZodIssueCode.custom,
|
|
8018
|
+
message: "A spawnable binding needs a template, so it must carry actorPath or objectClassPath.",
|
|
8019
|
+
path: ["objectClassPath"]
|
|
8020
|
+
});
|
|
8021
|
+
});
|
|
8022
|
+
const bridgeAddSequenceBindingRequestSchema = z.object({
|
|
8023
|
+
assetPath: assetPathSchema,
|
|
8024
|
+
bindings: z.array(bridgeSequenceBindingSchema).min(1).max(32),
|
|
8025
|
+
requestId: requestIdSchema,
|
|
8026
|
+
type: z.literal(BRIDGE_ADD_SEQUENCE_BINDING_REQUEST_TYPE),
|
|
8027
|
+
version: z.literal(2)
|
|
8028
|
+
});
|
|
8029
|
+
const bridgeAddSequenceTrackRequestFieldsSchema = z.object({
|
|
8030
|
+
assetPath: assetPathSchema,
|
|
8031
|
+
bindingId: sequenceBindingIdSchema.optional(),
|
|
8032
|
+
propertyPath: propertyPathSchema.optional(),
|
|
8033
|
+
requestId: requestIdSchema,
|
|
8034
|
+
sectionEndFrame: sequenceFrameSchema.optional(),
|
|
8035
|
+
sectionStartFrame: sequenceFrameSchema.optional(),
|
|
8036
|
+
trackKind: sequenceTrackKindSchema,
|
|
8037
|
+
type: z.literal(BRIDGE_ADD_SEQUENCE_TRACK_REQUEST_TYPE),
|
|
8038
|
+
version: z.literal(2)
|
|
8039
|
+
});
|
|
8040
|
+
const bridgeAddSequenceTrackRequestSchema = bridgeAddSequenceTrackRequestFieldsSchema.superRefine((request, ctx) => {
|
|
8041
|
+
if (request.trackKind === "property" && request.propertyPath === void 0) ctx.addIssue({
|
|
8042
|
+
code: z.ZodIssueCode.custom,
|
|
8043
|
+
message: "A 'property' track must name the propertyPath it animates.",
|
|
8044
|
+
path: ["propertyPath"]
|
|
8045
|
+
});
|
|
8046
|
+
if (request.trackKind !== "camera_cut" && request.bindingId === void 0) ctx.addIssue({
|
|
8047
|
+
code: z.ZodIssueCode.custom,
|
|
8048
|
+
message: `A '${request.trackKind}' track belongs to a binding, so bindingId is required.`,
|
|
8049
|
+
path: ["bindingId"]
|
|
8050
|
+
});
|
|
8051
|
+
if (request.sectionStartFrame !== void 0 && request.sectionEndFrame !== void 0 && request.sectionEndFrame < request.sectionStartFrame) ctx.addIssue({
|
|
8052
|
+
code: z.ZodIssueCode.custom,
|
|
8053
|
+
message: "A section cannot end before it starts.",
|
|
8054
|
+
path: ["sectionEndFrame"]
|
|
8055
|
+
});
|
|
8056
|
+
});
|
|
8057
|
+
const bridgeSequenceKeySchema = z.object({
|
|
8058
|
+
arriveTangent: z.number().optional(),
|
|
8059
|
+
interpolation: sequenceInterpolationSchema.default("auto"),
|
|
8060
|
+
leaveTangent: z.number().optional(),
|
|
8061
|
+
time: z.number(),
|
|
8062
|
+
value: z.number()
|
|
8063
|
+
});
|
|
8064
|
+
const bridgeAddSequenceKeysRequestSchema = z.object({
|
|
8065
|
+
assetPath: assetPathSchema,
|
|
8066
|
+
bindingId: sequenceBindingIdSchema.optional(),
|
|
8067
|
+
channelName: boundedStringSchema,
|
|
8068
|
+
keys: z.array(bridgeSequenceKeySchema).min(1).max(128),
|
|
8069
|
+
requestId: requestIdSchema,
|
|
8070
|
+
timeUnit: sequenceTimeUnitSchema,
|
|
8071
|
+
trackName: boundedStringSchema,
|
|
8072
|
+
type: z.literal(BRIDGE_ADD_SEQUENCE_KEYS_REQUEST_TYPE),
|
|
8073
|
+
version: z.literal(2)
|
|
8074
|
+
});
|
|
8075
|
+
const bridgeCreateLevelSequenceSuccessResponseSchema = z.object({
|
|
8076
|
+
...createdUserAssetResponseFields,
|
|
8077
|
+
displayRate: bridgeSequenceFrameRateSchema,
|
|
8078
|
+
durationInFrames: z.number().int().min(0),
|
|
8079
|
+
tickResolution: bridgeSequenceFrameRateSchema,
|
|
8080
|
+
type: z.literal(BRIDGE_CREATE_LEVEL_SEQUENCE_REQUEST_TYPE)
|
|
8081
|
+
});
|
|
8082
|
+
const bridgeAddSequenceBindingSuccessResponseSchema = z.object({
|
|
8083
|
+
...authoringBatchResponseFields,
|
|
8084
|
+
type: z.literal(BRIDGE_ADD_SEQUENCE_BINDING_REQUEST_TYPE)
|
|
8085
|
+
});
|
|
8086
|
+
const bridgeAddSequenceTrackSuccessResponseSchema = z.object({
|
|
8087
|
+
assetPath: z.string(),
|
|
8088
|
+
message: nonEmptyStringSchema.optional(),
|
|
8089
|
+
ok: z.literal(true),
|
|
8090
|
+
packageDirty: z.boolean(),
|
|
8091
|
+
requestId: requestIdSchema,
|
|
8092
|
+
sectionIndex: z.number().int().min(0),
|
|
8093
|
+
state: creativeEditStateSchema,
|
|
8094
|
+
trackKind: sequenceTrackKindSchema,
|
|
8095
|
+
trackName: z.string(),
|
|
8096
|
+
type: z.literal(BRIDGE_ADD_SEQUENCE_TRACK_REQUEST_TYPE),
|
|
8097
|
+
version: z.literal(2)
|
|
8098
|
+
});
|
|
8099
|
+
const bridgeAddSequenceKeysSuccessResponseSchema = z.object({
|
|
8100
|
+
assetPath: z.string(),
|
|
8101
|
+
channelName: z.string(),
|
|
8102
|
+
keyCount: z.number().int().min(0),
|
|
8103
|
+
message: nonEmptyStringSchema.optional(),
|
|
8104
|
+
ok: z.literal(true),
|
|
8105
|
+
packageDirty: z.boolean(),
|
|
8106
|
+
requestId: requestIdSchema,
|
|
8107
|
+
resolvedFrames: z.array(z.number().int()).max(128),
|
|
8108
|
+
state: creativeEditStateSchema,
|
|
8109
|
+
type: z.literal(BRIDGE_ADD_SEQUENCE_KEYS_REQUEST_TYPE),
|
|
8110
|
+
version: z.literal(2)
|
|
8111
|
+
});
|
|
8112
|
+
const bridgeCreateLevelSequenceResponseSchema = z.union([bridgeCreateLevelSequenceSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
8113
|
+
const bridgeAddSequenceBindingResponseSchema = z.union([bridgeAddSequenceBindingSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
8114
|
+
const bridgeAddSequenceTrackResponseSchema = z.union([bridgeAddSequenceTrackSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
8115
|
+
const bridgeAddSequenceKeysResponseSchema = z.union([bridgeAddSequenceKeysSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
8116
|
+
function createBridgeCreateLevelSequenceRequest(assetName, packagePath, options = {}, requestId = randomUUID()) {
|
|
8117
|
+
return bridgeCreateLevelSequenceRequestSchema.parse({
|
|
8118
|
+
assetName,
|
|
8119
|
+
displayRate: options.displayRate,
|
|
8120
|
+
durationInFrames: options.durationInFrames,
|
|
8121
|
+
packagePath,
|
|
8122
|
+
requestId,
|
|
8123
|
+
tickResolution: options.tickResolution,
|
|
8124
|
+
type: BRIDGE_CREATE_LEVEL_SEQUENCE_REQUEST_TYPE,
|
|
8125
|
+
version: 2
|
|
8126
|
+
});
|
|
8127
|
+
}
|
|
8128
|
+
function createBridgeAddSequenceBindingRequest(assetPath, bindings, requestId = randomUUID()) {
|
|
8129
|
+
return bridgeAddSequenceBindingRequestSchema.parse({
|
|
8130
|
+
assetPath,
|
|
8131
|
+
bindings,
|
|
8132
|
+
requestId,
|
|
8133
|
+
type: BRIDGE_ADD_SEQUENCE_BINDING_REQUEST_TYPE,
|
|
8134
|
+
version: 2
|
|
8135
|
+
});
|
|
8136
|
+
}
|
|
8137
|
+
function createBridgeAddSequenceTrackRequest(assetPath, trackKind, options = {}, requestId = randomUUID()) {
|
|
8138
|
+
return bridgeAddSequenceTrackRequestSchema.parse({
|
|
8139
|
+
assetPath,
|
|
8140
|
+
bindingId: options.bindingId,
|
|
8141
|
+
propertyPath: options.propertyPath,
|
|
8142
|
+
requestId,
|
|
8143
|
+
sectionEndFrame: options.sectionEndFrame,
|
|
8144
|
+
sectionStartFrame: options.sectionStartFrame,
|
|
8145
|
+
trackKind,
|
|
8146
|
+
type: BRIDGE_ADD_SEQUENCE_TRACK_REQUEST_TYPE,
|
|
8147
|
+
version: 2
|
|
8148
|
+
});
|
|
8149
|
+
}
|
|
8150
|
+
function createBridgeAddSequenceKeysRequest(assetPath, trackName, channelName, timeUnit, keys, options = {}, requestId = randomUUID()) {
|
|
8151
|
+
return bridgeAddSequenceKeysRequestSchema.parse({
|
|
8152
|
+
assetPath,
|
|
8153
|
+
bindingId: options.bindingId,
|
|
8154
|
+
channelName,
|
|
8155
|
+
keys,
|
|
8156
|
+
requestId,
|
|
8157
|
+
timeUnit,
|
|
8158
|
+
trackName,
|
|
8159
|
+
type: BRIDGE_ADD_SEQUENCE_KEYS_REQUEST_TYPE,
|
|
8160
|
+
version: 2
|
|
8161
|
+
});
|
|
8162
|
+
}
|
|
8163
|
+
//#endregion
|
|
8164
|
+
//#region src/protocol/foliage.ts
|
|
8165
|
+
const BRIDGE_ADD_FOLIAGE_TYPE_REQUEST_TYPE = "add_foliage_type";
|
|
8166
|
+
const BRIDGE_PAINT_FOLIAGE_REQUEST_TYPE = "paint_foliage";
|
|
8167
|
+
const BRIDGE_FOLIAGE_PLACEMENT_MODES = ["explicit", "region"];
|
|
8168
|
+
const BRIDGE_FOLIAGE_MAX_DENSITY = 1e3;
|
|
8169
|
+
const BRIDGE_FOLIAGE_COORDINATE_LIMIT = 21e6;
|
|
8170
|
+
const BRIDGE_FOLIAGE_MAX_SCALE = 1e3;
|
|
8171
|
+
const foliagePlacementModeSchema = z.enum(BRIDGE_FOLIAGE_PLACEMENT_MODES);
|
|
8172
|
+
const foliageCoordinateSchema = z.number().min(-21e6).max(BRIDGE_FOLIAGE_COORDINATE_LIMIT);
|
|
8173
|
+
const foliageSlopeSchema = z.number().min(0).max(90);
|
|
8174
|
+
const bridgeFoliageSettingsSchema = z.object({
|
|
8175
|
+
alignToNormal: z.boolean().optional(),
|
|
8176
|
+
collisionEnabled: z.boolean().optional(),
|
|
8177
|
+
density: z.number().min(0).max(BRIDGE_FOLIAGE_MAX_DENSITY).optional(),
|
|
8178
|
+
groundSlopeMax: foliageSlopeSchema.optional(),
|
|
8179
|
+
groundSlopeMin: foliageSlopeSchema.optional(),
|
|
8180
|
+
randomYaw: z.boolean().optional(),
|
|
8181
|
+
scaleMax: z.number().min(0).max(BRIDGE_FOLIAGE_MAX_SCALE).optional(),
|
|
7503
8182
|
scaleMin: z.number().min(0).max(BRIDGE_FOLIAGE_MAX_SCALE).optional()
|
|
7504
8183
|
});
|
|
7505
8184
|
const bridgeAddFoliageTypeRequestSchema = z.object({
|
|
@@ -8648,18 +9327,108 @@ function createBridgeAddBtNodeRequest(assetPath, nodes, requestId = randomUUID()
|
|
|
8648
9327
|
function createBridgeAddBtDecoratorRequest(assetPath, decorators, requestId = randomUUID()) {
|
|
8649
9328
|
return bridgeAddBtDecoratorRequestSchema.parse({
|
|
8650
9329
|
assetPath,
|
|
8651
|
-
decorators,
|
|
9330
|
+
decorators,
|
|
9331
|
+
requestId,
|
|
9332
|
+
type: BRIDGE_ADD_BT_DECORATOR_REQUEST_TYPE,
|
|
9333
|
+
version: 2
|
|
9334
|
+
});
|
|
9335
|
+
}
|
|
9336
|
+
function createBridgeAddBtServiceRequest(assetPath, services, requestId = randomUUID()) {
|
|
9337
|
+
return bridgeAddBtServiceRequestSchema.parse({
|
|
9338
|
+
assetPath,
|
|
9339
|
+
requestId,
|
|
9340
|
+
services,
|
|
9341
|
+
type: BRIDGE_ADD_BT_SERVICE_REQUEST_TYPE,
|
|
9342
|
+
version: 2
|
|
9343
|
+
});
|
|
9344
|
+
}
|
|
9345
|
+
const BRIDGE_GET_BEHAVIOR_TREE_REQUEST_TYPE = "get_behavior_tree";
|
|
9346
|
+
const BRIDGE_GET_BT_RUNTIME_STATE_REQUEST_TYPE = "get_bt_runtime_state";
|
|
9347
|
+
const bridgeGetBehaviorTreeRequestSchema = z.object({
|
|
9348
|
+
assetPath: assetPathSchema,
|
|
9349
|
+
requestId: requestIdSchema,
|
|
9350
|
+
type: z.literal(BRIDGE_GET_BEHAVIOR_TREE_REQUEST_TYPE),
|
|
9351
|
+
version: z.literal(2)
|
|
9352
|
+
});
|
|
9353
|
+
const bridgeBehaviorTreeSubNodeReportSchema = z.object({
|
|
9354
|
+
blackboardKeys: z.array(z.string()).max(64),
|
|
9355
|
+
name: z.string(),
|
|
9356
|
+
nodeClass: z.string(),
|
|
9357
|
+
nodeGuid: z.string(),
|
|
9358
|
+
params: aiParamsSchema
|
|
9359
|
+
});
|
|
9360
|
+
const bridgeBehaviorTreeNodeReportSchema = z.object({
|
|
9361
|
+
blackboardKeys: z.array(z.string()).max(64),
|
|
9362
|
+
childIndex: z.number().int().min(0),
|
|
9363
|
+
decorators: z.array(bridgeBehaviorTreeSubNodeReportSchema).max(200),
|
|
9364
|
+
name: z.string(),
|
|
9365
|
+
nodeClass: z.string(),
|
|
9366
|
+
nodeGuid: z.string(),
|
|
9367
|
+
nodeKind: z.string(),
|
|
9368
|
+
params: aiParamsSchema,
|
|
9369
|
+
parentNodeGuid: z.string().optional(),
|
|
9370
|
+
services: z.array(bridgeBehaviorTreeSubNodeReportSchema).max(200)
|
|
9371
|
+
});
|
|
9372
|
+
const bridgeGetBehaviorTreeSuccessResponseSchema = z.object({
|
|
9373
|
+
assetPath: z.string(),
|
|
9374
|
+
blackboardPath: z.string().optional(),
|
|
9375
|
+
message: nonEmptyStringSchema.optional(),
|
|
9376
|
+
nodeCount: z.number().int().min(0),
|
|
9377
|
+
nodes: z.array(bridgeBehaviorTreeNodeReportSchema).max(200),
|
|
9378
|
+
ok: z.literal(true),
|
|
9379
|
+
requestId: requestIdSchema,
|
|
9380
|
+
rootNodeGuid: z.string().optional(),
|
|
9381
|
+
state: aiReportStateSchema,
|
|
9382
|
+
truncated: z.boolean(),
|
|
9383
|
+
type: z.literal(BRIDGE_GET_BEHAVIOR_TREE_REQUEST_TYPE),
|
|
9384
|
+
version: z.literal(2)
|
|
9385
|
+
});
|
|
9386
|
+
const bridgeGetBtRuntimeStateRequestSchema = z.object({
|
|
9387
|
+
actorPath: assetPathSchema.optional(),
|
|
9388
|
+
maxAborts: z.number().int().min(0).max(25).default(25),
|
|
9389
|
+
requestId: requestIdSchema,
|
|
9390
|
+
type: z.literal(BRIDGE_GET_BT_RUNTIME_STATE_REQUEST_TYPE),
|
|
9391
|
+
version: z.literal(2)
|
|
9392
|
+
});
|
|
9393
|
+
const bridgeBtBlackboardValueSchema = z.object({
|
|
9394
|
+
keyName: z.string(),
|
|
9395
|
+
keyType: z.string(),
|
|
9396
|
+
value: z.string()
|
|
9397
|
+
});
|
|
9398
|
+
const bridgeBtAbortReportSchema = z.object({
|
|
9399
|
+
decoratorName: z.string(),
|
|
9400
|
+
nodeName: z.string(),
|
|
9401
|
+
timestampSeconds: z.number().min(0)
|
|
9402
|
+
});
|
|
9403
|
+
const bridgeGetBtRuntimeStateSuccessResponseSchema = z.object({
|
|
9404
|
+
activeNodePath: z.array(z.string()).max(32),
|
|
9405
|
+
actorPath: z.string().optional(),
|
|
9406
|
+
blackboard: z.array(bridgeBtBlackboardValueSchema).max(64),
|
|
9407
|
+
message: nonEmptyStringSchema.optional(),
|
|
9408
|
+
ok: z.literal(true),
|
|
9409
|
+
recentAborts: z.array(bridgeBtAbortReportSchema).max(25),
|
|
9410
|
+
requestId: requestIdSchema,
|
|
9411
|
+
state: aiRuntimeStateSchema,
|
|
9412
|
+
treePath: z.string().optional(),
|
|
9413
|
+
type: z.literal(BRIDGE_GET_BT_RUNTIME_STATE_REQUEST_TYPE),
|
|
9414
|
+
version: z.literal(2)
|
|
9415
|
+
});
|
|
9416
|
+
const bridgeGetBehaviorTreeResponseSchema = z.union([bridgeGetBehaviorTreeSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
9417
|
+
const bridgeGetBtRuntimeStateResponseSchema = z.union([bridgeGetBtRuntimeStateSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
9418
|
+
function createBridgeGetBehaviorTreeRequest(assetPath, requestId = randomUUID()) {
|
|
9419
|
+
return bridgeGetBehaviorTreeRequestSchema.parse({
|
|
9420
|
+
assetPath,
|
|
8652
9421
|
requestId,
|
|
8653
|
-
type:
|
|
9422
|
+
type: BRIDGE_GET_BEHAVIOR_TREE_REQUEST_TYPE,
|
|
8654
9423
|
version: 2
|
|
8655
9424
|
});
|
|
8656
9425
|
}
|
|
8657
|
-
function
|
|
8658
|
-
return
|
|
8659
|
-
|
|
9426
|
+
function createBridgeGetBtRuntimeStateRequest(options = {}, requestId = randomUUID()) {
|
|
9427
|
+
return bridgeGetBtRuntimeStateRequestSchema.parse({
|
|
9428
|
+
actorPath: options.actorPath,
|
|
9429
|
+
maxAborts: options.maxAborts,
|
|
8660
9430
|
requestId,
|
|
8661
|
-
|
|
8662
|
-
type: BRIDGE_ADD_BT_SERVICE_REQUEST_TYPE,
|
|
9431
|
+
type: BRIDGE_GET_BT_RUNTIME_STATE_REQUEST_TYPE,
|
|
8663
9432
|
version: 2
|
|
8664
9433
|
});
|
|
8665
9434
|
}
|
|
@@ -9715,7 +10484,7 @@ function createBridgeSetDefaultGamemodeRequest(scope, gameModePath, options = {}
|
|
|
9715
10484
|
}
|
|
9716
10485
|
//#endregion
|
|
9717
10486
|
//#region src/version.ts
|
|
9718
|
-
const SERVER_VERSION = "1.
|
|
10487
|
+
const SERVER_VERSION = "1.10.0";
|
|
9719
10488
|
//#endregion
|
|
9720
10489
|
//#region src/bridgeSocketClient.ts
|
|
9721
10490
|
var BridgeSocketError = class extends Error {
|
|
@@ -10605,6 +11374,48 @@ async function sendBridgeControlBlueprintDebuggerRequest(request, options) {
|
|
|
10605
11374
|
async function sendBridgeWatchBlueprintPinRequest(request, options) {
|
|
10606
11375
|
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeWatchBlueprintPinResponseSchema, request.requestId);
|
|
10607
11376
|
}
|
|
11377
|
+
async function sendBridgeAddStateTreeComponentRequest(request, options) {
|
|
11378
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeAddStateTreeComponentResponseSchema, request.requestId);
|
|
11379
|
+
}
|
|
11380
|
+
async function sendBridgeAddStimuliSourceRequest(request, options) {
|
|
11381
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeAddStimuliSourceResponseSchema, request.requestId);
|
|
11382
|
+
}
|
|
11383
|
+
async function sendBridgeConfigureAiPerceptionRequest(request, options) {
|
|
11384
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeConfigureAiPerceptionResponseSchema, request.requestId);
|
|
11385
|
+
}
|
|
11386
|
+
async function sendBridgeCreateAiControllerRequest(request, options) {
|
|
11387
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeCreateAiControllerResponseSchema, request.requestId);
|
|
11388
|
+
}
|
|
11389
|
+
async function sendBridgeEditEqsQueryRequest(request, options) {
|
|
11390
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeEditEqsQueryResponseSchema, request.requestId);
|
|
11391
|
+
}
|
|
11392
|
+
async function sendBridgeGetBehaviorTreeRequest(request, options) {
|
|
11393
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeGetBehaviorTreeResponseSchema, request.requestId);
|
|
11394
|
+
}
|
|
11395
|
+
async function sendBridgeGetBtRuntimeStateRequest(request, options) {
|
|
11396
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeGetBtRuntimeStateResponseSchema, request.requestId);
|
|
11397
|
+
}
|
|
11398
|
+
async function sendBridgeGetEqsQueryRequest(request, options) {
|
|
11399
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeGetEqsQueryResponseSchema, request.requestId);
|
|
11400
|
+
}
|
|
11401
|
+
async function sendBridgeGetStateTreeRequest(request, options) {
|
|
11402
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeGetStateTreeResponseSchema, request.requestId);
|
|
11403
|
+
}
|
|
11404
|
+
async function sendBridgeLinkStateTreeStateRequest(request, options) {
|
|
11405
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeLinkStateTreeStateResponseSchema, request.requestId);
|
|
11406
|
+
}
|
|
11407
|
+
async function sendBridgeRunEqsQueryRequest(request, options) {
|
|
11408
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeRunEqsQueryResponseSchema, request.requestId);
|
|
11409
|
+
}
|
|
11410
|
+
async function sendBridgeSetStateTreeConsiderationsRequest(request, options) {
|
|
11411
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeSetStateTreeConsiderationsResponseSchema, request.requestId);
|
|
11412
|
+
}
|
|
11413
|
+
async function sendBridgeSetStateTreeGlobalsRequest(request, options) {
|
|
11414
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeSetStateTreeGlobalsResponseSchema, request.requestId);
|
|
11415
|
+
}
|
|
11416
|
+
async function sendBridgeTraceStateTreeRequest(request, options) {
|
|
11417
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeTraceStateTreeResponseSchema, request.requestId);
|
|
11418
|
+
}
|
|
10608
11419
|
//#endregion
|
|
10609
11420
|
//#region src/enginePing.ts
|
|
10610
11421
|
async function pingRegistryEntry$1(entry, options) {
|
|
@@ -13677,6 +14488,24 @@ async function addBtDecorator(input, dependencies) {
|
|
|
13677
14488
|
async function addBtService(input, dependencies) {
|
|
13678
14489
|
return await exchangeCreativeRequest(createBridgeAddBtServiceRequest(input.assetPath, input.services), sendBridgeAddBtServiceRequest, BRIDGE_ADD_BT_SERVICE_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
13679
14490
|
}
|
|
14491
|
+
const getBehaviorTreeInputSchema = {
|
|
14492
|
+
assetPath: bridgeGetBehaviorTreeRequestSchema.shape.assetPath.describe("Object path of the Behavior Tree asset to read."),
|
|
14493
|
+
projectId: creativeProjectIdSchema
|
|
14494
|
+
};
|
|
14495
|
+
const getBtRuntimeStateInputSchema = {
|
|
14496
|
+
actorPath: bridgeGetBtRuntimeStateRequestSchema.shape.actorPath.describe("Actor in the PIE world to report on. Omitted reports the first AI found running a Behavior Tree."),
|
|
14497
|
+
maxAborts: bridgeGetBtRuntimeStateRequestSchema.shape.maxAborts.describe("Maximum recent aborts to return (0-25, default 25)."),
|
|
14498
|
+
projectId: creativeProjectIdSchema
|
|
14499
|
+
};
|
|
14500
|
+
async function getBehaviorTree(input, dependencies) {
|
|
14501
|
+
return await exchangeCreativeRequest(createBridgeGetBehaviorTreeRequest(input.assetPath), sendBridgeGetBehaviorTreeRequest, BRIDGE_GET_BEHAVIOR_TREE_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
14502
|
+
}
|
|
14503
|
+
async function getBtRuntimeState(input, dependencies) {
|
|
14504
|
+
return await exchangeCreativeRequest(createBridgeGetBtRuntimeStateRequest({
|
|
14505
|
+
actorPath: input.actorPath,
|
|
14506
|
+
maxAborts: input.maxAborts
|
|
14507
|
+
}), sendBridgeGetBtRuntimeStateRequest, BRIDGE_GET_BT_RUNTIME_STATE_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
14508
|
+
}
|
|
13680
14509
|
function registerBehaviorTreeTools(server, dependencies) {
|
|
13681
14510
|
server.registerTool("create_behavior_tree", {
|
|
13682
14511
|
description: "Create a Behavior Tree asset and link its blackboard. Populate it with add_bt_node, then attach decorators and services. A tree with no blackboard has nothing for the stock decorators to key off.",
|
|
@@ -13723,6 +14552,27 @@ function registerBehaviorTreeTools(server, dependencies) {
|
|
|
13723
14552
|
services
|
|
13724
14553
|
}, dependencies));
|
|
13725
14554
|
});
|
|
14555
|
+
server.registerTool("get_behavior_tree", {
|
|
14556
|
+
description: "Read a Behavior Tree back: the node hierarchy with each node's GUID, class, child index, decorators, services, property values and the blackboard keys it reads. The GUIDs are the ones add_bt_decorator and add_bt_service address nodes by, so this is the call to make before editing a tree you did not author.",
|
|
14557
|
+
inputSchema: getBehaviorTreeInputSchema,
|
|
14558
|
+
title: "Get Behavior Tree"
|
|
14559
|
+
}, async ({ assetPath, projectId }) => {
|
|
14560
|
+
return toToolSuccess(await getBehaviorTree({
|
|
14561
|
+
assetPath,
|
|
14562
|
+
projectId
|
|
14563
|
+
}, dependencies));
|
|
14564
|
+
});
|
|
14565
|
+
server.registerTool("get_bt_runtime_state", {
|
|
14566
|
+
description: "Report what an AI is actually doing in Play In Editor: the active node path from root to the running task, the live blackboard values, and recent aborts, each naming the decorator on the branch that was left whose observer could have caused it — the usual answer to a task that keeps stopping halfway. Aborts are sampled at 10 Hz rather than read from a real abort signal, so an entry is a node change under a branch carrying an observer abort, not a confirmed abort. Outside PIE the response comes back not_running rather than failing.",
|
|
14567
|
+
inputSchema: getBtRuntimeStateInputSchema,
|
|
14568
|
+
title: "Get Behavior Tree Runtime State"
|
|
14569
|
+
}, async ({ actorPath, maxAborts, projectId }) => {
|
|
14570
|
+
return toToolSuccess(await getBtRuntimeState({
|
|
14571
|
+
actorPath,
|
|
14572
|
+
maxAborts,
|
|
14573
|
+
projectId
|
|
14574
|
+
}, dependencies));
|
|
14575
|
+
});
|
|
13726
14576
|
}
|
|
13727
14577
|
const behaviorTreeToolDomain = {
|
|
13728
14578
|
domain: "behaviorTree",
|
|
@@ -13731,7 +14581,9 @@ const behaviorTreeToolDomain = {
|
|
|
13731
14581
|
"create_behavior_tree",
|
|
13732
14582
|
"add_bt_node",
|
|
13733
14583
|
"add_bt_decorator",
|
|
13734
|
-
"add_bt_service"
|
|
14584
|
+
"add_bt_service",
|
|
14585
|
+
"get_behavior_tree",
|
|
14586
|
+
"get_bt_runtime_state"
|
|
13735
14587
|
]
|
|
13736
14588
|
};
|
|
13737
14589
|
const EXEC_PIN_NAMES = /* @__PURE__ */ new Set(["execute", "then"]);
|
|
@@ -14576,72 +15428,583 @@ async function collectGraphNodes(input, graphName, dependencies) {
|
|
|
14576
15428
|
};
|
|
14577
15429
|
cursor = response.nextNodeCursor;
|
|
14578
15430
|
}
|
|
14579
|
-
return {
|
|
14580
|
-
graphKind,
|
|
14581
|
-
nodes,
|
|
14582
|
-
truncated: true
|
|
14583
|
-
};
|
|
15431
|
+
return {
|
|
15432
|
+
graphKind,
|
|
15433
|
+
nodes,
|
|
15434
|
+
truncated: true
|
|
15435
|
+
};
|
|
15436
|
+
}
|
|
15437
|
+
async function exportBlueprintCpp(input, dependencies) {
|
|
15438
|
+
const { summary, truncated: summaryTruncated } = await collectBlueprintSummary(input, dependencies);
|
|
15439
|
+
const selected = input.graphName === void 0 ? summary.graphs.slice(0, input.maxGraphs) : summary.graphs.filter((graph) => graph.name === input.graphName);
|
|
15440
|
+
if (input.graphName !== void 0 && selected.length === 0) throw new Error(`Blueprint '${summary.blueprintPath}' has no graph named '${input.graphName}'.`);
|
|
15441
|
+
const rendered = [];
|
|
15442
|
+
let truncated = summaryTruncated || input.graphName === void 0 && selected.length < summary.graphs.length;
|
|
15443
|
+
for (const graph of selected) {
|
|
15444
|
+
const { graphKind, nodes, truncated: graphTruncated } = await collectGraphNodes(input, graph.name, dependencies);
|
|
15445
|
+
const pseudoCode = renderGraphPseudoCode({
|
|
15446
|
+
graphKind,
|
|
15447
|
+
graphName: graph.name,
|
|
15448
|
+
nodes,
|
|
15449
|
+
truncated: graphTruncated
|
|
15450
|
+
});
|
|
15451
|
+
truncated = truncated || pseudoCode.truncated;
|
|
15452
|
+
rendered.push(pseudoCode);
|
|
15453
|
+
}
|
|
15454
|
+
const skeleton = renderCppSkeleton({
|
|
15455
|
+
blueprintName: summary.blueprintName,
|
|
15456
|
+
functions: summary.functions,
|
|
15457
|
+
interfaces: summary.interfaces,
|
|
15458
|
+
...summary.parentClass === void 0 ? {} : { parentClass: summary.parentClass },
|
|
15459
|
+
variables: summary.variables
|
|
15460
|
+
});
|
|
15461
|
+
dependencies.logger.info({
|
|
15462
|
+
blueprintPath: summary.blueprintPath,
|
|
15463
|
+
graphCount: rendered.length,
|
|
15464
|
+
projectId: summary.projectId
|
|
15465
|
+
}, "Exported Blueprint graphs as pseudo-code");
|
|
15466
|
+
return {
|
|
15467
|
+
blueprintName: summary.blueprintName,
|
|
15468
|
+
blueprintPath: summary.blueprintPath,
|
|
15469
|
+
graphs: rendered,
|
|
15470
|
+
projectId: summary.projectId,
|
|
15471
|
+
pseudoCode: rendered.map((graph) => [`// ${graph.graphName} (${graph.graphKind})`, ...graph.lines].join("\n")).join("\n\n"),
|
|
15472
|
+
skeleton,
|
|
15473
|
+
truncated
|
|
15474
|
+
};
|
|
15475
|
+
}
|
|
15476
|
+
const blueprintToolDomain = {
|
|
15477
|
+
domain: "blueprint",
|
|
15478
|
+
register: registerBlueprintTools,
|
|
15479
|
+
toolNames: [
|
|
15480
|
+
"find_blueprint_references",
|
|
15481
|
+
"get_blueprint_summary",
|
|
15482
|
+
"get_blueprint_graph",
|
|
15483
|
+
"get_blueprint_compile_errors",
|
|
15484
|
+
"compile_blueprint",
|
|
15485
|
+
"get_blueprint_compile_status",
|
|
15486
|
+
"create_blueprint",
|
|
15487
|
+
"add_bp_variable",
|
|
15488
|
+
"add_bp_function",
|
|
15489
|
+
"add_bp_event",
|
|
15490
|
+
"add_bp_component",
|
|
15491
|
+
"add_bp_interface",
|
|
15492
|
+
"set_bp_default",
|
|
15493
|
+
"batch_edit",
|
|
15494
|
+
"export_blueprint_cpp"
|
|
15495
|
+
]
|
|
15496
|
+
};
|
|
15497
|
+
//#endregion
|
|
15498
|
+
//#region src/aiScaffold.ts
|
|
15499
|
+
const AI_NODE_KINDS = [
|
|
15500
|
+
"state_tree_task",
|
|
15501
|
+
"state_tree_condition",
|
|
15502
|
+
"state_tree_evaluator",
|
|
15503
|
+
"bt_task",
|
|
15504
|
+
"bt_decorator",
|
|
15505
|
+
"bt_service",
|
|
15506
|
+
"eqs_generator",
|
|
15507
|
+
"eqs_test"
|
|
15508
|
+
];
|
|
15509
|
+
const TEAM_AGENT_CLASS_KINDS = [
|
|
15510
|
+
"controller",
|
|
15511
|
+
"character",
|
|
15512
|
+
"attitude_solver"
|
|
15513
|
+
];
|
|
15514
|
+
const CLASS_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9_]*$/;
|
|
15515
|
+
const CLASS_NAME_MAX_LENGTH = 96;
|
|
15516
|
+
const SUPPORTED_DESCRIPTOR_EXTENSIONS$1 = [".uproject", ".uplugin"];
|
|
15517
|
+
const NODE_KIND_DEPENDENCIES = {
|
|
15518
|
+
bt_decorator: ["AIModule", "GameplayTasks"],
|
|
15519
|
+
bt_service: ["AIModule", "GameplayTasks"],
|
|
15520
|
+
bt_task: ["AIModule", "GameplayTasks"],
|
|
15521
|
+
eqs_generator: ["AIModule", "GameplayTasks"],
|
|
15522
|
+
eqs_test: ["AIModule", "GameplayTasks"],
|
|
15523
|
+
state_tree_condition: ["StateTreeModule"],
|
|
15524
|
+
state_tree_evaluator: ["StateTreeModule"],
|
|
15525
|
+
state_tree_task: ["StateTreeModule"]
|
|
15526
|
+
};
|
|
15527
|
+
const TEAM_AGENT_DEPENDENCIES = ["AIModule", "GameplayTasks"];
|
|
15528
|
+
async function scaffoldAiNodeClass(input) {
|
|
15529
|
+
const className = input.className.trim();
|
|
15530
|
+
validateIdentifier(className, "Class name");
|
|
15531
|
+
const moduleName = input.moduleName.trim();
|
|
15532
|
+
validateIdentifier(moduleName, "Module name");
|
|
15533
|
+
const descriptorPath = path.resolve(input.descriptorPath.trim());
|
|
15534
|
+
validateDescriptorExtension$1(descriptorPath);
|
|
15535
|
+
await assertModuleRegistered(descriptorPath, moduleName);
|
|
15536
|
+
const moduleRoot = path.join(path.dirname(descriptorPath), "Source", moduleName);
|
|
15537
|
+
await assertModuleRootExists(moduleRoot, moduleName);
|
|
15538
|
+
const typeName = buildNodeTypeName(input.nodeKind, className);
|
|
15539
|
+
const fileStem = typeName.startsWith("F") || typeName.startsWith("U") ? typeName.slice(1) : typeName;
|
|
15540
|
+
const headerPath = path.join(moduleRoot, "Public", `${fileStem}.h`);
|
|
15541
|
+
const sourcePath = path.join(moduleRoot, "Private", `${fileStem}.cpp`);
|
|
15542
|
+
await assertFilesAbsent([headerPath, sourcePath]);
|
|
15543
|
+
const displayName = (input.displayName ?? className).trim();
|
|
15544
|
+
const apiMacro = `${moduleName.toUpperCase()}_API`;
|
|
15545
|
+
const header = renderNodeHeader(input.nodeKind, typeName, fileStem, displayName, apiMacro);
|
|
15546
|
+
const source = renderNodeSource(input.nodeKind, typeName, fileStem);
|
|
15547
|
+
const createdFiles = await writeGeneratedFiles([{
|
|
15548
|
+
contents: header,
|
|
15549
|
+
filePath: headerPath
|
|
15550
|
+
}, {
|
|
15551
|
+
contents: source,
|
|
15552
|
+
filePath: sourcePath
|
|
15553
|
+
}]);
|
|
15554
|
+
const requiredModuleDependencies = NODE_KIND_DEPENDENCIES[input.nodeKind];
|
|
15555
|
+
const buildCsPath = path.join(moduleRoot, `${moduleName}.Build.cs`);
|
|
15556
|
+
return {
|
|
15557
|
+
buildCsPath,
|
|
15558
|
+
buildCsUpdated: input.updateBuildCs === false ? false : await tryAddBuildDependencies(buildCsPath, requiredModuleDependencies),
|
|
15559
|
+
createdFiles,
|
|
15560
|
+
descriptorPath,
|
|
15561
|
+
generatedTypes: [typeName],
|
|
15562
|
+
moduleName,
|
|
15563
|
+
moduleRoot,
|
|
15564
|
+
requiredModuleDependencies
|
|
15565
|
+
};
|
|
15566
|
+
}
|
|
15567
|
+
async function scaffoldTeamAgentClass(input) {
|
|
15568
|
+
const classPrefix = input.classPrefix.trim();
|
|
15569
|
+
validateIdentifier(classPrefix, "Class prefix");
|
|
15570
|
+
const moduleName = input.moduleName.trim();
|
|
15571
|
+
validateIdentifier(moduleName, "Module name");
|
|
15572
|
+
if (input.classKinds.length === 0) throw new ModuleScaffoldError("At least one classKind must be requested.");
|
|
15573
|
+
const defaultTeamId = input.defaultTeamId ?? 1;
|
|
15574
|
+
if (!Number.isInteger(defaultTeamId) || defaultTeamId < 0 || defaultTeamId > 255) throw new ModuleScaffoldError(`Team id ${String(defaultTeamId)} is outside the 0-255 range FGenericTeamId holds.`);
|
|
15575
|
+
const descriptorPath = path.resolve(input.descriptorPath.trim());
|
|
15576
|
+
validateDescriptorExtension$1(descriptorPath);
|
|
15577
|
+
await assertModuleRegistered(descriptorPath, moduleName);
|
|
15578
|
+
const moduleRoot = path.join(path.dirname(descriptorPath), "Source", moduleName);
|
|
15579
|
+
await assertModuleRootExists(moduleRoot, moduleName);
|
|
15580
|
+
const apiMacro = `${moduleName.toUpperCase()}_API`;
|
|
15581
|
+
const pending = [];
|
|
15582
|
+
const generatedTypes = [];
|
|
15583
|
+
for (const classKind of [...new Set(input.classKinds)]) {
|
|
15584
|
+
const fileStem = buildTeamAgentFileStem(classKind, classPrefix);
|
|
15585
|
+
const typeName = buildTeamAgentTypeName(classKind, classPrefix);
|
|
15586
|
+
generatedTypes.push(typeName);
|
|
15587
|
+
pending.push({
|
|
15588
|
+
contents: renderTeamAgentHeader(classKind, classPrefix, fileStem, apiMacro, defaultTeamId),
|
|
15589
|
+
filePath: path.join(moduleRoot, "Public", `${fileStem}.h`)
|
|
15590
|
+
});
|
|
15591
|
+
pending.push({
|
|
15592
|
+
contents: renderTeamAgentSource(classKind, classPrefix, fileStem, defaultTeamId),
|
|
15593
|
+
filePath: path.join(moduleRoot, "Private", `${fileStem}.cpp`)
|
|
15594
|
+
});
|
|
15595
|
+
}
|
|
15596
|
+
await assertFilesAbsent(pending.map((file) => file.filePath));
|
|
15597
|
+
const createdFiles = await writeGeneratedFiles(pending);
|
|
15598
|
+
const buildCsPath = path.join(moduleRoot, `${moduleName}.Build.cs`);
|
|
15599
|
+
return {
|
|
15600
|
+
buildCsPath,
|
|
15601
|
+
buildCsUpdated: input.updateBuildCs === false ? false : await tryAddBuildDependencies(buildCsPath, TEAM_AGENT_DEPENDENCIES),
|
|
15602
|
+
createdFiles,
|
|
15603
|
+
descriptorPath,
|
|
15604
|
+
generatedTypes,
|
|
15605
|
+
moduleName,
|
|
15606
|
+
moduleRoot,
|
|
15607
|
+
requiredModuleDependencies: TEAM_AGENT_DEPENDENCIES
|
|
15608
|
+
};
|
|
15609
|
+
}
|
|
15610
|
+
function validateIdentifier(value, label) {
|
|
15611
|
+
if (value.length === 0) throw new ModuleScaffoldError(`${label} cannot be empty.`);
|
|
15612
|
+
if (value.length > CLASS_NAME_MAX_LENGTH) throw new ModuleScaffoldError(`${label} '${value}' exceeds ${String(CLASS_NAME_MAX_LENGTH)} characters.`);
|
|
15613
|
+
if (!CLASS_NAME_PATTERN.test(value)) throw new ModuleScaffoldError(`${label} '${value}' must be a valid C++ identifier (letters, digits and underscores, starting with a letter).`);
|
|
15614
|
+
}
|
|
15615
|
+
function validateDescriptorExtension$1(descriptorPath) {
|
|
15616
|
+
if (!SUPPORTED_DESCRIPTOR_EXTENSIONS$1.includes(path.extname(descriptorPath).toLowerCase())) throw new ModuleScaffoldError(`Descriptor path must end in .uproject or .uplugin, got '${descriptorPath}'.`);
|
|
15617
|
+
}
|
|
15618
|
+
async function assertModuleRegistered(descriptorPath, moduleName) {
|
|
15619
|
+
let descriptorText;
|
|
15620
|
+
try {
|
|
15621
|
+
descriptorText = await readFile(descriptorPath, "utf8");
|
|
15622
|
+
} catch (error) {
|
|
15623
|
+
if (getErrorCode$1(error) === "ENOENT") throw new ModuleScaffoldError(`Descriptor not found at ${descriptorPath}.`);
|
|
15624
|
+
throw error;
|
|
15625
|
+
}
|
|
15626
|
+
let parsed;
|
|
15627
|
+
try {
|
|
15628
|
+
parsed = JSON.parse(descriptorText);
|
|
15629
|
+
} catch (error) {
|
|
15630
|
+
throw new ModuleScaffoldError(`Descriptor at ${descriptorPath} is not valid JSON.`, { cause: error });
|
|
15631
|
+
}
|
|
15632
|
+
const modules = isPlainObject$1(parsed) ? parsed.Modules : void 0;
|
|
15633
|
+
if (!(Array.isArray(modules) && modules.some((entry) => isPlainObject$1(entry) && typeof entry.Name === "string" && entry.Name.toLowerCase() === moduleName.toLowerCase()))) throw new ModuleScaffoldError(`Module '${moduleName}' is not registered in ${descriptorPath}; add it with add_module first.`);
|
|
15634
|
+
}
|
|
15635
|
+
async function assertModuleRootExists(moduleRoot, moduleName) {
|
|
15636
|
+
try {
|
|
15637
|
+
await stat(moduleRoot);
|
|
15638
|
+
} catch (error) {
|
|
15639
|
+
if (getErrorCode$1(error) === "ENOENT") throw new ModuleScaffoldError(`Module source directory for '${moduleName}' was not found at ${moduleRoot}.`);
|
|
15640
|
+
throw error;
|
|
15641
|
+
}
|
|
15642
|
+
}
|
|
15643
|
+
async function assertFilesAbsent(filePaths) {
|
|
15644
|
+
for (const filePath of filePaths) {
|
|
15645
|
+
try {
|
|
15646
|
+
await stat(filePath);
|
|
15647
|
+
} catch (error) {
|
|
15648
|
+
if (getErrorCode$1(error) === "ENOENT") continue;
|
|
15649
|
+
throw error;
|
|
15650
|
+
}
|
|
15651
|
+
throw new ModuleScaffoldError(`${filePath} already exists; refusing to overwrite it.`);
|
|
15652
|
+
}
|
|
15653
|
+
}
|
|
15654
|
+
async function writeGeneratedFiles(files) {
|
|
15655
|
+
const written = [];
|
|
15656
|
+
try {
|
|
15657
|
+
for (const file of files) {
|
|
15658
|
+
await mkdir(path.dirname(file.filePath), { recursive: true });
|
|
15659
|
+
await writeFile(file.filePath, file.contents, "utf8");
|
|
15660
|
+
written.push(file.filePath);
|
|
15661
|
+
}
|
|
15662
|
+
} catch (error) {
|
|
15663
|
+
for (const filePath of written) await rm(filePath, { force: true });
|
|
15664
|
+
throw error;
|
|
15665
|
+
}
|
|
15666
|
+
return written;
|
|
15667
|
+
}
|
|
15668
|
+
async function tryAddBuildDependencies(buildCsPath, moduleNames) {
|
|
15669
|
+
let buildCsText;
|
|
15670
|
+
try {
|
|
15671
|
+
buildCsText = await readFile(buildCsPath, "utf8");
|
|
15672
|
+
} catch (error) {
|
|
15673
|
+
if (getErrorCode$1(error) === "ENOENT") return false;
|
|
15674
|
+
throw error;
|
|
15675
|
+
}
|
|
15676
|
+
const addRangeIndex = buildCsText.indexOf("PrivateDependencyModuleNames.AddRange");
|
|
15677
|
+
if (addRangeIndex < 0) return false;
|
|
15678
|
+
const statementEnd = buildCsText.indexOf(";", addRangeIndex);
|
|
15679
|
+
const openBrace = buildCsText.indexOf("{", addRangeIndex);
|
|
15680
|
+
const closeBrace = openBrace < 0 ? -1 : buildCsText.indexOf("}", openBrace);
|
|
15681
|
+
if (statementEnd < 0 || openBrace < 0 || closeBrace < 0 || openBrace > statementEnd) return false;
|
|
15682
|
+
const body = buildCsText.slice(openBrace + 1, closeBrace);
|
|
15683
|
+
const existing = new Set(Array.from(body.matchAll(/"([^"]+)"/g), (match) => match[1] ?? ""));
|
|
15684
|
+
const missing = moduleNames.filter((moduleName) => !existing.has(moduleName));
|
|
15685
|
+
if (missing.length === 0) return true;
|
|
15686
|
+
const hasEntries = existing.size > 0;
|
|
15687
|
+
const additions = missing.map((moduleName) => ` "${moduleName}"`).join(",\n");
|
|
15688
|
+
const separator = hasEntries ? ",\n" : "\n";
|
|
15689
|
+
const nextBody = `${body.replace(/\s+$/, "")}${separator}${additions}\n `;
|
|
15690
|
+
await writeFile(buildCsPath, `${buildCsText.slice(0, openBrace + 1)}${nextBody}${buildCsText.slice(closeBrace)}`, "utf8");
|
|
15691
|
+
return true;
|
|
15692
|
+
}
|
|
15693
|
+
function buildNodeTypeName(nodeKind, className) {
|
|
15694
|
+
switch (nodeKind) {
|
|
15695
|
+
case "state_tree_task": return `F${className}Task`;
|
|
15696
|
+
case "state_tree_condition": return `F${className}Condition`;
|
|
15697
|
+
case "state_tree_evaluator": return `F${className}Evaluator`;
|
|
15698
|
+
case "bt_task": return `UBTTask_${className}`;
|
|
15699
|
+
case "bt_decorator": return `UBTDecorator_${className}`;
|
|
15700
|
+
case "bt_service": return `UBTService_${className}`;
|
|
15701
|
+
case "eqs_generator": return `UEnvQueryGenerator_${className}`;
|
|
15702
|
+
default: return `UEnvQueryTest_${className}`;
|
|
15703
|
+
}
|
|
15704
|
+
}
|
|
15705
|
+
function isStateTreeNode(nodeKind) {
|
|
15706
|
+
return nodeKind.startsWith("state_tree_");
|
|
15707
|
+
}
|
|
15708
|
+
function renderNodeHeader(nodeKind, typeName, fileStem, displayName, apiMacro) {
|
|
15709
|
+
if (isStateTreeNode(nodeKind)) return renderStateTreeNodeHeader(nodeKind, typeName, fileStem, displayName, apiMacro);
|
|
15710
|
+
return renderObjectNodeHeader(nodeKind, typeName, fileStem, displayName, apiMacro);
|
|
15711
|
+
}
|
|
15712
|
+
function renderStateTreeNodeHeader(nodeKind, typeName, fileStem, displayName, apiMacro) {
|
|
15713
|
+
const instanceDataType = `${typeName}InstanceData`;
|
|
15714
|
+
return `#pragma once
|
|
15715
|
+
|
|
15716
|
+
#include "CoreMinimal.h"
|
|
15717
|
+
|
|
15718
|
+
#include "StateTreeExecutionContext.h"
|
|
15719
|
+
#include "${nodeKind === "state_tree_task" ? "StateTreeTaskBase.h" : nodeKind === "state_tree_condition" ? "StateTreeConditionBase.h" : "StateTreeEvaluatorBase.h"}"
|
|
15720
|
+
|
|
15721
|
+
#include "${fileStem}.generated.h"
|
|
15722
|
+
|
|
15723
|
+
// Per-run state for ${typeName}. A StateTree node is stateless — the tree hands it this struct — so
|
|
15724
|
+
// anything the node needs between ticks belongs here rather than on the node itself.
|
|
15725
|
+
USTRUCT()
|
|
15726
|
+
struct ${instanceDataType}
|
|
15727
|
+
{
|
|
15728
|
+
GENERATED_BODY()
|
|
15729
|
+
};
|
|
15730
|
+
|
|
15731
|
+
USTRUCT(meta = (DisplayName = "${displayName}", Category = "AI"))
|
|
15732
|
+
struct ${apiMacro} ${typeName} : public ${nodeKind === "state_tree_task" ? "FStateTreeTaskCommonBase" : nodeKind === "state_tree_condition" ? "FStateTreeConditionCommonBase" : "FStateTreeEvaluatorCommonBase"}
|
|
15733
|
+
{
|
|
15734
|
+
GENERATED_BODY()
|
|
15735
|
+
|
|
15736
|
+
using FInstanceDataType = ${instanceDataType};
|
|
15737
|
+
|
|
15738
|
+
virtual const UStruct* GetInstanceDataType() const override
|
|
15739
|
+
{
|
|
15740
|
+
return FInstanceDataType::StaticStruct();
|
|
15741
|
+
}
|
|
15742
|
+
${nodeKind === "state_tree_task" ? `
|
|
15743
|
+
virtual EStateTreeRunStatus EnterState(
|
|
15744
|
+
FStateTreeExecutionContext& Context,
|
|
15745
|
+
const FStateTreeTransitionResult& Transition
|
|
15746
|
+
) const override;
|
|
15747
|
+
|
|
15748
|
+
virtual EStateTreeRunStatus Tick(FStateTreeExecutionContext& Context, const float DeltaTime) const override;
|
|
15749
|
+
` : nodeKind === "state_tree_condition" ? `
|
|
15750
|
+
virtual bool TestCondition(FStateTreeExecutionContext& Context) const override;
|
|
15751
|
+
` : `
|
|
15752
|
+
virtual void Tick(FStateTreeExecutionContext& Context, const float DeltaTime) const override;
|
|
15753
|
+
`}};
|
|
15754
|
+
`;
|
|
15755
|
+
}
|
|
15756
|
+
function renderObjectNodeHeader(nodeKind, typeName, fileStem, displayName, apiMacro) {
|
|
15757
|
+
return `#pragma once
|
|
15758
|
+
|
|
15759
|
+
#include "CoreMinimal.h"
|
|
15760
|
+
|
|
15761
|
+
#include "${nodeKind === "bt_task" ? "BehaviorTree/BTTaskNode.h" : nodeKind === "bt_decorator" ? "BehaviorTree/BTDecorator.h" : nodeKind === "bt_service" ? "BehaviorTree/BTService.h" : nodeKind === "eqs_generator" ? "EnvironmentQuery/EnvQueryGenerator.h" : "EnvironmentQuery/EnvQueryTest.h"}"
|
|
15762
|
+
|
|
15763
|
+
#include "${fileStem}.generated.h"
|
|
15764
|
+
|
|
15765
|
+
UCLASS(meta = (DisplayName = "${displayName}"))
|
|
15766
|
+
class ${apiMacro} ${typeName} : public ${nodeKind === "bt_task" ? "UBTTaskNode" : nodeKind === "bt_decorator" ? "UBTDecorator" : nodeKind === "bt_service" ? "UBTService" : nodeKind === "eqs_generator" ? "UEnvQueryGenerator" : "UEnvQueryTest"}
|
|
15767
|
+
{
|
|
15768
|
+
GENERATED_BODY()
|
|
15769
|
+
|
|
15770
|
+
public:
|
|
15771
|
+
${typeName}();
|
|
15772
|
+
${nodeKind === "bt_task" ? `
|
|
15773
|
+
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
|
|
15774
|
+
` : nodeKind === "bt_decorator" ? `
|
|
15775
|
+
protected:
|
|
15776
|
+
virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override;
|
|
15777
|
+
` : nodeKind === "bt_service" ? `
|
|
15778
|
+
protected:
|
|
15779
|
+
virtual void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override;
|
|
15780
|
+
` : nodeKind === "eqs_generator" ? `
|
|
15781
|
+
virtual void GenerateItems(FEnvQueryInstance& QueryInstance) const override;
|
|
15782
|
+
virtual FText GetDescriptionTitle() const override;
|
|
15783
|
+
` : `
|
|
15784
|
+
virtual void RunTest(FEnvQueryInstance& QueryInstance) const override;
|
|
15785
|
+
virtual FText GetDescriptionTitle() const override;
|
|
15786
|
+
`}};
|
|
15787
|
+
`;
|
|
15788
|
+
}
|
|
15789
|
+
function renderNodeSource(nodeKind, typeName, fileStem) {
|
|
15790
|
+
switch (nodeKind) {
|
|
15791
|
+
case "state_tree_task": return `#include "${fileStem}.h"
|
|
15792
|
+
|
|
15793
|
+
EStateTreeRunStatus ${typeName}::EnterState(
|
|
15794
|
+
FStateTreeExecutionContext& Context,
|
|
15795
|
+
const FStateTreeTransitionResult& Transition
|
|
15796
|
+
) const
|
|
15797
|
+
{
|
|
15798
|
+
// Returning Running keeps the state alive until Tick decides otherwise; return Succeeded here for
|
|
15799
|
+
// a task that does its whole job on entry.
|
|
15800
|
+
return EStateTreeRunStatus::Running;
|
|
15801
|
+
}
|
|
15802
|
+
|
|
15803
|
+
EStateTreeRunStatus ${typeName}::Tick(FStateTreeExecutionContext& Context, const float DeltaTime) const
|
|
15804
|
+
{
|
|
15805
|
+
return EStateTreeRunStatus::Running;
|
|
15806
|
+
}
|
|
15807
|
+
`;
|
|
15808
|
+
case "state_tree_condition": return `#include "${fileStem}.h"
|
|
15809
|
+
|
|
15810
|
+
bool ${typeName}::TestCondition(FStateTreeExecutionContext& Context) const
|
|
15811
|
+
{
|
|
15812
|
+
return true;
|
|
15813
|
+
}
|
|
15814
|
+
`;
|
|
15815
|
+
case "state_tree_evaluator": return `#include "${fileStem}.h"
|
|
15816
|
+
|
|
15817
|
+
void ${typeName}::Tick(FStateTreeExecutionContext& Context, const float DeltaTime) const
|
|
15818
|
+
{
|
|
15819
|
+
}
|
|
15820
|
+
`;
|
|
15821
|
+
case "bt_task": return `#include "${fileStem}.h"
|
|
15822
|
+
|
|
15823
|
+
${typeName}::${typeName}()
|
|
15824
|
+
{
|
|
15825
|
+
NodeName = TEXT("${typeName}");
|
|
15826
|
+
}
|
|
15827
|
+
|
|
15828
|
+
EBTNodeResult::Type ${typeName}::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
|
|
15829
|
+
{
|
|
15830
|
+
return EBTNodeResult::Succeeded;
|
|
15831
|
+
}
|
|
15832
|
+
`;
|
|
15833
|
+
case "bt_decorator": return `#include "${fileStem}.h"
|
|
15834
|
+
|
|
15835
|
+
${typeName}::${typeName}()
|
|
15836
|
+
{
|
|
15837
|
+
NodeName = TEXT("${typeName}");
|
|
15838
|
+
}
|
|
15839
|
+
|
|
15840
|
+
bool ${typeName}::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const
|
|
15841
|
+
{
|
|
15842
|
+
return true;
|
|
15843
|
+
}
|
|
15844
|
+
`;
|
|
15845
|
+
case "bt_service": return `#include "${fileStem}.h"
|
|
15846
|
+
|
|
15847
|
+
${typeName}::${typeName}()
|
|
15848
|
+
{
|
|
15849
|
+
NodeName = TEXT("${typeName}");
|
|
15850
|
+
bNotifyTick = true;
|
|
15851
|
+
}
|
|
15852
|
+
|
|
15853
|
+
void ${typeName}::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
|
|
15854
|
+
{
|
|
15855
|
+
Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds);
|
|
15856
|
+
}
|
|
15857
|
+
`;
|
|
15858
|
+
case "eqs_generator": return `#include "${fileStem}.h"
|
|
15859
|
+
|
|
15860
|
+
#include "EnvironmentQuery/Items/EnvQueryItemType_Point.h"
|
|
15861
|
+
|
|
15862
|
+
${typeName}::${typeName}()
|
|
15863
|
+
{
|
|
15864
|
+
// Without an item type the query has nothing to score and every test silently rejects its items.
|
|
15865
|
+
ItemType = UEnvQueryItemType_Point::StaticClass();
|
|
15866
|
+
}
|
|
15867
|
+
|
|
15868
|
+
void ${typeName}::GenerateItems(FEnvQueryInstance& QueryInstance) const
|
|
15869
|
+
{
|
|
15870
|
+
}
|
|
15871
|
+
|
|
15872
|
+
FText ${typeName}::GetDescriptionTitle() const
|
|
15873
|
+
{
|
|
15874
|
+
return FText::FromString(TEXT("${typeName}"));
|
|
15875
|
+
}
|
|
15876
|
+
`;
|
|
15877
|
+
default: return `#include "${fileStem}.h"
|
|
15878
|
+
|
|
15879
|
+
#include "EnvironmentQuery/Items/EnvQueryItemType_Point.h"
|
|
15880
|
+
|
|
15881
|
+
${typeName}::${typeName}()
|
|
15882
|
+
{
|
|
15883
|
+
// Restricting the test to the item types it can actually read keeps it out of the picker for a
|
|
15884
|
+
// query whose generator produces something else.
|
|
15885
|
+
ValidItemType = UEnvQueryItemType_Point::StaticClass();
|
|
15886
|
+
}
|
|
15887
|
+
|
|
15888
|
+
void ${typeName}::RunTest(FEnvQueryInstance& QueryInstance) const
|
|
15889
|
+
{
|
|
15890
|
+
}
|
|
15891
|
+
|
|
15892
|
+
FText ${typeName}::GetDescriptionTitle() const
|
|
15893
|
+
{
|
|
15894
|
+
return FText::FromString(TEXT("${typeName}"));
|
|
15895
|
+
}
|
|
15896
|
+
`;
|
|
15897
|
+
}
|
|
14584
15898
|
}
|
|
14585
|
-
|
|
14586
|
-
|
|
14587
|
-
|
|
14588
|
-
|
|
14589
|
-
|
|
14590
|
-
let truncated = summaryTruncated || input.graphName === void 0 && selected.length < summary.graphs.length;
|
|
14591
|
-
for (const graph of selected) {
|
|
14592
|
-
const { graphKind, nodes, truncated: graphTruncated } = await collectGraphNodes(input, graph.name, dependencies);
|
|
14593
|
-
const pseudoCode = renderGraphPseudoCode({
|
|
14594
|
-
graphKind,
|
|
14595
|
-
graphName: graph.name,
|
|
14596
|
-
nodes,
|
|
14597
|
-
truncated: graphTruncated
|
|
14598
|
-
});
|
|
14599
|
-
truncated = truncated || pseudoCode.truncated;
|
|
14600
|
-
rendered.push(pseudoCode);
|
|
15899
|
+
function buildTeamAgentTypeName(classKind, classPrefix) {
|
|
15900
|
+
switch (classKind) {
|
|
15901
|
+
case "controller": return `A${classPrefix}AIController`;
|
|
15902
|
+
case "character": return `A${classPrefix}Character`;
|
|
15903
|
+
default: return `F${classPrefix}TeamAttitudeSolver`;
|
|
14601
15904
|
}
|
|
14602
|
-
const skeleton = renderCppSkeleton({
|
|
14603
|
-
blueprintName: summary.blueprintName,
|
|
14604
|
-
functions: summary.functions,
|
|
14605
|
-
interfaces: summary.interfaces,
|
|
14606
|
-
...summary.parentClass === void 0 ? {} : { parentClass: summary.parentClass },
|
|
14607
|
-
variables: summary.variables
|
|
14608
|
-
});
|
|
14609
|
-
dependencies.logger.info({
|
|
14610
|
-
blueprintPath: summary.blueprintPath,
|
|
14611
|
-
graphCount: rendered.length,
|
|
14612
|
-
projectId: summary.projectId
|
|
14613
|
-
}, "Exported Blueprint graphs as pseudo-code");
|
|
14614
|
-
return {
|
|
14615
|
-
blueprintName: summary.blueprintName,
|
|
14616
|
-
blueprintPath: summary.blueprintPath,
|
|
14617
|
-
graphs: rendered,
|
|
14618
|
-
projectId: summary.projectId,
|
|
14619
|
-
pseudoCode: rendered.map((graph) => [`// ${graph.graphName} (${graph.graphKind})`, ...graph.lines].join("\n")).join("\n\n"),
|
|
14620
|
-
skeleton,
|
|
14621
|
-
truncated
|
|
14622
|
-
};
|
|
14623
15905
|
}
|
|
14624
|
-
|
|
14625
|
-
|
|
14626
|
-
|
|
14627
|
-
|
|
14628
|
-
|
|
14629
|
-
|
|
14630
|
-
|
|
14631
|
-
|
|
14632
|
-
|
|
14633
|
-
|
|
14634
|
-
|
|
14635
|
-
|
|
14636
|
-
|
|
14637
|
-
|
|
14638
|
-
|
|
14639
|
-
|
|
14640
|
-
|
|
14641
|
-
|
|
14642
|
-
|
|
14643
|
-
|
|
15906
|
+
function buildTeamAgentFileStem(classKind, classPrefix) {
|
|
15907
|
+
switch (classKind) {
|
|
15908
|
+
case "controller": return `${classPrefix}AIController`;
|
|
15909
|
+
case "character": return `${classPrefix}Character`;
|
|
15910
|
+
default: return `${classPrefix}TeamAttitudeSolver`;
|
|
15911
|
+
}
|
|
15912
|
+
}
|
|
15913
|
+
function renderTeamAgentHeader(classKind, classPrefix, fileStem, apiMacro, defaultTeamId) {
|
|
15914
|
+
if (classKind === "attitude_solver") return `#pragma once
|
|
15915
|
+
|
|
15916
|
+
#include "CoreMinimal.h"
|
|
15917
|
+
|
|
15918
|
+
#include "GenericTeamAgentInterface.h"
|
|
15919
|
+
|
|
15920
|
+
// The attitude solver decides what every team id means to every other one. It is a single global
|
|
15921
|
+
// hook — FGenericTeamId::SetAttitudeSolver — so it is registered once at module startup and never
|
|
15922
|
+
// per actor; until it is registered, AI perception treats every non-matching id as hostile.
|
|
15923
|
+
struct ${apiMacro} F${classPrefix}TeamAttitudeSolver
|
|
15924
|
+
{
|
|
15925
|
+
static ETeamAttitude::Type Solve(FGenericTeamId Lhs, FGenericTeamId Rhs);
|
|
15926
|
+
|
|
15927
|
+
// Call from your module's StartupModule.
|
|
15928
|
+
static void Register();
|
|
15929
|
+
};
|
|
15930
|
+
`;
|
|
15931
|
+
const includeLine = classKind === "controller" ? "#include \"AIController.h\"" : "#include \"GameFramework/Character.h\"";
|
|
15932
|
+
const baseClass = classKind === "controller" ? "AAIController" : "ACharacter";
|
|
15933
|
+
const typeName = buildTeamAgentTypeName(classKind, classPrefix);
|
|
15934
|
+
return `#pragma once
|
|
15935
|
+
|
|
15936
|
+
#include "CoreMinimal.h"
|
|
15937
|
+
|
|
15938
|
+
${includeLine}
|
|
15939
|
+
#include "GenericTeamAgentInterface.h"
|
|
15940
|
+
|
|
15941
|
+
#include "${fileStem}.generated.h"
|
|
15942
|
+
|
|
15943
|
+
UCLASS()
|
|
15944
|
+
class ${apiMacro} ${typeName} : public ${baseClass}${classKind === "controller" ? "" : ", public IGenericTeamAgentInterface"}
|
|
15945
|
+
{
|
|
15946
|
+
GENERATED_BODY()
|
|
15947
|
+
|
|
15948
|
+
public:
|
|
15949
|
+
${typeName}();
|
|
15950
|
+
|
|
15951
|
+
// Both halves of IGenericTeamAgentInterface. Perception asks for the id through the interface, so
|
|
15952
|
+
// an actor that only stores a team without answering here is still treated as having none.
|
|
15953
|
+
virtual FGenericTeamId GetGenericTeamId() const override;
|
|
15954
|
+
virtual void SetGenericTeamId(const FGenericTeamId& NewTeamId) override;
|
|
15955
|
+
|
|
15956
|
+
protected:
|
|
15957
|
+
// ${String(defaultTeamId)} by default; 255 is FGenericTeamId::NoTeam, which every attitude solver reads as neutral.
|
|
15958
|
+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Team")
|
|
15959
|
+
uint8 TeamId = ${String(defaultTeamId)};
|
|
14644
15960
|
};
|
|
15961
|
+
`;
|
|
15962
|
+
}
|
|
15963
|
+
function renderTeamAgentSource(classKind, classPrefix, fileStem, defaultTeamId) {
|
|
15964
|
+
const typeName = buildTeamAgentTypeName(classKind, classPrefix);
|
|
15965
|
+
if (classKind === "attitude_solver") return `#include "${fileStem}.h"
|
|
15966
|
+
|
|
15967
|
+
ETeamAttitude::Type F${classPrefix}TeamAttitudeSolver::Solve(FGenericTeamId Lhs, FGenericTeamId Rhs)
|
|
15968
|
+
{
|
|
15969
|
+
if (Lhs == FGenericTeamId::NoTeam || Rhs == FGenericTeamId::NoTeam)
|
|
15970
|
+
{
|
|
15971
|
+
return ETeamAttitude::Neutral;
|
|
15972
|
+
}
|
|
15973
|
+
|
|
15974
|
+
return Lhs == Rhs ? ETeamAttitude::Friendly : ETeamAttitude::Hostile;
|
|
15975
|
+
}
|
|
15976
|
+
|
|
15977
|
+
void F${classPrefix}TeamAttitudeSolver::Register()
|
|
15978
|
+
{
|
|
15979
|
+
FGenericTeamId::SetAttitudeSolver(&F${classPrefix}TeamAttitudeSolver::Solve);
|
|
15980
|
+
}
|
|
15981
|
+
`;
|
|
15982
|
+
return `#include "${fileStem}.h"
|
|
15983
|
+
|
|
15984
|
+
${typeName}::${typeName}()
|
|
15985
|
+
{
|
|
15986
|
+
${classKind === "controller" ? ` // Written through the interface rather than straight onto the member so the controller and any
|
|
15987
|
+
// pawn it possesses stay in step from the first frame.
|
|
15988
|
+
SetGenericTeamId(FGenericTeamId(${String(defaultTeamId)}));` : ` TeamId = ${String(defaultTeamId)};`}
|
|
15989
|
+
}
|
|
15990
|
+
|
|
15991
|
+
FGenericTeamId ${typeName}::GetGenericTeamId() const
|
|
15992
|
+
{
|
|
15993
|
+
return FGenericTeamId(TeamId);
|
|
15994
|
+
}
|
|
15995
|
+
|
|
15996
|
+
void ${typeName}::SetGenericTeamId(const FGenericTeamId& NewTeamId)
|
|
15997
|
+
{
|
|
15998
|
+
TeamId = NewTeamId.GetId();
|
|
15999
|
+
}
|
|
16000
|
+
`;
|
|
16001
|
+
}
|
|
16002
|
+
function isPlainObject$1(value) {
|
|
16003
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16004
|
+
}
|
|
16005
|
+
function getErrorCode$1(error) {
|
|
16006
|
+
if (error instanceof Error && "code" in error && typeof error.code === "string") return error.code;
|
|
16007
|
+
}
|
|
14645
16008
|
//#endregion
|
|
14646
16009
|
//#region src/classScaffold.ts
|
|
14647
16010
|
const REFLECTED_MEMBER_KINDS = ["property", "function"];
|
|
@@ -15827,6 +17190,38 @@ function buildGetCreateClassStatusResult(response, projectId) {
|
|
|
15827
17190
|
if (response.sourcePath !== void 0) result.sourcePath = response.sourcePath;
|
|
15828
17191
|
return result;
|
|
15829
17192
|
}
|
|
17193
|
+
const createAiNodeClassInputSchema = {
|
|
17194
|
+
className: z.string().trim().min(1).max(96).describe("Bare class name without a prefix, e.g. 'MoveToCover'. The engine's prefix is added for you."),
|
|
17195
|
+
descriptorPath: z.string().trim().min(1).describe("Absolute path to the .uproject or .uplugin the target module is registered in."),
|
|
17196
|
+
displayName: z.string().trim().min(1).max(128).optional().describe("Name shown in the editor's node picker. Omitted uses the class name."),
|
|
17197
|
+
moduleName: z.string().trim().min(1).max(128).describe("Existing module to generate into. Create it first with add_module if it does not exist."),
|
|
17198
|
+
nodeKind: z.enum(AI_NODE_KINDS).describe("Which AI node to generate. Decides the base class and the override set."),
|
|
17199
|
+
updateBuildCs: z.boolean().optional().describe("Add the node's required modules to the module's Build.cs (default true). Off only reports them.")
|
|
17200
|
+
};
|
|
17201
|
+
const createTeamAgentClassInputSchema = {
|
|
17202
|
+
classKinds: z.array(z.enum(TEAM_AGENT_CLASS_KINDS)).min(1).max(3).describe("Which classes to generate: 'controller', 'character' and 'attitude_solver'. Perception only reports hostile or friendly once a solver is registered."),
|
|
17203
|
+
classPrefix: z.string().trim().min(1).max(96).describe("Prefix for the generated types, e.g. 'Guard' produces AGuardAIController and AGuardCharacter."),
|
|
17204
|
+
defaultTeamId: z.number().int().min(0).max(255).optional().describe("Team id the generated actors report by default (0-255, default 1). 255 is NoTeam."),
|
|
17205
|
+
descriptorPath: z.string().trim().min(1).describe("Absolute path to the .uproject or .uplugin the target module is registered in."),
|
|
17206
|
+
moduleName: z.string().trim().min(1).max(128).describe("Existing module to generate into."),
|
|
17207
|
+
updateBuildCs: z.boolean().optional().describe("Add AIModule and GameplayTasks to the module's Build.cs (default true).")
|
|
17208
|
+
};
|
|
17209
|
+
async function createAiNodeClass(input, dependencies) {
|
|
17210
|
+
const result = await scaffoldAiNodeClass(input);
|
|
17211
|
+
dependencies.logger.info({
|
|
17212
|
+
generatedTypes: result.generatedTypes,
|
|
17213
|
+
moduleName: result.moduleName
|
|
17214
|
+
}, "Scaffolded AI node class");
|
|
17215
|
+
return result;
|
|
17216
|
+
}
|
|
17217
|
+
async function createTeamAgentClass(input, dependencies) {
|
|
17218
|
+
const result = await scaffoldTeamAgentClass(input);
|
|
17219
|
+
dependencies.logger.info({
|
|
17220
|
+
generatedTypes: result.generatedTypes,
|
|
17221
|
+
moduleName: result.moduleName
|
|
17222
|
+
}, "Scaffolded team affiliation classes");
|
|
17223
|
+
return result;
|
|
17224
|
+
}
|
|
15830
17225
|
function registerCodeGenTools(server, dependencies) {
|
|
15831
17226
|
server.registerTool("add_module", {
|
|
15832
17227
|
description: "Scaffold a new Unreal C++ module (Source/<moduleName> with Build.cs, Public/<moduleName>.h, Private/<moduleName>.cpp) and register it in a .uproject or .uplugin descriptor. Pure filesystem scaffold; run generate_project_files + build_target afterward to compile it.",
|
|
@@ -15872,6 +17267,20 @@ function registerCodeGenTools(server, dependencies) {
|
|
|
15872
17267
|
}, async (input) => {
|
|
15873
17268
|
return toToolSuccess(await findSymbol(input, dependencies));
|
|
15874
17269
|
});
|
|
17270
|
+
server.registerTool("create_ai_node_class", {
|
|
17271
|
+
description: "Generate a C++ AI node class — a StateTree task, condition or evaluator, a Behavior Tree task, decorator or service, or an EQS generator or test — with the right base class, instance data struct, override signatures and prefix, plus the module dependencies it needs added to the module's Build.cs. Getting any of those wrong produces a class that compiles and never appears in the editor's node picker. Pure filesystem scaffold; run generate_project_files and build_target afterwards. For a Blueprint node use create_blueprint with the matching parent class instead.",
|
|
17272
|
+
inputSchema: createAiNodeClassInputSchema,
|
|
17273
|
+
title: "Create AI Node Class"
|
|
17274
|
+
}, async ({ className, descriptorPath, displayName, moduleName, nodeKind, updateBuildCs }) => {
|
|
17275
|
+
return toToolSuccess(await createAiNodeClass({
|
|
17276
|
+
className,
|
|
17277
|
+
descriptorPath,
|
|
17278
|
+
displayName,
|
|
17279
|
+
moduleName,
|
|
17280
|
+
nodeKind,
|
|
17281
|
+
updateBuildCs
|
|
17282
|
+
}, dependencies));
|
|
17283
|
+
});
|
|
15875
17284
|
server.registerTool("add_reflected_member", {
|
|
15876
17285
|
description: "Insert a UPROPERTY or UFUNCTION into an existing class or struct header, and append a matching .cpp stub for a function. Specifiers are validated against the UHT rules (conflicting edit/visibility specifiers, BlueprintReadOnly with BlueprintReadWrite, an RPC without Reliable/Unreliable or with a non-void return, a bare ReplicatedUsing) and nothing is written when they fail. The member goes in its own public: section right after GENERATED_BODY(), and any UE type it names by pointer or reference is forward-declared above the class. Server-side; does not require a running editor.",
|
|
15877
17286
|
inputSchema: addReflectedMemberInputSchema,
|
|
@@ -15886,6 +17295,20 @@ function registerCodeGenTools(server, dependencies) {
|
|
|
15886
17295
|
}, async (input) => {
|
|
15887
17296
|
return toToolSuccess(await scaffoldClassTemplate(input));
|
|
15888
17297
|
});
|
|
17298
|
+
server.registerTool("create_team_agent_class", {
|
|
17299
|
+
description: "Generate the C++ a team-based AI needs: an AIController and a Character that answer the generic team agent interface, and an attitude solver that decides what every team id means to every other one. Until a solver is registered, perception reports every actor with a different id as hostile and nothing as friendly, which is the behaviour this exists to replace. Pure filesystem scaffold; call the generated solver Register() from your module startup.",
|
|
17300
|
+
inputSchema: createTeamAgentClassInputSchema,
|
|
17301
|
+
title: "Create Team Agent Class"
|
|
17302
|
+
}, async ({ classKinds, classPrefix, defaultTeamId, descriptorPath, moduleName, updateBuildCs }) => {
|
|
17303
|
+
return toToolSuccess(await createTeamAgentClass({
|
|
17304
|
+
classKinds,
|
|
17305
|
+
classPrefix,
|
|
17306
|
+
defaultTeamId,
|
|
17307
|
+
descriptorPath,
|
|
17308
|
+
moduleName,
|
|
17309
|
+
updateBuildCs
|
|
17310
|
+
}, dependencies));
|
|
17311
|
+
});
|
|
15889
17312
|
}
|
|
15890
17313
|
const codeGenToolDomain = {
|
|
15891
17314
|
domain: "codeGen",
|
|
@@ -15896,7 +17319,9 @@ const codeGenToolDomain = {
|
|
|
15896
17319
|
"get_create_class_status",
|
|
15897
17320
|
"find_symbol",
|
|
15898
17321
|
"add_reflected_member",
|
|
15899
|
-
"scaffold_class_template"
|
|
17322
|
+
"scaffold_class_template",
|
|
17323
|
+
"create_ai_node_class",
|
|
17324
|
+
"create_team_agent_class"
|
|
15900
17325
|
]
|
|
15901
17326
|
};
|
|
15902
17327
|
//#endregion
|
|
@@ -17856,6 +19281,96 @@ const editorBuildToolDomain = {
|
|
|
17856
19281
|
]
|
|
17857
19282
|
};
|
|
17858
19283
|
//#endregion
|
|
19284
|
+
//#region src/tools/eqs.ts
|
|
19285
|
+
const getEqsQueryInputSchema = {
|
|
19286
|
+
assetPath: bridgeGetEqsQueryRequestSchema.shape.assetPath.describe("Object path of the Environment Query asset to read."),
|
|
19287
|
+
projectId: creativeProjectIdSchema
|
|
19288
|
+
};
|
|
19289
|
+
const editEqsQueryInputSchema = {
|
|
19290
|
+
assetPath: bridgeEditEqsQueryRequestSchema.shape.assetPath.describe("Object path of the Environment Query asset to edit."),
|
|
19291
|
+
generatorClass: bridgeEditEqsQueryRequestSchema.shape.generatorClass.describe("Replace the generator with this class. Omitted leaves the generator class alone."),
|
|
19292
|
+
generatorParams: bridgeEditEqsQueryRequestSchema.shape.generatorParams.describe("Reflected properties written onto the generator, valued as ExportText."),
|
|
19293
|
+
optionIndex: bridgeEditEqsQueryRequestSchema.shape.optionIndex.describe("Which query option to edit. Defaults 0, which is the only one most queries have."),
|
|
19294
|
+
projectId: creativeProjectIdSchema,
|
|
19295
|
+
tests: bridgeEditEqsQueryRequestSchema.shape.tests.describe("Test edits applied in order, each { operation, testIndex?, testClass?, purpose?, params?, toIndex? }. Indices address the list as it was before this call.")
|
|
19296
|
+
};
|
|
19297
|
+
const runEqsQueryInputSchema = {
|
|
19298
|
+
assetPath: bridgeRunEqsQueryRequestFieldsSchema.shape.assetPath.describe("Object path of the Environment Query asset to run."),
|
|
19299
|
+
maxItems: bridgeRunEqsQueryRequestFieldsSchema.shape.maxItems.describe("Maximum scored items to return (1-64, default 25)."),
|
|
19300
|
+
projectId: creativeProjectIdSchema,
|
|
19301
|
+
querierActorPath: bridgeRunEqsQueryRequestFieldsSchema.shape.querierActorPath.describe("Actor the query runs from. Most generators and every team test need one."),
|
|
19302
|
+
querierLocation: bridgeRunEqsQueryRequestFieldsSchema.shape.querierLocation.describe("World location to run the query from when there is no querier actor."),
|
|
19303
|
+
runMode: bridgeRunEqsQueryRequestFieldsSchema.shape.runMode.describe("EEnvQueryRunMode. 'all_matching' scores every item, which is what makes a run readable.")
|
|
19304
|
+
};
|
|
19305
|
+
async function getEqsQuery(input, dependencies) {
|
|
19306
|
+
return await exchangeCreativeRequest(createBridgeGetEqsQueryRequest(input.assetPath), sendBridgeGetEqsQueryRequest, BRIDGE_GET_EQS_QUERY_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
19307
|
+
}
|
|
19308
|
+
async function editEqsQuery(input, dependencies) {
|
|
19309
|
+
return await exchangeCreativeRequest(createBridgeEditEqsQueryRequest(input.assetPath, {
|
|
19310
|
+
generatorClass: input.generatorClass,
|
|
19311
|
+
generatorParams: input.generatorParams,
|
|
19312
|
+
optionIndex: input.optionIndex,
|
|
19313
|
+
tests: input.tests
|
|
19314
|
+
}), sendBridgeEditEqsQueryRequest, BRIDGE_EDIT_EQS_QUERY_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
19315
|
+
}
|
|
19316
|
+
async function runEqsQuery(input, dependencies) {
|
|
19317
|
+
return await exchangeCreativeRequest(createBridgeRunEqsQueryRequest(input.assetPath, {
|
|
19318
|
+
maxItems: input.maxItems,
|
|
19319
|
+
querierActorPath: input.querierActorPath,
|
|
19320
|
+
querierLocation: input.querierLocation,
|
|
19321
|
+
runMode: input.runMode
|
|
19322
|
+
}), sendBridgeRunEqsQueryRequest, BRIDGE_RUN_EQS_QUERY_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
19323
|
+
}
|
|
19324
|
+
function registerEqsTools(server, dependencies) {
|
|
19325
|
+
server.registerTool("get_eqs_query", {
|
|
19326
|
+
description: "Read an Environment Query back: each option's generator with its settings, and every test with its purpose, settings and position in the run order. The test indices are what edit_eqs_query addresses, so this is the call to make before changing a query you did not author.",
|
|
19327
|
+
inputSchema: getEqsQueryInputSchema,
|
|
19328
|
+
title: "Get EQS Query"
|
|
19329
|
+
}, async ({ assetPath, projectId }) => {
|
|
19330
|
+
return toToolSuccess(await getEqsQuery({
|
|
19331
|
+
assetPath,
|
|
19332
|
+
projectId
|
|
19333
|
+
}, dependencies));
|
|
19334
|
+
});
|
|
19335
|
+
server.registerTool("edit_eqs_query", {
|
|
19336
|
+
description: "Change an existing Environment Query: retune the generator, and add, update, remove or reorder its tests. Order matters — EQS runs filters before scores and a cheap filter placed first is the difference between a query that costs nothing and one that scores every item — so moving a test is a first-class operation rather than a delete and re-add.",
|
|
19337
|
+
inputSchema: editEqsQueryInputSchema,
|
|
19338
|
+
title: "Edit EQS Query"
|
|
19339
|
+
}, async ({ assetPath, generatorClass, generatorParams, optionIndex, projectId, tests }) => {
|
|
19340
|
+
return toToolSuccess(await editEqsQuery({
|
|
19341
|
+
assetPath,
|
|
19342
|
+
generatorClass,
|
|
19343
|
+
generatorParams,
|
|
19344
|
+
optionIndex,
|
|
19345
|
+
projectId,
|
|
19346
|
+
tests
|
|
19347
|
+
}, dependencies));
|
|
19348
|
+
});
|
|
19349
|
+
server.registerTool("run_eqs_query", {
|
|
19350
|
+
description: "Run an Environment Query in the editor world and return every generated item with its per-test scores and the winning one — the same numbers the EQS testing pawn draws, without placing one or entering Play In Editor. Use it to tune a query by running it, reading the scores and editing, rather than by guessing at weights.",
|
|
19351
|
+
inputSchema: runEqsQueryInputSchema,
|
|
19352
|
+
title: "Run EQS Query"
|
|
19353
|
+
}, async ({ assetPath, maxItems, projectId, querierActorPath, querierLocation, runMode }) => {
|
|
19354
|
+
return toToolSuccess(await runEqsQuery({
|
|
19355
|
+
assetPath,
|
|
19356
|
+
maxItems,
|
|
19357
|
+
projectId,
|
|
19358
|
+
querierActorPath,
|
|
19359
|
+
querierLocation,
|
|
19360
|
+
runMode
|
|
19361
|
+
}, dependencies));
|
|
19362
|
+
});
|
|
19363
|
+
}
|
|
19364
|
+
const eqsToolDomain = {
|
|
19365
|
+
domain: "eqs",
|
|
19366
|
+
register: registerEqsTools,
|
|
19367
|
+
toolNames: [
|
|
19368
|
+
"get_eqs_query",
|
|
19369
|
+
"edit_eqs_query",
|
|
19370
|
+
"run_eqs_query"
|
|
19371
|
+
]
|
|
19372
|
+
};
|
|
19373
|
+
//#endregion
|
|
17859
19374
|
//#region src/tools/foliage.ts
|
|
17860
19375
|
const addFoliageTypeInputSchema = {
|
|
17861
19376
|
assetName: bridgeAddFoliageTypeRequestSchema.shape.assetName.describe("Name of the new foliage type, e.g. 'FT_Grass'."),
|
|
@@ -21023,6 +22538,115 @@ const pcgToolDomain = {
|
|
|
21023
22538
|
toolNames: ["create_pcg_graph", "run_pcg_generate"]
|
|
21024
22539
|
};
|
|
21025
22540
|
//#endregion
|
|
22541
|
+
//#region src/tools/perception.ts
|
|
22542
|
+
const createAiControllerInputSchema = {
|
|
22543
|
+
addPerception: bridgeCreateAiControllerRequestFieldsSchema.shape.addPerception.describe("Add a perception component with no senses, which configure_ai_perception then fills in."),
|
|
22544
|
+
assetName: bridgeCreateAiControllerRequestFieldsSchema.shape.assetName.describe("Name of the new controller Blueprint, e.g. 'BP_GuardController'."),
|
|
22545
|
+
autoPossess: bridgeCreateAiControllerRequestFieldsSchema.shape.autoPossess.describe("EAutoPossessAI value written onto the pawn class, so a pawn placed in the level gets this controller."),
|
|
22546
|
+
behaviorTreePath: bridgeCreateAiControllerRequestFieldsSchema.shape.behaviorTreePath.describe("Behavior Tree the controller runs on possess. Required when brainKind is 'behavior_tree'."),
|
|
22547
|
+
blackboardPath: bridgeCreateAiControllerRequestFieldsSchema.shape.blackboardPath.describe("Blackboard to initialize. Omitted uses the Behavior Tree's own."),
|
|
22548
|
+
brainKind: bridgeCreateAiControllerRequestFieldsSchema.shape.brainKind.describe("What runs the AI: 'behavior_tree', 'state_tree', or 'none' for a controller whose subclass decides."),
|
|
22549
|
+
packagePath: bridgeCreateAiControllerRequestFieldsSchema.shape.packagePath.describe("Content folder to create the controller in."),
|
|
22550
|
+
parentClass: bridgeCreateAiControllerRequestFieldsSchema.shape.parentClass.describe("Parent class for the Blueprint. Omitted uses AIController."),
|
|
22551
|
+
pawnClassPath: bridgeCreateAiControllerRequestFieldsSchema.shape.pawnClassPath.describe("Pawn class to assign this controller to. Assigning it recompiles that Blueprint."),
|
|
22552
|
+
projectId: creativeProjectIdSchema,
|
|
22553
|
+
stateTreePath: bridgeCreateAiControllerRequestFieldsSchema.shape.stateTreePath.describe("StateTree the controller runs. Required when brainKind is 'state_tree'.")
|
|
22554
|
+
};
|
|
22555
|
+
const configureAiPerceptionInputSchema = {
|
|
22556
|
+
blueprintPath: bridgeConfigureAiPerceptionRequestSchema.shape.blueprintPath.describe("Object path of the Blueprint whose perception component to configure."),
|
|
22557
|
+
componentName: bridgeConfigureAiPerceptionRequestSchema.shape.componentName.describe("Perception component to edit. Omitted edits the first one on the Blueprint."),
|
|
22558
|
+
dominantSense: bridgeConfigureAiPerceptionRequestSchema.shape.dominantSense.describe("Sense that decides where a perceived actor is reported from when several fire at once."),
|
|
22559
|
+
projectId: creativeProjectIdSchema,
|
|
22560
|
+
senses: bridgeConfigureAiPerceptionRequestSchema.shape.senses.describe("Senses to write, each { senseKind, mode?, params?, detectEnemies?, detectNeutrals?, detectFriendlies? }. Every affiliation flag off is why a well-configured sense detects nothing.")
|
|
22561
|
+
};
|
|
22562
|
+
const addStimuliSourceInputSchema = {
|
|
22563
|
+
autoRegisterAsSource: bridgeAddStimuliSourceRequestSchema.shape.autoRegisterAsSource.describe("Register the actor with the perception system on begin play. Off leaves it invisible until something registers it by hand."),
|
|
22564
|
+
blueprintPath: bridgeAddStimuliSourceRequestSchema.shape.blueprintPath.describe("Object path of the Blueprint to make perceivable."),
|
|
22565
|
+
componentName: bridgeAddStimuliSourceRequestSchema.shape.componentName.describe("Name for the new stimuli source component. Omitted uses AIPerceptionStimuliSource."),
|
|
22566
|
+
projectId: creativeProjectIdSchema,
|
|
22567
|
+
senses: bridgeAddStimuliSourceRequestSchema.shape.senses.describe("Senses the actor registers itself for. An actor registered for no sense is perceived by nothing.")
|
|
22568
|
+
};
|
|
22569
|
+
async function createAiController(input, dependencies) {
|
|
22570
|
+
return await exchangeCreativeRequest(createBridgeCreateAiControllerRequest(input.assetName, input.packagePath, {
|
|
22571
|
+
addPerception: input.addPerception,
|
|
22572
|
+
autoPossess: input.autoPossess,
|
|
22573
|
+
behaviorTreePath: input.behaviorTreePath,
|
|
22574
|
+
blackboardPath: input.blackboardPath,
|
|
22575
|
+
brainKind: input.brainKind,
|
|
22576
|
+
parentClass: input.parentClass,
|
|
22577
|
+
pawnClassPath: input.pawnClassPath,
|
|
22578
|
+
stateTreePath: input.stateTreePath
|
|
22579
|
+
}), sendBridgeCreateAiControllerRequest, BRIDGE_CREATE_AI_CONTROLLER_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
22580
|
+
}
|
|
22581
|
+
async function configureAiPerception(input, dependencies) {
|
|
22582
|
+
return await exchangeCreativeRequest(createBridgeConfigureAiPerceptionRequest(input.blueprintPath, input.senses, {
|
|
22583
|
+
componentName: input.componentName,
|
|
22584
|
+
dominantSense: input.dominantSense
|
|
22585
|
+
}), sendBridgeConfigureAiPerceptionRequest, BRIDGE_CONFIGURE_AI_PERCEPTION_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
22586
|
+
}
|
|
22587
|
+
async function addStimuliSource(input, dependencies) {
|
|
22588
|
+
return await exchangeCreativeRequest(createBridgeAddStimuliSourceRequest(input.blueprintPath, input.senses, {
|
|
22589
|
+
autoRegisterAsSource: input.autoRegisterAsSource,
|
|
22590
|
+
componentName: input.componentName
|
|
22591
|
+
}), sendBridgeAddStimuliSourceRequest, BRIDGE_ADD_STIMULI_SOURCE_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
22592
|
+
}
|
|
22593
|
+
function registerPerceptionTools(server, dependencies) {
|
|
22594
|
+
server.registerTool("create_ai_controller", {
|
|
22595
|
+
description: "Create an AIController Blueprint that runs a Behavior Tree or a StateTree on possess, optionally with a perception component, and assign it to a pawn class with auto-possess — the several-asset setup that otherwise takes a handful of separate calls. Assigning the controller recompiles the pawn Blueprint, which the response names rather than doing silently.",
|
|
22596
|
+
inputSchema: createAiControllerInputSchema,
|
|
22597
|
+
title: "Create AI Controller"
|
|
22598
|
+
}, async ({ addPerception, assetName, autoPossess, behaviorTreePath, blackboardPath, brainKind, packagePath, parentClass, pawnClassPath, projectId, stateTreePath }) => {
|
|
22599
|
+
return toToolSuccess(await createAiController({
|
|
22600
|
+
addPerception,
|
|
22601
|
+
assetName,
|
|
22602
|
+
autoPossess,
|
|
22603
|
+
behaviorTreePath,
|
|
22604
|
+
blackboardPath,
|
|
22605
|
+
brainKind,
|
|
22606
|
+
packagePath,
|
|
22607
|
+
parentClass,
|
|
22608
|
+
pawnClassPath,
|
|
22609
|
+
projectId,
|
|
22610
|
+
stateTreePath
|
|
22611
|
+
}, dependencies));
|
|
22612
|
+
});
|
|
22613
|
+
server.registerTool("configure_ai_perception", {
|
|
22614
|
+
description: "Configure the senses on a Blueprint's AI perception component — sight cones and radii, hearing range, damage, team and touch — including the affiliation flags that decide what each sense reports at all. Every affiliation off is the default on a fresh sight config and the usual reason a perfectly configured sense detects nothing.",
|
|
22615
|
+
inputSchema: configureAiPerceptionInputSchema,
|
|
22616
|
+
title: "Configure AI Perception"
|
|
22617
|
+
}, async ({ blueprintPath, componentName, dominantSense, projectId, senses }) => {
|
|
22618
|
+
return toToolSuccess(await configureAiPerception({
|
|
22619
|
+
blueprintPath,
|
|
22620
|
+
componentName,
|
|
22621
|
+
dominantSense,
|
|
22622
|
+
projectId,
|
|
22623
|
+
senses
|
|
22624
|
+
}, dependencies));
|
|
22625
|
+
});
|
|
22626
|
+
server.registerTool("add_stimuli_source", {
|
|
22627
|
+
description: "Make an actor perceivable by adding a stimuli source component registered for the senses it should be detected by. This is the half of perception setup that is easy to forget: an actor that registers for no sense is invisible to every perception component in the level, however well those are configured.",
|
|
22628
|
+
inputSchema: addStimuliSourceInputSchema,
|
|
22629
|
+
title: "Add Stimuli Source"
|
|
22630
|
+
}, async ({ autoRegisterAsSource, blueprintPath, componentName, projectId, senses }) => {
|
|
22631
|
+
return toToolSuccess(await addStimuliSource({
|
|
22632
|
+
autoRegisterAsSource,
|
|
22633
|
+
blueprintPath,
|
|
22634
|
+
componentName,
|
|
22635
|
+
projectId,
|
|
22636
|
+
senses
|
|
22637
|
+
}, dependencies));
|
|
22638
|
+
});
|
|
22639
|
+
}
|
|
22640
|
+
const perceptionToolDomain = {
|
|
22641
|
+
domain: "perception",
|
|
22642
|
+
register: registerPerceptionTools,
|
|
22643
|
+
toolNames: [
|
|
22644
|
+
"create_ai_controller",
|
|
22645
|
+
"configure_ai_perception",
|
|
22646
|
+
"add_stimuli_source"
|
|
22647
|
+
]
|
|
22648
|
+
};
|
|
22649
|
+
//#endregion
|
|
21026
22650
|
//#region src/tools/postProcess.ts
|
|
21027
22651
|
const createPostProcessVolumeInputSchema = {
|
|
21028
22652
|
actorLabel: bridgeCreatePostProcessVolumeRequestSchema.shape.actorLabel.describe("Label for the placed volume. Omitted lets the editor name it."),
|
|
@@ -21765,6 +23389,160 @@ const sequencerToolDomain = {
|
|
|
21765
23389
|
]
|
|
21766
23390
|
};
|
|
21767
23391
|
//#endregion
|
|
23392
|
+
//#region src/tools/stateTree.ts
|
|
23393
|
+
const getStateTreeInputSchema = {
|
|
23394
|
+
assetPath: bridgeGetStateTreeRequestSchema.shape.assetPath.describe("Object path of the StateTree asset to read."),
|
|
23395
|
+
projectId: creativeProjectIdSchema
|
|
23396
|
+
};
|
|
23397
|
+
const setStateTreeGlobalsInputSchema = {
|
|
23398
|
+
assetPath: bridgeSetStateTreeGlobalsRequestSchema.shape.assetPath.describe("Object path of the StateTree asset to edit."),
|
|
23399
|
+
compile: bridgeSetStateTreeGlobalsRequestSchema.shape.compile.describe("Run the StateTree compiler after the edit. Defaults true — an evaluator is not visible to states until the tree compiles."),
|
|
23400
|
+
mode: bridgeSetStateTreeGlobalsRequestSchema.shape.mode.describe("'merge' appends to what the tree already carries; 'replace' makes the root's lists exactly what was sent, which is the only way to remove one."),
|
|
23401
|
+
nodes: bridgeSetStateTreeGlobalsRequestSchema.shape.nodes.describe("Tree-level nodes, each { kind, nodeClass, params? }. kind is 'evaluator' or 'global_task'; nodeClass names a script struct such as '/Script/StateTreeModule.StateTreeEvaluatorBase' subclass."),
|
|
23402
|
+
projectId: creativeProjectIdSchema
|
|
23403
|
+
};
|
|
23404
|
+
const setStateTreeConsiderationsInputSchema = {
|
|
23405
|
+
assetPath: bridgeSetStateTreeConsiderationsRequestSchema.shape.assetPath.describe("Object path of the StateTree asset to edit."),
|
|
23406
|
+
compile: bridgeSetStateTreeConsiderationsRequestSchema.shape.compile.describe("Run the StateTree compiler after the edit. Defaults true."),
|
|
23407
|
+
projectId: creativeProjectIdSchema,
|
|
23408
|
+
states: bridgeSetStateTreeConsiderationsRequestSchema.shape.states.describe("States to score, each { stateName, selectionBehavior?, weight?, considerations? }. Considerations are { nodeClass, params? }. The weight scales the whole state score, because that is where the engine keeps it, and it only matters under a utility selection behaviour.")
|
|
23409
|
+
};
|
|
23410
|
+
const linkStateTreeStateInputSchema = {
|
|
23411
|
+
assetPath: bridgeLinkStateTreeStateRequestSchema.shape.assetPath.describe("Object path of the StateTree asset to edit."),
|
|
23412
|
+
compile: bridgeLinkStateTreeStateRequestSchema.shape.compile.describe("Run the StateTree compiler after the edit. Defaults true."),
|
|
23413
|
+
links: bridgeLinkStateTreeStateRequestSchema.shape.links.describe("Links to apply, each { stateName, linkType, targetStateName?, linkedAssetPath?, parameterOverrides? }. A 'linked_state' names a state in this tree; a 'linked_asset' names another StateTree."),
|
|
23414
|
+
projectId: creativeProjectIdSchema
|
|
23415
|
+
};
|
|
23416
|
+
const addStateTreeComponentInputSchema = {
|
|
23417
|
+
blueprintPath: bridgeAddStateTreeComponentRequestSchema.shape.blueprintPath.describe("Object path of the Blueprint to add the component to."),
|
|
23418
|
+
componentKind: bridgeAddStateTreeComponentRequestSchema.shape.componentKind.describe("'state_tree' runs any actor-schema tree; 'state_tree_ai' is the AIController-bound component the AI schema's tasks need."),
|
|
23419
|
+
componentName: bridgeAddStateTreeComponentRequestSchema.shape.componentName.describe("Name for the new component. Omitted names it after its kind."),
|
|
23420
|
+
projectId: creativeProjectIdSchema,
|
|
23421
|
+
startLogicAutomatically: bridgeAddStateTreeComponentRequestSchema.shape.startLogicAutomatically.describe("Start the tree when the component begins play. Off leaves it assigned but dormant."),
|
|
23422
|
+
stateTreePath: bridgeAddStateTreeComponentRequestSchema.shape.stateTreePath.describe("Object path of the StateTree asset to assign. Its schema must match the component kind.")
|
|
23423
|
+
};
|
|
23424
|
+
const traceStateTreeInputSchema = {
|
|
23425
|
+
action: bridgeTraceStateTreeRequestSchema.shape.action.describe("'start' begins recording, 'poll' drains what has been recorded so far, 'stop' ends the recording and drains the rest."),
|
|
23426
|
+
actorPath: bridgeTraceStateTreeRequestSchema.shape.actorPath.describe("Actor to record. Omitted on start records every StateTree in the session, which floods quickly."),
|
|
23427
|
+
maxEvents: bridgeTraceStateTreeRequestSchema.shape.maxEvents.describe("Maximum events to return in one poll (1-200, default 50)."),
|
|
23428
|
+
projectId: creativeProjectIdSchema
|
|
23429
|
+
};
|
|
23430
|
+
async function getStateTree(input, dependencies) {
|
|
23431
|
+
return await exchangeCreativeRequest(createBridgeGetStateTreeRequest(input.assetPath), sendBridgeGetStateTreeRequest, BRIDGE_GET_STATE_TREE_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
23432
|
+
}
|
|
23433
|
+
async function setStateTreeGlobals(input, dependencies) {
|
|
23434
|
+
return await exchangeCreativeRequest(createBridgeSetStateTreeGlobalsRequest(input.assetPath, input.nodes ?? [], {
|
|
23435
|
+
compile: input.compile,
|
|
23436
|
+
mode: input.mode
|
|
23437
|
+
}), sendBridgeSetStateTreeGlobalsRequest, BRIDGE_SET_STATE_TREE_GLOBALS_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
23438
|
+
}
|
|
23439
|
+
async function setStateTreeConsiderations(input, dependencies) {
|
|
23440
|
+
return await exchangeCreativeRequest(createBridgeSetStateTreeConsiderationsRequest(input.assetPath, input.states, { compile: input.compile }), sendBridgeSetStateTreeConsiderationsRequest, BRIDGE_SET_STATE_TREE_CONSIDERATIONS_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
23441
|
+
}
|
|
23442
|
+
async function linkStateTreeState(input, dependencies) {
|
|
23443
|
+
return await exchangeCreativeRequest(createBridgeLinkStateTreeStateRequest(input.assetPath, input.links, { compile: input.compile }), sendBridgeLinkStateTreeStateRequest, BRIDGE_LINK_STATE_TREE_STATE_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
23444
|
+
}
|
|
23445
|
+
async function addStateTreeComponent(input, dependencies) {
|
|
23446
|
+
return await exchangeCreativeRequest(createBridgeAddStateTreeComponentRequest(input.blueprintPath, input.stateTreePath, {
|
|
23447
|
+
componentKind: input.componentKind,
|
|
23448
|
+
componentName: input.componentName,
|
|
23449
|
+
startLogicAutomatically: input.startLogicAutomatically
|
|
23450
|
+
}), sendBridgeAddStateTreeComponentRequest, BRIDGE_ADD_STATE_TREE_COMPONENT_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
23451
|
+
}
|
|
23452
|
+
async function traceStateTree(input, dependencies) {
|
|
23453
|
+
return await exchangeCreativeRequest(createBridgeTraceStateTreeRequest(input.action, {
|
|
23454
|
+
actorPath: input.actorPath,
|
|
23455
|
+
maxEvents: input.maxEvents
|
|
23456
|
+
}), sendBridgeTraceStateTreeRequest, BRIDGE_TRACE_STATE_TREE_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
23457
|
+
}
|
|
23458
|
+
function registerStateTreeTools(server, dependencies) {
|
|
23459
|
+
server.registerTool("get_state_tree", {
|
|
23460
|
+
description: "Read a StateTree back: its schema, parameters, evaluators, global tasks and the full state hierarchy with each state's tasks, enter conditions and transitions. Every state and node carries the id the edit tools address it by, so this is the call to make before editing a tree you did not author. compiled reports whether the asset carries runtime data — a tree that reads back correctly with compiled false is authored but will not run.",
|
|
23461
|
+
inputSchema: getStateTreeInputSchema,
|
|
23462
|
+
title: "Get StateTree"
|
|
23463
|
+
}, async ({ assetPath, projectId }) => {
|
|
23464
|
+
return toToolSuccess(await getStateTree({
|
|
23465
|
+
assetPath,
|
|
23466
|
+
projectId
|
|
23467
|
+
}, dependencies));
|
|
23468
|
+
});
|
|
23469
|
+
server.registerTool("set_state_tree_globals", {
|
|
23470
|
+
description: "Add or replace the evaluators and global tasks on a StateTree's root. An evaluator produces values every tick for states to bind against; a global task runs for the whole lifetime of the tree. The tree is recompiled by default because an evaluator's output is not visible to any state until it is.",
|
|
23471
|
+
inputSchema: setStateTreeGlobalsInputSchema,
|
|
23472
|
+
title: "Set StateTree Globals"
|
|
23473
|
+
}, async ({ assetPath, compile, mode, nodes, projectId }) => {
|
|
23474
|
+
return toToolSuccess(await setStateTreeGlobals({
|
|
23475
|
+
assetPath,
|
|
23476
|
+
compile,
|
|
23477
|
+
mode,
|
|
23478
|
+
nodes,
|
|
23479
|
+
projectId
|
|
23480
|
+
}, dependencies));
|
|
23481
|
+
});
|
|
23482
|
+
server.registerTool("set_state_tree_considerations", {
|
|
23483
|
+
description: "Switch states to utility-scored selection and give them weighted considerations, so the parent picks the highest-scoring child rather than the first one whose conditions pass. Utility selection only exists on newer engines: on an older one nothing is written, supported comes back false and supportedVersions names the engines that have it.",
|
|
23484
|
+
inputSchema: setStateTreeConsiderationsInputSchema,
|
|
23485
|
+
title: "Set StateTree Considerations"
|
|
23486
|
+
}, async ({ assetPath, compile, projectId, states }) => {
|
|
23487
|
+
return toToolSuccess(await setStateTreeConsiderations({
|
|
23488
|
+
assetPath,
|
|
23489
|
+
compile,
|
|
23490
|
+
projectId,
|
|
23491
|
+
states
|
|
23492
|
+
}, dependencies));
|
|
23493
|
+
});
|
|
23494
|
+
server.registerTool("link_state_tree_state", {
|
|
23495
|
+
description: "Turn states into linked states or linked assets so a subtree can be reused. A 'linked_state' runs another state in the same tree; a 'linked_asset' runs a whole other StateTree, which is the reuse unit that survives being edited somewhere else. Parameter overrides are checked against the target's own parameters rather than dropped.",
|
|
23496
|
+
inputSchema: linkStateTreeStateInputSchema,
|
|
23497
|
+
title: "Link StateTree State"
|
|
23498
|
+
}, async ({ assetPath, compile, links, projectId }) => {
|
|
23499
|
+
return toToolSuccess(await linkStateTreeState({
|
|
23500
|
+
assetPath,
|
|
23501
|
+
compile,
|
|
23502
|
+
links,
|
|
23503
|
+
projectId
|
|
23504
|
+
}, dependencies));
|
|
23505
|
+
});
|
|
23506
|
+
server.registerTool("add_state_tree_component", {
|
|
23507
|
+
description: "Add a StateTree component to a Blueprint with the tree assigned, which is what makes an authored tree actually run on an actor. The tree's schema is checked against the component kind and a mismatch is refused rather than left to fail at runtime. When the engine plugin that provides the AI component is switched off, the response comes back unsupported with the reason instead of failing.",
|
|
23508
|
+
inputSchema: addStateTreeComponentInputSchema,
|
|
23509
|
+
title: "Add StateTree Component"
|
|
23510
|
+
}, async ({ blueprintPath, componentKind, componentName, projectId, startLogicAutomatically, stateTreePath }) => {
|
|
23511
|
+
return toToolSuccess(await addStateTreeComponent({
|
|
23512
|
+
blueprintPath,
|
|
23513
|
+
componentKind,
|
|
23514
|
+
componentName,
|
|
23515
|
+
projectId,
|
|
23516
|
+
startLogicAutomatically,
|
|
23517
|
+
stateTreePath
|
|
23518
|
+
}, dependencies));
|
|
23519
|
+
});
|
|
23520
|
+
server.registerTool("trace_state_tree", {
|
|
23521
|
+
description: "Record and read back what a StateTree did during Play In Editor: which states were entered and left, which transitions fired and why, and how each task and condition answered, each stamped with seconds since the recording started. Start the recording, run the fixture, then poll. droppedCount tells a quiet fixture apart from one whose trace outran the buffer.",
|
|
23522
|
+
inputSchema: traceStateTreeInputSchema,
|
|
23523
|
+
title: "Trace StateTree"
|
|
23524
|
+
}, async ({ action, actorPath, maxEvents, projectId }) => {
|
|
23525
|
+
return toToolSuccess(await traceStateTree({
|
|
23526
|
+
action,
|
|
23527
|
+
actorPath,
|
|
23528
|
+
maxEvents,
|
|
23529
|
+
projectId
|
|
23530
|
+
}, dependencies));
|
|
23531
|
+
});
|
|
23532
|
+
}
|
|
23533
|
+
const stateTreeToolDomain = {
|
|
23534
|
+
domain: "stateTree",
|
|
23535
|
+
register: registerStateTreeTools,
|
|
23536
|
+
toolNames: [
|
|
23537
|
+
"get_state_tree",
|
|
23538
|
+
"set_state_tree_globals",
|
|
23539
|
+
"set_state_tree_considerations",
|
|
23540
|
+
"link_state_tree_state",
|
|
23541
|
+
"add_state_tree_component",
|
|
23542
|
+
"trace_state_tree"
|
|
23543
|
+
]
|
|
23544
|
+
};
|
|
23545
|
+
//#endregion
|
|
21768
23546
|
//#region src/tools/toolchain.ts
|
|
21769
23547
|
const buildTimeoutSchema = z.number().int().min(1e3).max(MAX_PROCESS_TIMEOUT_MS).optional().describe(`Hard timeout in milliseconds before the child process is killed (default ${DEFAULT_PROCESS_TIMEOUT_MS}).`);
|
|
21770
23548
|
const platformSchema = z.enum(UNREAL_TARGET_PLATFORMS).optional().describe("Target platform; defaults to the host platform (Win64/Mac/Linux).");
|
|
@@ -22678,6 +24456,9 @@ const TOOL_CATALOG = [
|
|
|
22678
24456
|
inputToolDomain,
|
|
22679
24457
|
abilitiesToolDomain,
|
|
22680
24458
|
behaviorTreeToolDomain,
|
|
24459
|
+
stateTreeToolDomain,
|
|
24460
|
+
perceptionToolDomain,
|
|
24461
|
+
eqsToolDomain,
|
|
22681
24462
|
animToolDomain,
|
|
22682
24463
|
umgToolDomain,
|
|
22683
24464
|
renderToolDomain,
|