From a6278cedb1c5e8144c3fcdf005d38b38d6d341ff Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Sun, 28 Jan 2024 22:08:08 +0100 Subject: [PATCH] Added basic chat --- client/Global.gd | 1 + client/network/Chat.gd | 21 ++++++++ client/network/PlayerAdd.gd | 10 ++-- client/network/PlayerMove.gd | 4 ++ client/network/shared/PacketHandler.gd | 1 + client/player/controller/PlayerController.gd | 5 +- client/project.godot | 5 ++ client/ui/ChatBox.gd | 7 +++ client/ui/ChatInput.gd | 21 ++++++++ client/ui/UI.gd | 5 ++ client/ui/UI.tscn | 52 +++++++++++++++----- client/world/Main.tscn | 31 ++++++++++-- client/world/PlayerManager.gd | 3 ++ server/game/Chat.go | 19 +++++++ server/game/Game.go | 11 ++++- server/game/String.go | 7 +++ server/game/packet/packet.go | 1 + 17 files changed, 182 insertions(+), 22 deletions(-) create mode 100644 client/network/Chat.gd create mode 100644 client/ui/ChatBox.gd create mode 100644 client/ui/ChatInput.gd create mode 100644 server/game/Chat.go diff --git a/client/Global.gd b/client/Global.gd index 5f48619..63922c6 100644 --- a/client/Global.gd +++ b/client/Global.gd @@ -6,3 +6,4 @@ var players: PlayerManager var instance_id := OS.get_process_id() % 4 var username := "user%d" % instance_id var account_id: String +var interacting_with_ui: bool diff --git a/client/network/Chat.gd b/client/network/Chat.gd new file mode 100644 index 0000000..9e82ede --- /dev/null +++ b/client/network/Chat.gd @@ -0,0 +1,21 @@ +extends PacketHandler + +signal message_received(message: String) + +func send_message(message: String): + var buffer := StreamPeerBuffer.new() + buffer.put_8(Packet.CHAT) + buffer.put_data(message.to_utf8_buffer()) + %Client.send(buffer.data_array) + +func handle_packet(data: PackedByteArray, _peer: PacketPeer): + var buffer := StreamPeerBuffer.new() + buffer.data_array = data + + var player_id := buffer.get_string() + var player := Global.players.get_player(player_id) + var message := buffer.get_utf8_string() + + print("[%s] %s: %s" % [Global.username, player.name, message]) + message_received.emit("[color=#808080]%s:[/color] %s" % [player.name, message]) + \ No newline at end of file diff --git a/client/network/PlayerAdd.gd b/client/network/PlayerAdd.gd index 8da8e79..93de719 100644 --- a/client/network/PlayerAdd.gd +++ b/client/network/PlayerAdd.gd @@ -25,7 +25,11 @@ func handle_packet(data: PackedByteArray, _peer: PacketPeer): player.position = server_position player.set_character_name(player_name) - if player_id == Global.account_id: +func spawn_player(id: String) -> Player: + var player = player_scene.instantiate() + player.id = id + + if id == Global.account_id: Global.player = player player.controller = PlayerController.new() main_player_spawned.emit(player) @@ -34,9 +38,5 @@ func handle_packet(data: PackedByteArray, _peer: PacketPeer): player.controller.character = player player.add_child(player.controller) - -func spawn_player(id: String) -> Player: - var player = player_scene.instantiate() - player.id = id %Players.add(player) return player diff --git a/client/network/PlayerMove.gd b/client/network/PlayerMove.gd index b404041..39a4ddb 100644 --- a/client/network/PlayerMove.gd +++ b/client/network/PlayerMove.gd @@ -16,6 +16,10 @@ func handle_packet(data: PackedByteArray, _peer: PacketPeer): var z := buffer.get_float() var player := Global.players.get_player(player_id) + + if !player: + return + var controller := player.controller as ProxyController controller.server_position.x = x controller.server_position.z = z diff --git a/client/network/shared/PacketHandler.gd b/client/network/shared/PacketHandler.gd index 7f23e55..95efe59 100644 --- a/client/network/shared/PacketHandler.gd +++ b/client/network/shared/PacketHandler.gd @@ -11,6 +11,7 @@ enum Packet { PLAYER_MOVE = 12, PLAYER_JUMP = 13, PLAYER_ATTACK = 14, + CHAT = 20, } @export var packet_type: Packet diff --git a/client/player/controller/PlayerController.gd b/client/player/controller/PlayerController.gd index 8e52eb1..7ea2bb0 100644 --- a/client/player/controller/PlayerController.gd +++ b/client/player/controller/PlayerController.gd @@ -6,7 +6,10 @@ extends Node var move: Vector2 -func _input(_event): +func _unhandled_input(_event): + if Global.interacting_with_ui: + return + move = Input.get_vector("move_left", "move_right", "move_forward", "move_backward") character.direction = (Global.camera.transform.basis * Vector3(move.x, 0, move.y)) character.direction.y = 0 diff --git a/client/project.godot b/client/project.godot index 5213f76..077f209 100644 --- a/client/project.godot +++ b/client/project.godot @@ -98,6 +98,11 @@ menu={ , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":6,"pressure":0.0,"pressed":false,"script":null) ] } +open_chat={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194309,"key_label":0,"unicode":0,"echo":false,"script":null) +] +} [physics] diff --git a/client/ui/ChatBox.gd b/client/ui/ChatBox.gd new file mode 100644 index 0000000..3c4f27c --- /dev/null +++ b/client/ui/ChatBox.gd @@ -0,0 +1,7 @@ +extends RichTextLabel + +func _ready(): + owner.on_message_received.connect(on_message_received) + +func on_message_received(bbcode: String): + append_text(bbcode + "\n") \ No newline at end of file diff --git a/client/ui/ChatInput.gd b/client/ui/ChatInput.gd new file mode 100644 index 0000000..edac899 --- /dev/null +++ b/client/ui/ChatInput.gd @@ -0,0 +1,21 @@ +extends LineEdit + +signal chat_message_submitted(message: String) + +func _unhandled_input(event): + if Global.interacting_with_ui: + return + + if event.is_action_pressed("open_chat"): + call_deferred("grab_focus") + +func _on_focus_entered(): + Global.interacting_with_ui = true + +func _on_focus_exited(): + Global.interacting_with_ui = false + +func _on_text_submitted(message: String): + (owner as UIManager).chat_message_submitted.emit(message) + text = "" + release_focus() diff --git a/client/ui/UI.gd b/client/ui/UI.gd index ccb08ad..db0bd8c 100644 --- a/client/ui/UI.gd +++ b/client/ui/UI.gd @@ -1,10 +1,15 @@ +class_name UIManager extends Control +signal chat_message_submitted(message: String) + var on_ping_changed: Signal var on_download_changed: Signal var on_upload_changed: Signal +var on_message_received: Signal func _enter_tree(): on_ping_changed = %Ping.changed on_download_changed = %Client.download_changed on_upload_changed = %Client.upload_changed + on_message_received = %Chat.message_received diff --git a/client/ui/UI.tscn b/client/ui/UI.tscn index 80fae70..f2b4809 100644 --- a/client/ui/UI.tscn +++ b/client/ui/UI.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=9 format=3 uid="uid://dagn5bf7ou3sd"] +[gd_scene load_steps=11 format=3 uid="uid://dagn5bf7ou3sd"] [ext_resource type="PackedScene" uid="uid://cch67vqpsmtej" path="res://ui/debug/DebugLabel.tscn" id="1_7s8uu"] [ext_resource type="Script" path="res://ui/UI.gd" id="1_l5b6o"] @@ -6,6 +6,8 @@ [ext_resource type="Script" path="res://ui/debug/PingLabel.gd" id="3_xjdws"] [ext_resource type="Script" path="res://ui/debug/PositionLabel.gd" id="4_beqf6"] [ext_resource type="Script" path="res://ui/debug/VelocityLabel.gd" id="5_8lm6a"] +[ext_resource type="Script" path="res://ui/ChatBox.gd" id="5_vdqtm"] +[ext_resource type="Script" path="res://ui/ChatInput.gd" id="6_70anv"] [ext_resource type="Script" path="res://ui/debug/UploadLabel.gd" id="7_cfnpx"] [ext_resource type="Script" path="res://ui/debug/DownloadLabel.gd" id="8_ogt38"] @@ -35,21 +37,24 @@ script = ExtResource("3_xjdws") anchors_preset = 2 anchor_top = 1.0 anchor_bottom = 1.0 -offset_top = -10.0 -offset_right = 10.0 +offset_top = -134.0 +offset_right = 263.0 grow_vertical = 0 [node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/BottomLeft"] layout_mode = 2 alignment = 2 -[node name="Send" parent="CanvasLayer/BottomLeft/VBoxContainer" instance=ExtResource("1_7s8uu")] +[node name="ChatBox" type="RichTextLabel" parent="CanvasLayer/BottomLeft/VBoxContainer"] layout_mode = 2 -script = ExtResource("7_cfnpx") +size_flags_vertical = 3 +bbcode_enabled = true +scroll_following = true +script = ExtResource("5_vdqtm") -[node name="Receive" parent="CanvasLayer/BottomLeft/VBoxContainer" instance=ExtResource("1_7s8uu")] +[node name="ChatInput" type="LineEdit" parent="CanvasLayer/BottomLeft/VBoxContainer"] layout_mode = 2 -script = ExtResource("8_ogt38") +script = ExtResource("6_70anv") [node name="BottomRight" type="MarginContainer" parent="CanvasLayer"] anchors_preset = 3 @@ -57,8 +62,8 @@ anchor_left = 1.0 anchor_top = 1.0 anchor_right = 1.0 anchor_bottom = 1.0 -offset_left = -79.0 -offset_top = -102.0 +offset_left = -76.0 +offset_top = -54.0 grow_horizontal = 0 grow_vertical = 0 @@ -66,12 +71,37 @@ grow_vertical = 0 layout_mode = 2 alignment = 2 -[node name="Position" parent="CanvasLayer/BottomRight/VBoxContainer" instance=ExtResource("1_7s8uu")] +[node name="Send" parent="CanvasLayer/BottomRight/VBoxContainer" instance=ExtResource("1_7s8uu")] +layout_mode = 2 +alignment = 2 +script = ExtResource("7_cfnpx") + +[node name="Receive" parent="CanvasLayer/BottomRight/VBoxContainer" instance=ExtResource("1_7s8uu")] +layout_mode = 2 +alignment = 2 +script = ExtResource("8_ogt38") + +[node name="TopRight" type="MarginContainer" parent="CanvasLayer"] +anchors_preset = 1 +anchor_left = 1.0 +anchor_right = 1.0 +offset_left = -79.0 +offset_bottom = 102.0 +grow_horizontal = 0 + +[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/TopRight"] +layout_mode = 2 + +[node name="Position" parent="CanvasLayer/TopRight/VBoxContainer" instance=ExtResource("1_7s8uu")] layout_mode = 2 alignment = 2 script = ExtResource("4_beqf6") -[node name="Velocity" parent="CanvasLayer/BottomRight/VBoxContainer" instance=ExtResource("1_7s8uu")] +[node name="Velocity" parent="CanvasLayer/TopRight/VBoxContainer" instance=ExtResource("1_7s8uu")] layout_mode = 2 alignment = 2 script = ExtResource("5_8lm6a") + +[connection signal="focus_entered" from="CanvasLayer/BottomLeft/VBoxContainer/ChatInput" to="CanvasLayer/BottomLeft/VBoxContainer/ChatInput" method="_on_focus_entered"] +[connection signal="focus_exited" from="CanvasLayer/BottomLeft/VBoxContainer/ChatInput" to="CanvasLayer/BottomLeft/VBoxContainer/ChatInput" method="_on_focus_exited"] +[connection signal="text_submitted" from="CanvasLayer/BottomLeft/VBoxContainer/ChatInput" to="CanvasLayer/BottomLeft/VBoxContainer/ChatInput" method="_on_text_submitted"] diff --git a/client/world/Main.tscn b/client/world/Main.tscn index 469c8bf..39d35e4 100644 --- a/client/world/Main.tscn +++ b/client/world/Main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=21 format=3 uid="uid://b40y7iuskv1ar"] +[gd_scene load_steps=24 format=3 uid="uid://b40y7iuskv1ar"] [ext_resource type="Script" path="res://Game.gd" id="1_uxop2"] [ext_resource type="Script" path="res://network/Client.gd" id="2_00qe8"] @@ -12,7 +12,7 @@ [ext_resource type="Script" path="res://network/PlayerJump.gd" id="8_p6kmr"] [ext_resource type="Environment" uid="uid://dixa0yso2s1u3" path="res://world/Environment.tres" id="9_4u3r5"] [ext_resource type="CameraAttributesPractical" uid="uid://b835orxyqq6w5" path="res://camera/CameraAttributes.tres" id="10_4uslp"] -[ext_resource type="PackedScene" uid="uid://tgmbtt7u172g" path="res://world/Arena.blend" id="11_ffpbh"] +[ext_resource type="Script" path="res://network/Chat.gd" id="10_27gvi"] [ext_resource type="PackedScene" uid="uid://hnn0n1xc2qt7" path="res://world/Tree.blend" id="12_x8kho"] [ext_resource type="PackedScene" uid="uid://cb2t7bvvf3gwh" path="res://enemy/slime/Slime.tscn" id="13_hdbbd"] [ext_resource type="PackedScene" uid="uid://dagn5bf7ou3sd" path="res://ui/UI.tscn" id="14_ofk4r"] @@ -20,6 +20,16 @@ [ext_resource type="Script" path="res://world/PlayerManager.gd" id="16_sjldq"] [ext_resource type="Material" uid="uid://ddy5gkw0k16dq" path="res://shader/OutlineMaterial.tres" id="16_srvfy"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_lp0k7"] +albedo_color = Color(0, 0, 0, 1) + +[sub_resource type="BoxMesh" id="BoxMesh_j5fsa"] +material = SubResource("StandardMaterial3D_lp0k7") +size = Vector3(100, 1, 100) + +[sub_resource type="BoxShape3D" id="BoxShape3D_yg2lt"] +size = Vector3(100, 1, 100) + [sub_resource type="QuadMesh" id="QuadMesh_7yiqd"] material = ExtResource("16_srvfy") flip_faces = true @@ -68,6 +78,11 @@ packet_type = 12 script = ExtResource("8_p6kmr") packet_type = 13 +[node name="Chat" type="Node" parent="Client"] +unique_name_in_owner = true +script = ExtResource("10_27gvi") +packet_type = 20 + [node name="Statistics" type="Timer" parent="Client"] autostart = true @@ -83,8 +98,6 @@ script = ExtResource("8_leyo3") environment = ExtResource("9_4u3r5") camera_attributes = ExtResource("10_4uslp") -[node name="Arena" parent="World" instance=ExtResource("11_ffpbh")] - [node name="Trees" type="Node3D" parent="World"] [node name="Tree" parent="World/Trees" instance=ExtResource("12_x8kho")] @@ -104,6 +117,15 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.00829, 1.28057, -1.95247) [node name="Slime3" parent="World/Enemies" instance=ExtResource("13_hdbbd")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.53558, 1.28057, -0.306177) +[node name="Floor" type="MeshInstance3D" parent="World"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.5, 0) +mesh = SubResource("BoxMesh_j5fsa") + +[node name="StaticBody3D" type="StaticBody3D" parent="World/Floor"] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="World/Floor/StaticBody3D"] +shape = SubResource("BoxShape3D_yg2lt") + [node name="Players" type="Node3D" parent="."] unique_name_in_owner = true script = ExtResource("16_sjldq") @@ -146,3 +168,4 @@ mesh = SubResource("QuadMesh_7yiqd") [connection signal="timeout" from="Client/Ping/Timer" to="Client/Ping" method="send_ping"] [connection signal="timeout" from="Client/Login/Timer" to="Client/Login" method="send_login"] [connection signal="timeout" from="Client/Statistics" to="Client" method="update_statistics"] +[connection signal="chat_message_submitted" from="UI" to="Client/Chat" method="send_message"] diff --git a/client/world/PlayerManager.gd b/client/world/PlayerManager.gd index c21ebf1..dfe1dbd 100644 --- a/client/world/PlayerManager.gd +++ b/client/world/PlayerManager.gd @@ -14,5 +14,8 @@ func get_player(id: String) -> Player: return players[id] as Player func remove(id: String): + if !players.has(id): + return + players[id].queue_free() players.erase(id) diff --git a/server/game/Chat.go b/server/game/Chat.go new file mode 100644 index 0000000..8540bb7 --- /dev/null +++ b/server/game/Chat.go @@ -0,0 +1,19 @@ +package game + +import ( + "fmt" + "net" + "server/game/packet" +) + +// Chat is used for chat messages. +func (game *Game) Chat(data []byte, address *net.UDPAddr, server *Server) error { + player := game.players.Get(address) + fmt.Printf("[%s] %s\n", player.Name, string(data)) + + newData := []byte{} + newData = AppendString(newData, player.ID) + newData = AppendStringBytes(newData, data) + game.Broadcast(packet.Chat, newData) + return nil +} diff --git a/server/game/Game.go b/server/game/Game.go index dce248a..2111029 100644 --- a/server/game/Game.go +++ b/server/game/Game.go @@ -30,7 +30,15 @@ func (game *Game) Run() { <-close } -// BroadcastOthers sends the packet to all other players. +// Broadcast sends the packet to all players. +func (game *Game) Broadcast(code byte, data []byte) { + game.players.Each(func(other *Player) bool { + game.server.Send(code, data, other.address) + return true + }) +} + +// BroadcastOthers sends the packet to all other players except the original sender. func (game *Game) BroadcastOthers(code byte, data []byte, exclude *Player) { game.players.Each(func(other *Player) bool { if other == exclude { @@ -55,6 +63,7 @@ func (game *Game) network() { game.server.SetHandler(packet.Login, game.Login) game.server.SetHandler(packet.PlayerMove, game.Move) game.server.SetHandler(packet.PlayerJump, game.Jump) + game.server.SetHandler(packet.Chat, game.Chat) game.server.Run(4242) } diff --git a/server/game/String.go b/server/game/String.go index 0679a0c..c008fc8 100644 --- a/server/game/String.go +++ b/server/game/String.go @@ -8,3 +8,10 @@ func AppendString(data []byte, str string) []byte { data = append(data, []byte(str)...) return data } + +// AppendStringBytes appends the length of the string followed by its contents. +func AppendStringBytes(data []byte, str []byte) []byte { + data = binary.LittleEndian.AppendUint32(data, uint32(len(str))) + data = append(data, str...) + return data +} diff --git a/server/game/packet/packet.go b/server/game/packet/packet.go index 815c8bc..2d7ec2d 100644 --- a/server/game/packet/packet.go +++ b/server/game/packet/packet.go @@ -9,4 +9,5 @@ const ( PlayerMove = 12 PlayerJump = 13 PlayerAttack = 14 + Chat = 20 )