Godot Version
Godot 4.4.1.
Question
ENetMultiplayerPeer
What I need to do to fix online connection/lobby ?
Buttons aren’t being created in the lobby for client.
Problems with the client connection and I have no idea how to transfer information from host to client ?
extends Node
@export var hint_txt: Label
@export var server_button_scene: PackedScene
@export var no_servers_label: Label
@export var container: VBoxContainer
@export var join_game_back: Button
@export var refresh_btn: Button
var player_model: Node3D = null
var servers: Array[Dictionary] = []
var is_hosting: bool = false
var save_system: Node = null
var SFX: Node = null
var peer: ENetMultiplayerPeer = null
var host_port: int = 9900
var host_ip: String = "127.0.0.1"
@export_group("Game")
@export var map_btn: Button
var online_game_scene: PackedScene
var current_map_index: int
var game_mode_index: int
@export var tex_map_im: TextureRect
@export var modes: Array[GameModeClass] = []
func _ready() -> void:
SFX = Global.find_node_in_group("SFX")
save_system = Global.find_node_in_group("save_system")
save_system.load_options()
save_system.system_s["online"] = true
save_system.save_options(false)
refresh_btn.pressed.connect(Callable(self, "_on_refresh_btn_pressed"))
_update_server_list()
current_map_index = 0
update_map_ui()
func update_map_ui() -> void:
if modes != null:
for i in modes:
i.load_images()
tex_map_im.texture = modes[game_mode_index].map_im[current_map_index]
var localized_string: String = tr("Map {n}").replace("{n}", str(current_map_index + 1))
map_btn.text = localized_string
online_game_scene = load(modes[game_mode_index].map_scene_path + str(current_map_index) + ".tscn")
func next_map() -> void:
current_map_index = (current_map_index + 1) % modes[game_mode_index].map_im.size()
update_map_ui()
func prev_map() -> void:
current_map_index = (current_map_index - 1 + modes[game_mode_index].map_im.size()) % modes[game_mode_index].map_im.size()
update_map_ui()
func _server_in_list(new_server: Dictionary) -> bool:
for s in servers:
if s["ip"] == new_server["ip"] and s["port"] == new_server["port"]:
return true
return false
func _on_Host_pressed() -> void:
create_server(host_port, 6)
func _on_refresh_btn_pressed() -> void:
_update_server_list()
func create_server(port: int = 9900, max_clients: int = 6) -> void:
var mp := get_tree().get_multiplayer()
if mp.multiplayer_peer != null:
mp.multiplayer_peer = null
peer = ENetMultiplayerPeer.new()
var err := peer.create_server(port, max_clients)
if err != OK:
push_error("[DEBUG] PORT IS BUSY (err=%d)" % [port, err])
peer = null
return
mp.multiplayer_peer = peer
is_hosting = true
host_port = port
host_ip = "127.0.0.1"
var server_entry: Dictionary = {"name": "Server", "ip": host_ip, "port": host_port}
if not _server_in_list(server_entry):
servers.append(server_entry)
_update_server_list()
rpc("rpc_add_server", server_entry)
_connect_multiplayer_signals(mp)
load_online_scene(online_game_scene)
func join_server(ip: String, port: int = 9900) -> void:
var mp := get_tree().get_multiplayer()
if mp.multiplayer_peer != null:
mp.multiplayer_peer = null
peer = ENetMultiplayerPeer.new()
var err := peer.create_client(ip, port)
if err != OK:
push_error("No connection %s:%d (err=%d)" % [ip, port, err])
peer = null
return
mp.multiplayer_peer = peer
is_hosting = false
_connect_multiplayer_signals(mp)
func _connect_multiplayer_signals(mp: MultiplayerAPI) -> void:
if not mp.is_connected("peer_connected", Callable(self, "_on_peer_connected")):
mp.peer_connected.connect(Callable(self, "_on_peer_connected"))
if not mp.is_connected("peer_disconnected", Callable(self, "_on_peer_disconnected")):
mp.peer_disconnected.connect(Callable(self, "_on_peer_disconnected"))
if not mp.is_connected("connected_to_server", Callable(self, "_on_connected_to_server")):
mp.connected_to_server.connect(Callable(self, "_on_connected_to_server"))
if not mp.is_connected("connection_failed", Callable(self, "_on_connection_failed")):
mp.connection_failed.connect(Callable(self, "_on_connection_failed"))
if not mp.is_connected("server_disconnected", Callable(self, "_on_server_disconnected")):
mp.server_disconnected.connect(Callable(self, "_on_server_disconnected"))
@rpc("any_peer")
func rpc_add_server(server: Dictionary) -> void:
if not _server_in_list(server):
servers.append(server)
_update_server_list()
func _on_connected_to_server() -> void:
load_online_scene(online_game_scene)
func _on_connection_failed() -> void:
push_error("Соединение не удалось.")
var mp := get_tree().get_multiplayer()
mp.multiplayer_peer = null
peer = null
is_hosting = false
func _on_server_disconnected() -> void:
print("Server disconnected")
_leave_online_scene()
func _on_peer_connected(id: int) -> void:
print("New client:", id)
if is_hosting:
for server_entry in servers:
rpc_id(id, "rpc_add_server", server_entry)
func _on_peer_disconnected(id: int) -> void:
print("peer_disconnected:", id)
if id == 1 and not is_hosting:
print("Host disconnected")
_remove_local_server_entries()
_leave_online_scene()
@rpc("any_peer", "call_local")
func rpc_player_joined(peer_id: int, player_name: String) -> void:
print("Player connected:", player_name, "id:", peer_id)
func _remove_local_server_entries() -> void:
var new_list: Array[Dictionary] = []
for s in servers:
if s.has("ip") and s.has("port"):
if s["ip"] == host_ip and s["port"] == host_port:
continue
new_list.append(s)
servers = new_list
_update_server_list()
func load_online_scene(scene: PackedScene) -> void:
self.visible = false
var err := get_tree().change_scene_to_packed(scene)
if err != OK:
push_error("Cannot load online scene (err=%d)" % err)
return
func _leave_online_scene() -> void:
var mp := get_tree().get_multiplayer()
if mp != null:
mp.multiplayer_peer = null
peer = null
is_hosting = false
_remove_local_server_entries()
var err := get_tree().change_scene_to_file("res://Scene/Menu/4_online.tscn")
if err != OK:
push_error("Cannot load menu: err=%d" % err)
self.visible = true
func _on_default_join_pressed() -> void:
join_server("127.0.0.1", host_port)
func _update_server_list() -> void:
for child in container.get_children():
if child != refresh_btn and child != join_game_back and child != no_servers_label:
child.queue_free()
if servers.size() == 0:
no_servers_label.text = "No Servers"
print("[DEBUG] NO SERVERS")
else:
no_servers_label.text = "Servers: %d" % servers.size()
for server in servers:
var exists: bool = false
for child in container.get_children():
if child is Button and child.text.begins_with(server.get("name","Server")):
exists = true
break
if exists:
continue
var btn: Button = server_button_scene.instantiate() as Button
btn.text = "%s (%s:%d)" % [server.get("name","Server"), server.get("ip","?"), server.get("port",0)]
btn.pressed.connect(Callable(self, "_on_server_button_pressed").bind(server))
container.add_child(btn)
print("Server button added: %s" % btn.text)
func _on_server_button_pressed(server: Dictionary) -> void:
if server.has("ip") and server.has("port"):
join_server(server["ip"], int(server["port"]))