extends Control class_name Main @onready var start_btn : Button = $Mainmenu/Menu/MarginContainer/VBoxContainer/HBoxContainer4/VBoxContainer3/Start @onready var disconnect_btn : Button = $Pausemenu/Menu/MarginContainer/VBoxCurrentLobby/Disconnect @onready var name_edit : = $Mainmenu/Menu/MarginContainer/VBoxContainer/HBoxContainer4/VBoxContainer2/NameEdit @onready var disconnectDialog = $Dialogs/DisconnectDialog @onready var pausemenu = $Pausemenu @onready var mainmenu = $Mainmenu @onready var hud = $Hud @onready var mapsParent: Node3D = $Maps @onready var playersParent: Node3D = $Players var peer = WebSocketMultiplayerPeer.new() var lobby: PackedScene = preload("res://Maps/Lobby/Lobby.tscn") var player: PackedScene = preload("res://actors/Player/player_character.tscn") var mic_capture : AudioEffectOpusChunked var audio_stats : Dictionary[int, Array] # id->[last_number, packetsreceived, packetslost] var packets_sent: int = 0 func _init(): peer.supported_protocols = ["ludus"] Steamworks.initialize() func _ready(): var mic_bus = AudioServer.get_bus_index("Mic") mic_capture = AudioServer.get_bus_effect(mic_bus, 0) await Multiplayer.noray_connected multiplayer.peer_connected.connect(peer_connected) multiplayer.peer_disconnected.connect(peer_disconnected) multiplayer.server_disconnected.connect(close_network) multiplayer.connection_failed.connect(close_network) multiplayer.connected_to_server.connect(connected) # Set the player name according to the system username. Fallback to the path. if Steamworks.is_initiallized: get_tree().auto_accept_quit = false Steamworks.create_lobby() name_edit.text = Steam.getPersonaName() elif false: #TODO: Set text to saved value name_edit.text = "" disableMultiplayer() else: name_edit.text = "Spacebots Player" disableMultiplayer() func _process(_delta: float): if Input.is_action_just_pressed("pause") and playersParent.get_child_count() > 0 and %Settingsmenu.visible == false: if not pausemenu.visible: pausemenu.show() pausemenu.grab_focus() #TODO: fix hud.hide() Input.mouse_mode = Input.MOUSE_MODE_CONFINED else: hud.show() pausemenu.hide() Input.mouse_mode = Input.MOUSE_MODE_CAPTURED if !mic_capture or Multiplayer.playerDict.is_empty(): return while mic_capture.chunk_available(): #var seq_num : PackedByteArray = PackedByteArray() #seq_num.resize(8) #seq_num.encode_u64(0,packets_sent+1) var packet = mic_capture.read_opus_packet(PackedByteArray()) mic_capture.drop_chunk() if multiplayer.multiplayer_peer.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTED: _voice_packet_received.rpc(packet) packets_sent += 1 if (packets_sent % 100) == 0: print("Packets sent: ", packets_sent, " from id ", multiplayer.get_unique_id()) func disableMultiplayer() -> void: $/root/Main/Mainmenu/Menu/MarginContainer/VBoxContainer/HBoxContainer/VBoxMultiplayerDisabled.show() $/root/Main/Mainmenu/Menu/MarginContainer/VBoxContainer/HBoxContainer/VBoxLobbylist.hide() func start_game(): Input.mouse_mode = Input.MOUSE_MODE_CAPTURED mainmenu.hide() start_btn.disabled = true disconnect_btn.disabled = false hud.show() @rpc("authority","call_local","reliable") func changeMap(newMap: PackedScene) -> void: var map = newMap.instantiate() if mapsParent.get_child_count() > 0: if Multiplayer.getCurrentMapLogic().is_connected(StringName("missionLost"),missionLost): Multiplayer.getCurrentMapLogic().disconnect(StringName("missionLost"),missionLost) mapsParent.get_child(0).queue_free() mapsParent.add_child(map) initiatePlayerPosition(map.playerStartPos) Multiplayer.setCurrentMapLogic(map) map.missionLost.connect(missionLost) func initiatePlayerPosition(pos: Vector3) -> void: for p in Multiplayer.playerDict.values(): if p.is_multiplayer_authority(): p.global_position = pos print(p) func missionLost() -> void: changeMap(lobby) func stop_game(): disconnect_btn.disabled = true mainmenu.show() pausemenu.hide() hud.hide() Input.mouse_mode = Input.MOUSE_MODE_CONFINED #Steamworks.stop() var currentMaps = mapsParent.get_children() for child in currentMaps: child.queue_free() var players = playersParent.get_children() for child in players: child.queue_free() await get_tree().process_frame start_btn.disabled = false func close_network(): peer.close() stop_game() disconnectDialog.popup_centered() disconnectDialog.get_ok_button().grab_focus() multiplayer.multiplayer_peer = null Multiplayer.currentMapLogic = null Multiplayer.playerDict = {} Multiplayer.alivePlayerDict = {} Multiplayer.is_host = false func connected(): if Multiplayer.is_host == false: add_player.rpc_id(1, multiplayer.get_unique_id()) func peer_connected(_id): pass #Steamworks.on_peer_add(id) func peer_disconnected(id): print("Disconnected %d" % id) #Steamworks.on_peer_del(id) remove_player.rpc_id(1, id) if(id == 1): on_Disconnect_pressed() func on_Start_pressed(): Multiplayer.host() start_game() changeMap(lobby) add_player(multiplayer.get_unique_id()) func on_Disconnect_pressed(): if Steamworks.lobby_members.size() > 1: Steam.leaveLobby(Steamworks.lobby_id) close_network() func on_Connect(norayid: String): start_btn.disabled = true disconnect_btn.disabled = false start_game() Multiplayer.join(norayid) @rpc("any_peer") func add_player(id): var player_instance: CharacterBody3D = player.instantiate() player_instance.name = str(id) playersParent.add_child(player_instance) @rpc("any_peer") func remove_player(id): if playersParent.get_node(str(id)): playersParent.get_node(str(id)).queue_free() @rpc("any_peer", "unreliable_ordered") func _voice_packet_received(packet: PackedByteArray): var sender_id = multiplayer.get_remote_sender_id() #Stats for printing var sender_stats = audio_stats.get(sender_id, [0,0,0]) if (sender_stats[0]+1 != packet.decode_u32(0)): sender_stats[2]+=1 sender_stats[0]=packet.decode_u64(0) sender_stats[1]+=1 audio_stats.set(sender_id, sender_stats) if (sender_stats[1] % 250) == 0: print("Packets received: ", sender_stats[1], " from id ", sender_id, " Lossrate: ", sender_stats[2], "/", sender_stats[1], "(" , str(100*(sender_stats[2]/sender_stats[1])), "%)") var VoiceChatPlayerOutputNode: AudioStreamPlayer3D = Multiplayer.playerDict.get(sender_id).VoiceChat var OpusStream : AudioStreamOpusChunked = VoiceChatPlayerOutputNode.stream OpusStream.push_opus_packet(packet,0, 0)