Compare commits
2 Commits
fix/883
...
fix/1535-w
| Author | SHA1 | Date | |
|---|---|---|---|
| 6dcdc0544a | |||
| 4c7abbc0b3 |
59
app.js
59
app.js
@@ -69,6 +69,39 @@ function escHtml(s) {
|
||||
let hermesWs = null;
|
||||
let wsReconnectTimer = null;
|
||||
let wsConnected = false;
|
||||
let _heartbeatTimer = null;
|
||||
let _heartbeatMissed = 0;
|
||||
let _savedPlayerPos = null;
|
||||
let _savedPlayerRot = null;
|
||||
const HEARTBEAT_INTERVAL = 30000; // 30s
|
||||
const HEARTBEAT_MAX_MISSED = 2;
|
||||
|
||||
function _startHeartbeat() {
|
||||
_stopHeartbeat();
|
||||
_heartbeatMissed = 0;
|
||||
_heartbeatTimer = setInterval(() => {
|
||||
if (!hermesWs || hermesWs.readyState !== WebSocket.OPEN) return;
|
||||
if (_heartbeatMissed >= HEARTBEAT_MAX_MISSED) {
|
||||
console.warn('Heartbeat: ' + _heartbeatMissed + ' missed pongs. Reconnecting...');
|
||||
hermesWs.close();
|
||||
return;
|
||||
}
|
||||
_heartbeatMissed++;
|
||||
try {
|
||||
hermesWs.send(JSON.stringify({ type: 'ping' }));
|
||||
} catch (e) {
|
||||
console.warn('Heartbeat send failed:', e);
|
||||
}
|
||||
}, HEARTBEAT_INTERVAL);
|
||||
}
|
||||
|
||||
function _stopHeartbeat() {
|
||||
if (_heartbeatTimer) {
|
||||
clearInterval(_heartbeatTimer);
|
||||
_heartbeatTimer = null;
|
||||
}
|
||||
_heartbeatMissed = 0;
|
||||
}
|
||||
// ═══ EVENNIA ROOM STATE ═══
|
||||
let evenniaRoom = null; // {title, desc, exits[], objects[], occupants[], timestamp, roomKey}
|
||||
let evenniaConnected = false;
|
||||
@@ -2213,6 +2246,18 @@ function connectHermes() {
|
||||
} catch (e) {
|
||||
console.warn('[Mnemosyne] Failed to send sync_request:', e);
|
||||
}
|
||||
|
||||
// Heartbeat: start ping timer
|
||||
_startHeartbeat();
|
||||
|
||||
// Restore position after reconnect
|
||||
if (_savedPlayerPos && typeof playerPos !== 'undefined') {
|
||||
playerPos = _savedPlayerPos;
|
||||
if (_savedPlayerRot && typeof playerRot !== 'undefined') playerRot = _savedPlayerRot;
|
||||
console.log('Restored player position after reconnect.');
|
||||
_savedPlayerPos = null;
|
||||
_savedPlayerRot = null;
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize MemPalace
|
||||
@@ -2221,6 +2266,16 @@ function connectHermes() {
|
||||
hermesWs.onmessage = (evt) => {
|
||||
try {
|
||||
const data = JSON.parse(evt.data);
|
||||
|
||||
// Heartbeat pong: reset missed count
|
||||
if (data.type === 'pong') {
|
||||
_heartbeatMissed = 0;
|
||||
if (data.user_count !== undefined) {
|
||||
console.debug('Heartbeat pong: ' + data.user_count + ' users connected.');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
handleHermesMessage(data);
|
||||
|
||||
// Store in MemPalace
|
||||
@@ -2238,6 +2293,10 @@ function connectHermes() {
|
||||
hermesWs.onclose = () => {
|
||||
console.warn('Hermes disconnected. Retrying in 5s...');
|
||||
wsConnected = false;
|
||||
_stopHeartbeat();
|
||||
// Save position for reconnect
|
||||
if (typeof playerPos !== 'undefined') _savedPlayerPos = playerPos;
|
||||
if (typeof playerRot !== 'undefined') _savedPlayerRot = playerRot;
|
||||
hermesWs = null;
|
||||
updateWsHudStatus(false);
|
||||
refreshWorkshopPanel();
|
||||
|
||||
10
server.py
10
server.py
@@ -44,6 +44,16 @@ async def broadcast_handler(websocket: websockets.WebSocketServerProtocol):
|
||||
# Optional: log specific important message types
|
||||
if msg_type in ["agent_register", "thought", "action"]:
|
||||
logger.debug(f"Received {msg_type} from {addr}")
|
||||
|
||||
# Heartbeat: respond with pong + user count
|
||||
if msg_type == "ping":
|
||||
pong = json.dumps({
|
||||
"type": "pong",
|
||||
"user_count": len(clients),
|
||||
"timestamp": asyncio.get_event_loop().time()
|
||||
})
|
||||
await websocket.send(pong)
|
||||
continue
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
pass
|
||||
|
||||
|
||||
Reference in New Issue
Block a user