extends Control var server := "seba-geek.de" var port := "3784" var ws_url := "wss://seba-geek.de/godot/cw-generator-ws/" var IS_DEBUG = false var ws := WebSocketPeer.new() var available_freqs = [] var mmb_self: MultiMorseBanner var mmb_others: Dictionary[String, MultiMorseBanner] class PlayerData: var num: int var color: Color var tone: int func _init(num, color, tone): self.num = num self.color = color self.tone = tone var player_data := [ PlayerData.new(0, Color( 0, 255, 0), 880), PlayerData.new(1, Color(255, 0, 0), 1200), PlayerData.new(2, Color( 0, 0, 255), 600), PlayerData.new(3, Color(255, 0, 255), 500), ] func _ready() -> void: # FIXME: connection handling / reconnect # FIXME: status / error messages # FIXME: randomize default join frquency # FIXME: automatic refresh if not IS_DEBUG: print(ws_url) ws.connect_to_url(ws_url) else: print("ws://%s:%s" % [server, port]) ws.connect_to_url("ws://%s:%s" % [server, port]) func refresh_list() -> void: pass func _process(_delta: float) -> void: ws.poll() var state := ws.get_ready_state() # print("moin ", state) while state == WebSocketPeer.STATE_OPEN and ws.get_available_packet_count(): _handle_packet() if state != WebSocketPeer.STATE_OPEN: print("Error: websocket in state", state) func _handle_packet() -> void: var data := ws.get_packet().get_string_from_utf8() print(data) var parsed: Dictionary = JSON.parse_string(data) if typeof(parsed) != TYPE_DICTIONARY or not parsed.has("type"): return print("parsed ", parsed) match parsed["type"]: "hello": # fetch frequency list on first join _on_refresh_button_pressed() "join": _join_freq(parsed["freq"], parsed["self_id"], parsed["other_players"]) "freq-list": %FreqList.clear() for freq in parsed["freqs"]: var text = "%s MHz (%d present)" % [freq["freq"], freq["players"]] print("Adding ", text) var idx: int = %FreqList.add_item(text) %FreqList.set_item_metadata(idx, freq) "morse-state": var from_player: String = parsed["from_player"] if from_player not in mmb_others: print("Error: Got morse state from unknown player ", from_player) return mmb_others[from_player].set_morse_state(parsed["state"]) "player-joined": var new_player: String = parsed["player"] if new_player in mmb_others: print("Error: got player join message, but player ", new_player, " is already present") return # find free player id var player_n := 1 while true: var found := false for other in mmb_others.values(): if other.num == player_n: print("New player, num ", player_n, " already taken") found = true break if not found: break player_n += 1 make_player(player_n, new_player) "player-left": var player: String = parsed["player"] if player not in mmb_others: print("Error: player not part of freq ", player) return remove_player(parsed["player"]) "leave": %MorseView.hide() mmb_self.set_morse_state(false) for mmb: MultiMorseBanner in mmb_others.values(): mmb.set_morse_state(false) mmb_self = null mmb_others.clear() for child in %PlayerContainer.get_children(): %PlayerContainer.remove_child(child) %ConnectView.show() _: print("Unhandled message: ", parsed["type"]) func _join_freq(freq: String, player_id: String, other_players: Array): for child in %PlayerContainer.get_children(): %PlayerContainer.remove_child(child) mmb_self = make_player(0, player_id) for n in range(other_players.size()): make_player(n + 1, other_players[n]) %FreqLabel.text = "%s MHz" % freq %ConnectView.hide() %MorseView.show() func _on_refresh_button_pressed() -> void: var refresh_cmd := {"cmd": "list", "type": "cw-generator"} var data := JSON.stringify(refresh_cmd) + "\n" ws.send_text(data) func _on_create_button_pressed() -> void: var freq: String = "%.3f" % float(%FrequencyCreator.text) var refresh_cmd := {"cmd": "create", "type": "cw-generator", "freq": freq} var data := JSON.stringify(refresh_cmd) + "\n" ws.send_text(data) func _on_freq_list_join(index: int, at_position: Vector2, mouse_button_index: int) -> void: var meta = %FreqList.get_item_metadata(index) var freq: String = meta["freq"] print("Yop ", index, " metadata ", freq) var join_cmd := {"cmd": "join", "freq": freq, "type": "cw-generator"} ws.send_text(JSON.stringify(join_cmd) + "\n") func make_player(no: int, player_id: String): var pd: PlayerData if no < player_data.size(): pd = player_data[no] else: pd = PlayerData.new(no, Color(randi_range(0, 255), randi_range(0, 255), randi_range(0, 255)), randi_range(440, 440 * 3)) var mmb = MultiMorseBanner.new_banner(pd.num, pd.color, pd.tone) %PlayerContainer.add_child(mmb) mmb_others[player_id] = mmb return mmb func remove_player(player_id: String): mmb_others[player_id].set_morse_state(false) %PlayerContainer.remove_child(mmb_others[player_id]) mmb_others.erase(player_id) func set_morse_state(state: bool): mmb_self.set_morse_state(state) send_data({"cmd": "morse-state", "state": state}) func send_data(data: Dictionary): var text := JSON.stringify(data) + "\n" ws.send_text(text) func _on_morse_button_button_down() -> void: if not mmb_self: return set_morse_state(true) func _on_morse_button_button_up() -> void: if not mmb_self: return set_morse_state(false) func _on_leave_button_pressed() -> void: send_data({"cmd": "leave"})