Godot Version
Godot Engine 4.6.3 stable
Question
Hi everyone, I hope you are good now, well, I have a question, I’m creating a multiplayer online game where I’m making an online room system, but it’s not working, because when I connect the second client to the server, the client spawns two instances, one that it’s correct and it works, but the another instance is receiving the inputs and methods of the first instance, that’s not correct, because such as you should know, the client must have an only one instance of their player, no more, besides that instance can’t receive and process events of another instance.
I’m not using MultiplayerSpawner node, because I had a lot of bugs with that node and their functionality, because I prefered using my own multiplayer spawning system.
I’ll share you the following image and my NetworkEvents script (it’s an autoload and it manages the rpc packets of server and client as you can see in the script), the image shows the bug that I explained before, ok?
Thank you for reading this topic and I hope you can help me to fix this bug :3
extends Node
signal show_room_manager
signal hide_room_manager
var authenticated_clients: Dictionary[int, Dictionary] = {}
var rooms: Dictionary = {}
## --------------- SERVER EVENTS ----------------------------
@rpc('any_peer', "call_remote", 'reliable')
func authenticate_client(username: String):
if username.is_empty(): return
var peer_id = multiplayer.get_remote_sender_id()
authenticated_clients[peer_id] = {
'username': username,
'room_id': ""
}
rpc_id(peer_id, "user_authenticated")
@rpc('any_peer')
func create_room():
var peer_id = multiplayer.get_remote_sender_id()
print("[SERVER] create_room llamado por peer: %d" % peer_id)
var room_id = ""
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
for i in range(8):
room_id += chars[randi() % chars.length()]
if multiplayer.is_server():
var room = preload('res://scenes/network/room.tscn').instantiate()
room.name = room_id
room.room_id = room_id
get_node('/root/Rooms').add_child(room)
rooms[room_id] = room
await get_tree().process_frame
var world = room.get_node('World')
if not world: return
world.terrain_seed = randi()
world.set_world_seed()
rpc_id(peer_id, "room_created", room_id)
@rpc("any_peer")
func join_the_room(room_id: String):
var peer_id = multiplayer.get_remote_sender_id()
if multiplayer.is_server():
for room in get_node('/root/Rooms').get_children():
if room.room_id == room_id:
rpc_id(peer_id, "joined_the_room", room_id, room.onlinePlayers.duplicate(), peer_id)
break
@rpc('any_peer')
func replicate_world(room_id: String):
var peer_id = multiplayer.get_remote_sender_id()
if multiplayer.is_server():
for room in get_node('/root/Rooms').get_children():
if room.room_id == room_id:
var world = room.get_node('World')
if not world: break
rpc_id(peer_id, 'world_replicated', room_id, world.terrain_seed)
break
@rpc('any_peer')
func spawn_player(room_id: String):
var peer_id = multiplayer.get_remote_sender_id()
print("[SERVER] spawn_player llamado | peer: %d | room: %s" % [peer_id, room_id])
if multiplayer.is_server():
for room in get_node('/root/Rooms').get_children():
if room.room_id == room_id:
if room.get_node('Players').has_node(str(peer_id)):
return
var player = preload('res://scenes/player.tscn').instantiate()
player.set_multiplayer_authority(peer_id)
player.name = str(peer_id)
player.is_online = true
room.get_node('Players').add_child(player)
var existing_players = room.onlinePlayers.duplicate()
print("[SERVER] spawn_existing_players para peer %d | existentes: %s" % [peer_id, str(existing_players)])
rpc_id(peer_id, 'spawn_existing_players', room_id, existing_players)
room.addPlayerToRoom(peer_id)
rpc_to_room(room.room_id, 'player_spawned', [room.room_id, peer_id])
break
func rpc_to_room(room_id: String, method: String, args: Array):
for room in get_node('/root/Rooms').get_children():
if room.room_id == room_id:
print("[rpc_to_room] method=%s | args=%s | enviando a: %s" % [method, str(args), str(room.onlinePlayers)])
for player_id in room.onlinePlayers:
rpc_id(player_id, method, args)
break
## --------------- CLIENT EVENTS ----------------------------
@rpc('authority')
func user_authenticated():
show_room_manager.emit()
@rpc("authority")
func room_created(room_id: String):
DisplayServer.clipboard_set(room_id)
print("Room ID is copied: %s." % room_id)
@rpc('authority')
func joined_the_room(room_id: String, onlinePlayers: Array, peer_id: int):
print("[joined_the_room] room=%s | onlinePlayers=%s | mi peer=%d" % [room_id, str(onlinePlayers), peer_id])
var room = preload('res://scenes/network/room.tscn').instantiate()
room.name = room_id
room.room_id = room_id
for player_id in onlinePlayers:
if player_id != peer_id:
room.addPlayerToRoom(player_id)
get_node('/root/Rooms').add_child(room)
print("[DEBUG] Hijos de room: ", room.get_children())
print("[DEBUG] ¿Tiene Players?: ", room.has_node('Players'))
hide_room_manager.emit()
rpc_id(1, 'spawn_player', room.room_id)
@rpc('authority')
func world_replicated(room_id: String, seed: int):
for room in get_node('/root/Rooms').get_children():
if room.room_id == room_id:
var world = room.get_node('World')
if not world: break
world.terrain_seed = seed
world.set_world_seed()
break
@rpc('authority')
func player_spawned(data: Array):
var rooms_node = get_node('/root/Rooms')
while not rooms_node.has_node(data[0]):
await get_tree().process_frame
var room = rooms_node.get_node(data[0])
var players_node = room.get_node('Players')
if players_node.has_node(str(data[1])):
print("[CLIENT %d] BLOQUEADO por has_node" % multiplayer.get_unique_id())
return
if players_node.has_node(str(data[1])):
print("[CLIENT %d] BLOQUEADO - peer %d ya existe" % [multiplayer.get_unique_id(), data[1]])
return
print("[player_spawned] hijos ANTES de instanciar: %s" % str(players_node.get_children().map(func(p): return p.name)))
var player = preload('res://scenes/player.tscn').instantiate()
player.set_multiplayer_authority(data[1])
player.name = str(data[1])
player.is_online = true
players_node.add_child(player)
if data[1] not in room.onlinePlayers:
room.onlinePlayers.append(data[1])
rpc_id(1, 'replicate_world', data[0])
@rpc('authority')
func spawn_existing_players(room_id: String, existing_ids: Array):
var rooms_node = get_node('/root/Rooms')
while not rooms_node.has_node(room_id):
await get_tree().process_frame
var room = rooms_node.get_node(room_id)
print("[CLIENT %d] Recibí los spawns: %s" % [multiplayer.get_unique_id(), existing_ids])
if room.room_id == room_id:
var players_node = room.get_node('Players')
for player_id in existing_ids:
print("[CLIENT %d] Instanciando existente con authority: %d" % [multiplayer.get_unique_id(), player_id])
if players_node.has_node(str(player_id)):
continue
var player = preload('res://scenes/player.tscn').instantiate()
player.set_multiplayer_authority(player_id)
player.name = str(player_id)
player.is_online = true
players_node.add_child(player)
room.addPlayerToRoom(player_id)
print("[spawn_existing_players] hijos después: %s" % str(players_node.get_children().map(func(p): return p.name)))
