Files
tactical-shooter/package/dist/tools/autoload-tools.js
T
shawn 91b878f347 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)
2026-07-05 22:53:27 -04:00

191 lines
8.9 KiB
JavaScript

import { readFileSync } from 'fs';
import { normalizeParameters, validateSubPath, validateProjectArgs, createErrorResponse, getErrorMessage, projectGodotPath, } from '../utils/godot-runner.js';
import { parseAutoloads, addAutoloadEntry, removeAutoloadEntry, updateAutoloadEntry, } from '../utils/autoload-ini.js';
// --- Tool definitions ---
export const autoloadToolDefinitions = [
{
name: 'list_autoloads',
description: 'List all registered autoloads in a project with paths and singleton status. Use first when diagnosing headless failures — broken autoloads crash all headless ops, so this tells you what is loaded. No Godot process required (reads project.godot directly). Returns: [{ name, path, singleton }].',
annotations: { readOnlyHint: true },
inputSchema: {
type: 'object',
properties: {
projectPath: { type: 'string', description: 'Path to the Godot project directory' },
},
required: ['projectPath'],
},
},
{
name: 'add_autoload',
description: 'Register a new autoload in a project. autoloadPath accepts "res://..." or a project-relative path (auto-prefixed). singleton defaults true (accessible globally by name). No Godot process required. Warning: autoloads initialize in headless mode — a broken script will crash every subsequent headless op; validate before adding. Returns plain-text confirmation with the registered name, path, and singleton flag. Errors if an autoload with the same name already exists; use update_autoload to modify.',
inputSchema: {
type: 'object',
properties: {
projectPath: { type: 'string', description: 'Path to the Godot project directory' },
autoloadName: {
type: 'string',
description: 'Name of the autoload node (e.g. "MyManager")',
},
autoloadPath: {
type: 'string',
description: 'Path to the script or scene (e.g. "res://autoload/my_manager.gd" or "autoload/my_manager.gd")',
},
singleton: {
type: 'boolean',
description: 'Register as a globally accessible singleton by name (default: true)',
},
},
required: ['projectPath', 'autoloadName', 'autoloadPath'],
},
},
{
name: 'remove_autoload',
description: 'Unregister an autoload from a project by name. Use to recover from a broken autoload that is crashing headless ops. No Godot process required. Returns plain-text confirmation on success. Errors if no autoload with that name exists.',
annotations: { destructiveHint: true },
inputSchema: {
type: 'object',
properties: {
projectPath: { type: 'string', description: 'Path to the Godot project directory' },
autoloadName: { type: 'string', description: 'Name of the autoload to remove' },
},
required: ['projectPath', 'autoloadName'],
},
},
{
name: 'update_autoload',
description: "Modify an existing autoload's path or singleton flag. Pass either or both — omitted fields keep their current value. Use instead of remove_autoload + add_autoload (single edit, no orphan window). No Godot process required. Returns plain-text confirmation on success. Errors if autoloadName is not registered.",
annotations: { idempotentHint: true },
inputSchema: {
type: 'object',
properties: {
projectPath: { type: 'string', description: 'Path to the Godot project directory' },
autoloadName: { type: 'string', description: 'Name of the autoload to update' },
autoloadPath: { type: 'string', description: 'New path to the script or scene' },
singleton: { type: 'boolean', description: 'New singleton flag' },
},
required: ['projectPath', 'autoloadName'],
},
},
];
// --- Handlers ---
export function handleListAutoloads(args) {
args = normalizeParameters(args);
const v = validateProjectArgs(args);
if ('isError' in v)
return v;
try {
const projectFile = projectGodotPath(v.projectPath);
const autoloads = parseAutoloads(projectFile);
return { content: [{ type: 'text', text: JSON.stringify(autoloads) }] };
}
catch (error) {
return createErrorResponse(`Failed to list autoloads: ${getErrorMessage(error)}`, [
'Check if project.godot is accessible',
]);
}
}
export function handleAddAutoload(args) {
args = normalizeParameters(args);
const v = validateProjectArgs(args);
if ('isError' in v)
return v;
if (!args.autoloadName || !args.autoloadPath) {
return createErrorResponse('autoloadName and autoloadPath are required', [
'Provide the autoload node name and script/scene path',
]);
}
if (!validateSubPath(v.projectPath, args.autoloadPath)) {
return createErrorResponse('Invalid autoload path', [
'Provide a valid relative path or res:// URI that stays inside the project directory',
]);
}
try {
const projectFile = projectGodotPath(v.projectPath);
const projectFileContent = readFileSync(projectFile, 'utf8');
const existing = parseAutoloads(projectFile, projectFileContent);
if (existing.some((a) => a.name === args.autoloadName)) {
return createErrorResponse(`Autoload '${args.autoloadName}' already exists`, [
'Use update_autoload to modify it',
'Use list_autoloads to see current autoloads',
]);
}
const isSingleton = args.singleton !== false;
addAutoloadEntry(projectFile, args.autoloadName, args.autoloadPath, isSingleton, projectFileContent);
return {
content: [
{
type: 'text',
text: `Autoload '${args.autoloadName}' registered at '${args.autoloadPath}' (singleton: ${isSingleton}).\nWarning: autoloads initialize in headless mode too. If this script has errors, all headless operations will fail. Verify by running get_scene_tree — if it fails, use remove_autoload to remove it.`,
},
],
};
}
catch (error) {
return createErrorResponse(`Failed to add autoload: ${getErrorMessage(error)}`, [
'Check if project.godot is accessible',
]);
}
}
export function handleRemoveAutoload(args) {
args = normalizeParameters(args);
const v = validateProjectArgs(args);
if ('isError' in v)
return v;
if (!args.autoloadName) {
return createErrorResponse('autoloadName is required', [
'Provide the name of the autoload to remove',
]);
}
try {
const projectFile = projectGodotPath(v.projectPath);
const removed = removeAutoloadEntry(projectFile, args.autoloadName);
if (!removed) {
return createErrorResponse(`Autoload '${args.autoloadName}' not found`, [
'Use list_autoloads to see existing autoloads',
]);
}
return {
content: [{ type: 'text', text: `Autoload '${args.autoloadName}' removed successfully.` }],
};
}
catch (error) {
return createErrorResponse(`Failed to remove autoload: ${getErrorMessage(error)}`, [
'Check if project.godot is accessible',
]);
}
}
export function handleUpdateAutoload(args) {
args = normalizeParameters(args);
const v = validateProjectArgs(args);
if ('isError' in v)
return v;
if (!args.autoloadName) {
return createErrorResponse('autoloadName is required', [
'Provide the name of the autoload to update',
]);
}
if (args.autoloadPath && !validateSubPath(v.projectPath, args.autoloadPath)) {
return createErrorResponse('Invalid autoload path', [
'Provide a valid relative path or res:// URI that stays inside the project directory',
]);
}
try {
const projectFile = projectGodotPath(v.projectPath);
const updated = updateAutoloadEntry(projectFile, args.autoloadName, args.autoloadPath, args.singleton);
if (!updated) {
return createErrorResponse(`Autoload '${args.autoloadName}' not found`, [
'Use list_autoloads to see existing autoloads',
'Use add_autoload to register a new one',
]);
}
return {
content: [{ type: 'text', text: `Autoload '${args.autoloadName}' updated successfully.` }],
};
}
catch (error) {
return createErrorResponse(`Failed to update autoload: ${getErrorMessage(error)}`, [
'Check if project.godot is accessible',
]);
}
}
//# sourceMappingURL=autoload-tools.js.map