-
Notifications
You must be signed in to change notification settings - Fork 0
Example 02 read a save file
Josh Dionne edited this page Sep 14, 2026
·
3 revisions
Generated from the thetowersdk repository. Edits made here are overwritten on the next push — change the source file instead.
/**
* Example 2 — Read a real save file.
*
* Two steps: decode `playerInfo.dat` into a save root, then pull typed data
* out of that root. The decode step is Node-only (it needs gzip); everything
* after it is pure and also runs in a browser.
*
* Run it:
* npx tsx examples/02-read-a-save-file.ts /path/to/playerInfo.dat
*
* Where to find your save is explained in the README ("Getting a save file").
*/
import { readFile } from 'node:fs/promises'
import { decodePlayerInfoSaveBytes } from 'thetowersdk/node'
import {
readCardsFromSaveRoot,
readLabsFromSaveRoot,
readWorkshopFromSaveRoot,
} from 'thetowersdk/save'
async function main(): Promise<void> {
const savePath = process.argv[2]
if (!savePath) {
console.error('Usage: tsx examples/02-read-a-save-file.ts <path-to-playerInfo.dat>')
process.exit(1)
}
// --- Step 1: decode -------------------------------------------------------
const bytes = await readFile(savePath)
const { parsedRoot, wasGzip, battleRunCount } = decodePlayerInfoSaveBytes(bytes)
console.log(`Decoded ${savePath}`)
console.log(` gzip-compressed: ${wasGzip}`)
console.log(` top-level keys: ${Object.keys(parsedRoot).length}`)
console.log(` battle runs: ${battleRunCount}`)
console.log()
// --- Step 2: extract the parts you care about -----------------------------
// Every extractor returns `null` instead of throwing when a save predates
// that feature, so always check before reading.
const labs = readLabsFromSaveRoot(parsedRoot)
if (labs) {
console.log('Labs')
console.log(` unlocked: ${labs.labsUnlocked}`)
console.log(` researches done: ${labs.researchedCount}`)
console.log(` maxed: ${labs.maxedCount}`)
console.log(` currently running: ${labs.activeQueue.length}`)
if (labs.warnings.length) {
// Extractors report anything they could not make sense of rather than
// silently dropping it -- worth surfacing while developing.
console.log(` warnings: ${labs.warnings.join('; ')}`)
}
} else {
console.log('Labs: not present in this save')
}
console.log()
const workshop = readWorkshopFromSaveRoot(parsedRoot)
console.log(workshop ? 'Workshop: present' : 'Workshop: not present in this save')
const cards = readCardsFromSaveRoot(parsedRoot)
console.log(cards ? 'Cards: present' : 'Cards: not present in this save')
}
main().catch((error: unknown) => {
console.error(error)
process.exit(1)
})Generated from TheTowerSDK — do not edit here. Docs and live demos: https://tmrxjd.github.io/TheTowerSDK/
- Quick Start
- Entry Points
- How It Fits Together
- Getting a Save File
- Reading a Save
- Reading The Community Wiki
- Formulas
- Builders
- Charts
- Effective Paths
- Examples
- Templates
- Building a Bot On This
- Google Sheets
- Desktop and Mobile
- Optional Add-ons
- Using It With An AI Agent
- Using Your Own Artwork
- Names And Acronyms
- Patch Notes
- Accuracy
- Versioning
- Where the Docs Live
- Contributing
- Credits
- License
Guides
Examples
- 01-browse-game-data.ts
- 02-read-a-save-file.ts
- 03-plan-upgrades-from-a-save.ts
- 04-generate-a-chart.ts
- 05-generate-a-cost-table.ts
- 06-read-the-community-wiki.ts
- 07-format-like-the-game.ts
- 08-build-a-calculator.ts
- 09-build-a-bot.ts
- 10-read-a-sheet.ts
- 11-build-a-knowledge-base.ts
- 12-show-module-and-card-art.ts
Templates