From fd6170437569cc41e880acf58ebe115f73bc4067 Mon Sep 17 00:00:00 2001 From: Lorenzune Date: Sat, 21 Mar 2026 14:27:57 +0100 Subject: [PATCH] fix(room): support wired click-user controls --- packages/api/src/nitro/room/IRoomEngine.ts | 1 + packages/room/src/RoomEngine.ts | 11 +++-- packages/room/src/RoomObjectEventHandler.ts | 47 ++++++++++++++++++--- 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/packages/api/src/nitro/room/IRoomEngine.ts b/packages/api/src/nitro/room/IRoomEngine.ts index f153dc0..986e7fb 100644 --- a/packages/api/src/nitro/room/IRoomEngine.ts +++ b/packages/api/src/nitro/room/IRoomEngine.ts @@ -65,6 +65,7 @@ export interface IRoomEngine getFurnitureWallName(typeId: number, extra?: string): string; selectRoomObject(roomId: number, objectId: number, objectCategory: number): void; setSelectedAvatar(roomId: number, objectId: number): void; + clearSelectedAvatar(roomId: number): void; cancelRoomObjectInsert(): void; getPetColorResult(petIndex: number, paletteIndex: number): IPetColorResult; getPetColorResultsForTag(petIndex: number, tagName: string): IPetColorResult[]; diff --git a/packages/room/src/RoomEngine.ts b/packages/room/src/RoomEngine.ts index ce53d69..19ca14a 100644 --- a/packages/room/src/RoomEngine.ts +++ b/packages/room/src/RoomEngine.ts @@ -2285,8 +2285,6 @@ export class RoomEngine implements IRoomEngine, IRoomCreator, IRoomEngineService private handleRoomDragging(canvas: IRoomRenderingCanvas, x: number, y: number, type: string, altKey: boolean, ctrlKey: boolean, shiftKey: boolean): boolean { - if(this.isPlayingGame()) return false; - if(this._areaSelectionManager.areaSelectionState === RoomAreaSelectionManager.SELECTING) { this._activeRoomIsDragged = false; @@ -2521,11 +2519,18 @@ export class RoomEngine implements IRoomEngine, IRoomCreator, IRoomEngineService public setSelectedAvatar(roomId: number, objectId: number): void { - if(this._roomObjectEventHandler) return; + if(!this._roomObjectEventHandler) return; this._roomObjectEventHandler.setSelectedAvatar(roomId, objectId, true); } + public clearSelectedAvatar(roomId: number): void + { + if(!this._roomObjectEventHandler) return; + + this._roomObjectEventHandler.clearSelectedAvatar(roomId); + } + public cancelRoomObjectInsert(): void { if(!this._roomObjectEventHandler) return; diff --git a/packages/room/src/RoomObjectEventHandler.ts b/packages/room/src/RoomObjectEventHandler.ts index 65ca483..4e7e2bb 100644 --- a/packages/room/src/RoomObjectEventHandler.ts +++ b/packages/room/src/RoomObjectEventHandler.ts @@ -10,6 +10,7 @@ import { SelectedRoomObjectData } from './utils'; export class RoomObjectEventHandler implements IRoomCanvasMouseListener, IRoomObjectEventManager { + private static readonly CLICK_USER_LOOK_DELAY_MS = 120; private _eventIds: Map> = new Map(); private _selectedAvatarId: number = -1; @@ -17,6 +18,7 @@ export class RoomObjectEventHandler implements IRoomCanvasMouseListener, IRoomOb private _selectedObjectCategory: number = -2; private _whereYouClickIsWhereYouGo: boolean = true; private _objectPlacementSource: string = null; + private _pendingAvatarLookTimeout: ReturnType = null; constructor( private readonly _roomEngine: IRoomEngineServices) @@ -2080,6 +2082,8 @@ export class RoomObjectEventHandler implements IRoomCanvasMouseListener, IRoomOb { if(!this._roomEngine) return; + this.clearPendingAvatarLook(); + const _local_4 = RoomObjectCategory.UNIT; const _local_5 = this._roomEngine.getRoomObject(k, this._selectedAvatarId, _local_4); @@ -2100,15 +2104,26 @@ export class RoomObjectEventHandler implements IRoomCanvasMouseListener, IRoomOb { _local_5.logic.processUpdateMessage(new ObjectAvatarSelectedMessage(true)); - _local_6 = true; + _local_6 = true; - this._selectedAvatarId = _arg_2; + this._selectedAvatarId = _arg_2; - const location = _local_5.getLocation(); + const location = _local_5.getLocation(); - if(location) GetCommunication().connection.send(new RoomUnitLookComposer(~~(location.x), ~~(location.y))); - } - } + if(location) + { + this._pendingAvatarLookTimeout = setTimeout(() => + { + this._pendingAvatarLookTimeout = null; + + if(this.shouldSuppressAvatarLook()) return; + if(this._selectedAvatarId !== _arg_2) return; + + GetCommunication().connection.send(new RoomUnitLookComposer(~~(location.x), ~~(location.y))); + }, RoomObjectEventHandler.CLICK_USER_LOOK_DELAY_MS); + } + } + } const selectionArrow = this._roomEngine.getRoomObjectSelectionArrow(k); @@ -2119,6 +2134,26 @@ export class RoomObjectEventHandler implements IRoomCanvasMouseListener, IRoomOb } } + public clearSelectedAvatar(roomId: number): void + { + this.setSelectedAvatar(roomId, 0, false); + } + + private clearPendingAvatarLook(): void + { + if(!this._pendingAvatarLookTimeout) return; + + clearTimeout(this._pendingAvatarLookTimeout); + this._pendingAvatarLookTimeout = null; + } + + private shouldSuppressAvatarLook(): boolean + { + const control = (globalThis as any).__nitroAvatarClickControl; + + return !!control && (control.suppressRotateUntil > Date.now()); + } + private resetSelectedObjectData(roomId: number): void { if(!this._roomEngine) return;