Skip to content

Releases: kefiiiiir/VNEngine

v0.2.2

Choose a tag to compare

@kefiiiiir kefiiiiir released this 31 Aug 15:09

VNEngine update

For writers

  • Typo fixes no longer nuke saves. Editing dialogue text (fixing a
    typo, rewording a line) used to silently invalidate every player's save,
    because the old text was baked into the save's "did the script change?"
    check. That's fixed — only structural stuff (who's speaking, jumps,
    labels, choices, etc.) is checked now, not the words themselves.
    • One-time heads up: because of how this fix works internally, saves
      made before this update will show the normal "Save may be out of
      date" prompt one last time on load, then behave correctly from then
      on.
  • Players can no longer bold/color/italicize their own name. If
    someone enters [b]Bob as their name, it now shows literally as
    [b]Bob instead of rendering as Bob. Markup tags ([b], [i],
    [c=...]) written by you in story.js still work exactly as before —
    this only strips them out of player-typed names and set() variables.
  • Docs fixed: removed two keyboard shortcuts from VNEngine.md
    (auto-advance's A key, skip's Ctrl/Tab) that were documented but
    never actually existed in the engine — the engine has always been
    buttons + Space/Enter/number-keys only.
  • Docs added: VNEngine.md now says plainly that rollback history (the
    "back one line" buffer) and the backlog/history overlay are memory
    only
    — they reset on reload. Only checkpoints/auto-save/seen-tracking
    survive a reload.
  • Topbar buttons are now screen-reader friendly (aria-labels added,
    visuals unchanged).
  • Renamed to "VNEngine" (capital E) in the visible/branded spots:
    page title, title-screen logo, README heading, and the manual — which is
    now template/VNEngine.md (was VNengine.md).

For coders

  • engine.jssave-resolve.js extraction. Pulled the DOM-free save
    logic (digestOps, hashStr, buildLabels, segmentNameAt,
    posFromPtr, resolvePos) out into template/js/save-resolve.js — a
    small UMD module (window.VNSaveResolve in the browser, module.exports
    in Node). engine.js now calls into it via a local SR alias. Loaded in
    index.html right before engine.js.
  • The fix itself: digestOps's say case dropped o.text, kept
    o.who. Save format bumped v: 2 → v: 3; applySnapshot now checks
    s.v === 3. Anything else (v1's raw ptr, or v2 — whose hash can't be
    trusted anymore since it included text) falls into the legacy/mismatch
    path, but still resolves pos when the save has one instead of just
    resetting to line 0.
  • segmentNameAt is now binary search, not Object.keys().forEach.
    buildLabels() returns a pre-sorted [index, name] array once at boot;
    lookup is O(log labels) instead of O(labels), called on every line of
    dialogue.
  • Tests: template/tools/tests/save-resolve.test.js — plain Node, no
    framework, 14 cases covering hashStr, digestOps (incl. the "text
    change → same digest" regression lock), buildLabels/segmentNameAt,
    and posFromPtr/resolvePos round-trips (including "insert lines in an
    earlier label → save still resolves correctly," and a documented edge
    case for inserting within the same segment before the saved line).
    Run: node template/tools/tests/save-resolve.test.js.
    • Location note: lives under template/tools/tests/, not a
      repo-root tests/ — repo root is just the setup scaffolder, template/
      is the actual engine project, and tools/ is where the other
      dev-only/never-shipped tooling already lives (packager, devlog.js).
      projectpackager-windows.py's ARCHIVE_DIRS = (css, js, src) confirms
      tools/ never ships in a built game.
  • CI added: .github/workflows/ci.yml, on push/PR — py_compiles
    setup.py, template/playtest.py, template/tools/*.py, and runs the
    test file above.
  • setup.py rmtree hardened (~line 471, now main()'s overwrite
    block + new _looks_like_vnengine_project() helper): refuses to touch a
    non-empty destination unless it contains a project.json with
    "engine": "VNengine"; shows file count in the confirmation prompt;
    renames the old folder to <name>.bak-<timestamp> instead of
    shutil.rmtree-ing it.
  • fmt() in engine.js: added stripMarkup(), applied to
    player.first, player.last, and each interpolated state.vars[k]
    before substitution (not to the final string — writer-authored markup
    elsewhere in the line is untouched).
  • Rename: template/VNengine.mdtemplate/VNEngine.md via a
    two-commit-safe git mv (staged as a rename, not yet committed — Windows
    git needs the two-step dance for a pure case change).

v0.2.1

Choose a tag to compare

@kefiiiiir kefiiiiir released this 31 Aug 09:53

VNengine v0.2.1

VNengine now builds and ships as a desktop app, not a browser tab — and the
diagnostics you used to have to dig for in F12 come straight to your terminal.

Highlights

Native window

playtest and every packaged build open the game in its own window via
pywebview (WebView2 on Windows) — no browser
chrome, no address bar, no tab. The HTTP server runs on a background thread and
shuts down when you close the window; there's no separate Ctrl+C step.
VN_NO_BROWSER=1 still serves headlessly, and if pywebview isn't installed it
falls back to opening your default browser.

Boot diagnostics in the playtest terminal

A ~60-line dev shim (tools/devlog.js) is injected into index.html only when
playtest.py has a console
(source runs, or a development build). It forwards
console.*, uncaught errors, and failed image/audio loads to the terminal, which
renders them grouped and colour-coded — errors red, warnings amber, one green
"no problems found" on a clean boot. Never referenced by index.html, never in a
shipping build; the real F12 console still works.

Two build profiles

The packager now asks for a profile:

profile runtime for
development --console testing — console window streams diagnostics next to the game
shipping --windowed release — no console, no dev shim, index.html untouched

Each profile has its own cached frozen runtime (keyed on a hash of
playtest.py), so switching profiles doesn't force a rebuild of the other.

index.html moved into the .pak

Packaged output is now just <Project>.exe + <Project>.pak — the HTML is
inside the archive, so there's no loose file for a player to edit.
project.json rides along too, and the window is titled from it (falling back to
the <title> in index.html). Old builds with a loose index.html still run
(disk fallback preserved).

In-world confirmation dialogs

"Erase save?", "Return to menu?", and checkpoint-jump prompts are now themed
in-engine modals — no more browser confirm() boxes reading "localhost:8000
says". Escape or a backdrop click cancels; destructive actions get a red button
with focus defaulting to Cancel; respects prefers-reduced-motion.

setup installs the toolchain

After scaffolding, setup offers to pip install the two packages a project
needs: pywebview (play/ship window) and pyinstaller (packager).

New dependencies

  • pywebview — required for the native window (graceful browser fallback if absent)
  • pyinstaller — required only for packaging

setup installs both on request; otherwise: pip install pywebview pyinstaller.

Upgrading an existing project

Projects are copies of the engine, so they don't auto-update. Either re-scaffold
with the new setup, or copy these into your project and reload:

  • playtest.py
  • tools/devlog.js (new file)
  • tools/projectpackager-windows.py
  • tools/projectpackager-tools/build-runtime.py
  • merge the js/engine.js + css/style.css changes (in-world dialogs)

Existing packaged .exe builds keep working unchanged.

Assets

  • VNEngine-Dist.zip — extract, run setup.exe (Windows)
  • Source: git clone, then python setup.py

Known rough edges

  • First frozen build per machine can take ~a minute (PyInstaller cold start).
  • A mis-bundled pywebview falls back to the default browser rather than erroring.
  • Only a single .pak beside the .exe is supported.
  • Tooling is Windows-first; running from source on macOS/Linux is untested.

v0.2

Choose a tag to compare

@kefiiiiir kefiiiiir released this 31 Aug 05:22

VNEngine v0.2

For coders

The big fix: saves no longer break when you edit the script

  • Every save now stores a hash of the script plus its position as (nearest label, offset) instead of a raw op index. Insert a line in chapter 1 and existing saves in chapter 3 still resume in the right place.
  • If the hash doesn't match on load, the player gets a "Save may be out of date" dialog (Resume / Restart chapter / Back to title) instead of silently landing mid-sentence in the wrong scene.

Read-tracking cleaned up

  • seen ("have I read this line") moved to its own localStorage key, vnengine_seen, keyed by label+offset. It's no longer cloned into all 30 checkpoints, so it can't blow the storage quota.
  • lsSet now reports failures (quota full) with a toast + console error instead of swallowing them.

Boot-time validator

  • On load, engine.js checks the script and logs a grouped console report:
    • Errors: duplicate labels, unknown jump/choice targets
    • Warnings: unknown characters, unknown sfx names, unreachable code
    • Each entry includes the op index. It never stops the game.
  • jump/if to a missing label is now guarded (was a hard crash).

Rendering / effects

  • renderSprites() diffs by data-id and swaps src in place instead of rebuilding. Fixes sprite pop-in and the sprite "jump" on every expression change (the bob animation no longer restarts).
  • The flash effect is removed on animationend, so it fades fully instead of being cut at 260ms.
  • Character color now actually tints the name box (with an auto light/dark text-contrast pick).

New engine subsystems

  • Rollback (50-entry ring buffer; wheel-up / PageUp / button)
  • A backlog overlay
  • Skip / auto-advance modes

Tooling

  • playtest.py: dev mode sends Cache-Control: no-store (so the ?v= cache-busting trick is gone), packaged-archive assets get a long immutable cache, and it scans for a free port instead of assuming port 8000 is the same game.
  • Fonts are bundled as woff2 in src/fonts/ and @font-face'd — no Google Fonts request, works offline.
  • setup.py now rewrites the title-screen logo and credit line from project.json, so a fresh project doesn't show the engine's branding.
  • audio.js: the dead MARKS map is wired into music() offsets; SFX_NAMES is exported for the validator.

Touched: engine.js (most of it), story.js, audio.js, style.css, index.html, playtest.py, setup.py, VNengine.md, README.md, new src/fonts/. Nothing committed.


For writers

Your saves won't break when you edit your script. Add, move, or rewrite lines freely. Old saves resume in the right spot because they're anchored to the nearest label, not a line count. If a save is from an older draft, the player sees a small "this save may be out of date" prompt instead of getting dumped into the wrong scene.

The console now tells you when you make a mistake. Open the browser console (F12) and the engine lists: typo'd jump/choice targets, duplicate label names, characters or sound names you referenced but didn't define, and unreachable lines — each with its position. It won't stop your game, it just points at the problem.

New things you can write

  • Variables in text. set({ gold: 5 }) then say('ari', 'You have {gold} coins'). Any variable name in {curly braces} gets substituted.
  • Text styling. [b]bold[/b], [i]italic[/i], [c=#ff8ec4]coloured[/c] inside any line.
  • Conditional choices. Give a choice option a show function and it only appears when that's true:
    { text: 'Hug them', to: 'hug', show: function (s) { return s.vars.warmth > 2; } }
  • Set a number exactly. Normally set({ gold: 5 }) adds 5. Use abs() to assign: set({ gold: abs(0) }) sets it to 0.
  • Voice lines. say('ari', 'Hello.', 'talk', 'ari_hello') — the 4th argument plays a sound file (registered in SFX_FILES) for that line.

New things your players get, for free

  • Rollback — scroll the mouse wheel up, press PageUp, or click the ↶ button to go back a line.
  • Backlog — press L or the ▤ button to see everything said so far.
  • Skip — hold Ctrl (or press Tab) to fast-forward; it stops at every choice.
  • Auto-advance — press A.

Other

  • Character color now tints the name box, not just the placeholder card.
  • Sprites fade in smoothly and no longer jump when they change expression.
  • The flash effect fades instead of cutting off.
  • Fonts are built in, so your game works with no internet.
  • Editing while playtesting: just reload — no more bumping ?v= numbers.

v0.1.1

Choose a tag to compare

@kefiiiiir kefiiiiir released this 30 Aug 14:18

Better UI & UX for all CLI scripts

Full Changelog: v0.1...v0.1.1

v0.1

Choose a tag to compare

@kefiiiiir kefiiiiir released this 30 Aug 13:32

First release. enjoy

Full Changelog: https://github.com/kefiiiiir/VNEngine/commits/v0.1