Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,7 @@ gen/

# Python bytecode
__pycache__/

# Blockbench views of the vehicle models, written by assets/vehicles/build.py
assets/vehicles/out/*.bbmodel
assets/vehicles/review.bbmodel
19 changes: 19 additions & 0 deletions assets/minecraft/bedrock_addon/scripts/cars.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import { Bits, ahead, distance, numbers, randInt, turnBetween, warn, yawOf } fro

const FAMILY = "arnis_car";
const BRAKE = "arnis:brake";
// Speed in half blocks a second, as far as the client turns the wheels by it: it changes
// only when that does, so a car cruising sends nothing.
const SPEED = "arnis:speed";
// As bedrock_addon/mod.rs declares it: room for 130 km/h at the largest scale.
const SPEED_MAX = 255;
/** Cars this close to a player move. */
const DRIVE_REACH = 96;
/** A car placed at the start appears once a player comes this close. */
Expand Down Expand Up @@ -144,6 +149,9 @@ export class Cars {
}
if (!car) continue;
car.drives = players.some((p) => distance(p.location, car) <= DRIVE_REACH);
// The wheels turn by the speed last sent, saved with the car: one that no longer
// drives, or comes back from a save, stands still.
if (!car.drives) this.wheels(car, 0);
cars.set(id, car);
this.index(car);
}
Expand Down Expand Up @@ -187,6 +195,7 @@ export class Cars {
w: 0,
q: 0,
b: e.getProperty(BRAKE) === true ? 1 : 0,
ws: e.getProperty(SPEED) ?? 0,
n: tieBreak(e.id),
};
this.enter(car);
Expand Down Expand Up @@ -305,6 +314,8 @@ export class Cars {
car.b = b;
car.e.setProperty(BRAKE, b === 1);
}
// c is in thousandths of a block per step, ten steps a second.
this.wheels(car, Math.min(SPEED_MAX, Math.max(0, Math.round(car.c / 50))));
if (car.c <= 0) return;
this.move(car, car.c * 0.001);
}
Expand Down Expand Up @@ -396,6 +407,13 @@ export class Cars {
}
}

/** Tells the client how fast the wheels turn, when that changes. */
wheels(car, ws) {
if (ws === car.ws) return;
car.ws = ws;
car.e.setProperty(SPEED, ws);
}

/** A car that has driven out of everyone's reach is gone, and a new one joins nearer. */
leave() {
for (const car of [...this.cars.values()]) {
Expand Down Expand Up @@ -424,6 +442,7 @@ export class Cars {
w: 0,
q: 0,
b: 0,
ws: 0,
n: tieBreak(e.id),
drives: false,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ $tp @s $(x) $(y) $(z)
# Held on the stop line until its group has green.
execute if data entity @s data.g if score #red arnis.car matches 1 run return 0
data remove entity @s data.j
tag @s remove arnis.car.cross
execute store result score #i arnis.car run data get entity @s data.i
scoreboard players add #i arnis.car 1
$execute store result score #n arnis.car run data get storage arnis:cars seg[$(s)].p
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
execute store result entity @s data.b byte 1 run scoreboard players get #b arnis.car
execute if score #b arnis.car matches 1 as @e[type=block_display,tag=arnis.car.tail,distance=..0.1] if score @s arnis.car = #id arnis.car run data merge entity @s {brightness:{sky:15,block:15}}
execute if score #b arnis.car matches 0 as @e[type=block_display,tag=arnis.car.tail,distance=..0.1] if score @s arnis.car = #id arnis.car run data merge entity @s {brightness:{sky:7,block:7}}
execute if score #b arnis.car matches 1 as @e[type=item_display,tag=arnis.car.tail,distance=..0.1] if score @s arnis.car = #id arnis.car run data merge entity @s {brightness:{sky:15,block:15}}
execute if score #b arnis.car matches 0 as @e[type=item_display,tag=arnis.car.tail,distance=..0.1] if score @s arnis.car = #id arnis.car run data merge entity @s {brightness:{sky:7,block:7}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# About to cross a junction: not while a red light too close past it, or a car standing
# there, would leave this car standing in the junction. It waits at the edge instead, for
# 40 s at most: longer than any red light, and how cars that wait on each other in a ring
# round a block of short lanes get going again.
execute store result score #gq arnis.car run data get entity @s data.q
execute if score #gq arnis.car matches 400.. run return 0
execute if entity @s[tag=!arnis.car.long] if data entity @s data{gc:1b} unless score #tl arnis matches 0..239 run return run function arnis:cars/gated
execute if entity @s[tag=!arnis.car.long] if data entity @s data{gc:2b} unless score #tl arnis matches 340..579 run return run function arnis:cars/gated
execute if entity @s[tag=arnis.car.long] if data entity @s data{gl:1b} unless score #tl arnis matches 0..239 run return run function arnis:cars/gated
execute if entity @s[tag=arnis.car.long] if data entity @s data{gl:2b} unless score #tl arnis matches 340..579 run return run function arnis:cars/gated
execute if data entity @s data.gr run function arnis:cars/gate_at with entity @s data
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Waiting at the edge of a junction for room past it. Not held as at a red line: its front
# may reach into the road it crosses, so crossing traffic still gives way to it. It counts
# towards being stuck, which gate gives up on.
scoreboard players set #t arnis.car 0
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# A stop line has a point for cars and one further back for buses and trucks, so that each
# stands with its front at the line: the other kind drives on to its own.
execute if data entity @s data{k:1b} if entity @s[tag=arnis.car.long] run return 0
execute if data entity @s data{k:2b} if entity @s[tag=!arnis.car.long] run return 0
# Amber counts as red: only a green group drives over its stop line.
scoreboard players set #red arnis.car 1
execute if data entity @s data{g:1b} if score #tl arnis matches 0..239 run scoreboard players set #red arnis.car 0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
# The next lane, joined at the first of its points ahead of the car, and whether getting
# there crosses a junction.
data remove entity @s data.gr
data remove entity @s data.gc
data remove entity @s data.gl
data remove entity @s data.gy
data remove entity @s data.gb
$data modify entity @s data merge from storage arnis:cars seg[$(s)].n[$(k)]
# Across a junction: before setting off, room past it (gate). Others tell it is crossing.
execute if data entity @s data.j run tag @s add arnis.car.gate
execute if data entity @s data.j run tag @s add arnis.car.cross
function arnis:cars/enter with entity @s data
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,20 @@ function arnis:cars/look
execute if score #ahead arnis.car matches 2 run scoreboard players operation #t arnis.car < #q25 arnis.car
execute if score #ahead arnis.car matches 1 run scoreboard players operation #t arnis.car < #q50 arnis.car
# Crossing a junction, a car close ahead is a conflict to give way to for a while; on a
# lane it is a queue to wait in.
# lane it is a queue to wait in, and so is one waiting at a red line past the junction.
execute if score #ahead arnis.car matches 3 unless data entity @s data.j run scoreboard players set #t arnis.car 0
execute if score #ahead arnis.car matches 3 if data entity @s data.j run scoreboard players set #jam arnis.car 1
execute if score #ahead arnis.car matches 3 if data entity @s data.j run function arnis:cars/conflict
function arnis:cars/clear
execute if entity @s[tag=arnis.car.gate] if score #t arnis.car matches 1.. run function arnis:cars/gate
# Gentle on the throttle, firm on the brake.
execute store result score #c arnis.car run data get entity @s data.c
scoreboard players operation #was arnis.car = #c arnis.car
scoreboard players operation #c arnis.car += #accel arnis
scoreboard players operation #c arnis.car < #t arnis.car
execute store result entity @s data.c int 1 run scoreboard players get #c arnis.car
execute store result entity @s data.w int 1 run scoreboard players get #w arnis.car
# Off across the junction: the room past it was checked.
execute if score #c arnis.car matches 1.. run tag @s remove arnis.car.gate
# Standing for a minute with no red light to blame is stuck: it leaves and another car comes.
execute store result score #q arnis.car run data get entity @s data.q
execute if score #c arnis.car matches 1.. run scoreboard players set #q arnis.car 0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
data remove entity @s data.g
data remove entity @s data.m
data remove entity @s data.k
$data modify entity @s data merge from storage arnis:cars seg[$(s)].p[$(i)]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data modify entity @s item.components."minecraft:item_model" set value "arnis:vehicle/signal_car_amber_std"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data modify entity @s item.components."minecraft:item_model" set value "arnis:vehicle/signal_car_green_std"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data modify entity @s item.components."minecraft:item_model" set value "arnis:vehicle/signal_car_red_std"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data modify entity @s item.components."minecraft:item_model" set value "arnis:vehicle/signal_car_red_amber_std"
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Sets one lamp to what its group shows now.
# Sets one head to what its group shows now: 0 green, 1 amber, 2 red, 3 red and amber; a
# walkers' head 0 red, 1 green.
scoreboard players operation @s arnis.tl = #tl_epoch arnis
execute if entity @s[tag=arnis.tl_a_g] if score #tl_a arnis matches 0 run return run function arnis:traffic/on
execute if entity @s[tag=arnis.tl_a_y] if score #tl_a arnis matches 1 run return run function arnis:traffic/on
execute if entity @s[tag=arnis.tl_a_y] if score #tl_a arnis matches 3 run return run function arnis:traffic/on
execute if entity @s[tag=arnis.tl_a_r] if score #tl_a arnis matches 2..3 run return run function arnis:traffic/on
execute if entity @s[tag=arnis.tl_b_g] if score #tl_b arnis matches 0 run return run function arnis:traffic/on
execute if entity @s[tag=arnis.tl_b_y] if score #tl_b arnis matches 1 run return run function arnis:traffic/on
execute if entity @s[tag=arnis.tl_b_y] if score #tl_b arnis matches 3 run return run function arnis:traffic/on
execute if entity @s[tag=arnis.tl_b_r] if score #tl_b arnis matches 2..3 run return run function arnis:traffic/on
execute if entity @s[tag=arnis.tl_pa_g] if score #tl_pa arnis matches 1 run return run function arnis:traffic/on
execute if entity @s[tag=arnis.tl_pa_r] if score #tl_pa arnis matches 0 run return run function arnis:traffic/on
execute if entity @s[tag=arnis.tl_pb_g] if score #tl_pb arnis matches 1 run return run function arnis:traffic/on
execute if entity @s[tag=arnis.tl_pb_r] if score #tl_pb arnis matches 0 run return run function arnis:traffic/on
function arnis:traffic/off
execute if entity @s[tag=arnis.tl_a] if score #tl_a arnis matches 0 run return run function arnis:traffic/car/green
execute if entity @s[tag=arnis.tl_a] if score #tl_a arnis matches 1 run return run function arnis:traffic/car/amber
execute if entity @s[tag=arnis.tl_a] if score #tl_a arnis matches 2 run return run function arnis:traffic/car/red
execute if entity @s[tag=arnis.tl_a] if score #tl_a arnis matches 3 run return run function arnis:traffic/car/red_amber
execute if entity @s[tag=arnis.tl_b] if score #tl_b arnis matches 0 run return run function arnis:traffic/car/green
execute if entity @s[tag=arnis.tl_b] if score #tl_b arnis matches 1 run return run function arnis:traffic/car/amber
execute if entity @s[tag=arnis.tl_b] if score #tl_b arnis matches 2 run return run function arnis:traffic/car/red
execute if entity @s[tag=arnis.tl_b] if score #tl_b arnis matches 3 run return run function arnis:traffic/car/red_amber
execute if entity @s[tag=arnis.tl_pa] if score #tl_pa arnis matches 0 run return run function arnis:traffic/walk/red
execute if entity @s[tag=arnis.tl_pa] if score #tl_pa arnis matches 1 run return run function arnis:traffic/walk/green
execute if entity @s[tag=arnis.tl_pb] if score #tl_pb arnis matches 0 run return run function arnis:traffic/walk/red
execute if entity @s[tag=arnis.tl_pb] if score #tl_pb arnis matches 1 run return run function arnis:traffic/walk/green

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
execute as @e[type=block_display,tag=arnis.tl_a_g] run function arnis:traffic/off
execute as @e[type=block_display,tag=arnis.tl_a_y] run function arnis:traffic/on
execute as @e[type=item_display,tag=arnis.tl_a] run function arnis:traffic/car/amber
scoreboard players set #tl_a arnis 1
function arnis:traffic/switched
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
execute as @e[type=block_display,tag=arnis.tl_a_r] run function arnis:traffic/off
execute as @e[type=block_display,tag=arnis.tl_a_y] run function arnis:traffic/off
execute as @e[type=block_display,tag=arnis.tl_a_g] run function arnis:traffic/on
execute as @e[type=block_display,tag=arnis.tl_pb_r] run function arnis:traffic/off
execute as @e[type=block_display,tag=arnis.tl_pb_g] run function arnis:traffic/on
execute as @e[type=item_display,tag=arnis.tl_a] run function arnis:traffic/car/green
execute as @e[type=item_display,tag=arnis.tl_pb] run function arnis:traffic/walk/green
scoreboard players set #tl_a arnis 0
scoreboard players set #tl_pb arnis 1
function arnis:traffic/switched
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
execute as @e[type=block_display,tag=arnis.tl_a_y] run function arnis:traffic/on
execute as @e[type=item_display,tag=arnis.tl_a] run function arnis:traffic/car/red_amber
scoreboard players set #tl_a arnis 3
function arnis:traffic/switched
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
execute as @e[type=block_display,tag=arnis.tl_a_y] run function arnis:traffic/off
execute as @e[type=block_display,tag=arnis.tl_a_r] run function arnis:traffic/on
execute as @e[type=item_display,tag=arnis.tl_a] run function arnis:traffic/car/red
scoreboard players set #tl_a arnis 2
function arnis:traffic/switched
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
execute as @e[type=block_display,tag=arnis.tl_pa_g] run function arnis:traffic/off
execute as @e[type=block_display,tag=arnis.tl_pa_r] run function arnis:traffic/on
execute as @e[type=item_display,tag=arnis.tl_pa] run function arnis:traffic/walk/red
scoreboard players set #tl_pa arnis 0
function arnis:traffic/switched
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
execute as @e[type=block_display,tag=arnis.tl_b_g] run function arnis:traffic/off
execute as @e[type=block_display,tag=arnis.tl_b_y] run function arnis:traffic/on
execute as @e[type=item_display,tag=arnis.tl_b] run function arnis:traffic/car/amber
scoreboard players set #tl_b arnis 1
function arnis:traffic/switched
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
execute as @e[type=block_display,tag=arnis.tl_b_r] run function arnis:traffic/off
execute as @e[type=block_display,tag=arnis.tl_b_y] run function arnis:traffic/off
execute as @e[type=block_display,tag=arnis.tl_b_g] run function arnis:traffic/on
execute as @e[type=block_display,tag=arnis.tl_pa_r] run function arnis:traffic/off
execute as @e[type=block_display,tag=arnis.tl_pa_g] run function arnis:traffic/on
execute as @e[type=item_display,tag=arnis.tl_b] run function arnis:traffic/car/green
execute as @e[type=item_display,tag=arnis.tl_pa] run function arnis:traffic/walk/green
scoreboard players set #tl_b arnis 0
scoreboard players set #tl_pa arnis 1
function arnis:traffic/switched
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
execute as @e[type=block_display,tag=arnis.tl_b_y] run function arnis:traffic/on
execute as @e[type=item_display,tag=arnis.tl_b] run function arnis:traffic/car/red_amber
scoreboard players set #tl_b arnis 3
function arnis:traffic/switched
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
execute as @e[type=block_display,tag=arnis.tl_b_y] run function arnis:traffic/off
execute as @e[type=block_display,tag=arnis.tl_b_r] run function arnis:traffic/on
execute as @e[type=item_display,tag=arnis.tl_b] run function arnis:traffic/car/red
scoreboard players set #tl_b arnis 2
function arnis:traffic/switched
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
execute as @e[type=block_display,tag=arnis.tl_pb_g] run function arnis:traffic/off
execute as @e[type=block_display,tag=arnis.tl_pb_r] run function arnis:traffic/on
execute as @e[type=item_display,tag=arnis.tl_pb] run function arnis:traffic/walk/red
scoreboard players set #tl_pb arnis 0
function arnis:traffic/switched
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Every head in view took this switch; one out of view catches up when it comes back.
scoreboard players add #tl_epoch arnis 1
execute as @e[type=block_display,tag=arnis.tl] run scoreboard players operation @s arnis.tl = #tl_epoch arnis
execute as @e[type=item_display,tag=arnis.tl] run scoreboard players operation @s arnis.tl = #tl_epoch arnis
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# One 34 s cycle: east-west roads (a) and north-south roads (b) take turns.
# A head that was out of view at a switch catches up first, so the switch below reaches it too.
execute as @e[type=block_display,tag=arnis.tl] unless score @s arnis.tl = #tl_epoch arnis run function arnis:traffic/catch_up
execute as @e[type=item_display,tag=arnis.tl] unless score @s arnis.tl = #tl_epoch arnis run function arnis:traffic/catch_up
scoreboard players add #tl arnis 1
execute if score #tl arnis matches 680.. run scoreboard players set #tl arnis 0
execute if score #tl arnis matches 0 run function arnis:traffic/phase/a_go
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data modify entity @s item.components."minecraft:item_model" set value "arnis:vehicle/signal_walk_green_std"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data modify entity @s item.components."minecraft:item_model" set value "arnis:vehicle/signal_walk_red_std"
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
$execute positioned $(x) $(y) $(z) run kill @e[type=block_display,tag=arnis.tc$(c),distance=..24]
$execute positioned $(x) $(y) $(z) run kill @e[type=item_display,tag=arnis.tc$(c),distance=..24]
$execute positioned $(x) $(y) $(z) run kill @e[tag=arnis.ts$(c),distance=..32]
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Between point i and the next, a fraction f of the way, facing along the track.
$execute positioned $(x) $(y) $(z) unless loaded ~ ~ ~ run return 0
scoreboard players set #found arnis.train 0
$execute positioned $(x) $(y) $(z) rotated $(h) 0 positioned ^ ^ ^$(f) as @e[type=block_display,tag=arnis.tc$(c),distance=..12] run function arnis:trains/part
$execute positioned $(x) $(y) $(z) rotated $(h) 0 positioned ^ ^ ^$(f) as @e[type=item_display,tag=arnis.tc$(c),distance=..12] run function arnis:trains/part
# Not there yet: it has just come into view, or into the area.
$execute if score #found arnis.train matches 0 positioned $(x) $(y) $(z) rotated $(h) 0 positioned ^ ^ ^$(f) run function arnis:trains/body/$(b) with storage arnis:trains c
$execute if score #found arnis.train matches 0 positioned $(x) $(y) $(z) rotated $(h) 0 positioned ^ ^ ^$(f) as @e[type=block_display,tag=arnis.tc$(c),distance=..0.5] run scoreboard players operation @s arnis.te = #now arnis.train
$execute if score #found arnis.train matches 0 positioned $(x) $(y) $(z) rotated $(h) 0 positioned ^ ^ ^$(f) as @e[type=item_display,tag=arnis.tc$(c),distance=..0.5] run scoreboard players operation @s arnis.te = #now arnis.train
# Places to get on, only where someone could reach them.
$execute positioned $(x) $(y) $(z) rotated $(h) 0 positioned ^ ^ ^$(f) if entity @a[distance=..40] run function arnis:trains/door/$(d) with storage arnis:trains c
Loading
Loading