chore: add snarky remarks while building from a schematic

This commit is contained in:
2026-02-15 13:05:19 +01:00
parent 30289d591f
commit 786f259b8e
4 changed files with 350 additions and 104 deletions
+117
View File
@@ -2,6 +2,7 @@ import asyncio
import json
import math
import os
import random
import time
from typing import Any
@@ -323,6 +324,122 @@ async def load_schematic(name: str, x: int, y: int, z: int) -> str:
}, timeout=120.0))
_SNARKY_25 = [
"Quarter done with {name}... whoever designed this owes me an explanation.",
"25% into {name}. Starting to question my life choices.",
"A quarter of {name} is done. It's giving... abstract art.",
"25% through {name}. I deserve a raise for this.",
"One quarter of {name} complete. Three more quarters of suffering to go.",
]
_SNARKY_50 = [
"Halfway through {name}. It's... starting to look like something, I guess.",
"50% of {name} done. No turning back now.",
"Half of {name} built. The other half is judging me.",
"Halfway done with {name}. Send snacks.",
"50% into {name}. I've seen worse. Not much worse, but worse.",
]
_SNARKY_75 = [
"75% done with {name}. I can almost see the finish line... and it's ugly.",
"Almost done with {name}. My masterpiece. And by masterpiece, I mean your fault.",
"Three quarters through {name}. I'm basically an artist now.",
"75% of {name} complete. I'm starting to feel things. Mostly exhaustion.",
"Nearly there with {name}. Don't look at it yet. Actually, don't look at it ever.",
]
@mcp.tool()
async def build_schematic(name: str, x: int, y: int, z: int) -> str:
"""Load a schematic and build it layer by layer (bottom to top) with chat progress.
Creates a satisfying visual building effect. Use load_schematic for instant placement instead.
Name may only contain letters, numbers, underscore, and hyphen."""
# 1. Get schematic info
info = await _request("POST", "/get_schematic_info", json={
"name": name, "x": x, "y": y, "z": z,
}, timeout=15.0)
if isinstance(info, dict) and "error" in info:
return _fmt(info)
total_blocks = info.get("total_blocks", 0)
layers = info.get("layers", [])
fmt = info.get("format", "unknown")
num_layers = len(layers)
if num_layers == 0:
return _fmt({"ok": True, "message": "Schematic is empty, nothing to build.", "placed": 0})
# 2. Start build session and announce
await _ensure_build_session(x, y, z)
await _request("POST", "/chat", json={
"message": f"Starting build of {name}! {total_blocks} blocks, {num_layers} layers."
})
# 3. Build layer by layer
total_placed = 0
milestones_hit: set[int] = set()
milestone_remarks = {25: _SNARKY_25, 50: _SNARKY_50, 75: _SNARKY_75}
for i, layer in enumerate(layers):
layer_y = layer["y"]
block_count = layer["block_count"]
# Keep build session alive and look at current layer
await _ensure_build_session(x, layer_y, z)
# Check if this layer crosses a milestone threshold
progress = (i + 1) / num_layers
remark = None
for threshold, pool in milestone_remarks.items():
if threshold not in milestones_hit and progress >= threshold / 100:
milestones_hit.add(threshold)
remark = random.choice(pool).format(name=name)
break
if remark:
await _request("POST", "/chat", json={"message": remark})
else:
await _request("POST", "/chat", json={
"message": f"Layer {i + 1}/{num_layers} (Y={layer_y}) - {block_count} blocks..."
})
result = await _request("POST", "/place_schematic_layer", json={
"name": name, "x": x, "y": y, "z": z, "layer_y": layer_y,
}, timeout=15.0)
if isinstance(result, dict) and "error" in result:
await _request("POST", "/chat", json={
"message": f"Build failed at layer {i + 1}/{num_layers}! Error: {result['error']}"
})
return _fmt({
"ok": False,
"error": result["error"],
"layers_completed": i,
"layers_total": num_layers,
"blocks_placed": total_placed,
})
placed = result.get("placed", 0)
total_placed += placed
# Visual delay between layers
if i < num_layers - 1:
await asyncio.sleep(0.4)
# 4. Announce completion
await _request("POST", "/chat", json={
"message": f"Build complete! Placed {total_placed} blocks in {num_layers} layers."
})
return _fmt({
"ok": True,
"name": name,
"format": fmt,
"layers": num_layers,
"total_placed": total_placed,
})
@mcp.tool()
async def list_schematics() -> str:
"""List all available schematics (.json and .litematic) in the world's schematics folder.