bf6-portal-mod-framework
v1.1.6
Published
Framework and build system for Battlefield 6 Portal mods
Downloads
8,081
Readme
BF6 Portal Mod Framework
A development framework and CLI toolchain for creating Battlefield 6 Portal Mods using TypeScript.
It powers the official BF6 Portal Mod Template and provides:
bf6modCLI- automatic TypeScript merge (creates
__SCRIPT.ts) - automatic string extraction (creates
__STRINGS.json) - annotation-based dynamic string expansion
- live watch mode
- SDK updater
- does not include SDK files (downloaded per project)
🚀 Installation
npm install bf6-portal-mod-framework --save-devUpgrade to latest:
npm install bf6-portal-mod-framework@latest --save-dev📦 CLI Commands
The framework exposes:
bf6modUsed via npm scripts or directly.
🔨 Build (merge + strings)
bf6mod buildProduces:
__SCRIPT.ts
__STRINGS.jsonNotes:
__STRINGS.jsonis generated only during build- Watch mode does not trigger string extraction
👁 Watch (merge only)
bf6mod watchWatches src/ and regenerates:
__SCRIPT.tsDoes not update __STRINGS.json.
Run bf6mod build when editing string annotations.
🔄 Update SDK
bf6mod update-sdkDownloads latest BF6 Portal SDK typings:
SDK/mod/
SDK/modlib/🧱 Required Project Layout
SDK/
mod/
modlib/
src/
main.ts
...Outputs (__SCRIPT.ts, __STRINGS.json) are written to project root.
🛠 Merge Behavior
The merge tool (src/scripts/merge.js):
- scans all
.tsundersrc/ - resolves import order
- strips
import/export - flattens code
- writes:
__SCRIPT.tsThis is the file you paste into the Portal Web Editor.
💬 Strings System
This system extracts all string keys used in your mod and writes them into:
__STRINGS.jsonIt supports:
- static message keys
- message keys with parameters
mod.stringkeys.*usages- dynamic keys via template literals
- dynamic expansions through
// @stringkeysannotations
🎯 Static Strings
Basic
mod.Message("hello")Outputs:
{ "hello": "hello" }With Parameters
mod.Message("killLog", killer, victim)Outputs:
{ "killLog": "killLog {} {}" }Using mod.stringkeys
mod.stringkeys.ui.menu.StartOutputs:
ui.menu.Start🔥 Dynamic Strings
Dynamic keys must use template literals:
mod.Message(`ai.bots.${i}`)These require annotation declarations to generate all possible values.
📝 Annotations — @stringkeys
Format:
// @stringkeys <namespace>: <values>The namespace may have multiple dot segments:
ui.menu.buttons
ai.bots
dynamic.range✔ Numeric Range
// @stringkeys ai.bots: 0..3
mod.Message(`ai.bots.${i}`)Generates:
ai.bots.0
ai.bots.1
ai.bots.2
ai.bots.3✔ Alphabet Range
// @stringkeys grades: A..F✔ List
// @stringkeys ui.buttons: OK, Cancel, Retry✔ Mixed
// @stringkeys ai.states: Idle, Roam, Fight, A..C, 10..12📌 Dynamic Key Rules
Dynamic keys must follow the format:
namespace.static.${variable}Valid
mod.Message(`ai.bots.${i}`)
mod.Message(`ui.menu.buttons.${btn}`)
mod.Message(`world.zone.ids.${zone}`)❌ Invalid (ignored)
mod.Message(`ai.${type}.${i}`)
mod.Message(`${a}.${b}`)
mod.Message(`bots.` + p)
mod.Message(`bots.${p}.${x}`)Only one trailing dynamic part is supported.
🧪 Static Keys Are Always Added
mod.Message("scoreboard.title")→ included even without annotations.
🔥 Real Example (from Template)
Code:
mod.Message(`test`)
mod.Message(`static.message`)
mod.Message(`static.messageWithParams`, 1)
mod.stringkeys.static.stringkey
// @stringkeys dynamic.range: 1..2
for (let i = 0; i < 4; i++) {
mod.Message(`dynamic.range.${i}`)
}
// @stringkeys dynamic.list: Idle, Roam, Fight
const state = 'Idle'
mod.Message(`dynamic.list.${state}`)Output:
{
"dynamic": {
"range": {
"1": "dynamic.range.1",
"2": "dynamic.range.2"
},
"list": {
"Idle": "dynamic.list.Idle",
"Roam": "dynamic.list.Roam",
"Fight": "dynamic.list.Fight"
}
},
"test": "test",
"static": {
"message": "static.message",
"messageWithParams": "static.messageWithParams {}",
"stringkey": "static.stringkey"
}
}Notes:
- Only annotated values are added
- Looping extra values (
0and3) is ignored since they’re not in annotation range - Lists expand exactly as declared
- Static keys and
mod.stringkeysalways work
⚙ Optional Warning Mode
Add to your project’s package.json:
{
"bf6mod": {
"warnUnusedStrings": true
}
}When enabled, if the previous __STRINGS.json contained keys that no longer appear after rebuild, you will see warnings like:
Warning: unused string key removed: dynamic.range.3This helps catch accidental typos or removed behaviors.
🧩 Template Integration
Official template:
https://github.com/nikgodda/bf6-portal-mod-template
Provides:
- ready
src/layout - game mode base class
- SDK folder
- npm scripts mapped to the framework:
npm run build → bf6mod build
npm run watch → bf6mod watch
npm run update-sdk → bf6mod update-sdk📜 License
MIT
