extends Node3D @export var _player_scene: PackedScene @export var _players: Node3D @export var _chat_panel: Panel @export var _chat_input: LineEdit @export var _chat_history_scroll: ScrollContainer @export var _chat_history: VBoxContainer @export var _chat_panel_inactive: Panel @export var _chat_history_inactive: VBoxContainer @export var _chat_history_scroll_inactive: ScrollContainer ## Things to yet play, so to not repeat ourselves much. const PLAYLIST: Array[String] = [ "res://assets/musics/mod118.ogg", "res://assets/musics/mod147-medley.mp3", "res://assets/musics/mod170-toomanyfuckingdoors.ogg", "res://assets/musics/sho.ogg", ] var _playlist_remaining: Array[String] func _ready() -> void: print("ingame ready") _chat_history_scroll.get_v_scroll_bar().changed.connect( _on_chat_history_scroll_changed.bind(_chat_history_scroll) ) _chat_history_scroll_inactive.get_v_scroll_bar().changed.connect( _on_chat_history_scroll_changed.bind(_chat_history_scroll_inactive) ) if "--on-top" in OS.get_cmdline_args(): get_window().grab_focus() Input.mouse_mode = Input.MOUSE_MODE_CAPTURED if not multiplayer.is_server(): return multiplayer.peer_connected.connect(_add_player) multiplayer.peer_disconnected.connect(_remove_player) for id in multiplayer.get_peers(): _add_player.call_deferred(id) if not OS.has_feature("dedicated_server"): _add_player.call_deferred(1) if not "--join" in OS.get_cmdline_args(): $Soundtrack.finished.connect(_play_new_track) _play_new_track() # TODO: sync what's played for peers, server controlled func _play_new_track(): if _playlist_remaining.size() == 0: _playlist_remaining = PLAYLIST.duplicate() var selection = _playlist_remaining.pick_random() _playlist_remaining.erase(selection) $Soundtrack.stream = load(selection) $Soundtrack.play() func _exit_tree() -> void: if not multiplayer.is_server(): return multiplayer.peer_connected.disconnect(_add_player) multiplayer.peer_disconnected.disconnect(_remove_player) func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed("chat"): get_viewport().set_input_as_handled() _activate_chat() func _input(event: InputEvent) -> void: if event.is_action_pressed("ui_cancel"): get_viewport().set_input_as_handled() _deactivate_chat() func _activate_chat() -> void: _chat_panel.show() _chat_panel_inactive.hide() _chat_input.grab_focus.call_deferred() _players.get_node(str(multiplayer.get_unique_id())).controls_disabled = true Input.mouse_mode = Input.MOUSE_MODE_VISIBLE func _deactivate_chat() -> void: _chat_panel.hide() _chat_panel_inactive.show() _players.get_node(str(multiplayer.get_unique_id())).controls_disabled = false Input.mouse_mode = Input.MOUSE_MODE_CAPTURED func _add_player(id: int) -> void: print("add player %d" % id) var character: Player = _player_scene.instantiate() character.id = id character.name = str(id) _players.add_child(character, true) _set_character_authority.rpc(id) func _remove_player(id: int) -> void: if not _players.has_node(str(id)): return print("remove player %d" % id) _players.get_node(str(id)).queue_free() @rpc("authority", "call_local", "reliable") func _set_character_authority(id: int) -> void: if not _players.has_node(str(id)): return _players.get_node(str(id)).set_multiplayer_authority(id) @rpc("any_peer", "call_local", "reliable", 1) func _submit_chat_message(text: String) -> void: var id := multiplayer.get_remote_sender_id() var username: String = GameState.fetch().player_data[id].username _add_chat_message.rpc(username, text) @rpc("authority", "call_local", "reliable", 1) func _add_chat_message(username: String, text: String) -> void: _chat_history.add_child(_make_chat_message(username, text)) _chat_history_inactive.add_child(_make_chat_message(username, text)) func _on_chat_history_scroll_changed(history: ScrollContainer) -> void: # keep history scrolled to the bottom history.scroll_vertical = history.get_v_scroll_bar().max_value func _make_chat_message(username: String, text: String) -> RichTextLabel: var label := RichTextLabel.new() label.bbcode_enabled = true label.fit_content = true label.append_text("[color=red]%s[/color] %s" % [username.replace("[", "[lb]"), text.replace("[", "[lb]")]) return label func _on_chat_message_submitted(new_text := "") -> void: if _chat_input.text.is_empty(): _deactivate_chat() return _submit_chat_message.rpc_id(1, _chat_input.text) _chat_input.clear() _deactivate_chat()