Phaser AE

Customers and service

Free packv3.0.0-32DLogic

The guests of any service game, from the door to the bill. Parties arrive, queue, sit, order, eat, pay and leave a place to clear, losing patience while they wait on you and tipping by how happy they are, and the game chooses which of those steps it needs.

This is a Free pack. Every phaser.io account can use it in their games.

Released October 14, 2026 · updated October 19, 2026

Customers and service: 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

customers

function customers(): Pack<{ customers: CustomersApi }>

The customers pack: game.customers. No options.

Helpers

createService

function createService(options: ServiceOptions = {}): Service

Open a shift. Throws, with every fault, on options validateService refuses.

createServiceAutopilot

function createServiceAutopilot(service: Service, options: { pace?: number } = {}): ServiceAutopilot

A host for service, acting every pace seconds (default 0.8).

dinerMenu

const dinerMenu: MenuItem[]

The built-in menu.

guestKinds

const guestKinds: GuestKind[]

The built-in guests.

validateService

function validateService(options: ServiceOptions = {}): string[]

Check a shift's options. Empty when it can be played.

Types

CustomersApi

interface CustomersApi

What the customers pack adds to a game: game.customers.

  • create: typeof createService — Open a shift.
  • validate: typeof validateService — Check a shift's options.
  • kinds: typeof guestKinds — The built-in guest kinds.
  • menu: typeof dinerMenu — The built-in menu.
  • autopilot: typeof createServiceAutopilot — A host for an attract mode or a test.

GuestKind

interface GuestKind

A kind of guest.

  • id: string — Its name, unique among the kinds; a party's kind and a scheduled arrival's kind refer to it.
  • name?: string — Display name for a presenter to show; the pack itself does not read it.
  • weight?: number — How often it comes, against the others. Default 1.
  • party?: [number, number] — People in a party. Default [1, 2].
  • hearts?: number — Hearts of patience it arrives with, and seconds waiting that cost one. Default 5 and 8.
  • patience?: number — Seconds a party of this kind waits on the player before it loses a heart; above 0, default 8.
  • tip?: number — Tips are multiplied by this. Default 1.
  • think?: number — Seconds looking at the menu, and eating. Default 3 and 8.
  • eat?: number — Seconds a party of this kind spends eating; default 8.
  • items?: [number, number] — Items each person orders. Default [1, 1].
interface MenuItem

Something on the menu.

  • id: string — Its name, unique among the items; an order, serve and the events refer to it.
  • name?: string — Display name for a presenter to show; the pack itself does not read it.
  • price: number — What one costs on the bill, in the game's money units; 0 or more.
  • weight?: number — How often it is ordered, against the others. Default 1.

Party

interface Party

A party of guests.

  • id: string — Its name in the shift, 'g1', 'g2' and so on; the actions and events refer to the party by it.
  • kind: string — The id of its guest kind.
  • size: number — People in the party, a whole number; never more than the seats of the biggest place.
  • phase: PartyPhase — Where it is in its visit.
  • hearts: number — Hearts of patience left; at 0 it leaves angry.
  • maxHearts: number — Hearts it arrived with, the most it can have.
  • place: string | null — The place it sits at.
  • order: string[] — What it ordered (once it has), and what has come.
  • served: string[] — The items of its order brought so far, as menu ids.
  • timer: number — Seconds left thinking or eating; seconds towards losing the next heart while waiting.
  • waited: number — Seconds of waiting counted towards the next lost heart; back to 0 when something is done for the party.
  • arrived: number — Shift time, in seconds, at which it arrived.

PartyPhase

type PartyPhase = 'queue' | 'seated' | 'order' | 'wait' | 'eat' | 'pay'

Where a party is: in the queue, seated and thinking, waiting to order, waiting for food, eating, waiting to pay.

Place

interface Place

A table, a counter spot: somewhere a party sits.

  • id: string — Its name in the shift, 'p1', 'p2' and so on unless the options gave one.
  • seats: number — The biggest party it takes, in people.
  • party: string | null — The id of the party sitting there, or null when it is free.
  • dirty: boolean — True after a party has left and until the place is cleared; no one is seated at a dirty place.

Refusal

type Refusal = string | null

Why an action was refused, or null when it was done.

Service

interface Service

A shift.

  • readonly state: ServiceState — Where the shift stands; it changes as the shift runs.
  • readonly options: Readonly<{ kinds: GuestKind[]; menu: MenuItem[]; flow: Required<ServiceFlow>; duration: number; goal: number }> — The options with defaults filled in.
  • seat(party: string, place: string): Refusal — Seat a queued party at a free, clear place with enough seats.
  • takeOrder(party: string): Refusal — Take the order of a party waiting to order.
  • serve(party: string, item: string): Refusal — Bring a party an item of its order.
  • collect(party: string): Refusal — Take the money of a party waiting to pay.
  • clear(place: string): Refusal — Clear a place after a party has left.
  • step(dt: number): void — Advance, in fixed steps of 1/60 s.
  • bill(party: Party): number — A party's bill: the menu prices of what it ordered.
  • drain(): ServiceEvent[] — Events since the last call; the latest 512 are kept.
  • snapshot(): ServiceSave — The shift as plain JSON.
  • restore(save: ServiceSave): void — Pick up a saved shift made with the same options; pending events are dropped.

ServiceAutopilot

interface ServiceAutopilot

A host that acts on a shift.

  • act(dt: number): string | null — Advance its clock; when it is ready, do the most urgent thing and say what.

ServiceEvent

type ServiceEvent = | { kind: 'arrive'; party: string } | { kind: 'walkout'; party: string } | { kind: 'seat'; party: string; place: string } | { kind: 'ready'; party: string } | { kind: 'ordered'; party: string; order: string[] } | { kind: 'served'; party: string; item: string } | { kind: 'eat'; party: string } | { kind: 'done'; party: string } | { kind: 'paid'; party: string; bill: number; tip: number } | { kind: 'heart'; party: string; hearts: number } | { kind: 'angry'; party: string } | { kind: 'cleared'; place: string } | { kind: 'over'; won: boolean }

Something that happened.

ServiceFlow

interface ServiceFlow

Which steps a game uses.

  • order?: boolean — The order waits for someone to take it; without this the party orders as it sits. Default true.
  • eat?: boolean — The party eats before paying. Default true.
  • pay?: boolean — The party waits for someone to take its money; without this it pays as it finishes. Default true.
  • dirty?: boolean — The place needs clearing after a party leaves. Default true.
  • autoSeat?: boolean — The next party in the queue takes a free place by itself. Default false.

ServiceOptions

interface ServiceOptions

A shift's options.

  • seed?: number — Default 1.
  • kinds?: GuestKind[] — Guest kinds. Default guestKinds.
  • menu?: MenuItem[] — The menu. Default dinerMenu.
  • places?: number | { id?: string; seats?: number }[] — The places: how many (two seats each), or each with its seats. Default four of two and two of four.
  • flow?: ServiceFlow — Which steps it uses.
  • arrivals?: { every?: [number, number]; ramp?: number; schedule?: { at: number; kind?: string; size?: number }[] } — Seconds between parties, from the start to the end of ramp; or exact arrivals. Default [14, 6] over the shift.
  • queue?: number — The most parties waiting in the queue; another walks away. Default 4.
  • duration?: number — Seconds in the shift, and the money that wins it. Default 180 and 0.
  • goal?: number — The money that wins the shift: it is won when money is at least this at the end. Default 0, which any shift wins.
  • tip?: number — The tip at full hearts, as a share of the bill. Default 0.3.
  • restore?: number — Hearts each thing done for a party wins back. Default 1.

ServiceSave

interface ServiceSave

A shift saved as plain JSON.

  • state: ServiceState — The shift state.
  • next: number — Seconds until the next arrival at the rising rate.
  • serial: number — The count of party ids handed out so far.
  • schedule: number — How many scheduled arrivals have already happened.
  • carry: number — Seconds of step time not yet spent, less than one fixed step of 1/60 s.
  • rng: RngState — The state of the shift's random stream.

ServiceState

interface ServiceState

Where the shift stands.

  • time: number — Seconds into the shift.
  • phase: 'open' | 'over' — 'open' while it runs; 'over' once the time is up and the last party has left, or 120 s after the time is up.
  • won: boolean — Whether the shift was won: set when it ends, true if money reached the goal.
  • money: number — Money taken so far: the bills and the tips.
  • tips: number — The part of money that is tips.
  • served: number — Parties that paid, left angry, or walked away from a full queue.
  • lost: number — Parties that left angry or walked away from a full queue.
  • walkouts: number — Parties that walked away from a full queue; each is also counted in lost.
  • parties: Party[] — The parties in the shop now, queueing or seated.
  • places: Place[] — Every place, with who is at it.