Race
Host-only three-rival race lifecycle. Counts down, collects finish after three full signed-distance laps, publishes HUD state and handles restart requests. Mount on the world root; never on the player prototype.
Host-only three-rival race lifecycle. Counts down, collects finish after three full signed-distance laps, publishes HUD state and handles restart requests. Mount on the world root; never on the player prototype.
Interface
What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.
conforms to
zero/source-extract/v2tally( ) → void
tallyText( ) → void
winningTrack( ) → void
sharedRaceId( ) → void
mine( ) → void
authority( ) → void
Whether this peer decides what that race does. A solo race is always its owner's to run. The shared one is run by exactly one peer, and every peer has to name the same one: asking isHost() answered false on ALL of them once the peer that created the room had gone, so nobody advanced the race and its clock stood still while each screen waited. The lowest peer id in the room is an answer each peer reaches alone and all reach alike, and it survives the peer holding it leaving -- the next lowest simply takes it up. The peer that owns the race entity runs it. Deciding this by isHost() put the decision on one peer and the right to write the fields on another: a host that did not own the race computed a countdown the engine then refused, and the lobby sat on a number that never moved. Ownership is what the engine enforces, so ownership is what authority follows.
decode(s: ?) → void
| arg | type | description |
|---|---|---|
| s | ? |
namesForGrid(ids: ?) → void
| arg | type | description |
|---|---|---|
| ids | ? |
recordStats( ) → void
updateFinish( ) → void
slots( ) → void
ensureEntrants( ) → void
A replicated entity arrives without the parts that draw and move it, because those are added by whichever peer spawned it. Every peer therefore has to put them on each entrant itself, or the grid is a field of invisible cars for everyone but each car's owner. The parts a peer adds this way read the owner's synced fields rather than driving anything: a bot answers to the host, and a driver's car to the peer sitting in it.
clearBots( ) → void
localUserId( ) → void
refreshHumans( ) → void
restart( ) → void
chooseTrack(index: ?) → void
| arg | type | description |
|---|---|---|
| index | ? |
lockGrid( ) → void
bind( ) → void
joinLobby( ) → void
Joining and leaving are the two things a driver does about a race, and each is its own call. One `enterRace` served the multiplayer button, the circuit screen's button and the internal join, so what it meant depended on the phase it landed in -- and a peer that was only looking at circuits could not be told apart from one asking for a grid slot. Joining is something a PLAYER does, so it travels as the player's identity and nothing else. Carrying it on the car meant a spectator -- who has no car at all -- could never join, and meant the authority had to hold the joiner's car entity to read the request: a peer whose car had not replicated was simply never counted, and two people in one lobby each read one driver. The player list crosses peers; entities may not.
leaveLobby( ) → void
voteTrack(index: ?) → void
| arg | type | description |
|---|---|---|
| index | ? |
awake( ) → void
reconcileDuplicates(_dt: ?) → void
Every peer runs the scene's load, and the guard there asks whether a shared race exists before replication has had a chance to deliver anyone else's -- so each peer makes one. They cannot be prevented from being created, so they are reconciled instead: the lowest id wins, and a peer despawns the one it made itself once it can see an older one. Nobody has to agree first, and the answer is the same on every peer. Duplicates are left standing rather than despawned. Every peer already obeys the lowest id, so an extra race nobody obeys costs nothing -- while despawning one cost everything: a peer gave up its race in favour of another peer's, that peer left, and the room was holding no shared race at all. A race that is ignored can still be adopted if it turns out to be the last one; a despawned race cannot.
| arg | type | description |
|---|---|---|
| _dt | ? |
update(dt: ?) → void
| arg | type | description |
|---|---|---|
| dt | ? |
restart( ) → void
snapshot( ) → any
onDestroy( ) → void
Sub-parts
Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.
Showing up to 3 levels deep. Open a part to see what it holds further down.
Problems
Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.
agent_score is exposed.+ quality × 0.35
+ performance × 0.25
± compat factor
Usability ratings
Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".
Scoped to this part · feeds back into the world's score.