diff --git a/src/api/room/widgets/ICraftingIngredient.ts b/src/api/room/widgets/ICraftingIngredient.ts new file mode 100644 index 00000000..cb2b0311 --- /dev/null +++ b/src/api/room/widgets/ICraftingIngredient.ts @@ -0,0 +1,6 @@ +export interface ICraftingIngredient +{ + name: string; + iconUrl: string; + count: number; +} diff --git a/src/api/room/widgets/ICraftingRecipe.ts b/src/api/room/widgets/ICraftingRecipe.ts new file mode 100644 index 00000000..dd99291f --- /dev/null +++ b/src/api/room/widgets/ICraftingRecipe.ts @@ -0,0 +1,6 @@ +export interface ICraftingRecipe +{ + name: string; + localizedName: string; + iconUrl: string; +} diff --git a/src/api/room/widgets/index.ts b/src/api/room/widgets/index.ts index 14e561c3..ac77f8ef 100644 --- a/src/api/room/widgets/index.ts +++ b/src/api/room/widgets/index.ts @@ -11,6 +11,8 @@ export * from './DimmerFurnitureWidgetPresetItem'; export * from './DoChatsOverlap'; export * from './FurnitureDimmerUtilities'; export * from './IAvatarInfo'; +export * from './ICraftingIngredient'; +export * from './ICraftingRecipe'; export * from './IPhotoData'; export * from './MannequinUtilities'; export * from './PetSupplementEnum'; diff --git a/src/components/room/widgets/furniture/FurnitureCraftingView.tsx b/src/components/room/widgets/furniture/FurnitureCraftingView.tsx index 9f213dc4..28324392 100644 --- a/src/components/room/widgets/furniture/FurnitureCraftingView.tsx +++ b/src/components/room/widgets/furniture/FurnitureCraftingView.tsx @@ -1,21 +1,15 @@ -import { CraftingRecipeIngredientParser, RoomObjectCategory } from '@nitrots/nitro-renderer'; -import { FC, useEffect, useMemo, useState } from 'react'; +import { RoomObjectCategory } from '@nitrots/nitro-renderer'; +import { FC, ReactElement, useEffect, useMemo, useState } from 'react'; import { GetRoomEngine, IsOwnerOfFurniture, LocalizeText } from '../../../../api'; import { AutoGrid, Button, Column, Flex, LayoutGridItem, LayoutLoadingSpinnerView, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../common'; import { useFurnitureCraftingWidget, useRoom } from '../../../../hooks'; export const FurnitureCraftingView: FC<{}> = props => { - const { objectId = -1, recipes = [], ingredients = [], selectedRecipe = null, selectedRecipeIngredients = null, isCrafting = false, craft = null, selectRecipe = null, onClose = null } = useFurnitureCraftingWidget(); + const { objectId = -1, recipes = [], ingredients = [], selectedRecipe = null, requiredIngredients = null, isCrafting = false, craft = null, selectRecipe = null, onClose = null } = useFurnitureCraftingWidget(); const { roomSession = null } = useRoom(); - const [ waitingToConfirm, setWaitingToConfirm ] = useState(false); - useEffect(() => - { - setWaitingToConfirm(false); - }, [ selectedRecipe ]); - const isOwner = useMemo(() => { const roomObject = GetRoomEngine().getRoomObject(roomSession.roomId, objectId, RoomObjectCategory.FLOOR); @@ -24,21 +18,24 @@ export const FurnitureCraftingView: FC<{}> = props => const canCraft = useMemo(() => { - for (const ingredient of selectedRecipeIngredients) + if(!requiredIngredients || !requiredIngredients.length) return false; + + for (const ingredient of requiredIngredients) { - const ingredientData = ingredients.find((i) => i.name === ingredient.itemName); + const ingredientData = ingredients.find(data => (data.name === ingredient.itemName)); if (ingredientData.count < ingredient.count) return false; } return true; - }, [ ingredients, selectedRecipeIngredients ]); + }, [ ingredients, requiredIngredients ]); const tryCraft = () => { if (!waitingToConfirm) { setWaitingToConfirm(true); + return; } @@ -46,19 +43,10 @@ export const FurnitureCraftingView: FC<{}> = props => setWaitingToConfirm(false); }; - const renderSelectedRecipeIngredient = (ingredient: CraftingRecipeIngredientParser) => + useEffect(() => { - const ingredientData = ingredients.find((i) => i.name === ingredient.itemName); - - const elements = []; - - for (let i = 0; i < ingredient.count; i++) - { - elements.push(); - } - - return elements; - }; + setWaitingToConfirm(false); + }, [ selectedRecipe ]); if(objectId === -1) return null; @@ -87,7 +75,19 @@ export const FurnitureCraftingView: FC<{}> = props =>
{ LocalizeText('crafting.current_recipe') }
- { (selectedRecipeIngredients.length > 0) && selectedRecipeIngredients.map((item) => renderSelectedRecipeIngredient(item)) } + { !!requiredIngredients && (requiredIngredients.length > 0) && requiredIngredients.map(ingredient => + { + const ingredientData = ingredients.find((i) => i.name === ingredient.itemName); + + const elements: ReactElement[] = []; + + for (let i = 0; i < ingredient.count; i++) + { + elements.push(); + } + + return elements; + }) }
diff --git a/src/hooks/rooms/widgets/furniture/useFurnitureCraftingWidget.ts b/src/hooks/rooms/widgets/furniture/useFurnitureCraftingWidget.ts index 5bd285d4..8399a8e9 100644 --- a/src/hooks/rooms/widgets/furniture/useFurnitureCraftingWidget.ts +++ b/src/hooks/rooms/widgets/furniture/useFurnitureCraftingWidget.ts @@ -1,30 +1,30 @@ import { CraftableProductsEvent, CraftComposer, CraftingRecipeEvent, CraftingRecipeIngredientParser, CraftingRecipesAvailableEvent, CraftingResultEvent, GetCraftableProductsComposer, GetCraftingRecipeComposer, RoomEngineTriggerWidgetEvent, RoomWidgetEnum } from '@nitrots/nitro-renderer'; -import { useCallback, useState } from 'react'; -import { GetRoomEngine, LocalizeText, SendMessageComposer } from '../../../../api'; +import { useEffect, useState } from 'react'; +import { GetRoomEngine, ICraftingIngredient, ICraftingRecipe, LocalizeText, SendMessageComposer } from '../../../../api'; import { useMessageEvent, useRoomEngineEvent } from '../../../events'; import { useInventoryFurni } from '../../../inventory'; -import { useNotification } from './../../../notification/useNotification'; +import { useNotification } from './../../../notification'; const useFurnitureCraftingWidgetState = () => -{ - const { getItemsByType } = useInventoryFurni(); - const { simpleAlert } = useNotification(); - +{ const [ objectId, setObjectId ] = useState(-1); - const [ recipes, setRecipes ] = useState<{ name: string, localizedName: string, iconUrl: string }[]>([]); - const [ ingredients, setIngredients ] = useState<{ name: string, iconUrl: string, count: number }[]>([]); - const [ selectedRecipe, setSelectedRecipe ] = useState<{ name: string, localizedName: string, iconUrl: string }>(null); - const [ selectedRecipeIngredients, setSelectedRecipeIngredients ] = useState([]); - const [ cacheRecipeIngredients, setCacheRecipeIngredients ] = useState>(new Map()); + const [ recipes, setRecipes ] = useState([]); + const [ selectedRecipe, setSelectedRecipe ] = useState(null); + const [ ingredients, setIngredients ] = useState([]); + const [ ingredientNames, setIngredientNames ] = useState(null); + const [ cachedIngredients, setCachedIngredients ] = useState>(new Map()); const [ isCrafting, setIsCrafting ] = useState(false); + const { groupItems = [], getItemsByType = null, activate = null, deactivate = null } = useInventoryFurni(); + const { simpleAlert = null } = useNotification(); + + const requiredIngredients = ((selectedRecipe && cachedIngredients.get(selectedRecipe.name) || null)); const resetData = () => { setRecipes([]); - setIngredients([]); setSelectedRecipe(null); - setSelectedRecipeIngredients([]); - setCacheRecipeIngredients(new Map()); + setIngredients([]); + setCachedIngredients(new Map()); }; const onClose = () => @@ -36,26 +36,23 @@ const useFurnitureCraftingWidgetState = () => const craft = () => { setIsCrafting(true); + SendMessageComposer(new CraftComposer(objectId, selectedRecipe.name)); }; - const selectRecipe = useCallback((recipe: { name: string, localizedName: string, iconUrl: string }) => + const selectRecipe = (recipe: ICraftingRecipe) => { - setSelectedRecipeIngredients([]); setSelectedRecipe(recipe); - const cache = cacheRecipeIngredients.get(recipe.name); + const cache = cachedIngredients.get(recipe.name); - if (cache) - setSelectedRecipeIngredients(cache); - else - SendMessageComposer(new GetCraftingRecipeComposer(recipe.name)); - }, [ cacheRecipeIngredients ]); + if(!cache) SendMessageComposer(new GetCraftingRecipeComposer(recipe.name)); + } useRoomEngineEvent(RoomEngineTriggerWidgetEvent.OPEN_WIDGET, event => { if (event.widget !== RoomWidgetEnum.CRAFTING) return; - console.log(event); + setObjectId(event.objectId); resetData(); SendMessageComposer(new GetCraftableProductsComposer(event.objectId)); @@ -68,78 +65,102 @@ const useFurnitureCraftingWidgetState = () => if (!parser.isActive()) { setObjectId(-1); + return; } - const recipesToSet = []; - - for(const recipe of parser.recipes) + setRecipes(prevValue => { - //@ts-ignore - const itemId = GetRoomEngine().roomContentLoader._activeObjectTypeIds.get(recipe.itemName); - const iconUrl = GetRoomEngine().getFurnitureFloorIconUrl(itemId); - recipesToSet.push({ - name: recipe.itemName, - localizedName: LocalizeText('roomItem.name.' + itemId), - iconUrl - }); - } + const newValue: ICraftingRecipe[] = []; - setRecipes(recipesToSet); + for(const recipe of parser.recipes) + { + //@ts-ignore + const itemId = GetRoomEngine().roomContentLoader._activeObjectTypeIds.get(recipe.itemName); + const iconUrl = GetRoomEngine().getFurnitureFloorIconUrl(itemId); - const ingredientsToSet = []; + newValue.push({ + name: recipe.itemName, + localizedName: LocalizeText('roomItem.name.' + itemId), + iconUrl + }); + } - for(const ingredient of parser.ingredients) - { - //@ts-ignore - const itemId = GetRoomEngine().roomContentLoader._activeObjectTypeIds.get(ingredient); - const iconUrl = GetRoomEngine().getFurnitureFloorIconUrl(itemId); + return newValue; + }); - const inventoryItems = getItemsByType(itemId); - let amountAvailable = 0; - - for (const inventoryItem of inventoryItems) amountAvailable += inventoryItem.items.length; - - ingredientsToSet.push({ - name: ingredient, - iconUrl, - count: amountAvailable - }); - } - - setIngredients(ingredientsToSet); + setIngredientNames(parser.ingredients); }); useMessageEvent(CraftingRecipeEvent, event => { const parser = event.getParser(); - setSelectedRecipeIngredients(parser.ingredients); - const newCache = new Map(cacheRecipeIngredients); - newCache.set(selectedRecipe.name, parser.ingredients); - setCacheRecipeIngredients(newCache); + setCachedIngredients(prevValue => + { + const newValue = new Map(prevValue); + + newValue.set(selectedRecipe.name, parser.ingredients); + + return newValue; + }); }); useMessageEvent(CraftingResultEvent, event => { setSelectedRecipe(null); - setSelectedRecipeIngredients([]); + setIsCrafting(false); const parser = event.getParser(); - if (parser.result) - { - simpleAlert(LocalizeText('crafting.info.result.ok')); - } - - setIsCrafting(false); + if(parser.result) simpleAlert(LocalizeText('crafting.info.result.ok')); }); useMessageEvent(CraftingRecipesAvailableEvent, event => { }); - return { objectId, recipes, ingredients, selectedRecipe, selectedRecipeIngredients, isCrafting, selectRecipe, craft, onClose }; + useEffect(() => + { + if(!groupItems || !groupItems.length || !ingredientNames || !ingredientNames.length) return; + + setIngredients(prevValue => + { + const newValue: ICraftingIngredient[] = []; + + for(const name of ingredientNames) + { + //@ts-ignore + const itemId = GetRoomEngine().roomContentLoader._activeObjectTypeIds.get(name); + const iconUrl = GetRoomEngine().getFurnitureFloorIconUrl(itemId); + + const inventoryItems = getItemsByType(itemId); + + let amountAvailable = 0; + + for (const inventoryItem of inventoryItems) amountAvailable += inventoryItem.items.length; + + newValue.push({ + name: name, + iconUrl, + count: amountAvailable + }); + } + + return newValue; + }); + }, [ groupItems, ingredientNames, getItemsByType ]); + + useEffect(() => + { + if((objectId === -1)) return; + + const id = activate(); + + return () => deactivate(id); + }, [ objectId, activate, deactivate ]); + + return { objectId, recipes, ingredients, selectedRecipe, requiredIngredients, isCrafting, selectRecipe, craft, onClose }; } export const useFurnitureCraftingWidget = useFurnitureCraftingWidgetState;