OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / mesh_ping_headless.gd

92 lines · gd ref:
extends SceneTree
## Headless mesh-discovery test for the HyperswarmMultiplayerPeer GDExtension —
## the game's EPHEMERAL transport (live avatars / positions / peer count).
##
## mesh-ping.cjs already proved the JS Hyperswarm network path (HyperDHT +
## hole-punch + UDX) works cross-machine. This drives the actual C++ extension
## the same way menu_main._start_mesh does, and reports whether its
## swarm_connection / peer_connected signals fire. It isolates the extension
## from the network.
##
## Run two instances on the SAME topic (same or different host):
##   "$HYPER_TPS_GODOT" --headless --script res://scenes/test/mesh_ping_headless.gd -- server
##   "$HYPER_TPS_GODOT" --headless --script res://scenes/test/mesh_ping_headless.gd -- client
## (server/client only label the log; the extension joins as both server+client.)

const TOPIC_STR := "hyper-tps-mesh-ping-godot"
const BOOTSTRAP_TIMEOUT := 15.0
const RUN_TIME := 45.0

var _peer: MultiplayerPeer
var _kp: Dictionary
var _topic: PackedByteArray
var _state := "init"
var _elapsed := 0.0
var _label := "both"
var _swarm_hits := 0
var _mp_hits := 0


func _initialize() -> void:
	var args := OS.get_cmdline_user_args()
	if args.size() > 0:
		_label = args[0]
	if not ClassDB.class_exists(&"HyperswarmMultiplayerPeer"):
		_p("FATAL: HyperswarmMultiplayerPeer extension NOT loaded")
		quit(1)
		return
	_peer = ClassDB.instantiate(&"HyperswarmMultiplayerPeer")
	_kp = _peer.generate_dht_keypair()
	var pk_hex: String = (_kp["public_key"] as PackedByteArray).hex_encode()
	_p("role=%s pk=%s" % [_label, pk_hex.substr(0, 16)])
	_peer.swarm_connection.connect(_on_swarm_connection)
	_topic = TOPIC_STR.sha256_buffer()
	_p("topic=%s" % _topic.hex_encode().substr(0, 16))
	var err: int = _peer.join_dht(_kp["public_key"], _kp["secret_key"])
	if err != OK:
		_p("FATAL: join_dht err=%d" % err)
		quit(1)
		return
	_state = "bootstrapping"


func _on_swarm_connection(peer_id: int, pk: PackedByteArray, is_client: bool) -> void:
	_swarm_hits += 1
	_p("*** swarm_connection peer_id=%d pk=%s is_client=%s ***" % [peer_id, pk.hex_encode().substr(0, 16), is_client])


func _on_mp_peer_connected(id: int) -> void:
	_mp_hits += 1
	_p("*** multiplayer peer_connected id=%d ***" % id)


func _process(delta: float) -> bool:
	_elapsed += delta
	match _state:
		"bootstrapping":
			var status: Dictionary = _peer.get_dht_status()
			if status.get("bootstrapped", false):
				_p("DHT bootstrapped (%.1fs), swarm_join..." % _elapsed)
				var err: int = _peer.swarm_join(_topic, true, true)
				_p("swarm_join err=%d" % err)
				get_multiplayer().multiplayer_peer = _peer
				get_multiplayer().peer_connected.connect(_on_mp_peer_connected)
				_state = "joined"
			elif _elapsed > BOOTSTRAP_TIMEOUT:
				_p("FATAL: DHT bootstrap timeout")
				return true
		"joined":
			pass
	if _elapsed > RUN_TIME:
		_p("DONE swarm_hits=%d mp_hits=%d  => extension discovery %s" % [
			_swarm_hits, _mp_hits, "WORKS" if _swarm_hits > 0 else "FAILED (no peer found)"])
		return true
	return false


func _p(msg: String) -> void:
	var host := OS.get_environment("HOSTNAME")
	if host == "":
		host = "host"
	print("[godot-mesh %s/%s] %s" % [host, _label, msg])