-
Notifications
You must be signed in to change notification settings - Fork 0
Template save cli
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.
/**
* TEMPLATE — a command-line tool that reads a player's save.
*
* Copy this file into your own project and edit `report()`. The parts around it
* are the bits that are easy to get wrong: locating the file, decoding once,
* and handling saves that predate a feature.
*
* Needs Node (the decoder reads bytes). For a browser build see `browser-widget.ts`.
*
* npx tsx save-cli.ts <path-to-playerInfo.dat>
*/
import { readFile } from 'node:fs/promises'
import { decodePlayerInfoSaveBytes } from 'thetowersdk/node'
import {
readLabsFromSaveRoot,
readWorkshopFromSaveRoot,
} from 'thetowersdk/save'
import { formatLargeNumber } from 'thetowersdk/formatting'
/** Everything you want out of one save, gathered in one pass. */
function report(parsedRoot: Record<string, unknown>): void {
/*
* Extractors return null when the save has no data for that feature rather
* than throwing, so an older save degrades to a missing section instead of
* crashing the whole tool. Check before you read.
*/
const labs = readLabsFromSaveRoot(parsedRoot)
if (labs) {
console.log(`Labs: ${labs.researchedCount} researched, ${labs.maxedCount} maxed`)
// `warnings` is values the extractor could not interpret. Non-empty usually
// means the save shape changed — surface it rather than silently continuing.
if (labs.warnings.length) console.warn(' warnings:', labs.warnings)
} else {
console.log('Labs: not present in this save')
}
const workshop = readWorkshopFromSaveRoot(parsedRoot)
if (workshop) {
console.log(
`Workshop: ${workshop.workshopStatCount} upgrades, `
+ `${workshop.enhancementStatCount} enhancements, ${workshop.presets.length} saved presets`,
)
}
// Format anything you print with the game's own ladder, so a player can check
// your output against their screen.
console.log(`\n(example formatting: ${formatLargeNumber(1.234e18)})`)
}
async function main(): Promise<void> {
const savePath = process.argv[2]
if (!savePath) {
console.error('Usage: tsx save-cli.ts <path-to-playerInfo.dat>')
process.exit(1)
}
// Decode once. The save root is a plain object and extractors never mutate it,
// so run as many as you like over the same root.
const { parsedRoot } = decodePlayerInfoSaveBytes(await readFile(savePath))
report(parsedRoot)
}
main().catch((error: unknown) => {
console.error('Failed:', error instanceof Error ? error.message : 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