overte-www/scripts/manifoldDomain.js

117 lines
4.1 KiB
JavaScript
Raw Normal View History

2026-03-15 21:57:31 +00:00
//
// manifoldDomain.js — Manifold Domain Script
//
// Assignment client script — do NOT wrap in an IIFE.
// Requires EntityViewer to be initialized before entity queries work.
//
// Deploy via Domain Settings > Scripts.
//
var WS_URL = "wss://wizards.cyou/ws";
var SCAN_CENTER = { x: 0, y: 0, z: 0 };
var SCAN_RADIUS = 500;
var ws = null;
var reconnectTimer = null;
var heartbeatTimer = null;
var isReady = false;
// ── EntityViewer init ────────────────────────────────────────────
// AC scripts have no spatial presence — must set up EntityViewer
// before findEntitiesByType will return anything.
var initInterval = Script.setInterval(function () {
if (Entities.serversExist() && Entities.canRez()) {
EntityViewer.setPosition(SCAN_CENTER);
EntityViewer.setCenterRadius(SCAN_RADIUS);
EntityViewer.queryOctree();
Script.clearInterval(initInterval);
Script.setTimeout(function () {
isReady = true;
print("[Manifold] EntityViewer ready");
connect();
// Re-query octree periodically so newly spawned entities stay visible
heartbeatTimer = Script.setInterval(function () {
EntityViewer.queryOctree();
}, 10000);
}, 2000);
}
}, 500);
// ── entity cleanup ───────────────────────────────────────────────
function deleteClonesFor(username) {
if (!isReady) return;
EntityViewer.queryOctree();
Script.setTimeout(function () {
var ids = Entities.findEntitiesByType("Shape", SCAN_CENTER, SCAN_RADIUS);
var deleted = 0;
ids.forEach(function (id) {
try {
var ud = JSON.parse(Entities.getEntityProperties(id, ["userData"]).userData || "{}");
if (ud.manifoldClone && ud.owner === username) {
Entities.deleteEntity(id);
deleted++;
}
} catch (e) {}
});
print("[Manifold] deleted " + deleted + " clone(s) for " + username);
}, 1000);
}
// ── websocket ────────────────────────────────────────────────────
function connect() {
print("[Manifold] Connecting to " + WS_URL);
ws = new WebSocket(WS_URL);
ws.onopen = function () {
print("[Manifold] Connected");
if (reconnectTimer) {
Script.clearTimeout(reconnectTimer);
reconnectTimer = null;
}
};
ws.onmessage = function (event) {
try {
var msg = JSON.parse(event.data);
switch (msg.type) {
case "user:connected":
print("[Manifold] >>> " + msg.username + " joined");
break;
case "user:disconnected":
print("[Manifold] <<< " + msg.username + " left");
deleteClonesFor(msg.username);
break;
case "recall":
print("[Manifold] recall for " + msg.username);
deleteClonesFor(msg.username);
break;
}
} catch (e) {
print("[Manifold] message parse error: " + e);
}
};
ws.onerror = function (err) {
print("[Manifold] WS error: " + JSON.stringify(err));
};
ws.onclose = function (event) {
print("[Manifold] Disconnected (code=" + event.code + "). Reconnecting in 5s...");
ws = null;
reconnectTimer = Script.setTimeout(connect, 5000);
};
}
// ── lifecycle ────────────────────────────────────────────────────
Script.scriptEnding.connect(function () {
print("[Manifold] script ending");
if (reconnectTimer) { Script.clearTimeout(reconnectTimer); }
if (heartbeatTimer) { Script.clearInterval(heartbeatTimer); }
if (ws) { ws.close(); ws = null; }
});