diff --git a/packages/backend/src/core/WorldRoomMultiplayService.ts b/packages/backend/src/core/WorldRoomMultiplayService.ts index d741e69307..f7e855030e 100644 --- a/packages/backend/src/core/WorldRoomMultiplayService.ts +++ b/packages/backend/src/core/WorldRoomMultiplayService.ts @@ -60,7 +60,10 @@ export class WorldRoomMultiplayService { public async heartbeat(userId: MiUser['id'], roomId: MiWorldRoom['id']) { const exists = await this.redisClient.hexists(`worldRoom:${roomId}:players`, userId); if (exists) { - await this.redisClient.hexpire(`worldRoom:${roomId}:players`, 30, 'FIELDS', 1, userId); + const redisPipeline = this.redisClient.pipeline(); + redisPipeline.hexpire(`worldRoom:${roomId}:players`, 30, 'FIELDS', 1, userId); + redisPipeline.hexpire(`worldRoom:${roomId}:playerStates`, 30, 'FIELDS', 1, userId); + await redisPipeline.exec(); } else { throw new Error('Not in room.'); } diff --git a/packages/frontend-misskey-world-engine/package.json b/packages/frontend-misskey-world-engine/package.json index a2a41f8585..a987acb593 100644 --- a/packages/frontend-misskey-world-engine/package.json +++ b/packages/frontend-misskey-world-engine/package.json @@ -14,6 +14,7 @@ "esbuild": "0.28.0", "execa": "9.6.1", "nodemon": "3.1.14", + "throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6" }, "files": [ @@ -24,6 +25,7 @@ "@babylonjs/inspector": "9.9.0", "@babylonjs/loaders": "9.9.0", "@babylonjs/materials": "9.9.0", + "@types/throttle-debounce": "5.0.2", "eventemitter3": "5.0.4", "seedrandom": "3.0.5", "tinycolor2": "1.6.0", diff --git a/packages/frontend-misskey-world-engine/src/room/engine.ts b/packages/frontend-misskey-world-engine/src/room/engine.ts index 5bd1a858d8..4140e54781 100644 --- a/packages/frontend-misskey-world-engine/src/room/engine.ts +++ b/packages/frontend-misskey-world-engine/src/room/engine.ts @@ -18,6 +18,7 @@ import * as BABYLON from '@babylonjs/core'; import { registerBuiltInLoaders } from '@babylonjs/loaders/dynamic'; import { cm, WORLD_SCALE } from 'misskey-world/src/utility.js'; +import { throttle } from 'throttle-debounce'; import { TIME_MAP, getMeshesBoundingBox, Timer, getYRotationDirection, FreeCameraManualInput, remap } from '../utility.js'; import { EngineBase } from '../EngineBase.js'; import { genId } from '../id.js'; @@ -65,7 +66,7 @@ export class RoomEngine extends EngineBase<{ 'changeSittingState': (ctx: { isSitting: boolean }) => void; 'changeGridSnapping': (ctx: { gridSnapping: { enabled: boolean; scale: number } }) => void; 'changeRoomState': (ctx: { roomState: RoomState }) => void; - 'changeMyPlayerState': (ctx: { playerState: PlayerState }) => void; + 'changeMyPlayerState': (ctx: PlayerState) => void; 'playSfxUrl': (ctx: { url: string; options: { @@ -177,7 +178,7 @@ export class RoomEngine extends EngineBase<{ this.ev('changeSittingState', { isSitting: v }); } - private playerProfiles: Record = {}; + private playerProfiles: Record = {}; private playerStates: Record = {}; private playerContainers: PlayerContainer[] = []; @@ -499,6 +500,16 @@ export class RoomEngine extends EngineBase<{ } }); + this.timer.setInterval(() => { + const camera = this.scene.activeCamera!; + const myPos = camera.position; + const myRotation = camera.rotation; + this.ev('changeMyPlayerState', { + position: [myPos.x, myPos.y, myPos.z], + rotation: [myRotation.x, myRotation.y, myRotation.z], + }); + }, 100); + this.inited = true; } diff --git a/packages/frontend/src/world/room/controller.ts b/packages/frontend/src/world/room/controller.ts index 090b0121a6..ef4164c166 100644 --- a/packages/frontend/src/world/room/controller.ts +++ b/packages/frontend/src/world/room/controller.ts @@ -108,7 +108,7 @@ export class RoomController extends EngineControllerBase { } }); - engineEvents.on('changeMyPlayerState', ({ playerState }) => { + engineEvents.on('changeMyPlayerState', (playerState) => { this.myPlayerState.value = playerState; }); diff --git a/packages/frontend/vite.config.ts b/packages/frontend/vite.config.ts index 1c212eab6b..0d428b01d6 100644 --- a/packages/frontend/vite.config.ts +++ b/packages/frontend/vite.config.ts @@ -220,7 +220,7 @@ export function getConfig(): UserConfig { // https://vitejs.dev/guide/dep-pre-bundling.html#monorepos-and-linked-dependencies commonjsOptions: { - include: [/misskey-js/, /misskey-reversi/, /misskey-bubble-game/, /misskey-world/, /frontend-misskey-world-engine/, /node_modules/], + include: [/misskey-js/, /misskey-reversi/, /misskey-bubble-game/, /node_modules/], }, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5c99fe7cc1..6d96e74dce 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1184,6 +1184,9 @@ importers: '@babylonjs/materials': specifier: 9.9.0 version: 9.9.0(@babylonjs/core@9.9.0) + '@types/throttle-debounce': + specifier: 5.0.2 + version: 5.0.2 eventemitter3: specifier: 5.0.4 version: 5.0.4 @@ -1218,6 +1221,9 @@ importers: nodemon: specifier: 3.1.14 version: 3.1.14 + throttle-debounce: + specifier: 5.0.2 + version: 5.0.2 packages/frontend-shared: dependencies: @@ -10935,8 +10941,8 @@ packages: vue-component-type-helpers@3.2.8: resolution: {integrity: sha512-9689efAXhN/EV86plgkL/XFiJSXhGtWPG6JDboZ+QnjlUWUUQrQ0ILKQtw4iQsuwIwu5k6Aw+JnehDe7161e7A==} - vue-component-type-helpers@3.3.0: - resolution: {integrity: sha512-vwR8DDsBysI9NWXa0okPFpCcW+BUC3sPTuLBNo1faMzw4QWMFd+3/lFYFu29ZN0q+8UReXWJHEYesC9dcXYCLg==} + vue-component-type-helpers@3.3.1: + resolution: {integrity: sha512-pu58kqxmVyEH6VfNYW1UyEfR3XAnJ27ZXT3yzXxxpjLxVzAbyC35Zk/nm/RMs7ijWnJNSd9fWkeex2OhUsx3MA==} vue-demi@0.14.10: resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} @@ -15515,7 +15521,7 @@ snapshots: storybook: 10.3.6(@testing-library/dom@10.4.0)(bufferutil@4.1.0)(prettier@3.8.3)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) type-fest: 2.19.0 vue: 3.5.34(typescript@5.9.3) - vue-component-type-helpers: 3.3.0 + vue-component-type-helpers: 3.3.1 '@stylistic/eslint-plugin@5.10.0(eslint@9.39.4)': dependencies: @@ -22362,7 +22368,7 @@ snapshots: vue-component-type-helpers@3.2.8: {} - vue-component-type-helpers@3.3.0: {} + vue-component-type-helpers@3.3.1: {} vue-demi@0.14.10(vue@3.5.34(typescript@5.9.3)): dependencies: diff --git a/scripts/dev.mjs b/scripts/dev.mjs index dd08e95660..54fba71f0f 100644 --- a/scripts/dev.mjs +++ b/scripts/dev.mjs @@ -111,15 +111,3 @@ execa('pnpm', ['--filter', 'misskey-bubble-game', 'watch', '--no-clean'], { stdout: process.stdout, stderr: process.stderr, }); - -execa('pnpm', ['--filter', 'misskey-world', 'watch', '--no-clean'], { - cwd: _dirname + '/../', - stdout: process.stdout, - stderr: process.stderr, -}); - -execa('pnpm', ['--filter', 'frontend-misskey-world-engine', 'watch', '--no-clean'], { - cwd: _dirname + '/../', - stdout: process.stdout, - stderr: process.stderr, -});