Quaternius weapons, input fixes, sound & path fixes
- Added 6 Quaternius weapon models (Pistol, Revolver, Rifle, Shotgun, P90, SniperRifle) - Created weapon resource files with balanced stats - Wired Pistol + Rifle into player.tscn replacing Kenney blasters - Fixed WASD input (matched input map action names) - Fixed Escape key toggles mouse capture - Added Audio autoload singleton - Fixed broken sound asset paths across all scripts - Fixed all scene ext_resource text paths (nested under assets/kenney-fps/) - Fixed all .import source_file paths - Deleted stale .import files (will be regenerated by editor on open)
This commit is contained in:
Vendored
+248
@@ -0,0 +1,248 @@
|
||||
import type { ChildProcess } from 'child_process';
|
||||
/**
|
||||
* Thrown when the bridge socket closes (Godot exited, port closed, or peer
|
||||
* dropped the connection mid-flight). Lets callers distinguish
|
||||
* "session ended" from generic transport errors.
|
||||
*/
|
||||
export declare class BridgeDisconnectedError extends Error {
|
||||
constructor(message: string);
|
||||
}
|
||||
export declare const BRIDGE_WAIT_SPAWNED_TIMEOUT_MS = 8000;
|
||||
/**
|
||||
* Normalize a path for cross-platform comparison.
|
||||
* Folds Windows backslashes to forward slashes and strips trailing slashes,
|
||||
* so Node's `path.normalize` output matches Godot's `globalize_path("res://")`.
|
||||
*/
|
||||
export declare function normalizeForCompare(p: string): string;
|
||||
/**
|
||||
* Extract JSON from Godot output by finding the first { or [ and matching to the end.
|
||||
* This strips debug logs, version banners, and other noise.
|
||||
*/
|
||||
export declare function extractJson(output: string): string;
|
||||
/**
|
||||
* Strip Godot banner and debug lines from output, keeping only meaningful content.
|
||||
*/
|
||||
export declare function cleanOutput(output: string): string;
|
||||
export declare function cleanStdout(stdout: string): string;
|
||||
export interface GodotProcess {
|
||||
process: ChildProcess;
|
||||
output: string[];
|
||||
errors: string[];
|
||||
totalErrorsWritten: number;
|
||||
exitCode: number | null;
|
||||
hasExited: boolean;
|
||||
sessionToken: string;
|
||||
}
|
||||
export type RuntimeSessionMode = 'spawned' | 'attached';
|
||||
export interface RuntimeStopResult {
|
||||
mode: RuntimeSessionMode;
|
||||
output: string[];
|
||||
errors: string[];
|
||||
externalProcessPreserved?: boolean;
|
||||
}
|
||||
export interface GodotServerConfig {
|
||||
godotPath?: string;
|
||||
debugMode?: boolean;
|
||||
}
|
||||
export interface OperationParams {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
export interface OperationResult {
|
||||
stdout: string;
|
||||
stderr: string;
|
||||
}
|
||||
export interface ToolAnnotations {
|
||||
readOnlyHint?: boolean;
|
||||
destructiveHint?: boolean;
|
||||
idempotentHint?: boolean;
|
||||
openWorldHint?: boolean;
|
||||
title?: string;
|
||||
}
|
||||
export interface ToolDefinition {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: string;
|
||||
properties: Record<string, unknown>;
|
||||
required: string[];
|
||||
};
|
||||
outputSchema?: {
|
||||
type: string;
|
||||
properties?: Record<string, unknown>;
|
||||
required?: string[];
|
||||
};
|
||||
annotations?: ToolAnnotations;
|
||||
}
|
||||
export interface ToolResponse {
|
||||
content: Array<{
|
||||
type: string;
|
||||
text?: string;
|
||||
[k: string]: unknown;
|
||||
}>;
|
||||
isError?: boolean;
|
||||
structuredContent?: Record<string, unknown>;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
export type ToolHandler = (runner: GodotRunner, args: OperationParams) => Promise<ToolResponse> | ToolResponse;
|
||||
export declare function normalizeParameters(params: OperationParams): OperationParams;
|
||||
export declare function convertCamelToSnakeCase(params: OperationParams): OperationParams;
|
||||
/**
|
||||
* Check whether a display server (X11 / Wayland) is available on the current
|
||||
* platform. On macOS and Windows the display subsystem is always present;
|
||||
* on Linux we probe the standard environment variables.
|
||||
*/
|
||||
export declare function checkDisplayAvailable(): boolean;
|
||||
export declare function validatePath(path: string): boolean;
|
||||
/**
|
||||
* Stricter check for paths that must stay inside `projectPath`. Rejects `..`
|
||||
* (via `validatePath`) and absolute paths that escape the project root.
|
||||
* `path.join('/project', '/etc/passwd')` resolves to `/etc/passwd`, so the
|
||||
* basic `..`-substring check alone permits absolute-path traversal.
|
||||
*
|
||||
* Tolerates a leading `res://` (Godot's project-root URI) by stripping it
|
||||
* before resolving — autoload entries and resource paths use this prefix.
|
||||
*/
|
||||
export declare function validateSubPath(projectPath: string, userPath: string): boolean;
|
||||
/**
|
||||
* Validate a Godot scene-tree path (NodePath). Scene-tree paths are a
|
||||
* separate namespace from filesystem paths — they address nodes inside
|
||||
* a scene, not files on disk, so the project-root containment check
|
||||
* in `validateSubPath` does not apply.
|
||||
*
|
||||
* Rejects empty strings and `..` segments. Accepts both relative
|
||||
* (`root/Player`) and absolute (`/root/Player`) Godot forms; the
|
||||
* codebase convention is the relative form.
|
||||
*/
|
||||
export declare function validateNodePath(path: string): boolean;
|
||||
/**
|
||||
* True when `child` resolves to `parent` or a path beneath it. Used by
|
||||
* defense-in-depth checks on bridge-returned paths (e.g. screenshot files
|
||||
* that must live under `.mcp/screenshots/`).
|
||||
*/
|
||||
export declare function isUnderDir(parent: string, child: string): boolean;
|
||||
/**
|
||||
* Return `error.message` when `error` is an `Error`, otherwise `'Unknown error'`.
|
||||
* Centralizes the catch-block boilerplate so handlers can build error responses
|
||||
* without repeating the `instanceof Error` ternary.
|
||||
*/
|
||||
export declare function getErrorMessage(error: unknown): string;
|
||||
/**
|
||||
* Build the absolute path to a project's `project.godot` manifest. Use this
|
||||
* instead of `join(dir, 'project.godot')` ad hoc.
|
||||
*/
|
||||
export declare function projectGodotPath(projectDir: string): string;
|
||||
/**
|
||||
* Extract the first [ERROR] message from GDScript stderr output.
|
||||
* Falls back to a generic message if no [ERROR] line is found.
|
||||
*/
|
||||
export declare function extractGdError(stderr: string): string;
|
||||
export declare function createErrorResponse(message: string, possibleSolutions?: string[]): {
|
||||
content: Array<{
|
||||
type: 'text';
|
||||
text: string;
|
||||
}>;
|
||||
isError: boolean;
|
||||
};
|
||||
/**
|
||||
* Wrap a structured payload as a ToolResponse that satisfies the MCP
|
||||
* outputSchema contract. The same payload is emitted both as a JSON text
|
||||
* content block (for lenient clients) and as `structuredContent` (required
|
||||
* by strict clients per MCP spec revision 2025-06-18).
|
||||
*
|
||||
* `extraContent` is prepended for handlers that also return non-text blocks
|
||||
* (e.g. `take_screenshot`'s inline image).
|
||||
*/
|
||||
export declare function createStructuredResponse<T extends Record<string, unknown>>(payload: T, extraContent?: Array<{
|
||||
type: string;
|
||||
[k: string]: unknown;
|
||||
}>): ToolResponse;
|
||||
interface ValidatedProjectArgs {
|
||||
projectPath: string;
|
||||
}
|
||||
interface ValidatedSceneArgs {
|
||||
projectPath: string;
|
||||
scenePath: string;
|
||||
}
|
||||
type ValidationErrorResult = ReturnType<typeof createErrorResponse>;
|
||||
export declare function validateProjectArgs(args: OperationParams): ValidatedProjectArgs | ValidationErrorResult;
|
||||
export declare function validateSceneArgs(args: OperationParams, opts?: {
|
||||
sceneRequired?: boolean;
|
||||
}): ValidatedSceneArgs | ValidationErrorResult;
|
||||
export declare class GodotRunner {
|
||||
private godotPath;
|
||||
private operationsScriptPath;
|
||||
private bridge;
|
||||
private validatedPaths;
|
||||
private cachedVersion;
|
||||
activeProcess: GodotProcess | null;
|
||||
activeProjectPath: string | null;
|
||||
activeSessionMode: RuntimeSessionMode | null;
|
||||
activeBridgePort: number | null;
|
||||
private socket;
|
||||
private rxChunks;
|
||||
private rxTotal;
|
||||
private inFlight;
|
||||
constructor(config?: GodotServerConfig);
|
||||
private isValidGodotPathSync;
|
||||
private spawnAsync;
|
||||
private isValidGodotPath;
|
||||
detectGodotPath(): Promise<void>;
|
||||
getGodotPath(): string | null;
|
||||
/**
|
||||
* Read the port currently baked into the project's bridge script. Returns
|
||||
* null if the file is missing or malformed. Thin pass-through to
|
||||
* BridgeManager — used by bridge-wait-timeout race detection.
|
||||
*/
|
||||
readBakedBridgePort(projectPath: string): number | null;
|
||||
getVersion(): Promise<string>;
|
||||
executeOperation(operation: string, params: OperationParams, projectPath: string, timeoutMs?: number): Promise<OperationResult>;
|
||||
launchEditor(projectPath: string): ChildProcess;
|
||||
runProject(projectPath: string, scene?: string, background?: boolean, bridgePort?: number): Promise<GodotProcess>;
|
||||
attachProject(projectPath: string, bridgePort?: number): Promise<void>;
|
||||
stopProject(): Promise<RuntimeStopResult | null>;
|
||||
hasActiveRuntimeSession(): boolean;
|
||||
/**
|
||||
* Send a JSON command to the McpBridge over a long-lived TCP connection.
|
||||
*
|
||||
* MCP serializes tool calls so we hold one in-flight command at a time. The
|
||||
* socket is lazy-connected on first call and persists across commands until
|
||||
* `closeConnection` (or a peer-side close). A close mid-flight rejects with
|
||||
* `BridgeDisconnectedError`; a per-command timeout rejects but does NOT
|
||||
* close the socket — a slow command does not invalidate the session.
|
||||
*/
|
||||
sendCommand(command: string, params?: Record<string, unknown>, timeoutMs?: number): Promise<string>;
|
||||
/**
|
||||
* Tear down the bridge socket. Idempotent. Any in-flight command is
|
||||
* rejected with a session-ended error.
|
||||
*/
|
||||
closeConnection(): void;
|
||||
private resetRxBuffer;
|
||||
getErrorCount(): number;
|
||||
getErrorsSince(marker: number): string[];
|
||||
private static readonly SCRIPT_ERROR_PATTERNS;
|
||||
private static readonly RETRYABLE_BRIDGE_COMMANDS;
|
||||
extractRuntimeErrors(lines: string[]): string[];
|
||||
private sendCommandWithReconnect;
|
||||
sendCommandWithErrors(command: string, params?: Record<string, unknown>, timeoutMs?: number): Promise<{
|
||||
response: string;
|
||||
runtimeErrors: string[];
|
||||
}>;
|
||||
/**
|
||||
* Shared poll loop for `waitForBridge` (spawned) and `waitForBridgeAttached`.
|
||||
* Sends `ping` payloads until the bridge replies with a pong that
|
||||
* `validatePong` accepts, the deadline passes, or `shouldAbort` reports
|
||||
* the spawned process has exited.
|
||||
*/
|
||||
private pollBridge;
|
||||
waitForBridgeAttached(timeoutMs?: number, intervalMs?: number): Promise<{
|
||||
ready: boolean;
|
||||
error?: string;
|
||||
}>;
|
||||
waitForBridge(timeoutMs?: number, intervalMs?: number): Promise<{
|
||||
ready: boolean;
|
||||
error?: string;
|
||||
}>;
|
||||
getRecentErrors(count?: number): string[];
|
||||
}
|
||||
export {};
|
||||
//# sourceMappingURL=godot-runner.d.ts.map
|
||||
Reference in New Issue
Block a user