Nichts an schließende oder fehlende Verbindungen senden

NetLink merkt sich die Verbindungen, die es gerade schließt, und
schickt ihnen nichts mehr. Pakete an alle oder an alle außer einem gehen
einzeln an die offenen Verbindungen, statt Godot ein Ziel zu nennen, das
es nicht mehr gibt. Beides löste sonst Fehler in Godot aus, etwa wenn
der Host Figuren weiterreicht, während er einen abgelehnten Gast
hinauswirft. Ein neuer Test mit zwei Gästen deckt das ab.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
Steven Wroblewski
2026-10-01 20:27:07 +02:00
parent 0917450014
commit a43ce66a89
2 changed files with 60 additions and 10 deletions
+28 -7
View File
@@ -20,6 +20,9 @@ var connect_seconds := CONNECT_SECONDS
var _peer: ENetMultiplayerPeer
var _peers: Dictionary[int, bool] = {}
## Connections that close_peer is closing. Nothing more goes to them: Godot
## reports an error for every packet to a connection in that state.
var _closing: Dictionary[int, bool] = {}
var _events: Array[Dictionary] = []
var _connecting := false
var _waited := 0.0
@@ -67,6 +70,7 @@ func _start() -> void:
close()
_peer = ENetMultiplayerPeer.new()
_peers.clear()
_closing.clear()
_peer.peer_connected.connect(_on_connected)
_peer.peer_disconnected.connect(_on_disconnected)
@@ -78,6 +82,7 @@ func _on_connected(peer: int) -> void:
func _on_disconnected(peer: int) -> void:
_peers.erase(peer)
_closing.erase(peer)
_events.append({"type": "disconnected", "peer": peer})
@@ -118,7 +123,7 @@ func poll(delta: float) -> Array[Dictionary]:
## Sends a message of the core to `peer`, reliably and in order. A message
## to a connection that is gone is dropped.
## to a connection that is gone or being closed is dropped.
func send(peer: int, bytes: PackedByteArray) -> void:
_put(peer, bytes, CHANNEL_CORE, MultiplayerPeer.TRANSFER_MODE_RELIABLE)
@@ -130,19 +135,34 @@ func send_figure(peer: int, bytes: PackedByteArray) -> void:
func _put(peer: int, bytes: PackedByteArray, channel: int, mode: MultiplayerPeer.TransferMode) -> void:
if not is_connected_to_peers() or _peers.is_empty():
if not is_connected_to_peers():
return
if peer > 0 and not _peers.has(peer):
return
_peer.set_target_peer(peer)
_peer.set_transfer_channel(channel)
_peer.set_transfer_mode(mode)
_peer.put_packet(bytes)
# One packet per connection, so that no packet goes to a connection that
# is gone or being closed; Godot's own sending to all would.
for target in _targets(peer):
_peer.set_target_peer(target)
_peer.put_packet(bytes)
## The connections a packet for `peer` goes to: that one, every one if
## `peer` is 0, or every one but -`peer` if `peer` is negative. Connections
## that are being closed get nothing.
func _targets(peer: int) -> Array[int]:
var targets: Array[int] = []
for open: int in _peers:
if _closing.has(open):
continue
if peer == 0 or open == peer or (peer < 0 and open != -peer):
targets.append(open)
return targets
## Closes the connection to `peer` once the messages waiting for it are out.
func close_peer(peer: int) -> void:
if _peers.has(peer):
if _peers.has(peer) and not _closing.has(peer):
_closing[peer] = true
_peer.get_peer(peer).peer_disconnect_later()
@@ -151,4 +171,5 @@ func close() -> void:
if is_open():
_peer.close()
_peers.clear()
_closing.clear()
_connecting = false