extends Node ## Wechselt zwischen Menü und laufenden Partien. ## ## Mit `-- server ` läuft dieselbe Datei als Spielserver: kein Menü, kein ## Bild, dafür beliebig viele Räume nebeneinander. ## ## Ein Raum steckt in einem SubViewport mit eigener World3D. Nur so hat jede ## Partie ihren eigenen Physikraum. Die Knotennamen sind auf Server und Client ## gleich - daran hängt das RPC-Ziel. var menu: CanvasLayer var raeume: Node func _ready() -> void: raeume = Node.new() raeume.name = "Raeume" add_child(raeume) Net.game_started.connect(_raum_bauen) Net.room_closed.connect(_raum_abbauen) Net.server_closed.connect(_back_to_menu) var args := OS.get_cmdline_user_args() if args.size() >= 2 and args[0] == "server": if not Net.serve(int(args[1])): get_tree().quit(1) return menu = preload("res://scripts/menu.gd").new() add_child(menu) ## Das Spiel startet im Vollbild; F11 schaltet um. func _unhandled_key_input(event: InputEvent) -> void: if event is InputEventKey and event.pressed and event.keycode == KEY_F11: var full := DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED if full else DisplayServer.WINDOW_MODE_FULLSCREEN) get_viewport().set_input_as_handled() func _raum_bauen(code: String, cfg: Dictionary) -> void: if raeume.has_node(code): return if menu != null: menu.queue_free() menu = null var raum := Node.new() raum.name = code raeume.add_child(raum) var behaelter: Node var sicht: Node if Net.dedicated: # Auf dem Server laufen viele Partien nebeneinander. Jede braucht ihren # eigenen Physikraum, sonst lägen alle Würfel im selben. var c := SubViewportContainer.new() c.stretch = true c.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) var v := SubViewport.new() v.own_world_3d = true behaelter = c sicht = v else: # Der Client hat nur eine Partie und rendert direkt ins Fenster. Ein # SubViewport würde hier nur Auflösung und Kantenglättung kosten. # Die Knotennamen müssen trotzdem gleich heißen - daran hängt das # Ziel jedes RPC. behaelter = Node.new() sicht = Node.new() behaelter.name = "Container" sicht.name = "Viewport" raum.add_child(behaelter) behaelter.add_child(sicht) var game := Node3D.new() game.set_script(preload("res://scripts/game.gd")) game.name = "Game" sicht.add_child(game) game.setup(cfg) func _raum_abbauen(code: String) -> void: var raum := raeume.get_node_or_null(NodePath(code)) if raum != null: raum.queue_free() ## Nur wenn wirklich eine Partie lief. Sonst würde ein Verbindungsabbruch im ## Menü die Szene neu laden und die Meldung dazu gleich wieder wegwerfen. func _back_to_menu() -> void: if raeume.get_child_count() == 0: return get_tree().change_scene_to_file("res://scenes/main.tscn")