added friends' neko to scene page
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
lock_r,
|
lock_r,
|
||||||
models::app_data::UserData,
|
models::app_data::UserData,
|
||||||
services::{presence_modules::models::ModuleMetadata, sprite},
|
services::{
|
||||||
|
friend_active_doll_sprite, presence_modules::models::ModuleMetadata, sprite,
|
||||||
|
},
|
||||||
state::{init_app_data_scoped, AppDataRefreshScope, FDOLL},
|
state::{init_app_data_scoped, AppDataRefreshScope, FDOLL},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -32,3 +34,11 @@ pub fn get_modules() -> Result<Vec<ModuleMetadata>, String> {
|
|||||||
pub fn get_active_doll_sprite_base64() -> Result<Option<String>, String> {
|
pub fn get_active_doll_sprite_base64() -> Result<Option<String>, String> {
|
||||||
sprite::get_active_doll_sprite_base64()
|
sprite::get_active_doll_sprite_base64()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
#[specta::specta]
|
||||||
|
pub fn get_friend_active_doll_sprites_base64(
|
||||||
|
) -> Result<friend_active_doll_sprite::FriendActiveDollSpritesDto, String> {
|
||||||
|
friend_active_doll_sprite::sync_from_app_data();
|
||||||
|
Ok(friend_active_doll_sprite::get_snapshot())
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use commands::app::{quit_app, restart_app, retry_connection};
|
use commands::app::{quit_app, restart_app, retry_connection};
|
||||||
use commands::app_state::{get_active_doll_sprite_base64, get_app_data, refresh_app_data};
|
use commands::app_state::{
|
||||||
|
get_active_doll_sprite_base64, get_app_data, get_friend_active_doll_sprites_base64,
|
||||||
|
refresh_app_data,
|
||||||
|
};
|
||||||
use commands::auth::{change_password, login, logout_and_restart, register, reset_password};
|
use commands::auth::{change_password, login, logout_and_restart, register, reset_password};
|
||||||
use commands::config::{get_client_config, open_client_config_manager, save_client_config};
|
use commands::config::{get_client_config, open_client_config_manager, save_client_config};
|
||||||
use commands::dolls::{
|
use commands::dolls::{
|
||||||
@@ -25,7 +28,8 @@ use tauri_specta::{collect_commands, collect_events, Builder as SpectaBuilder, E
|
|||||||
|
|
||||||
use crate::services::app_events::{
|
use crate::services::app_events::{
|
||||||
ActiveDollSpriteChanged, AppDataRefreshed, CreateDoll, CursorMoved, EditDoll,
|
ActiveDollSpriteChanged, AppDataRefreshed, CreateDoll, CursorMoved, EditDoll,
|
||||||
FriendActiveDollChanged, FriendCursorPositionsUpdated, FriendDisconnected,
|
FriendActiveDollChanged, FriendActiveDollSpritesUpdated, FriendCursorPositionsUpdated,
|
||||||
|
FriendDisconnected,
|
||||||
FriendRequestAccepted, FriendRequestDenied, FriendRequestReceived, FriendUserStatusChanged,
|
FriendRequestAccepted, FriendRequestDenied, FriendRequestReceived, FriendUserStatusChanged,
|
||||||
InteractionDeliveryFailed, InteractionReceived, SceneInteractiveChanged, SetInteractionOverlay,
|
InteractionDeliveryFailed, InteractionReceived, SceneInteractiveChanged, SetInteractionOverlay,
|
||||||
Unfriended, UserStatusChanged,
|
Unfriended, UserStatusChanged,
|
||||||
@@ -66,6 +70,7 @@ pub fn run() {
|
|||||||
.commands(collect_commands![
|
.commands(collect_commands![
|
||||||
get_app_data,
|
get_app_data,
|
||||||
get_active_doll_sprite_base64,
|
get_active_doll_sprite_base64,
|
||||||
|
get_friend_active_doll_sprites_base64,
|
||||||
refresh_app_data,
|
refresh_app_data,
|
||||||
list_friends,
|
list_friends,
|
||||||
search_users,
|
search_users,
|
||||||
@@ -114,6 +119,7 @@ pub fn run() {
|
|||||||
FriendCursorPositionsUpdated,
|
FriendCursorPositionsUpdated,
|
||||||
FriendDisconnected,
|
FriendDisconnected,
|
||||||
FriendActiveDollChanged,
|
FriendActiveDollChanged,
|
||||||
|
FriendActiveDollSpritesUpdated,
|
||||||
FriendUserStatusChanged,
|
FriendUserStatusChanged,
|
||||||
InteractionReceived,
|
InteractionReceived,
|
||||||
InteractionDeliveryFailed,
|
InteractionDeliveryFailed,
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ use crate::{
|
|||||||
},
|
},
|
||||||
interaction::{InteractionDeliveryFailedDto, InteractionPayloadDto},
|
interaction::{InteractionDeliveryFailedDto, InteractionPayloadDto},
|
||||||
},
|
},
|
||||||
services::{cursor::CursorPositions, friend_cursor::FriendCursorPositionsDto},
|
services::{
|
||||||
|
cursor::CursorPositions, friend_active_doll_sprite::FriendActiveDollSpritesDto,
|
||||||
|
friend_cursor::FriendCursorPositionsDto,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
|
||||||
@@ -59,6 +62,10 @@ pub struct FriendDisconnected(pub FriendDisconnectedPayload);
|
|||||||
#[tauri_specta(event_name = "friend-active-doll-changed")]
|
#[tauri_specta(event_name = "friend-active-doll-changed")]
|
||||||
pub struct FriendActiveDollChanged(pub FriendActiveDollChangedPayload);
|
pub struct FriendActiveDollChanged(pub FriendActiveDollChangedPayload);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
|
||||||
|
#[tauri_specta(event_name = "friend-active-doll-sprites-updated")]
|
||||||
|
pub struct FriendActiveDollSpritesUpdated(pub FriendActiveDollSpritesDto);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
|
||||||
#[tauri_specta(event_name = "friend-user-status")]
|
#[tauri_specta(event_name = "friend-user-status")]
|
||||||
pub struct FriendUserStatusChanged(pub FriendUserStatusPayload);
|
pub struct FriendUserStatusChanged(pub FriendUserStatusPayload);
|
||||||
|
|||||||
126
src-tauri/src/services/friend_active_doll_sprite.rs
Normal file
126
src-tauri/src/services/friend_active_doll_sprite.rs
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
sync::{Arc, LazyLock, RwLock},
|
||||||
|
};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use specta::Type;
|
||||||
|
use tauri_specta::Event as _;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
get_app_handle, lock_r,
|
||||||
|
models::{dolls::DollDto, friends::FriendshipResponseDto},
|
||||||
|
services::{app_events::FriendActiveDollSpritesUpdated, sprite},
|
||||||
|
state::FDOLL,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Serialize, Deserialize, Type)]
|
||||||
|
#[serde(transparent)]
|
||||||
|
pub struct FriendActiveDollSpritesDto(pub HashMap<String, String>);
|
||||||
|
|
||||||
|
static FRIEND_ACTIVE_DOLL_SPRITES: LazyLock<Arc<RwLock<HashMap<String, String>>>> =
|
||||||
|
LazyLock::new(|| Arc::new(RwLock::new(HashMap::new())));
|
||||||
|
|
||||||
|
pub fn sync_from_app_data() {
|
||||||
|
let friends = {
|
||||||
|
let guard = lock_r!(FDOLL);
|
||||||
|
guard.user_data.friends.clone().unwrap_or_default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let next = build_sprites(&friends);
|
||||||
|
|
||||||
|
let mut projection = FRIEND_ACTIVE_DOLL_SPRITES
|
||||||
|
.write()
|
||||||
|
.expect("friend active doll sprite projection lock poisoned");
|
||||||
|
*projection = next;
|
||||||
|
|
||||||
|
emit_snapshot(&projection);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear() {
|
||||||
|
let mut projection = FRIEND_ACTIVE_DOLL_SPRITES
|
||||||
|
.write()
|
||||||
|
.expect("friend active doll sprite projection lock poisoned");
|
||||||
|
projection.clear();
|
||||||
|
|
||||||
|
emit_snapshot(&projection);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_friend(user_id: &str) {
|
||||||
|
let mut projection = FRIEND_ACTIVE_DOLL_SPRITES
|
||||||
|
.write()
|
||||||
|
.expect("friend active doll sprite projection lock poisoned");
|
||||||
|
|
||||||
|
if projection.remove(user_id).is_some() {
|
||||||
|
emit_snapshot(&projection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_active_doll(user_id: &str, doll: Option<&DollDto>) {
|
||||||
|
let mut projection = FRIEND_ACTIVE_DOLL_SPRITES
|
||||||
|
.write()
|
||||||
|
.expect("friend active doll sprite projection lock poisoned");
|
||||||
|
|
||||||
|
match doll {
|
||||||
|
Some(doll) => match sprite::encode_doll_sprite_base64(doll) {
|
||||||
|
Ok(sprite_b64) => {
|
||||||
|
projection.insert(user_id.to_string(), sprite_b64);
|
||||||
|
emit_snapshot(&projection);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
tracing::warn!(
|
||||||
|
"Failed to generate active doll sprite for friend {}: {}",
|
||||||
|
user_id,
|
||||||
|
err
|
||||||
|
);
|
||||||
|
|
||||||
|
if projection.remove(user_id).is_some() {
|
||||||
|
emit_snapshot(&projection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
if projection.remove(user_id).is_some() {
|
||||||
|
emit_snapshot(&projection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_snapshot() -> FriendActiveDollSpritesDto {
|
||||||
|
let projection = FRIEND_ACTIVE_DOLL_SPRITES
|
||||||
|
.read()
|
||||||
|
.expect("friend active doll sprite projection lock poisoned");
|
||||||
|
|
||||||
|
FriendActiveDollSpritesDto(projection.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_sprites(friends: &[FriendshipResponseDto]) -> HashMap<String, String> {
|
||||||
|
friends
|
||||||
|
.iter()
|
||||||
|
.filter_map(|friendship| {
|
||||||
|
let friend = friendship.friend.as_ref()?;
|
||||||
|
let doll = friend.active_doll.as_ref()?;
|
||||||
|
|
||||||
|
match sprite::encode_doll_sprite_base64(doll) {
|
||||||
|
Ok(sprite_b64) => Some((friend.id.clone(), sprite_b64)),
|
||||||
|
Err(err) => {
|
||||||
|
tracing::warn!(
|
||||||
|
"Failed to generate active doll sprite for friend {}: {}",
|
||||||
|
friend.id,
|
||||||
|
err
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_snapshot(sprites: &HashMap<String, String>) {
|
||||||
|
let payload = FriendActiveDollSpritesDto(sprites.clone());
|
||||||
|
|
||||||
|
if let Err(err) = FriendActiveDollSpritesUpdated(payload).emit(get_app_handle()) {
|
||||||
|
tracing::warn!("Failed to emit friend active doll sprites update: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ pub mod auth;
|
|||||||
pub mod client_config_manager;
|
pub mod client_config_manager;
|
||||||
pub mod cursor;
|
pub mod cursor;
|
||||||
pub mod doll_editor;
|
pub mod doll_editor;
|
||||||
|
pub mod friend_active_doll_sprite;
|
||||||
pub mod friend_cursor;
|
pub mod friend_cursor;
|
||||||
pub mod health_manager;
|
pub mod health_manager;
|
||||||
pub mod health_monitor;
|
pub mod health_monitor;
|
||||||
|
|||||||
@@ -2,6 +2,17 @@ use crate::{lock_r, models::dolls::DollDto, state::FDOLL};
|
|||||||
|
|
||||||
const APPLY_TEXTURE: bool = true;
|
const APPLY_TEXTURE: bool = true;
|
||||||
|
|
||||||
|
pub fn encode_doll_sprite_base64(doll: &DollDto) -> Result<String, String> {
|
||||||
|
let color_scheme = &doll.configuration.color_scheme;
|
||||||
|
|
||||||
|
super::sprite_recolor::recolor_gif_base64(
|
||||||
|
&color_scheme.body,
|
||||||
|
&color_scheme.outline,
|
||||||
|
APPLY_TEXTURE,
|
||||||
|
)
|
||||||
|
.map_err(|err| err.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_active_doll() -> Option<DollDto> {
|
pub fn get_active_doll() -> Option<DollDto> {
|
||||||
let guard = lock_r!(FDOLL);
|
let guard = lock_r!(FDOLL);
|
||||||
let active_doll_id = guard
|
let active_doll_id = guard
|
||||||
@@ -20,14 +31,7 @@ pub fn get_active_doll() -> Option<DollDto> {
|
|||||||
|
|
||||||
pub fn get_active_doll_sprite_base64() -> Result<Option<String>, String> {
|
pub fn get_active_doll_sprite_base64() -> Result<Option<String>, String> {
|
||||||
get_active_doll()
|
get_active_doll()
|
||||||
.map(|doll| {
|
.as_ref()
|
||||||
let color_scheme = doll.configuration.color_scheme;
|
.map(encode_doll_sprite_base64)
|
||||||
super::sprite_recolor::recolor_gif_base64(
|
|
||||||
&color_scheme.body,
|
|
||||||
&color_scheme.outline,
|
|
||||||
APPLY_TEXTURE,
|
|
||||||
)
|
|
||||||
.map_err(|err| err.to_string())
|
|
||||||
})
|
|
||||||
.transpose()
|
.transpose()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use crate::services::app_events::{
|
|||||||
};
|
};
|
||||||
use crate::services::{
|
use crate::services::{
|
||||||
cursor::{normalized_to_absolute, CursorPositions},
|
cursor::{normalized_to_absolute, CursorPositions},
|
||||||
friend_cursor,
|
friend_active_doll_sprite, friend_cursor,
|
||||||
};
|
};
|
||||||
use crate::state::AppDataRefreshScope;
|
use crate::state::AppDataRefreshScope;
|
||||||
|
|
||||||
@@ -77,6 +77,7 @@ pub fn on_friend_disconnected(payload: Payload, _socket: RawClient) {
|
|||||||
if let Ok(data) =
|
if let Ok(data) =
|
||||||
utils::extract_and_parse::<FriendDisconnectedPayload>(payload, "friend-disconnected")
|
utils::extract_and_parse::<FriendDisconnectedPayload>(payload, "friend-disconnected")
|
||||||
{
|
{
|
||||||
|
friend_active_doll_sprite::remove_friend(&data.user_id);
|
||||||
friend_cursor::remove_friend(&data.user_id);
|
friend_cursor::remove_friend(&data.user_id);
|
||||||
emitter::emit_to_frontend_typed(&FriendDisconnected(data));
|
emitter::emit_to_frontend_typed(&FriendDisconnected(data));
|
||||||
}
|
}
|
||||||
@@ -111,9 +112,9 @@ pub fn on_friend_active_doll_changed(payload: Payload, _socket: RawClient) {
|
|||||||
payload,
|
payload,
|
||||||
"friend-active-doll-changed",
|
"friend-active-doll-changed",
|
||||||
) {
|
) {
|
||||||
|
friend_active_doll_sprite::set_active_doll(&data.friend_id, data.doll.as_ref());
|
||||||
friend_cursor::set_active_doll(&data.friend_id, data.doll.is_some());
|
friend_cursor::set_active_doll(&data.friend_id, data.doll.is_some());
|
||||||
emitter::emit_to_frontend_typed(&FriendActiveDollChanged(data));
|
emitter::emit_to_frontend_typed(&FriendActiveDollChanged(data));
|
||||||
refresh::refresh_app_data(AppDataRefreshScope::Friends);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use crate::{
|
|||||||
remotes::{dolls::DollsRemote, friends::FriendRemote, user::UserRemote},
|
remotes::{dolls::DollsRemote, friends::FriendRemote, user::UserRemote},
|
||||||
services::{
|
services::{
|
||||||
app_events::{ActiveDollSpriteChanged, AppDataRefreshed},
|
app_events::{ActiveDollSpriteChanged, AppDataRefreshed},
|
||||||
friend_cursor, sprite,
|
friend_active_doll_sprite, friend_cursor, sprite,
|
||||||
},
|
},
|
||||||
state::FDOLL,
|
state::FDOLL,
|
||||||
};
|
};
|
||||||
@@ -165,6 +165,7 @@ pub async fn init_app_data_scoped(scope: AppDataRefreshScope) {
|
|||||||
let mut guard = lock_w!(crate::state::FDOLL);
|
let mut guard = lock_w!(crate::state::FDOLL);
|
||||||
guard.user_data.friends = Some(friends);
|
guard.user_data.friends = Some(friends);
|
||||||
drop(guard);
|
drop(guard);
|
||||||
|
friend_active_doll_sprite::sync_from_app_data();
|
||||||
friend_cursor::sync_from_app_data();
|
friend_cursor::sync_from_app_data();
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@@ -286,5 +287,6 @@ pub fn clear_app_data() {
|
|||||||
guard.user_data.user = None;
|
guard.user_data.user = None;
|
||||||
guard.user_data.friends = None;
|
guard.user_data.friends = None;
|
||||||
drop(guard);
|
drop(guard);
|
||||||
|
friend_active_doll_sprite::clear();
|
||||||
friend_cursor::clear();
|
friend_cursor::clear();
|
||||||
}
|
}
|
||||||
|
|||||||
36
src/events/friend-active-doll-sprite.ts
Normal file
36
src/events/friend-active-doll-sprite.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { writable } from "svelte/store";
|
||||||
|
import {
|
||||||
|
commands,
|
||||||
|
events,
|
||||||
|
type FriendActiveDollSpritesDto,
|
||||||
|
} from "$lib/bindings";
|
||||||
|
import { createEventSource } from "./listener-utils";
|
||||||
|
|
||||||
|
export const friendActiveDollSpriteUrls = writable<Record<string, string>>({});
|
||||||
|
|
||||||
|
function toSpriteUrls(
|
||||||
|
spriteBase64ByFriendId: FriendActiveDollSpritesDto,
|
||||||
|
): Record<string, string> {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(spriteBase64ByFriendId)
|
||||||
|
.filter((entry): entry is [string, string] => entry[1] !== undefined)
|
||||||
|
.map(([friendId, spriteBase64]) => [
|
||||||
|
friendId,
|
||||||
|
`data:image/gif;base64,${spriteBase64}`,
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const {
|
||||||
|
start: startFriendActiveDollSprite,
|
||||||
|
stop: stopFriendActiveDollSprite,
|
||||||
|
} = createEventSource(async (addEventListener) => {
|
||||||
|
const initialSprites = await commands.getFriendActiveDollSpritesBase64();
|
||||||
|
friendActiveDollSpriteUrls.set(toSpriteUrls(initialSprites));
|
||||||
|
|
||||||
|
addEventListener(
|
||||||
|
await events.friendActiveDollSpritesUpdated.listen((event) => {
|
||||||
|
friendActiveDollSpriteUrls.set(toSpriteUrls(event.payload));
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -11,6 +11,9 @@ async getAppData() : Promise<UserData> {
|
|||||||
async getActiveDollSpriteBase64() : Promise<string | null> {
|
async getActiveDollSpriteBase64() : Promise<string | null> {
|
||||||
return await TAURI_INVOKE("get_active_doll_sprite_base64");
|
return await TAURI_INVOKE("get_active_doll_sprite_base64");
|
||||||
},
|
},
|
||||||
|
async getFriendActiveDollSpritesBase64() : Promise<FriendActiveDollSpritesDto> {
|
||||||
|
return await TAURI_INVOKE("get_friend_active_doll_sprites_base64");
|
||||||
|
},
|
||||||
async refreshAppData() : Promise<UserData> {
|
async refreshAppData() : Promise<UserData> {
|
||||||
return await TAURI_INVOKE("refresh_app_data");
|
return await TAURI_INVOKE("refresh_app_data");
|
||||||
},
|
},
|
||||||
@@ -134,6 +137,7 @@ createDoll: CreateDoll,
|
|||||||
cursorMoved: CursorMoved,
|
cursorMoved: CursorMoved,
|
||||||
editDoll: EditDoll,
|
editDoll: EditDoll,
|
||||||
friendActiveDollChanged: FriendActiveDollChanged,
|
friendActiveDollChanged: FriendActiveDollChanged,
|
||||||
|
friendActiveDollSpritesUpdated: FriendActiveDollSpritesUpdated,
|
||||||
friendCursorPositionsUpdated: FriendCursorPositionsUpdated,
|
friendCursorPositionsUpdated: FriendCursorPositionsUpdated,
|
||||||
friendDisconnected: FriendDisconnected,
|
friendDisconnected: FriendDisconnected,
|
||||||
friendRequestAccepted: FriendRequestAccepted,
|
friendRequestAccepted: FriendRequestAccepted,
|
||||||
@@ -153,6 +157,7 @@ createDoll: "create-doll",
|
|||||||
cursorMoved: "cursor-moved",
|
cursorMoved: "cursor-moved",
|
||||||
editDoll: "edit-doll",
|
editDoll: "edit-doll",
|
||||||
friendActiveDollChanged: "friend-active-doll-changed",
|
friendActiveDollChanged: "friend-active-doll-changed",
|
||||||
|
friendActiveDollSpritesUpdated: "friend-active-doll-sprites-updated",
|
||||||
friendCursorPositionsUpdated: "friend-cursor-positions-updated",
|
friendCursorPositionsUpdated: "friend-cursor-positions-updated",
|
||||||
friendDisconnected: "friend-disconnected",
|
friendDisconnected: "friend-disconnected",
|
||||||
friendRequestAccepted: "friend-request-accepted",
|
friendRequestAccepted: "friend-request-accepted",
|
||||||
@@ -188,6 +193,8 @@ export type DollDto = { id: string; name: string; configuration: DollConfigurati
|
|||||||
export type EditDoll = string
|
export type EditDoll = string
|
||||||
export type FriendActiveDollChanged = FriendActiveDollChangedPayload
|
export type FriendActiveDollChanged = FriendActiveDollChangedPayload
|
||||||
export type FriendActiveDollChangedPayload = { friendId: string; doll: DollDto | null }
|
export type FriendActiveDollChangedPayload = { friendId: string; doll: DollDto | null }
|
||||||
|
export type FriendActiveDollSpritesDto = Partial<{ [key in string]: string }>
|
||||||
|
export type FriendActiveDollSpritesUpdated = FriendActiveDollSpritesDto
|
||||||
export type FriendCursorPositionsDto = Partial<{ [key in string]: CursorPositions }>
|
export type FriendCursorPositionsDto = Partial<{ [key in string]: CursorPositions }>
|
||||||
export type FriendCursorPositionsUpdated = FriendCursorPositionsDto
|
export type FriendCursorPositionsUpdated = FriendCursorPositionsDto
|
||||||
export type FriendDisconnected = FriendDisconnectedPayload
|
export type FriendDisconnected = FriendDisconnectedPayload
|
||||||
|
|||||||
@@ -10,6 +10,10 @@
|
|||||||
startActiveDollSprite,
|
startActiveDollSprite,
|
||||||
stopActiveDollSprite,
|
stopActiveDollSprite,
|
||||||
} from "../events/active-doll-sprite";
|
} from "../events/active-doll-sprite";
|
||||||
|
import {
|
||||||
|
startFriendActiveDollSprite,
|
||||||
|
stopFriendActiveDollSprite,
|
||||||
|
} from "../events/friend-active-doll-sprite";
|
||||||
import { startAppData } from "../events/app-data";
|
import { startAppData } from "../events/app-data";
|
||||||
import { startInteraction, stopInteraction } from "../events/interaction";
|
import { startInteraction, stopInteraction } from "../events/interaction";
|
||||||
import {
|
import {
|
||||||
@@ -24,6 +28,7 @@
|
|||||||
try {
|
try {
|
||||||
await startAppData();
|
await startAppData();
|
||||||
await startActiveDollSprite();
|
await startActiveDollSprite();
|
||||||
|
await startFriendActiveDollSprite();
|
||||||
await startCursorTracking();
|
await startCursorTracking();
|
||||||
await startFriendCursorTracking();
|
await startFriendCursorTracking();
|
||||||
await startSceneInteractive();
|
await startSceneInteractive();
|
||||||
@@ -38,6 +43,7 @@
|
|||||||
stopCursorTracking();
|
stopCursorTracking();
|
||||||
stopFriendCursorTracking();
|
stopFriendCursorTracking();
|
||||||
stopActiveDollSprite();
|
stopActiveDollSprite();
|
||||||
|
stopFriendActiveDollSprite();
|
||||||
stopSceneInteractive();
|
stopSceneInteractive();
|
||||||
stopInteraction();
|
stopInteraction();
|
||||||
stopUserStatus();
|
stopUserStatus();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import { friendsCursorPositions } from "../../events/friend-cursor";
|
import { friendsCursorPositions } from "../../events/friend-cursor";
|
||||||
import { appData } from "../../events/app-data";
|
import { appData } from "../../events/app-data";
|
||||||
import { activeDollSpriteUrl } from "../../events/active-doll-sprite";
|
import { activeDollSpriteUrl } from "../../events/active-doll-sprite";
|
||||||
|
import { friendActiveDollSpriteUrls } from "../../events/friend-active-doll-sprite";
|
||||||
import { sceneInteractive } from "../../events/scene-interactive";
|
import { sceneInteractive } from "../../events/scene-interactive";
|
||||||
import {
|
import {
|
||||||
friendsPresenceStates,
|
friendsPresenceStates,
|
||||||
@@ -26,6 +27,17 @@
|
|||||||
targetY={$cursorPositionOnScreen.raw.y}
|
targetY={$cursorPositionOnScreen.raw.y}
|
||||||
spriteUrl={$activeDollSpriteUrl}
|
spriteUrl={$activeDollSpriteUrl}
|
||||||
/>
|
/>
|
||||||
|
{#each Object.entries($friendsCursorPositions) as [friendId, position] (friendId)}
|
||||||
|
{#if $friendActiveDollSpriteUrls[friendId]}
|
||||||
|
<Neko
|
||||||
|
targetX={position.raw.x}
|
||||||
|
targetY={position.raw.y}
|
||||||
|
spriteUrl={$friendActiveDollSpriteUrls[friendId]}
|
||||||
|
initialX={position.raw.x}
|
||||||
|
initialY={position.raw.y}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
<div id="debug-bar">
|
<div id="debug-bar">
|
||||||
<DebugBar
|
<DebugBar
|
||||||
isInteractive={$sceneInteractive}
|
isInteractive={$sceneInteractive}
|
||||||
|
|||||||
@@ -8,14 +8,17 @@
|
|||||||
targetX: number;
|
targetX: number;
|
||||||
targetY: number;
|
targetY: number;
|
||||||
spriteUrl: string;
|
spriteUrl: string;
|
||||||
|
initialX?: number;
|
||||||
|
initialY?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { targetX, targetY, spriteUrl }: Props = $props();
|
let { targetX, targetY, spriteUrl, initialX = 32, initialY = 32 }: Props =
|
||||||
|
$props();
|
||||||
|
|
||||||
let nekoEl: HTMLDivElement;
|
let nekoEl: HTMLDivElement;
|
||||||
let animationFrameId: number;
|
let animationFrameId: number;
|
||||||
|
|
||||||
let nekoPos = $state({ x: 32, y: 32 });
|
let nekoPos = $state({ x: initialX, y: initialY });
|
||||||
let frameCount = 0;
|
let frameCount = 0;
|
||||||
let idleTime = 0;
|
let idleTime = 0;
|
||||||
let idleAnimation: string | null = $state(null);
|
let idleAnimation: string | null = $state(null);
|
||||||
|
|||||||
Reference in New Issue
Block a user