diff --git a/src/hooks/events/UseEventDispatcherHook.tsx b/src/hooks/events/UseEventDispatcherHook.tsx index 36664c1c..1510d7ec 100644 --- a/src/hooks/events/UseEventDispatcherHook.tsx +++ b/src/hooks/events/UseEventDispatcherHook.tsx @@ -1,7 +1,7 @@ import { IEventDispatcher, NitroEvent } from '@nitrots/nitro-renderer'; import { useEffect } from 'react'; -export const UseEventDispatcherHook = (type: string, eventDispatcher: IEventDispatcher, handler: (event: NitroEvent) => void) => +export const UseEventDispatcherHook = (type: string, eventDispatcher: IEventDispatcher, handler: (event: T) => void) => { useEffect(() => { diff --git a/src/hooks/events/nitro/UseRoomEngineEvent.tsx b/src/hooks/events/nitro/UseRoomEngineEvent.tsx index e0c4b547..6f5f8f76 100644 --- a/src/hooks/events/nitro/UseRoomEngineEvent.tsx +++ b/src/hooks/events/nitro/UseRoomEngineEvent.tsx @@ -2,4 +2,4 @@ import { NitroEvent } from '@nitrots/nitro-renderer'; import { GetRoomEngine } from '../../../api'; import { UseEventDispatcherHook } from '../UseEventDispatcherHook'; -export const UseRoomEngineEvent = (type: string, handler: (event: NitroEvent) => void) => UseEventDispatcherHook(type, GetRoomEngine().events, handler); +export const UseRoomEngineEvent = (type: string, handler: (event: T) => void) => UseEventDispatcherHook(type, GetRoomEngine().events, handler); diff --git a/src/hooks/events/nitro/UseRoomSessionManagerEvent.tsx b/src/hooks/events/nitro/UseRoomSessionManagerEvent.tsx index 02d65be7..044f101f 100644 --- a/src/hooks/events/nitro/UseRoomSessionManagerEvent.tsx +++ b/src/hooks/events/nitro/UseRoomSessionManagerEvent.tsx @@ -2,4 +2,4 @@ import { NitroEvent } from '@nitrots/nitro-renderer'; import { GetRoomSessionManager } from '../../../api'; import { UseEventDispatcherHook } from '../UseEventDispatcherHook'; -export const UseRoomSessionManagerEvent = (type: string, handler: (event: NitroEvent) => void) => UseEventDispatcherHook(type, GetRoomSessionManager().events, handler); +export const UseRoomSessionManagerEvent = (type: string, handler: (event: T) => void) => UseEventDispatcherHook(type, GetRoomSessionManager().events, handler); diff --git a/src/hooks/rooms/index.ts b/src/hooks/rooms/index.ts index e7e7a361..baaa0188 100644 --- a/src/hooks/rooms/index.ts +++ b/src/hooks/rooms/index.ts @@ -1 +1,3 @@ +export * from './useFurniRemovedEvent'; +export * from './useRoom'; export * from './widgets'; diff --git a/src/hooks/rooms/useFurniRemovedEvent.ts b/src/hooks/rooms/useFurniRemovedEvent.ts new file mode 100644 index 00000000..432bc6d4 --- /dev/null +++ b/src/hooks/rooms/useFurniRemovedEvent.ts @@ -0,0 +1,20 @@ +import { useEffect } from 'react'; +import { RoomWidgetUpdateRoomObjectEvent } from '../../api'; +import { UI_EVENT_DISPATCHER } from '../events'; + +export const useFurniRemovedEvent = (isActive: boolean, handler: (event: RoomWidgetUpdateRoomObjectEvent) => void) => +{ + useEffect(() => + { + if(!isActive) return; + + const onRoomWidgetUpdateRoomObjectEvent = (event: RoomWidgetUpdateRoomObjectEvent) => handler(event); + + UI_EVENT_DISPATCHER.addEventListener(RoomWidgetUpdateRoomObjectEvent.FURNI_REMOVED, onRoomWidgetUpdateRoomObjectEvent); + + return () => + { + UI_EVENT_DISPATCHER.removeEventListener(RoomWidgetUpdateRoomObjectEvent.FURNI_REMOVED, onRoomWidgetUpdateRoomObjectEvent); + } + }, [ isActive, handler ]); +} diff --git a/src/hooks/rooms/useRoom.ts b/src/hooks/rooms/useRoom.ts new file mode 100644 index 00000000..4d82cb6e --- /dev/null +++ b/src/hooks/rooms/useRoom.ts @@ -0,0 +1,139 @@ +import { EventDispatcher, IRoomSession, RoomEngineEvent, RoomGeometry, RoomId, RoomSessionEvent, RoomVariableEnum, Vector3d } from '@nitrots/nitro-renderer'; +import { useCallback, useEffect, useState } from 'react'; +import { useBetween } from 'use-between'; +import { FurnitureContextMenuWidgetHandler, FurnitureDimmerWidgetHandler, FurnitureInternalLinkHandler, FurnitureRoomLinkHandler, FurnitureYoutubeDisplayWidgetHandler, GetNitroInstance, GetRoomEngine, GetRoomSession, InitializeRoomInstanceRenderingCanvas, IRoomWidgetHandlerManager, PollWidgetHandler, RoomWidgetAvatarInfoHandler, RoomWidgetChatHandler, RoomWidgetChatInputHandler, RoomWidgetHandlerManager, RoomWidgetInfostandHandler, SetActiveRoomId, StartRoomSession, WordQuizWidgetHandler } from '../../api'; +import { UseRoomEngineEvent, UseRoomSessionManagerEvent } from '../events'; + +const useRoomState = () => +{ + const [ roomSession, setRoomSession ] = useState(null); + const [ widgetHandler, setWidgetHandler ] = useState(null); + + const resize = useCallback((event: UIEvent = null) => + { + const canvas = GetNitroInstance().renderer.view; + + if(!canvas) return; + + canvas.style.width = `${ Math.floor(window.innerWidth) }px`; + canvas.style.height = `${ Math.floor(window.innerHeight) }px`; + + const nitroInstance = GetNitroInstance(); + + nitroInstance.renderer.resolution = window.devicePixelRatio; + nitroInstance.renderer.resize(window.innerWidth, window.innerHeight); + + InitializeRoomInstanceRenderingCanvas(window.innerWidth, window.innerHeight, 1); + + nitroInstance.render(); + }, []); + + const onRoomEngineEvent = useCallback((event: RoomEngineEvent) => + { + if(RoomId.isRoomPreviewerId(event.roomId)) return; + + const session = GetRoomSession(); + + if(!session) return; + + switch(event.type) + { + case RoomEngineEvent.INITIALIZED: + SetActiveRoomId(event.roomId); + setRoomSession(session); + return; + case RoomEngineEvent.DISPOSED: + setRoomSession(null); + return; + } + }, []); + + UseRoomEngineEvent(RoomEngineEvent.INITIALIZED, onRoomEngineEvent); + UseRoomEngineEvent(RoomEngineEvent.DISPOSED, onRoomEngineEvent); + + const onRoomSessionEvent = useCallback((event: RoomSessionEvent) => + { + switch(event.type) + { + case RoomSessionEvent.CREATED: + StartRoomSession(event.session); + return; + case RoomSessionEvent.ENDED: + setRoomSession(null); + return; + } + }, []); + + UseRoomSessionManagerEvent(RoomSessionEvent.CREATED, onRoomSessionEvent); + UseRoomSessionManagerEvent(RoomSessionEvent.ENDED, onRoomSessionEvent); + + useEffect(() => + { + if(!roomSession) + { + setWidgetHandler(null); + + return; + } + + const widgetHandlerManager = new RoomWidgetHandlerManager(roomSession, new EventDispatcher()); + + widgetHandlerManager.registerHandler(new RoomWidgetAvatarInfoHandler()); + widgetHandlerManager.registerHandler(new RoomWidgetInfostandHandler()); + widgetHandlerManager.registerHandler(new RoomWidgetChatInputHandler()); + widgetHandlerManager.registerHandler(new RoomWidgetChatHandler()); + widgetHandlerManager.registerHandler(new WordQuizWidgetHandler()); + widgetHandlerManager.registerHandler(new PollWidgetHandler()); + widgetHandlerManager.registerHandler(new FurnitureContextMenuWidgetHandler()); + widgetHandlerManager.registerHandler(new FurnitureDimmerWidgetHandler()); + widgetHandlerManager.registerHandler(new FurnitureYoutubeDisplayWidgetHandler()); + widgetHandlerManager.registerHandler(new FurnitureInternalLinkHandler()); + widgetHandlerManager.registerHandler(new FurnitureRoomLinkHandler()); + + setWidgetHandler(widgetHandlerManager); + + const roomEngine = GetRoomEngine(); + const roomId = roomSession.roomId; + const canvasId = 1; + + resize(); + + const displayObject = roomEngine.getRoomInstanceDisplay(roomId, canvasId, window.innerWidth, window.innerHeight, RoomGeometry.SCALE_ZOOMED_IN); + + if(!displayObject) return; + + const geometry = (roomEngine.getRoomInstanceGeometry(roomId, canvasId) as RoomGeometry); + + if(geometry) + { + const minX = (roomEngine.getRoomInstanceVariable(roomId, RoomVariableEnum.ROOM_MIN_X) || 0); + const maxX = (roomEngine.getRoomInstanceVariable(roomId, RoomVariableEnum.ROOM_MAX_X) || 0); + const minY = (roomEngine.getRoomInstanceVariable(roomId, RoomVariableEnum.ROOM_MIN_Y) || 0); + const maxY = (roomEngine.getRoomInstanceVariable(roomId, RoomVariableEnum.ROOM_MAX_Y) || 0); + + let x = ((minX + maxX) / 2); + let y = ((minY + maxY) / 2); + + const offset = 20; + + x = (x + (offset - 1)); + y = (y + (offset - 1)); + + const z = (Math.sqrt(((offset * offset) + (offset * offset))) * Math.tan(((30 / 180) * Math.PI))); + + geometry.location = new Vector3d(x, y, z); + } + + const stage = GetNitroInstance().stage; + + if(!stage) return; + + stage.addChild(displayObject); + + SetActiveRoomId(roomSession.roomId); + }, [ roomSession, resize ]); + + return { roomSession, widgetHandler, resize }; +} + +export const useRoom = () => useBetween(useRoomState); diff --git a/src/hooks/rooms/widgets/furniture/index.ts b/src/hooks/rooms/widgets/furniture/index.ts new file mode 100644 index 00000000..f642bb87 --- /dev/null +++ b/src/hooks/rooms/widgets/furniture/index.ts @@ -0,0 +1,10 @@ +export * from './useFurnitureBackgroundColorWidget'; +export * from './useFurnitureBadgeDisplayWidget'; +export * from './useFurnitureExchangeWidget'; +export * from './useFurnitureExternalImageWidget'; +export * from './useFurnitureManipulationWidget'; +export * from './useFurnitureMannequinWidget'; +export * from './useFurniturePresentWidget'; +export * from './useFurnitureStackHeightWidget'; +export * from './useFurnitureStickieWidget'; +export * from './useFurnitureTrophyWidget'; diff --git a/src/hooks/rooms/widgets/furniture/useFurnitureBackgroundColorWidget.ts b/src/hooks/rooms/widgets/furniture/useFurnitureBackgroundColorWidget.ts new file mode 100644 index 00000000..46665819 --- /dev/null +++ b/src/hooks/rooms/widgets/furniture/useFurnitureBackgroundColorWidget.ts @@ -0,0 +1,62 @@ +import { ApplyTonerComposer, RoomEngineTriggerWidgetEvent, RoomObjectVariable } from '@nitrots/nitro-renderer'; +import { useCallback, useEffect, useState } from 'react'; +import { CanManipulateFurniture, GetRoomEngine, RoomWidgetUpdateBackgroundColorPreviewEvent, SendMessageComposer } from '../../../../api'; +import { UseRoomEngineEvent } from '../../../events'; +import { useFurniRemovedEvent } from '../../useFurniRemovedEvent'; +import { useRoom } from '../../useRoom'; + +const useFurnitureBackgroundColorWidgetState = () => +{ + const [ objectId, setObjectId ] = useState(-1); + const [ category, setCategory ] = useState(-1); + const [ hue, setHue ] = useState(0); + const [ saturation, setSaturation ] = useState(0); + const [ lightness, setLightness ] = useState(0); + const { roomSession = null, widgetHandler = null } = useRoom(); + + const applyToner = () => SendMessageComposer(new ApplyTonerComposer(objectId, hue, saturation, lightness)); + const toggleToner = () => roomSession.useMultistateItem(objectId); + + const close = useCallback(() => + { + widgetHandler.eventDispatcher.dispatchEvent(new RoomWidgetUpdateBackgroundColorPreviewEvent(RoomWidgetUpdateBackgroundColorPreviewEvent.CLEAR_PREVIEW)); + + setObjectId(-1); + setCategory(-1); + setHue(0); + setSaturation(0); + setLightness(0); + }, [ widgetHandler ]); + + UseRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_BACKGROUND_COLOR, event => + { + if(!CanManipulateFurniture(roomSession, event.objectId, event.category)) return; + + const roomObject = GetRoomEngine().getRoomObject(event.roomId, event.objectId, event.category); + const model = roomObject.model; + + setObjectId(event.objectId); + setCategory(event.category) + setHue(parseInt(model.getValue(RoomObjectVariable.FURNITURE_ROOM_BACKGROUND_COLOR_HUE))); + setSaturation(parseInt(model.getValue(RoomObjectVariable.FURNITURE_ROOM_BACKGROUND_COLOR_SATURATION))); + setLightness(parseInt(model.getValue(RoomObjectVariable.FURNITURE_ROOM_BACKGROUND_COLOR_LIGHTNESS))); + }); + + useFurniRemovedEvent(((objectId !== -1) && (category !== -1)), event => + { + if((event.id !== objectId) || (event.category !== category)) return; + + close(); + }); + + useEffect(() => + { + if((objectId === -1) || (category === -1)) return; + + widgetHandler.eventDispatcher.dispatchEvent(new RoomWidgetUpdateBackgroundColorPreviewEvent(RoomWidgetUpdateBackgroundColorPreviewEvent.PREVIEW, hue, saturation, lightness)); + }, [ objectId, category, widgetHandler, hue, saturation, lightness ]); + + return { objectId, hue, setHue, saturation, setSaturation, lightness, setLightness, applyToner, toggleToner, close }; +} + +export const useFurnitureBackgroundColorWidget = useFurnitureBackgroundColorWidgetState; diff --git a/src/hooks/rooms/widgets/furniture/useFurnitureBadgeDisplayWidget.ts b/src/hooks/rooms/widgets/furniture/useFurnitureBadgeDisplayWidget.ts new file mode 100644 index 00000000..8c20ef46 --- /dev/null +++ b/src/hooks/rooms/widgets/furniture/useFurnitureBadgeDisplayWidget.ts @@ -0,0 +1,60 @@ +import { RoomEngineTriggerWidgetEvent, StringDataType } from '@nitrots/nitro-renderer'; +import { useCallback, useState } from 'react'; +import { GetRoomEngine, LocalizeBadgeDescription, LocalizeBadgeName } from '../../../../api'; +import { UseRoomEngineEvent } from '../../../events'; +import { useFurniRemovedEvent } from '../../useFurniRemovedEvent'; + +const useFurnitureBadgeDisplayWidgetState = () => +{ + const [ objectId, setObjectId ] = useState(-1); + const [ category, setCategory ] = useState(-1); + const [ color, setColor ] = useState('1'); + const [ badgeName, setBadgeName ] = useState(''); + const [ badgeDesc, setBadgeDesc ] = useState(''); + const [ date, setDate ] = useState(''); + const [ senderName, setSenderName ] = useState(''); + + const close = useCallback(() => + { + setObjectId(-1); + setCategory(-1); + setColor('1'); + setBadgeName(''); + setBadgeDesc(''); + setDate(''); + setSenderName(''); + }, []); + + const onRoomEngineTriggerWidgetEvent = useCallback((event: RoomEngineTriggerWidgetEvent) => + { + const roomObject = GetRoomEngine().getRoomObject(event.roomId, event.objectId, event.category); + + if(!roomObject) return; + + const stringStuff = new StringDataType(); + + stringStuff.initializeFromRoomObjectModel(roomObject.model); + + setObjectId(event.objectId); + setCategory(event.category); + setColor('1'); + setBadgeName(LocalizeBadgeName(stringStuff.getValue(1))); + setBadgeDesc(LocalizeBadgeDescription(stringStuff.getValue(1))); + setDate(stringStuff.getValue(2)); + setSenderName(stringStuff.getValue(3)); + }, []); + + UseRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_BADGE_DISPLAY_ENGRAVING, onRoomEngineTriggerWidgetEvent); + UseRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_ACHIEVEMENT_RESOLUTION_ENGRAVING, onRoomEngineTriggerWidgetEvent); + + useFurniRemovedEvent(((objectId !== -1) && (category !== -1)), event => + { + if((event.id !== objectId) || (event.category !== category)) return; + + close(); + }); + + return { objectId, category, color, badgeName, badgeDesc, date, senderName, close }; +} + +export const useFurnitureBadgeDisplayWidget = useFurnitureBadgeDisplayWidgetState; diff --git a/src/hooks/rooms/widgets/furniture/useFurnitureExchangeWidget.ts b/src/hooks/rooms/widgets/furniture/useFurnitureExchangeWidget.ts new file mode 100644 index 00000000..990466e8 --- /dev/null +++ b/src/hooks/rooms/widgets/furniture/useFurnitureExchangeWidget.ts @@ -0,0 +1,48 @@ +import { FurnitureExchangeComposer, RoomEngineTriggerWidgetEvent, RoomObjectVariable } from '@nitrots/nitro-renderer'; +import { useCallback, useState } from 'react'; +import { GetRoomEngine, GetRoomSession, IsOwnerOfFurniture } from '../../../../api'; +import { UseRoomEngineEvent } from '../../../events'; +import { useFurniRemovedEvent } from '../../useFurniRemovedEvent'; + +const useFurnitureExchangeWidgetState = () => +{ + const [ objectId, setObjectId ] = useState(-1); + const [ category, setCategory ] = useState(-1); + const [ value, setValue ] = useState(0); + + const redeem = () => + { + GetRoomSession().connection.send(new FurnitureExchangeComposer(objectId)); + + close(); + } + + const close = useCallback(() => + { + setObjectId(-1); + setCategory(-1); + setValue(0); + }, []); + + UseRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_CREDITFURNI, event => + { + const roomObject = GetRoomEngine().getRoomObject(event.roomId, event.objectId, event.category); + + if(!roomObject || !IsOwnerOfFurniture(roomObject)) return; + + setObjectId(event.objectId); + setCategory(event.category); + setValue(roomObject.model.getValue(RoomObjectVariable.FURNITURE_CREDIT_VALUE) || 0); + }); + + useFurniRemovedEvent(((objectId !== -1) && (category !== -1)), event => + { + if((event.id !== objectId) || (event.category !== category)) return; + + close(); + }); + + return { objectId, value, redeem, close }; +} + +export const useFurnitureExchangeWidget = useFurnitureExchangeWidgetState; diff --git a/src/hooks/rooms/widgets/furniture/useFurnitureExternalImageWidget.ts b/src/hooks/rooms/widgets/furniture/useFurnitureExternalImageWidget.ts new file mode 100644 index 00000000..3b1dbcc8 --- /dev/null +++ b/src/hooks/rooms/widgets/furniture/useFurnitureExternalImageWidget.ts @@ -0,0 +1,44 @@ +import { RoomEngineTriggerWidgetEvent, RoomObjectVariable } from '@nitrots/nitro-renderer'; +import { useState } from 'react'; +import { GetRoomEngine, IPhotoData } from '../../../../api'; +import { UseRoomEngineEvent } from '../../../events'; +import { useFurniRemovedEvent } from '../../useFurniRemovedEvent'; + +const useFurnitureExternalImageWidgetState = () => +{ + const [ objectId, setObjectId ] = useState(-1); + const [ category, setCategory ] = useState(-1); + const [ photoData, setPhotoData ] = useState(null); + + const close = () => + { + setObjectId(-1); + setCategory(-1); + setPhotoData(null); + } + + UseRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_EXTERNAL_IMAGE, event => + { + const roomObject = GetRoomEngine().getRoomObject(event.roomId, event.objectId, event.category); + + if(!roomObject) return; + + const data = roomObject.model.getValue(RoomObjectVariable.FURNITURE_DATA); + const photoData = (JSON.parse(data) as IPhotoData); + + setObjectId(event.objectId); + setCategory(event.category); + setPhotoData(photoData); + }); + + useFurniRemovedEvent(((objectId !== -1) && (category !== -1)), event => + { + if((event.id !== objectId) || (event.category !== category)) return; + + close(); + }); + + return { objectId, photoData, close }; +} + +export const useFurnitureExternalImageWidget = useFurnitureExternalImageWidgetState; diff --git a/src/hooks/rooms/widgets/furniture/useFurnitureManipulationWidget.ts b/src/hooks/rooms/widgets/furniture/useFurnitureManipulationWidget.ts new file mode 100644 index 00000000..85c272de --- /dev/null +++ b/src/hooks/rooms/widgets/furniture/useFurnitureManipulationWidget.ts @@ -0,0 +1,123 @@ +import { RoomEngineObjectEvent, RoomId, RoomObjectCategory, RoomObjectOperationType } from '@nitrots/nitro-renderer'; +import { useCallback, useState } from 'react'; +import { CanManipulateFurniture, IsFurnitureSelectionDisabled, ProcessRoomObjectOperation, RoomWidgetUpdateRoomObjectEvent } from '../../../../api'; +import { UI_EVENT_DISPATCHER, UseRoomEngineEvent } from '../../../events'; +import { useRoom } from '../../useRoom'; + +const useFurnitureManipulationWidgetState = () => +{ + const [ manipulatingId, setManipulatingId ] = useState(-1); + const [ manipulatingCategory, setManipulatingCategory ] = useState(-1); + const { roomSession = null, widgetHandler = null } = useRoom(); + + const moveObject = () => ProcessRoomObjectOperation(manipulatingId, manipulatingCategory, RoomObjectOperationType.OBJECT_MOVE); + + const onRoomEngineObjectEvent = useCallback((event: RoomEngineObjectEvent) => + { + let updateEvent: RoomWidgetUpdateRoomObjectEvent = null; + + switch(event.type) + { + case RoomEngineObjectEvent.SELECTED: + if(!IsFurnitureSelectionDisabled(event)) updateEvent = new RoomWidgetUpdateRoomObjectEvent(RoomWidgetUpdateRoomObjectEvent.OBJECT_SELECTED, event.objectId, event.category, event.roomId); + break; + case RoomEngineObjectEvent.DESELECTED: + updateEvent = new RoomWidgetUpdateRoomObjectEvent(RoomWidgetUpdateRoomObjectEvent.OBJECT_DESELECTED, event.objectId, event.category, event.roomId); + + if(manipulatingId > -1) + { + setManipulatingId(-1); + setManipulatingCategory(-1); + } + break; + case RoomEngineObjectEvent.ADDED: { + let addedEventType: string = null; + + switch(event.category) + { + case RoomObjectCategory.FLOOR: + case RoomObjectCategory.WALL: + addedEventType = RoomWidgetUpdateRoomObjectEvent.FURNI_ADDED; + break; + case RoomObjectCategory.UNIT: + addedEventType = RoomWidgetUpdateRoomObjectEvent.USER_ADDED; + break; + } + + if(addedEventType) updateEvent = new RoomWidgetUpdateRoomObjectEvent(addedEventType, event.objectId, event.category, event.roomId); + break; + } + case RoomEngineObjectEvent.REMOVED: { + let removedEventType: string = null; + + switch(event.category) + { + case RoomObjectCategory.FLOOR: + case RoomObjectCategory.WALL: + removedEventType = RoomWidgetUpdateRoomObjectEvent.FURNI_REMOVED; + + if(manipulatingId === event.objectId) + { + setManipulatingId(-1); + setManipulatingCategory(-1); + } + break; + case RoomObjectCategory.UNIT: + removedEventType = RoomWidgetUpdateRoomObjectEvent.USER_REMOVED; + break; + } + + if(removedEventType) updateEvent = new RoomWidgetUpdateRoomObjectEvent(removedEventType, event.objectId, event.category, event.roomId); + break; + } + case RoomEngineObjectEvent.REQUEST_MOVE: + if(CanManipulateFurniture(roomSession, event.objectId, event.category)) ProcessRoomObjectOperation(event.objectId, event.category, RoomObjectOperationType.OBJECT_MOVE); + break; + case RoomEngineObjectEvent.REQUEST_ROTATE: + if(CanManipulateFurniture(roomSession, event.objectId, event.category)) ProcessRoomObjectOperation(event.objectId, event.category, RoomObjectOperationType.OBJECT_ROTATE_POSITIVE); + break; + case RoomEngineObjectEvent.REQUEST_MANIPULATION: + if(CanManipulateFurniture(roomSession, event.objectId, event.category)) + { + setManipulatingId(event.objectId); + setManipulatingCategory(event.category); + } + break; + case RoomEngineObjectEvent.MOUSE_ENTER: + updateEvent = new RoomWidgetUpdateRoomObjectEvent(RoomWidgetUpdateRoomObjectEvent.OBJECT_ROLL_OVER, event.objectId, event.category, event.roomId); + break; + case RoomEngineObjectEvent.MOUSE_LEAVE: + updateEvent = new RoomWidgetUpdateRoomObjectEvent(RoomWidgetUpdateRoomObjectEvent.OBJECT_ROLL_OUT, event.objectId, event.category, event.roomId); + break; + } + + if(updateEvent) + { + let dispatchEvent = true; + + if(updateEvent instanceof RoomWidgetUpdateRoomObjectEvent) dispatchEvent = (!RoomId.isRoomPreviewerId(updateEvent.roomId)); + + if(dispatchEvent) + { + widgetHandler.eventDispatcher.dispatchEvent(updateEvent); + + UI_EVENT_DISPATCHER.dispatchEvent(updateEvent); + } + } + }, [ roomSession, widgetHandler, manipulatingId ]); + + UseRoomEngineEvent(RoomEngineObjectEvent.SELECTED, onRoomEngineObjectEvent); + UseRoomEngineEvent(RoomEngineObjectEvent.DESELECTED, onRoomEngineObjectEvent); + UseRoomEngineEvent(RoomEngineObjectEvent.ADDED, onRoomEngineObjectEvent); + UseRoomEngineEvent(RoomEngineObjectEvent.REMOVED, onRoomEngineObjectEvent); + UseRoomEngineEvent(RoomEngineObjectEvent.PLACED, onRoomEngineObjectEvent); + UseRoomEngineEvent(RoomEngineObjectEvent.REQUEST_MOVE, onRoomEngineObjectEvent); + UseRoomEngineEvent(RoomEngineObjectEvent.REQUEST_ROTATE, onRoomEngineObjectEvent); + UseRoomEngineEvent(RoomEngineObjectEvent.REQUEST_MANIPULATION, onRoomEngineObjectEvent); + UseRoomEngineEvent(RoomEngineObjectEvent.MOUSE_ENTER, onRoomEngineObjectEvent); + UseRoomEngineEvent(RoomEngineObjectEvent.MOUSE_LEAVE, onRoomEngineObjectEvent); + + return { manipulatingId, manipulatingCategory, moveObject }; +} + +export const useFurnitureManipulationWidget = useFurnitureManipulationWidgetState; diff --git a/src/hooks/rooms/widgets/furniture/useFurnitureMannequinWidget.ts b/src/hooks/rooms/widgets/furniture/useFurnitureMannequinWidget.ts new file mode 100644 index 00000000..d9ba5cf1 --- /dev/null +++ b/src/hooks/rooms/widgets/furniture/useFurnitureMannequinWidget.ts @@ -0,0 +1,89 @@ +import { AvatarFigurePartType, FurnitureMannequinSaveLookComposer, FurnitureMannequinSaveNameComposer, FurnitureMultiStateComposer, HabboClubLevelEnum, RoomEngineTriggerWidgetEvent, RoomObjectVariable } from '@nitrots/nitro-renderer'; +import { useCallback, useState } from 'react'; +import { GetAvatarRenderManager, GetRoomEngine, SendMessageComposer } from '../../../../api'; +import { UseRoomEngineEvent } from '../../../events'; +import { useFurniRemovedEvent } from '../../useFurniRemovedEvent'; + +const MANNEQUIN_CLOTHING_PART_TYPES = [ + AvatarFigurePartType.CHEST_ACCESSORY, + AvatarFigurePartType.COAT_CHEST, + AvatarFigurePartType.CHEST, + AvatarFigurePartType.LEGS, + AvatarFigurePartType.SHOES, + AvatarFigurePartType.WAIST_ACCESSORY +]; + +const useFurnitureMannequinWidgetState = () => +{ + const [ objectId, setObjectId ] = useState(-1); + const [ category, setCategory ] = useState(-1); + const [ figure, setFigure ] = useState(null); + const [ gender, setGender ] = useState(null); + const [ clubLevel, setClubLevel ] = useState(HabboClubLevelEnum.NO_CLUB); + const [ name, setName ] = useState(null); + + const close = useCallback(() => + { + setObjectId(-1); + setCategory(-1); + setFigure(null); + setGender(null); + setName(null); + }, []); + + const saveFigure = () => + { + if(objectId === -1) return; + + SendMessageComposer(new FurnitureMannequinSaveLookComposer(objectId)); + + close(); + } + + const wearFigure = () => + { + if(objectId === -1) return; + + SendMessageComposer(new FurnitureMultiStateComposer(objectId)); + + close(); + } + + const saveName = () => + { + if(objectId === -1) return; + + SendMessageComposer(new FurnitureMannequinSaveNameComposer(objectId, name)); + } + + UseRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_MANNEQUIN, event => + { + const roomObject = GetRoomEngine().getRoomObject(event.roomId, event.objectId, event.category); + + if(!roomObject) return; + + const model = roomObject.model; + const figure = (model.getValue(RoomObjectVariable.FURNITURE_MANNEQUIN_FIGURE) || null); + const gender = (model.getValue(RoomObjectVariable.FURNITURE_MANNEQUIN_GENDER) || null); + const figureContainer = GetAvatarRenderManager().createFigureContainer(figure); + const figureClubLevel = GetAvatarRenderManager().getFigureClubLevel(figureContainer, gender, MANNEQUIN_CLOTHING_PART_TYPES); + + setObjectId(event.objectId); + setCategory(event.category); + setFigure(figure); + setGender(gender); + setClubLevel(figureClubLevel); + setName(model.getValue(RoomObjectVariable.FURNITURE_MANNEQUIN_NAME) || null); + }); + + useFurniRemovedEvent(((objectId !== -1) && (category !== -1)), event => + { + if((event.id !== objectId) || (event.category !== category)) return; + + close(); + }); + + return { objectId, figure, gender, clubLevel, name, setName, saveFigure, wearFigure, saveName, close }; +} + +export const useFurnitureMannequinWidget = useFurnitureMannequinWidgetState; diff --git a/src/hooks/rooms/widgets/furniture/useFurniturePresentWidget.ts b/src/hooks/rooms/widgets/furniture/useFurniturePresentWidget.ts new file mode 100644 index 00000000..871a7741 --- /dev/null +++ b/src/hooks/rooms/widgets/furniture/useFurniturePresentWidget.ts @@ -0,0 +1,225 @@ +import { IFurnitureData, IGetImageListener, PetFigureData, RoomEngineTriggerWidgetEvent, RoomObjectCategory, RoomObjectVariable, RoomSessionPresentEvent, TextureUtils, Vector3d } from '@nitrots/nitro-renderer'; +import { useMemo, useState } from 'react'; +import { useRoom } from '../../..'; +import { GetRoomEngine, GetSessionDataManager, IsOwnerOfFurniture, LocalizeText, ProductTypeEnum } from '../../../../api'; +import { UseRoomEngineEvent, UseRoomSessionManagerEvent } from '../../../events'; +import { useFurniRemovedEvent } from '../../useFurniRemovedEvent'; + +const FLOOR: string = 'floor'; +const WALLPAPER: string = 'wallpaper'; +const LANDSCAPE: string = 'landscape'; +const POSTER: string = 'poster'; + +const useFurniturePresentWidgetState = () => +{ + const [ objectId, setObjectId ] = useState(-1); + const [ classId, setClassId ] = useState(-1); + const [ itemType, setItemType ] = useState(null); + const [ text, setText ] = useState(null); + const [ isOwnerOfFurniture, setIsOwnerOfFurniture ] = useState(false); + const [ senderName, setSenderName ] = useState(null); + const [ senderFigure, setSenderFigure ] = useState(null); + const [ placedItemId, setPlacedItemId ] = useState(-1); + const [ placedItemType, setPlacedItemType ] = useState(null); + const [ placedInRoom, setPlacedInRoom ] = useState(false); + const [ imageUrl, setImageUrl ] = useState(null); + const { roomSession = null } = useRoom(); + + const openPresent = () => + { + if(objectId === -1) return; + + roomSession.openGift(objectId); + + GetRoomEngine().changeObjectModelData(GetRoomEngine().activeRoomId, objectId, RoomObjectCategory.FLOOR, RoomObjectVariable.FURNITURE_DISABLE_PICKING_ANIMATION, 1); + } + + const close = () => + { + setObjectId(-1); + setClassId(-1); + setItemType(null); + setText(null); + setIsOwnerOfFurniture(false); + setSenderName(null); + setSenderFigure(null); + setPlacedItemId(-1); + setPlacedItemType(null); + setPlacedInRoom(false); + setImageUrl(null); + } + + const imageListener: IGetImageListener = useMemo(() => + { + return { + imageReady: (id, texture, image) => + { + if(!image && texture) + { + image = TextureUtils.generateImage(texture); + } + + setImageUrl(image.src); + }, + imageFailed: null + } + }, []); + + UseRoomSessionManagerEvent(RoomSessionPresentEvent.RSPE_PRESENT_OPENED, event => + { + let furniData: IFurnitureData = null; + + if(event.itemType === ProductTypeEnum.FLOOR) + { + furniData = GetSessionDataManager().getFloorItemData(event.classId); + } + else if(event.itemType === ProductTypeEnum.WALL) + { + furniData = GetSessionDataManager().getWallItemData(event.classId); + } + + let isOwnerOfFurni = false; + + if(event.placedInRoom) + { + const roomObject = GetRoomEngine().getRoomObject(roomSession.roomId, event.placedItemId, RoomObjectCategory.FLOOR); + + if(roomObject) isOwnerOfFurni = IsOwnerOfFurniture(roomObject); + } + + let giftImage: string = null; + + switch(event.itemType) + { + case ProductTypeEnum.WALL: { + if(furniData) + { + switch(furniData.className) + { + case FLOOR: + case LANDSCAPE: + case WALLPAPER: + let imageType = null; + let message = null; + + if(furniData.className === FLOOR) + { + imageType = 'packagecard_icon_floor'; + message = LocalizeText('inventory.furni.item.floor.name'); + } + + else if(furniData.className === LANDSCAPE) + { + imageType = 'packagecard_icon_landscape'; + message = LocalizeText('inventory.furni.item.landscape.name'); + } + + else + { + imageType = 'packagecard_icon_wallpaper'; + message = LocalizeText('inventory.furni.item.wallpaper.name'); + } + + setText(message); + //setImageUrl(getGiftImageUrl(imageType)); + break; + case POSTER: { + const productCode = event.productCode; + + let extras: string = null; + + if(productCode.indexOf('poster') === 0) extras = productCode.replace('poster', ''); + + const productData = GetSessionDataManager().getProductData(productCode); + + let name: string = null; + + if(productData) name = productData.name; + else if(furniData) name = furniData.name; + + setText(name); + setImageUrl(GetRoomEngine().getFurnitureWallIconUrl(event.classId, extras)); + + break; + } + default: { + setText(furniData.name || null); + setImageUrl(GetRoomEngine().getFurnitureWallIconUrl(event.classId)); + break; + } + } + } + + break; + } + case ProductTypeEnum.HABBO_CLUB: + setText(LocalizeText('widget.furni.present.hc')); + //setImageUrl(getGiftImageUrl('packagecard_icon_hc')); + break; + default: { + if(event.placedItemType === ProductTypeEnum.PET) + { + const petfigureString = event.petFigureString; + + if(petfigureString && petfigureString.length) + { + const petFigureData = new PetFigureData(petfigureString); + + const petImage = GetRoomEngine().getRoomObjectPetImage(petFigureData.typeId, petFigureData.paletteId, petFigureData.color, new Vector3d(90), 64, imageListener, true, 0, petFigureData.customParts); + + if(petImage) setImageUrl(petImage.getImage().src); + } + } + else + { + const furniImage = GetRoomEngine().getFurnitureFloorImage(event.classId, new Vector3d(90), 64, imageListener); + + if(furniImage) setImageUrl(furniImage.getImage().src); + } + + const productData = GetSessionDataManager().getProductData(event.productCode); + + setText((productData && productData.name) || furniData.name); + break; + } + } + + setObjectId(0); + setClassId(event.classId); + setItemType(event.itemType); + setIsOwnerOfFurniture(isOwnerOfFurni); + setPlacedItemId(event.placedItemId); + setPlacedItemType(event.placedItemType); + setPlacedInRoom(event.placedInRoom); + }); + + UseRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_PRESENT, event => + { + const roomObject = GetRoomEngine().getRoomObject(event.roomId, event.objectId, event.category); + + if(!roomObject) return null; + + close(); + + setObjectId(event.objectId); + setClassId(-1); + setText((roomObject.model.getValue(RoomObjectVariable.FURNITURE_DATA) || '')); + setIsOwnerOfFurniture(IsOwnerOfFurniture(roomObject)); + setSenderName((roomObject.model.getValue(RoomObjectVariable.FURNITURE_PURCHASER_NAME) || null)); + setSenderFigure((roomObject.model.getValue(RoomObjectVariable.FURNITURE_PURCHASER_FIGURE) || null)); + }); + + useFurniRemovedEvent((objectId !== -1), event => + { + if(event.id === objectId) close(); + + if(event.id === placedItemId) + { + if(placedInRoom) setPlacedInRoom(false); + } + }); + + return { objectId, classId, itemType, text, isOwnerOfFurniture, senderName, senderFigure, placedItemId, placedItemType, placedInRoom, imageUrl, openPresent, close }; +} + +export const useFurniturePresentWidget = useFurniturePresentWidgetState; diff --git a/src/hooks/rooms/widgets/furniture/useFurnitureStackHeightWidget.ts b/src/hooks/rooms/widgets/furniture/useFurnitureStackHeightWidget.ts new file mode 100644 index 00000000..33ecdcf7 --- /dev/null +++ b/src/hooks/rooms/widgets/furniture/useFurnitureStackHeightWidget.ts @@ -0,0 +1,87 @@ +import { FurnitureStackHeightComposer, FurnitureStackHeightEvent, RoomEngineTriggerWidgetEvent } from '@nitrots/nitro-renderer'; +import { useCallback, useEffect, useState } from 'react'; +import { CanManipulateFurniture, GetRoomEngine, GetRoomSession, SendMessageComposer } from '../../../../api'; +import { UseRoomEngineEvent } from '../../../events'; +import { UseMessageEventHook } from '../../../messages'; +import { useFurniRemovedEvent } from '../../useFurniRemovedEvent'; + +const MAX_HEIGHT: number = 40; + +const useFurnitureStackHeightWidgetState = () => +{ + const [ objectId, setObjectId ] = useState(-1); + const [ category, setCategory ] = useState(-1); + const [ height, setHeight ] = useState(0); + const [ pendingHeight, setPendingHeight ] = useState(-1); + + const close = useCallback(() => + { + setObjectId(-1); + setCategory(-1); + setHeight(0); + setPendingHeight(-1); + }, []); + + const updateHeight = useCallback((height: number, server: boolean = false) => + { + if(!height) height = 0; + + height = Math.abs(height); + + if(!server) ((height > MAX_HEIGHT) && (height = MAX_HEIGHT)); + + setHeight(parseFloat(height.toFixed(2))); + + if(!server) setPendingHeight(height * 100); + }, []); + + const sendUpdate = useCallback((height: number) => + { + SendMessageComposer(new FurnitureStackHeightComposer(objectId, ~~(height))); + }, [ objectId ]); + + const onFurnitureStackHeightEvent = useCallback((event: FurnitureStackHeightEvent) => + { + const parser = event.getParser(); + + if(objectId !== parser.furniId) return; + + updateHeight(parser.height, true); + }, [ objectId, updateHeight ]); + + UseMessageEventHook(FurnitureStackHeightEvent, onFurnitureStackHeightEvent); + + UseRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_STACK_HEIGHT, event => + { + if(!CanManipulateFurniture(GetRoomSession(), event.objectId, event.category)) return; + + const roomObject = GetRoomEngine().getRoomObject(event.roomId, event.objectId, event.category); + + if(!roomObject) return; + + setObjectId(event.objectId); + setCategory(event.category); + setHeight(roomObject.getLocation().z); + setPendingHeight(-1); + }); + + useEffect(() => + { + if((objectId === -1) || (pendingHeight === -1)) return; + + const timeout = setTimeout(() => sendUpdate(~~(pendingHeight)), 10); + + return () => clearTimeout(timeout); + }, [ objectId, pendingHeight, sendUpdate ]); + + useFurniRemovedEvent(((objectId !== -1) && (category !== -1)), event => + { + if((event.id !== objectId) || (event.category !== category)) return; + + close(); + }); + + return { objectId, height, maxHeight: MAX_HEIGHT, close, updateHeight, sendUpdate }; +} + +export const useFurnitureStackHeightWidget = useFurnitureStackHeightWidgetState; diff --git a/src/hooks/rooms/widgets/furniture/useFurnitureStickieWidget.ts b/src/hooks/rooms/widgets/furniture/useFurnitureStickieWidget.ts new file mode 100644 index 00000000..458e8765 --- /dev/null +++ b/src/hooks/rooms/widgets/furniture/useFurnitureStickieWidget.ts @@ -0,0 +1,83 @@ +import { RoomEngineTriggerWidgetEvent, RoomObjectVariable } from '@nitrots/nitro-renderer'; +import { useCallback, useState } from 'react'; +import { GetRoomEngine, GetRoomSession, GetSessionDataManager } from '../../../../api'; +import { UseRoomEngineEvent } from '../../../events'; +import { useFurniRemovedEvent } from '../../useFurniRemovedEvent'; + +const useFurnitureStickieWidgetState = () => +{ + const [ objectId, setObjectId ] = useState(-1); + const [ category, setCategory ] = useState(-1); + const [ color, setColor ] = useState('0'); + const [ text, setText ] = useState(''); + + const canModify = (GetRoomSession().isRoomOwner || GetSessionDataManager().isModerator); + + const close = useCallback(() => + { + setObjectId(-1); + setCategory(-1); + setColor('0'); + setText(''); + }, []); + + const updateColor = (newColor: string) => + { + if(newColor === color) return; + + setColor(newColor); + + GetRoomEngine().modifyRoomObjectData(objectId, category, newColor, text); + } + + const updateText = (newText: string) => + { + setText(newText); + + GetRoomEngine().modifyRoomObjectData(objectId, category, color, newText); + } + + const trash = () => GetRoomEngine().deleteRoomObject(objectId, category); + + const onRoomEngineTriggerWidgetEvent = useCallback((event: RoomEngineTriggerWidgetEvent) => + { + const roomObject = GetRoomEngine().getRoomObject(event.roomId, event.objectId, event.category); + + if(!roomObject) return; + + const data = roomObject.model.getValue(RoomObjectVariable.FURNITURE_ITEMDATA); + + if(data.length < 6) return; + + let color: string = null; + let text: string = null; + + if(data.indexOf(' ') > 0) + { + color = data.slice(0, data.indexOf(' ')); + text = data.slice((data.indexOf(' ') + 1), data.length); + } + else + { + color = data; + } + + setObjectId(event.objectId); + setCategory(event.category); + setColor(color || '0'); + setText(text || ''); + }, []); + + UseRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_STICKIE, onRoomEngineTriggerWidgetEvent); + + useFurniRemovedEvent(((objectId !== -1) && (category !== -1)), event => + { + if((event.id !== objectId) || (event.category !== category)) return; + + close(); + }); + + return { objectId, color, text, canModify, updateColor, updateText, trash, close }; +} + +export const useFurnitureStickieWidget = useFurnitureStickieWidgetState; diff --git a/src/hooks/rooms/widgets/furniture/useFurnitureTrophyWidget.ts b/src/hooks/rooms/widgets/furniture/useFurnitureTrophyWidget.ts new file mode 100644 index 00000000..aea2f5b1 --- /dev/null +++ b/src/hooks/rooms/widgets/furniture/useFurnitureTrophyWidget.ts @@ -0,0 +1,63 @@ +import { RoomEngineTriggerWidgetEvent, RoomObjectVariable } from '@nitrots/nitro-renderer'; +import { useCallback, useState } from 'react'; +import { GetRoomEngine } from '../../../../api'; +import { UseRoomEngineEvent } from '../../../events'; +import { useFurniRemovedEvent } from '../../useFurniRemovedEvent'; + +const useFurnitureTrophyWidgetState = () => +{ + const [ objectId, setObjectId ] = useState(-1); + const [ category, setCategory ] = useState(-1); + const [ color, setColor ] = useState('1'); + const [ senderName, setSenderName ] = useState(''); + const [ date, setDate ] = useState(''); + const [ message, setMessage ] = useState(''); + + const close = useCallback(() => + { + setObjectId(-1); + setCategory(-1); + setColor('1'); + setSenderName(''); + setDate(''); + setMessage(''); + }, []); + + UseRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_TROPHY, event => + { + const roomObject = GetRoomEngine().getRoomObject(event.roomId, event.objectId, event.category); + + if(!roomObject) return; + + let data = roomObject.model.getValue(RoomObjectVariable.FURNITURE_DATA); + let extra = roomObject.model.getValue(RoomObjectVariable.FURNITURE_EXTRAS); + + if(!extra) extra = '0'; + + setObjectId(event.objectId); + setCategory(event.category); + setColor(roomObject.model.getValue(RoomObjectVariable.FURNITURE_COLOR) || '1'); + + const senderName = data.substring(0, data.indexOf('\t')); + + data = data.substring((senderName.length + 1), data.length); + + const trophyDate = data.substring(0, data.indexOf('\t')); + const trophyText = data.substr((trophyDate.length + 1), data.length); + + setSenderName(senderName); + setDate(trophyDate); + setMessage(trophyText); + }); + + useFurniRemovedEvent(((objectId !== -1) && (category !== -1)), event => + { + if((event.id !== objectId) || (event.category !== category)) return; + + close(); + }); + + return { objectId, color, senderName, date, message, close }; +} + +export const useFurnitureTrophyWidget = useFurnitureTrophyWidgetState; diff --git a/src/hooks/rooms/widgets/index.ts b/src/hooks/rooms/widgets/index.ts index d70c93df..a93f3f57 100644 --- a/src/hooks/rooms/widgets/index.ts +++ b/src/hooks/rooms/widgets/index.ts @@ -1 +1,5 @@ +export * from './furniture'; export * from './useDoorbellWidget'; +export * from './useFriendRequestWidget'; +export * from './useFurniChooserWidget'; +export * from './useUserChooserWidget'; diff --git a/src/hooks/rooms/widgets/useFriendRequestWidget.ts b/src/hooks/rooms/widgets/useFriendRequestWidget.ts new file mode 100644 index 00000000..a57578d8 --- /dev/null +++ b/src/hooks/rooms/widgets/useFriendRequestWidget.ts @@ -0,0 +1,91 @@ +import { RoomObjectCategory, RoomObjectUserType } from '@nitrots/nitro-renderer'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { GetRoomSession, MessengerRequest, RoomWidgetUpdateRoomObjectEvent } from '../../../api'; +import { UseUiEvent } from '../../events'; +import { useFriends } from '../../friends'; + +const useFriendRequestWidgetState = () => +{ + const [ activeRequests, setActiveRequests ] = useState<{ roomIndex: number, request: MessengerRequest }[]>([]); + const [ dismissedRequestIds, setDismissedRequestIds ] = useState([]); + const { requests = [] } = useFriends(); + + const displayedRequests = useMemo(() => activeRequests.filter(request => (dismissedRequestIds.indexOf(request.request.requesterUserId) === -1)), [ activeRequests, dismissedRequestIds ]); + + const hideFriendRequest = (userId: number) => + { + setDismissedRequestIds(prevValue => + { + if(prevValue.indexOf(userId) >= 0) return prevValue; + + const newValue = [ ...prevValue ]; + + newValue.push(userId); + + return newValue; + }); + } + + const onRoomWidgetUpdateRoomObjectEvent = useCallback((event: RoomWidgetUpdateRoomObjectEvent) => + { + if(event.category !== RoomObjectCategory.UNIT) return; + + const userData = GetRoomSession().userDataManager.getUserDataByIndex(event.id); + + if(userData && (userData.type === RoomObjectUserType.getTypeNumber(RoomObjectUserType.USER))) + { + if(event.type === RoomWidgetUpdateRoomObjectEvent.USER_ADDED) + { + const request = requests.find(request => (request.requesterUserId === userData.webID)); + + if(!request || activeRequests.find(request => (request.request.requesterUserId === userData.webID))) return; + + const newValue = [ ...activeRequests ]; + + newValue.push({ roomIndex: userData.roomIndex, request }); + + setActiveRequests(newValue); + } + + return; + } + + if(event.type === RoomWidgetUpdateRoomObjectEvent.USER_REMOVED) + { + const index = activeRequests.findIndex(request => (request.roomIndex === event.id)); + + if(index === -1) return; + + const newValue = [ ...activeRequests ]; + + newValue.splice(index, 1); + + setActiveRequests(newValue); + } + }, [ requests, activeRequests ]); + + UseUiEvent(RoomWidgetUpdateRoomObjectEvent.USER_ADDED, onRoomWidgetUpdateRoomObjectEvent); + UseUiEvent(RoomWidgetUpdateRoomObjectEvent.USER_REMOVED, onRoomWidgetUpdateRoomObjectEvent); + + useEffect(() => + { + if(!requests || !requests.length) return; + + const newDisplayedRequests: { roomIndex: number, request: MessengerRequest }[] = []; + + for(const request of requests) + { + const userData = GetRoomSession().userDataManager.getUserData(request.requesterUserId); + + if(!userData) continue; + + newDisplayedRequests.push({ roomIndex: userData.roomIndex, request }); + } + + setActiveRequests(newDisplayedRequests); + }, [ requests ]); + + return { displayedRequests, hideFriendRequest }; +} + +export const useFriendRequestWidget = useFriendRequestWidgetState; diff --git a/src/hooks/rooms/widgets/useFurniChooserWidget.ts b/src/hooks/rooms/widgets/useFurniChooserWidget.ts new file mode 100644 index 00000000..4b3534ab --- /dev/null +++ b/src/hooks/rooms/widgets/useFurniChooserWidget.ts @@ -0,0 +1,163 @@ +import { RoomObjectCategory, RoomObjectVariable } from '@nitrots/nitro-renderer'; +import { useCallback, useEffect, useState } from 'react'; +import { GetRoomEngine, GetRoomSession, GetSessionDataManager, LocalizeText, RoomObjectItem, RoomWidgetUpdateRoomObjectEvent } from '../../../api'; +import { UI_EVENT_DISPATCHER } from '../../events'; + +const useFurniChooserWidgetState = () => +{ + const [ items, setItems ] = useState(null); + + const close = () => + { + setItems(null); + } + + const selectItem = (item: RoomObjectItem) => + { + if(!item) return; + + GetRoomEngine().selectRoomObject(GetRoomSession().roomId, item.id, item.category); + } + + const populateChooser = useCallback(() => + { + const roomSession = GetRoomSession(); + const sessionDataManager = GetSessionDataManager(); + const wallObjects = GetRoomEngine().getRoomObjects(roomSession.roomId, RoomObjectCategory.WALL); + const floorObjects = GetRoomEngine().getRoomObjects(roomSession.roomId, RoomObjectCategory.FLOOR); + + const wallItems = wallObjects.map(roomObject => + { + if(roomObject.id < 0) return null; + + let name = roomObject.type; + + if(name.startsWith('poster')) + { + name = LocalizeText(`poster_${ name.replace('poster', '') }_name`); + } + else + { + const typeId = roomObject.model.getValue(RoomObjectVariable.FURNITURE_TYPE_ID); + const furniData = sessionDataManager.getWallItemData(typeId); + + if(furniData && furniData.name.length) name = furniData.name; + } + + return new RoomObjectItem(roomObject.id, RoomObjectCategory.WALL, name); + }); + + const floorItems = floorObjects.map(roomObject => + { + if(roomObject.id < 0) return null; + + let name = roomObject.type; + + const typeId = roomObject.model.getValue(RoomObjectVariable.FURNITURE_TYPE_ID); + const furniData = sessionDataManager.getFloorItemData(typeId); + + if(furniData && furniData.name.length) name = furniData.name; + + return new RoomObjectItem(roomObject.id, RoomObjectCategory.FLOOR, name); + }); + + setItems([ ...wallItems, ...floorItems ].sort((a, b) => ((a.name < b.name) ? -1 : 1))); + }, []); + + useEffect(() => + { + if(!items) return; + + const onRoomWidgetUpdateRoomObjectEvent = (event: RoomWidgetUpdateRoomObjectEvent) => + { + if(event.id < 0) return; + + const roomObject = GetRoomEngine().getRoomObject(GetRoomSession().roomId, event.id, event.category); + + if(!roomObject) return; + + let item: RoomObjectItem = null; + + switch(event.category) + { + case RoomObjectCategory.WALL: { + let name = roomObject.type; + + if(name.startsWith('poster')) + { + name = LocalizeText(`poster_${ name.replace('poster', '') }_name`); + } + else + { + const typeId = roomObject.model.getValue(RoomObjectVariable.FURNITURE_TYPE_ID); + const furniData = GetSessionDataManager().getWallItemData(typeId); + + if(furniData && furniData.name.length) name = furniData.name; + } + + item = new RoomObjectItem(roomObject.id, RoomObjectCategory.WALL, name); + + break; + } + case RoomObjectCategory.FLOOR: { + let name = roomObject.type; + + const typeId = roomObject.model.getValue(RoomObjectVariable.FURNITURE_TYPE_ID); + const furniData = GetSessionDataManager().getFloorItemData(typeId); + + if(furniData && furniData.name.length) name = furniData.name; + + item = new RoomObjectItem(roomObject.id, RoomObjectCategory.FLOOR, name); + } + } + + setItems(prevValue => [ ...prevValue, item ].sort((a, b) => ((a.name < b.name) ? -1 : 1))); + } + + UI_EVENT_DISPATCHER.addEventListener(RoomWidgetUpdateRoomObjectEvent.FURNI_ADDED, onRoomWidgetUpdateRoomObjectEvent); + + return () => + { + UI_EVENT_DISPATCHER.removeEventListener(RoomWidgetUpdateRoomObjectEvent.FURNI_ADDED, onRoomWidgetUpdateRoomObjectEvent); + } + }, [ items ]); + + useEffect(() => + { + if(!items) return; + + const onRoomWidgetUpdateRoomObjectEvent = (event: RoomWidgetUpdateRoomObjectEvent) => + { + if(event.id < 0) return; + + setItems(prevValue => + { + const newValue = [ ...prevValue ]; + + for(let i = 0; i < newValue.length; i++) + { + const existingValue = newValue[i]; + + if((existingValue.id !== event.id) || (existingValue.category !== event.category)) continue; + + newValue.splice(i, 1); + + break; + } + + return newValue; + }); + } + + UI_EVENT_DISPATCHER.addEventListener(RoomWidgetUpdateRoomObjectEvent.FURNI_REMOVED, onRoomWidgetUpdateRoomObjectEvent); + + return () => + { + UI_EVENT_DISPATCHER.removeEventListener(RoomWidgetUpdateRoomObjectEvent.FURNI_REMOVED, onRoomWidgetUpdateRoomObjectEvent); + } + }, [ items ]); + + return { items, close, selectItem, populateChooser }; +} + +export const useFurniChooserWidget = useFurniChooserWidgetState; diff --git a/src/hooks/rooms/widgets/useUserChooserWidget.ts b/src/hooks/rooms/widgets/useUserChooserWidget.ts new file mode 100644 index 00000000..b6a979fe --- /dev/null +++ b/src/hooks/rooms/widgets/useUserChooserWidget.ts @@ -0,0 +1,112 @@ +import { RoomObjectCategory } from '@nitrots/nitro-renderer'; +import { useCallback, useEffect, useState } from 'react'; +import { GetRoomEngine, GetRoomSession, RoomObjectItem, RoomWidgetUpdateRoomObjectEvent } from '../../../api'; +import { UI_EVENT_DISPATCHER } from '../../events'; + +const useUserChooserWidgetState = () => +{ + const [ items, setItems ] = useState(null); + + const close = () => + { + setItems(null); + } + + const selectItem = (item: RoomObjectItem) => + { + if(!item) return; + + GetRoomEngine().selectRoomObject(GetRoomSession().roomId, item.id, item.category); + } + + const populateChooser = useCallback(() => + { + const roomSession = GetRoomSession(); + const roomObjects = GetRoomEngine().getRoomObjects(roomSession.roomId, RoomObjectCategory.UNIT); + + const newItems = roomObjects + .map(roomObject => + { + if(roomObject.id < 0) return null; + + const userData = roomSession.userDataManager.getUserDataByIndex(roomObject.id); + + if(!userData) return null; + + return new RoomObjectItem(userData.roomIndex, RoomObjectCategory.UNIT, userData.name); + }) + .sort((a, b) => ((a.name < b.name) ? -1 : 1)); + + setItems(newItems); + }, []); + + useEffect(() => + { + if(!items) return; + + const onRoomWidgetUpdateRoomObjectEvent = (event: RoomWidgetUpdateRoomObjectEvent) => + { + if(event.id < 0) return; + + const userData = GetRoomSession().userDataManager.getUserDataByIndex(event.id); + + if(!userData) return; + + setItems(prevValue => + { + const newValue = [ ...prevValue ]; + + newValue.push(new RoomObjectItem(userData.roomIndex, RoomObjectCategory.UNIT, userData.name)); + newValue.sort((a, b) => ((a.name < b.name) ? -1 : 1)); + + return newValue; + }); + } + + UI_EVENT_DISPATCHER.addEventListener(RoomWidgetUpdateRoomObjectEvent.USER_ADDED, onRoomWidgetUpdateRoomObjectEvent); + + return () => + { + UI_EVENT_DISPATCHER.removeEventListener(RoomWidgetUpdateRoomObjectEvent.USER_ADDED, onRoomWidgetUpdateRoomObjectEvent); + } + }, [ items ]); + + useEffect(() => + { + if(!items) return; + + const onRoomWidgetUpdateRoomObjectEvent = (event: RoomWidgetUpdateRoomObjectEvent) => + { + if(event.id < 0) return; + + setItems(prevValue => + { + const newValue = [ ...prevValue ]; + + for(let i = 0; i < newValue.length; i++) + { + const existingValue = newValue[i]; + + if((existingValue.id !== event.id) || (existingValue.category !== event.category)) continue; + + newValue.splice(i, 1); + + break; + } + + return newValue; + }); + } + + UI_EVENT_DISPATCHER.addEventListener(RoomWidgetUpdateRoomObjectEvent.USER_REMOVED, onRoomWidgetUpdateRoomObjectEvent); + + return () => + { + UI_EVENT_DISPATCHER.removeEventListener(RoomWidgetUpdateRoomObjectEvent.USER_REMOVED, onRoomWidgetUpdateRoomObjectEvent); + } + }, [ items ]); + + return { items, close, selectItem, populateChooser }; +} + +export const useUserChooserWidget = useUserChooserWidgetState;