Files
Nitro-V3/src/components/inventory/views/furniture/InventoryFurnitureView.tsx
T
duckietm 888073acb1 🆙 Update #2
2026-05-29 15:16:14 +02:00

177 lines
8.3 KiB
TypeScript

import { InfiniteGrid } from '@layout/InfiniteGrid';
import { GetRoomEngine, GetSessionDataManager, IRoomSession, RoomObjectVariable, RoomPreviewer, Vector3d } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { FaPowerOff, FaSyncAlt, FaTrashAlt } from 'react-icons/fa';
import { DispatchUiEvent, FurniCategory, GroupItem, LocalizeText, UnseenItemCategory, attemptItemPlacement } from '../../../../api';
import { LayoutLimitedEditionCompactPlateView, LayoutRarityLevelView, LayoutRoomPreviewerView } from '../../../../common';
import { CatalogPostMarketplaceOfferEvent, DeleteItemConfirmEvent } from '../../../../events';
import { useInventoryFurni, useInventoryUnseenTracker } from '../../../../hooks';
import { NitroButton } from '../../../../layout';
import { InventoryCategoryEmptyView } from '../InventoryCategoryEmptyView';
import { InventoryFurnitureItemView } from './InventoryFurnitureItemView';
const attemptPlaceMarketplaceOffer = (groupItem: GroupItem) =>
{
const item = groupItem.getLastItem();
if(!item) return false;
if(!item.sellable) return false;
DispatchUiEvent(new CatalogPostMarketplaceOfferEvent(item));
};
const attemptDeleteItem = (groupItem: GroupItem) =>
{
const item = groupItem.getLastItem();
if(!item) return;
DispatchUiEvent(new DeleteItemConfirmEvent(item, groupItem.getTotalCount()));
};
export const InventoryFurnitureView: FC<{
roomSession: IRoomSession;
roomPreviewer: RoomPreviewer;
filteredGroupItems: GroupItem[];
}> = props =>
{
const { roomSession = null, roomPreviewer = null, filteredGroupItems = [] } = props;
const [ isVisible, setIsVisible ] = useState(false);
const { groupItems = [], selectedItem = null, activate = null, deactivate = null } = useInventoryFurni();
const { resetItems = null } = useInventoryUnseenTracker();
useEffect(() =>
{
if(!selectedItem || !roomPreviewer) return;
const furnitureItem = selectedItem.getLastItem();
if(!furnitureItem) return;
roomPreviewer.reset(false);
const isRoomDecoration = (furnitureItem.category === FurniCategory.WALL_PAPER) || (furnitureItem.category === FurniCategory.FLOOR) || (furnitureItem.category === FurniCategory.LANDSCAPE);
if(isRoomDecoration)
{
const roomEngine = GetRoomEngine();
let wallType = roomEngine.getRoomInstanceVariable<string>(roomEngine.activeRoomId, RoomObjectVariable.ROOM_WALL_TYPE);
let floorType = roomEngine.getRoomInstanceVariable<string>(roomEngine.activeRoomId, RoomObjectVariable.ROOM_FLOOR_TYPE);
let landscapeType = roomEngine.getRoomInstanceVariable<string>(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.updateRoomWallsAndFloorVisibility(true, true);
floorType = ((furnitureItem.category === FurniCategory.FLOOR) ? selectedItem.stuffData.getLegacyString() : floorType);
wallType = ((furnitureItem.category === FurniCategory.WALL_PAPER) ? selectedItem.stuffData.getLegacyString() : wallType);
landscapeType = ((furnitureItem.category === FurniCategory.LANDSCAPE) ? selectedItem.stuffData.getLegacyString() : landscapeType);
roomPreviewer.updateObjectRoom(floorType, wallType, landscapeType);
if(furnitureItem.category === FurniCategory.LANDSCAPE)
{
const data = GetSessionDataManager().getWallItemDataByName('window_double_default');
if(data) roomPreviewer.addWallItemIntoRoom(data.id, new Vector3d(90, 0, 0), data.customParams);
}
return;
}
roomPreviewer.updateObjectRoom('default', 'default', 'default');
roomPreviewer.updateRoomWallsAndFloorVisibility(true, true);
if(selectedItem.isWallItem)
{
roomPreviewer.addWallItemIntoRoom(selectedItem.type, new Vector3d(90), furnitureItem.stuffData.getLegacyString());
}
else
{
roomPreviewer.addFurnitureIntoRoom(selectedItem.type, new Vector3d(90), selectedItem.stuffData, (furnitureItem.extra.toString()));
}
}, [ roomPreviewer, selectedItem ]);
useEffect(() =>
{
if(!selectedItem || !selectedItem.hasUnseenItems) return;
resetItems(UnseenItemCategory.FURNI, selectedItem.items.map(item => item.id));
selectedItem.hasUnseenItems = false;
}, [ selectedItem, resetItems ]);
useEffect(() =>
{
if(!isVisible) return;
const id = activate();
return () => deactivate(id);
}, [ isVisible, activate, deactivate ]);
useEffect(() =>
{
setIsVisible(true);
return () => setIsVisible(false);
}, []);
if(!groupItems || !groupItems.length) return <InventoryCategoryEmptyView desc={ LocalizeText('inventory.empty.desc') } title={ LocalizeText('inventory.empty.title') } />;
return (
<div className="grid h-full grid-cols-12 gap-2">
<div className="flex flex-col col-span-7 gap-1 overflow-hidden">
<InfiniteGrid<GroupItem>
columnCount={ 6 }
itemRender={ item => <InventoryFurnitureItemView groupItem={ item } /> }
items={ filteredGroupItems } />
</div>
<div className="flex flex-col col-span-5">
<div className="relative flex flex-col">
<LayoutRoomPreviewerView height={ 140 } roomPreviewer={ roomPreviewer } />
{ selectedItem &&
<>
<button className="nitro-inventory-preview-btn nitro-inventory-preview-rotate" onClick={ () => roomPreviewer?.changeRoomObjectDirection() }>
<FaSyncAlt /> Rotate
</button>
<button className="nitro-inventory-preview-btn nitro-inventory-preview-state" onClick={ () => roomPreviewer?.changeRoomObjectState() }>
<FaPowerOff /> Toggle State
</button>
</> }
{ selectedItem &&
<NitroButton
className="bg-danger! hover:bg-danger/80! absolute bottom-2 inset-e-2 p-1"
onClick={ () => attemptDeleteItem(selectedItem) }>
<FaTrashAlt className="fa-icon" />
</NitroButton> }
{ selectedItem && selectedItem.stuffData.isUnique &&
<LayoutLimitedEditionCompactPlateView className="top-2 inset-e-2" position="absolute" uniqueNumber={ selectedItem.stuffData.uniqueNumber } uniqueSeries={ selectedItem.stuffData.uniqueSeries } /> }
{ (selectedItem && selectedItem.stuffData.rarityLevel > -1) &&
<LayoutRarityLevelView className="top-2 inset-e-2" level={ selectedItem.stuffData.rarityLevel } position="absolute" /> }
</div>
{ selectedItem &&
<div className="flex flex-col justify-between gap-2 grow">
<span className="text-sm truncate grow">{ selectedItem.name }</span>
{ selectedItem.description &&
<span className="text-xs truncate">{ selectedItem.description }</span> }
<div className="flex flex-col gap-1">
{ !!roomSession &&
<NitroButton className="nitro-inventory-btn-place" onClick={ event => attemptItemPlacement(selectedItem) }>
{ LocalizeText('inventory.furni.placetoroom') }
</NitroButton> }
{ selectedItem.isSellable &&
<NitroButton className="nitro-inventory-btn-sell" onClick={ event => attemptPlaceMarketplaceOffer(selectedItem) }>
{ LocalizeText('inventory.marketplace.sell') }
</NitroButton> }
</div>
</div> }
</div>
</div>
);
};