Updated

Reference games

The games and packs built out of the Dot collection — what each one exists to prove, and why the seams between addons only get exercised in a game.

Thirteen games ship alongside the collection — six full games and seven minigames — with two weapons packs and the map repositories several of them load, and they are not demonstrations. Every addon’s own suite runs that addon with the others absent, so the joins between them exist only in a game, and a code path that only one deployment shape reaches is a code path nothing has run.

They live under zees-games rather than under the organisation the addons are in; see the overview for why the split is a rule.

Every one of them is delivered, not built in. Each game is published as a signed dot-cloud pack; a server installs the ones it is told to offer, and a player’s client downloads the pack when it joins. The client shell contains no game at all, so it is the same build whatever it connects to, and a new game reaches players without a new client. That is also why every game here references its own scripts by path rather than by class_name: a mounted pack’s class_name globals are never registered, so a game written the other way mounts, loads its scenes, and runs none of its code.

This is where the bugs are

Putting the gameplay addons through one process found seven bugs, six of them in other repositories and not one reachable from that repository’s own suite. Running the whole thing end to end found twelve more. Opening a real browser client against a real server found seven more after that. The pattern holds every time.

Two addons are built for every game by TMC’s server tool rather than by any game: a dot-replay ring on every server (replay save at the console, and a clip’s hash filed with every kick and ban), and a dot-friends client beside the party client in the exported client shell, which switches itself off for the session when the site answers its friends routes with a 404. No game links either itself.

Bots are the other thing most of them share. Nine games fill empty seats with players from dot-bot, the family’s bot brain (game-arena, game-hungario, game-zombie-zone, game-hide-n-seek, mg-prop-hunt, mg-wipeout, mg-deathrun, mg-buses-from-hell and mg-dangerous-delivery), and all of them take its bot_difficulty presets at the console: easy, medium (the default), hard and nightmare, each a bundle of individual bot_* settings.

game-arena

A 3D dev-textured arena shooter. The reference game. It exists to prove the addons compose, to show what the bridges look like, and to be the thing a new game is copied from.

Seven modes (free-for-all, team deathmatch, a horde mode called siege, king of the hill, capture the flag, gun game and snipers only) on three built-in maps, dm_box, dm_atrium and dm_pit, plus the combat surf maps from g2gfast-maps. Most of the family runs in one process here: dot-player-controller, dot-combat, dot-weapon, dot-loadout, dot-match, dot-team, dot-spawn, dot-objective, dot-npc for the horde, dot-props, dot-bot, dot-ui, dot-menu, dot-net and dot-server, with chat, voice, moderation, stats and achievements beside them.

Four files matter, and the reason each one is in the game rather than in an addon is the same reason every time:

  • maps/arena_map.gd — a level is a list of boxes, and that list becomes three things: meshes, physics bodies, and analytic geometry for a headless server. Building them separately means three descriptions that drift, and the drift is invisible until shots start passing through something clients can see.
  • game/arena_player.gd — movement, weapons, health and hitboxes on one body. Every addon says this wiring belongs in the game, because an addon that did it would dictate a scene shape.
  • game/arena_game.gd — the seam. dot-match knows nothing about damage, dot-combat nothing about scoring, dot-loadout nothing about weapons; this is where a combat kill becomes a match score and a match respawn becomes a loadout. It never names dot-server, so a listen server, a test and a dedicated server all run the same game.
  • game/arena_module.gd — the dedicated-server integration. With game/arena_services.gd beside it, it is the only code that names dot-server.

The weapons are all twenty-seven of zee-dot-weapons, and none is defined in the game. A loadout, chosen on B, is five slots (melee, primary, secondary, thrown, gear) on a seven-point budget: a rifle, a pistol, a grenade and armour fit with a point to spare, and a heavy weapon with armour does not, because that is the combination nobody can answer. A server owner can restrict the choice, or fix one kit for everybody, with the mp_loadout_* cvars.

godot --headless --path . res://examples/headless_match.tscn   # a whole deathmatch
godot --headless --path . res://examples/headless_net.tscn     # one server, two clients, one packet in five lost
godot --headless --path . res://examples/dedicated.tscn        # a real DotServer

game-hungario

A grow-by-eating arena game with an avatar riding the monster. The first playable client in the collection, the first game with working netcode over a real socket, and the first place the gameplay half and the identity half ran together.

Uses dot-2d, dot-net, dot-server, dot-match, dot-ui, dot-user-avatar, dot-loadout, dot-platform, dot-cloud and dot-bot, and none of the 3D movement or combat addons. One pack carries six modes — classic, frenzy, gauntlet, warrens, reef and shallows — each a game.yml of its own over the same content.

It is also the shortest path to the browser column: small, needs no threads, and it exercises every browser constraint with nothing else in the way. Its web/README.md is the deployment contract — WebSocket because a browser has no UDP, client-only because a tab cannot listen, wss:// because an HTTPS page may not open an insecure socket, and thread support off because turning it on requires cross-origin isolation on every response and breaks every third-party embed on the page.

game-playground

A sandbox in the classic physics-sandbox shape. Hold Q for a menu of props, NPCs (some armed), weapons, tool-gun modes and your saved builds; click one and it is yours. A physics gun that holds, freezes and picks up players; a gravity gun that punts; a tool gun that resizes, paints, welds, ropes, wires buttons to doors and more. Builds are saved and loaded from the menu (one welded piece is listed as a custom prop), props can be breakable, standing on a moving prop carries you, and creative mode keeps a builder out of everybody’s way. Built-in maps (a sandbox with timed courses on its bonus tracks, a surf map, a bhop map, a generated one) plus custom maps delivered as JSON documents from game-playground-maps. The timed courses are what say dot-timer is not a surf-and-bhop thing: a jump course is not a movement genre.

Uses dot-player-controller, dot-timer, dot-map, dot-props, dot-npc, dot-vehicle, dot-inventory, dot-leaderboard, dot-ui, dot-server, and zee-dot-weapons for the guns.

It is the only place dot-player-controller, dot-timer, dot-map, dot-props, dot-leaderboard, dot-ui and dot-server run in one process. Its suite has found nine bugs, three of them in other repositories; screenshots found four more.

game-g2gfast

The bunny-hop and surf timer server, in the shape of the round-based competitive shooters’ movement servers. Their units, cvars and field of view, first and third person, and every player drawn as an avatar — theirs from the platform, or a stock one. Each imported map is its own pack, fetched when the server changes to it, so the game pack stays small and a new map needs no new game.

Uses dot-player-controller, dot-timer, dot-map, dot-leaderboard, dot-server, dot-user-avatar, dot-ui.

sv_tickrate 100
sv_autobunnyhopping 1
sv_airaccelerate 1000        // 150 for surf
sv_gravity 800
sv_allow_thirdperson 1
sv_replay_bot 1              // the server record as a visible ghost

Zone a map whose author never used this engine, from the console:

g2g_zone start
g2g_zone_mark          // stand on one corner
g2g_zone_mark          // and the other
g2g_zone stage main 1
g2g_zone_save

game-zombie-zone

The co-operative zombie shooter. A team of survivors crosses an exodus map from one shelter to the next, or a bigger team holds a survival map behind barricades through waves of the horde. The zombies are dot-npc NPCs, server-only and replicated, sent in by dot-npc-ai-director rather than at random, with eleven kinds of special infected that each have one trick. Zombies drop boxes that do something random when opened, good or very bad, and friendly fire is on. The maps come from zombie-zone-maps: a three-map campaign and the survival maps.

Uses dot-npc, dot-npc-ai, dot-npc-ai-director, dot-player-controller, dot-combat, dot-weapon, dot-match, dot-bot and dot-game, and it is the game that carries both weapons packs, zee-dot-weapons and zed-dot-weapons.

game-hide-n-seek

Hide and seek. Most players hide, as their own avatars in the hiders’ blue; a seeker for every eight players counts blindfolded, then goes looking. A touch catches (a server can make it being kept in view instead, or either), and every hider caught becomes a seeker where they stand, so the hunt grows as the round goes on. Doors open and shut on E, and a shut door is a wall to bodies, sight and touch. Eleven maps come from hide-n-seek-maps. It was built from mg-prop-hunt with the disguises and weapons taken out.

Uses dot-player-controller, dot-player-char, dot-team, dot-match, dot-props, dot-bot and dot-game.

mg-smash-copter

A minigame whose antagonist is the floor. Two to six teams stand on platforms balanced on single pillars, forty metres up, while a cannon in the middle throws things at them. Whoever is still up when the clock runs out is thrown into a corner of the sky with a weapon they did not choose, and the last team standing wins.

First- and third-person. Uses dot-props for everything the cannon throws, dot-vehicle for the chopper, dot-combat for health and hit registration, dot-match for the round and the sides, dot-player-controller, dot-net, dot-game for the server wiring, and zee-dot-weapons for the twenty-seven weapons the second half is fought with. dot-spectate, dot-audio, dot-stats and dot-achievements came later — it is last-team-standing, and an eliminated player had had nothing to look at. dot-settings followed, for the client’s options, with the field of view one a server may clamp.

mg-buses-from-hell

The asymmetric one. Two drivers in buses against everybody else on foot, in a walled sand bowl with crates and exploding barrels in it. The drivers try to run the runners over; the runners have a hammer, and the hammer does not hurt anybody — it breaks crates and shoves them. That is the whole game.

Uses dot-props, dot-vehicle, dot-combat, dot-match, dot-player-controller, dot-net and dot-game, plus dot-spectate, dot-audio, dot-stats, dot-achievements, dot-settings, dot-fx (for the exploding barrels) and dot-bot for the stand-ins. It unlinked dot-spawn, dot-team and dot-physics, each named and never used. It is also the project that dot-entity found a leak in: a _next_entity_id counter with no forget() anywhere, which left a DotHealth per player who had ever joined, each pointing at a freed node.

mg-wipeout

Obstacle courses over water. Sweeping arms, big balls, rolling logs, swinging hammers and floors that drop away; a fall sends a player back to their last checkpoint. If two or more sides finish, they fight a final death in a random arena with props to throw with the gravity gun and weapons lying on the floor. An obstacle is a pure function of the tick, so a course is sent once as a document and client prediction agrees with the server about every arm without another byte. Eleven courses and five arenas come from mg-wipeout-maps.

Uses dot-props, dot-player-controller, dot-combat, dot-weapon, dot-match, dot-bot, dot-game and zee-dot-weapons.

mg-deathrun

One long course of traps. Most players run it; activators, drawn fresh each round, stand on a walkway beside it with a button for every trap. Whoever reaches the end is handed a weapon, and the first one there calls the activators down to settle it. A trap is a pure function of the tick and the tick its button went on, so a press is one event and a runner’s own prediction carries them exactly as the server does. Three courses come from mg-deathrun-maps, and a practice course is built in.

Uses dot-player-controller, dot-combat, dot-weapon, dot-match, dot-team, dot-game and zee-dot-weapons, with bots named from dot-bot’s pool.

mg-prop-hunt

Hide as the furniture. Most players are props, who look at something on the map and become it; the rest are hunters, blindfolded while the props hide and then given a few minutes to find them, paying in health for every piece of real furniture they shoot. A disguise is a hull as well as a look (dot-props’ DotPropDisguise), and the blindfold is real on the wire: a hiding prop is in no hunter’s snapshot. Four maps (a school, a house with a pool, an office and the woods) come from mg-prop-hunt-maps, and a practice house is built in.

Uses dot-props, dot-team, dot-combat, dot-weapon, dot-match, dot-bot, dot-game and zee-dot-weapons.

mg-look-at-me

A small horror game. Players make their way through a dark house, thirty-two levels deep, while witches walk its rooms; being seen fills a meter, so the job is to find what opens the next door before one of them looks at you for too long. Doors are per player by default (a server can share them), so everybody does every level themselves and the server never has to end.

Uses dot-player-controller, dot-player-char, dot-net and dot-game.

mg-dangerous-delivery

Trucks up mountain roads with no rails. Drive a loaded truck through snow, rain, wind and falling rock and deliver the load to a depot; a harder haul pays more, and the money buys bigger trucks and upgrades. Nobody walks: a player is their truck, dot-vehicle’s wheeled chassis bound without the seat handover. The weather belongs to the mountain rather than to a trip, so everybody on the same pass drives through the same snow.

Uses dot-vehicle, dot-net, dot-bot (the stand-ins drive at bot_difficulty) and dot-game.

zee-dot-weapons

Not a game — a weapons pack. It is the half dot-weapon deliberately leaves out: the view models, the world models, the animation and the art, with twenty-seven weapons already built on top of its catalogue.

First-person view models, third-person world models, procedural animation, and the replication that makes another player’s weapon look right on your screen. The art is Kenney’s Blaster Kit with melee from the Weapon Pack and Survival Kit — all CC0, all vendored, nothing to download.

Shots are seen and heard with no code: ZeeShotFx draws a tracer, a muzzle flash and an impact, and ZeeWeaponSound plays a report per weapon class, synthesized on first use (a game can put a real recording in front of any of them). rig.view_punch() is the recoil for the camera, which a first-person game hands to dot-player-controller’s DotFpsView.external_angles.

zed-dot-weapons

A second weapons pack, on top of the first. Fourteen more weapons with a real-world look (two pistols, an Uzi, a tactical SMG, two shotguns, a hunting rifle, a machine gun, a grenade launcher, a rocket launcher and a flamethrower) and the throwables a co-operative zombie game needs: a molotov, a pipe bomb and a bile jar, tagged so a game knows what each does when it lands. It is content only: it registers into zee-dot-weapons’ catalogue, art and sounds, so one rig carries both packs. It was made for game-zombie-zone, and any game on zee-dot-weapons can carry it.

dot-game-template

Where a new game starts. Not one of the thirteen: it lives with the addons, under modcommunity, because it is what a third-party developer copies. It is Coin Grab, a small networked 2D game on dot-game — predicted, server-authoritative, and written without class_name so it works as a delivered pack from the first commit. tools/rename.sh makes it yours. On a v* tag its release workflow attaches the game as a -pack.zip, and the site signs and publishes that as <your site username>/<repository>, which is the name a server installs it by. The server tool mounts its packaged release on every check, so the template is verified the way a stranger’s game would be.

Lessons for your own bridges

Four failures recur across these games, and all four are invisible to the kind of check that would normally catch a bug.

A value produced correctly and consumed by nothing looks exactly like a value produced wrongly. The interpolated position, the interest set and the cloud client were all computed correctly and read by nobody, and in every case the visible symptom pointed at the producer.

A value consumed by two games and produced by nobody is the same bug with the ends swapped. DotTimer.effect_requested was declared, forwarded and connected — and emitted by no line anywhere, so every map’s pit volume was decoration in two games.

An interface’s bugs are invisible to assertions, because every property is correct and nothing fails. Two 0 × 0 Control trees and a black screen were found by rendering a frame and looking at it, not by a test.

So is motion. Every check in every suite asserts a simulated value, and the jitter that made a browser client unplayable had every simulated number right. The bug was in the mapping from the simulation to the screen, which no assertion on the simulation can reach.