feat: add recursive crafting and recipe management endpoints for enhanced crafting capabilities
This commit is contained in:
@@ -588,6 +588,122 @@ app.post('/api/craft', (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Recursive craft (multi-step crafting chain)
|
||||||
|
app.post('/api/recursive-craft', (req, res) => {
|
||||||
|
try {
|
||||||
|
const { itemName, count, commandId } = req.body;
|
||||||
|
|
||||||
|
const cached = checkIdempotent(commandId);
|
||||||
|
if (cached) return res.json(cached);
|
||||||
|
|
||||||
|
if (!itemName || typeof itemName !== 'string' || itemName.length > 200) {
|
||||||
|
return res.status(400).json({ error: 'Missing or invalid itemName' });
|
||||||
|
}
|
||||||
|
const parsedCount = parseInt(count);
|
||||||
|
if (!Number.isFinite(parsedCount) || parsedCount < 1 || parsedCount > 100000) {
|
||||||
|
return res.status(400).json({ error: 'Invalid count (1–100000)' });
|
||||||
|
}
|
||||||
|
|
||||||
|
pushCommandToBridge({ type: 'command', action: 'recursive_craft', commandId, itemName, count: parsedCount });
|
||||||
|
const result = { success: true, commandId, message: `Recursive craft sent: ${itemName} x${count}` };
|
||||||
|
recordCommand(commandId, result);
|
||||||
|
console.log(`🔨 Recursive craft: ${itemName} x${count}`);
|
||||||
|
res.json(result);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Learn a crafting recipe
|
||||||
|
app.post('/api/recipes/learn-crafting', (req, res) => {
|
||||||
|
try {
|
||||||
|
const { output, count, grid, commandId } = req.body;
|
||||||
|
|
||||||
|
const cached = checkIdempotent(commandId);
|
||||||
|
if (cached) return res.json(cached);
|
||||||
|
|
||||||
|
if (!output || typeof output !== 'string' || output.length > 200) {
|
||||||
|
return res.status(400).json({ error: 'Missing or invalid output' });
|
||||||
|
}
|
||||||
|
if (!grid || !Array.isArray(grid) || grid.length !== 9) {
|
||||||
|
return res.status(400).json({ error: 'grid must be an array of 9 items' });
|
||||||
|
}
|
||||||
|
|
||||||
|
pushCommandToBridge({ type: 'command', action: 'learn_crafting_recipe', commandId, output, count: count || 1, grid });
|
||||||
|
const result = { success: true, commandId, message: `Learned crafting recipe: ${output}` };
|
||||||
|
recordCommand(commandId, result);
|
||||||
|
console.log(`📖 Learn crafting recipe: ${output}`);
|
||||||
|
res.json(result);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Learn a smelting recipe
|
||||||
|
app.post('/api/recipes/learn-smelting', (req, res) => {
|
||||||
|
try {
|
||||||
|
const { input, result: recipeResult, furnaces, commandId } = req.body;
|
||||||
|
|
||||||
|
const cached = checkIdempotent(commandId);
|
||||||
|
if (cached) return res.json(cached);
|
||||||
|
|
||||||
|
if (!input || typeof input !== 'string' || input.length > 200) {
|
||||||
|
return res.status(400).json({ error: 'Missing or invalid input' });
|
||||||
|
}
|
||||||
|
if (!recipeResult || typeof recipeResult !== 'string' || recipeResult.length > 200) {
|
||||||
|
return res.status(400).json({ error: 'Missing or invalid result' });
|
||||||
|
}
|
||||||
|
|
||||||
|
pushCommandToBridge({ type: 'command', action: 'learn_smelting_recipe', commandId, input, result: recipeResult, furnaces });
|
||||||
|
const apiResult = { success: true, commandId, message: `Learned smelting recipe: ${input} → ${recipeResult}` };
|
||||||
|
recordCommand(commandId, apiResult);
|
||||||
|
console.log(`📖 Learn smelting recipe: ${input} → ${recipeResult}`);
|
||||||
|
res.json(apiResult);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Forget a recipe
|
||||||
|
app.post('/api/recipes/forget', (req, res) => {
|
||||||
|
try {
|
||||||
|
const { recipe, commandId } = req.body;
|
||||||
|
|
||||||
|
const cached = checkIdempotent(commandId);
|
||||||
|
if (cached) return res.json(cached);
|
||||||
|
|
||||||
|
if (!recipe || typeof recipe !== 'string' || recipe.length > 200) {
|
||||||
|
return res.status(400).json({ error: 'Missing or invalid recipe name' });
|
||||||
|
}
|
||||||
|
|
||||||
|
pushCommandToBridge({ type: 'command', action: 'forget_recipe', commandId, recipe });
|
||||||
|
const result = { success: true, commandId, message: `Forget recipe: ${recipe}` };
|
||||||
|
recordCommand(commandId, result);
|
||||||
|
console.log(`🗑️ Forget recipe: ${recipe}`);
|
||||||
|
res.json(result);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sync disabled recipes state
|
||||||
|
app.post('/api/recipes/sync', (req, res) => {
|
||||||
|
try {
|
||||||
|
const { disabledRecipes, smeltingPaused, commandId } = req.body;
|
||||||
|
|
||||||
|
const cached = checkIdempotent(commandId);
|
||||||
|
if (cached) return res.json(cached);
|
||||||
|
|
||||||
|
pushCommandToBridge({ type: 'command', action: 'sync_disabled_recipes', commandId, disabledRecipes, smeltingPaused });
|
||||||
|
const result = { success: true, commandId, message: 'Synced recipe state' };
|
||||||
|
recordCommand(commandId, result);
|
||||||
|
console.log('🔄 Sync disabled recipes');
|
||||||
|
res.json(result);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// ========== Bridge Endpoints (for HTTP polling fallback) ==========
|
// ========== Bridge Endpoints (for HTTP polling fallback) ==========
|
||||||
|
|
||||||
// Bridge sends inventory state
|
// Bridge sends inventory state
|
||||||
|
|||||||
Reference in New Issue
Block a user