More catalog changes

This commit is contained in:
Bill 2022-04-20 19:33:23 -04:00
parent 5426de9708
commit c45a8030b4
16 changed files with 382 additions and 601 deletions

View File

@ -10,7 +10,7 @@ import { MarketplacePostOfferView } from './views/page/layout/marketplace/Market
export const CatalogView: FC<{}> = props => export const CatalogView: FC<{}> = props =>
{ {
const { isVisible = false, setIsVisible = null, rootNode = null, currentPage = null, navigationHidden = false, setNavigationHidden = null, activeNodes = [], searchResult = null, setSearchResult = null, getNodeById = null, openPageByName = null, openPageByOfferId = null, activateNode = null } = useCatalog(); const { isVisible = false, setIsVisible = null, rootNode = null, currentPage = null, navigationHidden = false, setNavigationHidden = null, activeNodes = [], searchResult = null, setSearchResult = null, openPageByName = null, openPageByOfferId = null, activateNode = null } = useCatalog();
useEffect(() => useEffect(() =>
{ {

View File

@ -1,11 +1,11 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { PurchaseFromCatalogAsGiftComposer } from '@nitrots/nitro-renderer'; import { GiftReceiverNotFoundEvent, PurchaseFromCatalogAsGiftComposer } from '@nitrots/nitro-renderer';
import classNames from 'classnames'; import classNames from 'classnames';
import { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { FC, useCallback, useEffect, useMemo, useState } from 'react';
import { GetSessionDataManager, LocalizeText, ProductTypeEnum, SendMessageComposer } from '../../../../api'; import { GetSessionDataManager, LocalizeText, ProductTypeEnum, SendMessageComposer } from '../../../../api';
import { Base, Button, ButtonGroup, Column, Flex, FormGroup, LayoutCurrencyIcon, LayoutFurniImageView, LayoutGiftTagView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common'; import { Base, Button, ButtonGroup, Column, Flex, FormGroup, LayoutCurrencyIcon, LayoutFurniImageView, LayoutGiftTagView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common';
import { CatalogEvent, CatalogInitGiftEvent, CatalogPurchasedEvent } from '../../../../events'; import { CatalogEvent, CatalogInitGiftEvent, CatalogPurchasedEvent } from '../../../../events';
import { useCatalog, UseUiEvent } from '../../../../hooks'; import { useCatalog, UseMessageEventHook, UseUiEvent } from '../../../../hooks';
export const CatalogGiftView: FC<{}> = props => export const CatalogGiftView: FC<{}> = props =>
{ {
@ -58,15 +58,11 @@ export const CatalogGiftView: FC<{}> = props =>
setExtraData(castedEvent.extraData); setExtraData(castedEvent.extraData);
setIsVisible(true); setIsVisible(true);
return; return;
case CatalogEvent.GIFT_RECEIVER_NOT_FOUND:
setReceiverNotFound(true);
return;
} }
}, [ close ]); }, [ close ]);
UseUiEvent(CatalogPurchasedEvent.PURCHASE_SUCCESS, onCatalogEvent); UseUiEvent(CatalogPurchasedEvent.PURCHASE_SUCCESS, onCatalogEvent);
UseUiEvent(CatalogEvent.INIT_GIFT, onCatalogEvent); UseUiEvent(CatalogEvent.INIT_GIFT, onCatalogEvent);
UseUiEvent(CatalogEvent.GIFT_RECEIVER_NOT_FOUND, onCatalogEvent);
const isBoxDefault = useMemo(() => const isBoxDefault = useMemo(() =>
{ {
@ -117,6 +113,13 @@ export const CatalogGiftView: FC<{}> = props =>
} }
}, [ extraData, maxBoxIndex, maxRibbonIndex, message, offerId, pageId, receiverName, selectedBoxIndex, selectedColorId, selectedRibbonIndex, showMyFace ]); }, [ extraData, maxBoxIndex, maxRibbonIndex, message, offerId, pageId, receiverName, selectedBoxIndex, selectedColorId, selectedRibbonIndex, showMyFace ]);
const onGiftReceiverNotFoundEvent = useCallback(() =>
{
setReceiverNotFound(true);
}, []);
UseMessageEventHook(GiftReceiverNotFoundEvent, onGiftReceiverNotFoundEvent);
useEffect(() => useEffect(() =>
{ {
setReceiverNotFound(false); setReceiverNotFound(false);

View File

@ -2,7 +2,7 @@ import { MouseEventType } from '@nitrots/nitro-renderer';
import { FC, MouseEvent, useMemo, useState } from 'react'; import { FC, MouseEvent, useMemo, useState } from 'react';
import { IPurchasableOffer, Offer, ProductTypeEnum } from '../../../../../api'; import { IPurchasableOffer, Offer, ProductTypeEnum } from '../../../../../api';
import { LayoutAvatarImageView, LayoutGridItem, LayoutGridItemProps } from '../../../../../common'; import { LayoutAvatarImageView, LayoutGridItem, LayoutGridItemProps } from '../../../../../common';
import { useCatalog } from '../../../../../hooks'; import { useCatalog, useInventoryFurni } from '../../../../../hooks';
interface CatalogGridOfferViewProps extends LayoutGridItemProps interface CatalogGridOfferViewProps extends LayoutGridItemProps
{ {
@ -15,6 +15,7 @@ export const CatalogGridOfferView: FC<CatalogGridOfferViewProps> = props =>
const { offer = null, selectOffer = null, itemActive = false, ...rest } = props; const { offer = null, selectOffer = null, itemActive = false, ...rest } = props;
const [ isMouseDown, setMouseDown ] = useState(false); const [ isMouseDown, setMouseDown ] = useState(false);
const { requestOfferToMover = null } = useCatalog(); const { requestOfferToMover = null } = useCatalog();
const { isVisible = false } = useInventoryFurni();
const iconUrl = useMemo(() => const iconUrl = useMemo(() =>
{ {
@ -38,7 +39,7 @@ export const CatalogGridOfferView: FC<CatalogGridOfferViewProps> = props =>
setMouseDown(false); setMouseDown(false);
return; return;
case MouseEventType.ROLL_OUT: case MouseEventType.ROLL_OUT:
if(!isMouseDown || !itemActive) return; if(!isMouseDown || !itemActive || !isVisible) return;
requestOfferToMover(offer); requestOfferToMover(offer);
return; return;

View File

@ -1,67 +0,0 @@
import { ApproveNameMessageComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback, useState } from 'react';
import { IPurchasableOffer, LocalizeText, Offer, SendMessageComposer } from '../../../../../../api';
import { Column, Flex, LayoutCurrencyIcon, Text } from '../../../../../../common';
import { CatalogPurchasedEvent } from '../../../../../../events';
import { UseUiEvent } from '../../../../../../hooks';
import { CatalogPurchaseWidgetView } from '../../widgets/CatalogPurchaseWidgetView';
import { CatalogPetNameApprovalView } from './CatalogPetNameApprovalView';
export interface CatalogLayoutPetPurchaseViewProps
{
offer: IPurchasableOffer;
pageId: number;
extra?: string;
}
export const CatalogLayoutPetPurchaseView: FC<CatalogLayoutPetPurchaseViewProps> = props =>
{
const { offer = null, pageId = -1, extra = '' } = props;
const [ petNameValue, setPetNameValue ] = useState('');
const [ nameApproved, setNameApproved ] = useState(false);
const onCatalogPurchasedEvent = useCallback((event: CatalogPurchasedEvent) =>
{
setNameApproved(false);
}, []);
UseUiEvent(CatalogPurchasedEvent.PURCHASE_SUCCESS, onCatalogPurchasedEvent);
const beforePurchase = useCallback(() =>
{
SendMessageComposer(new ApproveNameMessageComposer(petNameValue, 1));
}, [ petNameValue ]);
const extraData = `${ petNameValue }\n${ extra }`;
return (
<Column fullWidth grow justifyContent="end">
<div className="d-flex flex-grow-1 justify-content-center align-items-center">
<CatalogPetNameApprovalView petNameValue={ petNameValue } setPetNameValue={ setPetNameValue } nameApproved={ nameApproved } setNameApproved={ setNameApproved } />
</div>
<Flex alignItems="end">
<div className="flex-grow-1 align-items-end">
<Text>{ LocalizeText('catalog.bundlewidget.price') }</Text>
</div>
<Column gap={ 1 }>
{ ((offer.priceType === Offer.PRICE_TYPE_CREDITS_ACTIVITYPOINTS) || (offer.priceType === Offer.PRICE_TYPE_CREDITS)) &&
<Flex alignItems="center" justifyContent="end" gap={ 1 }>
<Text>{ offer.priceInCredits }</Text>
<LayoutCurrencyIcon type={ -1 } />
</Flex> }
{ ((offer.priceType === Offer.PRICE_TYPE_CREDITS_ACTIVITYPOINTS) || (offer.priceType === Offer.PRICE_TYPE_ACTIVITYPOINTS)) &&
<Flex alignItems="center" justifyContent="end" gap={ 1 }>
<Text>{ offer.priceInActivityPoints }</Text>
<LayoutCurrencyIcon type={ offer.activityPointType } />
</Flex> }
</Column>
</Flex>
<Column gap={ 1 }>
<CatalogPurchaseWidgetView />
{ /* <CatalogPurchaseButtonView offer={ offer } pageId={ pageId } extra={ extraData } quantity={ 1 } isPurchaseAllowed={ nameApproved } beforePurchase={ beforePurchase } />
{ offer.giftable &&
<CatalogPurchaseGiftButtonView offer={ offer } pageId={ pageId } extra={ extraData } disabled={ nameApproved } /> } */ }
</Column>
</Column>
);
}

View File

@ -1,10 +1,10 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { ApproveNameMessageComposer, ColorConverter, GetSellablePetPalettesComposer, PurchaseFromCatalogComposer, SellablePetPaletteData } from '@nitrots/nitro-renderer'; import { ApproveNameMessageComposer, ApproveNameMessageEvent, ColorConverter, GetSellablePetPalettesComposer, PurchaseFromCatalogComposer, SellablePetPaletteData } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { FC, useCallback, useEffect, useMemo, useState } from 'react';
import { GetPetAvailableColors, GetPetIndexFromLocalization, LocalizeText, SendMessageComposer } from '../../../../../../api'; import { GetPetAvailableColors, GetPetIndexFromLocalization, LocalizeText, SendMessageComposer } from '../../../../../../api';
import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, LayoutPetImageView, Text } from '../../../../../../common'; import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, LayoutPetImageView, Text } from '../../../../../../common';
import { CatalogNameResultEvent, CatalogPurchaseFailureEvent, CatalogWidgetEvent } from '../../../../../../events'; import { CatalogPurchaseFailureEvent } from '../../../../../../events';
import { DispatchUiEvent, useCatalog, UseUiEvent } from '../../../../../../hooks'; import { DispatchUiEvent, useCatalog, UseMessageEventHook } from '../../../../../../hooks';
import { CatalogAddOnBadgeWidgetView } from '../../widgets/CatalogAddOnBadgeWidgetView'; import { CatalogAddOnBadgeWidgetView } from '../../widgets/CatalogAddOnBadgeWidgetView';
import { CatalogPurchaseWidgetView } from '../../widgets/CatalogPurchaseWidgetView'; import { CatalogPurchaseWidgetView } from '../../widgets/CatalogPurchaseWidgetView';
import { CatalogTotalPriceWidget } from '../../widgets/CatalogTotalPriceWidget'; import { CatalogTotalPriceWidget } from '../../widgets/CatalogTotalPriceWidget';
@ -104,15 +104,17 @@ export const CatalogLayoutPetView: FC<CatalogLayoutProps> = props =>
} }
}, [ page, currentOffer, petName, petPurchaseString, approvalResult ]); }, [ page, currentOffer, petName, petPurchaseString, approvalResult ]);
const onCatalogNameResultEvent = useCallback((event: CatalogNameResultEvent) => const onApproveNameMessageEvent = useCallback((event: ApproveNameMessageEvent) =>
{ {
setApprovalResult(event.result); const parser = event.getParser();
if(event.result === 0) purchasePet(); setApprovalResult(parser.result);
if(parser.result === 0) purchasePet();
else DispatchUiEvent(new CatalogPurchaseFailureEvent(-1)); else DispatchUiEvent(new CatalogPurchaseFailureEvent(-1));
}, [ purchasePet ]); }, [ purchasePet ]);
UseUiEvent(CatalogWidgetEvent.APPROVE_RESULT, onCatalogNameResultEvent); UseMessageEventHook(ApproveNameMessageEvent, onApproveNameMessageEvent);
useEffect(() => useEffect(() =>
{ {

View File

@ -1,68 +0,0 @@
import { Dispatch, FC, SetStateAction, useCallback, useEffect, useState } from 'react';
import { LocalizeText } from '../../../../../../api';
import { CatalogEvent, CatalogNameResultEvent } from '../../../../../../events';
import { UseUiEvent } from '../../../../../../hooks';
export interface CatalogPetNameApprovalViewProps
{
petNameValue: string;
setPetNameValue: Dispatch<SetStateAction<string>>;
nameApproved: boolean;
setNameApproved: Dispatch<SetStateAction<boolean>>;
}
export const CatalogPetNameApprovalView: FC<CatalogPetNameApprovalViewProps> = props =>
{
const { petNameValue = null, setPetNameValue = null, nameApproved = false, setNameApproved = null } = props;
const [ validationResult, setValidationResult ] = useState(-1);
const onCatalogNameResultEvent = useCallback((event: CatalogNameResultEvent) =>
{
if(event.result === 0)
{
setNameApproved(true);
return;
}
setValidationResult(event.result);
}, [ setNameApproved ]);
UseUiEvent(CatalogEvent.APPROVE_NAME_RESULT, onCatalogNameResultEvent);
const validationErrorMessage = () =>
{
let key: string = '';
switch(validationResult)
{
case 1:
key = 'catalog.alert.petname.long';
break;
case 2:
key = 'catalog.alert.petname.short';
break;
case 3:
key = 'catalog.alert.petname.chars';
break;
case 4:
key = 'catalog.alert.petname.bobba';
break;
}
return LocalizeText(key);
}
useEffect(() =>
{
setValidationResult(-1);
}, [ petNameValue ]);
return (
<div className="input-group has-validation">
<input type="text" className={ 'form-control form-control-sm '+ ((validationResult > 0) ? 'is-invalid ' : '') } placeholder={ LocalizeText('widgets.petpackage.name.title') } value={ petNameValue } onChange={ event => setPetNameValue(event.target.value) } />
{ (validationResult > 0) &&
<div className="invalid-feedback">{ validationErrorMessage }</div> }
</div>
);
}

View File

@ -7,7 +7,6 @@ export class CatalogEvent extends NitroEvent
public static TOGGLE_CATALOG: string = 'CE_TOGGLE_CATALOG'; public static TOGGLE_CATALOG: string = 'CE_TOGGLE_CATALOG';
public static SOLD_OUT: string = 'CE_SOLD_OUT'; public static SOLD_OUT: string = 'CE_SOLD_OUT';
public static APPROVE_NAME_RESULT: string = 'CE_APPROVE_NAME_RESULT'; public static APPROVE_NAME_RESULT: string = 'CE_APPROVE_NAME_RESULT';
public static GIFT_RECEIVER_NOT_FOUND: string = 'CE_GIFT_RECEIVER_NOT_FOUND';
public static PURCHASE_APPROVED: string = 'CE_PURCHASE_APPROVED'; public static PURCHASE_APPROVED: string = 'CE_PURCHASE_APPROVED';
public static INIT_GIFT: string = 'CE_INIT_GIFT'; public static INIT_GIFT: string = 'CE_INIT_GIFT';
public static CATALOG_RESET: string = 'CE_RESET'; public static CATALOG_RESET: string = 'CE_RESET';

View File

@ -1,9 +0,0 @@
import { CatalogEvent } from './CatalogEvent';
export class CatalogGiftReceiverNotFoundEvent extends CatalogEvent
{
constructor()
{
super(CatalogEvent.GIFT_RECEIVER_NOT_FOUND);
}
}

View File

@ -1,26 +0,0 @@
import { NitroEvent } from '@nitrots/nitro-renderer';
import { CatalogWidgetEvent } from './CatalogWidgetEvent';
export class CatalogNameResultEvent extends NitroEvent
{
private _result: number;
private _validationInfo: string;
constructor(result: number, validationInfo: string)
{
super(CatalogWidgetEvent.APPROVE_RESULT);
this._result = result;
this._validationInfo = validationInfo;
}
public get result(): number
{
return this._result;
}
public get validationInfo(): string
{
return this._validationInfo;
}
}

View File

@ -11,7 +11,6 @@ export class CatalogWidgetEvent extends NitroEvent
public static COLOUR_INDEX: string = 'CWE_COLOUR_INDEX'; public static COLOUR_INDEX: string = 'CWE_COLOUR_INDEX';
public static TEXT_INPUT: string = 'CWE_TEXT_INPUT'; public static TEXT_INPUT: string = 'CWE_TEXT_INPUT';
public static DROPMENU_SELECT: string = 'CWE_CWE_DROPMENU_SELECT'; public static DROPMENU_SELECT: string = 'CWE_CWE_DROPMENU_SELECT';
public static APPROVE_RESULT: string = 'CWE_CWE_APPROVE_RESULT';
public static PURCHASE_OVERRIDE: string = 'CWE_PURCHASE_OVERRIDE'; public static PURCHASE_OVERRIDE: string = 'CWE_PURCHASE_OVERRIDE';
public static SELLABLE_PET_PALETTES: string = 'CWE_SELLABLE_PET_PALETTES'; public static SELLABLE_PET_PALETTES: string = 'CWE_SELLABLE_PET_PALETTES';
public static UPDATE_ROOM_PREVIEW: string = 'CWE_UPDATE_ROOM_PREVIEW'; public static UPDATE_ROOM_PREVIEW: string = 'CWE_UPDATE_ROOM_PREVIEW';

View File

@ -1,7 +1,5 @@
export * from './CatalogEvent'; export * from './CatalogEvent';
export * from './CatalogGiftReceiverNotFoundEvent';
export * from './CatalogInitGiftEvent'; export * from './CatalogInitGiftEvent';
export * from './CatalogNameResultEvent';
export * from './CatalogPostMarketplaceOfferEvent'; export * from './CatalogPostMarketplaceOfferEvent';
export * from './CatalogPurchasedEvent'; export * from './CatalogPurchasedEvent';
export * from './CatalogPurchaseFailureEvent'; export * from './CatalogPurchaseFailureEvent';

View File

@ -1,5 +1,3 @@
export * from './useCatalog'; export * from './useCatalog';
export * from './useCatalogBuildersClub';
export * from './useCatalogItemMover';
export * from './useCatalogPlaceMultipleItems'; export * from './useCatalogPlaceMultipleItems';
export * from './useCatalogSkipPurchaseConfirmation'; export * from './useCatalogSkipPurchaseConfirmation';

View File

@ -1,12 +1,15 @@
import { ApproveNameMessageEvent, CatalogPageMessageEvent, CatalogPagesListEvent, CatalogPublishedMessageEvent, ClubGiftInfoEvent, FrontPageItem, GetCatalogIndexComposer, GetCatalogPageComposer, GetClubGiftInfo, GetGiftWrappingConfigurationComposer, GiftReceiverNotFoundEvent, GiftWrappingConfigurationEvent, GuildMembershipsMessageEvent, HabboClubOffersMessageEvent, LimitedEditionSoldOutEvent, MarketplaceMakeOfferResult, NodeData, ProductOfferEvent, PurchaseErrorMessageEvent, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, RoomPreviewer, SellablePetPalettesMessageEvent } from '@nitrots/nitro-renderer'; import { BuildersClubFurniCountMessageEvent, BuildersClubPlaceRoomItemMessageComposer, BuildersClubPlaceWallItemMessageComposer, BuildersClubQueryFurniCountMessageComposer, BuildersClubSubscriptionStatusMessageEvent, CatalogPageMessageEvent, CatalogPagesListEvent, CatalogPublishedMessageEvent, ClubGiftInfoEvent, FrontPageItem, FurniturePlaceComposer, FurniturePlacePaintComposer, GetCatalogIndexComposer, GetCatalogPageComposer, GetClubGiftInfo, GetGiftWrappingConfigurationComposer, GiftWrappingConfigurationEvent, GuildMembershipsMessageEvent, HabboClubOffersMessageEvent, LegacyDataType, LimitedEditionSoldOutEvent, MarketplaceMakeOfferResult, NodeData, ProductOfferEvent, PurchaseErrorMessageEvent, PurchaseFromCatalogComposer, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, RoomControllerLevel, RoomEngineObjectPlacedEvent, RoomObjectCategory, RoomObjectPlacementSource, RoomObjectType, RoomObjectVariable, RoomPreviewer, SellablePetPalettesMessageEvent, Vector3d } from '@nitrots/nitro-renderer';
import { useCallback, useEffect, useRef, useState } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import { useBetween } from 'use-between'; import { useBetween } from 'use-between';
import { CatalogNode, CatalogPage, CatalogPetPalette, CatalogType, GetFurnitureData, GetProductDataForLocalization, GetRoomEngine, GiftWrappingConfiguration, ICatalogNode, ICatalogOptions, ICatalogPage, IPageLocalization, IProduct, IPurchasableOffer, IPurchaseOptions, LocalizeText, NotificationAlertType, NotificationUtilities, Offer, PageLocalization, PlaySound, Product, ProductTypeEnum, RequestedPage, SearchResult, SendMessageComposer, SoundNames } from '../../api'; import { BuilderFurniPlaceableStatus, CatalogNode, CatalogPage, CatalogPetPalette, CatalogType, CreateLinkEvent, FurniCategory, GetFurnitureData, GetNitroInstance, GetProductDataForLocalization, GetRoomEngine, GetRoomSession, GiftWrappingConfiguration, ICatalogNode, ICatalogOptions, ICatalogPage, IPageLocalization, IProduct, IPurchasableOffer, IPurchaseOptions, LocalizeText, NotificationAlertType, NotificationUtilities, Offer, PageLocalization, PlacedObjectPurchaseData, PlaySound, Product, ProductTypeEnum, RequestedPage, SearchResult, SendMessageComposer, SoundNames } from '../../api';
import { CatalogGiftReceiverNotFoundEvent, CatalogNameResultEvent, CatalogPurchasedEvent, CatalogPurchaseFailureEvent, CatalogPurchaseNotAllowedEvent, CatalogPurchaseSoldOutEvent } from '../../events'; import { CatalogPurchasedEvent, CatalogPurchaseFailureEvent, CatalogPurchaseNotAllowedEvent, CatalogPurchaseSoldOutEvent, InventoryFurniAddedEvent } from '../../events';
import { DispatchUiEvent, UseUiEvent } from '../events'; import { DispatchUiEvent, UseRoomEngineEvent, UseUiEvent } from '../events';
import { UseMessageEventHook } from '../messages'; import { UseMessageEventHook } from '../messages';
import { useCatalogBuildersClub } from './useCatalogBuildersClub'; import { useCatalogPlaceMultipleItems } from './useCatalogPlaceMultipleItems';
import { useCatalogItemMover } from './useCatalogItemMover'; import { useCatalogSkipPurchaseConfirmation } from './useCatalogSkipPurchaseConfirmation';
const DUMMY_PAGE_ID_FOR_OFFER_SEARCH = -12345678;
const DRAG_AND_DROP_ENABLED = true;
const useCatalogState = () => const useCatalogState = () =>
{ {
@ -26,8 +29,17 @@ const useCatalogState = () =>
const [ navigationHidden, setNavigationHidden ] = useState(false); const [ navigationHidden, setNavigationHidden ] = useState(false);
const [ purchaseOptions, setPurchaseOptions ] = useState<IPurchaseOptions>({ quantity: 1, extraData: null, extraParamRequired: false, previewStuffData: null }); const [ purchaseOptions, setPurchaseOptions ] = useState<IPurchaseOptions>({ quantity: 1, extraData: null, extraParamRequired: false, previewStuffData: null });
const [ catalogOptions, setCatalogOptions ] = useState<ICatalogOptions>({}); const [ catalogOptions, setCatalogOptions ] = useState<ICatalogOptions>({});
const { furniCount = 0, furniLimit = 0, secondsLeft = 0 } = useCatalogBuildersClub(); const [ objectMoverRequested, setObjectMoverRequested ] = useState(false);
const { requestOfferToMover = null, cancelObjectMover = null } = useCatalogItemMover({ currentType, pageId, currentOffer, purchaseOptions }, { furniCount, furniLimit, secondsLeft }); const [ catalogPlaceMultipleObjects, setCatalogPlaceMultipleObjects ] = useCatalogPlaceMultipleItems();
const [ catalogSkipPurchaseConfirmation, setCatalogSkipPurchaseConfirmation ] = useCatalogSkipPurchaseConfirmation();
const [ purchasableOffer, setPurchaseableOffer ] = useState<IPurchasableOffer>(null);
const [ placedObjectPurchaseData, setPlacedObjectPurchaseData ] = useState<PlacedObjectPurchaseData>(null);
const [ furniCount, setFurniCount ] = useState(0);
const [ furniLimit, setFurniLimit ] = useState(0);
const [ maxFurniLimit, setMaxFurniLimit ] = useState(0);
const [ secondsLeft, setSecondsLeft ] = useState(0);
const [ updateTime, setUpdateTime ] = useState(0);
const [ secondsLeftWithGrace, setSecondsLeftWithGrace ] = useState(0);
const requestedPage = useRef(new RequestedPage()); const requestedPage = useRef(new RequestedPage());
const resetState = useCallback(() => const resetState = useCallback(() =>
@ -44,6 +56,166 @@ const useCatalogState = () =>
setIsVisible(false); setIsVisible(false);
}, []); }, []);
const getBuilderFurniPlaceableStatus = useCallback((offer: IPurchasableOffer) =>
{
if(!offer) return BuilderFurniPlaceableStatus.MISSING_OFFER;
if((furniCount < 0) || (furniCount >= furniLimit)) return BuilderFurniPlaceableStatus.FURNI_LIMIT_REACHED;
const roomSession = GetRoomSession();
if(!roomSession) return BuilderFurniPlaceableStatus.NOT_IN_ROOM;
if(!roomSession.isRoomOwner) return BuilderFurniPlaceableStatus.NOT_ROOM_OWNER;
if(secondsLeft <= 0)
{
const roomEngine = GetRoomEngine();
let objectCount = roomEngine.getRoomObjectCount(roomSession.roomId, RoomObjectCategory.UNIT);
while(objectCount > 0)
{
const roomObject = roomEngine.getRoomObjectByIndex(roomSession.roomId, objectCount, RoomObjectCategory.UNIT);
const userData = roomSession.userDataManager.getUserDataByIndex(roomObject.id);
if(userData && (userData.type === RoomObjectType.USER) && (userData.roomIndex !== roomSession.ownRoomIndex) && !userData.isModerator) return BuilderFurniPlaceableStatus.VISITORS_IN_ROOM;
objectCount--;
}
}
return BuilderFurniPlaceableStatus.OKAY;
}, [ furniCount, furniLimit, secondsLeft ]);
const isDraggable = useCallback((offer: IPurchasableOffer) =>
{
const roomSession = GetRoomSession();
if(((DRAG_AND_DROP_ENABLED && roomSession && offer.page && (offer.page.layoutCode !== 'sold_ltd_items') && (currentType === CatalogType.NORMAL) && (roomSession.isRoomOwner || (roomSession.isGuildRoom && (roomSession.controllerLevel >= RoomControllerLevel.GUILD_MEMBER)))) || ((currentType === CatalogType.BUILDER) && (getBuilderFurniPlaceableStatus(offer) === BuilderFurniPlaceableStatus.OKAY))) && (offer.pricingModel !== Offer.PRICING_MODEL_BUNDLE) && (offer.product.productType !== ProductTypeEnum.EFFECT) && (offer.product.productType !== ProductTypeEnum.HABBO_CLUB)) return true;
return false;
}, [ currentType, getBuilderFurniPlaceableStatus ]);
const requestOfferToMover = useCallback((offer: IPurchasableOffer) =>
{
if(!isDraggable(offer)) return;
const product = offer.product;
if(!product) return;
let category = 0;
switch(product.productType)
{
case ProductTypeEnum.FLOOR:
category = RoomObjectCategory.FLOOR;
break;
case ProductTypeEnum.WALL:
category = RoomObjectCategory.WALL;
break;
}
if(GetRoomEngine().processRoomObjectPlacement(RoomObjectPlacementSource.CATALOG, -(offer.offerId), category, product.productClassId, product.extraParam))
{
setPurchaseableOffer(offer);
setObjectMoverRequested(true);
setIsVisible(false);
}
}, [ isDraggable ]);
const resetRoomPaint = useCallback((planeType: string, type: string) =>
{
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';
switch(planeType)
{
case 'floor':
roomEngine.updateRoomInstancePlaneType(roomEngine.activeRoomId, type, wallType, landscapeType, true);
return;
case 'wallpaper':
roomEngine.updateRoomInstancePlaneType(roomEngine.activeRoomId, floorType, type, landscapeType, true);
return;
case 'landscape':
roomEngine.updateRoomInstancePlaneType(roomEngine.activeRoomId, floorType, wallType, type, true);
return;
default:
roomEngine.updateRoomInstancePlaneType(roomEngine.activeRoomId, floorType, wallType, landscapeType, true);
return;
}
}, []);
const cancelObjectMover = useCallback(() =>
{
if(!purchasableOffer) return;
GetRoomEngine().cancelRoomObjectInsert();
setObjectMoverRequested(false);
setPurchaseableOffer(null);
}, [ purchasableOffer ]);
const resetObjectMover = useCallback((flag: boolean = true) =>
{
setObjectMoverRequested(prevValue =>
{
if(prevValue && flag)
{
CreateLinkEvent('catalog/open');
}
return false;
});
}, []);
const resetPlacedOfferData = useCallback((flag: boolean = false) =>
{
if(!flag) resetObjectMover();
setPlacedObjectPurchaseData(prevValue =>
{
if(prevValue)
{
switch(prevValue.category)
{
case RoomObjectCategory.FLOOR:
GetRoomEngine().removeRoomObjectFloor(prevValue.roomId, prevValue.objectId);
break;
case RoomObjectCategory.WALL: {
switch(prevValue.furniData.className)
{
case 'floor':
case 'wallpaper':
case 'landscape':
resetRoomPaint('reset', '');
break;
default:
GetRoomEngine().removeRoomObjectWall(prevValue.roomId, prevValue.objectId);
break;
}
break;
}
default:
GetRoomEngine().deleteRoomObject(prevValue.objectId, prevValue.category);
break;
}
}
return null;
});
}, [ resetObjectMover, resetRoomPaint ]);
const getNodeById = useCallback((id: number, node: ICatalogNode) => const getNodeById = useCallback((id: number, node: ICatalogNode) =>
{ {
if((node.pageId === id) && (node !== rootNode)) return node; if((node.pageId === id) && (node !== rootNode)) return node;
@ -238,6 +410,11 @@ const useCatalogState = () =>
} }
}, [ isVisible, getNodesByOfferId, activateNode ]); }, [ isVisible, getNodesByOfferId, activateNode ]);
const refreshBuilderStatus = useCallback(() =>
{
}, []);
const onCatalogPagesListEvent = useCallback((event: CatalogPagesListEvent) => const onCatalogPagesListEvent = useCallback((event: CatalogPagesListEvent) =>
{ {
const parser = event.getParser(); const parser = event.getParser();
@ -421,22 +598,6 @@ const useCatalogState = () =>
UseMessageEventHook(SellablePetPalettesMessageEvent, onSellablePetPalettesMessageEvent); UseMessageEventHook(SellablePetPalettesMessageEvent, onSellablePetPalettesMessageEvent);
const onApproveNameMessageEvent = useCallback((event: ApproveNameMessageEvent) =>
{
const parser = event.getParser();
DispatchUiEvent(new CatalogNameResultEvent(parser.result, parser.validationInfo));
}, []);
UseMessageEventHook(ApproveNameMessageEvent, onApproveNameMessageEvent);
const onGiftReceiverNotFoundEvent = useCallback(() =>
{
DispatchUiEvent(new CatalogGiftReceiverNotFoundEvent());
}, []);
UseMessageEventHook(GiftReceiverNotFoundEvent, onGiftReceiverNotFoundEvent);
const onHabboClubOffersMessageEvent = useCallback((event: HabboClubOffersMessageEvent) => const onHabboClubOffersMessageEvent = useCallback((event: HabboClubOffersMessageEvent) =>
{ {
const parser = event.getParser(); const parser = event.getParser();
@ -527,6 +688,32 @@ const useCatalogState = () =>
UseMessageEventHook(CatalogPublishedMessageEvent, onCatalogPublishedMessageEvent); UseMessageEventHook(CatalogPublishedMessageEvent, onCatalogPublishedMessageEvent);
const onBuildersClubFurniCountMessageEvent = useCallback((event: BuildersClubFurniCountMessageEvent) =>
{
const parser = event.getParser();
setFurniCount(parser.furniCount);
refreshBuilderStatus();
}, [ refreshBuilderStatus ]);
UseMessageEventHook(BuildersClubFurniCountMessageEvent, onBuildersClubFurniCountMessageEvent);
const onBuildersClubSubscriptionStatusMessageEvent = useCallback((event: BuildersClubSubscriptionStatusMessageEvent) =>
{
const parser = event.getParser();
setFurniLimit(parser._Str_15864);
setMaxFurniLimit(parser._Str_24094);
setSecondsLeft(parser._Str_3709);
setUpdateTime(GetNitroInstance().time);
setSecondsLeftWithGrace(parser._Str_24379);
refreshBuilderStatus();
}, [ refreshBuilderStatus ]);
UseMessageEventHook(BuildersClubSubscriptionStatusMessageEvent, onBuildersClubSubscriptionStatusMessageEvent);
const onCatalogPurchasedEvent = useCallback((event: CatalogPurchasedEvent) => const onCatalogPurchasedEvent = useCallback((event: CatalogPurchasedEvent) =>
{ {
PlaySound(SoundNames.CREDITS); PlaySound(SoundNames.CREDITS);
@ -534,6 +721,153 @@ const useCatalogState = () =>
UseUiEvent(CatalogPurchasedEvent.PURCHASE_SUCCESS, onCatalogPurchasedEvent); UseUiEvent(CatalogPurchasedEvent.PURCHASE_SUCCESS, onCatalogPurchasedEvent);
const onRoomEngineObjectPlacedEvent = useCallback((event: RoomEngineObjectPlacedEvent) =>
{
if(!objectMoverRequested || (event.type !== RoomEngineObjectPlacedEvent.PLACED)) return;
resetPlacedOfferData(true);
if(!purchasableOffer)
{
resetObjectMover();
return;
}
let placed = false;
const product = purchasableOffer.product;
if(event.category === RoomObjectCategory.WALL)
{
switch(product.furnitureData.className)
{
case 'floor':
case 'wallpaper':
case 'landscape':
placed = (event.placedOnFloor || event.placedOnWall);
break;
default:
placed = event.placedInRoom;
break;
}
}
else
{
placed = event.placedInRoom;
}
if(!placed)
{
resetObjectMover();
return;
}
setPlacedObjectPurchaseData(new PlacedObjectPurchaseData(event.roomId, event.objectId, event.category, event.wallLocation, event.x, event.y, event.direction, purchasableOffer));
switch(currentType)
{
case CatalogType.NORMAL: {
switch(event.category)
{
case RoomObjectCategory.FLOOR:
GetRoomEngine().addFurnitureFloor(event.roomId, event.objectId, product.productClassId, new Vector3d(event.x, event.y, event.z), new Vector3d(event.direction), 0, new LegacyDataType());
break;
case RoomObjectCategory.WALL: {
switch(product.furnitureData.className)
{
case 'floor':
case 'wallpaper':
case 'landscape':
resetRoomPaint(product.furnitureData.className, product.extraParam);
break;
default:
GetRoomEngine().addFurnitureWall(event.roomId, event.objectId, product.productClassId, new Vector3d(event.x, event.y, event.z), new Vector3d(event.direction * 45), 0, event.instanceData, 0);
break;
}
}
}
const roomObject = GetRoomEngine().getRoomObject(event.roomId, event.objectId, event.category);
if(roomObject) roomObject.model.setValue(RoomObjectVariable.FURNITURE_ALPHA_MULTIPLIER, 0.5);
if(catalogSkipPurchaseConfirmation)
{
SendMessageComposer(new PurchaseFromCatalogComposer(pageId, purchasableOffer.offerId, product.extraParam, 1));
if(catalogPlaceMultipleObjects) requestOfferToMover(purchasableOffer);
}
else
{
// confirm
if(catalogPlaceMultipleObjects) requestOfferToMover(purchasableOffer);
}
break;
}
case CatalogType.BUILDER: {
let pageId = purchasableOffer.page.pageId;
if(pageId === DUMMY_PAGE_ID_FOR_OFFER_SEARCH)
{
pageId = -1;
}
switch(event.category)
{
case RoomObjectCategory.FLOOR:
SendMessageComposer(new BuildersClubPlaceRoomItemMessageComposer(pageId, purchasableOffer.offerId, product.extraParam, event.x, event.y, event.direction));
break;
case RoomObjectCategory.WALL:
SendMessageComposer(new BuildersClubPlaceWallItemMessageComposer(pageId, purchasableOffer.offerId, product.extraParam, event.wallLocation));
break;
}
if(catalogPlaceMultipleObjects) requestOfferToMover(purchasableOffer);
break;
}
}
}, [ objectMoverRequested, purchasableOffer, catalogPlaceMultipleObjects, catalogSkipPurchaseConfirmation, currentType, pageId, resetPlacedOfferData, resetObjectMover, resetRoomPaint, requestOfferToMover ]);
UseRoomEngineEvent(RoomEngineObjectPlacedEvent.PLACED, onRoomEngineObjectPlacedEvent);
const onInventoryFurniAddedEvent = useCallback((event: InventoryFurniAddedEvent) =>
{
const roomEngine = GetRoomEngine();
if(!placedObjectPurchaseData || (placedObjectPurchaseData.productClassId !== event.spriteId) || (placedObjectPurchaseData.roomId !== roomEngine.activeRoomId)) return;
switch(event.category)
{
case FurniCategory.FLOOR: {
const floorType = roomEngine.getRoomInstanceVariable(roomEngine.activeRoomId, RoomObjectVariable.ROOM_FLOOR_TYPE);
if(placedObjectPurchaseData.extraParam !== floorType) SendMessageComposer(new FurniturePlacePaintComposer(event.id));
break;
}
case FurniCategory.WALL_PAPER: {
const wallType = roomEngine.getRoomInstanceVariable(roomEngine.activeRoomId, RoomObjectVariable.ROOM_WALL_TYPE);
if(placedObjectPurchaseData.extraParam !== wallType) SendMessageComposer(new FurniturePlacePaintComposer(event.id));
break;
}
case FurniCategory.LANDSCAPE: {
const landscapeType = roomEngine.getRoomInstanceVariable(roomEngine.activeRoomId, RoomObjectVariable.ROOM_LANDSCAPE_TYPE);
if(placedObjectPurchaseData.extraParam !== landscapeType) SendMessageComposer(new FurniturePlacePaintComposer(event.id));
break;
}
default:
SendMessageComposer(new FurniturePlaceComposer(event.id, placedObjectPurchaseData.category, placedObjectPurchaseData.wallLocation, placedObjectPurchaseData.x, placedObjectPurchaseData.y, placedObjectPurchaseData.direction));
}
if(!catalogPlaceMultipleObjects) resetPlacedOfferData();
}, [ placedObjectPurchaseData, catalogPlaceMultipleObjects, resetPlacedOfferData ]);
UseUiEvent(InventoryFurniAddedEvent.FURNI_ADDED, onInventoryFurniAddedEvent);
useEffect(() => useEffect(() =>
{ {
return () => setCurrentOffer(null); return () => setCurrentOffer(null);
@ -588,6 +922,7 @@ const useCatalogState = () =>
SendMessageComposer(new GetGiftWrappingConfigurationComposer()); SendMessageComposer(new GetGiftWrappingConfigurationComposer());
SendMessageComposer(new GetClubGiftInfo()); SendMessageComposer(new GetClubGiftInfo());
SendMessageComposer(new GetCatalogIndexComposer(currentType)); SendMessageComposer(new GetCatalogIndexComposer(currentType));
SendMessageComposer(new BuildersClubQueryFurniCountMessageComposer());
}, [ isVisible, rootNode, currentType ]); }, [ isVisible, rootNode, currentType ]);
useEffect(() => useEffect(() =>

View File

@ -1,54 +0,0 @@
import { BuildersClubFurniCountMessageEvent, BuildersClubQueryFurniCountMessageComposer, BuildersClubSubscriptionStatusMessageEvent } from '@nitrots/nitro-renderer';
import { useCallback, useEffect, useState } from 'react';
import { GetNitroInstance, SendMessageComposer } from '../../api';
import { UseMessageEventHook } from '../messages';
const useCatalogBuildersClubState = () =>
{
const [ furniCount, setFurniCount ] = useState(0);
const [ furniLimit, setFurniLimit ] = useState(0);
const [ maxFurniLimit, setMaxFurniLimit ] = useState(0);
const [ secondsLeft, setSecondsLeft ] = useState(0);
const [ updateTime, setUpdateTime ] = useState(0);
const [ secondsLeftWithGrace, setSecondsLeftWithGrace ] = useState(0);
const refreshBuilderStatus = useCallback(() =>
{
}, []);
const onBuildersClubFurniCountMessageEvent = useCallback((event: BuildersClubFurniCountMessageEvent) =>
{
const parser = event.getParser();
setFurniCount(parser.furniCount);
refreshBuilderStatus();
}, [ refreshBuilderStatus ]);
UseMessageEventHook(BuildersClubFurniCountMessageEvent, onBuildersClubFurniCountMessageEvent);
const onBuildersClubSubscriptionStatusMessageEvent = useCallback((event: BuildersClubSubscriptionStatusMessageEvent) =>
{
const parser = event.getParser();
setFurniLimit(parser._Str_15864);
setMaxFurniLimit(parser._Str_24094);
setSecondsLeft(parser._Str_3709);
setUpdateTime(GetNitroInstance().time);
setSecondsLeftWithGrace(parser._Str_24379);
refreshBuilderStatus();
}, [ refreshBuilderStatus ]);
UseMessageEventHook(BuildersClubSubscriptionStatusMessageEvent, onBuildersClubSubscriptionStatusMessageEvent);
useEffect(() =>
{
SendMessageComposer(new BuildersClubQueryFurniCountMessageComposer());
}, []);
return { furniCount, furniLimit, maxFurniLimit, secondsLeft, updateTime, secondsLeftWithGrace };
}
export const useCatalogBuildersClub = useCatalogBuildersClubState;

View File

@ -1,330 +0,0 @@
import { BuildersClubPlaceRoomItemMessageComposer, BuildersClubPlaceWallItemMessageComposer, FurniturePlaceComposer, FurniturePlacePaintComposer, LegacyDataType, PurchaseFromCatalogComposer, RoomControllerLevel, RoomEngineObjectPlacedEvent, RoomObjectCategory, RoomObjectPlacementSource, RoomObjectType, RoomObjectVariable, Vector3d } from '@nitrots/nitro-renderer';
import { useCallback, useState } from 'react';
import { BuilderFurniPlaceableStatus, CatalogType, CreateLinkEvent, FurniCategory, GetRoomEngine, GetRoomSession, IPurchasableOffer, IPurchaseOptions, Offer, PlacedObjectPurchaseData, ProductTypeEnum, SendMessageComposer } from '../../api';
import { InventoryFurniAddedEvent } from '../../events';
import { UseRoomEngineEvent, UseUiEvent } from '../events';
import { useCatalogPlaceMultipleItems } from './useCatalogPlaceMultipleItems';
import { useCatalogSkipPurchaseConfirmation } from './useCatalogSkipPurchaseConfirmation';
const DUMMY_PAGE_ID_FOR_OFFER_SEARCH = -12345678;
const DRAG_AND_DROP_ENABLED = true;
const useCatalogItemMoverState = (catalog: { currentType: string, pageId: number, currentOffer: IPurchasableOffer, purchaseOptions: IPurchaseOptions }, buildersClub: { furniCount: number, furniLimit: number, secondsLeft: number }) =>
{
const [ objectMoverRequested, setObjectMoverRequested ] = useState(false);
const [ catalogPlaceMultipleObjects, setCatalogPlaceMultipleObjects ] = useCatalogPlaceMultipleItems();
const [ catalogSkipPurchaseConfirmation, setCatalogSkipPurchaseConfirmation ] = useCatalogSkipPurchaseConfirmation();
const [ purchasableOffer, setPurchaseableOffer ] = useState<IPurchasableOffer>(null);
const [ placedObjectPurchaseData, setPlacedObjectPurchaseData ] = useState<PlacedObjectPurchaseData>(null);
const getBuilderFurniPlaceableStatus = useCallback((offer: IPurchasableOffer) =>
{
if(!offer) return BuilderFurniPlaceableStatus.MISSING_OFFER;
if((buildersClub.furniCount < 0) || (buildersClub.furniCount >= buildersClub.furniLimit)) return BuilderFurniPlaceableStatus.FURNI_LIMIT_REACHED;
const roomSession = GetRoomSession();
if(!roomSession) return BuilderFurniPlaceableStatus.NOT_IN_ROOM;
if(!roomSession.isRoomOwner) return BuilderFurniPlaceableStatus.NOT_ROOM_OWNER;
if(buildersClub.secondsLeft <= 0)
{
const roomEngine = GetRoomEngine();
let objectCount = roomEngine.getRoomObjectCount(roomSession.roomId, RoomObjectCategory.UNIT);
while(objectCount > 0)
{
const roomObject = roomEngine.getRoomObjectByIndex(roomSession.roomId, objectCount, RoomObjectCategory.UNIT);
const userData = roomSession.userDataManager.getUserDataByIndex(roomObject.id);
if(userData && (userData.type === RoomObjectType.USER) && (userData.roomIndex !== roomSession.ownRoomIndex) && !userData.isModerator) return BuilderFurniPlaceableStatus.VISITORS_IN_ROOM;
objectCount--;
}
}
return BuilderFurniPlaceableStatus.OKAY;
}, [ buildersClub.furniCount, buildersClub.furniLimit, buildersClub.secondsLeft ]);
const isDraggable = useCallback((offer: IPurchasableOffer) =>
{
const roomSession = GetRoomSession();
if(((DRAG_AND_DROP_ENABLED && roomSession && offer.page && (offer.page.layoutCode !== 'sold_ltd_items') && (catalog.currentType === CatalogType.NORMAL) && (roomSession.isRoomOwner || (roomSession.isGuildRoom && (roomSession.controllerLevel >= RoomControllerLevel.GUILD_MEMBER)))) || ((catalog.currentType === CatalogType.BUILDER) && (getBuilderFurniPlaceableStatus(offer) === BuilderFurniPlaceableStatus.OKAY))) && (offer.pricingModel !== Offer.PRICING_MODEL_BUNDLE) && (offer.product.productType !== ProductTypeEnum.EFFECT) && (offer.product.productType !== ProductTypeEnum.HABBO_CLUB)) return true;
return false;
}, [ catalog.currentType, getBuilderFurniPlaceableStatus ]);
const requestOfferToMover = useCallback((offer: IPurchasableOffer) =>
{
if(!isDraggable(offer)) return;
const product = offer.product;
if(!product) return;
let category = 0;
switch(product.productType)
{
case ProductTypeEnum.FLOOR:
category = RoomObjectCategory.FLOOR;
break;
case ProductTypeEnum.WALL:
category = RoomObjectCategory.WALL;
break;
}
if(GetRoomEngine().processRoomObjectPlacement(RoomObjectPlacementSource.CATALOG, -(offer.offerId), category, product.productClassId, product.extraParam))
{
setPurchaseableOffer(offer);
setObjectMoverRequested(true);
CreateLinkEvent('catalog/hide');
}
}, [ isDraggable ]);
const resetRoomPaint = useCallback((planeType: string, type: string) =>
{
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';
switch(planeType)
{
case 'floor':
roomEngine.updateRoomInstancePlaneType(roomEngine.activeRoomId, type, wallType, landscapeType, true);
return;
case 'wallpaper':
roomEngine.updateRoomInstancePlaneType(roomEngine.activeRoomId, floorType, type, landscapeType, true);
return;
case 'landscape':
roomEngine.updateRoomInstancePlaneType(roomEngine.activeRoomId, floorType, wallType, type, true);
return;
default:
roomEngine.updateRoomInstancePlaneType(roomEngine.activeRoomId, floorType, wallType, landscapeType, true);
return;
}
}, []);
const cancelObjectMover = useCallback(() =>
{
if(!purchasableOffer) return;
GetRoomEngine().cancelRoomObjectInsert();
setObjectMoverRequested(false);
setPurchaseableOffer(null);
}, [ purchasableOffer ]);
const resetObjectMover = useCallback((flag: boolean = true) =>
{
setObjectMoverRequested(prevValue =>
{
if(prevValue && flag)
{
CreateLinkEvent('catalog/open');
}
return false;
});
}, []);
const resetPlacedOfferData = useCallback((flag: boolean = false) =>
{
if(!flag) resetObjectMover();
setPlacedObjectPurchaseData(prevValue =>
{
if(prevValue)
{
switch(prevValue.category)
{
case RoomObjectCategory.FLOOR:
GetRoomEngine().removeRoomObjectFloor(prevValue.roomId, prevValue.objectId);
break;
case RoomObjectCategory.WALL: {
switch(prevValue.furniData.className)
{
case 'floor':
case 'wallpaper':
case 'landscape':
resetRoomPaint('reset', '');
break;
default:
GetRoomEngine().removeRoomObjectWall(prevValue.roomId, prevValue.objectId);
break;
}
break;
}
default:
GetRoomEngine().deleteRoomObject(prevValue.objectId, prevValue.category);
break;
}
}
return null;
});
}, [ resetObjectMover, resetRoomPaint ]);
const onRoomEngineObjectPlacedEvent = useCallback((event: RoomEngineObjectPlacedEvent) =>
{
if(!objectMoverRequested || (event.type !== RoomEngineObjectPlacedEvent.PLACED)) return;
resetPlacedOfferData(true);
if(!purchasableOffer)
{
resetObjectMover();
return;
}
let placed = false;
const product = purchasableOffer.product;
if(event.category === RoomObjectCategory.WALL)
{
switch(product.furnitureData.className)
{
case 'floor':
case 'wallpaper':
case 'landscape':
placed = (event.placedOnFloor || event.placedOnWall);
break;
default:
placed = event.placedInRoom;
break;
}
}
else
{
placed = event.placedInRoom;
}
if(!placed)
{
resetObjectMover();
return;
}
setPlacedObjectPurchaseData(new PlacedObjectPurchaseData(event.roomId, event.objectId, event.category, event.wallLocation, event.x, event.y, event.direction, purchasableOffer));
switch(catalog.currentType)
{
case CatalogType.NORMAL: {
switch(event.category)
{
case RoomObjectCategory.FLOOR:
GetRoomEngine().addFurnitureFloor(event.roomId, event.objectId, product.productClassId, new Vector3d(event.x, event.y, event.z), new Vector3d(event.direction), 0, new LegacyDataType());
break;
case RoomObjectCategory.WALL: {
switch(product.furnitureData.className)
{
case 'floor':
case 'wallpaper':
case 'landscape':
resetRoomPaint(product.furnitureData.className, product.extraParam);
break;
default:
GetRoomEngine().addFurnitureWall(event.roomId, event.objectId, product.productClassId, new Vector3d(event.x, event.y, event.z), new Vector3d(event.direction * 45), 0, event.instanceData, 0);
break;
}
}
}
const roomObject = GetRoomEngine().getRoomObject(event.roomId, event.objectId, event.category);
if(roomObject) roomObject.model.setValue(RoomObjectVariable.FURNITURE_ALPHA_MULTIPLIER, 0.5);
if(catalogSkipPurchaseConfirmation)
{
SendMessageComposer(new PurchaseFromCatalogComposer(catalog.pageId, purchasableOffer.offerId, product.extraParam, 1));
if(catalogPlaceMultipleObjects) requestOfferToMover(purchasableOffer);
}
else
{
// confirm
if(catalogPlaceMultipleObjects) requestOfferToMover(purchasableOffer);
}
break;
}
case CatalogType.BUILDER: {
let pageId = purchasableOffer.page.pageId;
if(pageId === DUMMY_PAGE_ID_FOR_OFFER_SEARCH)
{
pageId = -1;
}
switch(event.category)
{
case RoomObjectCategory.FLOOR:
SendMessageComposer(new BuildersClubPlaceRoomItemMessageComposer(pageId, purchasableOffer.offerId, product.extraParam, event.x, event.y, event.direction));
break;
case RoomObjectCategory.WALL:
SendMessageComposer(new BuildersClubPlaceWallItemMessageComposer(pageId, purchasableOffer.offerId, product.extraParam, event.wallLocation));
break;
}
if(catalogPlaceMultipleObjects) requestOfferToMover(purchasableOffer);
break;
}
}
}, [ objectMoverRequested, purchasableOffer, catalogPlaceMultipleObjects, catalogSkipPurchaseConfirmation, catalog, resetPlacedOfferData, resetObjectMover, resetRoomPaint, requestOfferToMover ]);
UseRoomEngineEvent(RoomEngineObjectPlacedEvent.PLACED, onRoomEngineObjectPlacedEvent);
const onInventoryFurniAddedEvent = useCallback((event: InventoryFurniAddedEvent) =>
{
const roomEngine = GetRoomEngine();
if(!placedObjectPurchaseData || (placedObjectPurchaseData.productClassId !== event.spriteId) || (placedObjectPurchaseData.roomId !== roomEngine.activeRoomId)) return;
switch(event.category)
{
case FurniCategory.FLOOR: {
const floorType = roomEngine.getRoomInstanceVariable(roomEngine.activeRoomId, RoomObjectVariable.ROOM_FLOOR_TYPE);
if(placedObjectPurchaseData.extraParam !== floorType) SendMessageComposer(new FurniturePlacePaintComposer(event.id));
break;
}
case FurniCategory.WALL_PAPER: {
const wallType = roomEngine.getRoomInstanceVariable(roomEngine.activeRoomId, RoomObjectVariable.ROOM_WALL_TYPE);
if(placedObjectPurchaseData.extraParam !== wallType) SendMessageComposer(new FurniturePlacePaintComposer(event.id));
break;
}
case FurniCategory.LANDSCAPE: {
const landscapeType = roomEngine.getRoomInstanceVariable(roomEngine.activeRoomId, RoomObjectVariable.ROOM_LANDSCAPE_TYPE);
if(placedObjectPurchaseData.extraParam !== landscapeType) SendMessageComposer(new FurniturePlacePaintComposer(event.id));
break;
}
default:
SendMessageComposer(new FurniturePlaceComposer(event.id, placedObjectPurchaseData.category, placedObjectPurchaseData.wallLocation, placedObjectPurchaseData.x, placedObjectPurchaseData.y, placedObjectPurchaseData.direction));
}
if(!catalogPlaceMultipleObjects) resetPlacedOfferData();
}, [ placedObjectPurchaseData, catalogPlaceMultipleObjects, resetPlacedOfferData ]);
UseUiEvent(InventoryFurniAddedEvent.FURNI_ADDED, onInventoryFurniAddedEvent);
return { requestOfferToMover, cancelObjectMover };
}
export const useCatalogItemMover = useCatalogItemMoverState;

View File

@ -268,7 +268,7 @@ const useInventoryFurniState = () =>
setNeedsUpdate(false); setNeedsUpdate(false);
}, [ isVisible, needsUpdate ]); }, [ isVisible, needsUpdate ]);
return { groupItems, setGroupItems, selectedItem, setSelectedItem, activate, deactivate }; return { isVisible, groupItems, setGroupItems, selectedItem, setSelectedItem, activate, deactivate };
} }
export const useInventoryFurni = () => useBetween(useInventoryFurniState); export const useInventoryFurni = () => useBetween(useInventoryFurniState);