From 89167b15594f0ddf0004da31ddfcdf7ff1419443 Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Sat, 30 Sep 2023 19:40:07 -0500 Subject: [PATCH] Network merged with Peers. Start of chat. --- hamncheese/Art/chat-circle-dots-fill.svg | 1 + .../Art/chat-circle-dots-fill.svg.import | 37 ++++++++++ hamncheese/Scenes/about.tscn | 1 - hamncheese/Scenes/chat.tscn | 66 +++++++++++++++++ hamncheese/Scenes/main.tscn | 1 + hamncheese/Scenes/manual.tscn | 1 - hamncheese/Scripts/chat.gd | 73 +++++++++++++++++++ hamncheese/Scripts/edge.gd | 2 +- hamncheese/Scripts/main.gd | 40 +++++++--- hamncheese/Scripts/network.gd | 45 ------------ hamncheese/Scripts/peers.gd | 42 +++++++++-- hamncheese/project.godot | 2 +- 12 files changed, 244 insertions(+), 67 deletions(-) create mode 100644 hamncheese/Art/chat-circle-dots-fill.svg create mode 100644 hamncheese/Art/chat-circle-dots-fill.svg.import create mode 100644 hamncheese/Scenes/chat.tscn create mode 100644 hamncheese/Scripts/chat.gd delete mode 100644 hamncheese/Scripts/network.gd diff --git a/hamncheese/Art/chat-circle-dots-fill.svg b/hamncheese/Art/chat-circle-dots-fill.svg new file mode 100644 index 0000000..6a2da9a --- /dev/null +++ b/hamncheese/Art/chat-circle-dots-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/hamncheese/Art/chat-circle-dots-fill.svg.import b/hamncheese/Art/chat-circle-dots-fill.svg.import new file mode 100644 index 0000000..39fbeb6 --- /dev/null +++ b/hamncheese/Art/chat-circle-dots-fill.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ddaddue43x40h" +path="res://.godot/imported/chat-circle-dots-fill.svg-0f6d8e1393ef6af67f741a103fadd3b1.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Art/chat-circle-dots-fill.svg" +dest_files=["res://.godot/imported/chat-circle-dots-fill.svg-0f6d8e1393ef6af67f741a103fadd3b1.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/hamncheese/Scenes/about.tscn b/hamncheese/Scenes/about.tscn index 80f6565..7cb0322 100644 --- a/hamncheese/Scenes/about.tscn +++ b/hamncheese/Scenes/about.tscn @@ -16,7 +16,6 @@ unique_name_in_owner = true title = "About" initial_position = 1 size = Vector2i(200, 200) -visible = false unresizable = true [connection signal="close_requested" from="AboutWindow" to="." method="_on_about_window_close_requested"] diff --git a/hamncheese/Scenes/chat.tscn b/hamncheese/Scenes/chat.tscn new file mode 100644 index 0000000..034e98a --- /dev/null +++ b/hamncheese/Scenes/chat.tscn @@ -0,0 +1,66 @@ +[gd_scene load_steps=3 format=3 uid="uid://75hpb05uvo2f"] + +[ext_resource type="Script" path="res://Scripts/chat.gd" id="1_naye8"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_w4twb"] +bg_color = Color(0, 0, 0, 1) +corner_detail = 1 + +[node name="ChatWindowControl" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_naye8") + +[node name="ChatWindow" type="Window" parent="."] +unique_name_in_owner = true +title = "Chat" +position = Vector2i(0, 36) +size = Vector2i(600, 400) + +[node name="VBoxContainer" type="VBoxContainer" parent="ChatWindow"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="HSplitContainer" type="HSplitContainer" parent="ChatWindow/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +split_offset = 100 + +[node name="ChannelScrollContainer" type="ScrollContainer" parent="ChatWindow/VBoxContainer/HSplitContainer"] +layout_mode = 2 + +[node name="ChannelItemList" type="ItemList" parent="ChatWindow/VBoxContainer/HSplitContainer/ChannelScrollContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="TextScrollContainer" type="ScrollContainer" parent="ChatWindow/VBoxContainer/HSplitContainer"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="ChatRichTextLabel" type="RichTextLabel" parent="ChatWindow/VBoxContainer/HSplitContainer/TextScrollContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_styles/normal = SubResource("StyleBoxFlat_w4twb") +bbcode_enabled = true +fit_content = true +scroll_following = true + +[node name="InputLineEdit" type="LineEdit" parent="ChatWindow/VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 + +[connection signal="close_requested" from="ChatWindow" to="." method="_on_chat_window_close_requested"] +[connection signal="text_submitted" from="ChatWindow/VBoxContainer/InputLineEdit" to="." method="_on_input_line_edit_text_submitted"] diff --git a/hamncheese/Scenes/main.tscn b/hamncheese/Scenes/main.tscn index 4e51dcb..84cd5fd 100644 --- a/hamncheese/Scenes/main.tscn +++ b/hamncheese/Scenes/main.tscn @@ -75,3 +75,4 @@ hide_root = true [connection signal="id_pressed" from="VBoxContainer/HBoxContainer/MenuBar/File" to="." method="_on_file_id_pressed"] [connection signal="id_pressed" from="VBoxContainer/HBoxContainer/MenuBar/Help" to="." method="_on_help_id_pressed"] [connection signal="toggled" from="VBoxContainer/HBoxContainer/OnlineCheckButton" to="." method="_on_online_check_button_toggled"] +[connection signal="button_clicked" from="VBoxContainer/MarginContainer/PeersTree" to="." method="_on_peers_tree_button_clicked"] diff --git a/hamncheese/Scenes/manual.tscn b/hamncheese/Scenes/manual.tscn index 6135017..4b1cbbd 100644 --- a/hamncheese/Scenes/manual.tscn +++ b/hamncheese/Scenes/manual.tscn @@ -16,6 +16,5 @@ unique_name_in_owner = true title = "Manual" initial_position = 1 size = Vector2i(400, 400) -visible = false [connection signal="close_requested" from="ManualWindow" to="." method="_on_manual_window_close_requested"] diff --git a/hamncheese/Scripts/chat.gd b/hamncheese/Scripts/chat.gd new file mode 100644 index 0000000..c0d2a3d --- /dev/null +++ b/hamncheese/Scripts/chat.gd @@ -0,0 +1,73 @@ +# +# Ham'n'Cheese +# Copyright (C) 2023-2024 Scott Duensing +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# + + +extends Control + + +@onready var chat_window = %ChatWindow +@onready var channel_item_list = %ChannelItemList +@onready var chat_rich_text_label = %ChatRichTextLabel +@onready var input_line_edit = %InputLineEdit + + +func _add_channel(channel_name): + channel_item_list.select(channel_item_list.add_item(channel_name)) + + +func append_chat_line(username, message): + chat_rich_text_label.append_text("%s: [color=green]%s[/color]\n" % [_escape_bbcode(username), _escape_bbcode(message)]) + + +func _chat_received(peer, payload): + pass + + +func _clear_channels(): + channel_item_list.clear() + + +func _debug(): + # Fake a chat window. + pass + + +func _escape_bbcode(bbcode_text): + return bbcode_text.replace("[", "[lb]") + + +func _on_chat_window_close_requested(): + chat_window.visible = false + + +func _on_input_line_edit_text_submitted(new_text): + input_line_edit.text = "" + append_chat_line(Settings.user_name_line_edit.text, new_text) + + +func open(peer): + chat_window.visible = true + if peer == null: + _debug() + + +func startup(): + chat_window.visible = false + _clear_channels() + _add_channel("[Everyone]") + Peers.subscribe("chat", _chat_received) diff --git a/hamncheese/Scripts/edge.gd b/hamncheese/Scripts/edge.gd index 9be247f..76b75fb 100644 --- a/hamncheese/Scripts/edge.gd +++ b/hamncheese/Scripts/edge.gd @@ -128,7 +128,7 @@ func start_edge(): _timer.autostart = true _timer.timeout.connect(_on_timer_timeout) var binary = OS.get_user_data_dir() + "/edge" - var arguments = ["--management-password", _password, "-c", _community, "-k", _key, "-l", _supernode + ":" + str(_super_port), "-p"] + var arguments = ["-t", _management_port, "--management-password", _password, "-c", _community, "-k", _key, "-l", _supernode + ":" + str(_super_port), "-p"] if _local_ip != "": arguments.append(_local_ip + ":" + str(_local_port)) else: diff --git a/hamncheese/Scripts/main.gd b/hamncheese/Scripts/main.gd index dfbf558..342f445 100644 --- a/hamncheese/Scripts/main.gd +++ b/hamncheese/Scripts/main.gd @@ -41,6 +41,8 @@ const FILE_ID_EXIT = 2 const HELP_ID_ABOUT = 0 const HELP_ID_MANUAL = 1 +const BUTTON_CHAT = 1 + @onready var online_check_button = %OnlineCheckButton @onready var my_ip_label = %MyIPLabel @@ -73,8 +75,9 @@ func _data_recieved(type, data): func _draw_tree(): # Redraw peer tree. + var icon_chat = load("res://Art/chat-circle-dots-fill.svg") peers_tree.clear() - #***TODO**** We should really be displaying things in columns. + peers_tree.columns = 1 var root = peers_tree.create_item() for peer in Peers.peerArray: if peer["online"] or true: @@ -94,7 +97,9 @@ func _draw_tree(): _: debug = debug + "Unknown" var child = peers_tree.create_item(root) + child.set_meta("peer", peer["uuid"]) child.set_text(0, peer["user"] + " (" + peer["ip"] + ") " + debug) + child.add_button(0, icon_chat, BUTTON_CHAT) func _go_offline(): @@ -140,7 +145,7 @@ func _on_help_id_pressed(id): func _on_online_check_button_toggled(toggled_on): if toggled_on: - Edge.bind("" if Settings.vpn_bind_check_button.is_pressed else Settings.vpn_bind_line_edit, Settings.listening_port_spin_box.value) + Edge.bind("" if Settings.vpn_bind_check_button.is_pressed else Settings.vpn_bind_line_edit.text, Settings.listening_port_spin_box.value) Edge.set_network(Settings.network_name_line_edit.text, Settings.network_password_line_edit.text) Edge.set_supernode(Settings.server_line_edit.text, Settings.server_port_spin_box.value) Edge.set_management(Settings.management_port_spin_box.value, Settings.management_port_spin_box.value + 1) @@ -150,21 +155,30 @@ func _on_online_check_button_toggled(toggled_on): _go_offline() +func _on_peers_tree_button_clicked(item, _column, id, mouse_button_index): + # Handle left click. + if mouse_button_index == 1: + if id == BUTTON_CHAT: + Chat.open(item.get_meta("peer")) + + func _ready(): + About.about_window.visible = false + Manual.manual_window.visible = false Settings.startup() Process.startup(Settings.management_port_spin_box.value + 2) + Peers.startup() + Chat.startup() # If we're on Windows, be sure we're running as Administrator. # This is going to bork up network shares later. if OS.get_name() == "Windows": if !Process.is_elevated(): Process.elevate(OS.get_executable_path()) - Process.shutdown() - Engine.get_main_loop().quit() - Network.startup() - Peers.startup() + _shutdown() Edge.startup() Edge.data_recieved.connect(_data_recieved) Edge.network_died.connect(_network_died) + Chat.open(null) # Debug func _show_exit_dialog(): @@ -173,8 +187,12 @@ func _show_exit_dialog(): message = message + "\n\nThis will disconnect you from the network!\n " var result = await Dialog.confirm("Exit", message) if result: - if online_check_button.button_pressed: - _go_offline() - Process.shutdown() - Edge.shutdown() - Engine.get_main_loop().quit() + _shutdown() + + +func _shutdown(): + if online_check_button.button_pressed: + _go_offline() + Process.shutdown() + Edge.shutdown() + Engine.get_main_loop().quit() diff --git a/hamncheese/Scripts/network.gd b/hamncheese/Scripts/network.gd deleted file mode 100644 index 75ae436..0000000 --- a/hamncheese/Scripts/network.gd +++ /dev/null @@ -1,45 +0,0 @@ -# -# Ham'n'Cheese -# Copyright (C) 2023-2024 Scott Duensing -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# - - -extends Node - - -func _process(_delta): - pass - - -func _received_packet(peer, verb, payload): - match verb: - "status": - for key in payload: - if peer[key] != payload[key]: - peer[key] = payload[key] - peer["refresh"] = true - if !peer["online"]: - Peers.disconnect_peer(peer) - - _: - print("UNKNOWN VERB: ", verb) - print(peer) - print(payload) - print() - - -func startup(): - Peers.peer_received_packet.connect(_received_packet) diff --git a/hamncheese/Scripts/peers.gd b/hamncheese/Scripts/peers.gd index 5cac290..59b1500 100644 --- a/hamncheese/Scripts/peers.gd +++ b/hamncheese/Scripts/peers.gd @@ -20,13 +20,15 @@ extends Node -signal peer_received_packet(peer, verb, payload) +#signal peer_received_packet(peer, verb, payload) -var _tcp := TCPServer.new() -var _basePort : int -var _serverRunning: bool -var _timer : Timer +var _tcp := TCPServer.new() +var _basePort : int +var _serverRunning : bool +var _timer : Timer +var _subscriptions := {} + # This array is of dictionary elements that contain: # "id": Unique ID of this peer (1-254) based on IP. @@ -83,6 +85,15 @@ func _sort_by_ip(a, b): return false +func _status_update(peer, payload): + for key in payload: + if peer[key] != payload[key]: + peer[key] = payload[key] + peer["refresh"] = true + if !peer["online"]: + Peers.disconnect_peer(peer) + + func _tcp_server(): if _tcp.is_listening(): # New inbound connection. @@ -127,8 +138,20 @@ func _tcp_server(): # Data waiting? if peer["tcp"].get_status() == StreamPeerTCP.STATUS_CONNECTED: if peer["tcp"].get_available_bytes() > 0: - var data = peer["tcp"].get_var() - peer_received_packet.emit(peer, data["verb"], data["payload"]) + var data = peer["tcp"].get_var() + var verb = data["verb"] + var payload = data["payload"] + var found = false + for key in _subscriptions: + if key == verb: + found = true + _subscriptions[key].call(peer, payload) + break + if !found: + print("UNKNOWN VERB: ", verb) + print(peer) + print(payload) + print() func clear(): @@ -178,6 +201,7 @@ func start_server(address, portStart, user, uuid): func startup(): _serverRunning = false clear() + subscribe("status", _status_update) _timer = Timer.new() _timer.wait_time = 1 _timer.one_shot = false @@ -195,6 +219,10 @@ func stop_server(): _tcp.stop() +func subscribe(verb: String, callback: Callable): + _subscriptions[verb] = callback + + func update(peersFromCPP: Array): var found var changed = false diff --git a/hamncheese/project.godot b/hamncheese/project.godot index ed0d96d..c0fdae4 100644 --- a/hamncheese/project.godot +++ b/hamncheese/project.godot @@ -28,10 +28,10 @@ Process="*res://Scripts/process.gd" Dialog="*res://Scripts/dialog.gd" Edge="*res://Scripts/edge.gd" Peers="*res://Scripts/peers.gd" -Network="*res://Scripts/network.gd" Settings="*res://Scenes/settings.tscn" About="*res://Scenes/about.tscn" Manual="*res://Scenes/manual.tscn" +Chat="*res://Scenes/chat.tscn" [display]