Grabbed dndbeyond's source code

```
~/go/bin/sourcemapper -output ddb -jsurl https://media.dndbeyond.com/character-app/static/js/main.90aa78c5.js
```
This commit is contained in:
2025-05-28 11:50:03 -07:00
commit 8df9031d27
3592 changed files with 319051 additions and 0 deletions
@@ -0,0 +1,36 @@
export function getName(container) {
return container.name;
}
export function getMappingId(container) {
return container.mappingId;
}
export function getDefinitionKey(container) {
return container.definitionKey;
}
export function getItemMappingIds(container) {
return container.itemMappingIds;
}
export function getInfusedItemMappingIds(container) {
return container.infusedItemMappingIds;
}
export function hasInfusions(container) {
return container.hasInfusions;
}
export function getContainerType(container) {
return container.containerType;
}
export function isShared(container) {
return container.isShared;
}
export function getWeightInfo(container) {
return container.weightInfo;
}
export function isEquipped(container) {
return container.isEquipped;
}
export function getCoin(container) {
return container.coin;
}
export function getItem(container) {
return container.item;
}
@@ -0,0 +1,7 @@
export var ContainerTypeEnum;
(function (ContainerTypeEnum) {
ContainerTypeEnum[ContainerTypeEnum["CHARACTER"] = 1581111423] = "CHARACTER";
ContainerTypeEnum[ContainerTypeEnum["ITEM"] = 1439493548] = "ITEM";
ContainerTypeEnum[ContainerTypeEnum["CAMPAIGN"] = 618115330] = "CAMPAIGN";
ContainerTypeEnum[ContainerTypeEnum["SHOPPE"] = -1] = "SHOPPE";
})(ContainerTypeEnum || (ContainerTypeEnum = {}));
@@ -0,0 +1,171 @@
import { keyBy, sortBy } from 'lodash';
import { ConfigUtils } from '../../config';
import { CampaignAccessors, CampaignUtils } from '../Campaign';
import { generateCoinWeight } from '../Character/generators';
import { DefinitionHacks } from '../Definition';
import { FeatureFlagEnum, FeatureFlagInfoUtils } from '../FeatureFlagInfo';
import { ItemAccessors, ItemDerivers, ItemValidators } from '../Item';
import { getDefinitionKey, getName, isShared } from './accessors';
import { ContainerTypeEnum } from './constants';
function generateInitialCoins() {
return {
cp: 0,
sp: 0,
ep: 0,
gp: 0,
pp: 0,
};
}
/**
*
* @param items
* @param customItems
* @param characterId
* @param partyInfo
* @param partyInventory
* @param featureFlagInfo
* @param characterCoin
* @param preferences
* @param ruleData
*/
export function generateContainers(items, customItems, characterId, partyInfo, partyInventory, featureFlagInfo, characterCoin, preferences, ruleData) {
let sharingStateActive = false;
if (partyInfo && CampaignUtils.isSharingStateActive(CampaignAccessors.getSharingState(partyInfo))) {
sharingStateActive = true;
}
const partyInventoryActive = FeatureFlagInfoUtils.getFeatureFlagInfoValue(FeatureFlagEnum.RELEASE_GATE_IMS, featureFlagInfo) &&
sharingStateActive;
const rulesEngineConfig = ConfigUtils.getCurrentRulesEngineConfig();
// Do we want to display Cointainers? You betcha!
const canCointainer = (preferences === null || preferences === void 0 ? void 0 : preferences.enableContainerCurrency) && (rulesEngineConfig === null || rulesEngineConfig === void 0 ? void 0 : rulesEngineConfig.canUseCurrencyContainers);
//if includeCustomItems on the config is true - customItems are added on the Inventory as Items
//if includeCustomItems on the config is false/undefined (mobile until v5.1 support) - use the customItem contracts on the character JSON
const { includeCustomItems } = ConfigUtils.getCurrentRulesEngineConfig();
const includeCustomItemContractsInEquipment = !includeCustomItems;
const equipmentContainer = generateContainer(characterId, ContainerTypeEnum.CHARACTER, 'Equipment',
//TODO v5.1: All customItems mappings belong to character container for mobile until they can support customItems in containers
includeCustomItemContractsInEquipment ? [...customItems, ...items] : items, false, null, characterCoin, characterId, preferences, ruleData);
const itemContainers = items
.filter(ItemAccessors.isContainer)
.map((containerItem) => {
var _a;
return generateContainer(ItemAccessors.getMappingId(containerItem), ContainerTypeEnum.ITEM, ItemAccessors.getName(containerItem), items, false, containerItem, canCointainer ? (_a = ItemAccessors.getCurrency(containerItem)) !== null && _a !== void 0 ? _a : generateInitialCoins() : null, characterId, preferences, ruleData);
});
const campaignId = partyInfo ? CampaignAccessors.getId(partyInfo) : null;
let partyEquipmentContainer = null;
let partyContainers = [];
if (partyInventoryActive && campaignId) {
partyEquipmentContainer = generateContainer(campaignId, ContainerTypeEnum.CAMPAIGN, 'Party Equipment', partyInventory, true, null, partyInfo ? CampaignAccessors.getCoin(partyInfo) : null, characterId, preferences, ruleData);
partyContainers = partyInventory
.filter(ItemAccessors.isContainer)
.map((containerItem) => {
var _a;
return generateContainer(ItemAccessors.getMappingId(containerItem), ContainerTypeEnum.ITEM, ItemAccessors.getName(containerItem), partyInventory, true, containerItem, canCointainer ? (_a = ItemAccessors.getCurrency(containerItem)) !== null && _a !== void 0 ? _a : generateInitialCoins() : null, characterId, preferences, ruleData);
});
}
const playerContainers = sortBy(itemContainers, (container) => getName(container));
return partyInventoryActive && partyEquipmentContainer
? [equipmentContainer, ...playerContainers, partyEquipmentContainer, ...partyContainers]
: [equipmentContainer, ...playerContainers];
}
/**
*
* @param mappingId
* @param containerType
* @param name
* @param availableInventory
* @param isShared
* @param item
* @param coin
* @param characterId
* @param preferences
* @param ruleData
*/
export function generateContainer(mappingId, containerType, name, availableInventory, isShared, item, coin, characterId, preferences, ruleData) {
let definitionKey = DefinitionHacks.hack__generateDefinitionKey(containerType, mappingId);
const contents = availableInventory.filter((item) => ItemAccessors.getContainerDefinitionKey(item) === definitionKey && !ItemAccessors.isContainer(item));
const infusedItems = contents.filter(ItemAccessors.getInfusion);
return {
containerType,
coin,
definitionKey,
mappingId,
name,
hasInfusions: !!infusedItems.length,
item,
infusedItemMappingIds: infusedItems.map(ItemAccessors.getMappingId),
itemMappingIds: contents.map(ItemAccessors.getMappingId),
isEquipped: item ? ItemAccessors.isEquipped(item) : null,
isShared,
weightInfo: generateContainerWeightInfo(containerType, contents, item, characterId, coin, preferences, ruleData),
};
}
export function generateContainerWeightInfo(type, containerInventory, item, characterId, coin, preferences, ruleData) {
// Item total is the weight of all of the items in the container
const itemTotal = ItemDerivers.deriveItemsWeightTotal(containerInventory);
const coinTotal = generateCoinWeight(coin, preferences, ruleData);
const total = itemTotal + coinTotal;
// Default case is the character equipment container. All of its weight is applied.
let capacity = 0;
let itemApplied = itemTotal;
let coinApplied = coinTotal;
let applied = total;
if (type === ContainerTypeEnum.ITEM && item) {
// Case: It's a container, either in the character or party inventory.
// The weight of the container itself (5lbs for a backpack, for example)
// should be added in.
// Some containers, such as bags of holding, have a weight multiplier to nullify
// the weight of the contents.
// The weight multiplier also affects coins.
capacity = ItemAccessors.getCapacityWeight(item);
const itemWeight = ItemAccessors.getWeight(item);
const weightMultiplier = ItemAccessors.getWeightMultiplier(item);
itemApplied = itemWeight + itemTotal * weightMultiplier;
coinApplied = coinTotal * weightMultiplier;
applied = itemApplied + coinApplied;
}
else if (type === ContainerTypeEnum.CAMPAIGN) {
// Special case: This is the top level party inventory.
// Go through the items. Only items equipped to the current character
// are added to the applied weight.
itemApplied = containerInventory.reduce((acc, containerItem) => {
const itemEquippedToCharacter = ItemValidators.isEquippedToCurrentCharacter(containerItem, characterId);
if (itemEquippedToCharacter) {
return acc + ItemAccessors.getWeight(containerItem);
}
return acc;
}, 0);
coinApplied = 0; // never apply coin weight from the top level party inventory
applied = itemApplied;
}
return {
applied,
capacity,
total,
itemTotal,
coinTotal,
itemApplied,
coinApplied,
};
}
/**
*
* @param containers
*/
export function generateCharacterContainers(containers) {
return containers.filter((container) => !isShared(container));
}
/**
*
* @param containers
*/
export function generatePartyContainers(containers) {
return containers.filter(isShared);
}
/**
*
* @param containers
*/
export function generateContainerLookup(containers) {
return keyBy(containers, (container) => getDefinitionKey(container));
}
@@ -0,0 +1,10 @@
import * as ContainerAccessors from './accessors';
import * as ContainerConstants from './constants';
import * as ContainerGenerators from './generators';
import * as ContainerTypings from './typings';
import * as ContainerUtils from './utils';
import * as ContainerValidators from './validators';
export * from './typings';
export * from './constants';
export { ContainerAccessors, ContainerGenerators, ContainerValidators, ContainerUtils };
export default Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, ContainerAccessors), ContainerConstants), ContainerGenerators), ContainerTypings), ContainerValidators), ContainerUtils);
@@ -0,0 +1,84 @@
import { ContainerAccessors } from '.';
import { PartyInventorySharingStateEnum } from '../Campaign';
import { ItemAccessors } from '../Item';
import { getDefinitionKey, getItemMappingIds, getName } from './accessors';
import { ContainerTypeEnum } from './constants';
/**
*
* @param containers
* @param excludedDefinitionKeys
* @returns {Array<Container>}
*/
export function getAvailableContainers(containers, excludedDefinitionKeys) {
return containers.filter((container) => !excludedDefinitionKeys.includes(getDefinitionKey(container)));
}
/**
* @param characterId
* @returns {string}
*/
export function getCharacterContainerDefinitionKey(characterId) {
return `${ContainerTypeEnum.CHARACTER}:${characterId}`;
}
/**
* @param campaignId
* @returns {string}
*/
export function getPartyContainerDefinitionKey(campaignId) {
return `${ContainerTypeEnum.CAMPAIGN}:${campaignId}`;
}
/**
*
* @param containers
* @param itemContainerDefinitionKey
* @returns {Container | null}
*/
export function getItemParentContainer(containers, itemContainerDefinitionKey) {
var _a;
return (_a = containers.find((container) => getDefinitionKey(container) === itemContainerDefinitionKey)) !== null && _a !== void 0 ? _a : null;
}
/**
*
* @param container
* @param inventory
* @returns {Array<Item>}
*/
export function getInventoryItems(container, inventory) {
return inventory.filter((item) => getItemMappingIds(container).includes(ItemAccessors.getMappingId(item)));
}
/**
*
* @param currentContainerDefinitionKey
* @param containers
* @returns {Array<MenuOption>}
*/
export function getGroupedOptions(currentContainerDefinitionKey, containers, label, sharingState) {
const excludedKeys = [];
if (currentContainerDefinitionKey) {
excludedKeys.push(currentContainerDefinitionKey);
}
const availableContainers = getAvailableContainers(containers, excludedKeys);
const characterContainers = availableContainers.filter((container) => !ContainerAccessors.isShared(container));
const partyContainers = availableContainers.filter(ContainerAccessors.isShared);
const options = [];
if (characterContainers.length) {
options.push({
label,
options: characterContainers.map((container) => ({
value: getDefinitionKey(container),
label: getName(container),
})),
});
}
// Only display Party inventory if there are containers and the sharing state is turned to on
// ( e.g. hide these containers as options when OFF and in DELETE_ONLY )
if (partyContainers.length && sharingState === PartyInventorySharingStateEnum.ON) {
options.push({
label: `${!characterContainers.length ? `${label} ` : ''}Party Inventory`,
options: partyContainers.map((container) => ({
value: getDefinitionKey(container),
label: getName(container),
})),
});
}
return options;
}
@@ -0,0 +1,40 @@
import { DefinitionHacks } from '../Definition';
import { HelperUtils } from '../Helper';
import { getDefinitionKey, getWeightInfo, isShared } from './accessors';
import { ContainerTypeEnum } from './constants';
/**
*
* @param container
* @returns
*/
export function isCharacterContainer(container) {
return DefinitionHacks.hack__getDefinitionKeyType(getDefinitionKey(container)) === ContainerTypeEnum.CHARACTER;
}
/**
*
* @param container
* @returns {boolean}
*/
export function isPartyContainer(container) {
return isPartyContainerDefinitionKey(getDefinitionKey(container));
}
/**
*
* @param containerDefinitionKey
* @returns {boolean}
*/
export function isPartyContainerDefinitionKey(containerDefinitionKey) {
return DefinitionHacks.hack__getDefinitionKeyType(containerDefinitionKey) === ContainerTypeEnum.CAMPAIGN;
}
export function validateIsShared(containerDefinitionKey, containerLookup) {
const container = HelperUtils.lookupDataOrFallback(containerLookup, containerDefinitionKey);
return container ? isShared(container) : false;
}
/**
*
* @param container
*/
export function isOverCapacity(container) {
const weightInfo = getWeightInfo(container);
return weightInfo.total > weightInfo.capacity;
}