unreal-engine-mcp-server 0.4.0 → 0.4.4
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/.env.production +1 -1
- package/.github/copilot-instructions.md +45 -0
- package/.github/workflows/publish-mcp.yml +3 -2
- package/README.md +21 -5
- package/dist/index.js +124 -31
- package/dist/prompts/index.d.ts +10 -3
- package/dist/prompts/index.js +186 -7
- package/dist/resources/actors.d.ts +19 -1
- package/dist/resources/actors.js +55 -64
- package/dist/resources/assets.js +46 -62
- package/dist/resources/levels.d.ts +21 -3
- package/dist/resources/levels.js +29 -54
- package/dist/tools/actors.d.ts +3 -14
- package/dist/tools/actors.js +246 -302
- package/dist/tools/animation.d.ts +57 -102
- package/dist/tools/animation.js +429 -450
- package/dist/tools/assets.d.ts +13 -2
- package/dist/tools/assets.js +52 -44
- package/dist/tools/audio.d.ts +22 -13
- package/dist/tools/audio.js +467 -121
- package/dist/tools/blueprint.d.ts +32 -13
- package/dist/tools/blueprint.js +699 -448
- package/dist/tools/build_environment_advanced.d.ts +0 -1
- package/dist/tools/build_environment_advanced.js +190 -45
- package/dist/tools/consolidated-tool-definitions.js +78 -252
- package/dist/tools/consolidated-tool-handlers.js +506 -133
- package/dist/tools/debug.d.ts +72 -10
- package/dist/tools/debug.js +167 -31
- package/dist/tools/editor.d.ts +9 -2
- package/dist/tools/editor.js +30 -44
- package/dist/tools/foliage.d.ts +34 -15
- package/dist/tools/foliage.js +97 -107
- package/dist/tools/introspection.js +19 -21
- package/dist/tools/landscape.d.ts +1 -2
- package/dist/tools/landscape.js +311 -168
- package/dist/tools/level.d.ts +3 -28
- package/dist/tools/level.js +642 -192
- package/dist/tools/lighting.d.ts +14 -3
- package/dist/tools/lighting.js +236 -123
- package/dist/tools/materials.d.ts +25 -7
- package/dist/tools/materials.js +102 -79
- package/dist/tools/niagara.d.ts +10 -12
- package/dist/tools/niagara.js +74 -94
- package/dist/tools/performance.d.ts +12 -4
- package/dist/tools/performance.js +38 -79
- package/dist/tools/physics.d.ts +34 -10
- package/dist/tools/physics.js +364 -292
- package/dist/tools/rc.js +97 -23
- package/dist/tools/sequence.d.ts +1 -0
- package/dist/tools/sequence.js +125 -22
- package/dist/tools/ui.d.ts +31 -4
- package/dist/tools/ui.js +83 -66
- package/dist/tools/visual.d.ts +11 -0
- package/dist/tools/visual.js +245 -30
- package/dist/types/tool-types.d.ts +0 -6
- package/dist/types/tool-types.js +1 -8
- package/dist/unreal-bridge.d.ts +32 -2
- package/dist/unreal-bridge.js +621 -127
- package/dist/utils/elicitation.d.ts +57 -0
- package/dist/utils/elicitation.js +104 -0
- package/dist/utils/error-handler.d.ts +0 -33
- package/dist/utils/error-handler.js +4 -111
- package/dist/utils/http.d.ts +2 -22
- package/dist/utils/http.js +12 -75
- package/dist/utils/normalize.d.ts +4 -4
- package/dist/utils/normalize.js +15 -7
- package/dist/utils/python-output.d.ts +18 -0
- package/dist/utils/python-output.js +290 -0
- package/dist/utils/python.d.ts +2 -0
- package/dist/utils/python.js +4 -0
- package/dist/utils/response-validator.js +28 -2
- package/dist/utils/result-helpers.d.ts +27 -0
- package/dist/utils/result-helpers.js +147 -0
- package/dist/utils/safe-json.d.ts +0 -2
- package/dist/utils/safe-json.js +0 -43
- package/dist/utils/validation.d.ts +16 -0
- package/dist/utils/validation.js +70 -7
- package/mcp-config-example.json +2 -2
- package/package.json +10 -9
- package/server.json +37 -14
- package/src/index.ts +130 -33
- package/src/prompts/index.ts +211 -13
- package/src/resources/actors.ts +59 -44
- package/src/resources/assets.ts +48 -51
- package/src/resources/levels.ts +35 -45
- package/src/tools/actors.ts +269 -313
- package/src/tools/animation.ts +556 -539
- package/src/tools/assets.ts +53 -43
- package/src/tools/audio.ts +507 -113
- package/src/tools/blueprint.ts +778 -462
- package/src/tools/build_environment_advanced.ts +266 -64
- package/src/tools/consolidated-tool-definitions.ts +90 -264
- package/src/tools/consolidated-tool-handlers.ts +630 -121
- package/src/tools/debug.ts +176 -33
- package/src/tools/editor.ts +35 -37
- package/src/tools/foliage.ts +110 -104
- package/src/tools/introspection.ts +24 -22
- package/src/tools/landscape.ts +334 -181
- package/src/tools/level.ts +683 -182
- package/src/tools/lighting.ts +244 -123
- package/src/tools/materials.ts +114 -83
- package/src/tools/niagara.ts +87 -81
- package/src/tools/performance.ts +49 -88
- package/src/tools/physics.ts +393 -299
- package/src/tools/rc.ts +102 -24
- package/src/tools/sequence.ts +136 -28
- package/src/tools/ui.ts +101 -70
- package/src/tools/visual.ts +250 -29
- package/src/types/tool-types.ts +0 -9
- package/src/unreal-bridge.ts +658 -140
- package/src/utils/elicitation.ts +129 -0
- package/src/utils/error-handler.ts +4 -159
- package/src/utils/http.ts +16 -115
- package/src/utils/normalize.ts +20 -10
- package/src/utils/python-output.ts +351 -0
- package/src/utils/python.ts +3 -0
- package/src/utils/response-validator.ts +25 -2
- package/src/utils/result-helpers.ts +193 -0
- package/src/utils/safe-json.ts +0 -50
- package/src/utils/validation.ts +94 -7
- package/tests/run-unreal-tool-tests.mjs +720 -0
- package/tsconfig.json +2 -2
- package/dist/python-utils.d.ts +0 -29
- package/dist/python-utils.js +0 -54
- package/dist/types/index.d.ts +0 -323
- package/dist/types/index.js +0 -28
- package/dist/utils/cache-manager.d.ts +0 -64
- package/dist/utils/cache-manager.js +0 -176
- package/dist/utils/errors.d.ts +0 -133
- package/dist/utils/errors.js +0 -256
- package/src/python/editor_compat.py +0 -181
- package/src/python-utils.ts +0 -57
- package/src/types/index.ts +0 -414
- package/src/utils/cache-manager.ts +0 -213
- package/src/utils/errors.ts +0 -312
package/src/tools/debug.ts
CHANGED
|
@@ -1,40 +1,95 @@
|
|
|
1
1
|
// Debug visualization tools for Unreal Engine
|
|
2
2
|
import { UnrealBridge } from '../unreal-bridge.js';
|
|
3
|
+
import { bestEffortInterpretedText, coerceString, interpretStandardResult } from '../utils/result-helpers.js';
|
|
4
|
+
import { parseStandardResult } from '../utils/python-output.js';
|
|
3
5
|
|
|
4
6
|
export class DebugVisualizationTools {
|
|
5
7
|
constructor(private bridge: UnrealBridge) {}
|
|
6
8
|
|
|
7
|
-
// Execute console command (kept for legacy operations)
|
|
8
|
-
private async _executeCommand(command: string) {
|
|
9
|
-
return this.bridge.httpCall('/remote/object/call', 'PUT', {
|
|
10
|
-
objectPath: '/Script/Engine.Default__KismetSystemLibrary',
|
|
11
|
-
functionName: 'ExecuteConsoleCommand',
|
|
12
|
-
parameters: {
|
|
13
|
-
WorldContextObject: null,
|
|
14
|
-
Command: command,
|
|
15
|
-
SpecificPlayer: null
|
|
16
|
-
},
|
|
17
|
-
generateTransaction: false
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
|
|
21
9
|
// Helper to draw via Python SystemLibrary with the editor world
|
|
22
|
-
private async pyDraw(scriptBody: string) {
|
|
10
|
+
private async pyDraw(scriptBody: string, meta?: { action: string; params?: Record<string, unknown> }) {
|
|
11
|
+
const action = (meta?.action || 'debug_draw').replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
12
|
+
const payloadObject = meta?.params ?? {};
|
|
13
|
+
const payloadJson = JSON.stringify(payloadObject).replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
14
|
+
const indentedBody = scriptBody
|
|
15
|
+
.split(/\r?\n/)
|
|
16
|
+
.map(line => ` ${line}`)
|
|
17
|
+
.join('\n');
|
|
18
|
+
|
|
23
19
|
const script = `
|
|
24
20
|
import unreal
|
|
25
|
-
|
|
21
|
+
import json
|
|
22
|
+
|
|
23
|
+
payload = json.loads('${payloadJson}')
|
|
26
24
|
ues = unreal.get_editor_subsystem(unreal.UnrealEditorSubsystem)
|
|
27
25
|
if not ues:
|
|
28
26
|
raise Exception('UnrealEditorSubsystem not available')
|
|
29
27
|
world = ues.get_editor_world()
|
|
30
|
-
|
|
28
|
+
if not world:
|
|
29
|
+
raise Exception('Editor world unavailable')
|
|
30
|
+
try:
|
|
31
|
+
${indentedBody}
|
|
32
|
+
print('DEBUG_DRAW:' + json.dumps({'action': '${action}', 'params': payload}))
|
|
33
|
+
print('RESULT:' + json.dumps({'success': True, 'action': '${action}', 'params': payload}))
|
|
34
|
+
except Exception as e:
|
|
35
|
+
print('DEBUG_DRAW_ERROR:' + str(e))
|
|
36
|
+
print('RESULT:' + json.dumps({'success': False, 'action': '${action}', 'error': str(e)}))
|
|
31
37
|
`.trim()
|
|
32
38
|
.replace(/\r?\n/g, '\n');
|
|
39
|
+
|
|
33
40
|
try {
|
|
34
|
-
await this.bridge.executePython(script);
|
|
35
|
-
|
|
41
|
+
const response = await this.bridge.executePython(script);
|
|
42
|
+
let interpreted = interpretStandardResult(response, {
|
|
43
|
+
successMessage: `${action} executed`,
|
|
44
|
+
failureMessage: `${action} failed`
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const parsed = parseStandardResult(response);
|
|
48
|
+
const parsedPayload = parsed.data ?? {};
|
|
49
|
+
const parsedSuccessValue = (parsedPayload as any).success;
|
|
50
|
+
const normalizedSuccess = typeof parsedSuccessValue === 'string'
|
|
51
|
+
? ['true', '1', 'yes'].includes(parsedSuccessValue.toLowerCase())
|
|
52
|
+
: parsedSuccessValue === true;
|
|
53
|
+
|
|
54
|
+
if (!interpreted.success && normalizedSuccess) {
|
|
55
|
+
interpreted = {
|
|
56
|
+
...interpreted,
|
|
57
|
+
success: true,
|
|
58
|
+
error: undefined,
|
|
59
|
+
message: interpreted.message || `${action} executed`,
|
|
60
|
+
payload: { ...parsedPayload }
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const finalSuccess = interpreted.success || normalizedSuccess;
|
|
65
|
+
|
|
66
|
+
const resolvedAction = coerceString(interpreted.payload.action) ?? action;
|
|
67
|
+
const fallbackOutput = typeof parsed.text === 'string' ? parsed.text : '';
|
|
68
|
+
const rawOutput = bestEffortInterpretedText(interpreted) ?? (fallbackOutput ? fallbackOutput : undefined);
|
|
69
|
+
|
|
70
|
+
if (finalSuccess) {
|
|
71
|
+
return {
|
|
72
|
+
...interpreted.payload,
|
|
73
|
+
success: true,
|
|
74
|
+
action: resolvedAction,
|
|
75
|
+
warnings: interpreted.warnings,
|
|
76
|
+
details: interpreted.details,
|
|
77
|
+
rawOutput,
|
|
78
|
+
raw: parsed.raw ?? interpreted.raw
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
success: false,
|
|
84
|
+
action: resolvedAction,
|
|
85
|
+
error: interpreted.error ?? `${resolvedAction} failed`,
|
|
86
|
+
warnings: interpreted.warnings,
|
|
87
|
+
details: interpreted.details,
|
|
88
|
+
rawOutput,
|
|
89
|
+
raw: parsed.raw ?? interpreted.raw
|
|
90
|
+
};
|
|
36
91
|
} catch (e) {
|
|
37
|
-
return { success: false, error: String(e) };
|
|
92
|
+
return { success: false, error: String(e), action: meta?.action || 'debug_draw' };
|
|
38
93
|
}
|
|
39
94
|
}
|
|
40
95
|
|
|
@@ -58,7 +113,16 @@ end = unreal.Vector(${ex}, ${ey}, ${ez})
|
|
|
58
113
|
color = unreal.LinearColor(${sr}/255.0, ${sg}/255.0, ${sb}/255.0, ${sa}/255.0)
|
|
59
114
|
unreal.SystemLibrary.draw_debug_line(world, start, end, color, ${duration}, ${thickness})
|
|
60
115
|
`;
|
|
61
|
-
return this.pyDraw(script
|
|
116
|
+
return this.pyDraw(script, {
|
|
117
|
+
action: 'debug_line',
|
|
118
|
+
params: {
|
|
119
|
+
start: params.start,
|
|
120
|
+
end: params.end,
|
|
121
|
+
color,
|
|
122
|
+
duration,
|
|
123
|
+
thickness
|
|
124
|
+
}
|
|
125
|
+
});
|
|
62
126
|
}
|
|
63
127
|
|
|
64
128
|
// Draw debug box using Python SystemLibrary
|
|
@@ -85,7 +149,17 @@ rot = unreal.Rotator(${rp}, ${ry}, ${rr})
|
|
|
85
149
|
color = unreal.LinearColor(${cr}/255.0, ${cg}/255.0, ${cb}/255.0, ${ca}/255.0)
|
|
86
150
|
unreal.SystemLibrary.draw_debug_box(world, center, extent, color, rot, ${duration}, ${thickness})
|
|
87
151
|
`;
|
|
88
|
-
return this.pyDraw(script
|
|
152
|
+
return this.pyDraw(script, {
|
|
153
|
+
action: 'debug_box',
|
|
154
|
+
params: {
|
|
155
|
+
center: params.center,
|
|
156
|
+
extent: params.extent,
|
|
157
|
+
rotation,
|
|
158
|
+
color,
|
|
159
|
+
duration,
|
|
160
|
+
thickness
|
|
161
|
+
}
|
|
162
|
+
});
|
|
89
163
|
}
|
|
90
164
|
|
|
91
165
|
// Draw debug sphere using Python SystemLibrary
|
|
@@ -108,7 +182,17 @@ center = unreal.Vector(${cx}, ${cy}, ${cz})
|
|
|
108
182
|
color = unreal.LinearColor(${cr}/255.0, ${cg}/255.0, ${cb}/255.0, ${ca}/255.0)
|
|
109
183
|
unreal.SystemLibrary.draw_debug_sphere(world, center, ${params.radius}, ${segments}, color, ${duration}, ${thickness})
|
|
110
184
|
`;
|
|
111
|
-
return this.pyDraw(script
|
|
185
|
+
return this.pyDraw(script, {
|
|
186
|
+
action: 'debug_sphere',
|
|
187
|
+
params: {
|
|
188
|
+
center: params.center,
|
|
189
|
+
radius: params.radius,
|
|
190
|
+
segments,
|
|
191
|
+
color,
|
|
192
|
+
duration,
|
|
193
|
+
thickness
|
|
194
|
+
}
|
|
195
|
+
});
|
|
112
196
|
}
|
|
113
197
|
|
|
114
198
|
// The rest keep console-command fallbacks or editor helpers as before
|
|
@@ -128,7 +212,17 @@ unreal.SystemLibrary.draw_debug_sphere(world, center, ${params.radius}, ${segmen
|
|
|
128
212
|
const [rp, ry, rr] = rotation;
|
|
129
213
|
const [cr, cg, cb, ca] = color;
|
|
130
214
|
const script = `\ncenter = unreal.Vector(${cx}, ${cy}, ${cz})\nrot = unreal.Rotator(${rp}, ${ry}, ${rr})\ncolor = unreal.LinearColor(${cr}/255.0, ${cg}/255.0, ${cb}/255.0, ${ca}/255.0)\nunreal.SystemLibrary.draw_debug_capsule(world, center, ${params.halfHeight}, ${params.radius}, rot, color, ${duration}, 1.0)\n`;
|
|
131
|
-
return this.pyDraw(script
|
|
215
|
+
return this.pyDraw(script, {
|
|
216
|
+
action: 'debug_capsule',
|
|
217
|
+
params: {
|
|
218
|
+
center: params.center,
|
|
219
|
+
halfHeight: params.halfHeight,
|
|
220
|
+
radius: params.radius,
|
|
221
|
+
rotation,
|
|
222
|
+
color,
|
|
223
|
+
duration
|
|
224
|
+
}
|
|
225
|
+
});
|
|
132
226
|
}
|
|
133
227
|
|
|
134
228
|
async drawDebugCone(params: {
|
|
@@ -147,7 +241,19 @@ unreal.SystemLibrary.draw_debug_sphere(world, center, ${params.radius}, ${segmen
|
|
|
147
241
|
const [dx, dy, dz] = params.direction;
|
|
148
242
|
const [cr, cg, cb, ca] = color;
|
|
149
243
|
const script = `\norigin = unreal.Vector(${ox}, ${oy}, ${oz})\ndir = unreal.Vector(${dx}, ${dy}, ${dz})\ncolor = unreal.LinearColor(${cr}/255.0, ${cg}/255.0, ${cb}/255.0, ${ca}/255.0)\nunreal.SystemLibrary.draw_debug_cone(world, origin, dir, ${params.length}, ${params.angleWidth}, ${params.angleHeight}, ${params.numSides || 12}, color, ${duration}, 1.0)\n`;
|
|
150
|
-
return this.pyDraw(script
|
|
244
|
+
return this.pyDraw(script, {
|
|
245
|
+
action: 'debug_cone',
|
|
246
|
+
params: {
|
|
247
|
+
origin: params.origin,
|
|
248
|
+
direction: params.direction,
|
|
249
|
+
length: params.length,
|
|
250
|
+
angleWidth: params.angleWidth,
|
|
251
|
+
angleHeight: params.angleHeight,
|
|
252
|
+
numSides: params.numSides || 12,
|
|
253
|
+
color,
|
|
254
|
+
duration
|
|
255
|
+
}
|
|
256
|
+
});
|
|
151
257
|
}
|
|
152
258
|
|
|
153
259
|
async drawDebugString(params: {
|
|
@@ -162,7 +268,16 @@ unreal.SystemLibrary.draw_debug_sphere(world, center, ${params.radius}, ${segmen
|
|
|
162
268
|
const [x, y, z] = params.location;
|
|
163
269
|
const [r, g, b, a] = color;
|
|
164
270
|
const script = `\nloc = unreal.Vector(${x}, ${y}, ${z})\ncolor = unreal.LinearColor(${r}/255.0, ${g}/255.0, ${b}/255.0, ${a}/255.0)\nunreal.SystemLibrary.draw_debug_string(world, loc, "${params.text.replace(/"/g, '\\"')}", None, color, ${duration})\n`;
|
|
165
|
-
return this.pyDraw(script
|
|
271
|
+
return this.pyDraw(script, {
|
|
272
|
+
action: 'debug_string',
|
|
273
|
+
params: {
|
|
274
|
+
location: params.location,
|
|
275
|
+
text: params.text,
|
|
276
|
+
color,
|
|
277
|
+
duration,
|
|
278
|
+
fontSize: params.fontSize
|
|
279
|
+
}
|
|
280
|
+
});
|
|
166
281
|
}
|
|
167
282
|
|
|
168
283
|
async drawDebugArrow(params: {
|
|
@@ -180,7 +295,17 @@ unreal.SystemLibrary.draw_debug_sphere(world, center, ${params.radius}, ${segmen
|
|
|
180
295
|
const [ex, ey, ez] = params.end;
|
|
181
296
|
const [r, g, b, a] = color;
|
|
182
297
|
const script = `\nstart = unreal.Vector(${sx}, ${sy}, ${sz})\nend = unreal.Vector(${ex}, ${ey}, ${ez})\ncolor = unreal.LinearColor(${r}/255.0, ${g}/255.0, ${b}/255.0, ${a}/255.0)\nunreal.SystemLibrary.draw_debug_arrow(world, start, end, ${params.arrowSize || 10.0}, color, ${duration}, ${thickness})\n`;
|
|
183
|
-
return this.pyDraw(script
|
|
298
|
+
return this.pyDraw(script, {
|
|
299
|
+
action: 'debug_arrow',
|
|
300
|
+
params: {
|
|
301
|
+
start: params.start,
|
|
302
|
+
end: params.end,
|
|
303
|
+
arrowSize: params.arrowSize || 10.0,
|
|
304
|
+
color,
|
|
305
|
+
duration,
|
|
306
|
+
thickness
|
|
307
|
+
}
|
|
308
|
+
});
|
|
184
309
|
}
|
|
185
310
|
|
|
186
311
|
async drawDebugPoint(params: {
|
|
@@ -195,7 +320,15 @@ unreal.SystemLibrary.draw_debug_sphere(world, center, ${params.radius}, ${segmen
|
|
|
195
320
|
const [x, y, z] = params.location;
|
|
196
321
|
const [r, g, b, a] = color;
|
|
197
322
|
const script = `\nloc = unreal.Vector(${x}, ${y}, ${z})\ncolor = unreal.LinearColor(${r}/255.0, ${g}/255.0, ${b}/255.0, ${a}/255.0)\nunreal.SystemLibrary.draw_debug_point(world, loc, ${size}, color, ${duration})\n`;
|
|
198
|
-
return this.pyDraw(script
|
|
323
|
+
return this.pyDraw(script, {
|
|
324
|
+
action: 'debug_point',
|
|
325
|
+
params: {
|
|
326
|
+
location: params.location,
|
|
327
|
+
size,
|
|
328
|
+
color,
|
|
329
|
+
duration
|
|
330
|
+
}
|
|
331
|
+
});
|
|
199
332
|
}
|
|
200
333
|
|
|
201
334
|
async drawDebugCoordinateSystem(params: {
|
|
@@ -232,7 +365,19 @@ unreal.SystemLibrary.draw_debug_sphere(world, center, ${params.radius}, ${segmen
|
|
|
232
365
|
const [rp, ry, rr] = params.rotation;
|
|
233
366
|
const [r, g, b, a] = color;
|
|
234
367
|
const script = `\norigin = unreal.Vector(${ox}, ${oy}, ${oz})\nrot = unreal.Rotator(${rp}, ${ry}, ${rr})\ncolor = unreal.LinearColor(${r}/255.0, ${g}/255.0, ${b}/255.0, ${a}/255.0)\nunreal.SystemLibrary.draw_debug_frustum(world, origin, rot, ${params.fov}, ${aspectRatio}, ${nearPlane}, ${farPlane}, color, ${duration})\n`;
|
|
235
|
-
return this.pyDraw(script
|
|
368
|
+
return this.pyDraw(script, {
|
|
369
|
+
action: 'debug_frustum',
|
|
370
|
+
params: {
|
|
371
|
+
origin: params.origin,
|
|
372
|
+
rotation: params.rotation,
|
|
373
|
+
fov: params.fov,
|
|
374
|
+
aspectRatio,
|
|
375
|
+
nearPlane,
|
|
376
|
+
farPlane,
|
|
377
|
+
color,
|
|
378
|
+
duration
|
|
379
|
+
}
|
|
380
|
+
});
|
|
236
381
|
}
|
|
237
382
|
|
|
238
383
|
async clearDebugDrawings() {
|
|
@@ -243,16 +388,14 @@ unreal.SystemLibrary.draw_debug_sphere(world, center, ${params.radius}, ${segmen
|
|
|
243
388
|
enabled: boolean;
|
|
244
389
|
type?: 'Simple' | 'Complex' | 'Both';
|
|
245
390
|
}) {
|
|
246
|
-
|
|
391
|
+
const commands: string[] = [];
|
|
247
392
|
if (params.enabled) {
|
|
248
393
|
const typeCmd = params.type === 'Simple' ? '1' : params.type === 'Complex' ? '2' : '3';
|
|
249
394
|
commands.push(`show Collision ${typeCmd}`);
|
|
250
395
|
} else {
|
|
251
396
|
commands.push('show Collision 0');
|
|
252
397
|
}
|
|
253
|
-
|
|
254
|
-
await this.bridge.executeConsoleCommand(cmd);
|
|
255
|
-
}
|
|
398
|
+
await this.bridge.executeConsoleCommands(commands);
|
|
256
399
|
return { success: true, message: `Collision visualization ${params.enabled ? 'enabled' : 'disabled'}` };
|
|
257
400
|
}
|
|
258
401
|
|
package/src/tools/editor.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { UnrealBridge } from '../unreal-bridge.js';
|
|
2
2
|
import { toVec3Object, toRotObject } from '../utils/normalize.js';
|
|
3
|
+
import { bestEffortInterpretedText, coerceString, interpretStandardResult } from '../utils/result-helpers.js';
|
|
3
4
|
|
|
4
5
|
export class EditorTools {
|
|
5
6
|
constructor(private bridge: UnrealBridge) {}
|
|
@@ -69,26 +70,13 @@ else:
|
|
|
69
70
|
`.trim();
|
|
70
71
|
|
|
71
72
|
const resp: any = await this.bridge.executePython(pythonCmd);
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return { success: true, message: `PIE started (via ${method})` };
|
|
80
|
-
}
|
|
81
|
-
} catch {
|
|
82
|
-
try {
|
|
83
|
-
// Fallback: handle non-JSON python dict-style output
|
|
84
|
-
const sanitized = m[1].replace(/'/g, '"').replace(/\bTrue\b/g, 'true').replace(/\bFalse\b/g, 'false');
|
|
85
|
-
const parsed = JSON.parse(sanitized);
|
|
86
|
-
if (parsed.success) {
|
|
87
|
-
const method = parsed.method || 'LevelEditorSubsystem';
|
|
88
|
-
return { success: true, message: `PIE started (via ${method})` };
|
|
89
|
-
}
|
|
90
|
-
} catch {}
|
|
91
|
-
}
|
|
73
|
+
const interpreted = interpretStandardResult(resp, {
|
|
74
|
+
successMessage: 'PIE started',
|
|
75
|
+
failureMessage: 'Failed to start PIE'
|
|
76
|
+
});
|
|
77
|
+
if (interpreted.success) {
|
|
78
|
+
const method = coerceString(interpreted.payload.method) ?? 'LevelEditorSubsystem';
|
|
79
|
+
return { success: true, message: `PIE started (via ${method})` };
|
|
92
80
|
}
|
|
93
81
|
// If not verified, fall through to fallback
|
|
94
82
|
} catch (err) {
|
|
@@ -129,19 +117,21 @@ else:
|
|
|
129
117
|
print('RESULT:' + json.dumps({'success': False, 'error': 'LevelEditorSubsystem not available'}))
|
|
130
118
|
`.trim();
|
|
131
119
|
const resp: any = await this.bridge.executePython(pythonCmd);
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
120
|
+
const interpreted = interpretStandardResult(resp, {
|
|
121
|
+
successMessage: 'PIE stopped successfully',
|
|
122
|
+
failureMessage: 'Failed to stop PIE'
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
if (interpreted.success) {
|
|
126
|
+
const method = coerceString(interpreted.payload.method) ?? 'LevelEditorSubsystem';
|
|
127
|
+
return { success: true, message: `PIE stopped via ${method}` };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (interpreted.error) {
|
|
131
|
+
return { success: false, error: interpreted.error };
|
|
142
132
|
}
|
|
143
|
-
|
|
144
|
-
return { success:
|
|
133
|
+
|
|
134
|
+
return { success: false, error: 'Failed to stop PIE' };
|
|
145
135
|
} catch {
|
|
146
136
|
// Fallback to console command
|
|
147
137
|
await this.bridge.executeConsoleCommand('stop');
|
|
@@ -196,12 +186,20 @@ except Exception as e:
|
|
|
196
186
|
print('RESULT:' + json.dumps({'success': False, 'error': str(e)}))
|
|
197
187
|
`.trim();
|
|
198
188
|
const resp: any = await this.bridge.executePython(py);
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
189
|
+
const interpreted = interpretStandardResult(resp, {
|
|
190
|
+
successMessage: 'Lighting build started',
|
|
191
|
+
failureMessage: 'Failed to build lighting'
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
if (interpreted.success) {
|
|
195
|
+
return { success: true, message: interpreted.message };
|
|
203
196
|
}
|
|
204
|
-
|
|
197
|
+
|
|
198
|
+
return {
|
|
199
|
+
success: false,
|
|
200
|
+
error: interpreted.error ?? 'Failed to build lighting',
|
|
201
|
+
details: bestEffortInterpretedText(interpreted)
|
|
202
|
+
};
|
|
205
203
|
} catch (err) {
|
|
206
204
|
return { success: false, error: `Failed to build lighting: ${err}` };
|
|
207
205
|
}
|