mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-22 22:30:52 +01:00
Update crafting
This commit is contained in:
parent
5168eed641
commit
2fb75b3e17
6
src/api/room/widgets/ICraftingIngredient.ts
Normal file
6
src/api/room/widgets/ICraftingIngredient.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export interface ICraftingIngredient
|
||||||
|
{
|
||||||
|
name: string;
|
||||||
|
iconUrl: string;
|
||||||
|
count: number;
|
||||||
|
}
|
6
src/api/room/widgets/ICraftingRecipe.ts
Normal file
6
src/api/room/widgets/ICraftingRecipe.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export interface ICraftingRecipe
|
||||||
|
{
|
||||||
|
name: string;
|
||||||
|
localizedName: string;
|
||||||
|
iconUrl: string;
|
||||||
|
}
|
@ -11,6 +11,8 @@ export * from './DimmerFurnitureWidgetPresetItem';
|
|||||||
export * from './DoChatsOverlap';
|
export * from './DoChatsOverlap';
|
||||||
export * from './FurnitureDimmerUtilities';
|
export * from './FurnitureDimmerUtilities';
|
||||||
export * from './IAvatarInfo';
|
export * from './IAvatarInfo';
|
||||||
|
export * from './ICraftingIngredient';
|
||||||
|
export * from './ICraftingRecipe';
|
||||||
export * from './IPhotoData';
|
export * from './IPhotoData';
|
||||||
export * from './MannequinUtilities';
|
export * from './MannequinUtilities';
|
||||||
export * from './PetSupplementEnum';
|
export * from './PetSupplementEnum';
|
||||||
|
@ -1,21 +1,15 @@
|
|||||||
import { CraftingRecipeIngredientParser, RoomObjectCategory } from '@nitrots/nitro-renderer';
|
import { RoomObjectCategory } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useEffect, useMemo, useState } from 'react';
|
import { FC, ReactElement, useEffect, useMemo, useState } from 'react';
|
||||||
import { GetRoomEngine, IsOwnerOfFurniture, LocalizeText } from '../../../../api';
|
import { GetRoomEngine, IsOwnerOfFurniture, LocalizeText } from '../../../../api';
|
||||||
import { AutoGrid, Button, Column, Flex, LayoutGridItem, LayoutLoadingSpinnerView, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../common';
|
import { AutoGrid, Button, Column, Flex, LayoutGridItem, LayoutLoadingSpinnerView, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../common';
|
||||||
import { useFurnitureCraftingWidget, useRoom } from '../../../../hooks';
|
import { useFurnitureCraftingWidget, useRoom } from '../../../../hooks';
|
||||||
|
|
||||||
export const FurnitureCraftingView: FC<{}> = props =>
|
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 { roomSession = null } = useRoom();
|
||||||
|
|
||||||
const [ waitingToConfirm, setWaitingToConfirm ] = useState(false);
|
const [ waitingToConfirm, setWaitingToConfirm ] = useState(false);
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
setWaitingToConfirm(false);
|
|
||||||
}, [ selectedRecipe ]);
|
|
||||||
|
|
||||||
const isOwner = useMemo(() =>
|
const isOwner = useMemo(() =>
|
||||||
{
|
{
|
||||||
const roomObject = GetRoomEngine().getRoomObject(roomSession.roomId, objectId, RoomObjectCategory.FLOOR);
|
const roomObject = GetRoomEngine().getRoomObject(roomSession.roomId, objectId, RoomObjectCategory.FLOOR);
|
||||||
@ -24,21 +18,24 @@ export const FurnitureCraftingView: FC<{}> = props =>
|
|||||||
|
|
||||||
const canCraft = useMemo(() =>
|
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;
|
if (ingredientData.count < ingredient.count) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}, [ ingredients, selectedRecipeIngredients ]);
|
}, [ ingredients, requiredIngredients ]);
|
||||||
|
|
||||||
const tryCraft = () =>
|
const tryCraft = () =>
|
||||||
{
|
{
|
||||||
if (!waitingToConfirm)
|
if (!waitingToConfirm)
|
||||||
{
|
{
|
||||||
setWaitingToConfirm(true);
|
setWaitingToConfirm(true);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,19 +43,10 @@ export const FurnitureCraftingView: FC<{}> = props =>
|
|||||||
setWaitingToConfirm(false);
|
setWaitingToConfirm(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderSelectedRecipeIngredient = (ingredient: CraftingRecipeIngredientParser) =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
const ingredientData = ingredients.find((i) => i.name === ingredient.itemName);
|
setWaitingToConfirm(false);
|
||||||
|
}, [ selectedRecipe ]);
|
||||||
const elements = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < ingredient.count; i++)
|
|
||||||
{
|
|
||||||
elements.push(<LayoutGridItem key={ i } itemImage={ ingredientData.iconUrl } className={ (ingredientData.count - (i) <= 0 ? 'opacity-0-5 ' : '') + 'cursor-default' } />);
|
|
||||||
}
|
|
||||||
|
|
||||||
return elements;
|
|
||||||
};
|
|
||||||
|
|
||||||
if(objectId === -1) return null;
|
if(objectId === -1) return null;
|
||||||
|
|
||||||
@ -87,7 +75,19 @@ export const FurnitureCraftingView: FC<{}> = props =>
|
|||||||
<Column overflow="hidden" fullHeight>
|
<Column overflow="hidden" fullHeight>
|
||||||
<div className="bg-muted rounded py-1 text-center">{ LocalizeText('crafting.current_recipe') }</div>
|
<div className="bg-muted rounded py-1 text-center">{ LocalizeText('crafting.current_recipe') }</div>
|
||||||
<AutoGrid columnCount={ 5 }>
|
<AutoGrid columnCount={ 5 }>
|
||||||
{ (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(<LayoutGridItem key={ i } itemImage={ ingredientData.iconUrl } className={ (ingredientData.count - (i) <= 0 ? 'opacity-0-5 ' : '') + 'cursor-default' } />);
|
||||||
|
}
|
||||||
|
|
||||||
|
return elements;
|
||||||
|
}) }
|
||||||
</AutoGrid>
|
</AutoGrid>
|
||||||
</Column>
|
</Column>
|
||||||
<Flex gap={ 2 } column fullHeight>
|
<Flex gap={ 2 } column fullHeight>
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
import { CraftableProductsEvent, CraftComposer, CraftingRecipeEvent, CraftingRecipeIngredientParser, CraftingRecipesAvailableEvent, CraftingResultEvent, GetCraftableProductsComposer, GetCraftingRecipeComposer, RoomEngineTriggerWidgetEvent, RoomWidgetEnum } from '@nitrots/nitro-renderer';
|
import { CraftableProductsEvent, CraftComposer, CraftingRecipeEvent, CraftingRecipeIngredientParser, CraftingRecipesAvailableEvent, CraftingResultEvent, GetCraftableProductsComposer, GetCraftingRecipeComposer, RoomEngineTriggerWidgetEvent, RoomWidgetEnum } from '@nitrots/nitro-renderer';
|
||||||
import { useCallback, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { GetRoomEngine, LocalizeText, SendMessageComposer } from '../../../../api';
|
import { GetRoomEngine, ICraftingIngredient, ICraftingRecipe, LocalizeText, SendMessageComposer } from '../../../../api';
|
||||||
import { useMessageEvent, useRoomEngineEvent } from '../../../events';
|
import { useMessageEvent, useRoomEngineEvent } from '../../../events';
|
||||||
import { useInventoryFurni } from '../../../inventory';
|
import { useInventoryFurni } from '../../../inventory';
|
||||||
import { useNotification } from './../../../notification/useNotification';
|
import { useNotification } from './../../../notification';
|
||||||
|
|
||||||
const useFurnitureCraftingWidgetState = () =>
|
const useFurnitureCraftingWidgetState = () =>
|
||||||
{
|
{
|
||||||
const { getItemsByType } = useInventoryFurni();
|
|
||||||
const { simpleAlert } = useNotification();
|
|
||||||
|
|
||||||
const [ objectId, setObjectId ] = useState(-1);
|
const [ objectId, setObjectId ] = useState(-1);
|
||||||
const [ recipes, setRecipes ] = useState<{ name: string, localizedName: string, iconUrl: string }[]>([]);
|
const [ recipes, setRecipes ] = useState<ICraftingRecipe[]>([]);
|
||||||
const [ ingredients, setIngredients ] = useState<{ name: string, iconUrl: string, count: number }[]>([]);
|
const [ selectedRecipe, setSelectedRecipe ] = useState<ICraftingRecipe>(null);
|
||||||
const [ selectedRecipe, setSelectedRecipe ] = useState<{ name: string, localizedName: string, iconUrl: string }>(null);
|
const [ ingredients, setIngredients ] = useState<ICraftingIngredient[]>([]);
|
||||||
const [ selectedRecipeIngredients, setSelectedRecipeIngredients ] = useState<CraftingRecipeIngredientParser[]>([]);
|
const [ ingredientNames, setIngredientNames ] = useState<string[]>(null);
|
||||||
const [ cacheRecipeIngredients, setCacheRecipeIngredients ] = useState<Map<string, CraftingRecipeIngredientParser[]>>(new Map());
|
const [ cachedIngredients, setCachedIngredients ] = useState<Map<string, CraftingRecipeIngredientParser[]>>(new Map());
|
||||||
const [ isCrafting, setIsCrafting ] = useState(false);
|
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 = () =>
|
const resetData = () =>
|
||||||
{
|
{
|
||||||
setRecipes([]);
|
setRecipes([]);
|
||||||
setIngredients([]);
|
|
||||||
setSelectedRecipe(null);
|
setSelectedRecipe(null);
|
||||||
setSelectedRecipeIngredients([]);
|
setIngredients([]);
|
||||||
setCacheRecipeIngredients(new Map());
|
setCachedIngredients(new Map());
|
||||||
};
|
};
|
||||||
|
|
||||||
const onClose = () =>
|
const onClose = () =>
|
||||||
@ -36,26 +36,23 @@ const useFurnitureCraftingWidgetState = () =>
|
|||||||
const craft = () =>
|
const craft = () =>
|
||||||
{
|
{
|
||||||
setIsCrafting(true);
|
setIsCrafting(true);
|
||||||
|
|
||||||
SendMessageComposer(new CraftComposer(objectId, selectedRecipe.name));
|
SendMessageComposer(new CraftComposer(objectId, selectedRecipe.name));
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectRecipe = useCallback((recipe: { name: string, localizedName: string, iconUrl: string }) =>
|
const selectRecipe = (recipe: ICraftingRecipe) =>
|
||||||
{
|
{
|
||||||
setSelectedRecipeIngredients([]);
|
|
||||||
setSelectedRecipe(recipe);
|
setSelectedRecipe(recipe);
|
||||||
|
|
||||||
const cache = cacheRecipeIngredients.get(recipe.name);
|
const cache = cachedIngredients.get(recipe.name);
|
||||||
|
|
||||||
if (cache)
|
if(!cache) SendMessageComposer(new GetCraftingRecipeComposer(recipe.name));
|
||||||
setSelectedRecipeIngredients(cache);
|
}
|
||||||
else
|
|
||||||
SendMessageComposer(new GetCraftingRecipeComposer(recipe.name));
|
|
||||||
}, [ cacheRecipeIngredients ]);
|
|
||||||
|
|
||||||
useRoomEngineEvent<RoomEngineTriggerWidgetEvent>(RoomEngineTriggerWidgetEvent.OPEN_WIDGET, event =>
|
useRoomEngineEvent<RoomEngineTriggerWidgetEvent>(RoomEngineTriggerWidgetEvent.OPEN_WIDGET, event =>
|
||||||
{
|
{
|
||||||
if (event.widget !== RoomWidgetEnum.CRAFTING) return;
|
if (event.widget !== RoomWidgetEnum.CRAFTING) return;
|
||||||
console.log(event);
|
|
||||||
setObjectId(event.objectId);
|
setObjectId(event.objectId);
|
||||||
resetData();
|
resetData();
|
||||||
SendMessageComposer(new GetCraftableProductsComposer(event.objectId));
|
SendMessageComposer(new GetCraftableProductsComposer(event.objectId));
|
||||||
@ -68,78 +65,102 @@ const useFurnitureCraftingWidgetState = () =>
|
|||||||
if (!parser.isActive())
|
if (!parser.isActive())
|
||||||
{
|
{
|
||||||
setObjectId(-1);
|
setObjectId(-1);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const recipesToSet = [];
|
setRecipes(prevValue =>
|
||||||
|
|
||||||
for(const recipe of parser.recipes)
|
|
||||||
{
|
{
|
||||||
//@ts-ignore
|
const newValue: ICraftingRecipe[] = [];
|
||||||
const itemId = GetRoomEngine().roomContentLoader._activeObjectTypeIds.get(recipe.itemName);
|
|
||||||
const iconUrl = GetRoomEngine().getFurnitureFloorIconUrl(itemId);
|
|
||||||
recipesToSet.push({
|
|
||||||
name: recipe.itemName,
|
|
||||||
localizedName: LocalizeText('roomItem.name.' + itemId),
|
|
||||||
iconUrl
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
return newValue;
|
||||||
{
|
});
|
||||||
//@ts-ignore
|
|
||||||
const itemId = GetRoomEngine().roomContentLoader._activeObjectTypeIds.get(ingredient);
|
|
||||||
const iconUrl = GetRoomEngine().getFurnitureFloorIconUrl(itemId);
|
|
||||||
|
|
||||||
const inventoryItems = getItemsByType(itemId);
|
setIngredientNames(parser.ingredients);
|
||||||
let amountAvailable = 0;
|
|
||||||
|
|
||||||
for (const inventoryItem of inventoryItems) amountAvailable += inventoryItem.items.length;
|
|
||||||
|
|
||||||
ingredientsToSet.push({
|
|
||||||
name: ingredient,
|
|
||||||
iconUrl,
|
|
||||||
count: amountAvailable
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setIngredients(ingredientsToSet);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
useMessageEvent<CraftingRecipeEvent>(CraftingRecipeEvent, event =>
|
useMessageEvent<CraftingRecipeEvent>(CraftingRecipeEvent, event =>
|
||||||
{
|
{
|
||||||
const parser = event.getParser();
|
const parser = event.getParser();
|
||||||
setSelectedRecipeIngredients(parser.ingredients);
|
|
||||||
|
|
||||||
const newCache = new Map(cacheRecipeIngredients);
|
setCachedIngredients(prevValue =>
|
||||||
newCache.set(selectedRecipe.name, parser.ingredients);
|
{
|
||||||
setCacheRecipeIngredients(newCache);
|
const newValue = new Map(prevValue);
|
||||||
|
|
||||||
|
newValue.set(selectedRecipe.name, parser.ingredients);
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
useMessageEvent<CraftingResultEvent>(CraftingResultEvent, event =>
|
useMessageEvent<CraftingResultEvent>(CraftingResultEvent, event =>
|
||||||
{
|
{
|
||||||
setSelectedRecipe(null);
|
setSelectedRecipe(null);
|
||||||
setSelectedRecipeIngredients([]);
|
setIsCrafting(false);
|
||||||
|
|
||||||
const parser = event.getParser();
|
const parser = event.getParser();
|
||||||
|
|
||||||
if (parser.result)
|
if(parser.result) simpleAlert(LocalizeText('crafting.info.result.ok'));
|
||||||
{
|
|
||||||
simpleAlert(LocalizeText('crafting.info.result.ok'));
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsCrafting(false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
useMessageEvent<CraftingRecipesAvailableEvent>(CraftingRecipesAvailableEvent, event =>
|
useMessageEvent<CraftingRecipesAvailableEvent>(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;
|
export const useFurnitureCraftingWidget = useFurnitureCraftingWidgetState;
|
||||||
|
Loading…
Reference in New Issue
Block a user