diff --git a/src/events/inventory/InventoryEvent.ts b/src/events/inventory/InventoryEvent.ts index 453987b4..55ca046d 100644 --- a/src/events/inventory/InventoryEvent.ts +++ b/src/events/inventory/InventoryEvent.ts @@ -3,5 +3,6 @@ import { NitroEvent } from 'nitro-renderer'; export class InventoryEvent extends NitroEvent { public static SHOW_INVENTORY: string = 'IE_SHOW_INVENTORY'; + public static HIDE_INVENTORY: string = 'IE_HIDE_INVENTORY'; public static TOGGLE_INVENTORY: string = 'IE_TOGGLE_INVENTORY'; } diff --git a/src/hooks/Styles.scss b/src/hooks/Styles.scss new file mode 100644 index 00000000..4e8e0d96 --- /dev/null +++ b/src/hooks/Styles.scss @@ -0,0 +1 @@ +@import './draggable-window/DraggableWindow'; diff --git a/src/hooks/draggable-window/DraggableWindow.scss b/src/hooks/draggable-window/DraggableWindow.scss new file mode 100644 index 00000000..db44bd4a --- /dev/null +++ b/src/hooks/draggable-window/DraggableWindow.scss @@ -0,0 +1,6 @@ +.draggable-window { + + .drag-handler { + cursor: move; + } +} diff --git a/src/hooks/draggable-window/DraggableWindow.tsx b/src/hooks/draggable-window/DraggableWindow.tsx index 27d9da65..403af1bc 100644 --- a/src/hooks/draggable-window/DraggableWindow.tsx +++ b/src/hooks/draggable-window/DraggableWindow.tsx @@ -61,7 +61,7 @@ export function DraggableWindow(props: DraggableWindowProps): JSX.Element return ( -
+
{ props.children }
diff --git a/src/views/inventory/InventoryMessageHandler.tsx b/src/views/inventory/InventoryMessageHandler.tsx index c47cb395..b56fe53d 100644 --- a/src/views/inventory/InventoryMessageHandler.tsx +++ b/src/views/inventory/InventoryMessageHandler.tsx @@ -1,10 +1,103 @@ -import { FC } from 'react'; +import { FurnitureListAddOrUpdateEvent, FurnitureListEvent, FurnitureListInvalidateEvent, FurnitureListItemParser, FurnitureListRemovedEvent, FurniturePostItPlacedEvent } from 'nitro-renderer'; +import { FC, useCallback } from 'react'; +import { CreateMessageHook } from '../../hooks/messages/message-event'; import { InventoryMessageHandlerProps } from './InventoryMessageHandler.types'; +import { FurnitureItem } from './utils/FurnitureItem'; +import { addFurnitureItem, getGroupItemForFurnitureId, mergeFragments, processFragment, removeItemById } from './utils/FurnitureUtilities'; +let furniMsgFragments: Map[] = null; + export const InventoryMessageHandler: FC = props => { - return ( - <> - - ); + const { setNeedsFurniUpdate = null, setGroupItems = null } = props; + + const onFurnitureListAddOrUpdateEvent = useCallback((event: FurnitureListAddOrUpdateEvent) => + { + const parser = event.getParser(); + + setGroupItems(prevValue => + { + const newSet = [ ...prevValue ]; + + for(const item of parser.items) + { + const groupItem = getGroupItemForFurnitureId(newSet, item.itemId); + + if(groupItem) + { + const furniture = groupItem.getItemById(item.itemId); + + if(furniture) + { + furniture.update(item); + + groupItem.hasUnseenItems = true; + } + } + else + { + const furniture = new FurnitureItem(item); + + addFurnitureItem(newSet, furniture, false); + } + } + + return newSet; + }); + }, [ setGroupItems ]); + + const onFurnitureListEvent = useCallback((event: FurnitureListEvent) => + { + const parser = event.getParser(); + + if(!furniMsgFragments) furniMsgFragments = new Array(parser.totalFragments); + + const merged = mergeFragments(parser.fragment, parser.totalFragments, parser.fragmentNumber, furniMsgFragments); + + if(!merged) return; + + setGroupItems(prevValue => + { + return processFragment(prevValue, merged); + }); + }, [ setGroupItems ]); + + const onFurnitureListInvalidateEvent = useCallback((event: FurnitureListInvalidateEvent) => + { + setNeedsFurniUpdate(true); + }, [ setNeedsFurniUpdate ]); + + const onFurnitureListRemovedEvent = useCallback((event: FurnitureListRemovedEvent) => + { + const parser = event.getParser(); + + setGroupItems(prevValue => + { + const newSet = [ ...prevValue ]; + + const groupItem = removeItemById(parser.itemId, newSet); + + if(groupItem) + { + // set all seen + + return newSet; + } + + return prevValue; + }); + }, [ setGroupItems ]); + + const onFurniturePostItPlacedEvent = useCallback((event: FurniturePostItPlacedEvent) => + { + + }, []); + + CreateMessageHook(FurnitureListAddOrUpdateEvent, onFurnitureListAddOrUpdateEvent); + CreateMessageHook(FurnitureListEvent, onFurnitureListEvent); + CreateMessageHook(FurnitureListInvalidateEvent, onFurnitureListInvalidateEvent); + CreateMessageHook(FurnitureListRemovedEvent, onFurnitureListRemovedEvent); + CreateMessageHook(FurniturePostItPlacedEvent, onFurniturePostItPlacedEvent); + + return null; } diff --git a/src/views/inventory/InventoryMessageHandler.types.ts b/src/views/inventory/InventoryMessageHandler.types.ts index 098d4e0c..4b091bd8 100644 --- a/src/views/inventory/InventoryMessageHandler.types.ts +++ b/src/views/inventory/InventoryMessageHandler.types.ts @@ -1,4 +1,8 @@ +import { Dispatch, SetStateAction } from 'react'; +import { GroupItem } from './utils/GroupItem'; + export interface InventoryMessageHandlerProps { - + setNeedsFurniUpdate: Dispatch>; + setGroupItems: Dispatch>; } diff --git a/src/views/inventory/InventoryView.scss b/src/views/inventory/InventoryView.scss index 20970d53..22e4add7 100644 --- a/src/views/inventory/InventoryView.scss +++ b/src/views/inventory/InventoryView.scss @@ -1,3 +1,7 @@ .nitro-inventory { - width: 450px; + width: 475px; + height: 300px; + max-height: 300px; } + +@import './views/InventoryViews'; diff --git a/src/views/inventory/InventoryView.tsx b/src/views/inventory/InventoryView.tsx index fcbc191c..2855d60a 100644 --- a/src/views/inventory/InventoryView.tsx +++ b/src/views/inventory/InventoryView.tsx @@ -1,15 +1,16 @@ -import { RoomSessionEvent } from 'nitro-renderer'; -import { FC, useCallback, useState } from 'react'; +import classNames from 'classnames'; +import { IRoomSession, RoomPreviewer, RoomSessionEvent } from 'nitro-renderer'; +import { FC, useCallback, useEffect, useState } from 'react'; +import { GetRoomEngine } from '../../api'; import { InventoryEvent } from '../../events'; import { DraggableWindow } from '../../hooks/draggable-window/DraggableWindow'; import { useRoomSessionManagerEvent } from '../../hooks/events/nitro/session/room-session-manager-event'; import { useUiEvent } from '../../hooks/events/ui/ui-event'; import { LocalizeText } from '../../utils/LocalizeText'; -import { InventoryContextProvider } from './context/InventoryContext'; import { InventoryMessageHandler } from './InventoryMessageHandler'; import { InventoryTabs, InventoryViewProps } from './InventoryView.types'; -import { InventoryTabsContentView } from './tabs-content/InventoryTabsContentView'; -import { InventoryTabsSelectorView } from './tabs-selector/InventoryTabsSelectorView'; +import { GroupItem } from './utils/GroupItem'; +import { InventoryFurnitureView } from './views/furniture/InventoryFurnitureView'; export const InventoryView: FC = props => { @@ -18,6 +19,12 @@ export const InventoryView: FC = props => const [ isVisible, setIsVisible ] = useState(false); const [ currentTab, setCurrentTab ] = useState(tabs[0]); + const [ roomSession, setRoomSession ] = useState(null); + const [ needsFurniUpdate, setNeedsFurniUpdate ] = useState(true); + const [ groupItem, setGroupItem ] = useState(null); + const [ groupItems, setGroupItems ] = useState([]); + const [ roomPreviewer, setRoomPreviewer ] = useState(null); + const onInventoryEvent = useCallback((event: InventoryEvent) => { switch(event.type) @@ -25,6 +32,9 @@ export const InventoryView: FC = props => case InventoryEvent.SHOW_INVENTORY: setIsVisible(true); return; + case InventoryEvent.HIDE_INVENTORY: + setIsVisible(false); + return; case InventoryEvent.TOGGLE_INVENTORY: setIsVisible(value => !value); return; @@ -32,6 +42,7 @@ export const InventoryView: FC = props => }, []); useUiEvent(InventoryEvent.SHOW_INVENTORY, onInventoryEvent); + useUiEvent(InventoryEvent.HIDE_INVENTORY, onInventoryEvent); useUiEvent(InventoryEvent.TOGGLE_INVENTORY, onInventoryEvent); const onRoomSessionEvent = useCallback((event: RoomSessionEvent) => @@ -39,9 +50,10 @@ export const InventoryView: FC = props => switch(event.type) { case RoomSessionEvent.CREATED: - // + setRoomSession(event.session); return; case RoomSessionEvent.ENDED: + setRoomSession(null); setIsVisible(false); return; } @@ -50,26 +62,61 @@ export const InventoryView: FC = props => useRoomSessionManagerEvent(RoomSessionEvent.CREATED, onRoomSessionEvent); useRoomSessionManagerEvent(RoomSessionEvent.ENDED, onRoomSessionEvent); + useEffect(() => + { + setRoomPreviewer(new RoomPreviewer(GetRoomEngine(), ++RoomPreviewer.PREVIEW_COUNTER)); + + return () => + { + setRoomPreviewer(prevValue => + { + prevValue.dispose(); + + return null; + }); + } + }, []); + function hideInventory(): void { setIsVisible(false); } return ( - - + <> + { isVisible && -
-
-
{ LocalizeText('inventory.title') }
- +
+
+
    + { tabs.map((name, index) => + { + return
  • setCurrentTab(name) } > + { LocalizeText(name) } +
  • ; + }) } +
+
+ { (currentTab === InventoryTabs.FURNITURE ) && }
- -
} - + ); } diff --git a/src/views/inventory/context/InventoryContext.tsx b/src/views/inventory/context/InventoryContext.tsx index 3029af8f..9708b887 100644 --- a/src/views/inventory/context/InventoryContext.tsx +++ b/src/views/inventory/context/InventoryContext.tsx @@ -3,7 +3,7 @@ import { IInventoryContext, InventoryContextProps } from './InventoryContext.typ const InventoryContext = createContext({ currentTab: null, - setCurrentTab: null + setCurrentTab: null, }); export const InventoryContextProvider: FC = props => diff --git a/src/views/inventory/context/furniture/InventoryFurnitureContext.tsx b/src/views/inventory/context/furniture/InventoryFurnitureContext.tsx new file mode 100644 index 00000000..9f13c5f5 --- /dev/null +++ b/src/views/inventory/context/furniture/InventoryFurnitureContext.tsx @@ -0,0 +1,14 @@ +import { createContext, FC, useContext } from 'react'; +import { IInventoryFurnitureContext, InventoryFurnitureContextProps } from './InventoryFurnitureContext.types'; + +const InventoryFurnitureContext = createContext({ + setNeedsUpdate: null, + setGroupItems: null +}); + +export const InventoryFurnitureContextProvider: FC = props => +{ + return { props.children } +} + +export const useInventoryFurnitureContext = () => useContext(InventoryFurnitureContext); diff --git a/src/views/inventory/context/furniture/InventoryFurnitureContext.types.ts b/src/views/inventory/context/furniture/InventoryFurnitureContext.types.ts new file mode 100644 index 00000000..ca44e87f --- /dev/null +++ b/src/views/inventory/context/furniture/InventoryFurnitureContext.types.ts @@ -0,0 +1,13 @@ +import { Dispatch, ProviderProps, SetStateAction } from 'react'; +import { GroupItem } from '../../utils/GroupItem'; + +export interface IInventoryFurnitureContext +{ + setNeedsUpdate: Dispatch>; + setGroupItems: Dispatch>; +} + +export interface InventoryFurnitureContextProps extends ProviderProps +{ + +} diff --git a/src/views/inventory/tabs-content/InventoryTabsContentView.tsx b/src/views/inventory/tabs-content/InventoryTabsContentView.tsx deleted file mode 100644 index cb17071c..00000000 --- a/src/views/inventory/tabs-content/InventoryTabsContentView.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { FC } from 'react'; -import { useInventoryContext } from '../context/InventoryContext'; -import { InventoryTabs } from '../InventoryView.types'; -import { InventoryTabBadgesView } from './badges/InventoryTabBadgesView'; -import { InventoryTabBotsView } from './bots/InventoryTabBotsView'; -import { InventoryTabFurnitureView } from './furniture/InventoryTabFurnitureView'; -import { InventoryTabsContentViewProps } from './InventoryTabsContentView.types'; -import { InventoryTabPetsView } from './pets/InventoryTabPetsView'; - -export const InventoryTabsContentView: FC = props => -{ - const inventoryContext = useInventoryContext(); - - function renderCurrentTab(): JSX.Element - { - switch(inventoryContext.currentTab) - { - case InventoryTabs.FURNITURE: - return - case InventoryTabs.BOTS: - return - case InventoryTabs.PETS: - return - case InventoryTabs.BADGES: - return - } - - return null; - } - - return ( -
- { inventoryContext && inventoryContext.currentTab && renderCurrentTab() } -
- ); -} diff --git a/src/views/inventory/tabs-content/InventoryTabsContentView.types.ts b/src/views/inventory/tabs-content/InventoryTabsContentView.types.ts deleted file mode 100644 index 691c0edb..00000000 --- a/src/views/inventory/tabs-content/InventoryTabsContentView.types.ts +++ /dev/null @@ -1,2 +0,0 @@ -export interface InventoryTabsContentViewProps -{} diff --git a/src/views/inventory/tabs-content/badges/InventoryTabBadgesView.tsx b/src/views/inventory/tabs-content/badges/InventoryTabBadgesView.tsx deleted file mode 100644 index 7d2043fa..00000000 --- a/src/views/inventory/tabs-content/badges/InventoryTabBadgesView.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { FC } from 'react'; -import { useInventoryContext } from '../../context/InventoryContext'; -import { InventoryTabBadgesViewProps } from './InventoryTabBadgesView.types'; - -export const InventoryTabBadgesView: FC = props => -{ - const inventoryContext = useInventoryContext(); - - return ( - <>Badges content - ); -} diff --git a/src/views/inventory/tabs-content/badges/InventoryTabBadgesView.types.ts b/src/views/inventory/tabs-content/badges/InventoryTabBadgesView.types.ts deleted file mode 100644 index 8e739238..00000000 --- a/src/views/inventory/tabs-content/badges/InventoryTabBadgesView.types.ts +++ /dev/null @@ -1,2 +0,0 @@ -export interface InventoryTabBadgesViewProps -{} diff --git a/src/views/inventory/tabs-content/bots/InventoryTabBotsView.tsx b/src/views/inventory/tabs-content/bots/InventoryTabBotsView.tsx deleted file mode 100644 index bf45307c..00000000 --- a/src/views/inventory/tabs-content/bots/InventoryTabBotsView.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { FC } from 'react'; -import { useInventoryContext } from '../../context/InventoryContext'; -import { InventoryTabBotsViewProps } from './InventoryTabBotsView.types'; - -export const InventoryTabBotsView: FC = props => -{ - const inventoryContext = useInventoryContext(); - - return ( - <>Bots content - ); -} diff --git a/src/views/inventory/tabs-content/bots/InventoryTabBotsView.types.ts b/src/views/inventory/tabs-content/bots/InventoryTabBotsView.types.ts deleted file mode 100644 index 38892a21..00000000 --- a/src/views/inventory/tabs-content/bots/InventoryTabBotsView.types.ts +++ /dev/null @@ -1,2 +0,0 @@ -export interface InventoryTabBotsViewProps -{} diff --git a/src/views/inventory/tabs-content/furniture/InventoryTabFurnitureView.tsx b/src/views/inventory/tabs-content/furniture/InventoryTabFurnitureView.tsx deleted file mode 100644 index f082fff9..00000000 --- a/src/views/inventory/tabs-content/furniture/InventoryTabFurnitureView.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { FC } from 'react'; -import { useInventoryContext } from '../../context/InventoryContext'; -import { InventoryTabFurnitureViewProps } from './InventoryTabFurnitureView.types'; - -export const InventoryTabFurnitureView: FC = props => -{ - const inventoryContext = useInventoryContext(); - - return ( - <>Furniture content - ); -} diff --git a/src/views/inventory/tabs-content/furniture/InventoryTabFurnitureView.types.ts b/src/views/inventory/tabs-content/furniture/InventoryTabFurnitureView.types.ts deleted file mode 100644 index e17988c4..00000000 --- a/src/views/inventory/tabs-content/furniture/InventoryTabFurnitureView.types.ts +++ /dev/null @@ -1,2 +0,0 @@ -export interface InventoryTabFurnitureViewProps -{} diff --git a/src/views/inventory/tabs-content/pets/InventoryTabPetsView.tsx b/src/views/inventory/tabs-content/pets/InventoryTabPetsView.tsx deleted file mode 100644 index 3b91428b..00000000 --- a/src/views/inventory/tabs-content/pets/InventoryTabPetsView.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { FC } from 'react'; -import { useInventoryContext } from '../../context/InventoryContext'; -import { InventoryTabPetsViewProps } from './InventoryTabPetsView.types'; - -export const InventoryTabPetsView: FC = props => -{ - const inventoryContext = useInventoryContext(); - - return ( - <>Pets content - ); -} diff --git a/src/views/inventory/tabs-content/pets/InventoryTabPetsView.types.ts b/src/views/inventory/tabs-content/pets/InventoryTabPetsView.types.ts deleted file mode 100644 index 94be286b..00000000 --- a/src/views/inventory/tabs-content/pets/InventoryTabPetsView.types.ts +++ /dev/null @@ -1,2 +0,0 @@ -export interface InventoryTabPetsViewProps -{} diff --git a/src/views/inventory/tabs-selector/InventoryTabsSelectorView.tsx b/src/views/inventory/tabs-selector/InventoryTabsSelectorView.tsx deleted file mode 100644 index bb04ff7b..00000000 --- a/src/views/inventory/tabs-selector/InventoryTabsSelectorView.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { FC } from 'react'; -import { InventoryTabsSelectorViewProps } from './InventoryTabsSelectorView.types'; -import { InventoryTabView } from './tab/InventoryTabView'; - -export const InventoryTabsSelectorView: FC = props => -{ - const { tabs = null } = props; - - return ( -
- { tabs && tabs.length && -
- { props.tabs.map((tab, index) => - { - return - }) } -
} -
- ); -} diff --git a/src/views/inventory/tabs-selector/InventoryTabsSelectorView.types.ts b/src/views/inventory/tabs-selector/InventoryTabsSelectorView.types.ts deleted file mode 100644 index a5883422..00000000 --- a/src/views/inventory/tabs-selector/InventoryTabsSelectorView.types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface InventoryTabsSelectorViewProps -{ - tabs: string[]; -} diff --git a/src/views/inventory/tabs-selector/tab/InventoryTabView.tsx b/src/views/inventory/tabs-selector/tab/InventoryTabView.tsx deleted file mode 100644 index 11cb248c..00000000 --- a/src/views/inventory/tabs-selector/tab/InventoryTabView.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import classNames from 'classnames'; -import { FC, MouseEvent } from 'react'; -import { LocalizeText } from '../../../../utils/LocalizeText'; -import { useInventoryContext } from '../../context/InventoryContext'; -import { InventoryTabViewProps } from './InventoryTabView.types'; - -export const InventoryTabView: FC = props => -{ - const { tab = null } = props; - - const inventoryContext = useInventoryContext(); - - function selectTab(event: MouseEvent = null): void - { - inventoryContext.setCurrentTab(tab); - } - - if(!tab) return null; - - return ; -} diff --git a/src/views/inventory/tabs-selector/tab/InventoryTabView.types.ts b/src/views/inventory/tabs-selector/tab/InventoryTabView.types.ts deleted file mode 100644 index d8cdf704..00000000 --- a/src/views/inventory/tabs-selector/tab/InventoryTabView.types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface InventoryTabViewProps -{ - tab: string; -} diff --git a/src/views/inventory/utils/FurniCategory.ts b/src/views/inventory/utils/FurniCategory.ts new file mode 100644 index 00000000..7344af9e --- /dev/null +++ b/src/views/inventory/utils/FurniCategory.ts @@ -0,0 +1,26 @@ +export class FurniCategory +{ + public static DEFAULT: number = 1; + public static _Str_3639: number = 2; + public static _Str_3683: number = 3; + public static _Str_3432: number = 4; + public static _Str_12351: number = 5; + public static _Str_5186: number = 6; + public static _Str_21911: number = 7; + public static _Str_9125: number = 8; + public static _Str_5922: number = 9; + public static _Str_18231: number = 10; + public static _Str_4255: number = 11; + public static _Str_19933: number = 12; + public static _Str_7696: number = 13; + public static _Str_7297: number = 14; + public static _Str_7954: number = 15; + public static _Str_6096: number = 16; + public static _Str_12454: number = 17; + public static _Str_19144: number = 18; + public static MONSTERPLANT_SEED: number = 19; + public static _Str_6915: number = 20; + public static _Str_8726: number = 21; + public static _Str_9449: number = 22; + public static _Str_12534: number = 23; +} \ No newline at end of file diff --git a/src/views/inventory/utils/FurnitureItem.ts b/src/views/inventory/utils/FurnitureItem.ts new file mode 100644 index 00000000..621cb16e --- /dev/null +++ b/src/views/inventory/utils/FurnitureItem.ts @@ -0,0 +1,243 @@ +import { IFurnitureItemData, IObjectData, Nitro } from 'nitro-renderer'; +import { IFurnitureItem } from './IFurnitureItem'; + +export class FurnitureItem implements IFurnitureItem +{ + private _expirationTimeStamp: number; + private _isWallItem: boolean; + private _songId: number; + private _locked: boolean; + private _id: number; + private _ref: number; + private _category: number; + private _type: number; + private _stuffData: IObjectData; + private _extra: number; + private _recyclable: boolean; + private _tradeable: boolean; + private _groupable: boolean; + private _sellable: boolean; + private _secondsToExpiration: number; + private _hasRentPeriodStarted: boolean; + private _creationDay: number; + private _creationMonth: number; + private _creationYear: number; + private _slotId: string; + private _isRented: boolean; + private _flatId: number; + + constructor(parser: IFurnitureItemData) + { + this._locked = false; + this._id = parser.itemId; + this._type = parser.spriteId; + this._ref = parser.ref; + this._category = parser.category; + this._groupable = ((parser.isGroupable) && (!(parser.rentable))); + this._tradeable = parser.tradable; + this._recyclable = parser.isRecycleable; + this._sellable = parser.sellable; + this._stuffData = parser.stuffData; + this._extra = parser._Str_2794; + this._secondsToExpiration = parser.secondsToExpiration; + this._expirationTimeStamp = parser._Str_10616; + this._hasRentPeriodStarted = parser.hasRentPeriodStarted; + this._creationDay = parser._Str_8932; + this._creationMonth = parser._Str_9050; + this._creationYear = parser._Str_9408; + this._slotId = parser.slotId; + this._songId = parser._Str_3951; + this._flatId = parser.flatId; + this._isRented = parser.rentable; + this._isWallItem = parser.isWallItem; + } + + public get rentable(): boolean + { + return this._isRented; + } + + public get id(): number + { + return this._id; + } + + public get ref(): number + { + return this._ref; + } + + public get category(): number + { + return this._category; + } + + public get type(): number + { + return this._type; + } + + public get stuffData(): IObjectData + { + return this._stuffData; + } + + public set stuffData(k: IObjectData) + { + this._stuffData = k; + } + + public get extra(): number + { + return this._extra; + } + + public get _Str_16260(): boolean + { + return this._recyclable; + } + + public get isTradable(): boolean + { + return this._tradeable; + } + + public get isGroupable(): boolean + { + return this._groupable; + } + + public get sellable(): boolean + { + return this._sellable; + } + + public get secondsToExpiration(): number + { + if(this._secondsToExpiration === -1) return -1; + + let time = -1; + + if(this._hasRentPeriodStarted) + { + time = (this._secondsToExpiration - ((Nitro.instance.time - this._expirationTimeStamp) / 1000)); + + if(time < 0) time = 0; + } + else + { + time = this._secondsToExpiration; + } + + return time; + } + + public get _Str_8932(): number + { + return this._creationDay; + } + + public get _Str_9050(): number + { + return this._creationMonth; + } + + public get _Str_9408(): number + { + return this._creationYear; + } + + public get slotId(): string + { + return this._slotId; + } + + public get _Str_3951(): number + { + return this._songId; + } + + public get locked(): boolean + { + return this._locked; + } + + public set locked(k: boolean) + { + this._locked = k; + } + + public get flatId(): number + { + return this._flatId; + } + + public get isWallItem(): boolean + { + return this._isWallItem; + } + + public get hasRentPeriodStarted(): boolean + { + return this._hasRentPeriodStarted; + } + + public get _Str_10616(): number + { + return this._expirationTimeStamp; + } + + public update(parser: IFurnitureItemData): void + { + this._type = parser.spriteId; + this._ref = parser.ref; + this._category = parser.category; + this._groupable = (parser.isGroupable && !parser.rentable); + this._tradeable = parser.tradable; + this._recyclable = parser.isRecycleable; + this._sellable = parser.sellable; + this._stuffData = parser.stuffData; + this._extra = parser._Str_2794; + this._secondsToExpiration = parser.secondsToExpiration; + this._expirationTimeStamp = parser._Str_10616; + this._hasRentPeriodStarted = parser.hasRentPeriodStarted; + this._creationDay = parser._Str_8932; + this._creationMonth = parser._Str_9050; + this._creationYear = parser._Str_9408; + this._slotId = parser.slotId; + this._songId = parser._Str_3951; + this._flatId = parser.flatId; + this._isRented = parser.rentable; + this._isWallItem = parser.isWallItem; + } + + public clone(): FurnitureItem + { + const item = new FurnitureItem(null); + + item._expirationTimeStamp = this._expirationTimeStamp; + item._isWallItem = this._isWallItem; + item._songId = this._songId; + item._locked = this._locked; + item._id = this._id; + item._ref = this._ref; + item._category = this._category; + item._type = this._type; + item._stuffData = this._stuffData; + item._extra = this._extra; + item._recyclable = this._recyclable; + item._tradeable = this._tradeable; + item._groupable = this._groupable; + item._sellable = this._sellable; + item._secondsToExpiration = this._secondsToExpiration; + item._hasRentPeriodStarted = this._hasRentPeriodStarted; + item._creationDay = this._creationDay; + item._creationMonth = this._creationMonth; + item._creationYear = this._creationYear; + item._slotId = this._slotId; + item._isRented = this._isRented; + item._flatId = this._flatId; + + return item; + } +} diff --git a/src/views/inventory/utils/FurnitureUtilities.ts b/src/views/inventory/utils/FurnitureUtilities.ts new file mode 100644 index 00000000..06ed4ba6 --- /dev/null +++ b/src/views/inventory/utils/FurnitureUtilities.ts @@ -0,0 +1,369 @@ +import { FurnitureListItemParser, FurniturePlacePaintComposer, IObjectData, RoomObjectCategory, RoomObjectPlacementSource } from 'nitro-renderer'; +import { GetRoomEngine } from '../../../api'; +import { InventoryEvent } from '../../../events'; +import { dispatchUiEvent } from '../../../hooks/events/ui/ui-event'; +import { SendMessageHook } from '../../../hooks/messages/message-event'; +import { FurniCategory } from './FurniCategory'; +import { FurnitureItem } from './FurnitureItem'; +import { GroupItem } from './GroupItem'; + +let objectMoverRequested = false; +let itemIdInFurniPlacing = -1; + +export function isObjectMoverRequested(): boolean +{ + return objectMoverRequested; +} + +export function setObjectMoverRequested(flag: boolean) +{ + objectMoverRequested = flag; +} + +export function getPlacingFurnitureId(): number +{ + return itemIdInFurniPlacing; +} + +export function setPlacingFurnitureId(id: number) +{ + itemIdInFurniPlacing = id; +} + +export function attemptItemPlacement(groupItem: GroupItem, flag: boolean = false): boolean +{ + if(!groupItem || !groupItem.getUnlockedCount()) return false; + + const item = groupItem.getLastItem(); + + if(!item) return false; + + if((item.category === FurniCategory._Str_3683) || (item.category === FurniCategory._Str_3639) || (item.category === FurniCategory._Str_3432)) + { + if(flag) return false; + + SendMessageHook(new FurniturePlacePaintComposer(item.id)); + + return false; + } + else + { + dispatchUiEvent(new InventoryEvent(InventoryEvent.HIDE_INVENTORY)); + + let category = 0; + let isMoving = false; + + if(item.isWallItem) category = RoomObjectCategory.WALL; + else category = RoomObjectCategory.FLOOR; + + if((item.category === FurniCategory._Str_5186)) // or external image from furnidata + { + isMoving = GetRoomEngine().processRoomObjectPlacement(RoomObjectPlacementSource.INVENTORY, item.id, category, item.type, item.stuffData.getLegacyString()); + } + else + { + isMoving = GetRoomEngine().processRoomObjectPlacement(RoomObjectPlacementSource.INVENTORY, item.id, category, item.type, item.extra.toString(), item.stuffData); + } + + if(isMoving) + { + setPlacingFurnitureId(item.ref); + setObjectMoverRequested(true); + } + } + + return true; +} + +function cancelRoomObjectPlacement(): void +{ + if(getPlacingFurnitureId() === -1) return; + + GetRoomEngine().cancelRoomObjectPlacement(); + + setPlacingFurnitureId(-1); + setObjectMoverRequested(false); +} + +export function getGroupItemForFurnitureId(set: GroupItem[], id: number): GroupItem +{ + for(const groupItem of set) + { + if(groupItem.getItemById(id)) return groupItem; + } + + return null; +} + +export function mergeFragments(fragment: Map, totalFragments: number, fragmentNumber: number, fragments: Map[]) +{ + if(totalFragments === 1) return fragment; + + fragments[fragmentNumber] = fragment; + + for(const frag of fragments) + { + if(!frag) return null; + } + + const merged: Map = new Map(); + + for(const frag of fragments) + { + for(const [ key, value ] of frag) merged.set(key, value); + + frag.clear(); + } + + fragments = null; + + return merged; +} + +export function getAllItemIds(groupItems: GroupItem[]): number[] +{ + const itemIds: number[] = []; + + for(const groupItem of groupItems) + { + let totalCount = groupItem.getTotalCount(); + + if(groupItem.category === FurniCategory._Str_12351) totalCount = 1; + + let i = 0; + + while(i < totalCount) + { + itemIds.push(groupItem.getItemByIndex(i).id); + + i++; + } + } + + return itemIds; +} + +export function processFragment(set: GroupItem[], fragment: Map): GroupItem[] +{ + const existingIds = getAllItemIds(set); + const addedIds: number[] = []; + const removedIds: number[] = []; + + for(const key of fragment.keys()) (existingIds.indexOf(key) === -1) && addedIds.push(key); + + for(const itemId of existingIds) (!fragment.get(itemId)) && removedIds.push(itemId); + + const emptyExistingSet = (existingIds.length === 0); + + const newSet = [ ...set ]; + + for(const id of removedIds) removeItemById(id, newSet); + + for(const id of addedIds) + { + const parser = fragment.get(id); + + if(!parser) continue; + + const item = new FurnitureItem(parser); + + addFurnitureItem(newSet, item, true); + } + + return newSet; +} + +export function removeItemById(id: number, set: GroupItem[]): GroupItem +{ + let index = 0; + + while(index < set.length) + { + const group = set[index]; + const item = group.remove(id); + + if(item) + { + if(getPlacingFurnitureId() === item.ref) + { + cancelRoomObjectPlacement(); + + if(!attemptItemPlacement(group)) + { + setTimeout(() => dispatchUiEvent(new InventoryEvent(InventoryEvent.SHOW_INVENTORY)), 1); + } + } + + if(group.getTotalCount() <= 0) + { + set.splice(index, 1); + + group.dispose(); + } + + return group; + } + + index++; + } + + return null; +} + +export function addFurnitureItem(set: GroupItem[], item: FurnitureItem, flag: boolean): void +{ + let groupItem: GroupItem = null; + + if(!item.isGroupable) + { + groupItem = addSingleFurnitureItem(set, item, flag); + } + else + { + groupItem = addGroupableFurnitureItem(set, item, flag); + } + + if(!flag) groupItem.hasUnseenItems = true; +} + +export function addSingleFurnitureItem(set: GroupItem[], item: FurnitureItem, flag: boolean): GroupItem +{ + const groupItems: GroupItem[] = []; + + for(const groupItem of set) + { + if(groupItem.type === item.type) groupItems.push(groupItem); + } + + for(const groupItem of groupItems) + { + if(groupItem.getItemById(item.id)) return groupItem; + } + + const unseen = flag; //this.isFurnitureUnseen(item); + const groupItem = createGroupItem(item.type, item.category, item.stuffData, item.extra, unseen); + + groupItem.push(item, unseen); + + if(unseen) + { + groupItem.hasUnseenItems = true; + + set.unshift(groupItem); + } + else + { + set.push(groupItem); + } + + return groupItem; +} + +export function addGroupableFurnitureItem(set: GroupItem[], item: FurnitureItem, unseen: boolean): GroupItem +{ + let existingGroup: GroupItem = null; + + for(const groupItem of set) + { + if((groupItem.type === item.type) && (groupItem.isWallItem === item.isWallItem) && groupItem.isGroupable) + { + if(item.category === FurniCategory._Str_5186) + { + if(groupItem.stuffData.getLegacyString() === item.stuffData.getLegacyString()) + { + existingGroup = groupItem; + + break; + } + } + + else if(item.category === FurniCategory._Str_12454) + { + if(item.stuffData.compare(groupItem.stuffData)) + { + existingGroup = groupItem; + + break; + } + } + + else + { + existingGroup = groupItem; + + break; + } + } + } + + // unseen = unseen; //this.isFurnitureUnseen(item); + + if(existingGroup) + { + existingGroup.push(item, unseen); + + if(unseen) + { + existingGroup.hasUnseenItems = true; + + const index = set.indexOf(existingGroup); + + if(index >= 0) set.splice(index, 1); + + set.unshift(existingGroup); + } + + return existingGroup; + } + + existingGroup = createGroupItem(item.type, item.category, item.stuffData, item.extra, unseen); + + existingGroup.push(item, unseen); + + if(unseen) + { + existingGroup.hasUnseenItems = true; + + set.unshift(existingGroup); + } + else + { + set.push(existingGroup); + } + + return existingGroup; +} + +export function createGroupItem(type: number, category: number, stuffData: IObjectData, extra: number = NaN, flag: boolean = false): GroupItem +{ + // const iconImage: HTMLImageElement = null; + + if(category === FurniCategory._Str_3639) + { + // const icon = this._windowManager.assets.getAssetByName("inventory_furni_icon_wallpaper"); + // if (icon != null) + // { + // iconImage = (icon.content as BitmapData).clone(); + // } + } + + else if(category === FurniCategory._Str_3683) + { + // const icon = this._windowManager.assets.getAssetByName("inventory_furni_icon_floor"); + // if (icon != null) + // { + // iconImage = (icon.content as BitmapData).clone(); + // } + } + + else if(category === FurniCategory._Str_3432) + { + // const icon = this._windowManager.assets.getAssetByName("inventory_furni_icon_landscape"); + // if (icon != null) + // { + // iconImage = (icon.content as BitmapData).clone(); + // } + } + + return new GroupItem(type, category, GetRoomEngine(), stuffData, extra); +} diff --git a/src/views/inventory/utils/GroupItem.ts b/src/views/inventory/utils/GroupItem.ts new file mode 100644 index 00000000..a22edd46 --- /dev/null +++ b/src/views/inventory/utils/GroupItem.ts @@ -0,0 +1,423 @@ +import { IObjectData, IRoomEngine } from 'nitro-renderer'; +import { LocalizeText } from '../../../utils/LocalizeText'; +import { FurniCategory } from './FurniCategory'; +import { FurnitureItem } from './FurnitureItem'; +import { IFurnitureItem } from './IFurnitureItem'; + +export class GroupItem +{ + private _type: number; + private _category: number; + private _roomEngine: IRoomEngine; + private _stuffData: IObjectData; + private _extra: number; + private _isWallItem: boolean; + private _iconUrl: string; + private _name: string; + private _description: string; + private _locked: boolean; + private _selected: boolean; + private _hasUnseenItems: boolean; + private _items: FurnitureItem[]; + + constructor(type: number, category: number, roomEngine: IRoomEngine, stuffData: IObjectData, extra: number) + { + this._type = type; + this._category = category; + this._roomEngine = roomEngine; + this._stuffData = stuffData; + this._extra = extra; + this._isWallItem = false; + this._iconUrl = null; + this._name = null; + this._description = null; + this._locked = false; + this._selected = false; + this._hasUnseenItems = false; + this._items = []; + } + + public prepareGroup(): void + { + this.setIcon(); + this.setName(); + this.setDescription(); + } + + public dispose(): void + { + + } + + public getItemByIndex(index: number): FurnitureItem + { + return this._items[index]; + } + + public getItemById(id: number): FurnitureItem + { + for(const item of this._items) + { + if(item.id !== id) continue; + + return item; + } + + return null; + } + + public getTradeItems(count: number): IFurnitureItem[] + { + const items: IFurnitureItem[] = []; + + const furnitureItem = this.getLastItem(); + + if(!furnitureItem) return items; + + let found = 0; + let i = 0; + + while(i < this._items.length) + { + if(found >= count) break; + + const item = this.getItemByIndex(i); + + if(!item.locked && item.isTradable && (item.type === furnitureItem.type)) + { + items.push(item); + + found++; + } + + i++; + } + + return items; + } + + public push(item: FurnitureItem, unseen: boolean = false): void + { + const items = [ ...this._items ]; + + let index = 0; + + while(index < items.length) + { + let existingItem = items[index]; + + if(existingItem.id === item.id) + { + existingItem = existingItem.clone(); + + existingItem.locked = false; + + items.splice(index, 1); + + items.push(existingItem); + + this._items = items; + + return; + } + + index++; + } + + items.push(item); + + this._items = items; + + if(this._items.length === 1) this.prepareGroup(); + } + + public pop(): FurnitureItem + { + const items = [ ...this._items ]; + + let item: FurnitureItem = null; + + if(items.length > 0) + { + const index = (items.length - 1); + + item = items[index]; + + items.splice(index, 1); + } + + this._items = items; + + return item; + } + + public remove(k: number): FurnitureItem + { + const items = [ ...this._items ]; + + let index = 0; + + while(index < items.length) + { + let existingItem = items[index]; + + if(existingItem.id === k) + { + items.splice(index, 1); + + this._items = items; + + return existingItem; + } + + index++; + } + + return null; + } + + public getTotalCount(): number + { + if(this._category === FurniCategory._Str_12351) + { + let count = 0; + let index = 0; + + while(index < this._items.length) + { + const item = this.getItemByIndex(index); + + count = (count + parseInt(item.stuffData.getLegacyString())); + + index++; + } + + return count; + } + + return this._items.length; + } + + public getUnlockedCount(): number + { + if(this.category === FurniCategory._Str_12351) return this.getTotalCount(); + + let count = 0; + let index = 0; + + while(index < this._items.length) + { + const item = this.getItemByIndex(index); + + if(!item.locked) count++; + + index++; + } + + return count; + } + + public getLastItem(): FurnitureItem + { + if(!this._items.length) return null; + + const item = this.getItemByIndex((this._items.length - 1)); + + return item; + } + + public unlockAllItems(): void + { + const items = [ ...this._items ]; + + let index = 0; + + while(index < items.length) + { + const item = items[index]; + + if(item.locked) + { + const newItem = item.clone(); + + newItem.locked = false; + + items[index] = newItem; + } + + index++; + } + + this._items = items; + } + + public lockItemIds(itemIds: number[]): void + { + const items = [ ...this._items ]; + + let index = 0; + + while(index < items.length) + { + const item = items[index]; + const locked = (itemIds.indexOf(item.ref) >= 0); + + if(item.locked !== locked) + { + const newItem = item.clone(); + + newItem.locked = locked; + + items[index] = newItem; + } + + index++; + } + + this._items = items; + } + + private setName(): void + { + const k = this.getLastItem(); + + if(!k) + { + this._name = ''; + + return; + } + + let key = ''; + + switch(this._category) + { + case FurniCategory._Str_5186: + key = (('poster_' + k.stuffData.getLegacyString()) + '_name'); + break; + case FurniCategory._Str_9125: + this._name = 'SONG_NAME'; + return; + default: + if(this.isWallItem) + { + key = ('wallItem.name.' + k.type); + } + else + { + key = ('roomItem.name.' + k.type); + } + } + + this._name = LocalizeText(key); + } + + private setDescription(): void + { + this._description = ''; + } + + private setIcon(): void + { + if(this._iconUrl) return; + + let url = null; + + if(this.isWallItem) + { + url = this._roomEngine.getFurnitureWallIconUrl(this._type, this._stuffData.getLegacyString()); + } + else + { + url = this._roomEngine.getFurnitureFloorIconUrl(this._type); + } + + if(!url) return; + + this._iconUrl = url; + } + + public get type(): number + { + return this._type; + } + + public get category(): number + { + return this._category; + } + + public get stuffData(): IObjectData + { + return this._stuffData; + } + + public get extra(): number + { + return this._extra; + } + + public get iconUrl(): string + { + return this._iconUrl; + } + + public get name(): string + { + return this._name; + } + + public get description(): string + { + return this._description; + } + + public get hasUnseenItems(): boolean + { + return this._hasUnseenItems; + } + + public set hasUnseenItems(flag: boolean) + { + this._hasUnseenItems = flag; + } + + public get locked(): boolean + { + return this._locked; + } + + public set locked(flag: boolean) + { + this._locked = flag; + } + + public get selected(): boolean + { + return this._selected; + } + + public set selected(flag: boolean) + { + this._selected = flag; + } + + public get isWallItem(): boolean + { + const item = this.getItemByIndex(0); + + return (item ? item.isWallItem : false); + } + + public get isGroupable(): boolean + { + const item = this.getItemByIndex(0); + + return (item ? item.isGroupable : false); + } + + public get items(): FurnitureItem[] + { + return this._items; + } +} diff --git a/src/views/inventory/utils/IFurnitureItem.ts b/src/views/inventory/utils/IFurnitureItem.ts new file mode 100644 index 00000000..e9f3371b --- /dev/null +++ b/src/views/inventory/utils/IFurnitureItem.ts @@ -0,0 +1,17 @@ +import { IObjectData } from 'nitro-renderer'; + +export interface IFurnitureItem +{ + id: number; + ref: number; + type: number; + stuffData: IObjectData; + extra: number; + category: number; + _Str_16260: boolean; + isTradable: boolean; + isGroupable: boolean; + sellable: boolean; + locked: boolean; + isWallItem: boolean; +} diff --git a/src/views/inventory/views/InventoryViews.scss b/src/views/inventory/views/InventoryViews.scss new file mode 100644 index 00000000..b4525abe --- /dev/null +++ b/src/views/inventory/views/InventoryViews.scss @@ -0,0 +1 @@ +@import './furniture/InventoryFurnitureView'; diff --git a/src/views/inventory/views/furniture/InventoryFurnitureView.scss b/src/views/inventory/views/furniture/InventoryFurnitureView.scss new file mode 100644 index 00000000..ac3b8fa2 --- /dev/null +++ b/src/views/inventory/views/furniture/InventoryFurnitureView.scss @@ -0,0 +1,7 @@ +.item-container { + height: 220px; + max-height: 220px; + overflow-y: auto; +} + +@import './item/InventoryFurnitureItemView'; diff --git a/src/views/inventory/views/furniture/InventoryFurnitureView.tsx b/src/views/inventory/views/furniture/InventoryFurnitureView.tsx new file mode 100644 index 00000000..e0af15ac --- /dev/null +++ b/src/views/inventory/views/furniture/InventoryFurnitureView.tsx @@ -0,0 +1,117 @@ +import { FurnitureListComposer, RoomObjectVariable, Vector3d } from 'nitro-renderer'; +import { FC, useEffect } from 'react'; +import { GetRoomEngine } from '../../../../api'; +import { SendMessageHook } from '../../../../hooks/messages/message-event'; +import { LocalizeText } from '../../../../utils/LocalizeText'; +import { RoomPreviewerView } from '../../../room-previewer/RoomPreviewerView'; +import { FurniCategory } from '../../utils/FurniCategory'; +import { attemptItemPlacement } from '../../utils/FurnitureUtilities'; +import { InventoryFurnitureViewProps } from './InventoryFurnitureView.types'; +import { InventoryFurnitureItemView } from './item/InventoryFurnitureItemView'; + +export const InventoryFurnitureView: FC = props => +{ + const { needsFurniUpdate = false, setNeedsFurniUpdate = null, groupItem = null, setGroupItem = null, groupItems = null, roomSession = null, roomPreviewer = null } = props; + + console.log(props); + + useEffect(() => + { + if(needsFurniUpdate) + { + setNeedsFurniUpdate(false); + + SendMessageHook(new FurnitureListComposer()); + } + else + { + setGroupItem(prevValue => + { + if(!groupItems || !groupItems.length) return null; + + let index = 0; + + if(prevValue) + { + const foundIndex = groupItems.indexOf(prevValue); + + if(foundIndex > -1) index = foundIndex; + } + + return groupItems[index]; + }); + } + + }, [ needsFurniUpdate, setNeedsFurniUpdate, groupItems, setGroupItem ]); + + useEffect(() => + { + if(!groupItem || !roomPreviewer) return; + + const furnitureItem = groupItem.getLastItem(); + + if(!furnitureItem) return; + + const roomEngine = GetRoomEngine(); + + let wallType = roomEngine.getRoomInstanceVariable(roomEngine.activeRoomId, RoomObjectVariable.ROOM_WALL_TYPE); + let floorType = roomEngine.getRoomInstanceVariable(roomEngine.activeRoomId, RoomObjectVariable.ROOM_FLOOR_TYPE); + let landscapeType = roomEngine.getRoomInstanceVariable(roomEngine.activeRoomId, RoomObjectVariable.ROOM_LANDSCAPE_TYPE); + + wallType = (wallType && wallType.length) ? wallType : '101'; + floorType = (floorType && floorType.length) ? floorType : '101'; + landscapeType = (landscapeType && landscapeType.length) ? landscapeType : '1.1'; + + roomPreviewer.reset(false); + roomPreviewer.updateObjectRoom(floorType, wallType, landscapeType); + roomPreviewer.updateRoomWallsAndFloorVisibility(true, true); + + if((furnitureItem.category === FurniCategory._Str_3639) || (furnitureItem.category === FurniCategory._Str_3683) || (furnitureItem.category === FurniCategory._Str_3432)) + { + floorType = ((furnitureItem.category === FurniCategory._Str_3683) ? groupItem.stuffData.getLegacyString() : floorType); + wallType = ((furnitureItem.category === FurniCategory._Str_3639) ? groupItem.stuffData.getLegacyString() : wallType); + landscapeType = ((furnitureItem.category === FurniCategory._Str_3432) ? groupItem.stuffData.getLegacyString() : landscapeType); + + roomPreviewer.updateObjectRoom(floorType, wallType, landscapeType); + + if(furnitureItem.category === FurniCategory._Str_3432) + { + // insert a window if the type is landscape + //_local_19 = this._model.controller._Str_18225("ads_twi_windw", ProductTypeEnum.WALL); + //this._roomPreviewer._Str_12087(_local_19.id, new Vector3d(90, 0, 0), _local_19._Str_4558); + } + } + else + { + if(groupItem.isWallItem) + { + roomPreviewer.addWallItemIntoRoom(groupItem.type, new Vector3d(90), furnitureItem.stuffData.getLegacyString()); + } + else + { + roomPreviewer.addFurnitureIntoRoom(groupItem.type, new Vector3d(90), groupItem.stuffData, (furnitureItem.extra.toString())); + } + } + }, [ roomPreviewer, groupItem ]); + + return ( +
+
+
+ { groupItems && groupItems.length && groupItems.map((item, index) => + { + return + }) + } +
+
+
+ + { groupItem &&
+

{ groupItem.name }

+ { !!roomSession && } +
} +
+
+ ); +} diff --git a/src/views/inventory/views/furniture/InventoryFurnitureView.types.ts b/src/views/inventory/views/furniture/InventoryFurnitureView.types.ts new file mode 100644 index 00000000..9b033363 --- /dev/null +++ b/src/views/inventory/views/furniture/InventoryFurnitureView.types.ts @@ -0,0 +1,14 @@ +import { IRoomSession, RoomPreviewer } from 'nitro-renderer'; +import { Dispatch, SetStateAction } from 'react'; +import { GroupItem } from '../../utils/GroupItem'; + +export interface InventoryFurnitureViewProps +{ + needsFurniUpdate: boolean; + setNeedsFurniUpdate: Dispatch>; + groupItem: GroupItem; + setGroupItem: Dispatch>; + groupItems: GroupItem[]; + roomSession: IRoomSession; + roomPreviewer: RoomPreviewer; +} diff --git a/src/views/inventory/views/furniture/item/InventoryFurnitureItemView.scss b/src/views/inventory/views/furniture/item/InventoryFurnitureItemView.scss new file mode 100644 index 00000000..66091f74 --- /dev/null +++ b/src/views/inventory/views/furniture/item/InventoryFurnitureItemView.scss @@ -0,0 +1,19 @@ +.inventory-furniture-item { + background-position: center; + background-repeat: no-repeat; + height: 50px; + max-height: 50px; + border-color: $muted !important; + background-color: #CDD3D9; + + &.active { + border-color: $white !important; + background-color: #ECECEC; + } + + .badge { + top: 3px; + right: 3px; + font-size: 10px; + } +} diff --git a/src/views/inventory/views/furniture/item/InventoryFurnitureItemView.tsx b/src/views/inventory/views/furniture/item/InventoryFurnitureItemView.tsx new file mode 100644 index 00000000..97eeecd1 --- /dev/null +++ b/src/views/inventory/views/furniture/item/InventoryFurnitureItemView.tsx @@ -0,0 +1,17 @@ +import { FC } from 'react'; +import { InventoryFurnitureItemViewProps } from './InventoryFurnitureItemView.types'; + +export const InventoryFurnitureItemView: FC = props => +{ + const { groupItem = null, isActive = false, setGroupItem = null } = props; + + const imageUrl = `url(${ groupItem.iconUrl })`; + + return ( +
+
setGroupItem(groupItem) }> + { groupItem.getUnlockedCount() } +
+
+ ); +} diff --git a/src/views/inventory/views/furniture/item/InventoryFurnitureItemView.types.ts b/src/views/inventory/views/furniture/item/InventoryFurnitureItemView.types.ts new file mode 100644 index 00000000..167edede --- /dev/null +++ b/src/views/inventory/views/furniture/item/InventoryFurnitureItemView.types.ts @@ -0,0 +1,9 @@ +import { Dispatch, SetStateAction } from 'react'; +import { GroupItem } from '../../../utils/GroupItem'; + +export interface InventoryFurnitureItemViewProps +{ + groupItem: GroupItem; + isActive: boolean; + setGroupItem: Dispatch>; +}