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 './GetUIVersion';
|
||||
export * from './groups';
|
||||
export * from './inventory';
|
||||
export * from './navigator';
|
||||
export * from './nitro';
|
||||
export * from './nitro/avatar';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { IFurnitureItemData, IObjectData } from '@nitrots/nitro-renderer';
|
||||
import { GetNitroInstance } from '../../../api';
|
||||
import { IFurnitureItem } from './IFurnitureItem';
|
||||
import { IFurnitureItem } from '.';
|
||||
import { GetNitroInstance } from '..';
|
||||
|
||||
export class FurnitureItem implements IFurnitureItem
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
import { IObjectData, IRoomEngine } from '@nitrots/nitro-renderer';
|
||||
import { LocalizeText } from '../../../api';
|
||||
import { LocalizeText } from '..';
|
||||
import { FurniCategory } from './FurniCategory';
|
||||
import { FurnitureItem } from './FurnitureItem';
|
||||
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';
|
||||
|
||||
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 { GetRoomEngine, GetSessionDataManager, IsOwnerOfFurniture } from '../../../..';
|
||||
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 { RoomWidgetAvatarExpressionMessage, RoomWidgetChangePostureMessage, RoomWidgetDanceMessage, RoomWidgetMessage, RoomWidgetRoomObjectMessage, RoomWidgetUseProductMessage, RoomWidgetUserActionMessage } from '../messages';
|
||||
import { RoomWidgetHandler } from './RoomWidgetHandler';
|
||||
|
@ -1,10 +1,9 @@
|
||||
import { GetMarketplaceConfigurationMessageComposer, MakeOfferMessageComposer, MarketplaceConfigurationEvent } from '@nitrots/nitro-renderer';
|
||||
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 { CatalogPostMarketplaceOfferEvent } from '../../../../../../events';
|
||||
import { UseMessageEventHook, UseUiEvent } from '../../../../../../hooks';
|
||||
import { FurnitureItem } from '../../../../../inventory/common/FurnitureItem';
|
||||
import { useCatalogContext } from '../../../../CatalogContext';
|
||||
import { ProductTypeEnum } from '../../../../common/ProductTypeEnum';
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
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 { InventoryBadgesRequestEvent, InventoryBadgesUpdatedEvent } from '../../../../../events';
|
||||
import { DispatchUiEvent, UseUiEvent } from '../../../../../hooks';
|
||||
import { useSharedInventoryBadges } from '../../../../../hooks';
|
||||
import { useCatalogContext } from '../../../CatalogContext';
|
||||
|
||||
const EXCLUDED_BADGE_CODES: string[] = [];
|
||||
@ -15,16 +15,9 @@ interface CatalogBadgeSelectorWidgetViewProps extends AutoGridProps
|
||||
export const CatalogBadgeSelectorWidgetView: FC<CatalogBadgeSelectorWidgetViewProps> = props =>
|
||||
{
|
||||
const { columnCount = 5, ...rest } = props;
|
||||
const [ badges, setBadges ] = useState<string[]>([]);
|
||||
const [ currentBadge, setCurrentBadge ] = useState<string>(null);
|
||||
const [ currentBadge, setCurrentBadge ] = useState<IBadgeItem>(null);
|
||||
const { currentOffer = null, setPurchaseOptions = null } = useCatalogContext();
|
||||
|
||||
const onInventoryBadgesUpdatedEvent = useCallback((event: InventoryBadgesUpdatedEvent) =>
|
||||
{
|
||||
setBadges(event.badges);
|
||||
}, []);
|
||||
|
||||
UseUiEvent(InventoryBadgesUpdatedEvent.BADGES_UPDATED, onInventoryBadgesUpdatedEvent);
|
||||
const { badges = [] } = useSharedInventoryBadges();
|
||||
|
||||
const previewStuffData = useMemo(() =>
|
||||
{
|
||||
@ -32,7 +25,7 @@ export const CatalogBadgeSelectorWidgetView: FC<CatalogBadgeSelectorWidgetViewPr
|
||||
|
||||
const stuffData = new StringDataType();
|
||||
|
||||
stuffData.setValue([ '0', currentBadge, '', '' ]);
|
||||
stuffData.setValue([ '0', currentBadge.badgeCode, '', '' ]);
|
||||
|
||||
return stuffData;
|
||||
}, [ currentBadge ]);
|
||||
@ -53,18 +46,13 @@ export const CatalogBadgeSelectorWidgetView: FC<CatalogBadgeSelectorWidgetViewPr
|
||||
});
|
||||
}, [ currentOffer, previewStuffData, setPurchaseOptions ]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
DispatchUiEvent(new InventoryBadgesRequestEvent(InventoryBadgesRequestEvent.REQUEST_BADGES));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<AutoGrid columnCount={ columnCount } { ...rest }>
|
||||
{ badges && (badges.length > 0) && badges.map((code, index) =>
|
||||
{ badges && (badges.length > 0) && badges.map((badge, index) =>
|
||||
{
|
||||
return (
|
||||
<LayoutGridItem key={ index } itemActive={ (currentBadge === code) } onClick={ event => setCurrentBadge(code) }>
|
||||
<LayoutBadgeImageView badgeCode={ code } />
|
||||
<LayoutGridItem key={ index } itemActive={ (currentBadge === badge) } onClick={ event => setCurrentBadge(badge) }>
|
||||
<LayoutBadgeImageView badgeCode={ badge.badgeCode } />
|
||||
</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 { FC, useCallback, useEffect, useReducer, useState } from 'react';
|
||||
import { GetRoomEngine, LocalizeText, SendMessageComposer } from '../../api';
|
||||
import { BadgePointLimitsEvent, ILinkEventTracker, IRoomSession, RoomEngineObjectEvent, RoomEngineObjectPlacedEvent, RoomPreviewer, RoomSessionEvent, TradingOpenComposer } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useEffect, useState } from 'react';
|
||||
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 { InventoryBadgesUpdatedEvent, InventoryEvent, InventoryTradeRequestEvent } from '../../events';
|
||||
import { DispatchUiEvent, UseRoomEngineEvent, UseRoomSessionManagerEvent, UseUiEvent } from '../../hooks';
|
||||
import { isObjectMoverRequested, setObjectMoverRequested } from './common/InventoryUtilities';
|
||||
import { TradeState } from './common/TradeState';
|
||||
import { IUnseenItemTracker } from './common/unseen/IUnseenItemTracker';
|
||||
import { UnseenItemCategory } from './common/unseen/UnseenItemCategory';
|
||||
import { UnseenItemTracker } from './common/unseen/UnseenItemTracker';
|
||||
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';
|
||||
import { InventoryTradeRequestEvent } from '../../events';
|
||||
import { UseMessageEventHook, UseRoomEngineEvent, UseRoomSessionManagerEvent, useSharedInventoryUnseenTracker, UseUiEvent } from '../../hooks';
|
||||
import { InventoryBadgeView } from './views/InventoryBadgeView';
|
||||
import { InventoryBotView } from './views/InventoryBotView';
|
||||
import { InventoryFurnitureView } from './views/InventoryFurnitureView';
|
||||
import { InventoryPetView } from './views/InventoryPetView';
|
||||
import { InventoryTradeView } from './views/InventoryTradeView';
|
||||
|
||||
const TAB_FURNITURE: string = 'inventory.furni';
|
||||
const TAB_BOTS: string = 'inventory.bots';
|
||||
@ -34,66 +24,40 @@ export const InventoryView: FC<{}> = props =>
|
||||
const [ currentTab, setCurrentTab ] = useState<string>(TABS[0]);
|
||||
const [ roomSession, setRoomSession ] = useState<IRoomSession>(null);
|
||||
const [ roomPreviewer, setRoomPreviewer ] = useState<RoomPreviewer>(null);
|
||||
const [ furnitureState, dispatchFurnitureState ] = useReducer(InventoryFurnitureReducer, initialInventoryFurniture);
|
||||
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 { getCount = null, resetCategory = null } = useSharedInventoryUnseenTracker();
|
||||
|
||||
const close = useCallback(() =>
|
||||
{
|
||||
if(furnitureState.tradeData)
|
||||
{
|
||||
switch(furnitureState.tradeData.state)
|
||||
{
|
||||
case TradeState.TRADING_STATE_RUNNING:
|
||||
SendMessageComposer(new TradingCloseComposer());
|
||||
return;
|
||||
default:
|
||||
SendMessageComposer(new TradingCancelComposer());
|
||||
return;
|
||||
}
|
||||
}
|
||||
// close the trade
|
||||
// if(furnitureState.tradeData)
|
||||
// {
|
||||
// switch(furnitureState.tradeData.state)
|
||||
// {
|
||||
// case TradeState.TRADING_STATE_RUNNING:
|
||||
// SendMessageComposer(new TradingCloseComposer());
|
||||
// return;
|
||||
// default:
|
||||
// SendMessageComposer(new TradingCancelComposer());
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
|
||||
setIsVisible(false);
|
||||
}, [ furnitureState.tradeData ]);
|
||||
}, []);
|
||||
|
||||
const onInventoryEvent = useCallback((event: InventoryEvent) =>
|
||||
const onInventoryTradeRequestEvent = useCallback((event: InventoryTradeRequestEvent) =>
|
||||
{
|
||||
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: {
|
||||
const tradeEvent = (event as InventoryTradeRequestEvent);
|
||||
|
||||
SendMessageComposer(new TradingOpenComposer(tradeEvent.objectId));
|
||||
}
|
||||
}
|
||||
}, [ isVisible, close ]);
|
||||
}, []);
|
||||
|
||||
UseUiEvent(InventoryEvent.SHOW_INVENTORY, onInventoryEvent);
|
||||
UseUiEvent(InventoryEvent.HIDE_INVENTORY, onInventoryEvent);
|
||||
UseUiEvent(InventoryEvent.TOGGLE_INVENTORY, onInventoryEvent);
|
||||
UseUiEvent(InventoryTradeRequestEvent.REQUEST_TRADE, onInventoryEvent);
|
||||
UseUiEvent(InventoryTradeRequestEvent.REQUEST_TRADE, onInventoryTradeRequestEvent);
|
||||
|
||||
const onRoomEngineObjectPlacedEvent = useCallback((event: RoomEngineObjectPlacedEvent) =>
|
||||
{
|
||||
@ -123,44 +87,44 @@ export const InventoryView: FC<{}> = props =>
|
||||
UseRoomSessionManagerEvent(RoomSessionEvent.CREATED, 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];
|
||||
|
||||
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);
|
||||
}
|
||||
UseMessageEventHook(BadgePointLimitsEvent, onBadgePointLimitsEvent);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(isVisible) return;
|
||||
const linkTracker: ILinkEventTracker = {
|
||||
linkReceived: (url: string) =>
|
||||
{
|
||||
const parts = url.split('/');
|
||||
|
||||
if(currentTab) resetTrackerForTab(currentTab);
|
||||
}, [ currentTab, isVisible, resetTrackerForTab ]);
|
||||
if(parts.length < 2) return;
|
||||
|
||||
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(() =>
|
||||
{
|
||||
@ -181,53 +145,46 @@ export const InventoryView: FC<{}> = props =>
|
||||
{
|
||||
if(!isVisible)
|
||||
{
|
||||
if(furnitureState.tradeData) setIsVisible(true);
|
||||
// if trading show it
|
||||
}
|
||||
}, [ furnitureState.tradeData, isVisible ]);
|
||||
}, [ isVisible ]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(!badgeState.badges) return;
|
||||
|
||||
DispatchUiEvent(new InventoryBadgesUpdatedEvent(InventoryBadgesUpdatedEvent.BADGES_UPDATED, badgeState.badges));
|
||||
}, [ badgeState.badges ]);
|
||||
const isTrading = false;
|
||||
|
||||
if(!isVisible) return null;
|
||||
|
||||
return (
|
||||
<InventoryContextProvider value={ { furnitureState, dispatchFurnitureState, botState, dispatchBotState, petState, dispatchPetState, badgeState, dispatchBadgeState, unseenTracker } }>
|
||||
<InventoryMessageHandler />
|
||||
{ isVisible &&
|
||||
<NitroCardView uniqueKey={'inventory'} className="nitro-inventory" theme={ furnitureState.tradeData ? 'primary-slim' : '' } >
|
||||
<NitroCardHeaderView headerText={ LocalizeText('inventory.title') } onCloseClick={ close } />
|
||||
{ !furnitureState.tradeData &&
|
||||
<>
|
||||
<NitroCardTabsView>
|
||||
{ TABS.map((name, index) =>
|
||||
{
|
||||
const unseenCount = unseenTracker.getCount(UNSEEN_CATEGORIES[index]);
|
||||
<NitroCardView uniqueKey={'inventory'} className="nitro-inventory" theme={ isTrading ? 'primary-slim' : '' } >
|
||||
<NitroCardHeaderView headerText={ LocalizeText('inventory.title') } onCloseClick={ close } />
|
||||
{ !isTrading &&
|
||||
<>
|
||||
<NitroCardTabsView>
|
||||
{ TABS.map((name, index) =>
|
||||
{
|
||||
const unseenCount = getCount(UNSEEN_CATEGORIES[index]);
|
||||
|
||||
return (
|
||||
<NitroCardTabsItemView key={ index } isActive={ (currentTab === name) } onClick={ event => switchTab(currentTab, name) } count={ unseenCount }>
|
||||
{ LocalizeText(name) }
|
||||
</NitroCardTabsItemView>
|
||||
);
|
||||
}) }
|
||||
</NitroCardTabsView>
|
||||
<NitroCardContentView>
|
||||
{ (currentTab === TAB_FURNITURE ) &&
|
||||
<InventoryFurnitureView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
|
||||
{ (currentTab === TAB_BOTS ) &&
|
||||
<InventoryBotView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
|
||||
{ (currentTab === TAB_PETS ) &&
|
||||
<InventoryPetView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
|
||||
{ (currentTab === TAB_BADGES ) &&
|
||||
<InventoryBadgeView /> }
|
||||
</NitroCardContentView>
|
||||
</> }
|
||||
{ furnitureState.tradeData &&
|
||||
<NitroCardContentView>
|
||||
<InventoryTradeView cancelTrade={ close } />
|
||||
</NitroCardContentView> }
|
||||
</NitroCardView> }
|
||||
</InventoryContextProvider>
|
||||
return (
|
||||
<NitroCardTabsItemView key={ index } isActive={ (currentTab === name) } onClick={ event => setCurrentTab(name) } count={ unseenCount }>
|
||||
{ LocalizeText(name) }
|
||||
</NitroCardTabsItemView>
|
||||
);
|
||||
}) }
|
||||
</NitroCardTabsView>
|
||||
<NitroCardContentView>
|
||||
{ (currentTab === TAB_FURNITURE ) &&
|
||||
<InventoryFurnitureView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
|
||||
{ (currentTab === TAB_BOTS ) &&
|
||||
<InventoryBotView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
|
||||
{ (currentTab === TAB_PETS ) &&
|
||||
<InventoryPetView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
|
||||
{ (currentTab === TAB_BADGES ) &&
|
||||
<InventoryBadgeView /> }
|
||||
</NitroCardContentView>
|
||||
</> }
|
||||
{ isTrading &&
|
||||
<NitroCardContentView>
|
||||
<InventoryTradeView cancelTrade={ close } />
|
||||
</NitroCardContentView> }
|
||||
</NitroCardView>
|
||||
);
|
||||
}
|
||||
|
@ -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 { Column } from '../../../../common/Column';
|
||||
import { Grid, GridProps } from '../../../../common/Grid';
|
||||
import { Text } from '../../../../common/Text';
|
||||
import { Column, Grid, GridProps, Text } from '../../../common';
|
||||
|
||||
export interface InventoryCategoryEmptyViewProps extends GridProps
|
||||
{
|
@ -1,9 +1,7 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react';
|
||||
import { LocalizeText } from '../../../../api';
|
||||
import { Button } from '../../../../common/Button';
|
||||
import { Flex } from '../../../../common/Flex';
|
||||
import { GroupItem } from '../../common/GroupItem';
|
||||
import { GroupItem, LocalizeText } from '../../../api';
|
||||
import { Button, Flex } from '../../../common';
|
||||
|
||||
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 { 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 { LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer } from '../../../../api';
|
||||
import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../../common';
|
||||
import { FurniCategory } from '../../common/FurniCategory';
|
||||
import { GroupItem } from '../../common/GroupItem';
|
||||
import { IFurnitureItem } from '../../common/IFurnitureItem';
|
||||
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';
|
||||
import { FurniCategory, GroupItem, IFurnitureItem, LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer, TradeState } from '../../../api';
|
||||
import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../common';
|
||||
import { useSharedInventoryTrade } from '../../../hooks';
|
||||
import { getGuildFurniType } from '../../../hooks/inventory/common/TradingUtilities';
|
||||
import { InventoryFurnitureSearchView } from './InventoryFurnitureSearchView';
|
||||
|
||||
export interface InventoryTradeViewProps
|
||||
interface InventoryTradeViewProps
|
||||
{
|
||||
cancelTrade: () => void;
|
||||
}
|
||||
@ -27,14 +22,13 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
||||
const [ otherGroupItem, setOtherGroupItem ] = useState<GroupItem>(null);
|
||||
const [ filteredGroupItems, setFilteredGroupItems ] = useState<GroupItem[]>(null);
|
||||
const [ countdownTick, setCountdownTick ] = useState(3);
|
||||
const { furnitureState = null, dispatchFurnitureState = null } = useInventoryContext();
|
||||
const { needsFurniUpdate = false, groupItems = [], tradeData = null } = furnitureState;
|
||||
const { ownUser = null, otherUser = null, groupItems = [], tradeState = TradeState.TRADING_STATE_READY, progressTrade = null, removeItem = null, setTradeState = null } = useSharedInventoryTrade();
|
||||
|
||||
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;
|
||||
|
||||
@ -48,7 +42,7 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
||||
{
|
||||
if(category === FurniCategory.GUILD_FURNI)
|
||||
{
|
||||
type = _Str_16998(spriteId, stuffData);
|
||||
type = getGuildFurniType(spriteId, stuffData);
|
||||
}
|
||||
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) =>
|
||||
{
|
||||
if(!tradeData || !groupItem) return;
|
||||
if(!groupItem) return;
|
||||
|
||||
const tradeItems = groupItem.getTradeItems(count);
|
||||
|
||||
@ -77,7 +71,7 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
||||
if(!coreItem) coreItem = item;
|
||||
}
|
||||
|
||||
const ownItemCount = tradeData.ownUser.items.length;
|
||||
const ownItemCount = ownUser.items.length;
|
||||
|
||||
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 iconName = accepts ? 'lock' : 'unlock';
|
||||
const textColor = accepts ? 'success' : 'danger';
|
||||
|
||||
return <FontAwesomeIcon icon={ iconName } className={ 'text-' + textColor } />
|
||||
};
|
||||
}
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(needsFurniUpdate)
|
||||
{
|
||||
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;
|
||||
if(tradeState !== TradeState.TRADING_STATE_COUNTDOWN) return;
|
||||
|
||||
setCountdownTick(3);
|
||||
|
||||
@ -195,12 +132,7 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
||||
|
||||
if(newValue === 0)
|
||||
{
|
||||
dispatchFurnitureState({
|
||||
type: InventoryFurnitureActions.SET_TRADE_STATE,
|
||||
payload: {
|
||||
tradeState: TradeState.TRADING_STATE_CONFIRMING
|
||||
}
|
||||
});
|
||||
setTradeState(TradeState.TRADING_STATE_CONFIRMING);
|
||||
|
||||
clearInterval(interval);
|
||||
}
|
||||
@ -209,11 +141,8 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
return () =>
|
||||
{
|
||||
clearInterval(interval);
|
||||
}
|
||||
}, [ tradeData, dispatchFurnitureState ]);
|
||||
return () => clearInterval(interval);
|
||||
}, [ tradeState, setTradeState ]);
|
||||
|
||||
return (
|
||||
<Grid>
|
||||
@ -245,12 +174,12 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
||||
<Column size={ 6 } overflow="hidden">
|
||||
<Flex justifyContent="between" alignItems="center">
|
||||
<Text>{ LocalizeText('inventory.trading.you') } { LocalizeText('inventory.trading.areoffering') }:</Text>
|
||||
{ getLockIcon(tradeData.ownUser.accepts) }
|
||||
{ getLockIcon(ownUser.accepts) }
|
||||
</Flex>
|
||||
<AutoGrid columnCount={ 3 }>
|
||||
{ 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 } />;
|
||||
|
||||
@ -270,13 +199,13 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
||||
</Column>
|
||||
<Column size={ 6 } overflow="hidden">
|
||||
<Flex justifyContent="between" alignItems="center">
|
||||
<Text>{ tradeData.otherUser.userName } { LocalizeText('inventory.trading.isoffering') }:</Text>
|
||||
{ getLockIcon(tradeData.otherUser.accepts) }
|
||||
<Text>{ otherUser.userName } { LocalizeText('inventory.trading.isoffering') }:</Text>
|
||||
{ getLockIcon(otherUser.accepts) }
|
||||
</Flex>
|
||||
<AutoGrid columnCount={ 3 }>
|
||||
{ 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 } />;
|
||||
|
||||
@ -290,15 +219,15 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
||||
</Grid>
|
||||
<Flex grow justifyContent="between">
|
||||
<Button variant="danger" onClick={ cancelTrade }>{ LocalizeText('generic.cancel') }</Button>
|
||||
{ (tradeData.state === TradeState.TRADING_STATE_READY) &&
|
||||
<Button variant="secondary" disabled={ (!tradeData.ownUser.itemCount && !tradeData.otherUser.itemCount) } onClick={ progressTrade }>{ LocalizeText('inventory.trading.accept') }</Button> }
|
||||
{ (tradeData.state === 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> }
|
||||
{ (tradeData.state === TradeState.TRADING_STATE_COUNTDOWN) &&
|
||||
{ (tradeState === TradeState.TRADING_STATE_READY) &&
|
||||
<Button variant="secondary" disabled={ (!ownUser.itemCount && !otherUser.itemCount) } onClick={ progressTrade }>{ LocalizeText('inventory.trading.accept') }</Button> }
|
||||
{ (tradeState === TradeState.TRADING_STATE_RUNNING) &&
|
||||
<Button variant="secondary" disabled={ (!ownUser.itemCount && !otherUser.itemCount) } onClick={ progressTrade }>{ LocalizeText(ownUser.accepts ? 'inventory.trading.modify' : 'inventory.trading.accept') }</Button> }
|
||||
{ (tradeState === TradeState.TRADING_STATE_COUNTDOWN) &&
|
||||
<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> }
|
||||
{ (tradeData.state === TradeState.TRADING_STATE_CONFIRMED) &&
|
||||
{ (tradeState === TradeState.TRADING_STATE_CONFIRMED) &&
|
||||
<Button variant="secondary">{ LocalizeText('inventory.trading.info.waiting') }</Button> }
|
||||
</Flex>
|
||||
</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 { FC, useCallback, useReducer, useState } from 'react';
|
||||
import { FC, useCallback, useReducer, useRef, useState } from 'react';
|
||||
import { GetRoomSession } from '../../api';
|
||||
import { Base, Button, DraggableWindowPosition, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../common';
|
||||
import { ModToolsEvent, ModToolsOpenRoomChatlogEvent, ModToolsOpenRoomInfoEvent, ModToolsOpenUserInfoEvent } from '../../events';
|
||||
@ -21,6 +21,7 @@ export const ModToolsView: FC<{}> = props =>
|
||||
const [ isTicketsVisible, setIsTicketsVisible ] = useState(false);
|
||||
const [ modToolsState, dispatchModToolsState ] = useReducer(ModToolsReducer, initialModTools);
|
||||
const { currentRoomId = null, openRooms = null, openRoomChatlogs = null, openUserChatlogs = null, openUserInfo = null } = modToolsState;
|
||||
const elementRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
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">
|
||||
<Base className="icon icon-small-room position-absolute start-1"/> Room Tool
|
||||
</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
|
||||
</Button>
|
||||
<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 { 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 { FurniCategory } from '../../../inventory/common/FurniCategory';
|
||||
import { useRoomContext } from '../../RoomContext';
|
||||
|
||||
interface AvatarInfoUseProductConfirmViewProps
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { RoomObjectCategory, RoomObjectType } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useEffect, useState } from 'react';
|
||||
import { GetFurnitureDataForRoomObject, LocalizeText, UseProductItem } from '../../../../api';
|
||||
import { FurniCategory } from '../../../inventory/common/FurniCategory';
|
||||
import { FurniCategory, GetFurnitureDataForRoomObject, LocalizeText, UseProductItem } from '../../../../api';
|
||||
import { useRoomContext } from '../../RoomContext';
|
||||
import { ContextMenuHeaderView } from '../context-menu/ContextMenuHeaderView';
|
||||
import { ContextMenuListItemView } from '../context-menu/ContextMenuListItemView';
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { IFurnitureData, RoomObjectCategory } from '@nitrots/nitro-renderer';
|
||||
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 { FurniCategory } from '../../../../inventory/common/FurniCategory';
|
||||
import { useRoomContext } from '../../../RoomContext';
|
||||
|
||||
interface MonsterPlantSeedConfirmViewProps
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { RedeemItemClothingComposer, RoomObjectCategory, UserFigureComposer } from '@nitrots/nitro-renderer';
|
||||
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 { FigureData } from '../../../../avatar-editor/common/FigureData';
|
||||
import { FurniCategory } from '../../../../inventory/common/FurniCategory';
|
||||
import { useRoomContext } from '../../../RoomContext';
|
||||
|
||||
interface PurchasableClothingConfirmViewProps
|
||||
|
@ -2,8 +2,8 @@ import { Dispose, DropBounce, EaseOut, FigureUpdateEvent, JumpBy, Motions, Nitro
|
||||
import { FC, useCallback, useState } from 'react';
|
||||
import { CreateLinkEvent, GetSessionDataManager, GetUserProfile, OpenMessengerChat, VisitDesktop } from '../../api';
|
||||
import { Base, Flex, LayoutAvatarImageView, LayoutItemCountView, TransitionAnimation, TransitionAnimationTypes } from '../../common';
|
||||
import { AchievementsUIUnseenCountEvent, FriendsEvent, FriendsMessengerIconEvent, FriendsRequestCountEvent, GuideToolEvent, InventoryEvent, ModToolsEvent, UnseenItemTrackerUpdateEvent, UserSettingsUIEvent } from '../../events';
|
||||
import { BatchUpdates, DispatchUiEvent, UseMessageEventHook, UseRoomEngineEvent, UseUiEvent } from '../../hooks';
|
||||
import { AchievementsUIUnseenCountEvent, FriendsEvent, FriendsMessengerIconEvent, FriendsRequestCountEvent, GuideToolEvent, ModToolsEvent, UserSettingsUIEvent } from '../../events';
|
||||
import { BatchUpdates, DispatchUiEvent, UseMessageEventHook, UseRoomEngineEvent, useSharedInventoryUnseenTracker, UseUiEvent } from '../../hooks';
|
||||
import { ToolbarViewItems } from './common/ToolbarViewItems';
|
||||
import { ToolbarMeView } from './ToolbarMeView';
|
||||
|
||||
@ -25,9 +25,9 @@ export const ToolbarView: FC<ToolbarViewProps> = props =>
|
||||
const [ isMeExpanded, setMeExpanded ] = useState(false);
|
||||
const [ useGuideTool, setUseGuideTool ] = useState(false);
|
||||
const [ chatIconType, setChatIconType ] = useState(CHAT_ICON_HIDDEN);
|
||||
const [ unseenInventoryCount, setUnseenInventoryCount ] = useState(0);
|
||||
const [ unseenAchievementCount, setUnseenAchievementCount ] = useState(0);
|
||||
const [ unseenFriendRequestCount, setFriendRequestCount ] = useState(0);
|
||||
const { getFullCount = null } = useSharedInventoryUnseenTracker();
|
||||
const isMod = GetSessionDataManager().isModerator;
|
||||
|
||||
const onUserInfoEvent = useCallback((event: UserInfoEvent) =>
|
||||
@ -68,13 +68,6 @@ export const ToolbarView: FC<ToolbarViewProps> = props =>
|
||||
|
||||
UseUiEvent(FriendsMessengerIconEvent.UPDATE_ICON, onFriendsMessengerIconEvent);
|
||||
|
||||
const onUnseenItemTrackerUpdateEvent = useCallback((event: UnseenItemTrackerUpdateEvent) =>
|
||||
{
|
||||
setUnseenInventoryCount(event.count);
|
||||
}, []);
|
||||
|
||||
UseUiEvent(UnseenItemTrackerUpdateEvent.UPDATE_COUNT, onUnseenItemTrackerUpdateEvent);
|
||||
|
||||
const onAchievementsUIUnseenCountEvent = useCallback((event: AchievementsUIUnseenCountEvent) =>
|
||||
{
|
||||
setUnseenAchievementCount(event.count);
|
||||
@ -138,7 +131,7 @@ export const ToolbarView: FC<ToolbarViewProps> = props =>
|
||||
CreateLinkEvent('navigator/toggle');
|
||||
return;
|
||||
case ToolbarViewItems.INVENTORY_ITEM:
|
||||
DispatchUiEvent(new InventoryEvent(InventoryEvent.TOGGLE_INVENTORY));
|
||||
CreateLinkEvent('inventory/toggle');
|
||||
return;
|
||||
case ToolbarViewItems.CATALOG_ITEM:
|
||||
CreateLinkEvent('catalog/toggle');
|
||||
@ -178,6 +171,8 @@ export const ToolbarView: FC<ToolbarViewProps> = props =>
|
||||
}
|
||||
}, []);
|
||||
|
||||
const unseenInventoryCount = getFullCount();
|
||||
|
||||
return (
|
||||
<>
|
||||
<TransitionAnimation type={ TransitionAnimationTypes.FADE_IN } inProp={ isMeExpanded } timeout={ 300 }>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { CatalogEvent } from '.';
|
||||
import { FurnitureItem } from '../../components/inventory/common/FurnitureItem';
|
||||
import { FurnitureItem } from '../../api';
|
||||
|
||||
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';
|
||||
|
||||
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 './InventoryTradeRequestEvent';
|
||||
export * from './InventoryTradeStartEvent';
|
||||
export * from './UnseenItemTrackerUpdateEvent';
|
||||
|
@ -3,6 +3,8 @@ export * from './events';
|
||||
export * from './events/core';
|
||||
export * from './events/nitro';
|
||||
export * from './events/ui';
|
||||
export * from './inventory';
|
||||
export * from './messages';
|
||||
export * from './navigator';
|
||||
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 { GetSessionDataManager } from '../../../api';
|
||||
import { FurniCategory } from './FurniCategory';
|
||||
import { FurnitureItem } from './FurnitureItem';
|
||||
import { createGroupItem } from './FurnitureUtilities';
|
||||
import { GroupItem } from './GroupItem';
|
||||
import { createGroupItem } from '.';
|
||||
import { FurniCategory, FurnitureItem, GetSessionDataManager, GroupItem } from '../../../api';
|
||||
|
||||
function isExternalImage(spriteId: number): boolean
|
||||
{
|
||||
const furnitureData = GetSessionDataManager().getWallItemData(spriteId);
|
||||
|
||||
return (furnitureData && furnitureData.isExternalImage);
|
||||
}
|
||||
|
||||
export function parseTradeItems(items: ItemDataStructure[], _arg_2: AdvancedMap<string, GroupItem>): void
|
||||
const isExternalImage = (spriteId: number) => GetSessionDataManager().getWallItemData(spriteId)?.isExternalImage || false;
|
||||
|
||||
export const parseTradeItems = (items: ItemDataStructure[]) =>
|
||||
{
|
||||
const existingItems = new AdvancedMap<string, GroupItem>();
|
||||
const totalItems = items.length;
|
||||
|
||||
if(!totalItems) return;
|
||||
if(!totalItems) return null;
|
||||
|
||||
for(const item of items)
|
||||
{
|
||||
@ -40,33 +33,34 @@ export function parseTradeItems(items: ItemDataStructure[], _arg_2: AdvancedMap<
|
||||
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)
|
||||
{
|
||||
groupItem = createGroupItem(spriteId, category, item.stuffData);
|
||||
|
||||
_arg_2.add(name, groupItem);
|
||||
existingItems.add(name, groupItem);
|
||||
}
|
||||
|
||||
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();
|
||||
const _local_4 = (stuffData as StringDataType);
|
||||
|
||||
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;
|
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