J3a: the journey on a server. A server per land (Lands: the hub starts land servers on demand over a private link), the cliff tunnel online, crossings with one-time passes, shared characters that remember their land, one clock from the hub; test_net_lands

This commit is contained in:
Paul Bailey
2026-11-06 23:14:11 +00:00
parent 6544862885
commit 85bbed249b
17 changed files with 1050 additions and 28 deletions

View File

@@ -143,8 +143,20 @@ func dig_refusal(stage: int) -> String:
return "It's loose: prop the last stretch first ([E] at its mouth, %d wood)" % PROP_WOOD
return ""
## The face called `uid` (what a player's game asks the server to hit).
func face_by_uid(uid: String) -> Node3D:
return _face if _face != null and is_instance_valid(_face) and String(_face.uid) == uid and not _face.depleted else null
## On a server, everyone playing (and the other lands) hears how the tunnel
## stands after each change.
func _tell_everyone() -> void:
if Net.is_server():
WorldNet.tunnel_state(to_data())
func face_hit(f: Node) -> void:
face_hp = f.hp
if not f.depleted:
_tell_everyone()
func face_broken(f: Node) -> void:
face_hp = FACE_HP
@@ -158,9 +170,14 @@ func face_broken(f: Node) -> void:
else:
Actions.notify.emit("The rock gives. Prop this stretch before you dig on")
_rebuild.call_deferred()
_tell_everyone()
## [E] at the mouth of stretch `k`: sets a timber prop there.
## [E] at the mouth of stretch `k`: sets a timber prop there. (Online, your
## game asks the server, which sets it and tells everyone.)
func set_prop(player: Node, k: int) -> bool:
if world.is_online():
PlayerNet.ask("tunnel_prop", [k])
return true
if k < 1 or k > dug or props[k]:
return false
if player.inventory.count("wood") < PROP_WOOD:
@@ -170,14 +187,22 @@ func set_prop(player: Node, k: int) -> bool:
props[k] = true
Actions.notify.emit("Propped. The next face is safe to dig")
_rebuild.call_deferred()
_tell_everyone()
return true
# --- going in and out ----------------------------------------------------------
## (Online, your game asks the server, which moves you: player_net.gd.)
func go_in(player: Node3D) -> void:
if world.is_online() and player == world.player:
PlayerNet.ask("tunnel_go", ["in"])
return
_move(player, top + Vector3(0, 0.1, 0), Vector3(1, 0, 0))
func go_out(player: Node3D) -> void:
if world.is_online() and player == world.player:
PlayerNet.ask("tunnel_go", ["out"])
return
_move(player, seam_out + Vector3(0, 0.2, 0), -Vector3(seam_at.x, 0.0, seam_at.z).normalized())
func _move(player: Node3D, at: Vector3, facing: Vector3) -> void:
@@ -195,6 +220,7 @@ func to_data() -> Dictionary:
return {"opened": opened, "dug": dug, "face_hp": face_hp, "props": p}
func load_data(d: Dictionary) -> void:
var was := [opened, dug, props.duplicate()]
opened = bool(d.get("opened", false))
dug = clampi(int(d.get("dug", 0)), 0, STRETCHES)
face_hp = float(d.get("face_hp", FACE_HP))
@@ -202,6 +228,11 @@ func load_data(d: Dictionary) -> void:
for k in d.get("props", []):
if int(k) >= 1 and int(k) <= STRETCHES:
props[int(k)] = true
# (Online, a blow on the face only changes how much is left of it: no
# need to rebuild the rock for that.)
if was == [opened, dug, props] and _face != null and is_instance_valid(_face):
_face.hp = clampf(face_hp, 0.5, _face.max_hp)
return
_rebuild()
# --- building it ---------------------------------------------------------------