friend's neko in scene page
This commit is contained in:
96
src/events/friend-active-doll.ts
Normal file
96
src/events/friend-active-doll.ts
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import { writable, get } from "svelte/store";
|
||||||
|
import { events, type DollDto } from "$lib/bindings";
|
||||||
|
import { createEventSource, removeFromStore } from "./listener-utils";
|
||||||
|
import { getSpriteSheetUrl } from "$lib/utils/sprite-utils";
|
||||||
|
import { appData } from "./app-data";
|
||||||
|
import onekoGif from "../assets/oneko/oneko.gif";
|
||||||
|
|
||||||
|
export const friendsActiveDollSprites = writable<Record<string, string>>(
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
|
||||||
|
async function getFriendSpriteUrl(doll: DollDto): Promise<string> {
|
||||||
|
if (!doll.configuration?.colorScheme) {
|
||||||
|
return onekoGif;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await getSpriteSheetUrl(doll.configuration.colorScheme);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to generate friend sprite:", e);
|
||||||
|
return onekoGif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function syncFromAppData() {
|
||||||
|
const data = get(appData);
|
||||||
|
if (!data?.friends) return;
|
||||||
|
|
||||||
|
const currentSprites = get(friendsActiveDollSprites);
|
||||||
|
const newSprites: Record<string, string> = {};
|
||||||
|
|
||||||
|
const friendUpdates = data.friends
|
||||||
|
.filter((f) => f.friend?.activeDoll)
|
||||||
|
.map(async (f) => {
|
||||||
|
const friendId = f.friend!.id;
|
||||||
|
if (currentSprites[friendId]) {
|
||||||
|
newSprites[friendId] = currentSprites[friendId];
|
||||||
|
} else {
|
||||||
|
newSprites[friendId] = await getFriendSpriteUrl(f.friend!.activeDoll!);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(friendUpdates);
|
||||||
|
|
||||||
|
Object.keys(currentSprites).forEach((friendId) => {
|
||||||
|
if (!newSprites[friendId] && data.friends) {
|
||||||
|
const friend = data.friends.find(
|
||||||
|
(f) => f.friend?.id === friendId && f.friend?.activeDoll,
|
||||||
|
);
|
||||||
|
if (friend) {
|
||||||
|
getFriendSpriteUrl(friend.friend!.activeDoll!).then((spriteUrl) => {
|
||||||
|
friendsActiveDollSprites.update((current) => ({
|
||||||
|
...current,
|
||||||
|
[friendId]: spriteUrl,
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
friendsActiveDollSprites.set(newSprites);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const {
|
||||||
|
start: startFriendActiveDollTracking,
|
||||||
|
stop: stopFriendActiveDollTracking,
|
||||||
|
} = createEventSource(async (addEventListener) => {
|
||||||
|
await syncFromAppData();
|
||||||
|
|
||||||
|
addEventListener(
|
||||||
|
await events.friendActiveDollChanged.listen(async (event) => {
|
||||||
|
const { friendId, doll } = event.payload;
|
||||||
|
|
||||||
|
if (doll) {
|
||||||
|
const spriteUrl = await getFriendSpriteUrl(doll);
|
||||||
|
friendsActiveDollSprites.update((current) => ({
|
||||||
|
...current,
|
||||||
|
[friendId]: spriteUrl,
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
friendsActiveDollSprites.update((current) =>
|
||||||
|
removeFromStore(current, friendId),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
addEventListener(
|
||||||
|
await events.friendDisconnected.listen((event) => {
|
||||||
|
const { userId } = event.payload;
|
||||||
|
friendsActiveDollSprites.update((current) =>
|
||||||
|
removeFromStore(current, userId),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -17,6 +17,10 @@
|
|||||||
stopSceneInteractive,
|
stopSceneInteractive,
|
||||||
} from "../events/scene-interactive";
|
} from "../events/scene-interactive";
|
||||||
import { startUserStatus, stopUserStatus } from "../events/user-status";
|
import { startUserStatus, stopUserStatus } from "../events/user-status";
|
||||||
|
import {
|
||||||
|
startFriendActiveDollTracking,
|
||||||
|
stopFriendActiveDollTracking,
|
||||||
|
} from "../events/friend-active-doll";
|
||||||
|
|
||||||
let { children } = $props();
|
let { children } = $props();
|
||||||
if (browser) {
|
if (browser) {
|
||||||
@@ -29,6 +33,7 @@
|
|||||||
await startSceneInteractive();
|
await startSceneInteractive();
|
||||||
await startInteraction();
|
await startInteraction();
|
||||||
await startUserStatus();
|
await startUserStatus();
|
||||||
|
await startFriendActiveDollTracking();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to initialize event listeners:", err);
|
console.error("Failed to initialize event listeners:", err);
|
||||||
}
|
}
|
||||||
@@ -41,6 +46,7 @@
|
|||||||
stopSceneInteractive();
|
stopSceneInteractive();
|
||||||
stopInteraction();
|
stopInteraction();
|
||||||
stopUserStatus();
|
stopUserStatus();
|
||||||
|
stopFriendActiveDollTracking();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -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 { friendsActiveDollSprites } from "../../events/friend-active-doll";
|
||||||
import { sceneInteractive } from "../../events/scene-interactive";
|
import { sceneInteractive } from "../../events/scene-interactive";
|
||||||
import {
|
import {
|
||||||
friendsPresenceStates,
|
friendsPresenceStates,
|
||||||
@@ -26,6 +27,15 @@
|
|||||||
targetY={$cursorPositionOnScreen.raw.y}
|
targetY={$cursorPositionOnScreen.raw.y}
|
||||||
spriteUrl={$activeDollSpriteUrl}
|
spriteUrl={$activeDollSpriteUrl}
|
||||||
/>
|
/>
|
||||||
|
{#each Object.entries($friendsCursorPositions) as [friendId, position]}
|
||||||
|
{#if $friendsActiveDollSprites[friendId]}
|
||||||
|
<Neko
|
||||||
|
targetX={position.raw.x}
|
||||||
|
targetY={position.raw.y}
|
||||||
|
spriteUrl={$friendsActiveDollSprites[friendId]}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
<div id="debug-bar">
|
<div id="debug-bar">
|
||||||
<DebugBar
|
<DebugBar
|
||||||
isInteractive={$sceneInteractive}
|
isInteractive={$sceneInteractive}
|
||||||
|
|||||||
Reference in New Issue
Block a user