Bloons+
WIKI / DEVELOPERS

Developer guide

Build and contribute

Local development

Clone the repository, run npm ci, and create a Python 3.12 environment using py -3.12 -m venv .venv. Install requirements-installer.txt into that environment. On a fresh checkout only, copy autobtd6/userconfig.example.json to autobtd6/userconfig.json. Use npm run app for Electron or npm start for the local API and interface.

git clone https://github.com/Klaasawastaken/BloonsPlus.git
cd BloonsPlus
npm ci
py -3.12 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements-installer.txt
npm run app

Run these commands in PowerShell from the repository root. Keep an existing userconfig.json: replacing it resets local preferences. Install the Microsoft Visual C++ x64 runtime on the machine where Python executes, including the guest when using a VM.

Runtime architecture

electron-main.js owns the desktop window. server.js exposes the local API. assets/app/app.js renders controls and progress. lib/automation.js selects recordings and launches Python; lib/engine-lock.js prevents competing input jobs. The guest bridge lives in lib/vm-bridge.js, and setup in lib/vm-setup.js. The Python runner is autobtd6/replay.py; capture and simulated input are adapted by windowed_input.py.

API reference

GET /api/farm/status returns active replay status and logs. POST /api/farm/start starts a supported automation job. GET /api/progress/local-save exposes supported account progress; GET /api/route-failures returns failure evidence. Inspect the corresponding branches in server.js for request bodies and response shapes before integrating; the preview API may change. Keep the service local and do not expose game control to the internet.

EndpointBehavior
GET /api/farm/statusRead running state, current replay, recent logs and sweep progress. Polling does not start gameplay.
POST /api/farm/startFor the medal sweep, send {"type":"black-border-sweep"}. A queued response means setup or game startup is still in progress; inspect status instead of submitting duplicate starts.
POST /api/farm/pauseToggles pause. Read the current state first; repeated requests can resume the run.
POST /api/farm/stop-afterToggles stop after the current replay. Check stopAfterReplay before sending another request.
POST /api/setup/updateInstall the prepared host installer in the guest. An active replay blocks the update. Follow GET /api/setup/status until the job finishes.

Responses can contain private account and diagnostic information. Redact them before sharing. Treat the installed guest and host source as separate versions: editing the host does not replace guest files.

Verification workflow

Run syntax checks on changed JavaScript and Python files. Focused HUD and placement regressions live in tests/test_hud_and_placement.py. Check git diff --check and tools/check-publication.py before publishing. When a missing-medal replay runs, inspect placements and upgrades, then require a real victory and the saved medal before claiming a clear. Do not launch games solely for validation. Passing a syntax check does not establish a working strategy.

.\.venv\Scripts\python.exe -m unittest discover -s tests -p "test*.py"
if ($LASTEXITCODE -ne 0) { throw "Python regressions failed" }
foreach ($test in Get-ChildItem tests -Filter "test-*.js") {
  node $test.FullName
  if ($LASTEXITCODE -ne 0) { throw "Failed: $($test.Name)" }
}
git diff --check
.\.venv\Scripts\python.exe tools/check-publication.py

Run these commands in PowerShell from the repository root. The Python pattern includes both underscore and hyphen filenames, including installer, Steam download and SSH regressions. The JavaScript loop stops on a failed check. These checks run without sending game inputs; they do not prove a route wins or a clean Windows installation succeeds. Publication scanning checks known private-file and secret patterns; manually inspect new artifacts too.

Installer and website

installer/make-installer.py builds the Windows bootstrap and payload. installer/installer-bootstrap.cs supplies setup UI and dependency installation. Build tools live in tools/. The website is static HTML in docs/, with shared site.css and site.js; directory-based pages provide clean URLs. Preserve license notices for imported routes and assets.

Safe contributions

Never commit player saves, VM keys, tokens, account identifiers, private screenshots or generated progress. Keep personal settings local. Provide route provenance, game version, mode, account prerequisites and focused regression evidence in a change description. Original CHIMPS recordings remain preserved while runner fixes are developed.

Replay recovery

The runner persists the remaining action queue and unresolved upgrade targets. On resume, autobtd6/resume_recovery.py rebuilds actions from the current parsed route so keys, prices and intended tiers reflect current settings. Validated recovery positions and retry counts survive. Supplemental upgrades are reconsidered instead of replayed blindly.

Upgrade ownership is probed from the selected tower panel before purchasing. Cash changes alone cannot prove a tier was bought, because income can arrive during the action. Unknown panels and mismatched route intent must stay explicit in diagnostics. Offline recovery tests passing do not prove every interrupted game can resume.

Medal-only development workflow

  1. Read the active account's authoritative save progress and choose an obtainable missing medal. Skip owned map/mode pairs completely.
  2. Let the replay run while developing unrelated code. Keep original CHIMPS recordings intact.
  3. Save failures with route identity, mode, round and observed action evidence. Continue with another eligible candidate or another missing medal.
  4. Batch updates. Wait for the active replay to finish, stop between games, deploy and restart the missing-medal sweep.
  5. Count a clear only after both victory and the saved medal are confirmed. Once all supported obtainable medals are owned, stop the sweep entirely.

Generate and inspect new candidates offline. Do not launch gameplay merely to validate, benchmark or retest an already earned medal.