Signal + RPC Refactoring

This commit is contained in:
Torsten 2026-02-19 21:50:51 +01:00
parent 04f9b570d8
commit df727c4c88
11 changed files with 52 additions and 34 deletions

View file

@ -131,7 +131,7 @@ Verwenden Sie einheitliche Präfixe, um die Quelle des Signals anzugeben (z.B. p
Verwenden Sie Verben in der Vergangenheitsform, um anzuzeigen, dass ein Ereignis stattgefunden hat (z.B. player_moved, ui_buttonPressed, network_connected). Verwenden Sie Verben in der Vergangenheitsform, um anzuzeigen, dass ein Ereignis stattgefunden hat (z.B. player_moved, ui_buttonPressed, network_connected).
RPCs: RPCs:
An den Server gerichtet RPCs beginnen mit src_ und an den Client gerictete RPCs beginnen mit cl_ An den Server gerichtet RPCs beginnen mit srv_ und an den Client gerictete RPCs beginnen mit cl_
Variablen: Variablen:
- snake_case für lokale Variablen und Funktionsnamen (z.B. player_health, calculate_damage). - snake_case für lokale Variablen und Funktionsnamen (z.B. player_health, calculate_damage).
@ -147,7 +147,7 @@ Variablen:
* GameEvents.ui_join_requested.emit(ip_input.text, username, password) * GameEvents.ui_join_requested.emit(ip_input.text, username, password)
* Der NetworkManager des Clients hat das Signal abonniert und startet join_game, das den MultiplayerPeer instanziert. * Der NetworkManager des Clients hat das Signal abonniert und startet join_game, das den MultiplayerPeer instanziert.
* Der NetworkManager des Servers empfängt das Signal _on_player_connected aktiviert auf dem Client * Der NetworkManager des Servers empfängt das Signal _on_player_connected aktiviert auf dem Client
=> client_show_characters.rpc_id(id, []) , was auf dem Client die Charakterliste anzeigt( die aktuell leer ist). => cl_show_characters.rpc_id(id, []) , was auf dem Client die Charakterliste anzeigt( die aktuell leer ist).
In der Charakterliste kann über einen Button ein neuer Charakter angelegt werden. Der Button In der Charakterliste kann über einen Button ein neuer Charakter angelegt werden. Der Button
löst aus: GameEvents.create_character_screen.emit() , der von CharacterCreate abonniert ist, und dort die löst aus: GameEvents.create_character_screen.emit() , der von CharacterCreate abonniert ist, und dort die
Methode show_creation_screen auslöst. Methode show_creation_screen auslöst.

View file

@ -24,11 +24,6 @@ GameEvents="*uid://4xof67e363t4"
ChatManager="*uid://c351ysuym2mdm" ChatManager="*uid://c351ysuym2mdm"
NetworkManager="*uid://tniwwfk5703p" NetworkManager="*uid://tniwwfk5703p"
[debug]
settings/stdout/print_fps=true
settings/stdout/print_gpu_profile=true
[display] [display]
window/size/viewport_width=1280 window/size/viewport_width=1280

View file

@ -1,17 +1,15 @@
extends Node extends Node
@warning_ignore("unused_signal")
signal ui_join_requested(ip: String, username: String, password: String) signal ui_join_requested(ip: String, username: String, password: String)
@warning_ignore("unused_signal")
signal ui_host_requested() signal ui_host_requested()
signal player_area_join_requested(area_key: String) signal player_area_join_requested(area_key: String)
signal ui_area_join_requested(area_key: String) signal ui_area_join_requested(area_key: String)
signal ui_show_characters(characters:Array) signal network_show_characters(characters:Array)
signal ui_show_character_create() signal ui_create_character_screen()
signal ui_character_created(character: CharacterData) signal ui_character_created(character: CharacterData)

View file

@ -5,3 +5,31 @@ var name: String = "Neuer Held"
var level: int = 1 var level: int = 1
var area: String = "keuwin_grasland" var area: String = "keuwin_grasland"
var position: Vector3 = Vector3.ZERO var position: Vector3 = Vector3.ZERO
# Erstellt ein Dictionary – Vector3 bleibt ein Vector3!
func to_dict() -> Dictionary:
return {
"id": id,
"name": name,
"level": level,
"area": area,
"position": position
}
func from_dict(data: Dictionary) -> void:
id = data.get("id", id)
name = data.get("name", name)
level = data.get("level", level)
area = data.get("area", area)
position = data.get("position", position)
## Auf dem Client
#var data = mein_charakter.to_dict()
#update_server_pos.rpc(data)
## Die RPC Funktion
#@rpc("any_peer")
#func update_server_pos(data: Dictionary):
# var server_char = CharacterData.new()
# server_char.from_dict(data)
# print(server_char.position) # Funktioniert sofort als Vector3

View file

@ -1,7 +1,4 @@
extends Area3D extends Area3D
## Definiert, wohin dieses Portal führt und ermöglicht die Interaktion.
## Löst einen RPC an den NetworkManager aus, um einen Area-Wechsel anzufordern.
# Dieser Wert muss einem Schlüssel in NetworkManager.area_paths entsprechen (z.B. "ahnenhalle"). # Dieser Wert muss einem Schlüssel in NetworkManager.area_paths entsprechen (z.B. "ahnenhalle").
@export var target_area_key: String = "" @export var target_area_key: String = ""

View file

@ -1,7 +1,7 @@
extends Node extends Node
# Signal für die UI, um neue Nachrichten anzuzeigen # Signal für die UI, um neue Nachrichten anzuzeigen
signal message_received(sender_name: String, message: String, channel: String) signal network_message_received(sender_name: String, message: String, channel: String)
@rpc("any_peer", "call_remote", "reliable") @rpc("any_peer", "call_remote", "reliable")
func send_message(message: String): func send_message(message: String):
@ -19,8 +19,8 @@ func send_message(message: String):
# Broadcast: Nur an Spieler in der gleichen Area senden (NWN-Style) # Broadcast: Nur an Spieler in der gleichen Area senden (NWN-Style)
for id in NetworkManager.player_area_map: for id in NetworkManager.player_area_map:
if NetworkManager.player_area_map[id] == area: if NetworkManager.player_area_map[id] == area:
rpc_id(id, "receive_message", sender_name, message, "local") cl_receive_message.rpc_id(id, sender_name, message, "local")
@rpc("authority", "call_remote", "reliable") @rpc("authority", "call_remote", "reliable")
func receive_message(sender_name: String, message: String, channel: String): func cl_receive_message(sender_name: String, message: String, channel: String):
message_received.emit(sender_name, message, channel) network_message_received.emit(sender_name, message, channel)

View file

@ -39,13 +39,13 @@ func join_game(ip: String, username: String, password: String):
func _on_player_connected(id): func _on_player_connected(id):
print("Player connected with id:", id) print("Player connected with id:", id)
client_show_characters.rpc_id(id, []) cl_show_characters.rpc_id(id, [])
@rpc("authority", "call_remote", "reliable") @rpc("authority", "call_remote", "reliable")
func client_show_characters(characters): func cl_show_characters(characters):
print("Got client_show_characters") print("Got client_show_characters")
GameEvents.show_characters.emit(characters) GameEvents.network_show_characters.emit(characters)
func _on_player_disconnected(id): func _on_player_disconnected(id):
@ -97,7 +97,7 @@ func change_player_area(id: int, area_key: String):
player_worlds[id] = container_node player_worlds[id] = container_node
# Client anweisen, Szene zu laden # Client anweisen, Szene zu laden
rpc_id(id, "client_load_area", area_key) cl_load_area.rpc_id(id, area_key)
# Avatar auf Server erstellen erfolgt erst wenn Client Vollzug meldet (client_ready_to_spawn) # Avatar auf Server erstellen erfolgt erst wenn Client Vollzug meldet (client_ready_to_spawn)
@ -120,7 +120,7 @@ func client_ready_to_spawn(area_key:String):
@rpc("authority", "call_remote", "reliable") @rpc("authority", "call_remote", "reliable")
func client_load_area(area_key): func cl_load_area(area_key):
print("Client loads area") print("Client loads area")
# Client löscht alte Map, lädt neue lokal in das Root # Client löscht alte Map, lädt neue lokal in das Root
for child in get_children(): for child in get_children():
@ -194,10 +194,10 @@ func _spawn_player_in_world(id, spawn_target_node):
# Wir schicken dem Client eine Info, welchen Node er verfolgen soll # Wir schicken dem Client eine Info, welchen Node er verfolgen soll
# (Da der Name des Player-Nodes die ID ist, weiß der Client welcher seiner ist) # (Da der Name des Player-Nodes die ID ist, weiß der Client welcher seiner ist)
rpc_id(id, "assign_camera_target", str(id)) cl_assign_camera_target.rpc_id(id, str(id))
@rpc("authority", "call_remote", "reliable") @rpc("authority", "call_remote", "reliable")
func assign_camera_target(node_name: String): func cl_assign_camera_target(node_name: String):
# Der Client sucht seinen Player-Node im Baum # Der Client sucht seinen Player-Node im Baum
var p = get_tree().root.find_child(node_name, true, false) var p = get_tree().root.find_child(node_name, true, false)
if p and local_camera: if p and local_camera:
@ -206,7 +206,7 @@ func assign_camera_target(node_name: String):
# var camera = get_viewport().get_camera_3d() # var camera = get_viewport().get_camera_3d()
@rpc("any_peer", "call_remote", "reliable") @rpc("any_peer", "call_remote", "reliable")
func handle_area_change_request(area_key: String): func srv_handle_area_change_request(area_key: String):
var id = multiplayer.get_remote_sender_id() var id = multiplayer.get_remote_sender_id()
if not player_worlds.has(id): return if not player_worlds.has(id): return

View file

@ -63,7 +63,7 @@ func _physics_process(delta):
@rpc("any_peer", "call_remote", "reliable") @rpc("any_peer", "call_remote", "reliable")
func request_move(target: Vector3): func srv_request_move(target: Vector3):
if not multiplayer.is_server(): return if not multiplayer.is_server(): return
#print("Server: Request Move received from client") #print("Server: Request Move received from client")
@ -97,12 +97,12 @@ func _input(event):
if is_instance_valid(collider) and collider.is_in_group("portals"): if is_instance_valid(collider) and collider.is_in_group("portals"):
print("Portal angeklickt. Fordere Area-Wechsel an zu: ", collider.target_area_key) print("Portal angeklickt. Fordere Area-Wechsel an zu: ", collider.target_area_key)
# Sende RPC direkt an den NetworkManager mit dem Ziel des Portals # Sende RPC direkt an den NetworkManager mit dem Ziel des Portals
NetworkManager.handle_area_change_request.rpc_id(1, collider.target_area_key) NetworkManager.srv_handle_area_change_request.rpc_id(1, collider.target_area_key)
return # Wichtig: Aktion ist beendet, nichts weiter tun. return # Wichtig: Aktion ist beendet, nichts weiter tun.
# PRIORITÄT 2 (Fallback): Wir haben etwas anderes getroffen (vermutlich den Boden), also bewegen. # PRIORITÄT 2 (Fallback): Wir haben etwas anderes getroffen (vermutlich den Boden), also bewegen.
var target_position = click_result.position var target_position = click_result.position
request_move.rpc_id(1, target_position) srv_request_move.rpc_id(1, target_position)

View file

@ -37,7 +37,7 @@ func start_test():
print("Simuliere Klick auf: ", target_position) print("Simuliere Klick auf: ", target_position)
# Hier MÜSSEN wir den RPC direkt aufrufen. InputEvent geht nicht. # Hier MÜSSEN wir den RPC direkt aufrufen. InputEvent geht nicht.
player.request_move.rpc_id(1, target_position) # 1 = Server player.server_request_move.rpc_id(1, target_position) # 1 = Server
# Auf Bewegung warten (etwas unsauber, aber für den Moment ok) # Auf Bewegung warten (etwas unsauber, aber für den Moment ok)
await get_tree().create_timer(1.0).timeout # Warte 1 Sekunde await get_tree().create_timer(1.0).timeout # Warte 1 Sekunde

View file

@ -3,7 +3,7 @@ extends Control
@onready var name_line_edit: LineEdit = $NameLineEdit @onready var name_line_edit: LineEdit = $NameLineEdit
func _ready(): func _ready():
GameEvents.ui_show_character_create.connect(show_creation_screen) GameEvents.ui_create_character_screen.connect(show_creation_screen)
func show_creation_screen(): func show_creation_screen():
name_line_edit.text = "" name_line_edit.text = ""

View file

@ -5,7 +5,7 @@ extends Control
var characters: Array[CharacterData] = [] var characters: Array[CharacterData] = []
func _ready(): func _ready():
GameEvents.ui_show_characters.connect(show_list) GameEvents.network_show_characters.connect(show_list)
GameEvents.ui_character_created.connect(character_created) GameEvents.ui_character_created.connect(character_created)
func character_created(character): func character_created(character):
@ -29,7 +29,7 @@ func _on_character_selected(index):
func _on_create_character_button_pressed() -> void: func _on_create_character_button_pressed() -> void:
GameEvents.create_character_screen.emit() GameEvents.ui_create_character_screen.emit()
hide() hide()
# Doubleclick on Character should start area transition # Doubleclick on Character should start area transition