Repository navigation
api campaign
Audience: module authors consuming Blacksmith's campaign context.
Blacksmith exposes a normalized campaign API for other Coffee Pub modules so they do not need to read raw settings or resolve party actors themselves.
const api = game.modules.get('coffee-pub-blacksmith')?.api;
const campaign = api?.campaign?.getCampaign?.();const api = game.modules.get('coffee-pub-blacksmith')?.api;
console.log('Campaign API:', api?.campaign);
console.log('Full Campaign:', api?.campaign?.getCampaign?.());
console.log('Core:', api?.campaign?.getCore?.());
console.log('Geography:', api?.campaign?.getGeography?.());
console.log('Party:', api?.campaign?.getParty?.());
console.log('Party Leader:', api?.campaign?.getPartyLeader?.());
console.log('Rulebooks:', api?.campaign?.getRulebooks?.());
console.log('Journal Defaults:', api?.campaign?.getJournalDefaults?.());
console.log('Prompt Context:', api?.campaign?.getPromptContext?.());Quick readable dump:
const campaign = game.modules.get('coffee-pub-blacksmith')?.api?.campaign?.getCampaign?.();
console.log(JSON.stringify(campaign, null, 2));Returns the full normalized campaign object:
{
core: {
name: string,
rulesVersion: string,
customRulebooks: string,
rulebooks: {
configuredCount: number,
compendiums: [
{
id: string,
label: string,
package: string,
type: string
}
]
}
},
geography: {
realm: string,
region: string,
site: string,
area: string
},
party: {
name: string,
configuredSize: number,
memberCount: number,
members: [
{
id: string,
uuid: string,
name: string,
img: string,
actorType: string,
level: number | null,
className: string | null,
classes: string[]
}
],
summary: {
averageLevel: number | null,
levels: number[],
classNames: string[]
}
},
journal: {
narrative: {
folder: string,
imagePath: string, // note: no cardImage — see below
characterImagePath: string
},
encounter: {
folder: string,
cardImage: string, // encounter DOES have cardImage
imagePath: string
}
}
}-
name- Source setting:
Campaign Settings > Core > Campaign Name - The campaign name used as shared context for prompts and imports.
- This should be the user-facing campaign title, not a sourcebook or setting name.
- Good examples:
Shadows Over BlackstoneThe Ashen Crown Campaign
- Source setting:
-
rulesVersion- Source setting:
Campaign Settings > Core > Rules Version - The selected rules era for the campaign.
- Current values are:
-
2024for Modern Rules -
2014for Legacy Rules
-
- Consumers should treat this as a rules-behavior hint, not as a complete system identifier.
- This should reflect which D&D 5e rules revision the campaign is actually using, especially when other modules need to know whether 2014 or 2024 assumptions apply.
- Source setting:
-
customRulebooks- Source setting:
Campaign Settings > Core > Custom Rulebooks - Freeform supplemental rules text entered by the GM.
- Intended for books, supplements, houserule packets, or campaign documents not represented by selected compendium packs.
- This is best used for:
- unofficial supplements
- house rules packets
- campaign PDFs
- rulings that are not represented by a compendium selector
- This should be plain descriptive text, not a JSON blob or comma requirements list.
- Source setting:
-
rulebooks.configuredCount- Source setting:
Campaign Settings > Core > Number of Rulebooks - How many rulebook-compendium dropdowns the GM chose to expose in settings.
- This is configuration shape, not guaranteed content.
- Source setting:
-
rulebooks.compendiums- Source setting:
Campaign Settings > Core > Rulebook 1..N - The actual selected rulebook compendiums, resolved into metadata objects.
- These represent the structured rules corpus the campaign is expected to use.
- Consumers should prefer these over parsing
customRulebooks. - These should point at the compendiums that actually represent the campaign's active rules references.
- Typical examples:
Player's HandbookDungeon Master's GuideXanathar's Guide to EverythingTasha's Cauldron of Everything
- Source setting:
-
realm- Source setting:
Campaign Settings > Geography > Realm - Broad world, plane, or major setting scope, such as
FaerunorEberron. - This should describe the highest-level campaign location context.
- Source setting:
-
region- Source setting:
Campaign Settings > Geography > Region - Large political or geographic area within the realm, such as a kingdom, coast, or territory.
- This should narrow the campaign context beneath the realm, but still remain broader than a single city or dungeon.
- Source setting:
-
site- Source setting:
Campaign Settings > Geography > Site - Specific place within the region, such as a city, keep, mine, temple, or dungeon.
- This should identify the main location the campaign or current arc centers on.
- Source setting:
-
area- Source setting:
Campaign Settings > Geography > Area - Localized sub-area within the site, such as a room, chamber, district, street, or encounter zone.
- This should be the most granular campaign-location hint you want prompts or imports to inherit by default.
- Source setting:
These fields are intended as campaign context. They should not be assumed to match the currently active Foundry scene.
-
name- Source setting:
Campaign Settings > Party > Party Name - The configured party name used as campaign context.
- This should be the table-facing party title if one exists.
- Good examples:
The GloamwalkersCompany of the Broken Pike
- Source setting:
-
configuredSize- Source setting:
Campaign Settings > Party > Party Size - The number of party-member dropdowns exposed in settings.
- This is the intended party size, even if some slots are still empty.
- This should reflect how many player-character slots you want Blacksmith to track, not how many NPC companions happen to be present this week.
- Source setting:
-
memberCount- The number of valid actor selections currently configured.
- Consumers should use this for actual resolved membership.
-
members- Source setting:
Campaign Settings > Party > Party Member 1..N - Resolved actor summaries in configured order.
- This is the main data other modules should consume instead of doing their own actor lookup from settings.
- These should generally be the party's player-character actors, or whatever set of actors you want other Coffee Pub modules to treat as the canonical party roster.
- Source setting:
-
members[].id- World actor id.
-
members[].uuid- Full actor UUID for durable linking.
-
members[].name- Actor display name.
-
members[].img- Actor image for lightweight display use.
-
members[].actorType- Foundry/system actor type, such as
character.
- Foundry/system actor type, such as
-
members[].level- Best-effort derived level.
- May be
nullif the system or actor data does not expose a clear level.
-
members[].className- Human-readable joined class label, if derivable.
-
members[].classes- Best-effort class list as individual strings.
-
summary.averageLevel- Average of resolved member levels when available.
- May be
nullif no levels can be derived.
-
summary.levels- Raw numeric levels used to compute the average.
-
summary.classNames- Unique class names present across resolved party members.
-
journal.narrative.folder- Source setting:
Imports > Journal > Narrative > Narrative Folder - Default folder used for narrative journal generation/import.
- This should be the journal folder where generated narratives should land by default.
- Source setting:
-
journal.narrative.imagePath- Source setting:
Imports > Journal > Narrative > Custom Image - The resolved narrative image path.
-
There is no
journal.narrative.cardImage. Earlier versions of this page documented one, along with aNarrative > Card Imagesettings control. Both are gone: the narrative card-image setting was collapsed intoimagePathand is no longer registered. Its only surviving trace is a one-line legacy read insideresolveNarrativeImagePath(), which migrates the old value forward. Reading.cardImageoff narrative returnsundefined— silently, becausegetSettingSafelyreturns a default for unregistered keys rather than throwing. The encounter side genuinely does still havecardImage.
- Source setting:
-
journal.narrative.characterImagePath- Source setting:
Imports > Journal > Narrative > Character Image - Default character image for generated narratives. Exposed as
narrativeCharacterImagePathingetPromptContext().
- Source setting:
-
journal.encounter.folder- Source setting:
Imports > Journal > Encounter > Encounter Folder - Default folder used for encounter journal generation/import.
- This should be the journal folder where generated encounters should land by default.
- Source setting:
-
journal.encounter.cardImage- Source setting:
Imports > Journal > Encounter > Default Encounter Card Image - Selected built-in encounter card image path or
customornone. - This should be one of:
- a built-in image selection
customnone
- Source setting:
-
journal.encounter.imagePath- Source setting:
Imports > Journal > Encounter > Custom Image - Custom encounter image path used when
cardImage === 'custom'. - This should be a valid Foundry asset path only when the encounter card image mode is
custom.
- Source setting:
This section maps the normalized API fields back to the settings users actually configure. It is intended to help other module authors understand both where the data comes from and what kind of content the GM is expected to place there.
-
Campaign Name->campaign.getCore().name- Expected content: the table-facing name of the active campaign.
- Use this as narrative context, not as a compendium or system identifier.
-
Rules Version->campaign.getCore().rulesVersion- Expected content: which D&D 5e rules revision the campaign is running under.
- Current supported values:
20242014
-
Number of Rulebooks->campaign.getCore().rulebooks.configuredCount- Expected content: how many rulebook selectors the GM wants available.
- This shapes the settings UI and indicates the intended breadth of structured rulebook selection.
-
Rulebook 1..N->campaign.getCore().rulebooks.compendiums- Expected content: selected rulebook compendium packs that represent the structured rules corpus for the campaign.
- Consumers should prefer these over parsing freeform text.
-
Custom Rulebooks->campaign.getCore().customRulebooks- Expected content: supplemental freeform rules references that are not represented by the selected compendium packs.
- Good uses include house rules, third-party books, campaign documents, or short notes about special rules in effect.
-
Realm->campaign.getGeography().realm- Expected content: world-, plane-, or setting-level location context.
-
Region->campaign.getGeography().region- Expected content: kingdom-, coast-, territory-, or province-level context.
-
Site->campaign.getGeography().site- Expected content: city, dungeon, keep, temple, mine, settlement, or similarly specific location.
-
Area->campaign.getGeography().area- Expected content: the most local default location context, such as a district, room, street, or zone.
-
Party Name->campaign.getParty().name- Expected content: the canonical party name, if the group uses one.
-
Party Size->campaign.getParty().configuredSize- Expected content: how many party member slots should be tracked in settings.
-
Party Member 1..N->campaign.getParty().members- Expected content: the actor selections representing the campaign's actual party roster.
- These should usually be player characters rather than generic reference actors.
-
Narrative Folder->campaign.getJournalDefaults().narrative.folder- Expected content: the default journal folder for generated/imported narrative entries.
-
Custom Image->campaign.getJournalDefaults().narrative.imagePath- Expected content: a valid asset path.
-
Character Image->campaign.getJournalDefaults().narrative.characterImagePath- Expected content: a valid asset path.
- (A narrative
Card Imagecontrol was listed here. It no longer exists — the setting is not registered.)
-
Encounter Folder->campaign.getJournalDefaults().encounter.folder- Expected content: the default journal folder for generated/imported encounter entries.
-
Default Encounter Card Image->campaign.getJournalDefaults().encounter.cardImage- Expected content: a built-in image choice,
custom, ornone.
- Expected content: a built-in image choice,
-
Custom Image->campaign.getJournalDefaults().encounter.imagePath- Expected content: a valid asset path only when the selected encounter card image mode is
custom.
- Expected content: a valid asset path only when the selected encounter card image mode is
Returns the core block only.
Returns the geography block only.
Returns the normalized party block only.
Returns the configured party leader with the user and actor already resolved:
{
userId: string, // '' if unset
actorId: string, // '' if unset
user: User | null, // resolved from userId
actor: Actor | null, // resolved from actorId
name: string | null, // actor name, falling back to user name
isCurrentUser: boolean // true if the current user is the leader
}- Source setting:
partyLeader(hidden; set via the Blacksmith menubar, not the settings sheet). -
isCurrentUseris the field most consumers want for permission checks such as "may this user start a vote?". It requires a configuredactorIdand then either the storeduserIdmatching the current user or the current user owning the leader's actor — i.e.!!leader.actorId && (leader.userId === game.user?.id || !!actor?.isOwner). The ownership fallback matters because legacy worlds sometimes stored the GM'suserIdhere. Note the leadingactorIdrequirement: a leader configured with auserIdbut noactorIdyieldsfalseeven for that very user. (This page previously omitted that clause. The guard is deliberate — it mirrorsisCurrentUserPartyLeader(), which has the identicalif (!leader?.actorId) return false;check.) - Returns the same shape with empty/null fields when no leader is configured; it never throws.
Returns campaign.getCore().rulebooks.
Returns the journal block only.
Returns a flattened helper object for prompt/template replacement:
{
campaignName,
rulesVersion,
rulebooks,
partyName,
partySize,
partyLevel,
partyMakeup,
partyClasses,
realm,
region,
site,
area,
narrativeFolder,
narrativeImagePath,
narrativeCharacterImagePath,
encounterFolder,
encounterCardImage,
encounterImagePath
}This object has no narrativeCardImage key; the narrative character image field is narrativeCharacterImagePath.
-
campaignName- Prompt-ready campaign title.
-
rulesVersion- Prompt-ready rules era value (
2024or2014).
- Prompt-ready rules era value (
-
rulebooks- Flattened comma-delimited text built from selected rulebook compendium labels plus
customRulebooks.
- Flattened comma-delimited text built from selected rulebook compendium labels plus
-
partyName- Prompt-ready party title.
-
partySize- Prompt-ready size.
- Uses resolved
memberCountfirst, then falls back toconfiguredSize.
-
partyLevel- Prompt-ready level string.
- Uses derived party average level when available, then falls back to the hidden legacy setting for backward compatibility.
-
partyMakeup- Prompt-ready party description.
- Uses selected party actors first, then falls back to the hidden legacy freeform makeup string.
-
partyClasses- Prompt-ready comma-delimited list of unique class names derived from the selected party actors.
-
realm,region,site,area- Prompt-ready geography values.
-
narrativeFolder,narrativeImagePath,narrativeCharacterImagePath- Narrative journal defaults flattened for prompt/template replacement.
-
encounterFolder,encounterCardImage,encounterImagePath- Encounter journal defaults flattened for prompt/template replacement.
- The API is read-only.
- Party members come from the configured party-member actor dropdowns in Blacksmith settings.
- Rulebooks are built from selected rulebook compendiums plus the freeform
Custom Rulebookssetting. - Modules should prefer this API over direct
game.settings.get('coffee-pub-blacksmith', ...)reads for campaign and party context. -
partyLevelandpartyMakeupstill include a legacy fallback path for existing worlds while the new party-member settings are adopted. - Rulebook compendiums are a separate mapping from the main Compendium Mapping. For monsters, items, spells, features, and other content lookups — including turning plain text into a UUID — see api-compendiums.
- Ai assistance
- Applicationv2 traps
- CSS traps
- dnd5e conditions
- Documentation standard
- Token actor identity
- Campaign
- Canvas
- Chatcards
- Compendiums
- Contextmenu
- Core
- Create journal entry
- Dialog
- Active Effects
- Entity list
- Equiplocations
- Geography
- GM request
- Gmnotes
- Health
- Hookmanager
- Importer
- Inventory
- Menubar
- Notes
- Party
- Pins
- Quantity split
- Requestroll
- Rolls
- Scene config
- Sockets
- Stats
- Tags
- Toast
- Tokens
- Toolbar
- Window
- Worldclock