From d8191131b4f34cf8bd8945d5c89d1d12530426f3 Mon Sep 17 00:00:00 2001 From: ECWireless Date: Tue, 27 Aug 2024 08:47:01 -0600 Subject: [PATCH 1/2] Add MonstersContext for monster templates --- .../src/components/BattleOutcomeModal.tsx | 128 ++++------------- packages/client/src/contexts/ItemsContext.tsx | 5 +- packages/client/src/contexts/MapContext.tsx | 90 +++++------- .../client/src/contexts/MonstersContext.tsx | 130 ++++++++++++++++++ packages/client/src/index.tsx | 9 +- packages/client/src/utils/helpers.ts | 42 +++++- packages/client/src/utils/types.ts | 18 ++- 7 files changed, 253 insertions(+), 169 deletions(-) create mode 100644 packages/client/src/contexts/MonstersContext.tsx diff --git a/packages/client/src/components/BattleOutcomeModal.tsx b/packages/client/src/components/BattleOutcomeModal.tsx index f93068f72..11870c8dd 100644 --- a/packages/client/src/components/BattleOutcomeModal.tsx +++ b/packages/client/src/components/BattleOutcomeModal.tsx @@ -14,26 +14,20 @@ import { VStack, } from '@chakra-ui/react'; import { useComponentValue } from '@latticexyz/react'; -import { getComponentValueStrict } from '@latticexyz/recs'; -import { encodeEntity, singletonEntity } from '@latticexyz/store-sync/recs'; +import { encodeEntity } from '@latticexyz/store-sync/recs'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { Link } from 'react-router-dom'; +import { zeroAddress, zeroHash } from 'viem'; import { useBattle } from '../contexts/BattleContext'; import { useCharacter } from '../contexts/CharacterContext'; +import { useItems } from '../contexts/ItemsContext'; import { useMUD } from '../contexts/MUDContext'; import { useToast } from '../hooks/useToast'; import { BATTLE_OUTCOME_SEEN_KEY } from '../utils/constants'; -import { - decodeArmorStats, - decodeWeaponStats, - fetchMetadataFromUri, - uriToHttp, -} from '../utils/helpers'; import { type Armor, type CombatOutcomeType, - ItemType, type Weapon, } from '../utils/types'; import { ItemCard } from './ItemCard'; @@ -51,8 +45,9 @@ export const BattleOutcomeModal: React.FC = ({ }): JSX.Element => { const { renderError } = useToast(); const { - components: { Items, ItemsBaseURI, ItemsTokenURI, Levels }, + components: { Levels }, } = useMUD(); + const { armorTemplates, weaponTemplates } = useItems(); const { character } = useCharacter(); const { onContinueToBattleOutcome, opponent } = useBattle(); @@ -81,107 +76,32 @@ export const BattleOutcomeModal: React.FC = ({ }, [character, nextLevelXpRequirement]); const fetchLootedItems = useCallback( - async (_lootedItems: string[]) => { + (_lootedItemIds: string[]) => { try { - const _items = _lootedItems - .map(tokenId => { - const tokenIdEntity = encodeEntity( - { tokenId: 'uint256' }, - { tokenId: BigInt(tokenId) }, - ); - - const itemTemplate = getComponentValueStrict(Items, tokenIdEntity); - + const _armor = armorTemplates + .filter(a => _lootedItemIds.includes(a.tokenId)) + .map(armor => { return { + ...armor, balance: '1', - itemId: tokenIdEntity, - itemType: itemTemplate.itemType, - owner: '', - stats: itemTemplate.stats, - tokenId: tokenId.toString(), - tokenIdEntity, - }; - }) - .sort((a, b) => { - return Number(a.tokenId) - Number(b.tokenId); - }); - - const _armor = _items.filter(item => item.itemType === ItemType.Armor); - const _weapons = _items.filter( - item => item.itemType === ItemType.Weapon, - ); - - const fullArmor = await Promise.all( - _armor.map(async item => { - const decodedArmorStats = decodeArmorStats(item.stats); - - const baseURI = getComponentValueStrict( - ItemsBaseURI, - singletonEntity, - ).uri; - - const tokenURI = getComponentValueStrict( - ItemsTokenURI, - item.tokenIdEntity, - ).uri; - - const metadata = await fetchMetadataFromUri( - uriToHttp(`${baseURI}${tokenURI}`)[0], - ); - - return { - ...metadata, - agiModifier: decodedArmorStats.agiModifier, - armorModifier: decodedArmorStats.armorModifier, - classRestrictions: decodedArmorStats.classRestrictions, - hitPointModifier: decodedArmorStats.hitPointModifier, - intModifier: decodedArmorStats.intModifier, - itemId: item.itemId, - owner: item.owner, - strModifier: decodedArmorStats.strModifier, - tokenId: item.tokenId, + itemId: zeroHash, + owner: zeroAddress, } as Armor; - }), - ); - - const fullWeapons = await Promise.all( - _weapons.map(async item => { - const decodedWeaponStats = decodeWeaponStats(item.stats); - - const baseURI = getComponentValueStrict( - ItemsBaseURI, - singletonEntity, - ).uri; - - const tokenURI = getComponentValueStrict( - ItemsTokenURI, - item.tokenIdEntity, - ).uri; - - const metadata = await fetchMetadataFromUri( - uriToHttp(`${baseURI}${tokenURI}`)[0], - ); + }); + const _weapons = weaponTemplates + .filter(w => _lootedItemIds.includes(w.tokenId)) + .map(weapon => { return { - ...metadata, - agiModifier: decodedWeaponStats.agiModifier, - balance: item.balance, - classRestrictions: decodedWeaponStats.classRestrictions, - hitPointModifier: decodedWeaponStats.hitPointModifier, - intModifier: decodedWeaponStats.intModifier, - itemId: item.itemId, - maxDamage: decodedWeaponStats.maxDamage, - minDamage: decodedWeaponStats.minDamage, - minLevel: decodedWeaponStats.minLevel, - owner: item.owner, - strModifier: decodedWeaponStats.strModifier, - tokenId: item.tokenId, + ...weapon, + balance: '1', + itemId: zeroHash, + owner: zeroAddress, } as Weapon; - }), - ); + }); - setArmor(fullArmor); - setWeapons(fullWeapons); + setArmor(_armor); + setWeapons(_weapons); } catch (e) { renderError( (e as Error)?.message ?? 'Failed to fetch looted items.', @@ -191,7 +111,7 @@ export const BattleOutcomeModal: React.FC = ({ setIsLoadingItems(false); } }, - [Items, ItemsBaseURI, ItemsTokenURI, renderError], + [armorTemplates, renderError, weaponTemplates], ); useEffect(() => { diff --git a/packages/client/src/contexts/ItemsContext.tsx b/packages/client/src/contexts/ItemsContext.tsx index 67ad9649b..85162a87e 100644 --- a/packages/client/src/contexts/ItemsContext.tsx +++ b/packages/client/src/contexts/ItemsContext.tsx @@ -204,7 +204,10 @@ export const ItemsProvider = ({ setWeaponTemplates(_weapons); } } catch (e) { - renderError((e as Error)?.message ?? 'Failed to fetch items.', e); + renderError( + (e as Error)?.message ?? 'Failed to fetch item templates.', + e, + ); } finally { setIsLoading(false); } diff --git a/packages/client/src/contexts/MapContext.tsx b/packages/client/src/contexts/MapContext.tsx index 1083d5aa4..445965fc5 100644 --- a/packages/client/src/contexts/MapContext.tsx +++ b/packages/client/src/contexts/MapContext.tsx @@ -26,6 +26,7 @@ import { } from '../utils/helpers'; import { type Character, type Monster } from '../utils/types'; import { useCharacter } from './CharacterContext'; +import { useMonsters } from './MonstersContext'; import { useMUD } from './MUDContext'; type MapContextType = { @@ -66,7 +67,6 @@ export const MapProvider = ({ children }: MapProviderProps): JSX.Element => { CharactersTokenURI, EncounterEntity, GoldBalances, - Mobs, Position, Spawned, Stats, @@ -76,6 +76,7 @@ export const MapProvider = ({ children }: MapProviderProps): JSX.Element => { network: { publicClient, worldContract }, systemCalls: { spawn }, } = useMUD(); + const { monsterTemplates } = useMonsters(); const { character, refreshCharacter } = useCharacter(); const [isSpawning, setIsSpawning] = useState(false); @@ -224,59 +225,36 @@ export const MapProvider = ({ children }: MapProviderProps): JSX.Element => { ); const getMonsters = useCallback( - async ( - entities: Entity[], - ): Promise< - (Monster & { isSpawned: boolean; position: { x: number; y: number } })[] - > => { + (entities: Entity[]): Monster[] => { try { - const _monsters: (Monster & { - isSpawned: boolean; - position: { x: number; y: number }; - })[] = await Promise.all( - entities.map(async entity => { - const { mobId } = decodeMonsterId(entity as `0x${string}`); - const mobData = getComponentValueStrict( - Mobs, - encodeEntity({ mobId: 'uint256' }, { mobId: BigInt(mobId) }), - ); - const monsterStats = getComponentValueStrict(Stats, entity); - const encounterId = getComponentValue( - EncounterEntity, - entity, - )?.encounterId; - const inBattle = !!encounterId && encounterId !== zeroHash; - - const { mobMetadata: metadataURI } = mobData; - - const fetachedMetadata = await fetchMetadataFromUri( - uriToHttp(metadataURI)[0], - ); - - const isSpawned = getComponentValueStrict(Spawned, entity).spawned; - const _position = getComponentValueStrict(Position, entity); - - return { - agility: monsterStats.agility.toString(), - baseHp: monsterStats.baseHp.toString(), - currentHp: monsterStats.currentHp.toString(), - entityClass: monsterStats.class, - experience: monsterStats.experience.toString(), - id: entity, - inBattle, - intelligence: monsterStats.intelligence.toString(), - isSpawned, - level: monsterStats.level.toString(), - mobId, - position: { x: _position.x, y: _position.y }, - strength: monsterStats.strength.toString(), - ...fetachedMetadata, - } as Monster & { - isSpawned: boolean; - position: { x: number; y: number }; - }; - }), - ); + const _monsters: Monster[] = entities.map(entity => { + const { mobId } = decodeMonsterId(entity as `0x${string}`); + const encounterId = getComponentValue( + EncounterEntity, + entity, + )?.encounterId; + + const currentHp = getComponentValueStrict( + Stats, + entity, + ).currentHp.toString(); + const inBattle = !!encounterId && encounterId !== zeroHash; + const isSpawned = getComponentValueStrict(Spawned, entity).spawned; + const _position = getComponentValueStrict(Position, entity); + + const monsterTemplate = monsterTemplates.find( + m => m.mobId === mobId.toString(), + ); + + return { + ...monsterTemplate, + currentHp, + id: entity, + inBattle, + isSpawned, + position: { x: _position.x, y: _position.y }, + } as Monster; + }); return _monsters; } catch (e) { @@ -284,17 +262,17 @@ export const MapProvider = ({ children }: MapProviderProps): JSX.Element => { return []; } }, - [EncounterEntity, Mobs, Position, renderError, Spawned, Stats], + [EncounterEntity, monsterTemplates, Position, renderError, Spawned, Stats], ); useEffect(() => { - (async (): Promise => { + (async () => { if (!(allCharacterEntities && allMonsterEntities && isSynced)) return; const _allCharacters = await getAllCharacters(allCharacterEntities); setAllCharacters(_allCharacters as Character[]); - const _monsters = await getMonsters(allMonsterEntities); + const _monsters = getMonsters(allMonsterEntities); setAllMonsters(_monsters); })(); }, [ diff --git a/packages/client/src/contexts/MonstersContext.tsx b/packages/client/src/contexts/MonstersContext.tsx new file mode 100644 index 000000000..50d092e0a --- /dev/null +++ b/packages/client/src/contexts/MonstersContext.tsx @@ -0,0 +1,130 @@ +import { + getComponentValueStrict, + Has, + HasValue, + runQuery, +} from '@latticexyz/recs'; +import { decodeEntity, encodeEntity } from '@latticexyz/store-sync/recs'; +import { + createContext, + ReactNode, + useCallback, + useContext, + useEffect, + useState, +} from 'react'; + +import { useToast } from '../hooks/useToast'; +import { + decodeMonsterStats, + fetchMetadataFromUri, + uriToHttp, +} from '../utils/helpers'; +import { MobType, type MonsterTemplate } from '../utils/types'; +import { useMUD } from './MUDContext'; + +type MonstersContextType = { + monsterTemplates: MonsterTemplate[]; + isLoading: boolean; +}; + +const MonstersContext = createContext({ + monsterTemplates: [], + isLoading: false, +}); + +export const MonstersProvider = ({ + children, +}: { + children: ReactNode; +}): JSX.Element => { + const { renderError } = useToast(); + const { + components: { Mobs }, + isSynced, + } = useMUD(); + + const [monsterTemplates, setMonsterTemplates] = useState( + [], + ); + const [isLoading, setIsLoading] = useState(true); + + const fetchMonsterTemplates = useCallback( + async (allMonsterMobIds: bigint[]): Promise => { + const _monsterTemplates: MonsterTemplate[] = await Promise.all( + allMonsterMobIds.map(async mobId => { + const mobData = getComponentValueStrict( + Mobs, + encodeEntity({ mobId: 'uint256' }, { mobId: BigInt(mobId) }), + ); + + const { mobMetadata: metadataURI, mobStats } = mobData; + + const monsterStats = decodeMonsterStats(mobStats); + + const fetachedMetadata = await fetchMetadataFromUri( + uriToHttp(metadataURI)[0], + ); + + return { + agility: monsterStats.agility.toString(), + baseHp: monsterStats.baseHp.toString(), + currentHp: monsterStats.currentHp.toString(), + entityClass: monsterStats.entityClass, + experience: monsterStats.experience.toString(), + intelligence: monsterStats.intelligence.toString(), + level: monsterStats.level.toString(), + mobId: mobId.toString(), + strength: monsterStats.strength.toString(), + ...fetachedMetadata, + } as MonsterTemplate; + }), + ); + + return _monsterTemplates; + }, + [Mobs], + ); + + useEffect(() => { + (async () => { + if (!isSynced) return; + + try { + const allMonsterMobIds = Array.from( + runQuery([Has(Mobs), HasValue(Mobs, { mobType: MobType.Monster })]), + ).map(entity => { + const { mobId } = decodeEntity({ mobId: 'uint256' }, entity); + return mobId; + }); + + if (allMonsterMobIds.length > 0) { + const _monsterTemplates = + await fetchMonsterTemplates(allMonsterMobIds); + setMonsterTemplates(_monsterTemplates); + } + } catch (e) { + renderError( + (e as Error)?.message ?? 'Failed to fetch monster templates.', + e, + ); + } finally { + setIsLoading(false); + } + })(); + }, [fetchMonsterTemplates, isSynced, Mobs, renderError]); + + return ( + + {children} + + ); +}; + +export const useMonsters = (): MonstersContextType => + useContext(MonstersContext); diff --git a/packages/client/src/index.tsx b/packages/client/src/index.tsx index c72e546ce..f673a69e2 100644 --- a/packages/client/src/index.tsx +++ b/packages/client/src/index.tsx @@ -15,6 +15,7 @@ import { App } from './App'; import { DevTools } from './components/DevTools'; import { CharacterProvider } from './contexts/CharacterContext'; import { ItemsProvider } from './contexts/ItemsContext'; +import { MonstersProvider } from './contexts/MonstersContext'; import { MUDProvider } from './contexts/MUDContext'; import { Web3Provider } from './contexts/Web3Provider'; import { setup } from './lib/mud/setup'; @@ -32,9 +33,11 @@ setup().then(async result => { - - - + + + + + {import.meta.env.DEV && } diff --git a/packages/client/src/utils/helpers.ts b/packages/client/src/utils/helpers.ts index 3edb3854b..8ee9364e1 100644 --- a/packages/client/src/utils/helpers.ts +++ b/packages/client/src/utils/helpers.ts @@ -1,6 +1,11 @@ import { decodeAbiParameters, hexToBigInt } from 'viem'; -import { type ArmorStats, type Metadata, WeaponStats } from '../utils/types'; +import { + type ArmorStats, + type EntityStats, + type Metadata, + type WeaponStats, +} from '../utils/types'; export const decodeArmorStats = (statsBytes: string): ArmorStats => { const itemTemplateStats = decodeAbiParameters( @@ -81,6 +86,41 @@ export const decodeMonsterId = ( return { mobId: mobIdBigInt.toString() }; }; +export const decodeMonsterStats = (statsBytes: string): EntityStats => { + const monsterTemplateStats = decodeAbiParameters( + [ + { + name: 'monsterStats', + type: 'tuple', + components: [ + { name: 'actions', type: 'bytes32[]' }, + { name: 'agility', type: 'uint256' }, + { name: 'armor', type: 'uint256' }, + { name: 'class', type: 'uint8' }, + { name: 'experience', type: 'uint256' }, + { name: 'hitPoints', type: 'uint256' }, + { name: 'intelligence', type: 'uint256' }, + { name: 'inventory', type: 'uint256[]' }, + { name: 'level', type: 'uint256' }, + { name: 'strength', type: 'uint256' }, + ], + }, + ], + statsBytes as `0x${string}`, + )[0]; + + return { + agility: monsterTemplateStats.agility.toString(), + baseHp: monsterTemplateStats.hitPoints.toString(), + currentHp: monsterTemplateStats.hitPoints.toString(), + entityClass: monsterTemplateStats.class, + experience: monsterTemplateStats.experience.toString(), + intelligence: monsterTemplateStats.intelligence.toString(), + level: monsterTemplateStats.level.toString(), + strength: monsterTemplateStats.strength.toString(), + }; +}; + export const decodeWeaponStats = (statsBytes: string): WeaponStats => { const itemTemplateStats = decodeAbiParameters( [ diff --git a/packages/client/src/utils/types.ts b/packages/client/src/utils/types.ts index f8fae2e63..7ce464035 100644 --- a/packages/client/src/utils/types.ts +++ b/packages/client/src/utils/types.ts @@ -21,6 +21,11 @@ export enum ItemType { QuestItem, } +export enum MobType { + Monster, + NPC, +} + export enum StatsClasses { Warrior, Rogue, @@ -115,10 +120,15 @@ export type Metadata = { name: string; }; -export type Monster = Metadata & - EntityStats & { - id: Entity; - inBattle: boolean; +export type Monster = MonsterTemplate & { + id: Entity; + inBattle: boolean; + isSpawned: boolean; + position: { x: number; y: number }; +}; + +export type MonsterTemplate = EntityStats & + Metadata & { mobId: string; }; From d4254b894c492b1ae9c6e4bf821a0234c57cb06a Mon Sep 17 00:00:00 2001 From: ECWireless Date: Tue, 27 Aug 2024 09:01:09 -0600 Subject: [PATCH 2/2] Add an armor and template type --- packages/client/src/contexts/ItemsContext.tsx | 41 +++++-------------- .../client/src/pages/CharacterCreation.tsx | 30 ++++++++++---- packages/client/src/utils/types.ts | 28 ++++++------- 3 files changed, 48 insertions(+), 51 deletions(-) diff --git a/packages/client/src/contexts/ItemsContext.tsx b/packages/client/src/contexts/ItemsContext.tsx index 85162a87e..a55afcc3c 100644 --- a/packages/client/src/contexts/ItemsContext.tsx +++ b/packages/client/src/contexts/ItemsContext.tsx @@ -12,7 +12,6 @@ import { useEffect, useState, } from 'react'; -import { zeroAddress } from 'viem'; import { useToast } from '../hooks/useToast'; import { @@ -21,12 +20,16 @@ import { fetchMetadataFromUri, uriToHttp, } from '../utils/helpers'; -import { type Armor, ItemType, type Weapon } from '../utils/types'; +import { + type ArmorTemplate, + ItemType, + type WeaponTemplate, +} from '../utils/types'; import { useMUD } from './MUDContext'; type ItemsContextType = { - armorTemplates: Armor[]; - weaponTemplates: Weapon[]; + armorTemplates: ArmorTemplate[]; + weaponTemplates: WeaponTemplate[]; isLoading: boolean; }; @@ -47,22 +50,14 @@ export const ItemsProvider = ({ isSynced, } = useMUD(); - const [armorTemplates, setArmorTemplates] = useState([]); - const [weaponTemplates, setWeaponTemplates] = useState([]); + const [armorTemplates, setArmorTemplates] = useState([]); + const [weaponTemplates, setWeaponTemplates] = useState([]); const [isLoading, setIsLoading] = useState(true); const fetchAllArmor = useCallback( async (allArmorIds: bigint[]) => { const fullArmor = await Promise.all( allArmorIds.map(async armorId => { - const tokenOwnersEntity = encodeEntity( - { owner: 'address', tokenId: 'uint256' }, - { - owner: zeroAddress, - tokenId: armorId, - }, - ); - const tokenIdEntity = encodeEntity( { tokenId: 'uint256' }, { tokenId: armorId }, @@ -89,12 +84,9 @@ export const ItemsProvider = ({ ...metadata, agiModifier: decodedArmorStats.agiModifier, armorModifier: decodedArmorStats.armorModifier, - balance: '0', hitPointModifier: decodedArmorStats.hitPointModifier, intModifier: decodedArmorStats.intModifier, - itemId: tokenOwnersEntity, minLevel: decodedArmorStats.minLevel, - owner: zeroAddress, statRestrictions: { minAgility: decodedArmorStats.statRestrictions.minAgility, minIntelligence: @@ -103,7 +95,7 @@ export const ItemsProvider = ({ }, strModifier: decodedArmorStats.strModifier, tokenId: armorId.toString(), - } as Armor; + } as ArmorTemplate; }), ); @@ -116,14 +108,6 @@ export const ItemsProvider = ({ async (allWeaponIds: bigint[]) => { const fullWeapons = await Promise.all( allWeaponIds.map(async weaponId => { - const tokenOwnersEntity = encodeEntity( - { owner: 'address', tokenId: 'uint256' }, - { - owner: zeroAddress, - tokenId: weaponId, - }, - ); - const tokenIdEntity = encodeEntity( { tokenId: 'uint256' }, { tokenId: weaponId }, @@ -149,14 +133,11 @@ export const ItemsProvider = ({ return { ...metadata, agiModifier: decodedArmorStats.agiModifier, - balance: '0', hitPointModifier: decodedArmorStats.hitPointModifier, intModifier: decodedArmorStats.intModifier, - itemId: tokenOwnersEntity, maxDamage: decodedArmorStats.maxDamage, minDamage: decodedArmorStats.minDamage, minLevel: decodedArmorStats.minLevel, - owner: zeroAddress, statRestrictions: { minAgility: decodedArmorStats.statRestrictions.minAgility, minIntelligence: @@ -165,7 +146,7 @@ export const ItemsProvider = ({ }, strModifier: decodedArmorStats.strModifier, tokenId: weaponId.toString(), - } as Weapon; + } as WeaponTemplate; }), ); diff --git a/packages/client/src/pages/CharacterCreation.tsx b/packages/client/src/pages/CharacterCreation.tsx index 9c5a26a6b..3e5fb93b6 100644 --- a/packages/client/src/pages/CharacterCreation.tsx +++ b/packages/client/src/pages/CharacterCreation.tsx @@ -17,11 +17,17 @@ import { VStack, } from '@chakra-ui/react'; import { useComponentValue } from '@latticexyz/react'; -import { getComponentValueStrict, Has, runQuery } from '@latticexyz/recs'; +import { + Entity, + getComponentValueStrict, + Has, + runQuery, +} from '@latticexyz/recs'; import { singletonEntity } from '@latticexyz/store-sync/recs'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { FaLock } from 'react-icons/fa'; import { useNavigate } from 'react-router-dom'; +import { zeroAddress, zeroHash } from 'viem'; import { useAccount } from 'wagmi'; import { ItemCardSmall } from '../components/ItemCard'; @@ -99,12 +105,22 @@ export const CharacterCreation = (): JSX.Element => { item[1].toString(), ); - const _starterArmor = armorTemplates.filter(armor => - starterArmorTokenIds.includes(armor.tokenId), - ); - const _starterWeapons = weaponTemplates.filter(weapon => - starterWeaponTokenIds.includes(weapon.tokenId), - ); + const _starterArmor = armorTemplates + .filter(armor => starterArmorTokenIds.includes(armor.tokenId)) + .map(armor => ({ + ...armor, + balance: '1', + itemId: zeroHash as Entity, + owner: zeroAddress, + })); + const _starterWeapons = weaponTemplates + .filter(weapon => starterWeaponTokenIds.includes(weapon.tokenId)) + .map(armor => ({ + ...armor, + balance: '1', + itemId: zeroHash as Entity, + owner: zeroAddress, + })); setStarterArmor(_starterArmor); setStarterWeapons(_starterWeapons); diff --git a/packages/client/src/utils/types.ts b/packages/client/src/utils/types.ts index 7ce464035..ea485b860 100644 --- a/packages/client/src/utils/types.ts +++ b/packages/client/src/utils/types.ts @@ -51,13 +51,11 @@ export type ActionOutcomeType = { weaponId: string; }; -export type Armor = ArmorStats & - Metadata & { - balance: string; - itemId: Entity; - owner: string; - tokenId: string; - }; +export type Armor = ArmorTemplate & { + balance: string; + itemId: Entity; + owner: string; +}; export type ArmorStats = { agiModifier: string; @@ -69,6 +67,8 @@ export type ArmorStats = { strModifier: string; }; +export type ArmorTemplate = ArmorStats & Metadata & { tokenId: string }; + export type Character = CharacterData & EntityStats & Metadata; export type CharacterData = { @@ -132,13 +132,11 @@ export type MonsterTemplate = EntityStats & mobId: string; }; -export type Weapon = WeaponStats & - Metadata & { - balance: string; - itemId: Entity; - owner: string; - tokenId: string; - }; +export type Weapon = WeaponTemplate & { + balance: string; + itemId: Entity; + owner: string; +}; export type WeaponStats = { agiModifier: string; @@ -151,6 +149,8 @@ export type WeaponStats = { strModifier: string; }; +export type WeaponTemplate = WeaponStats & Metadata & { tokenId: string }; + export type Item = Metadata & { itemId: Entity; itemType: ItemType;