feat: add teleport

This commit is contained in:
Evan Carroll 2026-01-19 11:48:12 -06:00
parent 226c2e02b5
commit 32e5e42462
11 changed files with 603 additions and 16 deletions

View file

@ -391,11 +391,15 @@ async fn handle_socket(
// Clone ws_state for use in recv_task
let ws_state_for_recv = ws_state.clone();
// Clone pool for use in recv_task (for teleport queries)
let pool_for_recv = pool.clone();
// Create recv timeout from config
let recv_timeout = Duration::from_secs(ws_config.recv_timeout_secs);
// Spawn task to handle incoming messages from client
let recv_task = tokio::spawn(async move {
let pool = pool_for_recv;
let ws_state = ws_state_for_recv;
let mut disconnect_reason = DisconnectReason::Graceful;
@ -724,6 +728,90 @@ async fn handle_socket(
}
}
}
ClientMessage::Teleport { scene_id } => {
// Validate teleport permission and scene
// 1. Check realm allows user teleport
let realm = match realms::get_realm_by_id(
&pool,
realm_id,
)
.await
{
Ok(Some(r)) => r,
Ok(None) => {
let _ = direct_tx.send(ServerMessage::Error {
code: "REALM_NOT_FOUND".to_string(),
message: "Realm not found".to_string(),
}).await;
continue;
}
Err(e) => {
tracing::error!("[WS] Teleport realm lookup failed: {:?}", e);
let _ = direct_tx.send(ServerMessage::Error {
code: "TELEPORT_FAILED".to_string(),
message: "Failed to verify teleport permission".to_string(),
}).await;
continue;
}
};
if !realm.allow_user_teleport {
let _ = direct_tx.send(ServerMessage::Error {
code: "TELEPORT_DISABLED".to_string(),
message: "Teleporting is not enabled for this realm".to_string(),
}).await;
continue;
}
// 2. Validate scene exists, belongs to realm, and is not hidden
let scene = match scenes::get_scene_by_id(&pool, scene_id).await {
Ok(Some(s)) => s,
Ok(None) => {
let _ = direct_tx.send(ServerMessage::Error {
code: "SCENE_NOT_FOUND".to_string(),
message: "Scene not found".to_string(),
}).await;
continue;
}
Err(e) => {
tracing::error!("[WS] Teleport scene lookup failed: {:?}", e);
let _ = direct_tx.send(ServerMessage::Error {
code: "TELEPORT_FAILED".to_string(),
message: "Failed to verify scene".to_string(),
}).await;
continue;
}
};
if scene.realm_id != realm_id {
let _ = direct_tx.send(ServerMessage::Error {
code: "SCENE_NOT_IN_REALM".to_string(),
message: "Scene does not belong to this realm".to_string(),
}).await;
continue;
}
if scene.is_hidden {
let _ = direct_tx.send(ServerMessage::Error {
code: "SCENE_HIDDEN".to_string(),
message: "Cannot teleport to a hidden scene".to_string(),
}).await;
continue;
}
// 3. Send approval - client will disconnect and reconnect
#[cfg(debug_assertions)]
tracing::debug!(
"[WS] User {} teleporting to scene {} ({})",
user_id,
scene.name,
scene.slug
);
let _ = direct_tx.send(ServerMessage::TeleportApproved {
scene_id: scene.id,
scene_slug: scene.slug,
}).await;
}
}
}
Message::Close(close_frame) => {