Network merged with Peers. Start of chat.
This commit is contained in:
parent
27389bdb23
commit
89167b1559
12 changed files with 244 additions and 67 deletions
1
hamncheese/Art/chat-circle-dots-fill.svg
Normal file
1
hamncheese/Art/chat-circle-dots-fill.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M128,24A104,104,0,0,0,36.18,176.88L24.83,210.93a16,16,0,0,0,20.24,20.24l34.05-11.35A104,104,0,1,0,128,24ZM84,140a12,12,0,1,1,12-12A12,12,0,0,1,84,140Zm44,0a12,12,0,1,1,12-12A12,12,0,0,1,128,140Zm44,0a12,12,0,1,1,12-12A12,12,0,0,1,172,140Z"></path></svg>
|
After Width: | Height: | Size: 362 B |
37
hamncheese/Art/chat-circle-dots-fill.svg.import
Normal file
37
hamncheese/Art/chat-circle-dots-fill.svg.import
Normal file
|
@ -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
|
|
@ -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"]
|
||||
|
|
66
hamncheese/Scenes/chat.tscn
Normal file
66
hamncheese/Scenes/chat.tscn
Normal file
|
@ -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"]
|
|
@ -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"]
|
||||
|
|
|
@ -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"]
|
||||
|
|
73
hamncheese/Scripts/chat.gd
Normal file
73
hamncheese/Scripts/chat.gd
Normal file
|
@ -0,0 +1,73 @@
|
|||
#
|
||||
# Ham'n'Cheese
|
||||
# Copyright (C) 2023-2024 Scott Duensing <scott@kangaroopunch.com>
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>
|
||||
#
|
||||
|
||||
|
||||
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)
|
|
@ -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:
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
#
|
||||
# Ham'n'Cheese
|
||||
# Copyright (C) 2023-2024 Scott Duensing <scott@kangaroopunch.com>
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>
|
||||
#
|
||||
|
||||
|
||||
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)
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue