make emotions named instead, add drop prop
This commit is contained in:
parent
989e20757b
commit
ea3b444d71
19 changed files with 1429 additions and 150 deletions
|
|
@ -17,8 +17,8 @@ use tokio::sync::broadcast;
|
|||
use uuid::Uuid;
|
||||
|
||||
use chattyness_db::{
|
||||
models::{AvatarRenderData, ChannelMemberWithAvatar, User},
|
||||
queries::{avatars, channel_members, realms, scenes},
|
||||
models::{AvatarRenderData, ChannelMemberWithAvatar, EmotionState, User},
|
||||
queries::{avatars, channel_members, loose_props, realms, scenes},
|
||||
ws_messages::{ClientMessage, ServerMessage},
|
||||
};
|
||||
use chattyness_error::AppError;
|
||||
|
|
@ -97,14 +97,15 @@ where
|
|||
.await?
|
||||
.ok_or_else(|| AppError::NotFound(format!("Realm '{}' not found", slug)))?;
|
||||
|
||||
// Verify channel (scene) exists and belongs to this realm
|
||||
// Verify scene exists and belongs to this realm
|
||||
// Note: Using scene_id as channel_id since channel_members uses scenes directly
|
||||
let scene = scenes::get_scene_by_id(&pool, channel_id)
|
||||
.await?
|
||||
.ok_or_else(|| AppError::NotFound("Channel not found".to_string()))?;
|
||||
.ok_or_else(|| AppError::NotFound("Scene not found".to_string()))?;
|
||||
|
||||
if scene.realm_id != realm.id {
|
||||
return Err(AppError::NotFound(
|
||||
"Channel not found in this realm".to_string(),
|
||||
"Scene not found in this realm".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -230,6 +231,24 @@ async fn handle_socket(
|
|||
}
|
||||
}
|
||||
|
||||
// Send loose props sync
|
||||
match loose_props::list_channel_loose_props(&mut *conn, channel_id).await {
|
||||
Ok(props) => {
|
||||
let props_sync = ServerMessage::LoosePropsSync { props };
|
||||
if let Ok(json) = serde_json::to_string(&props_sync) {
|
||||
#[cfg(debug_assertions)]
|
||||
tracing::debug!("[WS->Client] {}", json);
|
||||
if sender.send(Message::Text(json.into())).await.is_err() {
|
||||
let _ = channel_members::leave_channel(&mut *conn, channel_id, user.id).await;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::warn!("[WS] Failed to get loose props: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Broadcast join to others
|
||||
let avatar = avatars::get_avatar_with_paths_conn(&mut *conn, user.id, realm_id)
|
||||
.await
|
||||
|
|
@ -295,15 +314,20 @@ async fn handle_socket(
|
|||
});
|
||||
}
|
||||
ClientMessage::UpdateEmotion { emotion } => {
|
||||
// We have 12 emotions (0-11)
|
||||
if emotion > 11 {
|
||||
continue;
|
||||
}
|
||||
// Parse emotion name to EmotionState
|
||||
let emotion_state = match emotion.parse::<EmotionState>() {
|
||||
Ok(e) => e,
|
||||
Err(_) => {
|
||||
#[cfg(debug_assertions)]
|
||||
tracing::warn!("[WS] Invalid emotion name: {}", emotion);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let emotion_layer = match avatars::set_emotion(
|
||||
&mut *recv_conn,
|
||||
user_id,
|
||||
realm_id,
|
||||
emotion as i16,
|
||||
emotion_state,
|
||||
)
|
||||
.await
|
||||
{
|
||||
|
|
@ -341,13 +365,17 @@ async fn handle_socket(
|
|||
.await;
|
||||
|
||||
if let Ok(Some(member)) = member_info {
|
||||
// Convert emotion index to name
|
||||
let emotion_name = EmotionState::from_index(member.current_emotion as u8)
|
||||
.map(|e| e.to_string())
|
||||
.unwrap_or_else(|| "neutral".to_string());
|
||||
let msg = ServerMessage::ChatMessageReceived {
|
||||
message_id: Uuid::new_v4(),
|
||||
user_id: Some(user_id),
|
||||
guest_session_id: None,
|
||||
display_name: member.display_name.clone(),
|
||||
content,
|
||||
emotion: member.current_emotion as u8,
|
||||
emotion: emotion_name,
|
||||
x: member.position_x,
|
||||
y: member.position_y,
|
||||
timestamp: chrono::Utc::now().timestamp_millis(),
|
||||
|
|
@ -355,6 +383,76 @@ async fn handle_socket(
|
|||
let _ = tx.send(msg);
|
||||
}
|
||||
}
|
||||
ClientMessage::DropProp { inventory_item_id } => {
|
||||
// Get user's current position for random offset
|
||||
let member_info = channel_members::get_channel_member(
|
||||
&mut *recv_conn,
|
||||
channel_id,
|
||||
user_id,
|
||||
realm_id,
|
||||
)
|
||||
.await;
|
||||
|
||||
if let Ok(Some(member)) = member_info {
|
||||
// Generate random offset (within ~50 pixels)
|
||||
let offset_x = (rand::random::<f64>() - 0.5) * 100.0;
|
||||
let offset_y = (rand::random::<f64>() - 0.5) * 100.0;
|
||||
let pos_x = member.position_x + offset_x;
|
||||
let pos_y = member.position_y + offset_y;
|
||||
|
||||
match loose_props::drop_prop_to_canvas(
|
||||
&mut *recv_conn,
|
||||
inventory_item_id,
|
||||
user_id,
|
||||
channel_id,
|
||||
pos_x,
|
||||
pos_y,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(prop) => {
|
||||
#[cfg(debug_assertions)]
|
||||
tracing::debug!(
|
||||
"[WS] User {} dropped prop {} at ({}, {})",
|
||||
user_id,
|
||||
prop.id,
|
||||
pos_x,
|
||||
pos_y
|
||||
);
|
||||
let _ = tx.send(ServerMessage::PropDropped { prop });
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("[WS] Drop prop failed: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ClientMessage::PickUpProp { loose_prop_id } => {
|
||||
match loose_props::pick_up_loose_prop(
|
||||
&mut *recv_conn,
|
||||
loose_prop_id,
|
||||
user_id,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(_inventory_item) => {
|
||||
#[cfg(debug_assertions)]
|
||||
tracing::debug!(
|
||||
"[WS] User {} picked up prop {}",
|
||||
user_id,
|
||||
loose_prop_id
|
||||
);
|
||||
let _ = tx.send(ServerMessage::PropPickedUp {
|
||||
prop_id: loose_prop_id,
|
||||
picked_up_by_user_id: Some(user_id),
|
||||
picked_up_by_guest_id: None,
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("[WS] Pick up prop failed: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue