Malik SohaibEmail me
← All work

Mini Havoc

Real-time party games for friends on a call: 23 games from one shared link, fair by design, playable offline against bots.

Role
Solo: game design, 3D, frontend, netcode, backend
When
Sep 2026 to now
Status
Live

Friends on a call want something to play together without everyone installing an app. One person makes a room and shares a code, and up to 24 people play on phones and laptops.

Many players are on Pakistani mobile networks, where latency is high and some connections block WebSockets outright.

Decisions

  1. 01

    Server-run worlds, judged at each player’s moment

    Chose
    The server runs every arena at 30 ticks a second; each screen predicts its own movement with the same shared code, and hits are judged at the tick the player saw.
    Instead of
    Trusting each client’s positions, or judging everything at the server’s present, which punishes the laggiest player.
    Why
    Nobody can cheat by editing their client, and lag never decides who wins. Snapshots correct you by replaying inputs the server has not seen yet, so play stays smooth.
  2. 02

    Seeded boards, one message per tick

    Chose
    Every round has a seed so each screen builds the board itself, players stream small progress updates, and each screen gets one combined message per tick.
    Instead of
    Relaying every player’s update to everyone as it arrives.
    Why
    Relaying grows with the square of the room. A 50-player room went from a third of a CPU core to about 4%.
  3. 03

    Secrets stay on the server

    Chose
    During secret planning, snapshots carry only what was last revealed; hidden answers and items stay on the server until the reveal.
    Instead of
    Sending the full state and hiding it in the client.
    Why
    Even a modified client cannot see a rival’s moves early, and late inputs count up to the reveal, so a network hiccup costs no turns.
  4. 04

    A way in when sockets are blocked

    Chose
    If a WebSocket never opens but the server answers, the tab switches to an event stream with batched posts, then to long polling.
    Instead of
    Telling those players they cannot connect.
    Why
    It was seen in the field on Android phones on Pakistani networks. The client also races three sockets and keeps the fastest.
  5. 05

    One room engine, on the server or the phone

    Chose
    The room engine is shared code with no server dependencies, saving through a storage interface.
    Instead of
    A separate offline mode with its own copy of the rules.
    Why
    A room of bots runs entirely on the phone, offline, with exactly the same rules, scoring and bots as online.

Mini Havoc, in use: Crossfire: beans on a round arena dodging a sweeping beam. Hex Drop: beans on a honeycomb that falls away under them. Sumo Out!: four beans shove each other around a ring. Havoc Golf: beans putting across a green island. Hush: a first-person view through a haunted house. Colour Floor: beans racing to the right coloured tiles.

Crossfire
Hex Drop
Sumo Out!
Havoc Golf
Hush
Colour Floor
  • CrossfireCrossfire, from a real game night.
  • Hex DropHex Drop: the floor falls away where you stand.
  • Sumo Out!Sumo Out!: last bean in the ring wins.
  • Havoc GolfHavoc Golf: everyone putts at once.

What shipped

  • 23 games, 7 of them real-time 3D arenas in three.js.
  • Load test: 480 players in 80 rooms, about 400 in live rounds at once, on a quarter of one CPU core and 3 MB/s.
  • 384 automated test cases, including bot-played rounds for every arena.
  • Seats survive reloads for 12 hours, drops get a 15-second grace, and rooms resume after a server restart.
  • About 860 commits and over 150 pull requests in its first month.

Built with

TypeScript, three.js, cannon-es, Fastify, WebSockets, node:sqlite, Web Audio, Capacitor