Configuring-equipability
Equippable & Composable is the most advanced module, as it requires both MultiAsset and Nestable ones. After you have deployed your NFT contract, you may add new equippable and/or composable assets. Equippable assets can receive children to be equipped or be equipped into a parent, or both.
Pre-requisites for equipment to be valid
For a token to be equippable there are a series of conditions that need to be met. They are tailored to ensure that only assets from collections meant to be equipped are possible:
- The slot must be defined in the catalog and it must be configured so that child collection can use it.
- The parent token must have an asset with slot parts.
- The child token must have an asset that is equippable into the parent's slot. This is done through the
equippableGroupId
.
Equippable Group Id
To better understand the equippableGroupId
paramater let's consider the following example. Let's say you have a collection of Soldiers and a collection of Weapons. You want to allow the Soldiers to equip the Weapons in either hand. You would need to:
- Create a catalog with a slot
WL
for the left hand and a slotWR
for the right hand. You also configure this slot to be usable by the Weapons collection. This can be achieved by using when creating part with eitheraddPart
oraddPartList
, or later throughaddEquippableAddresses
,setEquippableAddresses
orsetEquippableToAll
. See the Catalog section for more details. - The parent token must have an asset which includes
WL
andWR
in itspartIds
array. You do this exclusively with theaddEquippableAssetEntry
function. - Each Weapon NFT will have 2 assets, one for the left hand and one for the right hand. All assets meant for the left hand will have the same
equippableGroupId:EGL
and all assets meant for the right hand will have the sameequippableGroupId:EGR
. You need to set theequippableGroupId
when adding the asset with theaddEquippableAssetEntry
function and you configure eachequippableGroupId
to be equippable into the left and right hand slots of the Soldier collection, respectively. This can be achieved by using thesetValidParentForEquippableGroup
function.
With these conditions met, any NFT from the Weapons collection, nested into any NFT from the Soldiers collection will be equippable into the left or right hand slots.
These are the operations you may need to perform when working with equippable and composable assets:
Writing operations
- Adding a new equippable/composable asset.
- Equipping a child asset.
- Unequipping a child asset.
- Set valid parent for equippable group.
Adding a new equippable/composable asset
In our ready to use implementations, adding a new asset can be performed by the collection owner or a contributor.
For an asset to be equippable into a parent asset you need to use the addEquippableAssetEntry
function instead of addAssetEntry
and assign a non zero equippableGroupId
to it.
For an asset to be composable you need to use the addEquippableAssetEntry
function instead of addAssetEntry
and assign a catalogAddress
and non empty partIds
array to it.
The asset is added to the collection and can be later added into any token. Our implementations take care of assigning a unique Id, starting by 1. For more details on the contents of the metadata see the metadata section.
// For equippable into parent
const equippableGroupId = 1;
const catalogAddress = '0x0000000000000000000000000000000000000000'; // Unless also composable
const metadataURI = 'ipfs://...';
const partIds = []; // Unless also composable
// For composables
const equippableGroupId = 0; // Unless you want it to be equippable into a parent.
const catalogAddress = '0x...';
const metadataURI = 'ipfs://...';
const partIds = [1, 2, 3];
await contract.addEquippableAssetEntry(
equippableGroupId,
catalogAddress,
metadataURI,
partIds
);
Equipping a child asset
Used to equip a child into a token.
const parentId = 1;
const childId = 10;
const parentAssetId = 5;
const childAssetId = 15;
const slotPartId = 1;
// Find childIndex on parent's active children
const childrenIds = (await parentContract.childrenOf(parentId)).map(
(child) => child.tokenId.toNumber()
)
const childIndex = childrenIds.indexOf(childId)
const data = {
tokenId: parentId,
childIndex,
assetId: parentAssetId,
slotPartId,
childAssetId
}
await parentContract.equip(data);
Unequipping a child asset
Used to unequip child from parent token.
const parentId = 1;
const parentAssetId = 5;
const slotPartId = 1;
await parentContract.unequip(parentId, parentAssetId, slotPartId);
Set valid parent for equippable group
Used to declare that the assets belonging to a given equippableGroupId
are equippable into the Slot
with partId
on the collection at the specified parentAddress
. Every child NFT which has an asset belonging to the equippable group will be equippable into the slot of the parent NFT.
const equippableGroupId = 1;
const parentAddress = '0x...';
const partId = 1;
await childContract.setValidParentForEquippableGroup(
equippableGroupId,
parentAddress,
partId
);
Reading operations
- Check if a child is equipped.
- Check if a child is equippable in a slot
- Get asset and equippable data
- Get equipment
Check if a child is equipped
Used to check whether the token has a given child equipped. An equipped child will prevent the child token to be unnested.
const parentId = 1;
const childId = 10;
const childAddress = '0x...';
const isEquipped = await parentContract.isChildEquipped(
parentId,
childAddress,
childId
);
Check if a child is equippable in a slot
Used to verify whether a token can be equipped into a given parent's slot. This is called from child contract.
const parentAddress = '0x...';
const parentId = 1;
const assetId = 10;
const slotId = 1;
const canBeEquipped = await childContract.canTokenBeEquippedWithAssetIntoSlot(
parentAddress,
parentId,
assetId,
slotId
);
Get asset and equippable data
Used to get the asset and equippable data associated with given assetId
. The metadata returned is the same as the one returned by the getAssetMetadata
function.
const tokenId = 1;
const assetId = 10;
const {
metadataURI,
equippableGroupId,
catalogAddress,
partIds
} = await contract.getAssetAndEquippableData(tokenId, assetId);
Get equipment
Used to get the Equipment
data for a token, catalog and slot combination. It returns an empty struct if no equipment is found.
const tokenId = 1;
const targetCatalogAddress = '0x...';
const slotPartId = 1;
const equipment = await parentContract.getEquipment(
tokenId,
targetCatalogAddress,
slotPartId
);
// equipment = [
// assetId,
// childAssetId,
// childId,
// childEquippableAddress
// ]