feat: add world voxel snapshot forwarding

Collect chunk voxel data from the bot world and stream snapshot,
chunk, and unwatch messages through the forward protocol.
This commit is contained in:
2026-10-23 10:44:37 +08:00
parent 0acef64f48
commit 6c69afb38a
11 changed files with 1997 additions and 18 deletions
+19 -1
View File
@@ -252,6 +252,9 @@ export class NodeForwardManager {
case 'get_data_file_list':
case 'get_file_data':
case 'execute_function':
case 'world.snapshot':
case 'world.chunk':
case 'world.unwatch':
case 'workflow.start':
case 'workflow.stop':
case 'workflow.snapshot':
@@ -277,6 +280,14 @@ export class NodeForwardManager {
const listing = data as {expires_at: number};
listing.expires_at = Math.min(listing.expires_at, entry.lease || entry.command.expires_at);
}
} else if (request.method === 'world.snapshot') {
data = await this.until_deadline(entry.stream.world_snapshot(request.payload, request.deadline_at, check_transport),
request.deadline_at, () => {});
} else if (request.method === 'world.chunk') {
data = await this.until_deadline(entry.stream.world_chunk(request.payload, request.deadline_at, check_transport),
request.deadline_at, () => {});
} else if (request.method === 'world.unwatch') {
data = entry.stream.world_unwatch(request.payload, request.deadline_at, check_transport);
} else if (request.method === 'workflow.start') {
data = entry.stream.workflow_start(request.payload, request.deadline_at, check_transport);
} else if (request.method === 'workflow.stop') {
@@ -341,8 +352,15 @@ export class NodeForwardManager {
let window = Date.now();
let count = 0;
entry.unsubscribe = entry.stream!.subscribe(event => {
if ((event.name !== 'log' && event.name !== 'info_update') || entry.socket !== socket || !socket.connected
if ((event.name !== 'log' && event.name !== 'info_update' && event.name !== 'status_update') || entry.socket !== socket || !socket.connected
|| !entry.ready || entry.terminal || this.stopped) return;
if (event.name === 'status_update') {
// Lifecycle state must survive a busy log stream; reconnect rather
// than silently retaining an online snapshot when the queue is full.
if ((socket.io.engine?.writeBuffer.length ?? 0) >= 64) this.close_transport(entry);
else socket.emit('bot_event', {...event, forward_session_id: entry.command.forward_session_id});
return;
}
if (Date.now() - window >= 1000) { window = Date.now(); count = 0; }
if (++count > 150 || (socket.io.engine?.writeBuffer.length ?? 0) >= 64) return;
if (event.name === 'log') {