M2.4: the server decides online (characters, inventory, stats, death, owned graves, per-player saves); death screen with Respawn after 3 s

This commit is contained in:
Paul Bailey
2026-11-04 19:18:31 +00:00
parent 8e8f10eb96
commit 35a656e996
16 changed files with 1124 additions and 477 deletions

View File

@@ -88,6 +88,7 @@ func bind(p: CharacterBody3D) -> void:
wr.add_child(_worn_btn)
pv.add_child(wr)
player.worn_changed.connect(_refresh)
PlayerNet.cursor_changed.connect(_on_server_cursor)
pp.add_child(pv)
row.add_child(pp)
@@ -142,14 +143,13 @@ func open(chest: Node) -> void:
_refresh()
func close() -> void:
if _cursor != null:
if WorldNet.is_client():
PlayerNet.ask("close") # the server puts the cursor back in our bag
_cursor = null
elif _cursor != null:
var left: int = player.inventory.add(_cursor.id, _cursor.count)
if left > 0 and container != null and is_instance_valid(container):
if WorldNet.is_client():
WorldNet.chest_put(container, {"id": _cursor.id, "count": left})
left = 0
else:
left = container.inventory.add(_cursor.id, left)
left = container.inventory.add(_cursor.id, left)
_cursor = null
if container != null and is_instance_valid(container) and container.inventory.changed.is_connected(_refresh):
container.inventory.changed.disconnect(_refresh)
@@ -193,11 +193,16 @@ func _rebuild_chest() -> void:
_chest_grid.add_child(s)
_chest_slots.append(s)
## Online the server does every click (player_net.gd). Clicks in our own
## bag also happen here straight away, so dragging doesn't wait on the
## network; the server's copy replaces ours once it's caught up.
func _on_player_slot(i: int, right: bool, shift: bool) -> void:
if shift and container != null:
Actions.transfer(player, player.inventory, i, container.inventory, container)
else:
_cursor = player.inventory.click(i, _cursor, right)
if WorldNet.is_client():
PlayerNet.ask("inv_click", [0, i, right])
_refresh()
func _on_chest_slot(i: int, right: bool, shift: bool) -> void:
@@ -206,26 +211,17 @@ func _on_chest_slot(i: int, right: bool, shift: bool) -> void:
if shift:
Actions.transfer(player, container.inventory, i, player.inventory, container)
elif WorldNet.is_client():
# A shared chest: the server does the click (someone else may be in
# it too) and hands back what we're holding.
if WorldNet.chest_busy:
return
var held = _cursor
_cursor = null
WorldNet.chest_click(container, i, held, right, _on_chest_cursor)
# A shared chest (someone else may be in it too): only the server's
# answer counts.
PlayerNet.ask("inv_click", [WorldNet.nid(container), i, right])
else:
_cursor = container.inventory.click(i, _cursor, right)
_refresh()
func _on_chest_cursor(stack) -> void:
if visible:
_cursor = stack
_refresh()
elif stack != null:
# Closed in the meantime: into our bag (or the ground).
var left: int = player.inventory.add(stack.id, stack.count)
if left > 0:
player.get_parent().drop_item(stack.id, left, Transform3D(Basis(), player.global_position + Vector3(0, 0.1, 0)))
## Online: what the server says we're holding.
func _on_server_cursor(stack) -> void:
_cursor = stack if visible else null
_refresh()
func _refresh() -> void:
if player == null: