Phaser AE

Independent renovation progression

Pro packv3.0.0-2Logic

A renderer-free economy for the part of a game where earned rewards become purchases, unlocked rooms and the decorations a player chooses. Baskets commit whole or not at all, rewards pay exactly once, and a save written against last month's catalogue restores into this month's.

This is a Pro pack. Upgrade to Phaser Pro to use it in your games.See Phaser Pro →

Released October 14, 2026 · updated October 19, 2026

Independent renovation progression: a screenshot of its demo
A note about these graphics

Expansion packs don't come with graphics. This screenshot is one way of drawing what the pack does, made for its demo: none of the sprites, tiles or backgrounds in it are in the pack.

That's by design. A pack is a game's logic, mechanics and effects, and it works with whatever art you give it. Some packs draw effects, backdrops or 3D scenes of their own, but none carries a game's sprites.

So the look is yours. Make the art on phaser.io, bring your own, or let your agent draw it in code: the same pack can look like anything.

The pack

renovationProgress

function renovationProgress():Pack<{renovationProgress:typeof kit}>

Install independent rules; no renderer or game-specific owner required.

Helpers

createRenovationProgress

function createRenovationProgress(config:RenovationConfig)

Create the economy from a catalogue. Throws on a bad id, duplicate ids, a negative or fractional price, a prerequisite that does not exist or is cyclic, or a slot whose area or kind does not exist.

Classes

RenovationProgress

class RenovationProgress

The renovation economy: credits, stored and installed products, unlocked areas and granted rewards, changed only by whole atomic baskets. Create it with createRenovationProgress.

  • readonly config:RenovationConfig — The catalogue it was created with (an owned copy).
  • constructor(config:RenovationConfig)
  • get state() — A copy of the current state; changing it changes nothing.
  • owned(product:string,s=this.data) — Copies of a product the player has, stored plus installed. s defaults to the live state.
  • quote(actions:RenovationAction[]):RenovationResult — Quote and commit use the same atomic cart transition. A failed line spends nothing.
  • transact(actions:RenovationAction[]):RenovationResult — Commit every line of the basket in order, or reject the whole basket with a reason and change nothing. A basket has 1 to 100 lines.
  • apply(action:RenovationAction) — Commit one action as a single-line transaction.
  • grant(reward:RenovationReward):RenovationResult — Grant a reward once. A repeated id returns valid: true with duplicate: true and changes nothing; a bad id, credits or items, credit overflow, storage over capacity or 100,000 receipts already held are rejected with a reason.
  • serialize() — The save as text: the catalogue id, its version, the product ids it knew and the live state. The catalogue itself is not stored.
  • restore(serialized:string):RenovationRestoreReport — Replace the live state with a save, fitted to the current catalogue. A save is refused only when it is not one of this game's: unparsable or malformed text throws renovation: not a save, another catalogue id or an unknown format renovation: incompatible save. The catalogue may have changed in any other way since the save was written, and the state is kept as far as it still makes sense: credits, receipts and revision are kept as they are; copies of removed products and removed areas are dropped; an installed product whose slot, kind or area changed or went returns to storage; starting areas, prerequisites of areas the player already had, and the starting stock of products new since the save are added. Storage over a lowered capacity is kept, and blocks buying and rewards until the player makes room. A refused or failing restore leaves the live state untouched. The report says what changed.
  • save(storage:RenovationStorage,key=\renovation:${this.config.id}`)— Write the save to a storage adapter (anything with synchronoussetItem); storage exceptions propagate. The key defaults to renovation:`.
  • load(storage:RenovationStorage,key=\renovation:${this.config.id}`):RenovationRestoreReport|false— Restore from a storage adapter: the restore report, orfalsewhen nothing is stored under the key. A bad save throws asRenovationProgress.restore` does.

Types

RenovationAction

type RenovationAction={type:'buy';product:string;quantity?:number}|{type:'place';product:string;slot:string}|{type:'store';slot:string}|{type:'unlock';area:string}

One line of a basket: buy copies of a product, place a stored product in a slot (any product already there returns to storage), store the product in a slot, or unlock an area.

RenovationArea

interface RenovationArea

An unlockable area. Its slots can be used only once it is unlocked.

  • id:string — Unique id, in the same form as a product's.
  • cost:number — Credits to unlock it; a nonnegative safe integer.
  • requires?:string[] — Ids of areas that must be unlocked first.
  • needs?:string[] — Ids of products the player must own, stored or installed, to unlock it.

RenovationConfig

interface RenovationConfig

The authored catalogue. Saves are keyed on id and survive edits to everything else; see RenovationProgress.restore.

  • id:string — Names this game's saves. A save restores only into a catalogue with the same id; change it to start every player afresh.
  • version?:number — Optional catalogue revision (nonnegative integer) written into saves and reported back by restore, so a host can tell which release a save came from. It never refuses a save.
  • products:RenovationProduct[] — Everything that can be bought, stored and installed.
  • areas:RenovationArea[] — The unlockable areas.
  • slots:RenovationSlot[] — The places a product can be installed, each in an area and accepting one product kind.
  • initialCredits?:number — Credits a new game starts with; default 0.
  • initialAreas?:string[] — Areas unlocked from the start, and added to any restored save that lacks them; default none.
  • initialInventory?:Record<string,number> — Stored copies per product a new game starts with, and given once to a restored save that predates the product; default none.
  • inventoryCapacity?:number — Most copies the storage holds at once (installed copies do not count); default 1000.

RenovationProduct

interface RenovationProduct

Independent economy and scene-selection state. Hosts supply rewards and storage adapters.

  • id:string — Unique id: a letter or digit, then letters, digits, :, _ or -, up to 100 characters. Saves are keyed on it.
  • kind:string — Which slots take it: a slot accepts only products of its own kind.
  • cost:number — Credits to buy one copy; a nonnegative safe integer.
  • requires?:string[] — Ids of products the player must own, stored or installed, before this one can be bought.
  • label?:string — Display name; authored metadata the rules never read.
  • variant?:string — Variant name; authored metadata the rules never read.
  • level?:number — Level; authored metadata the rules never read.

RenovationProgressApi

type RenovationProgressApi=typeof kit

Public independent rules and helpers exposed by the composed pack.

RenovationRestoreReport

interface RenovationRestoreReport

What RenovationProgress.restore changed so that a save made against another revision of the catalogue fits the current one.

  • changed:boolean — True when anything below is not empty. A save made against the same catalogue restores with changed false.
  • savedVersion?:number — The version the catalogue had when the save was written, when it had one.
  • dropped:{products:Record<string,number>;areas:string[]} — What the catalogue no longer has: copies lost per removed product (stored and installed) and removed area ids.
  • unplaced:string[] — Saved slot ids that were emptied because the slot, its product, its kind or its area changed or went. A surviving product went back to storage.
  • added:{areas:string[];items:Record<string,number>} — What the catalogue added: areas unlocked (starting areas, and prerequisites of areas the player already had) and starting stock given for new products.

RenovationResult

type RenovationResult={valid:true;duplicate:boolean;spent:number;state:RenovationState}|{valid:false;reason:string}

The outcome of a quote or transaction: valid: true with the credits spent, whether it was a duplicate (a reward already granted) and the resulting state, or valid: false with a reason code that names the first failure.

RenovationReward

interface RenovationReward

A reward from the host game, paid once per id.

  • id:string — Receipt id, in the same form as a product's: granting the same id again changes nothing.
  • credits?:number — Credits to add; a nonnegative safe integer. Default 0.
  • items?:Record<string,number> — Copies to add to storage, by product id; each count a whole number from 0 to 1000.

RenovationSlot

interface RenovationSlot

A place a product can be installed.

  • id:string — Unique id, in the same form as a product's.
  • area:string — Id of the area it is in; it is usable only once that area is unlocked.
  • kind:string — The product kind it accepts.

RenovationState

interface RenovationState

Everything that changes as the game is played; a save holds exactly this.

  • credits:number — Credits in hand; a nonnegative safe integer.
  • inventory:Record<string,number> — Stored copies by product id; installed copies are not counted here.
  • installed:Record<string,string> — The product id installed in each slot, by slot id; an empty slot has no entry.
  • areas:string[] — Ids of the unlocked areas, in the order they were unlocked.
  • receipts:string[] — Ids of the rewards already granted, so a repeat is ignored; at most 100,000.
  • revision:number — Starts at 0 and rises by one for every committed basket and every new reward.

RenovationStorage

interface RenovationStorage

Anything with synchronous getItem and setItem, such as localStorage.

  • getItem(key:string):string|null — The text stored under key, or null when there is none.
  • setItem(key:string,value:string):void — Store value under key; may throw (a full or blocked store), and the exception propagates.