mirror of
https://github.com/billsonnn/nitro-react.git
synced 2025-01-19 05:46:27 +01:00
Completely redo inventory state
This commit is contained in:
parent
46c62e4012
commit
da1b0c508d
@ -6,6 +6,7 @@ export * from './friends';
|
|||||||
export * from './GetRendererVersion';
|
export * from './GetRendererVersion';
|
||||||
export * from './GetUIVersion';
|
export * from './GetUIVersion';
|
||||||
export * from './groups';
|
export * from './groups';
|
||||||
|
export * from './inventory';
|
||||||
export * from './navigator';
|
export * from './navigator';
|
||||||
export * from './nitro';
|
export * from './nitro';
|
||||||
export * from './nitro/avatar';
|
export * from './nitro/avatar';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { IFurnitureItemData, IObjectData } from '@nitrots/nitro-renderer';
|
import { IFurnitureItemData, IObjectData } from '@nitrots/nitro-renderer';
|
||||||
import { GetNitroInstance } from '../../../api';
|
import { IFurnitureItem } from '.';
|
||||||
import { IFurnitureItem } from './IFurnitureItem';
|
import { GetNitroInstance } from '..';
|
||||||
|
|
||||||
export class FurnitureItem implements IFurnitureItem
|
export class FurnitureItem implements IFurnitureItem
|
||||||
{
|
{
|
@ -1,5 +1,5 @@
|
|||||||
import { IObjectData, IRoomEngine } from '@nitrots/nitro-renderer';
|
import { IObjectData, IRoomEngine } from '@nitrots/nitro-renderer';
|
||||||
import { LocalizeText } from '../../../api';
|
import { LocalizeText } from '..';
|
||||||
import { FurniCategory } from './FurniCategory';
|
import { FurniCategory } from './FurniCategory';
|
||||||
import { FurnitureItem } from './FurnitureItem';
|
import { FurnitureItem } from './FurnitureItem';
|
||||||
import { IFurnitureItem } from './IFurnitureItem';
|
import { IFurnitureItem } from './IFurnitureItem';
|
5
src/api/inventory/IBadgeItem.ts
Normal file
5
src/api/inventory/IBadgeItem.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export interface IBadgeItem
|
||||||
|
{
|
||||||
|
id: number;
|
||||||
|
badgeCode: string;
|
||||||
|
}
|
6
src/api/inventory/IBotItem.ts
Normal file
6
src/api/inventory/IBotItem.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { BotData } from '@nitrots/nitro-renderer';
|
||||||
|
|
||||||
|
export interface IBotItem
|
||||||
|
{
|
||||||
|
botData: BotData;
|
||||||
|
}
|
6
src/api/inventory/IPetItem.ts
Normal file
6
src/api/inventory/IPetItem.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { PetData } from '@nitrots/nitro-renderer';
|
||||||
|
|
||||||
|
export interface IPetItem
|
||||||
|
{
|
||||||
|
petData: PetData;
|
||||||
|
}
|
116
src/api/inventory/InventoryUtilities.ts
Normal file
116
src/api/inventory/InventoryUtilities.ts
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import { FurniturePlacePaintComposer, RoomObjectCategory, RoomObjectPlacementSource, RoomObjectType } from '@nitrots/nitro-renderer';
|
||||||
|
import { FurniCategory, GroupItem } from '.';
|
||||||
|
import { CreateLinkEvent, GetRoomEngine, GetRoomSessionManager, SendMessageComposer } from '..';
|
||||||
|
import { IBotItem } from './IBotItem';
|
||||||
|
import { IPetItem } from './IPetItem';
|
||||||
|
|
||||||
|
let objectMoverRequested = false;
|
||||||
|
let itemIdInPlacing = -1;
|
||||||
|
|
||||||
|
export const isObjectMoverRequested = () => objectMoverRequested;
|
||||||
|
|
||||||
|
export const setObjectMoverRequested = (flag: boolean) => objectMoverRequested = flag;
|
||||||
|
|
||||||
|
export const getPlacingItemId = () => itemIdInPlacing;
|
||||||
|
|
||||||
|
export const setPlacingItemId = (id: number) => (itemIdInPlacing = id);
|
||||||
|
|
||||||
|
export const cancelRoomObjectPlacement = () =>
|
||||||
|
{
|
||||||
|
if(getPlacingItemId() === -1) return;
|
||||||
|
|
||||||
|
GetRoomEngine().cancelRoomObjectPlacement();
|
||||||
|
|
||||||
|
setPlacingItemId(-1);
|
||||||
|
setObjectMoverRequested(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const attemptPetPlacement = (petItem: IPetItem, flag: boolean = false) =>
|
||||||
|
{
|
||||||
|
const petData = petItem.petData;
|
||||||
|
|
||||||
|
if(!petData) return false;
|
||||||
|
|
||||||
|
const session = GetRoomSessionManager().getSession(1);
|
||||||
|
|
||||||
|
if(!session) return false;
|
||||||
|
|
||||||
|
if(!session.isRoomOwner && !session.allowPets) return false;
|
||||||
|
|
||||||
|
CreateLinkEvent('inventory/hide');
|
||||||
|
|
||||||
|
if(GetRoomEngine().processRoomObjectPlacement(RoomObjectPlacementSource.INVENTORY, -(petData.id), RoomObjectCategory.UNIT, RoomObjectType.PET, petData.figureData.figuredata))
|
||||||
|
{
|
||||||
|
setPlacingItemId(petData.id);
|
||||||
|
setObjectMoverRequested(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const attemptItemPlacement = (groupItem: GroupItem, flag: boolean = false) =>
|
||||||
|
{
|
||||||
|
if(!groupItem || !groupItem.getUnlockedCount()) return false;
|
||||||
|
|
||||||
|
const item = groupItem.getLastItem();
|
||||||
|
|
||||||
|
if(!item) return false;
|
||||||
|
|
||||||
|
if((item.category === FurniCategory.FLOOR) || (item.category === FurniCategory.WALL_PAPER) || (item.category === FurniCategory.LANDSCAPE))
|
||||||
|
{
|
||||||
|
if(flag) return false;
|
||||||
|
|
||||||
|
SendMessageComposer(new FurniturePlacePaintComposer(item.id));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CreateLinkEvent('inventory/hide');
|
||||||
|
|
||||||
|
let category = 0;
|
||||||
|
let isMoving = false;
|
||||||
|
|
||||||
|
if(item.isWallItem) category = RoomObjectCategory.WALL;
|
||||||
|
else category = RoomObjectCategory.FLOOR;
|
||||||
|
|
||||||
|
if((item.category === FurniCategory.POSTER)) // 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)
|
||||||
|
{
|
||||||
|
setPlacingItemId(item.ref);
|
||||||
|
setObjectMoverRequested(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const attemptBotPlacement = (botItem: IBotItem, flag: boolean = false) =>
|
||||||
|
{
|
||||||
|
const botData = botItem.botData;
|
||||||
|
|
||||||
|
if(!botData) return false;
|
||||||
|
|
||||||
|
const session = GetRoomSessionManager().getSession(1);
|
||||||
|
|
||||||
|
if(!session || !session.isRoomOwner) return false;
|
||||||
|
|
||||||
|
CreateLinkEvent('inventory/hide');
|
||||||
|
|
||||||
|
if(GetRoomEngine().processRoomObjectPlacement(RoomObjectPlacementSource.INVENTORY, -(botData.id), RoomObjectCategory.UNIT, RoomObjectType.RENTABLE_BOT, botData.figure))
|
||||||
|
{
|
||||||
|
setPlacingItemId(botData.id);
|
||||||
|
setObjectMoverRequested(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { LocalizeText, NotificationUtilities } from '../../../api';
|
import { LocalizeText, NotificationUtilities } from '..';
|
||||||
import { TradingNotificationType } from './TradingNotificationType';
|
import { TradingNotificationType } from './TradingNotificationType';
|
||||||
|
|
||||||
export const TradingNotificationMessage = (type: number) =>
|
export const TradingNotificationMessage = (type: number) =>
|
13
src/api/inventory/index.ts
Normal file
13
src/api/inventory/index.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
export * from './FurniCategory';
|
||||||
|
export * from './FurnitureItem';
|
||||||
|
export * from './GroupItem';
|
||||||
|
export * from './IBadgeItem';
|
||||||
|
export * from './IBotItem';
|
||||||
|
export * from './IFurnitureItem';
|
||||||
|
export * from './InventoryUtilities';
|
||||||
|
export * from './IPetItem';
|
||||||
|
export * from './TradeState';
|
||||||
|
export * from './TradeUserData';
|
||||||
|
export * from './TradingNotificationMessage';
|
||||||
|
export * from './TradingNotificationType';
|
||||||
|
export * from './unseen';
|
2
src/api/inventory/unseen/index.ts
Normal file
2
src/api/inventory/unseen/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './IUnseenItemTracker';
|
||||||
|
export * from './UnseenItemCategory';
|
@ -2,7 +2,7 @@ import { NitroEvent, RoomEngineUseProductEvent, RoomObjectCategory, RoomObjectTy
|
|||||||
import { SendMessageComposer } from '../../..';
|
import { SendMessageComposer } from '../../..';
|
||||||
import { GetRoomEngine, GetSessionDataManager, IsOwnerOfFurniture } from '../../../..';
|
import { GetRoomEngine, GetSessionDataManager, IsOwnerOfFurniture } from '../../../..';
|
||||||
import { MessengerFriend } from '../../../../../components/friends/common/MessengerFriend';
|
import { MessengerFriend } from '../../../../../components/friends/common/MessengerFriend';
|
||||||
import { FurniCategory } from '../../../../../components/inventory/common/FurniCategory';
|
import { FurniCategory } from '../../../../inventory/FurniCategory';
|
||||||
import { RoomWidgetAvatarInfoEvent, RoomWidgetUpdateDanceStatusEvent, RoomWidgetUpdateEvent, RoomWidgetUpdateUserDataEvent, RoomWidgetUseProductBubbleEvent, UseProductItem } from '../events';
|
import { RoomWidgetAvatarInfoEvent, RoomWidgetUpdateDanceStatusEvent, RoomWidgetUpdateEvent, RoomWidgetUpdateUserDataEvent, RoomWidgetUseProductBubbleEvent, UseProductItem } from '../events';
|
||||||
import { RoomWidgetAvatarExpressionMessage, RoomWidgetChangePostureMessage, RoomWidgetDanceMessage, RoomWidgetMessage, RoomWidgetRoomObjectMessage, RoomWidgetUseProductMessage, RoomWidgetUserActionMessage } from '../messages';
|
import { RoomWidgetAvatarExpressionMessage, RoomWidgetChangePostureMessage, RoomWidgetDanceMessage, RoomWidgetMessage, RoomWidgetRoomObjectMessage, RoomWidgetUseProductMessage, RoomWidgetUserActionMessage } from '../messages';
|
||||||
import { RoomWidgetHandler } from './RoomWidgetHandler';
|
import { RoomWidgetHandler } from './RoomWidgetHandler';
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import { GetMarketplaceConfigurationMessageComposer, MakeOfferMessageComposer, MarketplaceConfigurationEvent } from '@nitrots/nitro-renderer';
|
import { GetMarketplaceConfigurationMessageComposer, MakeOfferMessageComposer, MarketplaceConfigurationEvent } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useState } from 'react';
|
import { FC, useCallback, useEffect, useState } from 'react';
|
||||||
import { LocalizeText, NotificationUtilities, SendMessageComposer } from '../../../../../../api';
|
import { FurnitureItem, LocalizeText, NotificationUtilities, SendMessageComposer } from '../../../../../../api';
|
||||||
import { Base, Button, Column, Grid, LayoutFurniImageView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../../../common';
|
import { Base, Button, Column, Grid, LayoutFurniImageView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../../../common';
|
||||||
import { CatalogPostMarketplaceOfferEvent } from '../../../../../../events';
|
import { CatalogPostMarketplaceOfferEvent } from '../../../../../../events';
|
||||||
import { UseMessageEventHook, UseUiEvent } from '../../../../../../hooks';
|
import { UseMessageEventHook, UseUiEvent } from '../../../../../../hooks';
|
||||||
import { FurnitureItem } from '../../../../../inventory/common/FurnitureItem';
|
|
||||||
import { useCatalogContext } from '../../../../CatalogContext';
|
import { useCatalogContext } from '../../../../CatalogContext';
|
||||||
import { ProductTypeEnum } from '../../../../common/ProductTypeEnum';
|
import { ProductTypeEnum } from '../../../../common/ProductTypeEnum';
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { StringDataType } from '@nitrots/nitro-renderer';
|
import { StringDataType } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
import { FC, useEffect, useMemo, useState } from 'react';
|
||||||
|
import { IBadgeItem } from '../../../../../api';
|
||||||
import { AutoGrid, AutoGridProps, LayoutBadgeImageView, LayoutGridItem } from '../../../../../common';
|
import { AutoGrid, AutoGridProps, LayoutBadgeImageView, LayoutGridItem } from '../../../../../common';
|
||||||
import { InventoryBadgesRequestEvent, InventoryBadgesUpdatedEvent } from '../../../../../events';
|
import { useSharedInventoryBadges } from '../../../../../hooks';
|
||||||
import { DispatchUiEvent, UseUiEvent } from '../../../../../hooks';
|
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalogContext } from '../../../CatalogContext';
|
||||||
|
|
||||||
const EXCLUDED_BADGE_CODES: string[] = [];
|
const EXCLUDED_BADGE_CODES: string[] = [];
|
||||||
@ -15,16 +15,9 @@ interface CatalogBadgeSelectorWidgetViewProps extends AutoGridProps
|
|||||||
export const CatalogBadgeSelectorWidgetView: FC<CatalogBadgeSelectorWidgetViewProps> = props =>
|
export const CatalogBadgeSelectorWidgetView: FC<CatalogBadgeSelectorWidgetViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { columnCount = 5, ...rest } = props;
|
const { columnCount = 5, ...rest } = props;
|
||||||
const [ badges, setBadges ] = useState<string[]>([]);
|
const [ currentBadge, setCurrentBadge ] = useState<IBadgeItem>(null);
|
||||||
const [ currentBadge, setCurrentBadge ] = useState<string>(null);
|
|
||||||
const { currentOffer = null, setPurchaseOptions = null } = useCatalogContext();
|
const { currentOffer = null, setPurchaseOptions = null } = useCatalogContext();
|
||||||
|
const { badges = [] } = useSharedInventoryBadges();
|
||||||
const onInventoryBadgesUpdatedEvent = useCallback((event: InventoryBadgesUpdatedEvent) =>
|
|
||||||
{
|
|
||||||
setBadges(event.badges);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
UseUiEvent(InventoryBadgesUpdatedEvent.BADGES_UPDATED, onInventoryBadgesUpdatedEvent);
|
|
||||||
|
|
||||||
const previewStuffData = useMemo(() =>
|
const previewStuffData = useMemo(() =>
|
||||||
{
|
{
|
||||||
@ -32,7 +25,7 @@ export const CatalogBadgeSelectorWidgetView: FC<CatalogBadgeSelectorWidgetViewPr
|
|||||||
|
|
||||||
const stuffData = new StringDataType();
|
const stuffData = new StringDataType();
|
||||||
|
|
||||||
stuffData.setValue([ '0', currentBadge, '', '' ]);
|
stuffData.setValue([ '0', currentBadge.badgeCode, '', '' ]);
|
||||||
|
|
||||||
return stuffData;
|
return stuffData;
|
||||||
}, [ currentBadge ]);
|
}, [ currentBadge ]);
|
||||||
@ -53,18 +46,13 @@ export const CatalogBadgeSelectorWidgetView: FC<CatalogBadgeSelectorWidgetViewPr
|
|||||||
});
|
});
|
||||||
}, [ currentOffer, previewStuffData, setPurchaseOptions ]);
|
}, [ currentOffer, previewStuffData, setPurchaseOptions ]);
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
DispatchUiEvent(new InventoryBadgesRequestEvent(InventoryBadgesRequestEvent.REQUEST_BADGES));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AutoGrid columnCount={ columnCount } { ...rest }>
|
<AutoGrid columnCount={ columnCount } { ...rest }>
|
||||||
{ badges && (badges.length > 0) && badges.map((code, index) =>
|
{ badges && (badges.length > 0) && badges.map((badge, index) =>
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
<LayoutGridItem key={ index } itemActive={ (currentBadge === code) } onClick={ event => setCurrentBadge(code) }>
|
<LayoutGridItem key={ index } itemActive={ (currentBadge === badge) } onClick={ event => setCurrentBadge(badge) }>
|
||||||
<LayoutBadgeImageView badgeCode={ code } />
|
<LayoutBadgeImageView badgeCode={ badge.badgeCode } />
|
||||||
</LayoutGridItem>
|
</LayoutGridItem>
|
||||||
);
|
);
|
||||||
}) }
|
}) }
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
import { createContext, Dispatch, FC, ProviderProps, useContext } from 'react';
|
|
||||||
import { IUnseenItemTracker } from './common/unseen/IUnseenItemTracker';
|
|
||||||
import { IInventoryBadgeAction, IInventoryBadgeState } from './reducers/InventoryBadgeReducer';
|
|
||||||
import { IInventoryBotAction, IInventoryBotState } from './reducers/InventoryBotReducer';
|
|
||||||
import { IInventoryFurnitureAction, IInventoryFurnitureState } from './reducers/InventoryFurnitureReducer';
|
|
||||||
import { IInventoryPetAction, IInventoryPetState } from './reducers/InventoryPetReducer';
|
|
||||||
|
|
||||||
export interface IInventoryContext
|
|
||||||
{
|
|
||||||
furnitureState: IInventoryFurnitureState;
|
|
||||||
dispatchFurnitureState: Dispatch<IInventoryFurnitureAction>;
|
|
||||||
botState: IInventoryBotState;
|
|
||||||
dispatchBotState: Dispatch<IInventoryBotAction>;
|
|
||||||
petState: IInventoryPetState;
|
|
||||||
dispatchPetState: Dispatch<IInventoryPetAction>;
|
|
||||||
badgeState: IInventoryBadgeState;
|
|
||||||
dispatchBadgeState: Dispatch<IInventoryBadgeAction>;
|
|
||||||
unseenTracker: IUnseenItemTracker;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const InventoryContext = createContext<IInventoryContext>({
|
|
||||||
furnitureState: null,
|
|
||||||
dispatchFurnitureState: null,
|
|
||||||
botState: null,
|
|
||||||
dispatchBotState: null,
|
|
||||||
petState: null,
|
|
||||||
dispatchPetState: null,
|
|
||||||
badgeState: null,
|
|
||||||
dispatchBadgeState: null,
|
|
||||||
unseenTracker: null
|
|
||||||
});
|
|
||||||
|
|
||||||
export const InventoryContextProvider: FC<ProviderProps<IInventoryContext>> = props =>
|
|
||||||
{
|
|
||||||
return <InventoryContext.Provider value={ props.value }>{ props.children }</InventoryContext.Provider>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useInventoryContext = () => useContext(InventoryContext);
|
|
@ -1,386 +0,0 @@
|
|||||||
import { AdvancedMap, BadgePointLimitsEvent, BadgeReceivedEvent, BadgesEvent, BotAddedToInventoryEvent, BotInventoryMessageEvent, BotRemovedFromInventoryEvent, FurnitureListAddOrUpdateEvent, FurnitureListEvent, FurnitureListInvalidateEvent, FurnitureListItemParser, FurnitureListRemovedEvent, FurniturePostItPlacedEvent, PetAddedToInventoryEvent, PetData, PetInventoryEvent, PetRemovedFromInventory, RequestBadgesComposer, TradingAcceptEvent, TradingCloseEvent, TradingCloseParser, TradingCompletedEvent, TradingConfirmationEvent, TradingListItemEvent, TradingNotOpenEvent, TradingOpenEvent, TradingOpenFailedEvent, TradingOpenFailedParser, TradingOtherNotAllowedEvent, TradingYouAreNotAllowedEvent, UnseenItemsEvent } from '@nitrots/nitro-renderer';
|
|
||||||
import { FC, useCallback } from 'react';
|
|
||||||
import { GetLocalization, GetRoomSession, GetSessionDataManager, SendMessageComposer } from '../../api';
|
|
||||||
import { InventoryBadgesRequestEvent, InventoryBadgesUpdatedEvent } from '../../events';
|
|
||||||
import { DispatchUiEvent, UseMessageEventHook, UseUiEvent } from '../../hooks';
|
|
||||||
import { mergeFurniFragments } from './common/FurnitureUtilities';
|
|
||||||
import { mergePetFragments } from './common/PetUtilities';
|
|
||||||
import { TradeState } from './common/TradeState';
|
|
||||||
import { TradeUserData } from './common/TradeUserData';
|
|
||||||
import { TradingNotificationMessage } from './common/TradingNotificationMessage';
|
|
||||||
import { TradingNotificationType } from './common/TradingNotificationType';
|
|
||||||
import { useInventoryContext } from './InventoryContext';
|
|
||||||
import { InventoryBadgeActions } from './reducers/InventoryBadgeReducer';
|
|
||||||
import { InventoryBotActions } from './reducers/InventoryBotReducer';
|
|
||||||
import { InventoryFurnitureActions } from './reducers/InventoryFurnitureReducer';
|
|
||||||
import { InventoryPetActions } from './reducers/InventoryPetReducer';
|
|
||||||
|
|
||||||
let furniMsgFragments: Map<number, FurnitureListItemParser>[] = null;
|
|
||||||
let petMsgFragments: Map<number, PetData>[] = null;
|
|
||||||
|
|
||||||
export const InventoryMessageHandler: FC<{}> = props =>
|
|
||||||
{
|
|
||||||
const { dispatchFurnitureState = null, dispatchBotState = null, dispatchPetState = null, badgeState = null, dispatchBadgeState = null, unseenTracker = null, furnitureState = null } = useInventoryContext();
|
|
||||||
|
|
||||||
const onFurnitureListAddOrUpdateEvent = useCallback((event: FurnitureListAddOrUpdateEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
dispatchFurnitureState({
|
|
||||||
type: InventoryFurnitureActions.ADD_OR_UPDATE_FURNITURE,
|
|
||||||
payload: {
|
|
||||||
parsers: parser.items
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [ dispatchFurnitureState ]);
|
|
||||||
|
|
||||||
const onFurnitureListEvent = useCallback((event: FurnitureListEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
if(!furniMsgFragments) furniMsgFragments = new Array(parser.totalFragments);
|
|
||||||
|
|
||||||
const fragment = mergeFurniFragments(parser.fragment, parser.totalFragments, parser.fragmentNumber, furniMsgFragments);
|
|
||||||
|
|
||||||
if(!fragment) return;
|
|
||||||
|
|
||||||
dispatchFurnitureState({
|
|
||||||
type: InventoryFurnitureActions.PROCESS_FRAGMENT,
|
|
||||||
payload: { fragment, unseenTracker }
|
|
||||||
});
|
|
||||||
|
|
||||||
furniMsgFragments = null;
|
|
||||||
}, [ unseenTracker, dispatchFurnitureState ]);
|
|
||||||
|
|
||||||
const onFurnitureListInvalidateEvent = useCallback((event: FurnitureListInvalidateEvent) =>
|
|
||||||
{
|
|
||||||
dispatchFurnitureState({
|
|
||||||
type: InventoryFurnitureActions.SET_NEEDS_UPDATE,
|
|
||||||
payload: {
|
|
||||||
flag: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [ dispatchFurnitureState ]);
|
|
||||||
|
|
||||||
const onFurnitureListRemovedEvent = useCallback((event: FurnitureListRemovedEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
dispatchFurnitureState({
|
|
||||||
type: InventoryFurnitureActions.REMOVE_FURNITURE,
|
|
||||||
payload: {
|
|
||||||
itemId: parser.itemId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [ dispatchFurnitureState ]);
|
|
||||||
|
|
||||||
const onFurniturePostItPlacedEvent = useCallback((event: FurniturePostItPlacedEvent) =>
|
|
||||||
{
|
|
||||||
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onBotInventoryMessageEvent = useCallback((event: BotInventoryMessageEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
const fragment = Array.from(parser.items.values());
|
|
||||||
|
|
||||||
dispatchBotState({
|
|
||||||
type: InventoryBotActions.PROCESS_FRAGMENT,
|
|
||||||
payload: { fragment, unseenTracker }
|
|
||||||
});
|
|
||||||
}, [ dispatchBotState, unseenTracker ]);
|
|
||||||
|
|
||||||
const onBotAddedToInventoryEvent = useCallback((event: BotAddedToInventoryEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
dispatchBotState({
|
|
||||||
type: InventoryBotActions.ADD_BOT,
|
|
||||||
payload: {
|
|
||||||
botData: parser.item
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [ dispatchBotState ]);
|
|
||||||
|
|
||||||
const onBotRemovedFromInventoryEvent = useCallback((event: BotRemovedFromInventoryEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
dispatchBotState({
|
|
||||||
type: InventoryBotActions.REMOVE_BOT,
|
|
||||||
payload: {
|
|
||||||
botId: parser.itemId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [ dispatchBotState ]);
|
|
||||||
|
|
||||||
const onPetInventoryEvent = useCallback((event: PetInventoryEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
if(!petMsgFragments) petMsgFragments = new Array(parser.totalFragments);
|
|
||||||
|
|
||||||
const fragment = mergePetFragments(parser.fragment, parser.totalFragments, parser.fragmentNumber, petMsgFragments);
|
|
||||||
|
|
||||||
if(!fragment) return;
|
|
||||||
|
|
||||||
dispatchPetState({
|
|
||||||
type: InventoryPetActions.PROCESS_FRAGMENT,
|
|
||||||
payload: { fragment, unseenTracker }
|
|
||||||
});
|
|
||||||
}, [ dispatchPetState, unseenTracker ]);
|
|
||||||
|
|
||||||
const onPetAddedToInventoryEvent = useCallback((event: PetAddedToInventoryEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
dispatchPetState({
|
|
||||||
type: InventoryPetActions.ADD_PET,
|
|
||||||
payload: {
|
|
||||||
petData: parser.pet
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [ dispatchPetState ]);
|
|
||||||
|
|
||||||
const onPetRemovedFromInventory = useCallback((event: PetRemovedFromInventory) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
dispatchPetState({
|
|
||||||
type: InventoryPetActions.REMOVE_PET,
|
|
||||||
payload: {
|
|
||||||
petId: parser.petId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [ dispatchPetState ]);
|
|
||||||
|
|
||||||
const onBadgesEvent = useCallback((event: BadgesEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
dispatchBadgeState({
|
|
||||||
type: InventoryBadgeActions.SET_BADGES,
|
|
||||||
payload: {
|
|
||||||
badgeCodes: parser.getAllBadgeCodes(),
|
|
||||||
activeBadgeCodes: parser.getActiveBadgeCodes()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [ dispatchBadgeState ]);
|
|
||||||
|
|
||||||
const onBadgeReceivedEvent = useCallback((event: BadgeReceivedEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
dispatchBadgeState({
|
|
||||||
type: InventoryBadgeActions.ADD_BADGE,
|
|
||||||
payload: {
|
|
||||||
badgeCode: parser.badgeCode
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [ dispatchBadgeState ]);
|
|
||||||
|
|
||||||
const onTradingAcceptEvent = useCallback((event: TradingAcceptEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
dispatchFurnitureState({
|
|
||||||
type: InventoryFurnitureActions.SET_TRADE_ACCEPTANCE,
|
|
||||||
payload: {
|
|
||||||
userId: parser.userID,
|
|
||||||
flag: parser.userAccepts
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [ dispatchFurnitureState ]);
|
|
||||||
|
|
||||||
const onTradingCloseEvent = useCallback((event: TradingCloseEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
if(parser.reason === TradingCloseParser.ERROR_WHILE_COMMIT)
|
|
||||||
{
|
|
||||||
TradingNotificationMessage(TradingNotificationType.ERROR_WHILE_COMMIT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(parser.userID !== (furnitureState && furnitureState.tradeData.ownUser.userId))
|
|
||||||
{
|
|
||||||
TradingNotificationMessage(TradingNotificationType.ALERT_OTHER_CANCELLED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatchFurnitureState({
|
|
||||||
type: InventoryFurnitureActions.CLOSE_TRADE,
|
|
||||||
payload: {}
|
|
||||||
});
|
|
||||||
}, [ furnitureState, dispatchFurnitureState ]);
|
|
||||||
|
|
||||||
const onTradingCompletedEvent = useCallback((event: TradingCompletedEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
dispatchFurnitureState({
|
|
||||||
type: InventoryFurnitureActions.CLOSE_TRADE,
|
|
||||||
payload: {}
|
|
||||||
});
|
|
||||||
}, [ dispatchFurnitureState ]);
|
|
||||||
|
|
||||||
const onTradingConfirmationEvent = useCallback((event: TradingConfirmationEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
dispatchFurnitureState({
|
|
||||||
type: InventoryFurnitureActions.SET_TRADE_STATE,
|
|
||||||
payload: {
|
|
||||||
tradeState: TradeState.TRADING_STATE_COUNTDOWN
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [ dispatchFurnitureState ]);
|
|
||||||
|
|
||||||
const onTradingListItemEvent = useCallback((event: TradingListItemEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
dispatchFurnitureState({
|
|
||||||
type: InventoryFurnitureActions.UPDATE_TRADE,
|
|
||||||
payload: {
|
|
||||||
tradeParser: event.getParser()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [ dispatchFurnitureState ]);
|
|
||||||
|
|
||||||
const onTradingNotOpenEvent = useCallback((event: TradingNotOpenEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
console.log(parser);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onTradingOpenEvent = useCallback((event: TradingOpenEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
const ownUser = new TradeUserData();
|
|
||||||
const otherUser = new TradeUserData();
|
|
||||||
|
|
||||||
ownUser.userItems = new AdvancedMap();
|
|
||||||
otherUser.userItems = new AdvancedMap();
|
|
||||||
|
|
||||||
const userDataOne = GetRoomSession().userDataManager.getUserData(parser.userID);
|
|
||||||
const userDataTwo = GetRoomSession().userDataManager.getUserData(parser.otherUserID);
|
|
||||||
|
|
||||||
if(userDataOne.webID === GetSessionDataManager().userId)
|
|
||||||
{
|
|
||||||
ownUser.userId = userDataOne.webID;
|
|
||||||
ownUser.userName = userDataOne.name;
|
|
||||||
ownUser.canTrade = parser.userCanTrade;
|
|
||||||
|
|
||||||
otherUser.userId = userDataTwo.webID;
|
|
||||||
otherUser.userName = userDataTwo.name;
|
|
||||||
otherUser.canTrade = parser.otherUserCanTrade;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(userDataTwo.webID === GetSessionDataManager().userId)
|
|
||||||
{
|
|
||||||
ownUser.userId = userDataTwo.webID;
|
|
||||||
ownUser.userName = userDataTwo.name;
|
|
||||||
ownUser.canTrade = parser.otherUserCanTrade;
|
|
||||||
|
|
||||||
otherUser.userId = userDataOne.webID;
|
|
||||||
otherUser.userName = userDataOne.name;
|
|
||||||
otherUser.canTrade = parser.userCanTrade;
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatchFurnitureState({
|
|
||||||
type: InventoryFurnitureActions.SET_TRADE_DATA,
|
|
||||||
payload: {
|
|
||||||
ownTradeUser: ownUser,
|
|
||||||
otherTradeUser: otherUser
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [ dispatchFurnitureState ]);
|
|
||||||
|
|
||||||
const onTradingOpenFailedEvent = useCallback((event: TradingOpenFailedEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
if((parser.reason !== TradingOpenFailedParser.REASON_YOU_ARE_ALREADY_TRADING && (parser.reason !== TradingOpenFailedParser.REASON_OTHER_USER_ALREADY_TRADING))) return;
|
|
||||||
|
|
||||||
TradingNotificationMessage(TradingNotificationType.ALERT_ALREADY_OPEN);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onTradingOtherNotAllowedEvent = useCallback((event: TradingOtherNotAllowedEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
TradingNotificationMessage(TradingNotificationType.ALERT_OTHER_DISABLED);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onTradingYouAreNotAllowedEvent = useCallback((event: TradingYouAreNotAllowedEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
TradingNotificationMessage(TradingNotificationType.YOU_NOT_ALLOWED);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onUnseenItemsEvent = useCallback((event: UnseenItemsEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
for(const category of parser.categories)
|
|
||||||
{
|
|
||||||
const itemIds = parser.getItemsByCategory(category);
|
|
||||||
|
|
||||||
unseenTracker.addItems(category, itemIds);
|
|
||||||
}
|
|
||||||
}, [ unseenTracker ]);
|
|
||||||
|
|
||||||
const onBadgePointLimitsEvent = useCallback((event: BadgePointLimitsEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
for(const data of parser.data) GetLocalization().setBadgePointLimit(data.badgeId, data.limit);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
UseMessageEventHook(FurnitureListAddOrUpdateEvent, onFurnitureListAddOrUpdateEvent);
|
|
||||||
UseMessageEventHook(FurnitureListEvent, onFurnitureListEvent);
|
|
||||||
UseMessageEventHook(FurnitureListInvalidateEvent, onFurnitureListInvalidateEvent);
|
|
||||||
UseMessageEventHook(FurnitureListRemovedEvent, onFurnitureListRemovedEvent);
|
|
||||||
UseMessageEventHook(FurniturePostItPlacedEvent, onFurniturePostItPlacedEvent);
|
|
||||||
UseMessageEventHook(BotInventoryMessageEvent, onBotInventoryMessageEvent);
|
|
||||||
UseMessageEventHook(BotRemovedFromInventoryEvent, onBotRemovedFromInventoryEvent);
|
|
||||||
UseMessageEventHook(BotAddedToInventoryEvent, onBotAddedToInventoryEvent);
|
|
||||||
UseMessageEventHook(PetInventoryEvent, onPetInventoryEvent);
|
|
||||||
UseMessageEventHook(PetRemovedFromInventory, onPetRemovedFromInventory);
|
|
||||||
UseMessageEventHook(PetAddedToInventoryEvent, onPetAddedToInventoryEvent);
|
|
||||||
UseMessageEventHook(BadgesEvent, onBadgesEvent);
|
|
||||||
UseMessageEventHook(BadgeReceivedEvent, onBadgeReceivedEvent);
|
|
||||||
UseMessageEventHook(TradingAcceptEvent, onTradingAcceptEvent);
|
|
||||||
UseMessageEventHook(TradingCloseEvent, onTradingCloseEvent);
|
|
||||||
UseMessageEventHook(TradingCompletedEvent, onTradingCompletedEvent);
|
|
||||||
UseMessageEventHook(TradingConfirmationEvent, onTradingConfirmationEvent);
|
|
||||||
UseMessageEventHook(TradingListItemEvent, onTradingListItemEvent);
|
|
||||||
UseMessageEventHook(TradingNotOpenEvent, onTradingNotOpenEvent);
|
|
||||||
UseMessageEventHook(TradingOpenEvent, onTradingOpenEvent);
|
|
||||||
UseMessageEventHook(TradingOpenFailedEvent, onTradingOpenFailedEvent);
|
|
||||||
UseMessageEventHook(TradingOtherNotAllowedEvent, onTradingOtherNotAllowedEvent);
|
|
||||||
UseMessageEventHook(TradingYouAreNotAllowedEvent, onTradingYouAreNotAllowedEvent);
|
|
||||||
UseMessageEventHook(UnseenItemsEvent, onUnseenItemsEvent);
|
|
||||||
UseMessageEventHook(BadgePointLimitsEvent, onBadgePointLimitsEvent);
|
|
||||||
|
|
||||||
const onInventoryBadgesRequestEvent = useCallback((event: InventoryBadgesRequestEvent) =>
|
|
||||||
{
|
|
||||||
if(badgeState.needsBadgeUpdate)
|
|
||||||
{
|
|
||||||
SendMessageComposer(new RequestBadgesComposer());
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DispatchUiEvent(new InventoryBadgesUpdatedEvent(InventoryBadgesUpdatedEvent.BADGES_UPDATED, badgeState.badges));
|
|
||||||
}, [ badgeState ])
|
|
||||||
|
|
||||||
UseUiEvent(InventoryBadgesRequestEvent.REQUEST_BADGES, onInventoryBadgesRequestEvent);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
@ -1,25 +1,15 @@
|
|||||||
import { IRoomSession, RoomEngineObjectEvent, RoomEngineObjectPlacedEvent, RoomPreviewer, RoomSessionEvent, TradingCancelComposer, TradingCloseComposer, TradingOpenComposer } from '@nitrots/nitro-renderer';
|
import { BadgePointLimitsEvent, ILinkEventTracker, IRoomSession, RoomEngineObjectEvent, RoomEngineObjectPlacedEvent, RoomPreviewer, RoomSessionEvent, TradingOpenComposer } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useReducer, useState } from 'react';
|
import { FC, useCallback, useEffect, useState } from 'react';
|
||||||
import { GetRoomEngine, LocalizeText, SendMessageComposer } from '../../api';
|
import { AddEventLinkTracker, GetLocalization, GetRoomEngine, LocalizeText, RemoveLinkEventTracker, SendMessageComposer, UnseenItemCategory } from '../../api';
|
||||||
|
import { isObjectMoverRequested, setObjectMoverRequested } from '../../api/inventory/InventoryUtilities';
|
||||||
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../common';
|
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../common';
|
||||||
import { InventoryBadgesUpdatedEvent, InventoryEvent, InventoryTradeRequestEvent } from '../../events';
|
import { InventoryTradeRequestEvent } from '../../events';
|
||||||
import { DispatchUiEvent, UseRoomEngineEvent, UseRoomSessionManagerEvent, UseUiEvent } from '../../hooks';
|
import { UseMessageEventHook, UseRoomEngineEvent, UseRoomSessionManagerEvent, useSharedInventoryUnseenTracker, UseUiEvent } from '../../hooks';
|
||||||
import { isObjectMoverRequested, setObjectMoverRequested } from './common/InventoryUtilities';
|
import { InventoryBadgeView } from './views/InventoryBadgeView';
|
||||||
import { TradeState } from './common/TradeState';
|
import { InventoryBotView } from './views/InventoryBotView';
|
||||||
import { IUnseenItemTracker } from './common/unseen/IUnseenItemTracker';
|
import { InventoryFurnitureView } from './views/InventoryFurnitureView';
|
||||||
import { UnseenItemCategory } from './common/unseen/UnseenItemCategory';
|
import { InventoryPetView } from './views/InventoryPetView';
|
||||||
import { UnseenItemTracker } from './common/unseen/UnseenItemTracker';
|
import { InventoryTradeView } from './views/InventoryTradeView';
|
||||||
import { InventoryContextProvider } from './InventoryContext';
|
|
||||||
import { InventoryMessageHandler } from './InventoryMessageHandler';
|
|
||||||
import { initialInventoryBadge, InventoryBadgeReducer } from './reducers/InventoryBadgeReducer';
|
|
||||||
import { initialInventoryBot, InventoryBotReducer } from './reducers/InventoryBotReducer';
|
|
||||||
import { initialInventoryFurniture, InventoryFurnitureReducer } from './reducers/InventoryFurnitureReducer';
|
|
||||||
import { initialInventoryPet, InventoryPetReducer } from './reducers/InventoryPetReducer';
|
|
||||||
import { InventoryBadgeView } from './views/badge/InventoryBadgeView';
|
|
||||||
import { InventoryBotView } from './views/bot/InventoryBotView';
|
|
||||||
import { InventoryFurnitureView } from './views/furniture/InventoryFurnitureView';
|
|
||||||
import { InventoryPetView } from './views/pet/InventoryPetView';
|
|
||||||
import { InventoryTradeView } from './views/trade/InventoryTradeView';
|
|
||||||
|
|
||||||
const TAB_FURNITURE: string = 'inventory.furni';
|
const TAB_FURNITURE: string = 'inventory.furni';
|
||||||
const TAB_BOTS: string = 'inventory.bots';
|
const TAB_BOTS: string = 'inventory.bots';
|
||||||
@ -34,66 +24,40 @@ export const InventoryView: FC<{}> = props =>
|
|||||||
const [ currentTab, setCurrentTab ] = useState<string>(TABS[0]);
|
const [ currentTab, setCurrentTab ] = useState<string>(TABS[0]);
|
||||||
const [ roomSession, setRoomSession ] = useState<IRoomSession>(null);
|
const [ roomSession, setRoomSession ] = useState<IRoomSession>(null);
|
||||||
const [ roomPreviewer, setRoomPreviewer ] = useState<RoomPreviewer>(null);
|
const [ roomPreviewer, setRoomPreviewer ] = useState<RoomPreviewer>(null);
|
||||||
const [ furnitureState, dispatchFurnitureState ] = useReducer(InventoryFurnitureReducer, initialInventoryFurniture);
|
const { getCount = null, resetCategory = null } = useSharedInventoryUnseenTracker();
|
||||||
const [ botState, dispatchBotState ] = useReducer(InventoryBotReducer, initialInventoryBot);
|
|
||||||
const [ petState, dispatchPetState ] = useReducer(InventoryPetReducer, initialInventoryPet);
|
|
||||||
const [ badgeState, dispatchBadgeState ] = useReducer(InventoryBadgeReducer, initialInventoryBadge);
|
|
||||||
const [ unseenTracker ] = useState<IUnseenItemTracker>(new UnseenItemTracker());
|
|
||||||
|
|
||||||
const close = useCallback(() =>
|
const close = useCallback(() =>
|
||||||
{
|
{
|
||||||
if(furnitureState.tradeData)
|
// close the trade
|
||||||
{
|
// if(furnitureState.tradeData)
|
||||||
switch(furnitureState.tradeData.state)
|
// {
|
||||||
{
|
// switch(furnitureState.tradeData.state)
|
||||||
case TradeState.TRADING_STATE_RUNNING:
|
// {
|
||||||
SendMessageComposer(new TradingCloseComposer());
|
// case TradeState.TRADING_STATE_RUNNING:
|
||||||
return;
|
// SendMessageComposer(new TradingCloseComposer());
|
||||||
default:
|
// return;
|
||||||
SendMessageComposer(new TradingCancelComposer());
|
// default:
|
||||||
return;
|
// SendMessageComposer(new TradingCancelComposer());
|
||||||
}
|
// return;
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
setIsVisible(false);
|
setIsVisible(false);
|
||||||
}, [ furnitureState.tradeData ]);
|
}, []);
|
||||||
|
|
||||||
const onInventoryEvent = useCallback((event: InventoryEvent) =>
|
const onInventoryTradeRequestEvent = useCallback((event: InventoryTradeRequestEvent) =>
|
||||||
{
|
{
|
||||||
switch(event.type)
|
switch(event.type)
|
||||||
{
|
{
|
||||||
case InventoryEvent.SHOW_INVENTORY:
|
|
||||||
if(isVisible) return;
|
|
||||||
|
|
||||||
setIsVisible(true);
|
|
||||||
return;
|
|
||||||
case InventoryEvent.HIDE_INVENTORY:
|
|
||||||
if(!isVisible) return;
|
|
||||||
|
|
||||||
close();
|
|
||||||
return;
|
|
||||||
case InventoryEvent.TOGGLE_INVENTORY:
|
|
||||||
if(!isVisible)
|
|
||||||
{
|
|
||||||
setIsVisible(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case InventoryTradeRequestEvent.REQUEST_TRADE: {
|
case InventoryTradeRequestEvent.REQUEST_TRADE: {
|
||||||
const tradeEvent = (event as InventoryTradeRequestEvent);
|
const tradeEvent = (event as InventoryTradeRequestEvent);
|
||||||
|
|
||||||
SendMessageComposer(new TradingOpenComposer(tradeEvent.objectId));
|
SendMessageComposer(new TradingOpenComposer(tradeEvent.objectId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [ isVisible, close ]);
|
}, []);
|
||||||
|
|
||||||
UseUiEvent(InventoryEvent.SHOW_INVENTORY, onInventoryEvent);
|
UseUiEvent(InventoryTradeRequestEvent.REQUEST_TRADE, onInventoryTradeRequestEvent);
|
||||||
UseUiEvent(InventoryEvent.HIDE_INVENTORY, onInventoryEvent);
|
|
||||||
UseUiEvent(InventoryEvent.TOGGLE_INVENTORY, onInventoryEvent);
|
|
||||||
UseUiEvent(InventoryTradeRequestEvent.REQUEST_TRADE, onInventoryEvent);
|
|
||||||
|
|
||||||
const onRoomEngineObjectPlacedEvent = useCallback((event: RoomEngineObjectPlacedEvent) =>
|
const onRoomEngineObjectPlacedEvent = useCallback((event: RoomEngineObjectPlacedEvent) =>
|
||||||
{
|
{
|
||||||
@ -123,44 +87,44 @@ export const InventoryView: FC<{}> = props =>
|
|||||||
UseRoomSessionManagerEvent(RoomSessionEvent.CREATED, onRoomSessionEvent);
|
UseRoomSessionManagerEvent(RoomSessionEvent.CREATED, onRoomSessionEvent);
|
||||||
UseRoomSessionManagerEvent(RoomSessionEvent.ENDED, onRoomSessionEvent);
|
UseRoomSessionManagerEvent(RoomSessionEvent.ENDED, onRoomSessionEvent);
|
||||||
|
|
||||||
const resetTrackerForTab = useCallback((name: string) =>
|
const onBadgePointLimitsEvent = useCallback((event: BadgePointLimitsEvent) =>
|
||||||
{
|
{
|
||||||
const tabIndex = TABS.indexOf(name);
|
const parser = event.getParser();
|
||||||
|
|
||||||
if(tabIndex === -1) return;
|
for(const data of parser.data) GetLocalization().setBadgePointLimit(data.badgeId, data.limit);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const unseenCategory = UNSEEN_CATEGORIES[tabIndex];
|
UseMessageEventHook(BadgePointLimitsEvent, onBadgePointLimitsEvent);
|
||||||
|
|
||||||
if(unseenCategory === -1) return;
|
|
||||||
|
|
||||||
const count = unseenTracker.getCount(unseenCategory);
|
|
||||||
|
|
||||||
if(!count) return;
|
|
||||||
|
|
||||||
unseenTracker.resetCategory(unseenCategory);
|
|
||||||
|
|
||||||
switch(unseenCategory)
|
|
||||||
{
|
|
||||||
case UnseenItemCategory.FURNI:
|
|
||||||
for(const groupItem of furnitureState.groupItems) groupItem.hasUnseenItems = false;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}, [ furnitureState.groupItems, unseenTracker ]);
|
|
||||||
|
|
||||||
const switchTab = (prevTab: string, nextTab: string) =>
|
|
||||||
{
|
|
||||||
if(nextTab) setCurrentTab(nextTab);
|
|
||||||
|
|
||||||
resetTrackerForTab(prevTab);
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
if(isVisible) return;
|
const linkTracker: ILinkEventTracker = {
|
||||||
|
linkReceived: (url: string) =>
|
||||||
|
{
|
||||||
|
const parts = url.split('/');
|
||||||
|
|
||||||
if(currentTab) resetTrackerForTab(currentTab);
|
if(parts.length < 2) return;
|
||||||
}, [ currentTab, isVisible, resetTrackerForTab ]);
|
|
||||||
|
switch(parts[1])
|
||||||
|
{
|
||||||
|
case 'show':
|
||||||
|
setIsVisible(true);
|
||||||
|
return;
|
||||||
|
case 'hide':
|
||||||
|
setIsVisible(false);
|
||||||
|
return;
|
||||||
|
case 'toggle':
|
||||||
|
setIsVisible(prevValue => !prevValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
eventUrlPrefix: 'inventory/'
|
||||||
|
};
|
||||||
|
|
||||||
|
AddEventLinkTracker(linkTracker);
|
||||||
|
|
||||||
|
return () => RemoveLinkEventTracker(linkTracker);
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
@ -181,53 +145,46 @@ export const InventoryView: FC<{}> = props =>
|
|||||||
{
|
{
|
||||||
if(!isVisible)
|
if(!isVisible)
|
||||||
{
|
{
|
||||||
if(furnitureState.tradeData) setIsVisible(true);
|
// if trading show it
|
||||||
}
|
}
|
||||||
}, [ furnitureState.tradeData, isVisible ]);
|
}, [ isVisible ]);
|
||||||
|
|
||||||
useEffect(() =>
|
const isTrading = false;
|
||||||
{
|
|
||||||
if(!badgeState.badges) return;
|
|
||||||
|
|
||||||
DispatchUiEvent(new InventoryBadgesUpdatedEvent(InventoryBadgesUpdatedEvent.BADGES_UPDATED, badgeState.badges));
|
if(!isVisible) return null;
|
||||||
}, [ badgeState.badges ]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InventoryContextProvider value={ { furnitureState, dispatchFurnitureState, botState, dispatchBotState, petState, dispatchPetState, badgeState, dispatchBadgeState, unseenTracker } }>
|
<NitroCardView uniqueKey={'inventory'} className="nitro-inventory" theme={ isTrading ? 'primary-slim' : '' } >
|
||||||
<InventoryMessageHandler />
|
<NitroCardHeaderView headerText={ LocalizeText('inventory.title') } onCloseClick={ close } />
|
||||||
{ isVisible &&
|
{ !isTrading &&
|
||||||
<NitroCardView uniqueKey={'inventory'} className="nitro-inventory" theme={ furnitureState.tradeData ? 'primary-slim' : '' } >
|
<>
|
||||||
<NitroCardHeaderView headerText={ LocalizeText('inventory.title') } onCloseClick={ close } />
|
<NitroCardTabsView>
|
||||||
{ !furnitureState.tradeData &&
|
{ TABS.map((name, index) =>
|
||||||
<>
|
{
|
||||||
<NitroCardTabsView>
|
const unseenCount = getCount(UNSEEN_CATEGORIES[index]);
|
||||||
{ TABS.map((name, index) =>
|
|
||||||
{
|
|
||||||
const unseenCount = unseenTracker.getCount(UNSEEN_CATEGORIES[index]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NitroCardTabsItemView key={ index } isActive={ (currentTab === name) } onClick={ event => switchTab(currentTab, name) } count={ unseenCount }>
|
<NitroCardTabsItemView key={ index } isActive={ (currentTab === name) } onClick={ event => setCurrentTab(name) } count={ unseenCount }>
|
||||||
{ LocalizeText(name) }
|
{ LocalizeText(name) }
|
||||||
</NitroCardTabsItemView>
|
</NitroCardTabsItemView>
|
||||||
);
|
);
|
||||||
}) }
|
}) }
|
||||||
</NitroCardTabsView>
|
</NitroCardTabsView>
|
||||||
<NitroCardContentView>
|
<NitroCardContentView>
|
||||||
{ (currentTab === TAB_FURNITURE ) &&
|
{ (currentTab === TAB_FURNITURE ) &&
|
||||||
<InventoryFurnitureView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
|
<InventoryFurnitureView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
|
||||||
{ (currentTab === TAB_BOTS ) &&
|
{ (currentTab === TAB_BOTS ) &&
|
||||||
<InventoryBotView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
|
<InventoryBotView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
|
||||||
{ (currentTab === TAB_PETS ) &&
|
{ (currentTab === TAB_PETS ) &&
|
||||||
<InventoryPetView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
|
<InventoryPetView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
|
||||||
{ (currentTab === TAB_BADGES ) &&
|
{ (currentTab === TAB_BADGES ) &&
|
||||||
<InventoryBadgeView /> }
|
<InventoryBadgeView /> }
|
||||||
</NitroCardContentView>
|
</NitroCardContentView>
|
||||||
</> }
|
</> }
|
||||||
{ furnitureState.tradeData &&
|
{ isTrading &&
|
||||||
<NitroCardContentView>
|
<NitroCardContentView>
|
||||||
<InventoryTradeView cancelTrade={ close } />
|
<InventoryTradeView cancelTrade={ close } />
|
||||||
</NitroCardContentView> }
|
</NitroCardContentView> }
|
||||||
</NitroCardView> }
|
</NitroCardView>
|
||||||
</InventoryContextProvider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
export class BadgeItem
|
|
||||||
{
|
|
||||||
private _code: string;
|
|
||||||
private _isUnseen: boolean;
|
|
||||||
|
|
||||||
constructor(code: string)
|
|
||||||
{
|
|
||||||
this._code = code;
|
|
||||||
this._isUnseen = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get code(): string
|
|
||||||
{
|
|
||||||
return this._code;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get isUnseen(): boolean
|
|
||||||
{
|
|
||||||
return this._isUnseen;
|
|
||||||
}
|
|
||||||
|
|
||||||
public set isUnseen(flag: boolean)
|
|
||||||
{
|
|
||||||
this._isUnseen = flag;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
import { BotData } from '@nitrots/nitro-renderer';
|
|
||||||
|
|
||||||
export class BotItem
|
|
||||||
{
|
|
||||||
private _botData: BotData;
|
|
||||||
private _selected: boolean;
|
|
||||||
private _isUnseen: boolean;
|
|
||||||
|
|
||||||
constructor(botData: BotData)
|
|
||||||
{
|
|
||||||
this._botData = botData;
|
|
||||||
this._selected = false;
|
|
||||||
this._isUnseen = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get id(): number
|
|
||||||
{
|
|
||||||
return this._botData.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get botData(): BotData
|
|
||||||
{
|
|
||||||
return this._botData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get selected(): boolean
|
|
||||||
{
|
|
||||||
return this._selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public set selected(flag: boolean)
|
|
||||||
{
|
|
||||||
this._selected = flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get isUnseen(): boolean
|
|
||||||
{
|
|
||||||
return this._isUnseen;
|
|
||||||
}
|
|
||||||
|
|
||||||
public set isUnseen(flag: boolean)
|
|
||||||
{
|
|
||||||
this._isUnseen = flag;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,131 +0,0 @@
|
|||||||
import { BotData, RoomObjectCategory, RoomObjectPlacementSource, RoomObjectType } from '@nitrots/nitro-renderer';
|
|
||||||
import { GetRoomEngine, GetRoomSessionManager } from '../../../api';
|
|
||||||
import { InventoryEvent } from '../../../events';
|
|
||||||
import { DispatchUiEvent } from '../../../hooks';
|
|
||||||
import { BotItem } from './BotItem';
|
|
||||||
import { getPlacingItemId, setObjectMoverRequested, setPlacingItemId } from './InventoryUtilities';
|
|
||||||
import { IUnseenItemTracker } from './unseen/IUnseenItemTracker';
|
|
||||||
import { UnseenItemCategory } from './unseen/UnseenItemCategory';
|
|
||||||
|
|
||||||
export function cancelRoomObjectPlacement(): void
|
|
||||||
{
|
|
||||||
if(getPlacingItemId() === -1) return;
|
|
||||||
|
|
||||||
GetRoomEngine().cancelRoomObjectPlacement();
|
|
||||||
|
|
||||||
setPlacingItemId(-1);
|
|
||||||
setObjectMoverRequested(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function attemptBotPlacement(botItem: BotItem, flag: boolean = false): boolean
|
|
||||||
{
|
|
||||||
const botData = botItem.botData;
|
|
||||||
|
|
||||||
if(!botData) return false;
|
|
||||||
|
|
||||||
const session = GetRoomSessionManager().getSession(1);
|
|
||||||
|
|
||||||
if(!session || !session.isRoomOwner) return false;
|
|
||||||
|
|
||||||
DispatchUiEvent(new InventoryEvent(InventoryEvent.HIDE_INVENTORY));
|
|
||||||
|
|
||||||
if(GetRoomEngine().processRoomObjectPlacement(RoomObjectPlacementSource.INVENTORY, -(botData.id), RoomObjectCategory.UNIT, RoomObjectType.RENTABLE_BOT, botData.figure))
|
|
||||||
{
|
|
||||||
setPlacingItemId(botData.id);
|
|
||||||
setObjectMoverRequested(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAllItemIds(botItems: BotItem[]): number[]
|
|
||||||
{
|
|
||||||
const itemIds: number[] = [];
|
|
||||||
|
|
||||||
for(const botItem of botItems) itemIds.push(botItem.id);
|
|
||||||
|
|
||||||
return itemIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function processBotFragment(set: BotItem[], fragment: BotData[], unseenTracker: IUnseenItemTracker): BotItem[]
|
|
||||||
{
|
|
||||||
const existingIds = getAllItemIds(set);
|
|
||||||
const addedDatas: BotData[] = [];
|
|
||||||
const removedIds: number[] = [];
|
|
||||||
|
|
||||||
for(const botData of fragment) (existingIds.indexOf(botData.id) === -1) && addedDatas.push(botData);
|
|
||||||
|
|
||||||
for(const itemId of existingIds)
|
|
||||||
{
|
|
||||||
let remove = true;
|
|
||||||
|
|
||||||
for(const botData of fragment)
|
|
||||||
{
|
|
||||||
if(botData.id === itemId)
|
|
||||||
{
|
|
||||||
remove = false;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(remove) removedIds.push(itemId);
|
|
||||||
}
|
|
||||||
|
|
||||||
const emptyExistingSet = (existingIds.length === 0);
|
|
||||||
|
|
||||||
for(const id of removedIds) removeBotItemById(id, set);
|
|
||||||
|
|
||||||
for(const botData of addedDatas)
|
|
||||||
{
|
|
||||||
addSingleBotItem(botData, set, unseenTracker.isUnseen(UnseenItemCategory.BOT, botData.id));
|
|
||||||
}
|
|
||||||
|
|
||||||
return set;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removeBotItemById(id: number, set: BotItem[]): BotItem
|
|
||||||
{
|
|
||||||
let index = 0;
|
|
||||||
|
|
||||||
while(index < set.length)
|
|
||||||
{
|
|
||||||
const botItem = set[index];
|
|
||||||
|
|
||||||
if(botItem && (botItem.id === id))
|
|
||||||
{
|
|
||||||
if(getPlacingItemId() === botItem.id)
|
|
||||||
{
|
|
||||||
cancelRoomObjectPlacement();
|
|
||||||
|
|
||||||
setTimeout(() => DispatchUiEvent(new InventoryEvent(InventoryEvent.SHOW_INVENTORY)), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
set.splice(index, 1);
|
|
||||||
|
|
||||||
return botItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function addSingleBotItem(botData: BotData, set: BotItem[], unseen: boolean = true): BotItem
|
|
||||||
{
|
|
||||||
const botItem = new BotItem(botData);
|
|
||||||
|
|
||||||
if(unseen)
|
|
||||||
{
|
|
||||||
botItem.isUnseen = true;
|
|
||||||
|
|
||||||
set.unshift(botItem);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
set.push(botItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
return botItem;
|
|
||||||
}
|
|
@ -1,350 +0,0 @@
|
|||||||
import { FurnitureListItemParser, FurniturePlacePaintComposer, IObjectData, RoomObjectCategory, RoomObjectPlacementSource } from '@nitrots/nitro-renderer';
|
|
||||||
import { GetRoomEngine, SendMessageComposer } from '../../../api';
|
|
||||||
import { CatalogPostMarketplaceOfferEvent, InventoryEvent } from '../../../events';
|
|
||||||
import { DispatchUiEvent } from '../../../hooks';
|
|
||||||
import { FurniCategory } from './FurniCategory';
|
|
||||||
import { FurnitureItem } from './FurnitureItem';
|
|
||||||
import { GroupItem } from './GroupItem';
|
|
||||||
import { getPlacingItemId, setObjectMoverRequested, setPlacingItemId } from './InventoryUtilities';
|
|
||||||
import { IUnseenItemTracker } from './unseen/IUnseenItemTracker';
|
|
||||||
import { UnseenItemCategory } from './unseen/UnseenItemCategory';
|
|
||||||
|
|
||||||
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.FLOOR) || (item.category === FurniCategory.WALL_PAPER) || (item.category === FurniCategory.LANDSCAPE))
|
|
||||||
{
|
|
||||||
if(flag) return false;
|
|
||||||
|
|
||||||
SendMessageComposer(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.POSTER)) // 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)
|
|
||||||
{
|
|
||||||
setPlacingItemId(item.ref);
|
|
||||||
setObjectMoverRequested(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function attemptPlaceMarketplaceOffer(groupItem: GroupItem): boolean
|
|
||||||
{
|
|
||||||
const item = groupItem.getLastItem();
|
|
||||||
|
|
||||||
if(!item) return false;
|
|
||||||
|
|
||||||
if(!item.sellable) return false;
|
|
||||||
|
|
||||||
DispatchUiEvent(new CatalogPostMarketplaceOfferEvent(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
function cancelRoomObjectPlacement(): void
|
|
||||||
{
|
|
||||||
if(getPlacingItemId() === -1) return;
|
|
||||||
|
|
||||||
GetRoomEngine().cancelRoomObjectPlacement();
|
|
||||||
|
|
||||||
setPlacingItemId(-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 mergeFurniFragments(fragment: Map<number, FurnitureListItemParser>, totalFragments: number, fragmentNumber: number, fragments: Map<number, FurnitureListItemParser>[])
|
|
||||||
{
|
|
||||||
if(totalFragments === 1) return fragment;
|
|
||||||
|
|
||||||
fragments[fragmentNumber] = fragment;
|
|
||||||
|
|
||||||
for(const frag of fragments)
|
|
||||||
{
|
|
||||||
if(!frag) return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const merged: Map<number, FurnitureListItemParser> = new Map();
|
|
||||||
|
|
||||||
for(const frag of fragments)
|
|
||||||
{
|
|
||||||
for(const [ key, value ] of frag) merged.set(key, value);
|
|
||||||
|
|
||||||
frag.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
fragments = null;
|
|
||||||
|
|
||||||
return merged;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAllItemIds(groupItems: GroupItem[]): number[]
|
|
||||||
{
|
|
||||||
const itemIds: number[] = [];
|
|
||||||
|
|
||||||
for(const groupItem of groupItems)
|
|
||||||
{
|
|
||||||
let totalCount = groupItem.getTotalCount();
|
|
||||||
|
|
||||||
if(groupItem.category === FurniCategory.POST_IT) totalCount = 1;
|
|
||||||
|
|
||||||
let i = 0;
|
|
||||||
|
|
||||||
while(i < totalCount)
|
|
||||||
{
|
|
||||||
itemIds.push(groupItem.getItemByIndex(i).id);
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return itemIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function processFurniFragment(set: GroupItem[], fragment: Map<number, FurnitureListItemParser>, unseenTracker: IUnseenItemTracker): 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);
|
|
||||||
|
|
||||||
for(const id of removedIds) removeFurniItemById(id, set);
|
|
||||||
|
|
||||||
for(const id of addedIds)
|
|
||||||
{
|
|
||||||
const parser = fragment.get(id);
|
|
||||||
|
|
||||||
if(!parser) continue;
|
|
||||||
|
|
||||||
const item = new FurnitureItem(parser);
|
|
||||||
|
|
||||||
addFurnitureItem(set, item, unseenTracker.isUnseen(UnseenItemCategory.FURNI, id));
|
|
||||||
}
|
|
||||||
|
|
||||||
return set;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removeFurniItemById(id: number, set: GroupItem[]): GroupItem
|
|
||||||
{
|
|
||||||
let index = 0;
|
|
||||||
|
|
||||||
while(index < set.length)
|
|
||||||
{
|
|
||||||
const group = set[index];
|
|
||||||
const item = group.remove(id);
|
|
||||||
|
|
||||||
if(item)
|
|
||||||
{
|
|
||||||
if(getPlacingItemId() === 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, unseen: boolean): void
|
|
||||||
{
|
|
||||||
if(!item.isGroupable)
|
|
||||||
{
|
|
||||||
addSingleFurnitureItem(set, item, unseen);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
addGroupableFurnitureItem(set, item, unseen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addSingleFurnitureItem(set: GroupItem[], item: FurnitureItem, unseen: 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 groupItem = createGroupItem(item.type, item.category, item.stuffData, item.extra);
|
|
||||||
|
|
||||||
groupItem.push(item);
|
|
||||||
|
|
||||||
if(unseen)
|
|
||||||
{
|
|
||||||
groupItem.hasUnseenItems = true;
|
|
||||||
|
|
||||||
set.unshift(groupItem);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
set.push(groupItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
return groupItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
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.POSTER)
|
|
||||||
{
|
|
||||||
if(groupItem.stuffData.getLegacyString() === item.stuffData.getLegacyString())
|
|
||||||
{
|
|
||||||
existingGroup = groupItem;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(item.category === FurniCategory.GUILD_FURNI)
|
|
||||||
{
|
|
||||||
if(item.stuffData.compare(groupItem.stuffData))
|
|
||||||
{
|
|
||||||
existingGroup = groupItem;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
existingGroup = groupItem;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(existingGroup)
|
|
||||||
{
|
|
||||||
existingGroup.push(item);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
existingGroup.push(item);
|
|
||||||
|
|
||||||
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): GroupItem
|
|
||||||
{
|
|
||||||
// const iconImage: HTMLImageElement = null;
|
|
||||||
|
|
||||||
if(category === FurniCategory.WALL_PAPER)
|
|
||||||
{
|
|
||||||
// const icon = this._windowManager.assets.getAssetByName("inventory_furni_icon_wallpaper");
|
|
||||||
// if (icon != null)
|
|
||||||
// {
|
|
||||||
// iconImage = (icon.content as BitmapData).clone();
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(category === FurniCategory.FLOOR)
|
|
||||||
{
|
|
||||||
// const icon = this._windowManager.assets.getAssetByName("inventory_furni_icon_floor");
|
|
||||||
// if (icon != null)
|
|
||||||
// {
|
|
||||||
// iconImage = (icon.content as BitmapData).clone();
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(category === FurniCategory.LANDSCAPE)
|
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
let objectMoverRequested = false;
|
|
||||||
let itemIdInPlacing = -1;
|
|
||||||
|
|
||||||
export function isObjectMoverRequested(): boolean
|
|
||||||
{
|
|
||||||
return objectMoverRequested;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setObjectMoverRequested(flag: boolean)
|
|
||||||
{
|
|
||||||
objectMoverRequested = flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getPlacingItemId(): number
|
|
||||||
{
|
|
||||||
return itemIdInPlacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setPlacingItemId(id: number)
|
|
||||||
{
|
|
||||||
itemIdInPlacing = id;
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
import { PetData } from '@nitrots/nitro-renderer';
|
|
||||||
|
|
||||||
export class PetItem
|
|
||||||
{
|
|
||||||
private _petData: PetData;
|
|
||||||
private _selected: boolean;
|
|
||||||
private _isUnseen: boolean;
|
|
||||||
|
|
||||||
constructor(petData: PetData)
|
|
||||||
{
|
|
||||||
this._petData = petData;
|
|
||||||
this._selected = false;
|
|
||||||
this._isUnseen = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get id(): number
|
|
||||||
{
|
|
||||||
return this._petData.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get petData(): PetData
|
|
||||||
{
|
|
||||||
return this._petData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get selected(): boolean
|
|
||||||
{
|
|
||||||
return this._selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public set selected(flag: boolean)
|
|
||||||
{
|
|
||||||
this._selected = flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get isUnseen(): boolean
|
|
||||||
{
|
|
||||||
return this._isUnseen;
|
|
||||||
}
|
|
||||||
|
|
||||||
public set isUnseen(flag: boolean)
|
|
||||||
{
|
|
||||||
this._isUnseen = flag;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,150 +0,0 @@
|
|||||||
import { PetData, RoomObjectCategory, RoomObjectPlacementSource, RoomObjectType } from '@nitrots/nitro-renderer';
|
|
||||||
import { GetRoomEngine, GetRoomSessionManager } from '../../../api';
|
|
||||||
import { InventoryEvent } from '../../../events';
|
|
||||||
import { DispatchUiEvent } from '../../../hooks';
|
|
||||||
import { getPlacingItemId, setObjectMoverRequested, setPlacingItemId } from './InventoryUtilities';
|
|
||||||
import { PetItem } from './PetItem';
|
|
||||||
import { IUnseenItemTracker } from './unseen/IUnseenItemTracker';
|
|
||||||
import { UnseenItemCategory } from './unseen/UnseenItemCategory';
|
|
||||||
|
|
||||||
export function cancelRoomObjectPlacement(): void
|
|
||||||
{
|
|
||||||
if(getPlacingItemId() === -1) return;
|
|
||||||
|
|
||||||
GetRoomEngine().cancelRoomObjectPlacement();
|
|
||||||
|
|
||||||
setPlacingItemId(-1);
|
|
||||||
setObjectMoverRequested(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function attemptPetPlacement(petItem: PetItem, flag: boolean = false): boolean
|
|
||||||
{
|
|
||||||
const petData = petItem.petData;
|
|
||||||
|
|
||||||
if(!petData) return false;
|
|
||||||
|
|
||||||
const session = GetRoomSessionManager().getSession(1);
|
|
||||||
|
|
||||||
if(!session) return false;
|
|
||||||
|
|
||||||
if(!session.isRoomOwner)
|
|
||||||
{
|
|
||||||
if(!session.allowPets) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DispatchUiEvent(new InventoryEvent(InventoryEvent.HIDE_INVENTORY));
|
|
||||||
|
|
||||||
if(GetRoomEngine().processRoomObjectPlacement(RoomObjectPlacementSource.INVENTORY, -(petData.id), RoomObjectCategory.UNIT, RoomObjectType.PET, petData.figureData.figuredata))
|
|
||||||
{
|
|
||||||
setPlacingItemId(petData.id);
|
|
||||||
setObjectMoverRequested(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function mergePetFragments(fragment: Map<number, PetData>, totalFragments: number, fragmentNumber: number, fragments: Map<number, PetData>[])
|
|
||||||
{
|
|
||||||
if(totalFragments === 1) return fragment;
|
|
||||||
|
|
||||||
fragments[fragmentNumber] = fragment;
|
|
||||||
|
|
||||||
for(const frag of fragments)
|
|
||||||
{
|
|
||||||
if(!frag) return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const merged: Map<number, PetData> = new Map();
|
|
||||||
|
|
||||||
for(const frag of fragments)
|
|
||||||
{
|
|
||||||
for(const [ key, value ] of frag) merged.set(key, value);
|
|
||||||
|
|
||||||
frag.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
fragments = null;
|
|
||||||
|
|
||||||
return merged;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAllItemIds(petItems: PetItem[]): number[]
|
|
||||||
{
|
|
||||||
const itemIds: number[] = [];
|
|
||||||
|
|
||||||
for(const petItem of petItems) itemIds.push(petItem.id);
|
|
||||||
|
|
||||||
return itemIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function processPetFragment(set: PetItem[], fragment: Map<number, PetData>, unseenTracker: IUnseenItemTracker): PetItem[]
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
for(const id of removedIds) removePetItemById(id, set);
|
|
||||||
|
|
||||||
for(const id of addedIds)
|
|
||||||
{
|
|
||||||
const parser = fragment.get(id);
|
|
||||||
|
|
||||||
if(!parser) continue;
|
|
||||||
|
|
||||||
addSinglePetItem(parser, set, unseenTracker.isUnseen(UnseenItemCategory.PET, parser.id));
|
|
||||||
}
|
|
||||||
|
|
||||||
return set;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removePetItemById(id: number, set: PetItem[]): PetItem
|
|
||||||
{
|
|
||||||
let index = 0;
|
|
||||||
|
|
||||||
while(index < set.length)
|
|
||||||
{
|
|
||||||
const petItem = set[index];
|
|
||||||
|
|
||||||
if(petItem && (petItem.id === id))
|
|
||||||
{
|
|
||||||
if(getPlacingItemId() === petItem.id)
|
|
||||||
{
|
|
||||||
cancelRoomObjectPlacement();
|
|
||||||
|
|
||||||
setTimeout(() => DispatchUiEvent(new InventoryEvent(InventoryEvent.SHOW_INVENTORY)), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
set.splice(index, 1);
|
|
||||||
|
|
||||||
return petItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function addSinglePetItem(petData: PetData, set: PetItem[], unseen: boolean = true): PetItem
|
|
||||||
{
|
|
||||||
const petItem = new PetItem(petData);
|
|
||||||
|
|
||||||
if(unseen)
|
|
||||||
{
|
|
||||||
petItem.isUnseen = true;
|
|
||||||
|
|
||||||
set.unshift(petItem);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
set.push(petItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
return petItem;
|
|
||||||
}
|
|
@ -1,146 +0,0 @@
|
|||||||
import { UnseenResetCategoryComposer, UnseenResetItemsComposer } from '@nitrots/nitro-renderer';
|
|
||||||
import { SendMessageComposer } from '../../../../api';
|
|
||||||
import { UnseenItemTrackerUpdateEvent } from '../../../../events';
|
|
||||||
import { DispatchUiEvent } from '../../../../hooks';
|
|
||||||
import { IUnseenItemTracker } from './IUnseenItemTracker';
|
|
||||||
|
|
||||||
export class UnseenItemTracker implements IUnseenItemTracker
|
|
||||||
{
|
|
||||||
private _unseenItems: Map<number, number[]> = new Map();
|
|
||||||
|
|
||||||
public dispose(): void
|
|
||||||
{
|
|
||||||
this._unseenItems.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public resetCategory(category: number): boolean
|
|
||||||
{
|
|
||||||
if(!this.getCount(category)) return false;
|
|
||||||
|
|
||||||
this._unseenItems.delete(category);
|
|
||||||
|
|
||||||
this.dispatchUpdateEvent();
|
|
||||||
|
|
||||||
this.sendResetCategoryMessage(category);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public resetItems(category: number, itemIds: number[]): boolean
|
|
||||||
{
|
|
||||||
if(!this.getCount(category)) return false;
|
|
||||||
|
|
||||||
const existing = this._unseenItems.get(category);
|
|
||||||
|
|
||||||
for(const itemId of itemIds)
|
|
||||||
{
|
|
||||||
existing.splice(existing.indexOf(itemId), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dispatchUpdateEvent();
|
|
||||||
|
|
||||||
this.sendResetItemsMessage(category, itemIds);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public resetCategoryIfEmpty(category: number): boolean
|
|
||||||
{
|
|
||||||
if(this.getCount(category)) return false;
|
|
||||||
|
|
||||||
this._unseenItems.delete(category);
|
|
||||||
|
|
||||||
this.dispatchUpdateEvent();
|
|
||||||
|
|
||||||
this.sendResetCategoryMessage(category);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public isUnseen(category: number, itemId: number): boolean
|
|
||||||
{
|
|
||||||
if(!this._unseenItems.get(category)) return false;
|
|
||||||
|
|
||||||
const items = this._unseenItems.get(category);
|
|
||||||
|
|
||||||
return (items.indexOf(itemId) >= 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public removeUnseen(category: number, itemId: number): boolean
|
|
||||||
{
|
|
||||||
if(!this._unseenItems.get(category)) return false;
|
|
||||||
|
|
||||||
const items = this._unseenItems.get(category);
|
|
||||||
const index = items.indexOf(itemId);
|
|
||||||
|
|
||||||
if(index === -1) return false;
|
|
||||||
|
|
||||||
items.splice(index, 1);
|
|
||||||
|
|
||||||
this.dispatchUpdateEvent();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getIds(category: number): number[]
|
|
||||||
{
|
|
||||||
if(!this._unseenItems) return [];
|
|
||||||
|
|
||||||
return this._unseenItems.get(category);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getCount(category: number): number
|
|
||||||
{
|
|
||||||
if(!this._unseenItems.get(category)) return 0;
|
|
||||||
|
|
||||||
return this._unseenItems.get(category).length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getFullCount(): number
|
|
||||||
{
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
for(const key of this._unseenItems.keys())
|
|
||||||
{
|
|
||||||
count += this.getCount(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public addItems(category: number, itemIds: number[]): void
|
|
||||||
{
|
|
||||||
if(!itemIds) return;
|
|
||||||
|
|
||||||
let unseenItems = this._unseenItems.get(category);
|
|
||||||
|
|
||||||
if(!unseenItems)
|
|
||||||
{
|
|
||||||
unseenItems = [];
|
|
||||||
|
|
||||||
this._unseenItems.set(category, unseenItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(const itemId of itemIds)
|
|
||||||
{
|
|
||||||
if(unseenItems.indexOf(itemId) === -1) unseenItems.push(itemId);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dispatchUpdateEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
private dispatchUpdateEvent(): void
|
|
||||||
{
|
|
||||||
DispatchUiEvent(new UnseenItemTrackerUpdateEvent(this.getFullCount()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private sendResetCategoryMessage(category: number): void
|
|
||||||
{
|
|
||||||
SendMessageComposer(new UnseenResetCategoryComposer(category));
|
|
||||||
}
|
|
||||||
|
|
||||||
private sendResetItemsMessage(category: number, itemIds: number[]): void
|
|
||||||
{
|
|
||||||
SendMessageComposer(new UnseenResetItemsComposer(category, ...itemIds));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,128 +0,0 @@
|
|||||||
import { SetActivatedBadgesComposer } from '@nitrots/nitro-renderer';
|
|
||||||
import { Reducer } from 'react';
|
|
||||||
import { GetConfiguration, SendMessageComposer } from '../../../api';
|
|
||||||
|
|
||||||
export interface IInventoryBadgeState
|
|
||||||
{
|
|
||||||
needsBadgeUpdate: boolean;
|
|
||||||
badge: string;
|
|
||||||
badges: string[];
|
|
||||||
activeBadges: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IInventoryBadgeAction
|
|
||||||
{
|
|
||||||
type: string;
|
|
||||||
payload: {
|
|
||||||
flag?: boolean;
|
|
||||||
badgeCode?: string;
|
|
||||||
badgeCodes?: string[];
|
|
||||||
activeBadgeCodes?: string[];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class InventoryBadgeActions
|
|
||||||
{
|
|
||||||
public static SET_NEEDS_UPDATE: string = 'IBA_SET_NEEDS_UPDATE';
|
|
||||||
public static SET_BADGE: string = 'IBA_SET_BADGE';
|
|
||||||
public static SET_BADGES: string = 'IBA_SET_BADGES';
|
|
||||||
public static ADD_BADGE: string = 'IBA_ADD_BADGE';
|
|
||||||
public static ADD_ACTIVE_BADGE: string = 'IBA_ADD_ACTIVE_BADGE';
|
|
||||||
public static REMOVE_ACTIVE_BADGE: string = 'IBA_REMOVE_ACTIVE_BADGE';
|
|
||||||
}
|
|
||||||
|
|
||||||
export const initialInventoryBadge: IInventoryBadgeState = {
|
|
||||||
needsBadgeUpdate: true,
|
|
||||||
badge: null,
|
|
||||||
badges: [],
|
|
||||||
activeBadges: []
|
|
||||||
}
|
|
||||||
|
|
||||||
export const InventoryBadgeReducer: Reducer<IInventoryBadgeState, IInventoryBadgeAction> = (state, action) =>
|
|
||||||
{
|
|
||||||
switch(action.type)
|
|
||||||
{
|
|
||||||
case InventoryBadgeActions.SET_NEEDS_UPDATE:
|
|
||||||
return { ...state, needsBadgeUpdate: (action.payload.flag || false) };
|
|
||||||
case InventoryBadgeActions.SET_BADGE: {
|
|
||||||
let badge = (action.payload.badgeCode || state.badge || null);
|
|
||||||
|
|
||||||
let index = 0;
|
|
||||||
|
|
||||||
if(badge)
|
|
||||||
{
|
|
||||||
const foundIndex = state.badges.indexOf(badge);
|
|
||||||
|
|
||||||
if(foundIndex > -1) index = foundIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
badge = (state.badges[index] || null);
|
|
||||||
|
|
||||||
return { ...state, badge };
|
|
||||||
}
|
|
||||||
case InventoryBadgeActions.SET_BADGES: {
|
|
||||||
const badges: string[] = [];
|
|
||||||
const activeBadges: string[] = [];
|
|
||||||
|
|
||||||
const badgeCodes = action.payload.badgeCodes;
|
|
||||||
const activeBadgeCodes = action.payload.activeBadgeCodes;
|
|
||||||
|
|
||||||
for(const badgeCode of badgeCodes)
|
|
||||||
{
|
|
||||||
const wearingIndex = activeBadgeCodes.indexOf(badgeCode);
|
|
||||||
|
|
||||||
badges.push(badgeCode);
|
|
||||||
|
|
||||||
if(wearingIndex >= 0) activeBadges.push(badgeCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return { ...state, badges, activeBadges };
|
|
||||||
}
|
|
||||||
case InventoryBadgeActions.ADD_BADGE: {
|
|
||||||
const badges = [ ...state.badges ];
|
|
||||||
const badge = (action.payload.badgeCode);
|
|
||||||
|
|
||||||
if(badges.indexOf(badge) === -1) badges.push(badge);
|
|
||||||
|
|
||||||
return { ...state, badges };
|
|
||||||
}
|
|
||||||
case InventoryBadgeActions.ADD_ACTIVE_BADGE: {
|
|
||||||
const badgeCode = action.payload.badgeCode;
|
|
||||||
|
|
||||||
if(state.activeBadges.indexOf(badgeCode) >= 0) return state;
|
|
||||||
|
|
||||||
const activeBadges = [ ...state.activeBadges ];
|
|
||||||
|
|
||||||
activeBadges.push(badgeCode);
|
|
||||||
|
|
||||||
const composer = new SetActivatedBadgesComposer();
|
|
||||||
|
|
||||||
for(let i = 0; i < GetConfiguration<number>('user.badges.max.slots', 5); i++) composer.addActivatedBadge(activeBadges[i] || null);
|
|
||||||
|
|
||||||
SendMessageComposer(composer);
|
|
||||||
|
|
||||||
return { ...state, activeBadges };
|
|
||||||
}
|
|
||||||
case InventoryBadgeActions.REMOVE_ACTIVE_BADGE: {
|
|
||||||
const badgeCode = action.payload.badgeCode;
|
|
||||||
|
|
||||||
const index = state.activeBadges.indexOf(badgeCode);
|
|
||||||
|
|
||||||
if(index === -1) return state;
|
|
||||||
|
|
||||||
const activeBadges = [ ...state.activeBadges ];
|
|
||||||
|
|
||||||
activeBadges.splice(index, 1);
|
|
||||||
|
|
||||||
const composer = new SetActivatedBadgesComposer();
|
|
||||||
|
|
||||||
for(let i = 0; i < GetConfiguration<number>('user.badges.max.slots', 5); i++) composer.addActivatedBadge(activeBadges[i] || null);
|
|
||||||
|
|
||||||
SendMessageComposer(composer);
|
|
||||||
|
|
||||||
return { ...state, activeBadges };
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
import { BotData } from '@nitrots/nitro-renderer';
|
|
||||||
import { Reducer } from 'react';
|
|
||||||
import { BotItem } from '../common/BotItem';
|
|
||||||
import { addSingleBotItem, processBotFragment, removeBotItemById } from '../common/BotUtilities';
|
|
||||||
import { IUnseenItemTracker } from '../common/unseen/IUnseenItemTracker';
|
|
||||||
|
|
||||||
export interface IInventoryBotState
|
|
||||||
{
|
|
||||||
needsBotUpdate: boolean;
|
|
||||||
botItem: BotItem;
|
|
||||||
botItems: BotItem[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IInventoryBotAction
|
|
||||||
{
|
|
||||||
type: string;
|
|
||||||
payload: {
|
|
||||||
flag?: boolean;
|
|
||||||
botItem?: BotItem;
|
|
||||||
botId?: number;
|
|
||||||
botData?: BotData;
|
|
||||||
fragment?: BotData[];
|
|
||||||
unseenTracker?: IUnseenItemTracker;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class InventoryBotActions
|
|
||||||
{
|
|
||||||
public static SET_NEEDS_UPDATE: string = 'IBA_SET_NEEDS_UPDATE';
|
|
||||||
public static SET_BOT_ITEM: string = 'IBA_SET_BOT_ITEM';
|
|
||||||
public static PROCESS_FRAGMENT: string = 'IBA_PROCESS_FRAGMENT';
|
|
||||||
public static ADD_BOT: string = 'IBA_ADD_BOT';
|
|
||||||
public static REMOVE_BOT: string = 'IBA_REMOVE_BOT';
|
|
||||||
}
|
|
||||||
|
|
||||||
export const initialInventoryBot: IInventoryBotState = {
|
|
||||||
needsBotUpdate: true,
|
|
||||||
botItem: null,
|
|
||||||
botItems: []
|
|
||||||
}
|
|
||||||
|
|
||||||
export const InventoryBotReducer: Reducer<IInventoryBotState, IInventoryBotAction> = (state, action) =>
|
|
||||||
{
|
|
||||||
switch(action.type)
|
|
||||||
{
|
|
||||||
case InventoryBotActions.SET_NEEDS_UPDATE:
|
|
||||||
return { ...state, needsBotUpdate: (action.payload.flag || false) };
|
|
||||||
case InventoryBotActions.SET_BOT_ITEM: {
|
|
||||||
let botItem = (action.payload.botItem || state.botItem || null);
|
|
||||||
|
|
||||||
let index = 0;
|
|
||||||
|
|
||||||
if(botItem)
|
|
||||||
{
|
|
||||||
const foundIndex = state.botItems.indexOf(botItem);
|
|
||||||
|
|
||||||
if(foundIndex > -1) index = foundIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
botItem = (state.botItems[index] || null);
|
|
||||||
|
|
||||||
return { ...state, botItem };
|
|
||||||
}
|
|
||||||
case InventoryBotActions.PROCESS_FRAGMENT: {
|
|
||||||
const botItems = [ ...state.botItems ];
|
|
||||||
|
|
||||||
processBotFragment(botItems, action.payload.fragment, (action.payload.unseenTracker || null));
|
|
||||||
|
|
||||||
return { ...state, botItems };
|
|
||||||
}
|
|
||||||
case InventoryBotActions.ADD_BOT: {
|
|
||||||
const botItems = [ ...state.botItems ];
|
|
||||||
|
|
||||||
addSingleBotItem(action.payload.botData, botItems, true);
|
|
||||||
|
|
||||||
return { ...state, botItems };
|
|
||||||
}
|
|
||||||
case InventoryBotActions.REMOVE_BOT: {
|
|
||||||
const botItems = [ ...state.botItems ];
|
|
||||||
|
|
||||||
removeBotItemById(action.payload.botId, botItems);
|
|
||||||
|
|
||||||
return { ...state, botItems };
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,273 +0,0 @@
|
|||||||
import { AdvancedMap, FurnitureListItemParser, TradingListItemParser } from '@nitrots/nitro-renderer';
|
|
||||||
import { Reducer } from 'react';
|
|
||||||
import { FurnitureItem } from '../common/FurnitureItem';
|
|
||||||
import { addFurnitureItem, processFurniFragment, removeFurniItemById } from '../common/FurnitureUtilities';
|
|
||||||
import { GroupItem } from '../common/GroupItem';
|
|
||||||
import { TradeState } from '../common/TradeState';
|
|
||||||
import { TradeUserData } from '../common/TradeUserData';
|
|
||||||
import { parseTradeItems } from '../common/TradingUtilities';
|
|
||||||
import { IUnseenItemTracker } from '../common/unseen/IUnseenItemTracker';
|
|
||||||
|
|
||||||
export interface IInventoryFurnitureState
|
|
||||||
{
|
|
||||||
needsFurniUpdate: boolean;
|
|
||||||
groupItem: GroupItem;
|
|
||||||
groupItems: GroupItem[];
|
|
||||||
tradeData: {
|
|
||||||
ownUser: TradeUserData;
|
|
||||||
otherUser: TradeUserData;
|
|
||||||
state: number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IInventoryFurnitureAction
|
|
||||||
{
|
|
||||||
type: string;
|
|
||||||
payload: {
|
|
||||||
flag?: boolean;
|
|
||||||
groupItem?: GroupItem;
|
|
||||||
parsers?: FurnitureListItemParser[];
|
|
||||||
itemId?: number;
|
|
||||||
fragment?: Map<number, FurnitureListItemParser>;
|
|
||||||
ownTradeUser?: TradeUserData;
|
|
||||||
otherTradeUser?: TradeUserData;
|
|
||||||
tradeState?: number;
|
|
||||||
userId?: number;
|
|
||||||
tradeParser?: TradingListItemParser;
|
|
||||||
unseenTracker?: IUnseenItemTracker;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class InventoryFurnitureActions
|
|
||||||
{
|
|
||||||
public static SET_NEEDS_UPDATE: string = 'IFA_SET_NEEDS_UPDATE';
|
|
||||||
public static SET_GROUP_ITEM: string = 'IFA_SET_GROUP_ITEM';
|
|
||||||
public static PROCESS_FRAGMENT: string = 'IFA_PROCESS_FRAGMENT';
|
|
||||||
public static ADD_OR_UPDATE_FURNITURE: string = 'IFA_ADD_OR_UPDATE_FURNITURE';
|
|
||||||
public static REMOVE_FURNITURE: string = 'IFA_REMOVE_FURNITURE';
|
|
||||||
public static SET_TRADE_DATA: string = 'IFA_SET_TRADE_DATA';
|
|
||||||
public static SET_TRADE_STATE: string = 'IFA_SET_TRADE_STATE';
|
|
||||||
public static SET_TRADE_ACCEPTANCE: string = 'FA_SET_TRADE_ACCEPTANCE';
|
|
||||||
public static CLOSE_TRADE: string = 'IFA_CLOSE_STRING';
|
|
||||||
public static UPDATE_TRADE: string = 'IFA_UPDATE_TRADE';
|
|
||||||
}
|
|
||||||
|
|
||||||
export const initialInventoryFurniture: IInventoryFurnitureState = {
|
|
||||||
needsFurniUpdate: true,
|
|
||||||
groupItem: null,
|
|
||||||
groupItems: [],
|
|
||||||
tradeData: null
|
|
||||||
}
|
|
||||||
|
|
||||||
export const InventoryFurnitureReducer: Reducer<IInventoryFurnitureState, IInventoryFurnitureAction> = (state, action) =>
|
|
||||||
{
|
|
||||||
switch(action.type)
|
|
||||||
{
|
|
||||||
case InventoryFurnitureActions.SET_NEEDS_UPDATE:
|
|
||||||
return { ...state, needsFurniUpdate: (action.payload.flag || false) };
|
|
||||||
case InventoryFurnitureActions.SET_GROUP_ITEM: {
|
|
||||||
let groupItem = (action.payload.groupItem || state.groupItem || null);
|
|
||||||
|
|
||||||
let index = 0;
|
|
||||||
|
|
||||||
if(groupItem)
|
|
||||||
{
|
|
||||||
const foundIndex = state.groupItems.indexOf(groupItem);
|
|
||||||
|
|
||||||
if(foundIndex > -1) index = foundIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
groupItem = (state.groupItems[index] || null);
|
|
||||||
|
|
||||||
return { ...state, groupItem };
|
|
||||||
}
|
|
||||||
case InventoryFurnitureActions.PROCESS_FRAGMENT: {
|
|
||||||
const groupItems = [ ...state.groupItems ];
|
|
||||||
|
|
||||||
processFurniFragment(groupItems, (action.payload.fragment || null), (action.payload.unseenTracker || null));
|
|
||||||
|
|
||||||
return { ...state, groupItems };
|
|
||||||
}
|
|
||||||
case InventoryFurnitureActions.ADD_OR_UPDATE_FURNITURE: {
|
|
||||||
const groupItems = [ ...state.groupItems ];
|
|
||||||
|
|
||||||
for(const item of action.payload.parsers)
|
|
||||||
{
|
|
||||||
let i = 0;
|
|
||||||
let groupItem: GroupItem = null;
|
|
||||||
|
|
||||||
while(i < groupItems.length)
|
|
||||||
{
|
|
||||||
const group = groupItems[i];
|
|
||||||
|
|
||||||
let j = 0;
|
|
||||||
|
|
||||||
while(j < group.items.length)
|
|
||||||
{
|
|
||||||
const furniture = group.items[j];
|
|
||||||
|
|
||||||
if(furniture.id === item.itemId)
|
|
||||||
{
|
|
||||||
furniture.update(item);
|
|
||||||
|
|
||||||
const newFurniture = [ ...group.items ];
|
|
||||||
|
|
||||||
newFurniture[j] = furniture;
|
|
||||||
|
|
||||||
group.items = newFurniture;
|
|
||||||
|
|
||||||
groupItem = group;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
j++
|
|
||||||
}
|
|
||||||
|
|
||||||
if(groupItem) break;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(groupItem)
|
|
||||||
{
|
|
||||||
groupItem.hasUnseenItems = true;
|
|
||||||
|
|
||||||
groupItems[i] = Object.create(groupItem);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const furniture = new FurnitureItem(item);
|
|
||||||
|
|
||||||
addFurnitureItem(groupItems, furniture, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return { ...state, groupItems };
|
|
||||||
}
|
|
||||||
case InventoryFurnitureActions.REMOVE_FURNITURE: {
|
|
||||||
const groupItems = [ ...state.groupItems ];
|
|
||||||
|
|
||||||
removeFurniItemById(action.payload.itemId, groupItems);
|
|
||||||
|
|
||||||
return { ...state, groupItems };
|
|
||||||
}
|
|
||||||
case InventoryFurnitureActions.SET_TRADE_DATA: {
|
|
||||||
const tradeData = { ...state.tradeData };
|
|
||||||
|
|
||||||
tradeData.ownUser = (action.payload.ownTradeUser || null);
|
|
||||||
tradeData.otherUser = (action.payload.otherTradeUser || null);
|
|
||||||
tradeData.state = TradeState.TRADING_STATE_RUNNING;
|
|
||||||
|
|
||||||
return { ...state, tradeData };
|
|
||||||
}
|
|
||||||
case InventoryFurnitureActions.SET_TRADE_STATE: {
|
|
||||||
const tradeData = { ...state.tradeData };
|
|
||||||
|
|
||||||
tradeData.state = (action.payload.tradeState || TradeState.TRADING_STATE_RUNNING);
|
|
||||||
|
|
||||||
return { ...state, tradeData };
|
|
||||||
}
|
|
||||||
case InventoryFurnitureActions.SET_TRADE_ACCEPTANCE: {
|
|
||||||
const tradeData = { ...state.tradeData };
|
|
||||||
|
|
||||||
const userId = (action.payload.userId || -1);
|
|
||||||
|
|
||||||
if(tradeData.ownUser.userId === userId)
|
|
||||||
{
|
|
||||||
const ownUserData = Object.assign({}, tradeData.ownUser);
|
|
||||||
|
|
||||||
ownUserData.accepts = (action.payload.flag || false);
|
|
||||||
|
|
||||||
tradeData.ownUser = ownUserData;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(tradeData.otherUser.userId === userId)
|
|
||||||
{
|
|
||||||
const otherUserData = Object.assign({}, tradeData.otherUser);
|
|
||||||
|
|
||||||
otherUserData.accepts = (action.payload.flag || false);
|
|
||||||
|
|
||||||
tradeData.otherUser = otherUserData;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { ...state, tradeData };
|
|
||||||
}
|
|
||||||
case InventoryFurnitureActions.CLOSE_TRADE: {
|
|
||||||
const tradeData = null;
|
|
||||||
|
|
||||||
return { ...state, tradeData };
|
|
||||||
}
|
|
||||||
case InventoryFurnitureActions.UPDATE_TRADE: {
|
|
||||||
const tradeData = { ...state.tradeData };
|
|
||||||
const groupItems = [ ...state.groupItems ];
|
|
||||||
|
|
||||||
const parser = (action.payload.tradeParser || null);
|
|
||||||
|
|
||||||
if(parser)
|
|
||||||
{
|
|
||||||
const firstUserItems: AdvancedMap<string, GroupItem> = new AdvancedMap();
|
|
||||||
const secondUserItems: AdvancedMap<string, GroupItem> = new AdvancedMap();
|
|
||||||
|
|
||||||
parseTradeItems(parser.firstUserItemArray, firstUserItems);
|
|
||||||
parseTradeItems(parser.secondUserItemArray, secondUserItems);
|
|
||||||
|
|
||||||
const ownUserData = Object.assign({}, tradeData.ownUser);
|
|
||||||
const otherUserData = Object.assign({}, tradeData.otherUser);
|
|
||||||
|
|
||||||
if(tradeData.ownUser.userId === parser.firstUserID)
|
|
||||||
{
|
|
||||||
ownUserData.creditsCount = parser.firstUserNumCredits;
|
|
||||||
ownUserData.itemCount = parser.firstUserNumItems;
|
|
||||||
ownUserData.items = firstUserItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(tradeData.ownUser.userId === parser.secondUserID)
|
|
||||||
{
|
|
||||||
ownUserData.creditsCount = parser.secondUserNumCredits;
|
|
||||||
ownUserData.itemCount = parser.secondUserNumItems;
|
|
||||||
ownUserData.items = secondUserItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tradeData.otherUser.userId === parser.firstUserID)
|
|
||||||
{
|
|
||||||
otherUserData.creditsCount = parser.firstUserNumCredits;
|
|
||||||
otherUserData.itemCount = parser.firstUserNumItems;
|
|
||||||
otherUserData.items = firstUserItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(tradeData.otherUser.userId === parser.secondUserID)
|
|
||||||
{
|
|
||||||
otherUserData.creditsCount = parser.secondUserNumCredits;
|
|
||||||
otherUserData.itemCount = parser.secondUserNumItems;
|
|
||||||
otherUserData.items = secondUserItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
tradeData.ownUser = ownUserData;
|
|
||||||
tradeData.otherUser = otherUserData;
|
|
||||||
|
|
||||||
const tradeIds: number[] = [];
|
|
||||||
|
|
||||||
for(const groupItem of ownUserData.items.getValues())
|
|
||||||
{
|
|
||||||
let i = 0;
|
|
||||||
|
|
||||||
while(i < groupItem.getTotalCount())
|
|
||||||
{
|
|
||||||
const item = groupItem.getItemByIndex(i);
|
|
||||||
|
|
||||||
if(item) tradeIds.push(item.ref);
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(const groupItem of groupItems) groupItem.lockItemIds(tradeIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
return { ...state, groupItems, tradeData };
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
import { PetData } from '@nitrots/nitro-renderer';
|
|
||||||
import { Reducer } from 'react';
|
|
||||||
import { PetItem } from '../common/PetItem';
|
|
||||||
import { addSinglePetItem, processPetFragment, removePetItemById } from '../common/PetUtilities';
|
|
||||||
import { IUnseenItemTracker } from '../common/unseen/IUnseenItemTracker';
|
|
||||||
|
|
||||||
export interface IInventoryPetState
|
|
||||||
{
|
|
||||||
needsPetUpdate: boolean;
|
|
||||||
petItem: PetItem;
|
|
||||||
petItems: PetItem[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IInventoryPetAction
|
|
||||||
{
|
|
||||||
type: string;
|
|
||||||
payload: {
|
|
||||||
flag?: boolean;
|
|
||||||
petItem?: PetItem;
|
|
||||||
petId?: number;
|
|
||||||
petData?: PetData;
|
|
||||||
fragment?: Map<number, PetData>;
|
|
||||||
unseenTracker?: IUnseenItemTracker;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class InventoryPetActions
|
|
||||||
{
|
|
||||||
public static SET_NEEDS_UPDATE: string = 'IPA_SET_NEEDS_UPDATE';
|
|
||||||
public static SET_PET_ITEM: string = 'IPA_SET_PET_ITEM';
|
|
||||||
public static PROCESS_FRAGMENT: string = 'IPA_PROCESS_FRAGMENT';
|
|
||||||
public static ADD_PET: string = 'IPA_ADD_PET';
|
|
||||||
public static REMOVE_PET: string = 'IPA_REMOVE_PET';
|
|
||||||
}
|
|
||||||
|
|
||||||
export const initialInventoryPet: IInventoryPetState = {
|
|
||||||
needsPetUpdate: true,
|
|
||||||
petItem: null,
|
|
||||||
petItems: []
|
|
||||||
}
|
|
||||||
|
|
||||||
export const InventoryPetReducer: Reducer<IInventoryPetState, IInventoryPetAction> = (state, action) =>
|
|
||||||
{
|
|
||||||
switch(action.type)
|
|
||||||
{
|
|
||||||
case InventoryPetActions.SET_NEEDS_UPDATE:
|
|
||||||
return { ...state, needsPetUpdate: (action.payload.flag || false) };
|
|
||||||
case InventoryPetActions.SET_PET_ITEM: {
|
|
||||||
let petItem = (action.payload.petItem || state.petItem || null);
|
|
||||||
|
|
||||||
let index = 0;
|
|
||||||
|
|
||||||
if(petItem)
|
|
||||||
{
|
|
||||||
const foundIndex = state.petItems.indexOf(petItem);
|
|
||||||
|
|
||||||
if(foundIndex > -1) index = foundIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
petItem = (state.petItems[index] || null);
|
|
||||||
|
|
||||||
return { ...state, petItem };
|
|
||||||
}
|
|
||||||
case InventoryPetActions.PROCESS_FRAGMENT: {
|
|
||||||
const petItems = [ ...state.petItems ];
|
|
||||||
|
|
||||||
processPetFragment(petItems, (action.payload.fragment || null), (action.payload.unseenTracker || null));
|
|
||||||
|
|
||||||
return { ...state, petItems };
|
|
||||||
}
|
|
||||||
case InventoryPetActions.ADD_PET: {
|
|
||||||
const petItems = [ ...state.petItems ];
|
|
||||||
|
|
||||||
addSinglePetItem(action.payload.petData, petItems, true);
|
|
||||||
|
|
||||||
return { ...state, petItems };
|
|
||||||
}
|
|
||||||
case InventoryPetActions.REMOVE_PET: {
|
|
||||||
const petItems = [ ...state.petItems ];
|
|
||||||
|
|
||||||
removePetItemById(action.payload.petId, petItems);
|
|
||||||
|
|
||||||
return { ...state, petItems };
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
75
src/components/inventory/views/InventoryBadgeView.tsx
Normal file
75
src/components/inventory/views/InventoryBadgeView.tsx
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import { FC, useEffect } from 'react';
|
||||||
|
import { IBadgeItem, LocalizeBadgeName, LocalizeText, UnseenItemCategory } from '../../../api';
|
||||||
|
import { AutoGrid, Button, Column, Flex, Grid, LayoutBadgeImageView, LayoutGridItem, Text } from '../../../common';
|
||||||
|
import { useSharedInventoryBadges, useSharedInventoryUnseenTracker } from '../../../hooks';
|
||||||
|
|
||||||
|
export const InventoryBadgeView: FC<{}> = props =>
|
||||||
|
{
|
||||||
|
const { badges = [], activeBadges = [], selectedBadge = null, isWearingBadge = null, canWearBadges = null, toggleBadge = null, selectBadge = null } = useSharedInventoryBadges();
|
||||||
|
const { getCount = null, resetCategory = null, isUnseen = null, removeUnseen = null } = useSharedInventoryUnseenTracker();
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!badges || !badges.length) return;
|
||||||
|
|
||||||
|
return () =>
|
||||||
|
{
|
||||||
|
const count = getCount(UnseenItemCategory.BADGE);
|
||||||
|
|
||||||
|
if(!count) return;
|
||||||
|
|
||||||
|
resetCategory(UnseenItemCategory.BADGE);
|
||||||
|
}
|
||||||
|
}, [ badges, getCount, resetCategory ]);
|
||||||
|
|
||||||
|
const InventoryBadgeItemView: FC<{ badge: IBadgeItem }> = props =>
|
||||||
|
{
|
||||||
|
const { badge = null, children = null, ...rest } = props;
|
||||||
|
const unseen = isUnseen(UnseenItemCategory.BADGE, badge.id);
|
||||||
|
|
||||||
|
const select = () =>
|
||||||
|
{
|
||||||
|
selectBadge(badge);
|
||||||
|
|
||||||
|
if(unseen) removeUnseen(UnseenItemCategory.BADGE, badge.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LayoutGridItem itemActive={ (selectedBadge === badge) } itemUnseen={ unseen } onMouseDown={ select } { ...rest }>
|
||||||
|
<LayoutBadgeImageView badgeCode={ badge.badgeCode } />
|
||||||
|
{ children }
|
||||||
|
</LayoutGridItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid>
|
||||||
|
<Column size={ 7 } overflow="hidden">
|
||||||
|
<AutoGrid columnCount={ 4 }>
|
||||||
|
{ badges && (badges.length > 0) && badges.map((badge, index) =>
|
||||||
|
{
|
||||||
|
if(activeBadges.indexOf(badge) >= 0) return null;
|
||||||
|
|
||||||
|
return <InventoryBadgeItemView key={ index } badge={ badge } />
|
||||||
|
}) }
|
||||||
|
</AutoGrid>
|
||||||
|
</Column>
|
||||||
|
<Column className="justify-content-between" size={ 5 } overflow="auto">
|
||||||
|
<Column overflow="hidden" gap={ 2 }>
|
||||||
|
<Text>{ LocalizeText('inventory.badges.activebadges') }</Text>
|
||||||
|
<AutoGrid columnCount={ 3 }>
|
||||||
|
{ activeBadges && (activeBadges.length > 0) && activeBadges.map((badge, index) => <InventoryBadgeItemView key={ index } badge={ badge } />) }
|
||||||
|
</AutoGrid>
|
||||||
|
</Column>
|
||||||
|
{ !!selectedBadge &&
|
||||||
|
<Column grow justifyContent="end" gap={ 2 }>
|
||||||
|
<Flex alignItems="center" gap={ 2 }>
|
||||||
|
<LayoutBadgeImageView shrink badgeCode={ selectedBadge.badgeCode } />
|
||||||
|
<Text>{ LocalizeBadgeName(selectedBadge.badgeCode) }</Text>
|
||||||
|
</Flex>
|
||||||
|
<Button variant={ (isWearingBadge(selectedBadge) ? 'danger' : 'success') } disabled={ !isWearingBadge(selectedBadge) && !canWearBadges() } onClick={ event => toggleBadge(selectedBadge) }>{ LocalizeText(isWearingBadge(selectedBadge) ? 'inventory.badges.clearbadge' : 'inventory.badges.wearbadge') }</Button>
|
||||||
|
</Column> }
|
||||||
|
</Column>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
116
src/components/inventory/views/InventoryBotView.tsx
Normal file
116
src/components/inventory/views/InventoryBotView.tsx
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import { IRoomSession, MouseEventType, RoomObjectVariable, RoomPreviewer } from '@nitrots/nitro-renderer';
|
||||||
|
import { FC, MouseEvent, useEffect, useState } from 'react';
|
||||||
|
import { attemptBotPlacement, GetRoomEngine, IBotItem, LocalizeText, UnseenItemCategory } from '../../../api';
|
||||||
|
import { AutoGrid, Button, Column, Grid, LayoutAvatarImageView, LayoutGridItem, LayoutRoomPreviewerView, Text } from '../../../common';
|
||||||
|
import { useSharedInventoryBots, useSharedInventoryUnseenTracker } from '../../../hooks';
|
||||||
|
import { InventoryCategoryEmptyView } from './InventoryCategoryEmptyView';
|
||||||
|
|
||||||
|
interface InventoryBotViewProps
|
||||||
|
{
|
||||||
|
roomSession: IRoomSession;
|
||||||
|
roomPreviewer: RoomPreviewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const InventoryBotView: FC<InventoryBotViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { roomSession = null, roomPreviewer = null } = props;
|
||||||
|
const { botItems = [], selectedBot = null, selectBot = null } = useSharedInventoryBots();
|
||||||
|
const { getCount = null, resetCategory = null, isUnseen = null, removeUnseen = null } = useSharedInventoryUnseenTracker();
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!botItems || !botItems.length) return;
|
||||||
|
|
||||||
|
return () =>
|
||||||
|
{
|
||||||
|
const count = getCount(UnseenItemCategory.BOT);
|
||||||
|
|
||||||
|
if(!count) return;
|
||||||
|
|
||||||
|
resetCategory(UnseenItemCategory.BOT);
|
||||||
|
}
|
||||||
|
}, [ botItems, getCount, resetCategory ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!selectedBot || !roomPreviewer) return;
|
||||||
|
|
||||||
|
const botData = selectedBot.botData;
|
||||||
|
|
||||||
|
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.reset(false);
|
||||||
|
roomPreviewer.updateRoomWallsAndFloorVisibility(true, true);
|
||||||
|
roomPreviewer.updateObjectRoom(floorType, wallType, landscapeType);
|
||||||
|
roomPreviewer.addAvatarIntoRoom(botData.figure, 0);
|
||||||
|
}, [ roomPreviewer, selectedBot ]);
|
||||||
|
|
||||||
|
if(!botItems || !botItems.length) return <InventoryCategoryEmptyView title={ LocalizeText('inventory.empty.bots.title') } desc={ LocalizeText('inventory.empty.bots.desc') } />;
|
||||||
|
|
||||||
|
const InventoryBotItemView: FC<{ botItem: IBotItem }> = props =>
|
||||||
|
{
|
||||||
|
const { botItem = null } = props;
|
||||||
|
const [ isMouseDown, setMouseDown ] = useState(false);
|
||||||
|
const isActive = (botItem === selectedBot);
|
||||||
|
const unseen = isUnseen(UnseenItemCategory.BOT, botItem.botData.id);
|
||||||
|
|
||||||
|
const onMouseEvent = (event: MouseEvent) =>
|
||||||
|
{
|
||||||
|
switch(event.type)
|
||||||
|
{
|
||||||
|
case MouseEventType.MOUSE_DOWN:
|
||||||
|
selectBot(botItem);
|
||||||
|
|
||||||
|
if(unseen) removeUnseen(UnseenItemCategory.BOT, botItem.botData.id);
|
||||||
|
|
||||||
|
setMouseDown(true);
|
||||||
|
return;
|
||||||
|
case MouseEventType.MOUSE_UP:
|
||||||
|
setMouseDown(false);
|
||||||
|
return;
|
||||||
|
case MouseEventType.ROLL_OUT:
|
||||||
|
if(!isMouseDown || !isActive) return;
|
||||||
|
|
||||||
|
attemptBotPlacement(botItem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LayoutGridItem itemActive={ isActive } itemUnseen={ unseen } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent }>
|
||||||
|
<LayoutAvatarImageView figure={ botItem.botData.figure } direction={ 3 } headOnly={ true } />
|
||||||
|
</LayoutGridItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid>
|
||||||
|
<Column size={ 7 } overflow="hidden">
|
||||||
|
<AutoGrid columnCount={ 5 }>
|
||||||
|
{ botItems && (botItems.length > 0) && botItems.map(item => <InventoryBotItemView key={ item.botData.id } botItem={ item } />) }
|
||||||
|
</AutoGrid>
|
||||||
|
</Column>
|
||||||
|
<Column size={ 5 } overflow="auto">
|
||||||
|
<Column overflow="hidden" position="relative">
|
||||||
|
<LayoutRoomPreviewerView roomPreviewer={ roomPreviewer } height={ 140 } />
|
||||||
|
</Column>
|
||||||
|
{ selectedBot &&
|
||||||
|
<Column grow justifyContent="between" gap={ 2 }>
|
||||||
|
<Text grow truncate>{ selectedBot.botData.name }</Text>
|
||||||
|
{ !!roomSession &&
|
||||||
|
<Button variant="success" onClick={ event => attemptBotPlacement(selectedBot) }>
|
||||||
|
{ LocalizeText('inventory.furni.placetoroom') }
|
||||||
|
</Button> }
|
||||||
|
</Column> }
|
||||||
|
</Column>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
@ -1,7 +1,5 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { Column } from '../../../../common/Column';
|
import { Column, Grid, GridProps, Text } from '../../../common';
|
||||||
import { Grid, GridProps } from '../../../../common/Grid';
|
|
||||||
import { Text } from '../../../../common/Text';
|
|
||||||
|
|
||||||
export interface InventoryCategoryEmptyViewProps extends GridProps
|
export interface InventoryCategoryEmptyViewProps extends GridProps
|
||||||
{
|
{
|
@ -1,9 +1,7 @@
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react';
|
import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react';
|
||||||
import { LocalizeText } from '../../../../api';
|
import { GroupItem, LocalizeText } from '../../../api';
|
||||||
import { Button } from '../../../../common/Button';
|
import { Button, Flex } from '../../../common';
|
||||||
import { Flex } from '../../../../common/Flex';
|
|
||||||
import { GroupItem } from '../../common/GroupItem';
|
|
||||||
|
|
||||||
export interface InventoryFurnitureSearchViewProps
|
export interface InventoryFurnitureSearchViewProps
|
||||||
{
|
{
|
161
src/components/inventory/views/InventoryFurnitureView.tsx
Normal file
161
src/components/inventory/views/InventoryFurnitureView.tsx
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
import { IRoomSession, MouseEventType, RoomObjectVariable, RoomPreviewer, Vector3d } from '@nitrots/nitro-renderer';
|
||||||
|
import { FC, MouseEvent, useEffect, useState } from 'react';
|
||||||
|
import { attemptItemPlacement, FurniCategory, GetRoomEngine, GetSessionDataManager, GroupItem, LocalizeText, UnseenItemCategory } from '../../../api';
|
||||||
|
import { AutoGrid, Button, Column, Grid, LayoutGridItem, LayoutLimitedEditionCompactPlateView, LayoutRarityLevelView, LayoutRoomPreviewerView, Text } from '../../../common';
|
||||||
|
import { useSharedInventoryFurni, useSharedInventoryUnseenTracker } from '../../../hooks';
|
||||||
|
import { attemptPlaceMarketplaceOffer } from '../../../hooks/inventory/common';
|
||||||
|
import { InventoryCategoryEmptyView } from './InventoryCategoryEmptyView';
|
||||||
|
import { InventoryFurnitureSearchView } from './InventoryFurnitureSearchView';
|
||||||
|
|
||||||
|
interface InventoryFurnitureViewProps
|
||||||
|
{
|
||||||
|
roomSession: IRoomSession;
|
||||||
|
roomPreviewer: RoomPreviewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const InventoryFurnitureView: FC<InventoryFurnitureViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { roomSession = null, roomPreviewer = null } = props;
|
||||||
|
const { groupItems = [], selectedItem = null, selectItem = null } = useSharedInventoryFurni();
|
||||||
|
const [ filteredGroupItems, setFilteredGroupItems ] = useState<GroupItem[]>(groupItems);
|
||||||
|
const { getCount = null, resetCategory = null } = useSharedInventoryUnseenTracker();
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!selectedItem || !roomPreviewer) return;
|
||||||
|
|
||||||
|
const furnitureItem = selectedItem.getLastItem();
|
||||||
|
|
||||||
|
if(!furnitureItem) return;
|
||||||
|
|
||||||
|
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.reset(false);
|
||||||
|
roomPreviewer.updateObjectRoom(floorType, wallType, landscapeType);
|
||||||
|
roomPreviewer.updateRoomWallsAndFloorVisibility(true, true);
|
||||||
|
|
||||||
|
if((furnitureItem.category === FurniCategory.WALL_PAPER) || (furnitureItem.category === FurniCategory.FLOOR) || (furnitureItem.category === FurniCategory.LANDSCAPE))
|
||||||
|
{
|
||||||
|
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('noob_window_double');
|
||||||
|
|
||||||
|
if(data) roomPreviewer.addWallItemIntoRoom(data.id, new Vector3d(90, 0, 0), data.customParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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(!groupItems || !groupItems.length) return;
|
||||||
|
|
||||||
|
return () =>
|
||||||
|
{
|
||||||
|
const count = getCount(UnseenItemCategory.FURNI);
|
||||||
|
|
||||||
|
if(!count) return;
|
||||||
|
|
||||||
|
resetCategory(UnseenItemCategory.FURNI);
|
||||||
|
|
||||||
|
for(const groupItem of groupItems) groupItem.hasUnseenItems = false;
|
||||||
|
}
|
||||||
|
}, [ groupItems, getCount, resetCategory ]);
|
||||||
|
|
||||||
|
if(!groupItems || !groupItems.length) return <InventoryCategoryEmptyView title={ LocalizeText('inventory.empty.title') } desc={ LocalizeText('inventory.empty.desc') } />;
|
||||||
|
|
||||||
|
const InventoryFurnitureItemView: FC<{ groupItem: GroupItem }> = props =>
|
||||||
|
{
|
||||||
|
const { groupItem = null } = props;
|
||||||
|
const [ isMouseDown, setMouseDown ] = useState(false);
|
||||||
|
const isActive = (groupItem === selectedItem);
|
||||||
|
|
||||||
|
const onMouseEvent = (event: MouseEvent) =>
|
||||||
|
{
|
||||||
|
switch(event.type)
|
||||||
|
{
|
||||||
|
case MouseEventType.MOUSE_DOWN:
|
||||||
|
selectItem(groupItem);
|
||||||
|
setMouseDown(true);
|
||||||
|
return;
|
||||||
|
case MouseEventType.MOUSE_UP:
|
||||||
|
setMouseDown(false);
|
||||||
|
return;
|
||||||
|
case MouseEventType.ROLL_OUT:
|
||||||
|
if(!isMouseDown || !isActive) return;
|
||||||
|
|
||||||
|
attemptItemPlacement(groupItem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!isActive) return;
|
||||||
|
|
||||||
|
groupItem.hasUnseenItems = false;
|
||||||
|
}, [ isActive, groupItem ]);
|
||||||
|
|
||||||
|
const count = groupItem.getUnlockedCount();
|
||||||
|
|
||||||
|
return <LayoutGridItem className={ !count ? 'opacity-0-5 ' : '' } itemImage={ groupItem.iconUrl } itemCount={ count } itemActive={ isActive } itemUniqueNumber={ groupItem.stuffData.uniqueNumber } itemUnseen={ groupItem.hasUnseenItems } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent } />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid>
|
||||||
|
<Column size={ 7 } overflow="hidden">
|
||||||
|
<InventoryFurnitureSearchView groupItems={ groupItems } setGroupItems={ setFilteredGroupItems } />
|
||||||
|
<AutoGrid columnCount={ 5 }>
|
||||||
|
{ filteredGroupItems && (filteredGroupItems.length > 0) && filteredGroupItems.map((item, index) => <InventoryFurnitureItemView key={ index } groupItem={ item } />) }
|
||||||
|
</AutoGrid>
|
||||||
|
</Column>
|
||||||
|
<Column size={ 5 } overflow="auto">
|
||||||
|
<Column overflow="hidden" position="relative">
|
||||||
|
<LayoutRoomPreviewerView roomPreviewer={ roomPreviewer } height={ 140 } />
|
||||||
|
{ selectedItem && selectedItem.stuffData.isUnique &&
|
||||||
|
<LayoutLimitedEditionCompactPlateView className="top-2 end-2" position="absolute" uniqueNumber={ selectedItem.stuffData.uniqueNumber } uniqueSeries={ selectedItem.stuffData.uniqueSeries } /> }
|
||||||
|
{ (selectedItem && selectedItem.stuffData.rarityLevel > -1) &&
|
||||||
|
<LayoutRarityLevelView className="top-2 end-2" position="absolute" level={ selectedItem.stuffData.rarityLevel } /> }
|
||||||
|
</Column>
|
||||||
|
{ selectedItem &&
|
||||||
|
<Column grow justifyContent="between" gap={ 2 }>
|
||||||
|
<Text grow truncate>{ selectedItem.name }</Text>
|
||||||
|
<Column gap={ 1 }>
|
||||||
|
{ !!roomSession &&
|
||||||
|
<Button variant="success" onClick={ event => attemptItemPlacement(selectedItem) }>
|
||||||
|
{ LocalizeText('inventory.furni.placetoroom') }
|
||||||
|
</Button> }
|
||||||
|
{ (selectedItem && selectedItem.isSellable) &&
|
||||||
|
<Button onClick={ event => attemptPlaceMarketplaceOffer(selectedItem) }>
|
||||||
|
{ LocalizeText('inventory.marketplace.sell') }
|
||||||
|
</Button> }
|
||||||
|
</Column>
|
||||||
|
</Column> }
|
||||||
|
</Column>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
115
src/components/inventory/views/InventoryPetView.tsx
Normal file
115
src/components/inventory/views/InventoryPetView.tsx
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import { IRoomSession, MouseEventType, RoomObjectVariable, RoomPreviewer } from '@nitrots/nitro-renderer';
|
||||||
|
import { FC, MouseEvent, useEffect, useState } from 'react';
|
||||||
|
import { attemptPetPlacement, GetRoomEngine, IPetItem, LocalizeText, UnseenItemCategory } from '../../../api';
|
||||||
|
import { AutoGrid, Button, Column, Grid, LayoutGridItem, LayoutPetImageView, LayoutRoomPreviewerView, Text } from '../../../common';
|
||||||
|
import { useSharedInventoryPets, useSharedInventoryUnseenTracker } from '../../../hooks';
|
||||||
|
import { InventoryCategoryEmptyView } from './InventoryCategoryEmptyView';
|
||||||
|
|
||||||
|
interface InventoryPetViewProps
|
||||||
|
{
|
||||||
|
roomSession: IRoomSession;
|
||||||
|
roomPreviewer: RoomPreviewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const InventoryPetView: FC<InventoryPetViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { roomSession = null, roomPreviewer = null } = props;
|
||||||
|
const { petItems = null, selectedPet = null, selectPet = null } = useSharedInventoryPets();
|
||||||
|
const { getCount = null, resetCategory = null, isUnseen = null, removeUnseen = null } = useSharedInventoryUnseenTracker();
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!petItems || !petItems.length) return;
|
||||||
|
|
||||||
|
return () =>
|
||||||
|
{
|
||||||
|
const count = getCount(UnseenItemCategory.PET);
|
||||||
|
|
||||||
|
if(!count) return;
|
||||||
|
|
||||||
|
resetCategory(UnseenItemCategory.PET);
|
||||||
|
}
|
||||||
|
}, [ petItems, getCount, resetCategory ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!selectedPet || !roomPreviewer) return;
|
||||||
|
|
||||||
|
const petData = selectedPet.petData;
|
||||||
|
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.reset(false);
|
||||||
|
roomPreviewer.updateRoomWallsAndFloorVisibility(true, true);
|
||||||
|
roomPreviewer.updateObjectRoom(floorType, wallType, landscapeType);
|
||||||
|
roomPreviewer.addPetIntoRoom(petData.figureString);
|
||||||
|
}, [ roomPreviewer, selectedPet ]);
|
||||||
|
|
||||||
|
if(!petItems || !petItems.length) return <InventoryCategoryEmptyView title={ LocalizeText('inventory.empty.pets.title') } desc={ LocalizeText('inventory.empty.pets.desc') } />;
|
||||||
|
|
||||||
|
const InventoryPetItemView: FC<{ petItem: IPetItem }> = props =>
|
||||||
|
{
|
||||||
|
const { petItem = null } = props;
|
||||||
|
const [ isMouseDown, setMouseDown ] = useState(false);
|
||||||
|
const isActive = (petItem === selectedPet);
|
||||||
|
const unseen = isUnseen(UnseenItemCategory.PET, petItem.petData.id);
|
||||||
|
|
||||||
|
const onMouseEvent = (event: MouseEvent) =>
|
||||||
|
{
|
||||||
|
switch(event.type)
|
||||||
|
{
|
||||||
|
case MouseEventType.MOUSE_DOWN:
|
||||||
|
selectPet(petItem);
|
||||||
|
|
||||||
|
if(unseen) removeUnseen(UnseenItemCategory.PET, petItem.petData.id);
|
||||||
|
|
||||||
|
setMouseDown(true);
|
||||||
|
return;
|
||||||
|
case MouseEventType.MOUSE_UP:
|
||||||
|
setMouseDown(false);
|
||||||
|
return;
|
||||||
|
case MouseEventType.ROLL_OUT:
|
||||||
|
if(!isMouseDown || !isActive) return;
|
||||||
|
|
||||||
|
attemptPetPlacement(petItem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LayoutGridItem itemActive={ isActive } itemUnseen={ unseen } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent }>
|
||||||
|
<LayoutPetImageView figure={ petItem.petData.figureData.figuredata } direction={ 3 } headOnly={ true } />
|
||||||
|
</LayoutGridItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid>
|
||||||
|
<Column size={ 7 } overflow="hidden">
|
||||||
|
<AutoGrid columnCount={ 5 }>
|
||||||
|
{ petItems && (petItems.length > 0) && petItems.map(item => <InventoryPetItemView key={ item.petData.id } petItem={ item } />) }
|
||||||
|
</AutoGrid>
|
||||||
|
</Column>
|
||||||
|
<Column size={ 5 } overflow="auto">
|
||||||
|
<Column overflow="hidden" position="relative">
|
||||||
|
<LayoutRoomPreviewerView roomPreviewer={ roomPreviewer } height={ 140 } />
|
||||||
|
</Column>
|
||||||
|
{ selectedPet && selectedPet.petData &&
|
||||||
|
<Column grow justifyContent="between" gap={ 2 }>
|
||||||
|
<Text grow truncate>{ selectedPet.petData.name }</Text>
|
||||||
|
{ !!roomSession &&
|
||||||
|
<Button variant="success" onClick={ event => attemptPetPlacement(selectedPet) }>
|
||||||
|
{ LocalizeText('inventory.furni.placetoroom') }
|
||||||
|
</Button> }
|
||||||
|
</Column> }
|
||||||
|
</Column>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
@ -1,18 +1,13 @@
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { FurnitureListComposer, IObjectData, TradingAcceptComposer, TradingConfirmationComposer, TradingListAddItemComposer, TradingListAddItemsComposer, TradingListItemRemoveComposer, TradingUnacceptComposer } from '@nitrots/nitro-renderer';
|
import { IObjectData, TradingListAddItemComposer, TradingListAddItemsComposer } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useEffect, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer } from '../../../../api';
|
import { FurniCategory, GroupItem, IFurnitureItem, LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer, TradeState } from '../../../api';
|
||||||
import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../../common';
|
import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../common';
|
||||||
import { FurniCategory } from '../../common/FurniCategory';
|
import { useSharedInventoryTrade } from '../../../hooks';
|
||||||
import { GroupItem } from '../../common/GroupItem';
|
import { getGuildFurniType } from '../../../hooks/inventory/common/TradingUtilities';
|
||||||
import { IFurnitureItem } from '../../common/IFurnitureItem';
|
import { InventoryFurnitureSearchView } from './InventoryFurnitureSearchView';
|
||||||
import { TradeState } from '../../common/TradeState';
|
|
||||||
import { _Str_16998 } from '../../common/TradingUtilities';
|
|
||||||
import { useInventoryContext } from '../../InventoryContext';
|
|
||||||
import { InventoryFurnitureActions } from '../../reducers/InventoryFurnitureReducer';
|
|
||||||
import { InventoryFurnitureSearchView } from '../furniture/InventoryFurnitureSearchView';
|
|
||||||
|
|
||||||
export interface InventoryTradeViewProps
|
interface InventoryTradeViewProps
|
||||||
{
|
{
|
||||||
cancelTrade: () => void;
|
cancelTrade: () => void;
|
||||||
}
|
}
|
||||||
@ -27,14 +22,13 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
|||||||
const [ otherGroupItem, setOtherGroupItem ] = useState<GroupItem>(null);
|
const [ otherGroupItem, setOtherGroupItem ] = useState<GroupItem>(null);
|
||||||
const [ filteredGroupItems, setFilteredGroupItems ] = useState<GroupItem[]>(null);
|
const [ filteredGroupItems, setFilteredGroupItems ] = useState<GroupItem[]>(null);
|
||||||
const [ countdownTick, setCountdownTick ] = useState(3);
|
const [ countdownTick, setCountdownTick ] = useState(3);
|
||||||
const { furnitureState = null, dispatchFurnitureState = null } = useInventoryContext();
|
const { ownUser = null, otherUser = null, groupItems = [], tradeState = TradeState.TRADING_STATE_READY, progressTrade = null, removeItem = null, setTradeState = null } = useSharedInventoryTrade();
|
||||||
const { needsFurniUpdate = false, groupItems = [], tradeData = null } = furnitureState;
|
|
||||||
|
|
||||||
const canTradeItem = (isWallItem: boolean, spriteId: number, category: number, groupable: boolean, stuffData: IObjectData) =>
|
const canTradeItem = (isWallItem: boolean, spriteId: number, category: number, groupable: boolean, stuffData: IObjectData) =>
|
||||||
{
|
{
|
||||||
if(!tradeData || !tradeData.ownUser || tradeData.ownUser.accepts || !tradeData.ownUser.items) return false;
|
if(!ownUser || ownUser.accepts || !ownUser.items) return false;
|
||||||
|
|
||||||
if(tradeData.ownUser.items.length < MAX_ITEMS_TO_TRADE) return true;
|
if(ownUser.items.length < MAX_ITEMS_TO_TRADE) return true;
|
||||||
|
|
||||||
if(!groupable) return false;
|
if(!groupable) return false;
|
||||||
|
|
||||||
@ -48,7 +42,7 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
|||||||
{
|
{
|
||||||
if(category === FurniCategory.GUILD_FURNI)
|
if(category === FurniCategory.GUILD_FURNI)
|
||||||
{
|
{
|
||||||
type = _Str_16998(spriteId, stuffData);
|
type = getGuildFurniType(spriteId, stuffData);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -56,12 +50,12 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return !!tradeData.ownUser.items.getValue(type);
|
return !!ownUser.items.getValue(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
const attemptItemOffer = (count: number) =>
|
const attemptItemOffer = (count: number) =>
|
||||||
{
|
{
|
||||||
if(!tradeData || !groupItem) return;
|
if(!groupItem) return;
|
||||||
|
|
||||||
const tradeItems = groupItem.getTradeItems(count);
|
const tradeItems = groupItem.getTradeItems(count);
|
||||||
|
|
||||||
@ -77,7 +71,7 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
|||||||
if(!coreItem) coreItem = item;
|
if(!coreItem) coreItem = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ownItemCount = tradeData.ownUser.items.length;
|
const ownItemCount = ownUser.items.length;
|
||||||
|
|
||||||
if((ownItemCount + itemIds.length) <= 1500)
|
if((ownItemCount + itemIds.length) <= 1500)
|
||||||
{
|
{
|
||||||
@ -116,74 +110,17 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeItem = (group: GroupItem) =>
|
|
||||||
{
|
|
||||||
const item = group.getLastItem();
|
|
||||||
|
|
||||||
if(!item) return;
|
|
||||||
|
|
||||||
SendMessageComposer(new TradingListItemRemoveComposer(item.id));
|
|
||||||
}
|
|
||||||
|
|
||||||
const progressTrade = () =>
|
|
||||||
{
|
|
||||||
switch(tradeData.state)
|
|
||||||
{
|
|
||||||
case TradeState.TRADING_STATE_RUNNING:
|
|
||||||
if(!tradeData.otherUser.itemCount && !tradeData.ownUser.accepts)
|
|
||||||
{
|
|
||||||
NotificationUtilities.simpleAlert(LocalizeText('inventory.trading.warning.other_not_offering'), null, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tradeData.ownUser.accepts)
|
|
||||||
{
|
|
||||||
SendMessageComposer(new TradingUnacceptComposer());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SendMessageComposer(new TradingAcceptComposer());
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case TradeState.TRADING_STATE_CONFIRMING:
|
|
||||||
SendMessageComposer(new TradingConfirmationComposer());
|
|
||||||
|
|
||||||
dispatchFurnitureState({
|
|
||||||
type: InventoryFurnitureActions.SET_TRADE_STATE,
|
|
||||||
payload: {
|
|
||||||
tradeState: TradeState.TRADING_STATE_CONFIRMED
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getLockIcon = (accepts: boolean) =>
|
const getLockIcon = (accepts: boolean) =>
|
||||||
{
|
{
|
||||||
const iconName = accepts ? 'lock' : 'unlock';
|
const iconName = accepts ? 'lock' : 'unlock';
|
||||||
const textColor = accepts ? 'success' : 'danger';
|
const textColor = accepts ? 'success' : 'danger';
|
||||||
|
|
||||||
return <FontAwesomeIcon icon={ iconName } className={ 'text-' + textColor } />
|
return <FontAwesomeIcon icon={ iconName } className={ 'text-' + textColor } />
|
||||||
};
|
}
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
if(needsFurniUpdate)
|
if(tradeState !== TradeState.TRADING_STATE_COUNTDOWN) return;
|
||||||
{
|
|
||||||
dispatchFurnitureState({
|
|
||||||
type: InventoryFurnitureActions.SET_NEEDS_UPDATE,
|
|
||||||
payload: {
|
|
||||||
flag: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
SendMessageComposer(new FurnitureListComposer());
|
|
||||||
}
|
|
||||||
|
|
||||||
}, [ needsFurniUpdate, groupItems, dispatchFurnitureState ]);
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
if(!tradeData || (tradeData.state !== TradeState.TRADING_STATE_COUNTDOWN)) return;
|
|
||||||
|
|
||||||
setCountdownTick(3);
|
setCountdownTick(3);
|
||||||
|
|
||||||
@ -195,12 +132,7 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
|||||||
|
|
||||||
if(newValue === 0)
|
if(newValue === 0)
|
||||||
{
|
{
|
||||||
dispatchFurnitureState({
|
setTradeState(TradeState.TRADING_STATE_CONFIRMING);
|
||||||
type: InventoryFurnitureActions.SET_TRADE_STATE,
|
|
||||||
payload: {
|
|
||||||
tradeState: TradeState.TRADING_STATE_CONFIRMING
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
}
|
}
|
||||||
@ -209,11 +141,8 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
|||||||
});
|
});
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
return () =>
|
return () => clearInterval(interval);
|
||||||
{
|
}, [ tradeState, setTradeState ]);
|
||||||
clearInterval(interval);
|
|
||||||
}
|
|
||||||
}, [ tradeData, dispatchFurnitureState ]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid>
|
<Grid>
|
||||||
@ -245,12 +174,12 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
|||||||
<Column size={ 6 } overflow="hidden">
|
<Column size={ 6 } overflow="hidden">
|
||||||
<Flex justifyContent="between" alignItems="center">
|
<Flex justifyContent="between" alignItems="center">
|
||||||
<Text>{ LocalizeText('inventory.trading.you') } { LocalizeText('inventory.trading.areoffering') }:</Text>
|
<Text>{ LocalizeText('inventory.trading.you') } { LocalizeText('inventory.trading.areoffering') }:</Text>
|
||||||
{ getLockIcon(tradeData.ownUser.accepts) }
|
{ getLockIcon(ownUser.accepts) }
|
||||||
</Flex>
|
</Flex>
|
||||||
<AutoGrid columnCount={ 3 }>
|
<AutoGrid columnCount={ 3 }>
|
||||||
{ Array.from(Array(MAX_ITEMS_TO_TRADE), (e, i) =>
|
{ Array.from(Array(MAX_ITEMS_TO_TRADE), (e, i) =>
|
||||||
{
|
{
|
||||||
const item = (tradeData.ownUser.items.getWithIndex(i) || null);
|
const item = (ownUser.items.getWithIndex(i) || null);
|
||||||
|
|
||||||
if(!item) return <LayoutGridItem key={ i } />;
|
if(!item) return <LayoutGridItem key={ i } />;
|
||||||
|
|
||||||
@ -270,13 +199,13 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
|||||||
</Column>
|
</Column>
|
||||||
<Column size={ 6 } overflow="hidden">
|
<Column size={ 6 } overflow="hidden">
|
||||||
<Flex justifyContent="between" alignItems="center">
|
<Flex justifyContent="between" alignItems="center">
|
||||||
<Text>{ tradeData.otherUser.userName } { LocalizeText('inventory.trading.isoffering') }:</Text>
|
<Text>{ otherUser.userName } { LocalizeText('inventory.trading.isoffering') }:</Text>
|
||||||
{ getLockIcon(tradeData.otherUser.accepts) }
|
{ getLockIcon(otherUser.accepts) }
|
||||||
</Flex>
|
</Flex>
|
||||||
<AutoGrid columnCount={ 3 }>
|
<AutoGrid columnCount={ 3 }>
|
||||||
{ Array.from(Array(MAX_ITEMS_TO_TRADE), (e, i) =>
|
{ Array.from(Array(MAX_ITEMS_TO_TRADE), (e, i) =>
|
||||||
{
|
{
|
||||||
const item = (tradeData.otherUser.items.getWithIndex(i) || null);
|
const item = (otherUser.items.getWithIndex(i) || null);
|
||||||
|
|
||||||
if(!item) return <LayoutGridItem key={ i } />;
|
if(!item) return <LayoutGridItem key={ i } />;
|
||||||
|
|
||||||
@ -290,15 +219,15 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
|||||||
</Grid>
|
</Grid>
|
||||||
<Flex grow justifyContent="between">
|
<Flex grow justifyContent="between">
|
||||||
<Button variant="danger" onClick={ cancelTrade }>{ LocalizeText('generic.cancel') }</Button>
|
<Button variant="danger" onClick={ cancelTrade }>{ LocalizeText('generic.cancel') }</Button>
|
||||||
{ (tradeData.state === TradeState.TRADING_STATE_READY) &&
|
{ (tradeState === TradeState.TRADING_STATE_READY) &&
|
||||||
<Button variant="secondary" disabled={ (!tradeData.ownUser.itemCount && !tradeData.otherUser.itemCount) } onClick={ progressTrade }>{ LocalizeText('inventory.trading.accept') }</Button> }
|
<Button variant="secondary" disabled={ (!ownUser.itemCount && !otherUser.itemCount) } onClick={ progressTrade }>{ LocalizeText('inventory.trading.accept') }</Button> }
|
||||||
{ (tradeData.state === TradeState.TRADING_STATE_RUNNING) &&
|
{ (tradeState === TradeState.TRADING_STATE_RUNNING) &&
|
||||||
<Button variant="secondary" disabled={ (!tradeData.ownUser.itemCount && !tradeData.otherUser.itemCount) } onClick={ progressTrade }>{ LocalizeText(tradeData.ownUser.accepts ? 'inventory.trading.modify' : 'inventory.trading.accept') }</Button> }
|
<Button variant="secondary" disabled={ (!ownUser.itemCount && !otherUser.itemCount) } onClick={ progressTrade }>{ LocalizeText(ownUser.accepts ? 'inventory.trading.modify' : 'inventory.trading.accept') }</Button> }
|
||||||
{ (tradeData.state === TradeState.TRADING_STATE_COUNTDOWN) &&
|
{ (tradeState === TradeState.TRADING_STATE_COUNTDOWN) &&
|
||||||
<Button variant="secondary" disabled>{ LocalizeText('inventory.trading.countdown', [ 'counter' ], [ countdownTick.toString() ]) }</Button> }
|
<Button variant="secondary" disabled>{ LocalizeText('inventory.trading.countdown', [ 'counter' ], [ countdownTick.toString() ]) }</Button> }
|
||||||
{ (tradeData.state === TradeState.TRADING_STATE_CONFIRMING) &&
|
{ (tradeState === TradeState.TRADING_STATE_CONFIRMING) &&
|
||||||
<Button variant="secondary" onClick={ progressTrade }>{ LocalizeText('inventory.trading.button.restore') }</Button> }
|
<Button variant="secondary" onClick={ progressTrade }>{ LocalizeText('inventory.trading.button.restore') }</Button> }
|
||||||
{ (tradeData.state === TradeState.TRADING_STATE_CONFIRMED) &&
|
{ (tradeState === TradeState.TRADING_STATE_CONFIRMED) &&
|
||||||
<Button variant="secondary">{ LocalizeText('inventory.trading.info.waiting') }</Button> }
|
<Button variant="secondary">{ LocalizeText('inventory.trading.info.waiting') }</Button> }
|
||||||
</Flex>
|
</Flex>
|
||||||
</Column>
|
</Column>
|
@ -1,34 +0,0 @@
|
|||||||
import { MouseEventType } from '@nitrots/nitro-renderer';
|
|
||||||
import { FC, MouseEvent } from 'react';
|
|
||||||
import { LayoutBadgeImageView, LayoutGridItem } from '../../../../common';
|
|
||||||
import { useInventoryContext } from '../../InventoryContext';
|
|
||||||
import { InventoryBadgeActions } from '../../reducers/InventoryBadgeReducer';
|
|
||||||
|
|
||||||
export interface InventoryBadgeItemViewProps
|
|
||||||
{
|
|
||||||
badgeCode: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const InventoryBadgeItemView: FC<InventoryBadgeItemViewProps> = props =>
|
|
||||||
{
|
|
||||||
const { badgeCode = null } = props;
|
|
||||||
const { badgeState = null, dispatchBadgeState = null } = useInventoryContext();
|
|
||||||
|
|
||||||
const onMouseEvent = (event: MouseEvent) =>
|
|
||||||
{
|
|
||||||
switch(event.type)
|
|
||||||
{
|
|
||||||
case MouseEventType.MOUSE_DOWN:
|
|
||||||
dispatchBadgeState({
|
|
||||||
type: InventoryBadgeActions.SET_BADGE,
|
|
||||||
payload: { badgeCode }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<LayoutGridItem itemActive={ (badgeState.badge === badgeCode) } onMouseDown={ onMouseEvent }>
|
|
||||||
<LayoutBadgeImageView badgeCode={ badgeCode } />
|
|
||||||
</LayoutGridItem>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,102 +0,0 @@
|
|||||||
import { RequestBadgesComposer } from '@nitrots/nitro-renderer';
|
|
||||||
import { FC, useEffect } from 'react';
|
|
||||||
import { GetConfiguration, LocalizeBadgeName, LocalizeText, SendMessageComposer } from '../../../../api';
|
|
||||||
import { AutoGrid, Button, Column, Flex, Grid, LayoutBadgeImageView, Text } from '../../../../common';
|
|
||||||
import { useInventoryContext } from '../../InventoryContext';
|
|
||||||
import { InventoryBadgeActions } from '../../reducers/InventoryBadgeReducer';
|
|
||||||
import { InventoryBadgeItemView } from './InventoryBadgeItemView';
|
|
||||||
|
|
||||||
export interface InventoryBadgeViewProps
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
export const InventoryBadgeView: FC<InventoryBadgeViewProps> = props =>
|
|
||||||
{
|
|
||||||
const { badgeState = null, dispatchBadgeState = null } = useInventoryContext();
|
|
||||||
const { needsBadgeUpdate = false, badge = null, badges = [], activeBadges = [] } = badgeState;
|
|
||||||
|
|
||||||
const maxBadgeCount = GetConfiguration<number>('user.badges.max.slots', 5);
|
|
||||||
|
|
||||||
const isWearingBadge = (badgeCode: string) => (activeBadges.indexOf(badgeCode) >= 0);
|
|
||||||
const canWearBadges = () => (activeBadges.length < maxBadgeCount);
|
|
||||||
|
|
||||||
const toggleBadge = () =>
|
|
||||||
{
|
|
||||||
if(isWearingBadge(badge))
|
|
||||||
{
|
|
||||||
dispatchBadgeState({
|
|
||||||
type: InventoryBadgeActions.REMOVE_ACTIVE_BADGE,
|
|
||||||
payload: {
|
|
||||||
badgeCode: badge
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(!canWearBadges()) return;
|
|
||||||
|
|
||||||
dispatchBadgeState({
|
|
||||||
type: InventoryBadgeActions.ADD_ACTIVE_BADGE,
|
|
||||||
payload: {
|
|
||||||
badgeCode: badge
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
if(needsBadgeUpdate)
|
|
||||||
{
|
|
||||||
dispatchBadgeState({
|
|
||||||
type: InventoryBadgeActions.SET_NEEDS_UPDATE,
|
|
||||||
payload: {
|
|
||||||
flag: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
SendMessageComposer(new RequestBadgesComposer());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dispatchBadgeState({
|
|
||||||
type: InventoryBadgeActions.SET_BADGE,
|
|
||||||
payload: {
|
|
||||||
badgeCode: null
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}, [ needsBadgeUpdate, badges, dispatchBadgeState ]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Grid>
|
|
||||||
<Column size={ 7 } overflow="hidden">
|
|
||||||
<AutoGrid columnCount={ 4 }>
|
|
||||||
{ badges && (badges.length > 0) && badges.map((code, index) =>
|
|
||||||
{
|
|
||||||
if(activeBadges.indexOf(code) >= 0) return null;
|
|
||||||
|
|
||||||
return <InventoryBadgeItemView key={ index } badgeCode={ code } />
|
|
||||||
}) }
|
|
||||||
</AutoGrid>
|
|
||||||
</Column>
|
|
||||||
<Column className="justify-content-between" size={ 5 } overflow="auto">
|
|
||||||
<Column overflow="hidden" gap={ 2 }>
|
|
||||||
<Text>{ LocalizeText('inventory.badges.activebadges') }</Text>
|
|
||||||
<AutoGrid columnCount={ 3 }>
|
|
||||||
{ activeBadges && (activeBadges.length > 0) && activeBadges.map((code, index) => <InventoryBadgeItemView key={ code } badgeCode={ code } />) }
|
|
||||||
</AutoGrid>
|
|
||||||
</Column>
|
|
||||||
{ badge && (badge.length > 0) &&
|
|
||||||
<Column grow justifyContent="end" gap={ 2 }>
|
|
||||||
<Flex alignItems="center" gap={ 2 }>
|
|
||||||
<LayoutBadgeImageView shrink badgeCode={ badge } />
|
|
||||||
<Text>{ LocalizeBadgeName(badge) }</Text>
|
|
||||||
</Flex>
|
|
||||||
<Button variant={ (isWearingBadge(badge) ? 'danger' : 'success') } disabled={ !isWearingBadge(badge) && !canWearBadges() } onClick={ toggleBadge }>{ LocalizeText(isWearingBadge(badge) ? 'inventory.badges.clearbadge' : 'inventory.badges.wearbadge') }</Button>
|
|
||||||
</Column> }
|
|
||||||
</Column>
|
|
||||||
</Grid>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
import { MouseEventType } from '@nitrots/nitro-renderer';
|
|
||||||
import { FC, MouseEvent, useEffect, useState } from 'react';
|
|
||||||
import { LayoutAvatarImageView, LayoutGridItem } from '../../../../common';
|
|
||||||
import { BotItem } from '../../common/BotItem';
|
|
||||||
import { attemptBotPlacement } from '../../common/BotUtilities';
|
|
||||||
import { useInventoryContext } from '../../InventoryContext';
|
|
||||||
import { InventoryBotActions } from '../../reducers/InventoryBotReducer';
|
|
||||||
|
|
||||||
export interface InventoryBotItemViewProps
|
|
||||||
{
|
|
||||||
botItem: BotItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const InventoryBotItemView: FC<InventoryBotItemViewProps> = props =>
|
|
||||||
{
|
|
||||||
const { botItem } = props;
|
|
||||||
const [ isMouseDown, setMouseDown ] = useState(false);
|
|
||||||
const { botState = null, dispatchBotState = null } = useInventoryContext();
|
|
||||||
const isActive = (botState.botItem === botItem);
|
|
||||||
|
|
||||||
const onMouseEvent = (event: MouseEvent) =>
|
|
||||||
{
|
|
||||||
switch(event.type)
|
|
||||||
{
|
|
||||||
case MouseEventType.MOUSE_DOWN:
|
|
||||||
dispatchBotState({
|
|
||||||
type: InventoryBotActions.SET_BOT_ITEM,
|
|
||||||
payload: { botItem }
|
|
||||||
});
|
|
||||||
|
|
||||||
setMouseDown(true);
|
|
||||||
return;
|
|
||||||
case MouseEventType.MOUSE_UP:
|
|
||||||
setMouseDown(false);
|
|
||||||
return;
|
|
||||||
case MouseEventType.ROLL_OUT:
|
|
||||||
if(!isMouseDown || !isActive) return;
|
|
||||||
|
|
||||||
attemptBotPlacement(botItem);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
if(!isActive) return;
|
|
||||||
|
|
||||||
botItem.isUnseen = false;
|
|
||||||
}, [ isActive, botItem ]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<LayoutGridItem itemActive={ isActive } itemUnseen={ botItem.isUnseen } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent }>
|
|
||||||
<LayoutAvatarImageView figure={ botItem.botData.figure } direction={ 3 } headOnly={ true } />
|
|
||||||
</LayoutGridItem>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,94 +0,0 @@
|
|||||||
import { GetBotInventoryComposer, IRoomSession, RoomObjectVariable, RoomPreviewer } from '@nitrots/nitro-renderer';
|
|
||||||
import { FC, useEffect } from 'react';
|
|
||||||
import { GetRoomEngine, LocalizeText, SendMessageComposer } from '../../../../api';
|
|
||||||
import { AutoGrid, Button, Column, Grid, LayoutRoomPreviewerView, Text } from '../../../../common';
|
|
||||||
import { attemptBotPlacement } from '../../common/BotUtilities';
|
|
||||||
import { useInventoryContext } from '../../InventoryContext';
|
|
||||||
import { InventoryBotActions } from '../../reducers/InventoryBotReducer';
|
|
||||||
import { InventoryCategoryEmptyView } from '../category-empty/InventoryCategoryEmptyView';
|
|
||||||
import { InventoryBotItemView } from './InventoryBotItemView';
|
|
||||||
|
|
||||||
export interface InventoryBotViewProps
|
|
||||||
{
|
|
||||||
roomSession: IRoomSession;
|
|
||||||
roomPreviewer: RoomPreviewer;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const InventoryBotView: FC<InventoryBotViewProps> = props =>
|
|
||||||
{
|
|
||||||
const { roomSession = null, roomPreviewer = null } = props;
|
|
||||||
const { botState = null, dispatchBotState = null } = useInventoryContext();
|
|
||||||
const { needsBotUpdate = false, botItem = null, botItems = [] } = botState;
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
if(needsBotUpdate)
|
|
||||||
{
|
|
||||||
dispatchBotState({
|
|
||||||
type: InventoryBotActions.SET_NEEDS_UPDATE,
|
|
||||||
payload: {
|
|
||||||
flag: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
SendMessageComposer(new GetBotInventoryComposer());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dispatchBotState({
|
|
||||||
type: InventoryBotActions.SET_BOT_ITEM,
|
|
||||||
payload: {
|
|
||||||
botItem: null
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}, [ needsBotUpdate, botItems, dispatchBotState ]);
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
if(!botItem || !roomPreviewer) return;
|
|
||||||
|
|
||||||
const botData = botItem.botData;
|
|
||||||
|
|
||||||
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.reset(false);
|
|
||||||
roomPreviewer.updateRoomWallsAndFloorVisibility(true, true);
|
|
||||||
roomPreviewer.updateObjectRoom(floorType, wallType, landscapeType);
|
|
||||||
roomPreviewer.addAvatarIntoRoom(botData.figure, 0);
|
|
||||||
}, [ roomPreviewer, botItem ]);
|
|
||||||
|
|
||||||
if(!botItems || !botItems.length) return <InventoryCategoryEmptyView title={ LocalizeText('inventory.empty.bots.title') } desc={ LocalizeText('inventory.empty.bots.desc') } />;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Grid>
|
|
||||||
<Column size={ 7 } overflow="hidden">
|
|
||||||
<AutoGrid columnCount={ 5 }>
|
|
||||||
{ botItems && (botItems.length > 0) && botItems.map(item => <InventoryBotItemView key={ item.id } botItem={ item } />) }
|
|
||||||
</AutoGrid>
|
|
||||||
</Column>
|
|
||||||
<Column size={ 5 } overflow="auto">
|
|
||||||
<Column overflow="hidden" position="relative">
|
|
||||||
<LayoutRoomPreviewerView roomPreviewer={ roomPreviewer } height={ 140 } />
|
|
||||||
</Column>
|
|
||||||
{ botItem &&
|
|
||||||
<Column grow justifyContent="between" gap={ 2 }>
|
|
||||||
<Text grow truncate>{ botItem.botData.name }</Text>
|
|
||||||
{ !!roomSession &&
|
|
||||||
<Button variant="success" onClick={ event => attemptBotPlacement(botItem) }>
|
|
||||||
{ LocalizeText('inventory.furni.placetoroom') }
|
|
||||||
</Button> }
|
|
||||||
</Column> }
|
|
||||||
</Column>
|
|
||||||
</Grid>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
import { MouseEventType } from '@nitrots/nitro-renderer';
|
|
||||||
import { FC, MouseEvent, useEffect, useState } from 'react';
|
|
||||||
import { LayoutGridItem } from '../../../../common/layout/LayoutGridItem';
|
|
||||||
import { attemptItemPlacement } from '../../common/FurnitureUtilities';
|
|
||||||
import { GroupItem } from '../../common/GroupItem';
|
|
||||||
import { useInventoryContext } from '../../InventoryContext';
|
|
||||||
import { InventoryFurnitureActions } from '../../reducers/InventoryFurnitureReducer';
|
|
||||||
|
|
||||||
export interface InventoryFurnitureItemViewProps
|
|
||||||
{
|
|
||||||
groupItem: GroupItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const InventoryFurnitureItemView: FC<InventoryFurnitureItemViewProps> = props =>
|
|
||||||
{
|
|
||||||
const { groupItem } = props;
|
|
||||||
const [ isMouseDown, setMouseDown ] = useState(false);
|
|
||||||
const { furnitureState, dispatchFurnitureState } = useInventoryContext();
|
|
||||||
const isActive = (furnitureState.groupItem === groupItem);
|
|
||||||
|
|
||||||
const onMouseEvent = (event: MouseEvent) =>
|
|
||||||
{
|
|
||||||
switch(event.type)
|
|
||||||
{
|
|
||||||
case MouseEventType.MOUSE_DOWN:
|
|
||||||
dispatchFurnitureState({
|
|
||||||
type: InventoryFurnitureActions.SET_GROUP_ITEM,
|
|
||||||
payload: { groupItem }
|
|
||||||
});
|
|
||||||
|
|
||||||
setMouseDown(true);
|
|
||||||
return;
|
|
||||||
case MouseEventType.MOUSE_UP:
|
|
||||||
setMouseDown(false);
|
|
||||||
return;
|
|
||||||
case MouseEventType.ROLL_OUT:
|
|
||||||
if(!isMouseDown || !isActive) return;
|
|
||||||
|
|
||||||
attemptItemPlacement(groupItem);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
if(!isActive) return;
|
|
||||||
|
|
||||||
groupItem.hasUnseenItems = false;
|
|
||||||
}, [ isActive, groupItem ]);
|
|
||||||
|
|
||||||
const count = groupItem.getUnlockedCount();
|
|
||||||
|
|
||||||
return <LayoutGridItem className={ !count ? 'opacity-0-5 ' : '' } itemImage={ groupItem.iconUrl } itemCount={ count } itemActive={ isActive } itemUniqueNumber={ groupItem.stuffData.uniqueNumber } itemUnseen={ groupItem.hasUnseenItems } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent } />;
|
|
||||||
}
|
|
@ -1,139 +0,0 @@
|
|||||||
import { FurnitureListComposer, IRoomSession, RoomObjectVariable, RoomPreviewer, Vector3d } from '@nitrots/nitro-renderer';
|
|
||||||
import { FC, useEffect, useState } from 'react';
|
|
||||||
import { GetRoomEngine, GetSessionDataManager, LocalizeText, SendMessageComposer } from '../../../../api';
|
|
||||||
import { AutoGrid, Button, Column, Grid, LayoutLimitedEditionCompactPlateView, LayoutRarityLevelView, LayoutRoomPreviewerView, Text } from '../../../../common';
|
|
||||||
import { FurniCategory } from '../../common/FurniCategory';
|
|
||||||
import { attemptItemPlacement, attemptPlaceMarketplaceOffer } from '../../common/FurnitureUtilities';
|
|
||||||
import { GroupItem } from '../../common/GroupItem';
|
|
||||||
import { useInventoryContext } from '../../InventoryContext';
|
|
||||||
import { InventoryFurnitureActions } from '../../reducers/InventoryFurnitureReducer';
|
|
||||||
import { InventoryCategoryEmptyView } from '../category-empty/InventoryCategoryEmptyView';
|
|
||||||
import { InventoryFurnitureItemView } from './InventoryFurnitureItemView';
|
|
||||||
import { InventoryFurnitureSearchView } from './InventoryFurnitureSearchView';
|
|
||||||
|
|
||||||
export interface InventoryFurnitureViewProps
|
|
||||||
{
|
|
||||||
roomSession: IRoomSession;
|
|
||||||
roomPreviewer: RoomPreviewer;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const InventoryFurnitureView: FC<InventoryFurnitureViewProps> = props =>
|
|
||||||
{
|
|
||||||
const { roomSession = null, roomPreviewer = null } = props;
|
|
||||||
const { furnitureState = null, dispatchFurnitureState = null, unseenTracker = null } = useInventoryContext();
|
|
||||||
const { needsFurniUpdate = false, groupItem = null, groupItems = [] } = furnitureState;
|
|
||||||
const [ filteredGroupItems, setFilteredGroupItems ] = useState<GroupItem[]>(groupItems);
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
if(needsFurniUpdate)
|
|
||||||
{
|
|
||||||
dispatchFurnitureState({
|
|
||||||
type: InventoryFurnitureActions.SET_NEEDS_UPDATE,
|
|
||||||
payload: {
|
|
||||||
flag: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
SendMessageComposer(new FurnitureListComposer());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setFilteredGroupItems(groupItems);
|
|
||||||
|
|
||||||
dispatchFurnitureState({
|
|
||||||
type: InventoryFurnitureActions.SET_GROUP_ITEM,
|
|
||||||
payload: {
|
|
||||||
groupItem: null
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}, [ needsFurniUpdate, groupItems, dispatchFurnitureState ]);
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
if(!groupItem || !roomPreviewer) return;
|
|
||||||
|
|
||||||
const furnitureItem = groupItem.getLastItem();
|
|
||||||
|
|
||||||
if(!furnitureItem) return;
|
|
||||||
|
|
||||||
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.reset(false);
|
|
||||||
roomPreviewer.updateObjectRoom(floorType, wallType, landscapeType);
|
|
||||||
roomPreviewer.updateRoomWallsAndFloorVisibility(true, true);
|
|
||||||
|
|
||||||
if((furnitureItem.category === FurniCategory.WALL_PAPER) || (furnitureItem.category === FurniCategory.FLOOR) || (furnitureItem.category === FurniCategory.LANDSCAPE))
|
|
||||||
{
|
|
||||||
floorType = ((furnitureItem.category === FurniCategory.FLOOR) ? groupItem.stuffData.getLegacyString() : floorType);
|
|
||||||
wallType = ((furnitureItem.category === FurniCategory.WALL_PAPER) ? groupItem.stuffData.getLegacyString() : wallType);
|
|
||||||
landscapeType = ((furnitureItem.category === FurniCategory.LANDSCAPE) ? groupItem.stuffData.getLegacyString() : landscapeType);
|
|
||||||
|
|
||||||
roomPreviewer.updateObjectRoom(floorType, wallType, landscapeType);
|
|
||||||
|
|
||||||
if(furnitureItem.category === FurniCategory.LANDSCAPE)
|
|
||||||
{
|
|
||||||
const data = GetSessionDataManager().getWallItemDataByName('noob_window_double');
|
|
||||||
|
|
||||||
if(data) roomPreviewer.addWallItemIntoRoom(data.id, new Vector3d(90, 0, 0), data.customParams);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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 ]);
|
|
||||||
|
|
||||||
if(!groupItems || !groupItems.length) return <InventoryCategoryEmptyView title={ LocalizeText('inventory.empty.title') } desc={ LocalizeText('inventory.empty.desc') } />;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Grid>
|
|
||||||
<Column size={ 7 } overflow="hidden">
|
|
||||||
<InventoryFurnitureSearchView groupItems={ groupItems } setGroupItems={ setFilteredGroupItems } />
|
|
||||||
<AutoGrid columnCount={ 5 }>
|
|
||||||
{ filteredGroupItems && (filteredGroupItems.length > 0) && filteredGroupItems.map((item, index) => <InventoryFurnitureItemView key={ index } groupItem={ item } />) }
|
|
||||||
</AutoGrid>
|
|
||||||
</Column>
|
|
||||||
<Column size={ 5 } overflow="auto">
|
|
||||||
<Column overflow="hidden" position="relative">
|
|
||||||
<LayoutRoomPreviewerView roomPreviewer={ roomPreviewer } height={ 140 } />
|
|
||||||
{ groupItem && groupItem.stuffData.isUnique &&
|
|
||||||
<LayoutLimitedEditionCompactPlateView className="top-2 end-2" position="absolute" uniqueNumber={ groupItem.stuffData.uniqueNumber } uniqueSeries={ groupItem.stuffData.uniqueSeries } /> }
|
|
||||||
{ (groupItem && groupItem.stuffData.rarityLevel > -1) &&
|
|
||||||
<LayoutRarityLevelView className="top-2 end-2" position="absolute" level={ groupItem.stuffData.rarityLevel } /> }
|
|
||||||
</Column>
|
|
||||||
{ groupItem &&
|
|
||||||
<Column grow justifyContent="between" gap={ 2 }>
|
|
||||||
<Text grow truncate>{ groupItem.name }</Text>
|
|
||||||
<Column gap={ 1 }>
|
|
||||||
{ !!roomSession &&
|
|
||||||
<Button variant="success" onClick={ event => attemptItemPlacement(groupItem) }>
|
|
||||||
{ LocalizeText('inventory.furni.placetoroom') }
|
|
||||||
</Button> }
|
|
||||||
{ (groupItem && groupItem.isSellable) &&
|
|
||||||
<Button onClick={ event => attemptPlaceMarketplaceOffer(groupItem) }>
|
|
||||||
{ LocalizeText('inventory.marketplace.sell') }
|
|
||||||
</Button> }
|
|
||||||
</Column>
|
|
||||||
</Column> }
|
|
||||||
</Column>
|
|
||||||
</Grid>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
import { MouseEventType } from '@nitrots/nitro-renderer';
|
|
||||||
import { FC, MouseEvent, useEffect, useState } from 'react';
|
|
||||||
import { LayoutGridItem, LayoutPetImageView } from '../../../../common';
|
|
||||||
import { PetItem } from '../../common/PetItem';
|
|
||||||
import { attemptPetPlacement } from '../../common/PetUtilities';
|
|
||||||
import { useInventoryContext } from '../../InventoryContext';
|
|
||||||
import { InventoryPetActions } from '../../reducers/InventoryPetReducer';
|
|
||||||
|
|
||||||
export interface InventoryPetItemViewProps
|
|
||||||
{
|
|
||||||
petItem: PetItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const InventoryPetItemView: FC<InventoryPetItemViewProps> = props =>
|
|
||||||
{
|
|
||||||
const { petItem } = props;
|
|
||||||
const [ isMouseDown, setMouseDown ] = useState(false);
|
|
||||||
const { petState = null, dispatchPetState = null } = useInventoryContext();
|
|
||||||
const isActive = (petState.petItem === petItem);
|
|
||||||
|
|
||||||
const onMouseEvent = (event: MouseEvent) =>
|
|
||||||
{
|
|
||||||
switch(event.type)
|
|
||||||
{
|
|
||||||
case MouseEventType.MOUSE_DOWN:
|
|
||||||
dispatchPetState({
|
|
||||||
type: InventoryPetActions.SET_PET_ITEM,
|
|
||||||
payload: { petItem }
|
|
||||||
});
|
|
||||||
|
|
||||||
setMouseDown(true);
|
|
||||||
return;
|
|
||||||
case MouseEventType.MOUSE_UP:
|
|
||||||
setMouseDown(false);
|
|
||||||
return;
|
|
||||||
case MouseEventType.ROLL_OUT:
|
|
||||||
if(!isMouseDown || !isActive) return;
|
|
||||||
|
|
||||||
attemptPetPlacement(petItem);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
if(!isActive) return;
|
|
||||||
|
|
||||||
petItem.isUnseen = false;
|
|
||||||
}, [ isActive, petItem ]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<LayoutGridItem itemActive={ isActive } itemUnseen={ petItem.isUnseen } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent }>
|
|
||||||
<LayoutPetImageView figure={ petItem.petData.figureData.figuredata } direction={ 3 } headOnly={ true } />
|
|
||||||
</LayoutGridItem>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
import { IRoomSession, RequestPetsComposer, RoomObjectVariable, RoomPreviewer } from '@nitrots/nitro-renderer';
|
|
||||||
import { FC, useEffect } from 'react';
|
|
||||||
import { GetRoomEngine, LocalizeText, SendMessageComposer } from '../../../../api';
|
|
||||||
import { AutoGrid, Button, Column, Grid, LayoutRoomPreviewerView, Text } from '../../../../common';
|
|
||||||
import { attemptPetPlacement } from '../../common/PetUtilities';
|
|
||||||
import { useInventoryContext } from '../../InventoryContext';
|
|
||||||
import { InventoryPetActions } from '../../reducers/InventoryPetReducer';
|
|
||||||
import { InventoryCategoryEmptyView } from '../category-empty/InventoryCategoryEmptyView';
|
|
||||||
import { InventoryPetItemView } from './InventoryPetItemView';
|
|
||||||
|
|
||||||
export interface InventoryPetViewProps
|
|
||||||
{
|
|
||||||
roomSession: IRoomSession;
|
|
||||||
roomPreviewer: RoomPreviewer;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const InventoryPetView: FC<InventoryPetViewProps> = props =>
|
|
||||||
{
|
|
||||||
const { roomSession = null, roomPreviewer = null } = props;
|
|
||||||
const { petState = null, dispatchPetState = null } = useInventoryContext();
|
|
||||||
const { needsPetUpdate = false, petItem = null, petItems = [] } = petState;
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
if(needsPetUpdate)
|
|
||||||
{
|
|
||||||
dispatchPetState({
|
|
||||||
type: InventoryPetActions.SET_NEEDS_UPDATE,
|
|
||||||
payload: {
|
|
||||||
flag: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
SendMessageComposer(new RequestPetsComposer());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dispatchPetState({
|
|
||||||
type: InventoryPetActions.SET_PET_ITEM,
|
|
||||||
payload: {
|
|
||||||
petItem: null
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}, [ needsPetUpdate, petItems, dispatchPetState ]);
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
if(!petItem || !roomPreviewer) return;
|
|
||||||
|
|
||||||
const petData = petItem.petData;
|
|
||||||
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.reset(false);
|
|
||||||
roomPreviewer.updateRoomWallsAndFloorVisibility(true, true);
|
|
||||||
roomPreviewer.updateObjectRoom(floorType, wallType, landscapeType);
|
|
||||||
roomPreviewer.addPetIntoRoom(petData.figureString);
|
|
||||||
}, [ roomPreviewer, petItem ]);
|
|
||||||
|
|
||||||
if(!petItems || !petItems.length) return <InventoryCategoryEmptyView title={ LocalizeText('inventory.empty.pets.title') } desc={ LocalizeText('inventory.empty.pets.desc') } />;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Grid>
|
|
||||||
<Column size={ 7 } overflow="hidden">
|
|
||||||
<AutoGrid columnCount={ 5 }>
|
|
||||||
{ petItems && (petItems.length > 0) && petItems.map(item => <InventoryPetItemView key={ item.id } petItem={ item } />) }
|
|
||||||
</AutoGrid>
|
|
||||||
</Column>
|
|
||||||
<Column size={ 5 } overflow="auto">
|
|
||||||
<Column overflow="hidden" position="relative">
|
|
||||||
<LayoutRoomPreviewerView roomPreviewer={ roomPreviewer } height={ 140 } />
|
|
||||||
</Column>
|
|
||||||
{ petItem &&
|
|
||||||
<Column grow justifyContent="between" gap={ 2 }>
|
|
||||||
<Text grow truncate>{ petItem.petData.name }</Text>
|
|
||||||
{ !!roomSession &&
|
|
||||||
<Button variant="success" onClick={ event => attemptPetPlacement(petItem) }>
|
|
||||||
{ LocalizeText('inventory.furni.placetoroom') }
|
|
||||||
</Button> }
|
|
||||||
</Column> }
|
|
||||||
</Column>
|
|
||||||
</Grid>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
import { RoomEngineObjectEvent, RoomObjectCategory, RoomObjectType } from '@nitrots/nitro-renderer';
|
import { RoomEngineObjectEvent, RoomObjectCategory, RoomObjectType } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useReducer, useState } from 'react';
|
import { FC, useCallback, useReducer, useRef, useState } from 'react';
|
||||||
import { GetRoomSession } from '../../api';
|
import { GetRoomSession } from '../../api';
|
||||||
import { Base, Button, DraggableWindowPosition, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../common';
|
import { Base, Button, DraggableWindowPosition, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../common';
|
||||||
import { ModToolsEvent, ModToolsOpenRoomChatlogEvent, ModToolsOpenRoomInfoEvent, ModToolsOpenUserInfoEvent } from '../../events';
|
import { ModToolsEvent, ModToolsOpenRoomChatlogEvent, ModToolsOpenRoomInfoEvent, ModToolsOpenUserInfoEvent } from '../../events';
|
||||||
@ -21,6 +21,7 @@ export const ModToolsView: FC<{}> = props =>
|
|||||||
const [ isTicketsVisible, setIsTicketsVisible ] = useState(false);
|
const [ isTicketsVisible, setIsTicketsVisible ] = useState(false);
|
||||||
const [ modToolsState, dispatchModToolsState ] = useReducer(ModToolsReducer, initialModTools);
|
const [ modToolsState, dispatchModToolsState ] = useReducer(ModToolsReducer, initialModTools);
|
||||||
const { currentRoomId = null, openRooms = null, openRoomChatlogs = null, openUserChatlogs = null, openUserInfo = null } = modToolsState;
|
const { currentRoomId = null, openRooms = null, openRoomChatlogs = null, openUserChatlogs = null, openUserInfo = null } = modToolsState;
|
||||||
|
const elementRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const onModToolsEvent = useCallback((event: ModToolsEvent) =>
|
const onModToolsEvent = useCallback((event: ModToolsEvent) =>
|
||||||
{
|
{
|
||||||
@ -190,7 +191,7 @@ export const ModToolsView: FC<{}> = props =>
|
|||||||
<Button gap={ 1 } onClick={ event => handleClick('toggle_room') } disabled={ !currentRoomId } className="position-relative">
|
<Button gap={ 1 } onClick={ event => handleClick('toggle_room') } disabled={ !currentRoomId } className="position-relative">
|
||||||
<Base className="icon icon-small-room position-absolute start-1"/> Room Tool
|
<Base className="icon icon-small-room position-absolute start-1"/> Room Tool
|
||||||
</Button>
|
</Button>
|
||||||
<Button gap={ 1 } onClick={ event => handleClick('toggle_room_chatlog') } disabled={ !currentRoomId } className="position-relative">
|
<Button innerRef={ elementRef } gap={ 1 } onClick={ event => handleClick('toggle_room_chatlog') } disabled={ !currentRoomId } className="position-relative">
|
||||||
<Base className="icon icon-chat-history position-absolute start-1"/> Chatlog Tool
|
<Base className="icon icon-chat-history position-absolute start-1"/> Chatlog Tool
|
||||||
</Button>
|
</Button>
|
||||||
<Button gap={ 1 } onClick={ () => handleClick('toggle_user_info') } disabled={ !selectedUser } className="position-relative">
|
<Button gap={ 1 } onClick={ () => handleClick('toggle_user_info') } disabled={ !selectedUser } className="position-relative">
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { IFurnitureData, PetCustomPart, PetFigureData, RoomObjectCategory, RoomObjectVariable, RoomUserData } from '@nitrots/nitro-renderer';
|
import { IFurnitureData, PetCustomPart, PetFigureData, RoomObjectCategory, RoomObjectVariable, RoomUserData } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { GetFurnitureDataForRoomObject, GetRoomEngine, LocalizeText, RoomWidgetUseProductMessage, UseProductItem } from '../../../../api';
|
import { FurniCategory, GetFurnitureDataForRoomObject, GetRoomEngine, LocalizeText, RoomWidgetUseProductMessage, UseProductItem } from '../../../../api';
|
||||||
import { Base, Button, Column, Flex, LayoutPetImageView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common';
|
import { Base, Button, Column, Flex, LayoutPetImageView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common';
|
||||||
import { FurniCategory } from '../../../inventory/common/FurniCategory';
|
|
||||||
import { useRoomContext } from '../../RoomContext';
|
import { useRoomContext } from '../../RoomContext';
|
||||||
|
|
||||||
interface AvatarInfoUseProductConfirmViewProps
|
interface AvatarInfoUseProductConfirmViewProps
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { RoomObjectCategory, RoomObjectType } from '@nitrots/nitro-renderer';
|
import { RoomObjectCategory, RoomObjectType } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useState } from 'react';
|
import { FC, useCallback, useEffect, useState } from 'react';
|
||||||
import { GetFurnitureDataForRoomObject, LocalizeText, UseProductItem } from '../../../../api';
|
import { FurniCategory, GetFurnitureDataForRoomObject, LocalizeText, UseProductItem } from '../../../../api';
|
||||||
import { FurniCategory } from '../../../inventory/common/FurniCategory';
|
|
||||||
import { useRoomContext } from '../../RoomContext';
|
import { useRoomContext } from '../../RoomContext';
|
||||||
import { ContextMenuHeaderView } from '../context-menu/ContextMenuHeaderView';
|
import { ContextMenuHeaderView } from '../context-menu/ContextMenuHeaderView';
|
||||||
import { ContextMenuListItemView } from '../context-menu/ContextMenuListItemView';
|
import { ContextMenuListItemView } from '../context-menu/ContextMenuListItemView';
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { IFurnitureData, RoomObjectCategory } from '@nitrots/nitro-renderer';
|
import { IFurnitureData, RoomObjectCategory } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useEffect, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { GetFurnitureDataForRoomObject, LocalizeText, RoomWidgetUseProductMessage } from '../../../../../api';
|
import { FurniCategory, GetFurnitureDataForRoomObject, LocalizeText, RoomWidgetUseProductMessage } from '../../../../../api';
|
||||||
import { Base, Button, Column, Flex, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../../common';
|
import { Base, Button, Column, Flex, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../../common';
|
||||||
import { FurniCategory } from '../../../../inventory/common/FurniCategory';
|
|
||||||
import { useRoomContext } from '../../../RoomContext';
|
import { useRoomContext } from '../../../RoomContext';
|
||||||
|
|
||||||
interface MonsterPlantSeedConfirmViewProps
|
interface MonsterPlantSeedConfirmViewProps
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import { RedeemItemClothingComposer, RoomObjectCategory, UserFigureComposer } from '@nitrots/nitro-renderer';
|
import { RedeemItemClothingComposer, RoomObjectCategory, UserFigureComposer } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useEffect, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { GetAvatarRenderManager, GetConnection, GetFurnitureDataForRoomObject, GetSessionDataManager, LocalizeText } from '../../../../../api';
|
import { FurniCategory, GetAvatarRenderManager, GetConnection, GetFurnitureDataForRoomObject, GetSessionDataManager, LocalizeText } from '../../../../../api';
|
||||||
import { Base, Button, Column, Flex, LayoutAvatarImageView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../../common';
|
import { Base, Button, Column, Flex, LayoutAvatarImageView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../../common';
|
||||||
import { FigureData } from '../../../../avatar-editor/common/FigureData';
|
import { FigureData } from '../../../../avatar-editor/common/FigureData';
|
||||||
import { FurniCategory } from '../../../../inventory/common/FurniCategory';
|
|
||||||
import { useRoomContext } from '../../../RoomContext';
|
import { useRoomContext } from '../../../RoomContext';
|
||||||
|
|
||||||
interface PurchasableClothingConfirmViewProps
|
interface PurchasableClothingConfirmViewProps
|
||||||
|
@ -2,8 +2,8 @@ import { Dispose, DropBounce, EaseOut, FigureUpdateEvent, JumpBy, Motions, Nitro
|
|||||||
import { FC, useCallback, useState } from 'react';
|
import { FC, useCallback, useState } from 'react';
|
||||||
import { CreateLinkEvent, GetSessionDataManager, GetUserProfile, OpenMessengerChat, VisitDesktop } from '../../api';
|
import { CreateLinkEvent, GetSessionDataManager, GetUserProfile, OpenMessengerChat, VisitDesktop } from '../../api';
|
||||||
import { Base, Flex, LayoutAvatarImageView, LayoutItemCountView, TransitionAnimation, TransitionAnimationTypes } from '../../common';
|
import { Base, Flex, LayoutAvatarImageView, LayoutItemCountView, TransitionAnimation, TransitionAnimationTypes } from '../../common';
|
||||||
import { AchievementsUIUnseenCountEvent, FriendsEvent, FriendsMessengerIconEvent, FriendsRequestCountEvent, GuideToolEvent, InventoryEvent, ModToolsEvent, UnseenItemTrackerUpdateEvent, UserSettingsUIEvent } from '../../events';
|
import { AchievementsUIUnseenCountEvent, FriendsEvent, FriendsMessengerIconEvent, FriendsRequestCountEvent, GuideToolEvent, ModToolsEvent, UserSettingsUIEvent } from '../../events';
|
||||||
import { BatchUpdates, DispatchUiEvent, UseMessageEventHook, UseRoomEngineEvent, UseUiEvent } from '../../hooks';
|
import { BatchUpdates, DispatchUiEvent, UseMessageEventHook, UseRoomEngineEvent, useSharedInventoryUnseenTracker, UseUiEvent } from '../../hooks';
|
||||||
import { ToolbarViewItems } from './common/ToolbarViewItems';
|
import { ToolbarViewItems } from './common/ToolbarViewItems';
|
||||||
import { ToolbarMeView } from './ToolbarMeView';
|
import { ToolbarMeView } from './ToolbarMeView';
|
||||||
|
|
||||||
@ -25,9 +25,9 @@ export const ToolbarView: FC<ToolbarViewProps> = props =>
|
|||||||
const [ isMeExpanded, setMeExpanded ] = useState(false);
|
const [ isMeExpanded, setMeExpanded ] = useState(false);
|
||||||
const [ useGuideTool, setUseGuideTool ] = useState(false);
|
const [ useGuideTool, setUseGuideTool ] = useState(false);
|
||||||
const [ chatIconType, setChatIconType ] = useState(CHAT_ICON_HIDDEN);
|
const [ chatIconType, setChatIconType ] = useState(CHAT_ICON_HIDDEN);
|
||||||
const [ unseenInventoryCount, setUnseenInventoryCount ] = useState(0);
|
|
||||||
const [ unseenAchievementCount, setUnseenAchievementCount ] = useState(0);
|
const [ unseenAchievementCount, setUnseenAchievementCount ] = useState(0);
|
||||||
const [ unseenFriendRequestCount, setFriendRequestCount ] = useState(0);
|
const [ unseenFriendRequestCount, setFriendRequestCount ] = useState(0);
|
||||||
|
const { getFullCount = null } = useSharedInventoryUnseenTracker();
|
||||||
const isMod = GetSessionDataManager().isModerator;
|
const isMod = GetSessionDataManager().isModerator;
|
||||||
|
|
||||||
const onUserInfoEvent = useCallback((event: UserInfoEvent) =>
|
const onUserInfoEvent = useCallback((event: UserInfoEvent) =>
|
||||||
@ -68,13 +68,6 @@ export const ToolbarView: FC<ToolbarViewProps> = props =>
|
|||||||
|
|
||||||
UseUiEvent(FriendsMessengerIconEvent.UPDATE_ICON, onFriendsMessengerIconEvent);
|
UseUiEvent(FriendsMessengerIconEvent.UPDATE_ICON, onFriendsMessengerIconEvent);
|
||||||
|
|
||||||
const onUnseenItemTrackerUpdateEvent = useCallback((event: UnseenItemTrackerUpdateEvent) =>
|
|
||||||
{
|
|
||||||
setUnseenInventoryCount(event.count);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
UseUiEvent(UnseenItemTrackerUpdateEvent.UPDATE_COUNT, onUnseenItemTrackerUpdateEvent);
|
|
||||||
|
|
||||||
const onAchievementsUIUnseenCountEvent = useCallback((event: AchievementsUIUnseenCountEvent) =>
|
const onAchievementsUIUnseenCountEvent = useCallback((event: AchievementsUIUnseenCountEvent) =>
|
||||||
{
|
{
|
||||||
setUnseenAchievementCount(event.count);
|
setUnseenAchievementCount(event.count);
|
||||||
@ -138,7 +131,7 @@ export const ToolbarView: FC<ToolbarViewProps> = props =>
|
|||||||
CreateLinkEvent('navigator/toggle');
|
CreateLinkEvent('navigator/toggle');
|
||||||
return;
|
return;
|
||||||
case ToolbarViewItems.INVENTORY_ITEM:
|
case ToolbarViewItems.INVENTORY_ITEM:
|
||||||
DispatchUiEvent(new InventoryEvent(InventoryEvent.TOGGLE_INVENTORY));
|
CreateLinkEvent('inventory/toggle');
|
||||||
return;
|
return;
|
||||||
case ToolbarViewItems.CATALOG_ITEM:
|
case ToolbarViewItems.CATALOG_ITEM:
|
||||||
CreateLinkEvent('catalog/toggle');
|
CreateLinkEvent('catalog/toggle');
|
||||||
@ -178,6 +171,8 @@ export const ToolbarView: FC<ToolbarViewProps> = props =>
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const unseenInventoryCount = getFullCount();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TransitionAnimation type={ TransitionAnimationTypes.FADE_IN } inProp={ isMeExpanded } timeout={ 300 }>
|
<TransitionAnimation type={ TransitionAnimationTypes.FADE_IN } inProp={ isMeExpanded } timeout={ 300 }>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { CatalogEvent } from '.';
|
import { CatalogEvent } from '.';
|
||||||
import { FurnitureItem } from '../../components/inventory/common/FurnitureItem';
|
import { FurnitureItem } from '../../api';
|
||||||
|
|
||||||
export class CatalogPostMarketplaceOfferEvent extends CatalogEvent
|
export class CatalogPostMarketplaceOfferEvent extends CatalogEvent
|
||||||
{
|
{
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
import { NitroEvent } from '@nitrots/nitro-renderer';
|
|
||||||
|
|
||||||
export class InventoryBadgesRequestEvent extends NitroEvent
|
|
||||||
{
|
|
||||||
public static REQUEST_BADGES: string = 'IBRE_REQUEST_BADGES';
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
import { NitroEvent } from '@nitrots/nitro-renderer';
|
|
||||||
|
|
||||||
export class InventoryBadgesUpdatedEvent extends NitroEvent
|
|
||||||
{
|
|
||||||
public static BADGES_UPDATED: string = 'IBUE_BADGES_UPDATED';
|
|
||||||
|
|
||||||
private _badges: string[] = [];
|
|
||||||
|
|
||||||
constructor(type: string, badges: string[] = [])
|
|
||||||
{
|
|
||||||
super(type);
|
|
||||||
|
|
||||||
this._badges = badges;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get badges(): string[]
|
|
||||||
{
|
|
||||||
return this._badges;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
import { TradeUserData } from '../../components/inventory/common/TradeUserData';
|
import { TradeUserData } from '../../api';
|
||||||
import { InventoryEvent } from './InventoryEvent';
|
import { InventoryEvent } from './InventoryEvent';
|
||||||
|
|
||||||
export class InventoryTradeStartEvent extends InventoryEvent
|
export class InventoryTradeStartEvent extends InventoryEvent
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
import { NitroEvent } from '@nitrots/nitro-renderer';
|
|
||||||
|
|
||||||
export class UnseenItemTrackerUpdateEvent extends NitroEvent
|
|
||||||
{
|
|
||||||
public static UPDATE_COUNT: string = 'UITUE_UPDATE_COUNTER';
|
|
||||||
|
|
||||||
private _count: number;
|
|
||||||
|
|
||||||
constructor(count: number)
|
|
||||||
{
|
|
||||||
super(UnseenItemTrackerUpdateEvent.UPDATE_COUNT);
|
|
||||||
|
|
||||||
this._count = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get count(): number
|
|
||||||
{
|
|
||||||
return this._count;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,3 @@
|
|||||||
export * from './InventoryBadgesRequestEvent';
|
|
||||||
export * from './InventoryBadgesUpdatedEvent';
|
|
||||||
export * from './InventoryEvent';
|
export * from './InventoryEvent';
|
||||||
export * from './InventoryTradeRequestEvent';
|
export * from './InventoryTradeRequestEvent';
|
||||||
export * from './InventoryTradeStartEvent';
|
export * from './InventoryTradeStartEvent';
|
||||||
export * from './UnseenItemTrackerUpdateEvent';
|
|
||||||
|
@ -3,6 +3,8 @@ export * from './events';
|
|||||||
export * from './events/core';
|
export * from './events/core';
|
||||||
export * from './events/nitro';
|
export * from './events/nitro';
|
||||||
export * from './events/ui';
|
export * from './events/ui';
|
||||||
|
export * from './inventory';
|
||||||
export * from './messages';
|
export * from './messages';
|
||||||
export * from './navigator';
|
export * from './navigator';
|
||||||
export * from './UseMountEffect';
|
export * from './UseMountEffect';
|
||||||
|
export * from './useSharedVisibility';
|
||||||
|
182
src/hooks/inventory/common/FurnitureUtilities.ts
Normal file
182
src/hooks/inventory/common/FurnitureUtilities.ts
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
import { FurnitureListItemParser, IObjectData } from '@nitrots/nitro-renderer';
|
||||||
|
import { DispatchUiEvent } from '../..';
|
||||||
|
import { FurniCategory, FurnitureItem, GetRoomEngine, GroupItem } from '../../../api';
|
||||||
|
import { CatalogPostMarketplaceOfferEvent } from '../../../events';
|
||||||
|
|
||||||
|
export const attemptPlaceMarketplaceOffer = (groupItem: GroupItem) =>
|
||||||
|
{
|
||||||
|
const item = groupItem.getLastItem();
|
||||||
|
|
||||||
|
if(!item) return false;
|
||||||
|
|
||||||
|
if(!item.sellable) return false;
|
||||||
|
|
||||||
|
DispatchUiEvent(new CatalogPostMarketplaceOfferEvent(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createGroupItem = (type: number, category: number, stuffData: IObjectData, extra: number = NaN) => new GroupItem(type, category, GetRoomEngine(), stuffData, extra);
|
||||||
|
|
||||||
|
const addSingleFurnitureItem = (set: GroupItem[], item: FurnitureItem, unseen: boolean) =>
|
||||||
|
{
|
||||||
|
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 groupItem = createGroupItem(item.type, item.category, item.stuffData, item.extra);
|
||||||
|
|
||||||
|
groupItem.push(item);
|
||||||
|
|
||||||
|
if(unseen)
|
||||||
|
{
|
||||||
|
groupItem.hasUnseenItems = true;
|
||||||
|
|
||||||
|
set.unshift(groupItem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set.push(groupItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return groupItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
const addGroupableFurnitureItem = (set: GroupItem[], item: FurnitureItem, unseen: boolean) =>
|
||||||
|
{
|
||||||
|
let existingGroup: GroupItem = null;
|
||||||
|
|
||||||
|
for(const groupItem of set)
|
||||||
|
{
|
||||||
|
if((groupItem.type === item.type) && (groupItem.isWallItem === item.isWallItem) && groupItem.isGroupable)
|
||||||
|
{
|
||||||
|
if(item.category === FurniCategory.POSTER)
|
||||||
|
{
|
||||||
|
if(groupItem.stuffData.getLegacyString() === item.stuffData.getLegacyString())
|
||||||
|
{
|
||||||
|
existingGroup = groupItem;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(item.category === FurniCategory.GUILD_FURNI)
|
||||||
|
{
|
||||||
|
if(item.stuffData.compare(groupItem.stuffData))
|
||||||
|
{
|
||||||
|
existingGroup = groupItem;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
existingGroup = groupItem;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(existingGroup)
|
||||||
|
{
|
||||||
|
existingGroup.push(item);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
existingGroup.push(item);
|
||||||
|
|
||||||
|
if(unseen)
|
||||||
|
{
|
||||||
|
existingGroup.hasUnseenItems = true;
|
||||||
|
|
||||||
|
set.unshift(existingGroup);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set.push(existingGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
return existingGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const addFurnitureItem = (set: GroupItem[], item: FurnitureItem, unseen: boolean) =>
|
||||||
|
{
|
||||||
|
if(!item.isGroupable)
|
||||||
|
{
|
||||||
|
addSingleFurnitureItem(set, item, unseen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addGroupableFurnitureItem(set, item, unseen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mergeFurniFragments = (fragment: Map<number, FurnitureListItemParser>, totalFragments: number, fragmentNumber: number, fragments: Map<number, FurnitureListItemParser>[]) =>
|
||||||
|
{
|
||||||
|
if(totalFragments === 1) return fragment;
|
||||||
|
|
||||||
|
fragments[fragmentNumber] = fragment;
|
||||||
|
|
||||||
|
for(const frag of fragments)
|
||||||
|
{
|
||||||
|
if(!frag) return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const merged: Map<number, FurnitureListItemParser> = new Map();
|
||||||
|
|
||||||
|
for(const frag of fragments)
|
||||||
|
{
|
||||||
|
for(const [ key, value ] of frag) merged.set(key, value);
|
||||||
|
|
||||||
|
frag.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
fragments = null;
|
||||||
|
|
||||||
|
return merged;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getAllItemIds = (groupItems: GroupItem[]) =>
|
||||||
|
{
|
||||||
|
const itemIds: number[] = [];
|
||||||
|
|
||||||
|
for(const groupItem of groupItems)
|
||||||
|
{
|
||||||
|
let totalCount = groupItem.getTotalCount();
|
||||||
|
|
||||||
|
if(groupItem.category === FurniCategory.POST_IT) totalCount = 1;
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
while(i < totalCount)
|
||||||
|
{
|
||||||
|
itemIds.push(groupItem.getItemByIndex(i).id);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemIds;
|
||||||
|
}
|
102
src/hooks/inventory/common/PetUtilities.ts
Normal file
102
src/hooks/inventory/common/PetUtilities.ts
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import { PetData } from '@nitrots/nitro-renderer';
|
||||||
|
import { cancelRoomObjectPlacement, CreateLinkEvent, getPlacingItemId, UnseenItemCategory } from '../../../api';
|
||||||
|
import { IPetItem } from '../../../api/inventory/IPetItem';
|
||||||
|
|
||||||
|
export const getAllPetIds = (petItems: IPetItem[]) => petItems.map(item => item.petData.id);
|
||||||
|
|
||||||
|
export const addSinglePetItem = (petData: PetData, set: IPetItem[], unseen: boolean = true) =>
|
||||||
|
{
|
||||||
|
const petItem = { petData };
|
||||||
|
|
||||||
|
if(unseen)
|
||||||
|
{
|
||||||
|
//petItem.isUnseen = true;
|
||||||
|
|
||||||
|
set.unshift(petItem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set.push(petItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return petItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const removePetItemById = (id: number, set: IPetItem[]) =>
|
||||||
|
{
|
||||||
|
let index = 0;
|
||||||
|
|
||||||
|
while(index < set.length)
|
||||||
|
{
|
||||||
|
const petItem = set[index];
|
||||||
|
|
||||||
|
if(petItem && (petItem.petData.id === id))
|
||||||
|
{
|
||||||
|
if(getPlacingItemId() === petItem.petData.id)
|
||||||
|
{
|
||||||
|
cancelRoomObjectPlacement();
|
||||||
|
|
||||||
|
CreateLinkEvent('inventory/open');
|
||||||
|
}
|
||||||
|
|
||||||
|
set.splice(index, 1);
|
||||||
|
|
||||||
|
return petItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const processPetFragment = (set: IPetItem[], fragment: Map<number, PetData>, isUnseen: (category: number, itemId: number) => boolean) =>
|
||||||
|
{
|
||||||
|
const existingIds = getAllPetIds(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);
|
||||||
|
|
||||||
|
for(const id of removedIds) removePetItemById(id, set);
|
||||||
|
|
||||||
|
for(const id of addedIds)
|
||||||
|
{
|
||||||
|
const parser = fragment.get(id);
|
||||||
|
|
||||||
|
if(!parser) continue;
|
||||||
|
|
||||||
|
addSinglePetItem(parser, set, isUnseen(UnseenItemCategory.PET, parser.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mergePetFragments = (fragment: Map<number, PetData>, totalFragments: number, fragmentNumber: number, fragments: Map<number, PetData>[]) =>
|
||||||
|
{
|
||||||
|
if(totalFragments === 1) return fragment;
|
||||||
|
|
||||||
|
fragments[fragmentNumber] = fragment;
|
||||||
|
|
||||||
|
for(const frag of fragments)
|
||||||
|
{
|
||||||
|
if(!frag) return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const merged: Map<number, PetData> = new Map();
|
||||||
|
|
||||||
|
for(const frag of fragments)
|
||||||
|
{
|
||||||
|
for(const [ key, value ] of frag) merged.set(key, value);
|
||||||
|
|
||||||
|
frag.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
fragments = null;
|
||||||
|
|
||||||
|
return merged;
|
||||||
|
}
|
@ -1,22 +1,15 @@
|
|||||||
import { AdvancedMap, IObjectData, ItemDataStructure, StringDataType } from '@nitrots/nitro-renderer';
|
import { AdvancedMap, IObjectData, ItemDataStructure, StringDataType } from '@nitrots/nitro-renderer';
|
||||||
import { GetSessionDataManager } from '../../../api';
|
import { createGroupItem } from '.';
|
||||||
import { FurniCategory } from './FurniCategory';
|
import { FurniCategory, FurnitureItem, GetSessionDataManager, GroupItem } from '../../../api';
|
||||||
import { FurnitureItem } from './FurnitureItem';
|
|
||||||
import { createGroupItem } from './FurnitureUtilities';
|
|
||||||
import { GroupItem } from './GroupItem';
|
|
||||||
|
|
||||||
function isExternalImage(spriteId: number): boolean
|
const isExternalImage = (spriteId: number) => GetSessionDataManager().getWallItemData(spriteId)?.isExternalImage || false;
|
||||||
{
|
|
||||||
const furnitureData = GetSessionDataManager().getWallItemData(spriteId);
|
export const parseTradeItems = (items: ItemDataStructure[]) =>
|
||||||
|
|
||||||
return (furnitureData && furnitureData.isExternalImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parseTradeItems(items: ItemDataStructure[], _arg_2: AdvancedMap<string, GroupItem>): void
|
|
||||||
{
|
{
|
||||||
|
const existingItems = new AdvancedMap<string, GroupItem>();
|
||||||
const totalItems = items.length;
|
const totalItems = items.length;
|
||||||
|
|
||||||
if(!totalItems) return;
|
if(!totalItems) return null;
|
||||||
|
|
||||||
for(const item of items)
|
for(const item of items)
|
||||||
{
|
{
|
||||||
@ -40,33 +33,34 @@ export function parseTradeItems(items: ItemDataStructure[], _arg_2: AdvancedMap<
|
|||||||
name = '';
|
name = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
let groupItem = ((item.isGroupable && !isExternalImage(item.spriteId)) ? _arg_2.getValue(name) : null);
|
let groupItem = ((item.isGroupable && !isExternalImage(item.spriteId)) ? existingItems.getValue(name) : null);
|
||||||
|
|
||||||
if(!groupItem)
|
if(!groupItem)
|
||||||
{
|
{
|
||||||
groupItem = createGroupItem(spriteId, category, item.stuffData);
|
groupItem = createGroupItem(spriteId, category, item.stuffData);
|
||||||
|
|
||||||
_arg_2.add(name, groupItem);
|
existingItems.add(name, groupItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
groupItem.push(new FurnitureItem(item));
|
groupItem.push(new FurnitureItem(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return existingItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function _Str_16998(spriteId: number, stuffData: IObjectData): string
|
export const getGuildFurniType = (spriteId: number, stuffData: IObjectData) =>
|
||||||
{
|
{
|
||||||
let type = spriteId.toString();
|
let type = spriteId.toString();
|
||||||
const _local_4 = (stuffData as StringDataType);
|
|
||||||
|
|
||||||
if(!(stuffData instanceof StringDataType)) return type;
|
if(!(stuffData instanceof StringDataType)) return type;
|
||||||
|
|
||||||
let _local_5 = 1;
|
let i = 1;
|
||||||
|
|
||||||
while(_local_5 < 5)
|
while(i < 5)
|
||||||
{
|
{
|
||||||
type = (type + (',' + _local_4.getValue(_local_5)));
|
type = (type + (',' + stuffData.getValue(i)));
|
||||||
|
|
||||||
_local_5++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return type;
|
return type;
|
3
src/hooks/inventory/common/index.ts
Normal file
3
src/hooks/inventory/common/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from './FurnitureUtilities';
|
||||||
|
export * from './PetUtilities';
|
||||||
|
export * from './TradingUtilities';
|
7
src/hooks/inventory/index.ts
Normal file
7
src/hooks/inventory/index.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export * from './common';
|
||||||
|
export * from './useSharedInventoryBadges';
|
||||||
|
export * from './useSharedInventoryBots';
|
||||||
|
export * from './useSharedInventoryFurni';
|
||||||
|
export * from './useSharedInventoryPets';
|
||||||
|
export * from './useSharedInventoryTrade';
|
||||||
|
export * from './useSharedInventoryUnseenTracker';
|
148
src/hooks/inventory/useSharedInventoryBadges.ts
Normal file
148
src/hooks/inventory/useSharedInventoryBadges.ts
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
import { BadgeReceivedEvent, BadgesEvent, RequestBadgesComposer, SetActivatedBadgesComposer } from '@nitrots/nitro-renderer';
|
||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { useBetween } from 'use-between';
|
||||||
|
import { BatchUpdates, UseMessageEventHook } from '..';
|
||||||
|
import { GetConfiguration, IBadgeItem, SendMessageComposer } from '../../api';
|
||||||
|
import { useSharedVisibility } from '../useSharedVisibility';
|
||||||
|
|
||||||
|
const useInventoryBadges = () =>
|
||||||
|
{
|
||||||
|
const [ isVisible, setIsVisible ] = useState(false);
|
||||||
|
const [ needsUpdate, setNeedsUpdate ] = useState(true);
|
||||||
|
const [ badges, setBadges ] = useState<IBadgeItem[]>([]);
|
||||||
|
const [ activeBadges, setActiveBadges ] = useState<IBadgeItem[]>([]);
|
||||||
|
const [ selectedBadge, setSelectedBadge ] = useState<IBadgeItem>(null);
|
||||||
|
|
||||||
|
const maxBadgeCount = GetConfiguration<number>('user.badges.max.slots', 5);
|
||||||
|
const isWearingBadge = (badge: IBadgeItem) => (activeBadges.indexOf(badge) >= 0);
|
||||||
|
const canWearBadges = () => (activeBadges.length < maxBadgeCount);
|
||||||
|
|
||||||
|
const toggleBadge = (badge: IBadgeItem) =>
|
||||||
|
{
|
||||||
|
setActiveBadges(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = [ ...prevValue ];
|
||||||
|
|
||||||
|
const index = newValue.indexOf(badge);
|
||||||
|
|
||||||
|
if(index === -1)
|
||||||
|
{
|
||||||
|
if(!canWearBadges()) return prevValue;
|
||||||
|
|
||||||
|
newValue.push(badge);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newValue.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const composer = new SetActivatedBadgesComposer();
|
||||||
|
|
||||||
|
for(let i = 0; i < maxBadgeCount; i++) composer.addActivatedBadge((newValue[i] && newValue[i].badgeCode) || null);
|
||||||
|
|
||||||
|
SendMessageComposer(composer);
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectBadge = (badge: IBadgeItem) =>
|
||||||
|
{
|
||||||
|
if(badges.indexOf(badge) === -1) return;
|
||||||
|
|
||||||
|
setSelectedBadge(badge);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onBadgesEvent = useCallback((event: BadgesEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
BatchUpdates(() =>
|
||||||
|
{
|
||||||
|
setBadges(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue: IBadgeItem[] = [];
|
||||||
|
const badgeCodes = parser.getAllBadgeCodes();
|
||||||
|
|
||||||
|
for(const badgeCode of badgeCodes) newValue.push({ id: parser.getBadgeId(badgeCode), badgeCode });
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
setActiveBadges(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue: IBadgeItem[] = [];
|
||||||
|
const badgeCodes = parser.getActiveBadgeCodes();
|
||||||
|
|
||||||
|
for(const badgeCode of badgeCodes) newValue.push({ id: parser.getBadgeId(badgeCode), badgeCode });
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(BadgesEvent, onBadgesEvent);
|
||||||
|
|
||||||
|
const onBadgeReceivedEvent = useCallback((event: BadgeReceivedEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setBadges(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = [ ...prevValue ];
|
||||||
|
|
||||||
|
newValue.push({ id: parser.badgeId, badgeCode: parser.badgeCode });
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(BadgeReceivedEvent, onBadgeReceivedEvent);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!badges || !badges.length) return;
|
||||||
|
|
||||||
|
setSelectedBadge(prevValue =>
|
||||||
|
{
|
||||||
|
let newValue = prevValue;
|
||||||
|
|
||||||
|
if(newValue && (badges.indexOf(newValue) === -1)) newValue = null;
|
||||||
|
|
||||||
|
if(!newValue) newValue = badges[0];
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}, [ badges ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!isVisible || !needsUpdate) return;
|
||||||
|
|
||||||
|
SendMessageComposer(new RequestBadgesComposer());
|
||||||
|
|
||||||
|
setNeedsUpdate(false);
|
||||||
|
}, [ isVisible, needsUpdate ]);
|
||||||
|
|
||||||
|
return { badges, activeBadges, selectedBadge, isWearingBadge, canWearBadges, toggleBadge, selectBadge, setIsVisible };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSharedInventoryBadges = () =>
|
||||||
|
{
|
||||||
|
const { setIsVisible, ...rest } = useBetween(useInventoryBadges);
|
||||||
|
const { isVisible = false, activate = null, deactivate = null } = useSharedVisibility();
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
const id = activate();
|
||||||
|
|
||||||
|
return () => deactivate(id);
|
||||||
|
}, [ activate, deactivate ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
setIsVisible(isVisible);
|
||||||
|
}, [ isVisible, setIsVisible ]);
|
||||||
|
|
||||||
|
return { ...rest };
|
||||||
|
}
|
172
src/hooks/inventory/useSharedInventoryBots.ts
Normal file
172
src/hooks/inventory/useSharedInventoryBots.ts
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
import { BotAddedToInventoryEvent, BotData, BotInventoryMessageEvent, BotRemovedFromInventoryEvent, GetBotInventoryComposer } from '@nitrots/nitro-renderer';
|
||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { useBetween } from 'use-between';
|
||||||
|
import { useSharedInventoryUnseenTracker } from '.';
|
||||||
|
import { UseMessageEventHook } from '..';
|
||||||
|
import { cancelRoomObjectPlacement, CreateLinkEvent, getPlacingItemId, IBotItem, SendMessageComposer, UnseenItemCategory } from '../../api';
|
||||||
|
import { useSharedVisibility } from '../useSharedVisibility';
|
||||||
|
|
||||||
|
const useInventoryBots = () =>
|
||||||
|
{
|
||||||
|
const [ isVisible, setIsVisible ] = useState(false);
|
||||||
|
const [ needsUpdate, setNeedsUpdate ] = useState(true);
|
||||||
|
const [ botItems, setBotItems ] = useState<IBotItem[]>([]);
|
||||||
|
const [ selectedBot, setSelectedBot ] = useState<IBotItem>(null);
|
||||||
|
const { isUnseen = null } = useSharedInventoryUnseenTracker();
|
||||||
|
|
||||||
|
const selectBot = (bot: IBotItem) => setSelectedBot(bot);
|
||||||
|
|
||||||
|
const onBotInventoryMessageEvent = useCallback((event: BotInventoryMessageEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setBotItems(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = [ ...prevValue ];
|
||||||
|
const existingIds = newValue.map(item => item.botData.id);
|
||||||
|
const addedDatas: BotData[] = [];
|
||||||
|
|
||||||
|
for(const botData of parser.items.values()) ((existingIds.indexOf(botData.id) === -1) && addedDatas.push(botData));
|
||||||
|
|
||||||
|
for(const existingId of existingIds)
|
||||||
|
{
|
||||||
|
let remove = true;
|
||||||
|
|
||||||
|
for(const botData of parser.items.values())
|
||||||
|
{
|
||||||
|
if(botData.id === existingId)
|
||||||
|
{
|
||||||
|
remove = false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!remove) continue;
|
||||||
|
|
||||||
|
const index = newValue.findIndex(item => (item.botData.id === existingId));
|
||||||
|
const botItem = newValue[index];
|
||||||
|
|
||||||
|
if((index === -1) || !botItem) continue;
|
||||||
|
|
||||||
|
if(getPlacingItemId() === botItem.botData.id)
|
||||||
|
{
|
||||||
|
cancelRoomObjectPlacement();
|
||||||
|
|
||||||
|
CreateLinkEvent('inventory/open');
|
||||||
|
}
|
||||||
|
|
||||||
|
newValue.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const botData of addedDatas)
|
||||||
|
{
|
||||||
|
const botItem = { botData } as IBotItem;
|
||||||
|
const unseen = isUnseen(UnseenItemCategory.BOT, botData.id);
|
||||||
|
|
||||||
|
if(unseen) newValue.unshift(botItem);
|
||||||
|
newValue.push(botItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}, [ isUnseen ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(BotInventoryMessageEvent, onBotInventoryMessageEvent);
|
||||||
|
|
||||||
|
const onBotAddedToInventoryEvent = useCallback((event: BotAddedToInventoryEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setBotItems(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = [ ...prevValue ];
|
||||||
|
|
||||||
|
const index = newValue.findIndex(item => (item.botData.id === parser.item.id));
|
||||||
|
|
||||||
|
if(index >= 0) return prevValue;
|
||||||
|
|
||||||
|
const botItem = { botData: parser.item } as IBotItem;
|
||||||
|
|
||||||
|
newValue.push(botItem);
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(BotAddedToInventoryEvent, onBotAddedToInventoryEvent);
|
||||||
|
|
||||||
|
const onBotRemovedFromInventoryEvent = useCallback((event: BotRemovedFromInventoryEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setBotItems(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = [ ...prevValue ];
|
||||||
|
|
||||||
|
const index = newValue.findIndex(item => (item.botData.id === parser.itemId));
|
||||||
|
|
||||||
|
if(index === -1) return prevValue;
|
||||||
|
|
||||||
|
newValue.splice(index, 1);
|
||||||
|
|
||||||
|
if(getPlacingItemId() === parser.itemId)
|
||||||
|
{
|
||||||
|
cancelRoomObjectPlacement();
|
||||||
|
|
||||||
|
CreateLinkEvent('inventory/show');
|
||||||
|
}
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(BotRemovedFromInventoryEvent, onBotRemovedFromInventoryEvent);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!botItems || !botItems.length) return;
|
||||||
|
|
||||||
|
setSelectedBot(prevValue =>
|
||||||
|
{
|
||||||
|
let newValue = prevValue;
|
||||||
|
|
||||||
|
if(newValue && (botItems.indexOf(newValue) === -1)) newValue = null;
|
||||||
|
|
||||||
|
if(!newValue) newValue = botItems[0];
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}, [ botItems ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!isVisible || !needsUpdate) return;
|
||||||
|
|
||||||
|
SendMessageComposer(new GetBotInventoryComposer());
|
||||||
|
|
||||||
|
setNeedsUpdate(false);
|
||||||
|
}, [ isVisible, needsUpdate ]);
|
||||||
|
|
||||||
|
return { botItems, selectedBot, selectBot, setIsVisible };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSharedInventoryBots = () =>
|
||||||
|
{
|
||||||
|
const { setIsVisible, ...rest } = useBetween(useInventoryBots);
|
||||||
|
const { isVisible = false, activate = null, deactivate = null } = useSharedVisibility();
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
const id = activate();
|
||||||
|
|
||||||
|
return () => deactivate(id);
|
||||||
|
}, [ activate, deactivate ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
setIsVisible(isVisible);
|
||||||
|
}, [ isVisible, setIsVisible ]);
|
||||||
|
|
||||||
|
return { ...rest };
|
||||||
|
}
|
264
src/hooks/inventory/useSharedInventoryFurni.ts
Normal file
264
src/hooks/inventory/useSharedInventoryFurni.ts
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
import { FurnitureListAddOrUpdateEvent, FurnitureListComposer, FurnitureListEvent, FurnitureListInvalidateEvent, FurnitureListItemParser, FurnitureListRemovedEvent, FurniturePostItPlacedEvent } from '@nitrots/nitro-renderer';
|
||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { useBetween } from 'use-between';
|
||||||
|
import { useSharedInventoryUnseenTracker } from '.';
|
||||||
|
import { UseMessageEventHook } from '..';
|
||||||
|
import { attemptItemPlacement, cancelRoomObjectPlacement, CloneObject, CreateLinkEvent, FurnitureItem, getPlacingItemId, GroupItem, SendMessageComposer, UnseenItemCategory } from '../../api';
|
||||||
|
import { useSharedVisibility } from '../useSharedVisibility';
|
||||||
|
import { addFurnitureItem, getAllItemIds, mergeFurniFragments } from './common';
|
||||||
|
|
||||||
|
let furniMsgFragments: Map<number, FurnitureListItemParser>[] = null;
|
||||||
|
|
||||||
|
const useInventoryFurni = () =>
|
||||||
|
{
|
||||||
|
const [ isVisible, setIsVisible ] = useState(false);
|
||||||
|
const [ needsUpdate, setNeedsUpdate ] = useState(true);
|
||||||
|
const [ groupItems, setGroupItems ] = useState<GroupItem[]>([]);
|
||||||
|
const [ selectedItem, setSelectedItem ] = useState<GroupItem>(null);
|
||||||
|
const { isUnseen = null, removeUnseen = null, resetCategory = null, getCount = null } = useSharedInventoryUnseenTracker();
|
||||||
|
|
||||||
|
const selectItem = (item: GroupItem) =>
|
||||||
|
{
|
||||||
|
//removeUnseen(UnseenItemCategory.FURNI, item.id);
|
||||||
|
|
||||||
|
setSelectedItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onFurnitureListAddOrUpdateEvent = useCallback((event: FurnitureListAddOrUpdateEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setGroupItems(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = [ ...prevValue ];
|
||||||
|
|
||||||
|
for(const item of parser.items)
|
||||||
|
{
|
||||||
|
let i = 0;
|
||||||
|
let groupItem: GroupItem = null;
|
||||||
|
|
||||||
|
while(i < newValue.length)
|
||||||
|
{
|
||||||
|
const group = newValue[i];
|
||||||
|
|
||||||
|
let j = 0;
|
||||||
|
|
||||||
|
while(j < group.items.length)
|
||||||
|
{
|
||||||
|
const furniture = group.items[j];
|
||||||
|
|
||||||
|
if(furniture.id === item.itemId)
|
||||||
|
{
|
||||||
|
furniture.update(item);
|
||||||
|
|
||||||
|
const newFurniture = [ ...group.items ];
|
||||||
|
|
||||||
|
newFurniture[j] = furniture;
|
||||||
|
|
||||||
|
group.items = newFurniture;
|
||||||
|
|
||||||
|
groupItem = group;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
|
||||||
|
if(groupItem) break;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(groupItem)
|
||||||
|
{
|
||||||
|
groupItem.hasUnseenItems = true;
|
||||||
|
|
||||||
|
newValue[i] = CloneObject(groupItem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const furniture = new FurnitureItem(item);
|
||||||
|
|
||||||
|
addFurnitureItem(newValue, furniture, isUnseen(UnseenItemCategory.FURNI, item.itemId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}, [ isUnseen ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(FurnitureListAddOrUpdateEvent, onFurnitureListAddOrUpdateEvent);
|
||||||
|
|
||||||
|
const onFurnitureListEvent = useCallback((event: FurnitureListEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
if(!furniMsgFragments) furniMsgFragments = new Array(parser.totalFragments);
|
||||||
|
|
||||||
|
const fragment = mergeFurniFragments(parser.fragment, parser.totalFragments, parser.fragmentNumber, furniMsgFragments);
|
||||||
|
|
||||||
|
if(!fragment) return;
|
||||||
|
|
||||||
|
setGroupItems(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = [ ...prevValue ];
|
||||||
|
const existingIds = getAllItemIds(newValue);
|
||||||
|
|
||||||
|
for(const existingId of existingIds)
|
||||||
|
{
|
||||||
|
if(fragment.get(existingId)) continue;
|
||||||
|
|
||||||
|
let index = 0;
|
||||||
|
|
||||||
|
while(index < newValue.length)
|
||||||
|
{
|
||||||
|
const group = newValue[index];
|
||||||
|
const item = group.remove(existingId);
|
||||||
|
|
||||||
|
if(!item) index++;
|
||||||
|
|
||||||
|
if(getPlacingItemId() === item.ref)
|
||||||
|
{
|
||||||
|
cancelRoomObjectPlacement();
|
||||||
|
|
||||||
|
if(!attemptItemPlacement(group))
|
||||||
|
{
|
||||||
|
CreateLinkEvent('inventory/show');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(group.getTotalCount() <= 0)
|
||||||
|
{
|
||||||
|
newValue.splice(index, 1);
|
||||||
|
|
||||||
|
group.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const itemId of fragment.keys())
|
||||||
|
{
|
||||||
|
if(existingIds.indexOf(itemId) >= 0) continue;
|
||||||
|
|
||||||
|
const parser = fragment.get(itemId);
|
||||||
|
|
||||||
|
if(!parser) continue;
|
||||||
|
|
||||||
|
const item = new FurnitureItem(parser);
|
||||||
|
|
||||||
|
addFurnitureItem(newValue, item, isUnseen(UnseenItemCategory.FURNI, itemId));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
furniMsgFragments = null;
|
||||||
|
}, [ isUnseen ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(FurnitureListEvent, onFurnitureListEvent);
|
||||||
|
|
||||||
|
const onFurnitureListInvalidateEvent = useCallback((event: FurnitureListInvalidateEvent) =>
|
||||||
|
{
|
||||||
|
setNeedsUpdate(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(FurnitureListInvalidateEvent, onFurnitureListInvalidateEvent);
|
||||||
|
|
||||||
|
const onFurnitureListRemovedEvent = useCallback((event: FurnitureListRemovedEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setGroupItems(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = [ ...prevValue ];
|
||||||
|
|
||||||
|
let index = 0;
|
||||||
|
|
||||||
|
while(index < newValue.length)
|
||||||
|
{
|
||||||
|
const group = newValue[index];
|
||||||
|
const item = group.remove(parser.itemId);
|
||||||
|
|
||||||
|
if(!item) index++;
|
||||||
|
|
||||||
|
if(getPlacingItemId() === item.ref)
|
||||||
|
{
|
||||||
|
cancelRoomObjectPlacement();
|
||||||
|
|
||||||
|
if(!attemptItemPlacement(group)) CreateLinkEvent('inventory/show');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(group.getTotalCount() <= 0)
|
||||||
|
{
|
||||||
|
newValue.splice(index, 1);
|
||||||
|
|
||||||
|
group.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(FurnitureListRemovedEvent, onFurnitureListRemovedEvent);
|
||||||
|
|
||||||
|
const onFurniturePostItPlacedEvent = useCallback((event: FurniturePostItPlacedEvent) =>
|
||||||
|
{
|
||||||
|
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(FurniturePostItPlacedEvent, onFurniturePostItPlacedEvent);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!groupItems || !groupItems.length) return;
|
||||||
|
|
||||||
|
setSelectedItem(prevValue =>
|
||||||
|
{
|
||||||
|
let newValue = prevValue;
|
||||||
|
|
||||||
|
if(newValue && (groupItems.indexOf(newValue) === -1)) newValue = null;
|
||||||
|
|
||||||
|
if(!newValue) newValue = groupItems[0];
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}, [ groupItems ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!isVisible || !needsUpdate) return;
|
||||||
|
|
||||||
|
SendMessageComposer(new FurnitureListComposer());
|
||||||
|
|
||||||
|
setNeedsUpdate(false);
|
||||||
|
}, [ isVisible, needsUpdate ]);
|
||||||
|
|
||||||
|
return { groupItems, setGroupItems, selectedItem, selectItem, setIsVisible };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSharedInventoryFurni = () =>
|
||||||
|
{
|
||||||
|
const { setIsVisible, ...rest } = useBetween(useInventoryFurni);
|
||||||
|
const { isVisible = false, activate = null, deactivate = null } = useSharedVisibility();
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
const id = activate();
|
||||||
|
|
||||||
|
return () => deactivate(id);
|
||||||
|
}, [ activate, deactivate ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
setIsVisible(isVisible);
|
||||||
|
}, [ isVisible, setIsVisible ]);
|
||||||
|
|
||||||
|
return { ...rest };
|
||||||
|
}
|
125
src/hooks/inventory/useSharedInventoryPets.ts
Normal file
125
src/hooks/inventory/useSharedInventoryPets.ts
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
import { PetAddedToInventoryEvent, PetData, PetInventoryEvent, PetRemovedFromInventory, RequestPetsComposer } from '@nitrots/nitro-renderer';
|
||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { useBetween } from 'use-between';
|
||||||
|
import { useSharedInventoryUnseenTracker } from '.';
|
||||||
|
import { UseMessageEventHook } from '..';
|
||||||
|
import { SendMessageComposer } from '../../api';
|
||||||
|
import { IPetItem } from '../../api/inventory/IPetItem';
|
||||||
|
import { useSharedVisibility } from '../useSharedVisibility';
|
||||||
|
import { addSinglePetItem, mergePetFragments, processPetFragment, removePetItemById } from './common';
|
||||||
|
|
||||||
|
let petMsgFragments: Map<number, PetData>[] = null;
|
||||||
|
|
||||||
|
const useInventoryPets = () =>
|
||||||
|
{
|
||||||
|
const [ isVisible, setIsVisible ] = useState(false);
|
||||||
|
const [ needsUpdate, setNeedsUpdate ] = useState(true);
|
||||||
|
const [ petItems, setPetItems ] = useState<IPetItem[]>([]);
|
||||||
|
const [ selectedPet, setSelectedPet ] = useState<IPetItem>(null);
|
||||||
|
const { isUnseen = null } = useSharedInventoryUnseenTracker();
|
||||||
|
|
||||||
|
const selectPet = (pet: IPetItem) => setSelectedPet(pet);
|
||||||
|
|
||||||
|
const onPetInventoryEvent = useCallback((event: PetInventoryEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
if(!petMsgFragments) petMsgFragments = new Array(parser.totalFragments);
|
||||||
|
|
||||||
|
const fragment = mergePetFragments(parser.fragment, parser.totalFragments, parser.fragmentNumber, petMsgFragments);
|
||||||
|
|
||||||
|
if(!fragment) return;
|
||||||
|
|
||||||
|
setPetItems(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = [ ...prevValue ];
|
||||||
|
|
||||||
|
processPetFragment(newValue, fragment, isUnseen);
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
petMsgFragments = null;
|
||||||
|
}, [ isUnseen ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(PetInventoryEvent, onPetInventoryEvent);
|
||||||
|
|
||||||
|
const onPetAddedToInventoryEvent = useCallback((event: PetAddedToInventoryEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setPetItems(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = [ ...prevValue ];
|
||||||
|
|
||||||
|
addSinglePetItem(parser.pet, newValue, true);
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(PetAddedToInventoryEvent, onPetAddedToInventoryEvent);
|
||||||
|
|
||||||
|
const onPetRemovedFromInventory = useCallback((event: PetRemovedFromInventory) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setPetItems(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = [ ...prevValue ];
|
||||||
|
|
||||||
|
removePetItemById(parser.petId, newValue);
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(PetRemovedFromInventory, onPetRemovedFromInventory);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!petItems || !petItems.length) return;
|
||||||
|
|
||||||
|
setSelectedPet(prevValue =>
|
||||||
|
{
|
||||||
|
let newValue = prevValue;
|
||||||
|
|
||||||
|
if(newValue && (petItems.indexOf(newValue) === -1)) newValue = null;
|
||||||
|
|
||||||
|
if(!newValue) newValue = petItems[0];
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}, [ petItems ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!isVisible || !needsUpdate) return;
|
||||||
|
|
||||||
|
SendMessageComposer(new RequestPetsComposer());
|
||||||
|
|
||||||
|
setNeedsUpdate(false);
|
||||||
|
}, [ isVisible, needsUpdate ]);
|
||||||
|
|
||||||
|
return { petItems, selectedPet, selectPet, setIsVisible };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSharedInventoryPets = () =>
|
||||||
|
{
|
||||||
|
const { setIsVisible, ...rest } = useBetween(useInventoryPets);
|
||||||
|
const { isVisible = false, activate = null, deactivate = null } = useSharedVisibility();
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
const id = activate();
|
||||||
|
|
||||||
|
return () => deactivate(id);
|
||||||
|
}, [ activate, deactivate ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
setIsVisible(isVisible);
|
||||||
|
}, [ isVisible, setIsVisible ]);
|
||||||
|
|
||||||
|
return { ...rest };
|
||||||
|
}
|
293
src/hooks/inventory/useSharedInventoryTrade.ts
Normal file
293
src/hooks/inventory/useSharedInventoryTrade.ts
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
import { AdvancedMap, TradingAcceptComposer, TradingAcceptEvent, TradingCloseEvent, TradingCloseParser, TradingCompletedEvent, TradingConfirmationComposer, TradingConfirmationEvent, TradingListItemEvent, TradingListItemRemoveComposer, TradingNotOpenEvent, TradingOpenEvent, TradingOpenFailedEvent, TradingOpenFailedParser, TradingOtherNotAllowedEvent, TradingUnacceptComposer, TradingYouAreNotAllowedEvent } from '@nitrots/nitro-renderer';
|
||||||
|
import { useCallback, useState } from 'react';
|
||||||
|
import { useBetween } from 'use-between';
|
||||||
|
import { useSharedInventoryFurni } from '.';
|
||||||
|
import { BatchUpdates, UseMessageEventHook } from '..';
|
||||||
|
import { CloneObject, GetRoomSession, GetSessionDataManager, GroupItem, LocalizeText, NotificationUtilities, SendMessageComposer, TradeState, TradeUserData, TradingNotificationMessage, TradingNotificationType } from '../../api';
|
||||||
|
import { parseTradeItems } from './common';
|
||||||
|
|
||||||
|
const useInventoryTrade = () =>
|
||||||
|
{
|
||||||
|
const [ ownUser, setOwnUser ] = useState<TradeUserData>(null);
|
||||||
|
const [ otherUser, setOtherUser ] = useState<TradeUserData>(null);
|
||||||
|
const [ tradeState, setTradeState ] = useState(TradeState.TRADING_STATE_READY);
|
||||||
|
const { groupItems = [], setGroupItems = null } = useSharedInventoryFurni();
|
||||||
|
|
||||||
|
const progressTrade = () =>
|
||||||
|
{
|
||||||
|
switch(tradeState)
|
||||||
|
{
|
||||||
|
case TradeState.TRADING_STATE_RUNNING:
|
||||||
|
if(!otherUser.itemCount && !ownUser.accepts)
|
||||||
|
{
|
||||||
|
NotificationUtilities.simpleAlert(LocalizeText('inventory.trading.warning.other_not_offering'), null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ownUser.accepts)
|
||||||
|
{
|
||||||
|
SendMessageComposer(new TradingUnacceptComposer());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendMessageComposer(new TradingAcceptComposer());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case TradeState.TRADING_STATE_CONFIRMING:
|
||||||
|
SendMessageComposer(new TradingConfirmationComposer());
|
||||||
|
|
||||||
|
setTradeState(TradeState.TRADING_STATE_CONFIRMED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeItem = (group: GroupItem) =>
|
||||||
|
{
|
||||||
|
const item = group.getLastItem();
|
||||||
|
|
||||||
|
if(!item) return;
|
||||||
|
|
||||||
|
SendMessageComposer(new TradingListItemRemoveComposer(item.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
const onTradingAcceptEvent = useCallback((event: TradingAcceptEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
if(!ownUser || !otherUser) return;
|
||||||
|
|
||||||
|
if(ownUser.userId === parser.userID)
|
||||||
|
{
|
||||||
|
setOwnUser(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = CloneObject(prevValue);
|
||||||
|
|
||||||
|
newValue.accepts = parser.userAccepts;
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(otherUser.userId === parser.userID)
|
||||||
|
{
|
||||||
|
setOtherUser(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = CloneObject(prevValue);
|
||||||
|
|
||||||
|
newValue.accepts = parser.userAccepts;
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [ ownUser, otherUser ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(TradingAcceptEvent, onTradingAcceptEvent);
|
||||||
|
|
||||||
|
const onTradingCloseEvent = useCallback((event: TradingCloseEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
if(parser.reason === TradingCloseParser.ERROR_WHILE_COMMIT)
|
||||||
|
{
|
||||||
|
TradingNotificationMessage(TradingNotificationType.ERROR_WHILE_COMMIT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(ownUser && (parser.userID !== ownUser.userId))
|
||||||
|
{
|
||||||
|
TradingNotificationMessage(TradingNotificationType.ALERT_OTHER_CANCELLED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BatchUpdates(() =>
|
||||||
|
{
|
||||||
|
setOwnUser(null);
|
||||||
|
setOtherUser(null);
|
||||||
|
});
|
||||||
|
}, [ ownUser ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(TradingCloseEvent, onTradingCloseEvent);
|
||||||
|
|
||||||
|
const onTradingCompletedEvent = useCallback((event: TradingCompletedEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
BatchUpdates(() =>
|
||||||
|
{
|
||||||
|
setOwnUser(null);
|
||||||
|
setOtherUser(null);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(TradingCompletedEvent, onTradingCompletedEvent);
|
||||||
|
|
||||||
|
const onTradingConfirmationEvent = useCallback((event: TradingConfirmationEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setTradeState(TradeState.TRADING_STATE_COUNTDOWN);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(TradingConfirmationEvent, onTradingConfirmationEvent);
|
||||||
|
|
||||||
|
const onTradingListItemEvent = useCallback((event: TradingListItemEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
const firstUserItems = parseTradeItems(parser.firstUserItemArray);
|
||||||
|
const secondUserItems = parseTradeItems(parser.secondUserItemArray);
|
||||||
|
|
||||||
|
setOwnUser(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = CloneObject(prevValue);
|
||||||
|
|
||||||
|
if(newValue.userId === parser.firstUserID)
|
||||||
|
{
|
||||||
|
newValue.creditsCount = parser.firstUserNumCredits;
|
||||||
|
newValue.itemCount = parser.firstUserNumItems;
|
||||||
|
newValue.items = firstUserItems;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newValue.creditsCount = parser.secondUserNumCredits;
|
||||||
|
newValue.itemCount = parser.secondUserNumItems;
|
||||||
|
newValue.items = secondUserItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tradeIds: number[] = [];
|
||||||
|
|
||||||
|
for(const groupItem of newValue.items.getValues())
|
||||||
|
{
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
while(i < groupItem.getTotalCount())
|
||||||
|
{
|
||||||
|
const item = groupItem.getItemByIndex(i);
|
||||||
|
|
||||||
|
if(item) tradeIds.push(item.ref);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setGroupItems(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = [ ...prevValue ];
|
||||||
|
|
||||||
|
for(const groupItem of newValue) groupItem.lockItemIds(tradeIds);
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
setOtherUser(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = CloneObject(prevValue);
|
||||||
|
|
||||||
|
if(newValue.userId === parser.firstUserID)
|
||||||
|
{
|
||||||
|
newValue.creditsCount = parser.firstUserNumCredits;
|
||||||
|
newValue.itemCount = parser.firstUserNumItems;
|
||||||
|
newValue.items = firstUserItems;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newValue.creditsCount = parser.secondUserNumCredits;
|
||||||
|
newValue.itemCount = parser.secondUserNumItems;
|
||||||
|
newValue.items = secondUserItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}, [ setGroupItems ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(TradingListItemEvent, onTradingListItemEvent);
|
||||||
|
|
||||||
|
const onTradingNotOpenEvent = useCallback((event: TradingNotOpenEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
console.log(parser);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(TradingNotOpenEvent, onTradingNotOpenEvent);
|
||||||
|
|
||||||
|
const onTradingOpenEvent = useCallback((event: TradingOpenEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
const firstUser = new TradeUserData();
|
||||||
|
const firstUserData = GetRoomSession().userDataManager.getUserData(parser.userID);
|
||||||
|
|
||||||
|
firstUser.userItems = new AdvancedMap();
|
||||||
|
|
||||||
|
const secondUser = new TradeUserData();
|
||||||
|
const secondUserData = GetRoomSession().userDataManager.getUserData(parser.otherUserID);
|
||||||
|
|
||||||
|
secondUser.userItems = new AdvancedMap();
|
||||||
|
|
||||||
|
if(firstUserData.webID === GetSessionDataManager().userId)
|
||||||
|
{
|
||||||
|
firstUser.userId = firstUserData.webID;
|
||||||
|
firstUser.userName = firstUserData.name;
|
||||||
|
firstUser.canTrade = parser.userCanTrade;
|
||||||
|
|
||||||
|
secondUser.userId = secondUserData.webID;
|
||||||
|
secondUser.userName = secondUserData.name;
|
||||||
|
secondUser.canTrade = parser.otherUserCanTrade;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(secondUserData.webID === GetSessionDataManager().userId)
|
||||||
|
{
|
||||||
|
firstUser.userId = secondUserData.webID;
|
||||||
|
firstUser.userName = secondUserData.name;
|
||||||
|
firstUser.canTrade = parser.otherUserCanTrade;
|
||||||
|
|
||||||
|
secondUser.userId = firstUserData.webID;
|
||||||
|
secondUser.userName = firstUserData.name;
|
||||||
|
secondUser.canTrade = parser.userCanTrade;
|
||||||
|
}
|
||||||
|
|
||||||
|
BatchUpdates(() =>
|
||||||
|
{
|
||||||
|
setOwnUser(firstUser);
|
||||||
|
setOtherUser(secondUser);
|
||||||
|
setTradeState(TradeState.TRADING_STATE_RUNNING);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(TradingOpenEvent, onTradingOpenEvent);
|
||||||
|
|
||||||
|
const onTradingOpenFailedEvent = useCallback((event: TradingOpenFailedEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
if((parser.reason !== TradingOpenFailedParser.REASON_YOU_ARE_ALREADY_TRADING && (parser.reason !== TradingOpenFailedParser.REASON_OTHER_USER_ALREADY_TRADING))) return;
|
||||||
|
|
||||||
|
TradingNotificationMessage(TradingNotificationType.ALERT_ALREADY_OPEN);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(TradingOpenFailedEvent, onTradingOpenFailedEvent);
|
||||||
|
|
||||||
|
const onTradingOtherNotAllowedEvent = useCallback((event: TradingOtherNotAllowedEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
TradingNotificationMessage(TradingNotificationType.ALERT_OTHER_DISABLED);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(TradingOtherNotAllowedEvent, onTradingOtherNotAllowedEvent);
|
||||||
|
|
||||||
|
const onTradingYouAreNotAllowedEvent = useCallback((event: TradingYouAreNotAllowedEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
TradingNotificationMessage(TradingNotificationType.YOU_NOT_ALLOWED);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(TradingYouAreNotAllowedEvent, onTradingYouAreNotAllowedEvent);
|
||||||
|
|
||||||
|
return { ownUser, otherUser, tradeState, setTradeState, groupItems, progressTrade, removeItem };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSharedInventoryTrade = () => useBetween(useInventoryTrade);
|
143
src/hooks/inventory/useSharedInventoryUnseenTracker.ts
Normal file
143
src/hooks/inventory/useSharedInventoryUnseenTracker.ts
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
import { UnseenItemsEvent, UnseenResetCategoryComposer, UnseenResetItemsComposer } from '@nitrots/nitro-renderer';
|
||||||
|
import { useCallback, useState } from 'react';
|
||||||
|
import { useBetween } from 'use-between';
|
||||||
|
import { UseMessageEventHook } from '..';
|
||||||
|
import { SendMessageComposer } from '../../api';
|
||||||
|
|
||||||
|
const sendResetCategoryMessage = (category: number) => SendMessageComposer(new UnseenResetCategoryComposer(category));
|
||||||
|
const sendResetItemsMessage = (category: number, itemIds: number[]) => SendMessageComposer(new UnseenResetItemsComposer(category, ...itemIds));
|
||||||
|
|
||||||
|
const useInventoryUnseenTracker = () =>
|
||||||
|
{
|
||||||
|
const [ unseenItems, setUnseenItems ] = useState<Map<number, number[]>>(new Map());
|
||||||
|
const getIds = (category: number) => unseenItems.get(category);
|
||||||
|
const getCount = (category: number) => (unseenItems.get(category)?.length || 0);
|
||||||
|
|
||||||
|
const getFullCount = () =>
|
||||||
|
{
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
for(const key of unseenItems.keys()) count += getCount(key);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetCategory = (category: number) =>
|
||||||
|
{
|
||||||
|
if(!getCount(category)) return false;
|
||||||
|
|
||||||
|
setUnseenItems(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = new Map(prevValue);
|
||||||
|
|
||||||
|
newValue.delete(category);
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
sendResetCategoryMessage(category);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetCategoryIfEmpty = (category: number) =>
|
||||||
|
{
|
||||||
|
if(getCount(category)) return false;
|
||||||
|
|
||||||
|
setUnseenItems(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = new Map(prevValue);
|
||||||
|
|
||||||
|
newValue.delete(category);
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
sendResetCategoryMessage(category);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetItems = (category: number, itemIds: number[]) =>
|
||||||
|
{
|
||||||
|
if(!getCount(category)) return false;
|
||||||
|
|
||||||
|
setUnseenItems(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = new Map(prevValue);
|
||||||
|
const existing = newValue.get(category);
|
||||||
|
|
||||||
|
if(existing) for(const itemId of itemIds) existing.splice(existing.indexOf(itemId), 1);
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
sendResetItemsMessage(category, itemIds);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isUnseen = (category: number, itemId: number) =>
|
||||||
|
{
|
||||||
|
if(!unseenItems.has(category)) return false;
|
||||||
|
|
||||||
|
const items = unseenItems.get(category);
|
||||||
|
|
||||||
|
return (items.indexOf(itemId) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeUnseen = (category: number, itemId: number) =>
|
||||||
|
{
|
||||||
|
if(!unseenItems.has(category)) return false;
|
||||||
|
|
||||||
|
setUnseenItems(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = new Map(prevValue);
|
||||||
|
const items = newValue.get(category);
|
||||||
|
const index = items.indexOf(itemId);
|
||||||
|
|
||||||
|
if(index >= 0)
|
||||||
|
{
|
||||||
|
items.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const onUnseenItemsEvent = useCallback((event: UnseenItemsEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
console.log(parser);
|
||||||
|
|
||||||
|
setUnseenItems(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = new Map(prevValue);
|
||||||
|
|
||||||
|
for(const category of parser.categories)
|
||||||
|
{
|
||||||
|
let existing = newValue.get(category);
|
||||||
|
|
||||||
|
if(!existing)
|
||||||
|
{
|
||||||
|
existing = [];
|
||||||
|
|
||||||
|
newValue.set(category, existing);
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemIds = parser.getItemsByCategory(category);
|
||||||
|
|
||||||
|
for(const itemId of itemIds) ((existing.indexOf(itemId) === -1) && existing.push(itemId));
|
||||||
|
}
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(UnseenItemsEvent, onUnseenItemsEvent);
|
||||||
|
|
||||||
|
return { getIds, getCount, getFullCount, resetCategory, resetCategoryIfEmpty, resetItems, isUnseen, removeUnseen };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSharedInventoryUnseenTracker = () => useBetween(useInventoryUnseenTracker);
|
44
src/hooks/useSharedVisibility.ts
Normal file
44
src/hooks/useSharedVisibility.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
export const useSharedVisibility = () =>
|
||||||
|
{
|
||||||
|
const [ activeIds, setActiveIds ] = useState<number[]>([]);
|
||||||
|
|
||||||
|
const isVisible = useMemo(() => !!activeIds.length, [ activeIds ]);
|
||||||
|
|
||||||
|
const activate = useCallback(() =>
|
||||||
|
{
|
||||||
|
let id = -1;
|
||||||
|
|
||||||
|
setActiveIds(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = [ ...prevValue ];
|
||||||
|
|
||||||
|
id = newValue.length ? (newValue[(newValue.length - 1)] + 1) : 0;
|
||||||
|
|
||||||
|
newValue.push(id);
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const deactivate = useCallback((id: number) =>
|
||||||
|
{
|
||||||
|
setActiveIds(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = [ ...prevValue ];
|
||||||
|
|
||||||
|
const index = newValue.indexOf(id);
|
||||||
|
|
||||||
|
if(index === -1) return prevValue;
|
||||||
|
|
||||||
|
newValue.splice(index, 1);
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return { isVisible, activate, deactivate };
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user