jesse 1d23c187ad Daikoku PA: two perimeter ramps, far side served by the median opening
Rework the PA junction to match the reference drawing: yellow = PA -> highway
(entry), red = highway -> PA (exit). Entry and exit swap sides (entry now
EAST, exit WEST) and both trunks hug the PA perimeter instead of running
concentric spirals.

The simplification: both carriageways sit at the same deck level, adjacent,
so the median opening IS the far-side access path. The under-deck crossing
and merge runs are deleted outright -- 8 runs collapse to 4, and the
girder-soffit ceiling logic that constrained the crossing goes with them.
Part count 24,210 -> 21,691.

The median opening is now load-bearing rather than cosmetic (it is the only
route from the far carriageway to the ramps), so it widens from 6 to 9
samples per junction.

Orientation is a single flip-able constant (ORIENT) so a mirrored result is
a one-line correction, not a rewrite.

Measured on the built map (not asserted):
  - 600 entry + 600 exit ramp parts
  - max grade 8.00% / 8.27%, under the 9% limit
  - 0 collisions with piers/masts/girders (558 structural parts)
  - segment continuity <= 2.5 studs; trunk->merge handoff <= 1.7 studs
  - merge lands at dY 0.0 (exact deck level), 33 studs lateral
  - median open at junctions: 0 parts vs. control ~7 on plain mainline

Two traps worth recording, both caught by controls:

1. Studio's require() cache silently rebuilt STALE code. The first "passing"
   build reported 17,575 parts and zero ramps, and the map contained
   PAOffRamp/PAOnRamp parts whose names exist nowhere in the current source.
   Every measurement taken before this was describing an old map. Added
   tools/rebuild_fresh.luau, which clones the module to bust the cache; use
   it rather than requiring MapBuilder directly.

2. A reported "median never opens" bug was a bad probe, not a defect. It
   counted `Barrier` (the outer edge parapet, which must NEVER open) instead
   of `Median_<i>`. Re-run against the right name: control 7, junctions 0.

Both were only visible because the probes carry controls -- a 0-hit result
with no control is vacuous. The verification harnesses are kept in tools/
with their controls built in.
2026-08-03 11:53:40 -04:00

Tokyo Wangan Racing

A Roblox game where you cruise a neon Tokyo expressway at night in cool cars — starting with a real 1993 Mazda RX-7. The driving feel comes first; everything else layers on top of it. See docs/ROADMAP.md for what comes next.

Status: Playable. Spawn → drive → switch cars → respawn, plus the full three-mode Wangan loop. CI green on a self-hosted Gitea runner. Built code-first — nothing to hand-build in Studio.

The Daikoku loop (how you play)

Daikoku Futo PA is the hub, exactly like Tokyo Xtreme Racer. You are never "joining a match" — you park, pick how you want to run, and drive out.

        IN THE PA  ──►  pick a mode  ──►  cross the exit gate  ──►  RUNNING
             ▲                                                        │
             └──────────────── pull back into the PA ─────────────────┘
Mode 日本語 What it is
CRUISE 流し Free roam. Bank kilometres, meet other drivers. Rivals can pull alongside and challenge you.
DUEL バトル Hunt rivals. First to open a ~350-stud gap and hold it for 3s wins. No laps, no checkpoints — who breaks first.
TIME ATTACK タイムアタック Solo flying lap with 4 sector splits and a saved personal best. Rivals can't interrupt you.

Cruise and Duel both allow challenges, so a cruise can turn into a battle organically — pull alongside someone and the prompt appears for both of you. Time Attack deliberately opts out so a hot lap is never ruined.

Kilometres, lap times and duel records all persist via ProfileStore.


Prerequisites

Toolchain is managed by Rokit. With Rokit on your PATH:

rokit install     # rojo, wally, selene, stylua at pinned versions
wally install     # restores ProfileStore into ServerPackages/
Tool Purpose
rojo Sync/build code ↔ Roblox place
wally Package manager (ProfileStore)
selene Static analysis / linter
stylua Code formatter

Build & run

rojo build --output build.rbxl   # standalone place file to open in Studio
# OR live-sync into an open Studio place (install the Rojo Studio plugin):
rojo serve

In Studio press Play. You spawn on the expressway in your car. Bottom bar: CARS (switch car) and RESPAWN (re-spawn if you flip). The RX-7 only appears for allowlisted accounts.

Quality gates (CI enforces these on every push)

stylua --check src/     # formatting
selene src/             # lint
rojo build --output build.rbxl   # must compile

CI runs on a self-hosted Gitea Actions runner on UNRAID-1 (Ubuntu 24.04 job container — rojo's binary needs glibc 2.39). Workflow: .gitea/workflows/ci.yml.


Architecture (server-authoritative)

Clients request, the server decides. The RX-7 allowlist and anti-cheat are server-side.

ReplicatedStorage/Shared     GameConfig, Cars, ProfileTemplate, Remotes
ServerScriptService/Server   init.server + managers (below)
ServerScriptService/ServerPackages  ProfileStore (Wally)
StarterPlayerScripts/Client  init.client (HUD + car picker)
Module Responsibility
DataManager Wraps ProfileStore — session locking, reconcile, Studio mock. Remembers your last car.
CarManager Spawns the equipped car (VehicleSeat-driven placeholder) and enforces the RX-7 allowlist.
MapBuilder Procedurally builds the expressway, spawn pad, neon pylons, kill walls.
AntiCheat Movement sanity check (speed/teleport) — a speed bump, not a fortress.

The RX-7 demo-lock: GameConfig.RX7AllowedUserIds holds the owner's + son's Roblox UserIds; only they can select/drive the RX-7 (enforced in CarManager and the EquipCar remote).

Replacing the placeholder RX-7 with the real mesh

One function changes: CarManager.buildCarModel. Full step-by-step in docs/MESH_SWAP.md. Reference photos live on the NAS at unraid-1:/mnt/user/data/yy-roblox-games/0-tokyo-wangan-racing/001-1993 Mazda RX-7/.

S
Description
Tokyo Wangan Racing — Roblox street-racing sim. Cruise, duel, or time-attack the Wangan from Daikoku Futo PA. Rojo + Wally + ProfileStore.
Readme
12 MiB
Languages
Luau 92.7%
Python 7.1%
PowerShell 0.2%