9.0 KiB
9.0 KiB
Architettura
Panoramica
MUDlet AI Client usa un'architettura a 3 layer basata su Electron:
┌─────────────────────────────────────────────────────────┐
│ ELECTRON MAIN │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ TelnetService│ │ OllamaService│ │ AutoplayerService│ │
│ └──────┬──────┘ └──────┬──────┘ └────────┬────────┘ │
│ │ │ │ │
│ └────────────────┼───────────────────┘ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ IPC Handlers │ │
│ └─────────┬───────────┘ │
└────────────────────────┼────────────────────────────────┘
│
┌────────────────────────┼────────────────────────────────┐
│ PRELOAD JS │
│ contextBridge.exposeInMainWorld() │
└────────────────────────┼────────────────────────────────┘
│
┌────────────────────────┼────────────────────────────────┐
│ REACT RENDERER │
│ ┌─────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ App │ │ GameWindow │ │ AutoplayerPanel │ │
│ └─────────┘ └─────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────┘
Layer 1: Electron Main Process
Main Entry (src/main/index.ts)
Responsabilità:
- Inizializzazione finestra BrowserWindow
- Setup IPC handlers
- Event forwarding tra servizi e renderer
- Lifecycle management (app ready, window closed, etc.)
// Flusso dati Telnet
telnetService.on('output', (data) => {
mainWindow.webContents.send('telnet-output', data);
autoplayerService.processOutput(data); // Forward all'autoplayer
});
TelnetService (src/main/services/TelnetService.ts)
Wrapper attorno a telnet-client con funzionalità aggiuntive:
| Metodo | Descrizione |
|---|---|
connect(host, port) |
Stabilisce connessione Telnet |
send(data) |
Invia comando al server |
getOutput() |
Restituisce buffer output |
parseAnsiCodes(text) |
Converte ANSI escape codes in HTML |
Eventi:
output- Emesso quando arrives nuovo outputconnected- Connessione stabilitadisconnected- Connessione chiusaerror- Errore di connessione
Parsing ANSI:
// ansicolor converte sequenze ANSI in spans colorati
// Ogni span viene convertito in <span style="...">
OllamaService (src/main/services/OllamaService.ts)
Client HTTP per Ollama API. Supporta:
| Metodo | Descrizione |
|---|---|
chat(messages, options) |
Chat singola, attesa risposta |
chatStream(messages, options) |
Streaming response token-by-token |
getLocalModels() |
Lista modelli disponibili |
isAvailable() |
Check server reachability |
API Endpoint:
POST http://ollama.solarpi.net/api/chat
{
"model": "llama3.2",
"messages": [...],
"stream": true,
"options": {
"temperature": 0.7,
"num_predict": 512
}
}
AutoplayerService (src/main/services/AutoplayerService.ts)
Decision engine che orchestrate il loop autoplayer:
┌─────────────────────────────────────────────────────────┐
│ AUTOPLAYER LOOP │
│ │
│ 1. OBSERVE ← processOutput(output) │
│ 2. PARSE ← parseGameState() │
│ 3. THINK ← ollamaService.chat() │
│ 4. DECIDE ← extractAction() │
│ 5. ACT ← executeAction() / queueAction() │
│ │
└─────────────────────────────────────────────────────────┘
Configurazione:
interface AutoplayerConfig {
model: string; // Model LLM da usare
systemPrompt: string; // Comportamento del bot
temperature: number; // Creatività (0.0-1.0)
autoSend: boolean; // Auto-esegui azioni
}
Game State Parser:
parseGameState(output: string): GameState {
// Estrae: location, exits, players, objects, description
}
Decision Prompt:
Context: [ultimi 30 righe output]
Sei in: [location]
Uscite disponibili: north, south, east
Cosa fai? (rispondi SOLO con il comando)
Layer 2: Preload Script
espone API sicure al renderer tramite contextBridge:
// Telnet
telnetConnect(host, port)
telnetSend(data)
onTelnetOutput(callback)
// Ollama
ollamaChat(messages, options)
ollamaGetModels()
ollamaIsAvailable()
// Autoplayer
autoplayerConfigure(config)
autoplayerStart()
autoplayerStop()
autoplayerExecuteAction(action)
onAutoplayerDecision(callback)
onAutoplayerAction(callback)
Layer 3: React Renderer
App (src/renderer/App.tsx)
Root component con navigation:
// Navigation state
const [activePanel, setActivePanel] = useState<'connection' | 'game' | 'autoplayer'>();
// Connection status
const [isConnected, setIsConnected] = useState(false);
GameWindow (src/renderer/components/GameWindow.tsx)
Display principale del gioco:
| Componente | Funzione |
|---|---|
| Output div | Visualizza output HTML con colors |
| Form | Input comandi + submit |
| Auto-scroll | Mantiene focus su output recente |
// Subscribe a output Telnet
useEffect(() => {
window.electronAPI.onTelnetOutput((data) => {
setOutput(prev => prev + data);
});
}, []);
AutoplayerPanel (src/renderer/components/AutoplayerPanel.tsx)
Pannello controllo autoplayer:
| Feature | UI |
|---|---|
| Toggle On/Off | Switch button |
| Model selection | Dropdown (da Ollama) |
| System prompt | Textarea modificabile |
| Live status | Ultime decisioni/azioni |
| Ollama availability | Check automatico |
Flusso Dati
Telnet → UI
1. Telnet server → telnet-client
2. TelnetService → emits 'output'
3. Main process → ipcRenderer.send('telnet-output')
4. GameWindow → onTelnetOutput callback
5. React state → setOutput()
6. Render → HTML display
Autoplayer Decision
1. Output Telnet arrives
2. AutoplayerService.processOutput()
3. parseGameState() → GameState { location, exits, ... }
4. shouldMakeDecision() → true/false
5. ollamaService.chat(messages)
6. extractAction() → "go north"
7. autoSend ? executeAction() : queueAction()
8. Events: 'decision', 'action'
9. UI updates: lastDecision, lastAction
Configurazione
Environment
- Server Ollama:
http://ollama.solarpi.net(hardcoded) - LPMUD default:
172.24.19.225:6666
Tipi Condivisi
// src/main/services/AutoplayerService.ts
interface GameState {
location: string;
description: string;
exits: string[];
players: string[];
objects: string[];
health?: string;
mana?: string;
prompt?: string;
}
interface OllamaMessage {
role: 'user' | 'assistant' | 'system';
content: string;
}
Limitazioni Attuali
| Componente | Limitation | Piani |
|---|---|---|
| ANSI Parsing | Solo colori basic | Parser completo |
| Game Parser | Regex-based, fragile | ML parser |
| Autoplayer | No memory persistent | SQLite storage |
| Mapper | Non implementato | Fase 3 |
| Triggers | Non implementati | Fase 3 |
| Plugins | Non implementati | Fase 4 |