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 () {
|
2026-03-16 22:08:46 +00:00
|
|
|
// Use untyped findEntities to avoid type-specific visibility issues
|
|
|
|
|
// (Box entities are not always returned by findEntitiesByType)
|
|
|
|
|
var ids = Entities.findEntities(SCAN_CENTER, SCAN_RADIUS);
|
2026-03-15 21:57:31 +00:00
|
|
|
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; }
|
|
|
|
|
});
|