Qwen3.5-9B on prod, Gemini 2.5 Flash for dev, error correction, branding
Prod deployment: - paper-ai and shrink-world switched from gemma3n:e4b to qwen3.5:9b - Error correction: detects RCON errors (<--[HERE]), asks model to fix, retries - Broadened error patterns: Unknown game mode, Unknown enchantment, etc. - Fixed fire fallback matching "firework" as fire intent - Fixed command format examples (WRONG vs RIGHT in prompt) - max_tokens bumped to 600 for command calls - Removed template workflow commands from sudo prompt Dev server: - Gemini 2.5 Flash ($0.15/$0.60 per M tokens) replaces Flash Lite - 10 bots for ~$1-1.5/hr training data generation - Dynamic pricing by model name in cost tracker Branding: - Rajdhani Bold as official Mortdecai font - Logo variants: mortdecai + mortdec.ai in 6 fonts - Whitelist page updated with Mortdecai branding + mortdec.ai domain Whitelist UUID fix: - Looks up real Mojang UUID via api.mojang.com - Patches all whitelist.json files directly - No more offline-mode UUID mismatches WorldEdit schematics: - 77 schematics installed (villages, bridges, lighthouses, parks, etc.) Mortdecai v4 training in progress: 63% complete on steel141 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+60
-6
@@ -25,7 +25,7 @@ SERVERS = [
|
||||
|
||||
WHITELIST_LOG = "/var/log/mc_whitelist.log"
|
||||
|
||||
LOGO_URL = "https://storage.googleapis.com/sethfreiberg.com/sethflix/favicon.png"
|
||||
LOGO_URL = "https://git.sethpc.xyz/Seth/Mortdecai/raw/branch/master/branding/mortdec_ai_rajdhani.png"
|
||||
|
||||
|
||||
def rcon_command(cmd, host, port, password):
|
||||
@@ -54,11 +54,65 @@ def rcon_command(cmd, host, port, password):
|
||||
return f"ERROR: {e}"
|
||||
|
||||
|
||||
def lookup_mojang_uuid(username):
|
||||
"""Look up a player's real Mojang UUID from the API."""
|
||||
try:
|
||||
import urllib.request
|
||||
url = f"https://api.mojang.com/users/profiles/minecraft/{username}"
|
||||
req = urllib.request.Request(url, headers={"User-Agent": "MortdecaiWhitelist/1.0"})
|
||||
resp = urllib.request.urlopen(req, timeout=5)
|
||||
data = json.loads(resp.read())
|
||||
raw = data.get("id", "")
|
||||
if len(raw) == 32:
|
||||
# Format as UUID with dashes
|
||||
return f"{raw[:8]}-{raw[8:12]}-{raw[12:16]}-{raw[16:20]}-{raw[20:]}"
|
||||
return raw
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def whitelist_player(username):
|
||||
"""Whitelist player on all servers, fixing UUIDs to real Mojang UUIDs."""
|
||||
results = {}
|
||||
|
||||
# Get real UUID from Mojang
|
||||
uuid = lookup_mojang_uuid(username)
|
||||
|
||||
for srv in SERVERS:
|
||||
# RCON whitelist add (creates entry, possibly with wrong offline UUID)
|
||||
result = rcon_command(f"whitelist add {username}", srv["host"], srv["rcon_port"], srv["rcon_pass"])
|
||||
results[srv["name"]] = result.strip()
|
||||
|
||||
# Fix UUIDs in whitelist.json files directly
|
||||
if uuid:
|
||||
WHITELIST_FILES = [
|
||||
"/opt/paper-ai-25567/whitelist.json",
|
||||
"/opt/mcsmanager/daemon/data/InstanceData/shrinkborder1234567890abcdef12345/whitelist.json",
|
||||
"/opt/mcsmanager/daemon/data/InstanceData/d39f55861cb34204a92a18a9e1c78ca6/whitelist.json",
|
||||
]
|
||||
for wl_path in WHITELIST_FILES:
|
||||
try:
|
||||
with open(wl_path) as f:
|
||||
wl = json.load(f)
|
||||
changed = False
|
||||
for entry in wl:
|
||||
if entry["name"].lower() == username.lower() and entry["uuid"] != uuid:
|
||||
entry["uuid"] = uuid
|
||||
entry["name"] = username
|
||||
changed = True
|
||||
if changed:
|
||||
with open(wl_path, "w") as f:
|
||||
json.dump(wl, f, indent=2)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Reload whitelists
|
||||
for srv in SERVERS:
|
||||
try:
|
||||
rcon_command("whitelist reload", srv["host"], srv["rcon_port"], srv["rcon_pass"])
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return results
|
||||
|
||||
|
||||
@@ -71,7 +125,7 @@ PAGE = """<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Minecraft AI Server — sethpc.xyz</title>
|
||||
<title>Mortdecai — Minecraft AI</title>
|
||||
<style>
|
||||
* {{ margin: 0; padding: 0; box-sizing: border-box; }}
|
||||
body {{ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
@@ -80,8 +134,8 @@ PAGE = """<!DOCTYPE html>
|
||||
a:hover {{ color: #e65c00; }}
|
||||
|
||||
.header {{ background: #000; padding: 1rem; text-align: center; border-bottom: 2px solid #D35400; }}
|
||||
.header img {{ width: 40px; vertical-align: middle; border: none; }}
|
||||
.header span {{ font-size: 1.2rem; font-weight: 700; color: #D35400; margin-left: 0.5rem; vertical-align: middle; }}
|
||||
.header img {{ height: 40px; vertical-align: middle; border: none; }}
|
||||
.header span {{ font-size: 1.2rem; font-weight: 700; color: #D35400; margin-left: 0.5rem; vertical-align: middle; display: none; }}
|
||||
|
||||
.container {{ max-width: 600px; margin: 0 auto; padding: 1.5rem; }}
|
||||
|
||||
@@ -137,12 +191,12 @@ PAGE = """<!DOCTYPE html>
|
||||
|
||||
<div class="header">
|
||||
<img src="{logo}" alt="logo" class="noborder">
|
||||
<span>sethpc.xyz</span>
|
||||
<span>mortdec.ai</span>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="hero">
|
||||
<h1>Minecraft AI Server</h1>
|
||||
<h1>Mortdecai</h1>
|
||||
<p>An AI runs on this server that listens to in-game chat and does things in the world based on what you say.</p>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user