You don't have to rewrite anything. wowlua init turns the addon you ship
today into a wowlua project, leaves its code as it is, and builds the same
AddOn your players have now. Then you add types one file at a time, when you
want them.
Three commands
Run them in your addon's folder, best with a clean git working tree. Inside a
git repository, files are moved with git mv, so their history follows them.
$ wowlua init --from-pkgmeta Adopted Tally for standard, vanilla (3 files moved into src/, 0 in-game paths updated) Converted 4 externals from .pkgmeta Note TOC files are generated from wowlua.json now; the old Tally.toc, Tally_Vanilla.toc can be deleted Note .github/workflows/release.yml publishes with the BigWigs packager, which keeps working; to publish with wowlua, replace its packager steps with one - uses: DomenikIrrgang/wowlua/.github/actions/setup-wowlua@main - run: wowlua publish env: # the packager step's env (CF_API_TOKEN, WOWI_API_TOKEN, WAGO_API_TOKEN, GITHUB_OAUTH) (runs with `-d`, which upload nothing, become `wowlua package`) $ wowlua build --release # compare dist/release/Tally with the packager's zip $ wowlua publish --dry-run # see what each site would get
Tally is a small example addon: a retail and a Classic Era TOC, four Ace3
libraries as packager externals in .pkgmeta, and a release workflow that
runs the BigWigs packager.
.pkgmeta (or pkgmeta.yaml) is converted whenever it exists.
--from-pkgmeta makes it required, and --from-pkgmeta <file> names another
packager project file. An addon without one is adopted from its TOC files
alone with plain wowlua init; --from-toc <file> picks the TOC when there
are several.
What changes in your folder
Before:
Tally/├── .github/workflows/release.yml runs BigWigsMods/packager@v2├── .pkgmeta├── CHANGELOG.md├── README.md├── Tally.toc ## Interface: 120100├── Tally_Vanilla.toc ## Interface: 11509├── embeds.xml├── Locale.lua├── Core.lua└── Media/icon.tgaAfter wowlua init --from-pkgmeta:
Tally/├── .github/workflows/release.yml unchanged├── .pkgmeta unchanged├── CHANGELOG.md├── README.md├── Tally.toc no longer used, delete when you like├── Tally_Vanilla.toc no longer used, delete when you like├── wowlua.json what the TOCs and .pkgmeta said├── wowlua.lock the pinned interface numbers├── src/│ ├── embeds.xml│ ├── Locale.lua contents untouched│ └── Core.lua└── Media/icon.tga assets stay where they are- The title, notes, SavedVariables, dependencies,
X-fields and interface versions move from the TOCs intowowlua.json. The interface versions give the flavors, herestandardandvanilla. TOCs are generated from now on. - Every Lua and XML file the TOCs load moves into
src/, and absolute in-game paths to them (Interface\AddOns\Tally\…) are rewritten. If the addon already has asrcfolder, the sources go towowlua-src/. - The load order is kept exactly, in
build.load-order, per flavor where the TOCs differ. Files only some flavors load go intobuild.flavor-files. .pkgmetaexternals become dependencies,ignorebecomesbuild.exclude, andX-Curse-Project-ID,X-Wago-IDandX-WoWI-IDbecome publish targets.- Textures, sounds and fonts stay where they are and become
build.assets, so their paths don't change. wowlua.lockpins the interface numbers, so the first build writes the same## Interfacelines.
Lua and XML files that no TOC loads are listed in a warning and left in
place. Part of Tally's new wowlua.json:
{ "addon": { "title": "Tally", "notes": "Counts your kills.", "saved-variables": ["TallyDB"] }, "flavors": { "standard": {}, "vanilla": {} }, "build": { "assets": ["Media/**/*.{tga,blp,png,jpg,jpeg,ogg,mp3,wav,ttf,otf}"], "load-order": ["src/embeds.xml", "src/Locale.lua", "src/Core.lua"], "libs-dir": "Libs", "exclude": ["README.md/**", "README.md"] }, "dependencies": { "aceaddon-3-0": { "svn": "https://repos.wowace.com/wow/ace3/trunk/AceAddon-3.0", "kind": "lua-library", "curseforge-slug": "ace3", "install-path": "AceAddon-3.0", "files": ["AceAddon-3.0.xml"] } }}The full file also has the other three dependencies, the CurseForge and Wago
targets, the changelog, and the compat settings and release profile of
the next section. Every step of init, with its edge cases, is in
CLI §12.6.
The same AddOn as the packager
An adopted packager project builds what the packager builds: the same loaded
code, the same shipped files, line endings and TOC versions, with
@project-version@, @debug@ blocks and the flavor blocks replaced as the
packager replaces them. This is checked on 36 addons, including BigWigs, DBM,
WeakAuras, ElvUI and Details.
To get there, init writes compat settings
(Manifest §9.14):
"compat": { "packager-keywords": true, "line-endings": "crlf", "toc-version": "@project-version@"}It also writes a release profile without bundling, minification or
optimizations, like the packager's zip. When you want smaller release builds
that load faster, remove those overrides from profiles.release
(Building and publishing).
A repository whose addons all come from .pkgmeta move-folders, such as
WeakAuras, DBM or ElvUI, becomes a
workspace. You can also keep
.pkgmeta as the source of truth for dependencies and publishing, with
"compat": { "pkgmeta": true }; wowlua.json then only adds wowlua's own
settings, and a key both files set is E4005.
How .pkgmeta maps to wowlua.json
.pkgmeta |
wowlua.json |
|---|---|
externals |
dependencies, with build.libs-dir and an install-path each |
ignore |
build.exclude |
plain-copy |
build.assets |
package-as |
addon.name |
manual-changelog |
publish.changelog |
move-folders |
workspace members, or workspace.external-addons |
license-output |
compat.license-output |
changelog-title |
compat.changelog-title |
enable-nolib-creation |
compat.nolib-package |
wowi-convert-changelog, wowi-create-changelog, wowi-archive-previous |
the WoWInterface target's changelog-output, changelog and archive-previous |
required-dependencies, optional-dependencies, embedded-libraries, tools-used |
CurseForge relations |
git, SVN and zip externals convert. URLs are read the way the packager reads
them: old CurseForge URLs, SVN trunk and tags/ paths, and sub-paths of
CurseForge and GitHub git URLs. hg externals are listed with W4333 and need a
git mirror or an archive instead.
Your CI keeps working
init leaves .github/workflows alone, so a workflow that runs the packager
keeps publishing. For each one, it prints how to switch: the packager step
becomes two steps with the same secrets. Before:
- uses: BigWigsMods/packager@v2 env: CF_API_KEY: ${{ secrets.CF_API_KEY }} GITHUB_OAUTH: ${{ secrets.GITHUB_TOKEN }}After:
- uses: DomenikIrrgang/wowlua/.github/actions/setup-wowlua@main- run: wowlua publish env: CF_API_KEY: ${{ secrets.CF_API_KEY }} GITHUB_OAUTH: ${{ secrets.GITHUB_TOKEN }}A converted project publishes the way the packager does. There is no clean
working tree check, the targets upload in the packager's order (CurseForge,
WoWInterface, Wago, GitHub), and a target without a token is skipped with a
note. Tokens come from the packager's environment variables (CF_API_KEY or
CF_API_TOKEN, WAGO_API_TOKEN, WOWI_API_TOKEN, GITHUB_OAUTH, …; not
GITHUB_TOKEN) and from its .env file, so the secrets you have keep
working. Runs with -d, which upload nothing, become wowlua package.
Publishing §11.9
has the details.
Try it in the game
The addon builds as it is. Run wowlua dev, /reload in the game, and type
/wl: the dev window profiles and
monitors your existing Lua with no change to your code
(Getting started explains
wowlua dev).
Then add types, file by file
Every Lua 5.1 file is already valid wowlua. When you want types in a file,
rename it from .lua to .wowlua. In a file that uses no wowlua syntax,
name and type problems are only warnings, so a renamed file builds as
before. They become errors once the file uses wowlua syntax, so fix them at
your own pace. In src/Core.lua:
local function addKill(name, count) count = count or 1 TallyDB[name] = (TallyDB[name] or 0) + countendLater, in src/Core.wowlua, with typed parameters, a default value and ??:
local function addKill(name: string, count: number = 1) TallyDB[name] = (TallyDB[name] ?? 0) + countendTo get hints in the files you haven't renamed yet, set
"check": { "lua": true }: it type-checks the remaining .lua files too,
with warnings only.
Already using LuaLS annotations?
Keep the work you put into ---@class and ---@param. wowlua types convert turns them into a .d.wowlua declaration file, from one file or a
whole folder:
$ wowlua types convert src # writes src.d.wowlua
--out <dir> names the folder to write it to; the default is the current
one.
Where to go next
- A tour of wowlua: what you can write once a file is
.wowlua. - Testing your addon without starting the game.
- Building and publishing with bundled release builds.
- WoW API: what the checker knows about the game's functions.