Added basic chat

This commit is contained in:
Eduard Urbach 2024-01-28 22:08:08 +01:00
parent 75801e21fd
commit a6278cedb1
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
17 changed files with 182 additions and 22 deletions

View File

@ -6,3 +6,4 @@ var players: PlayerManager
var instance_id := OS.get_process_id() % 4 var instance_id := OS.get_process_id() % 4
var username := "user%d" % instance_id var username := "user%d" % instance_id
var account_id: String var account_id: String
var interacting_with_ui: bool

21
client/network/Chat.gd Normal file
View File

@ -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])

View File

@ -25,7 +25,11 @@ func handle_packet(data: PackedByteArray, _peer: PacketPeer):
player.position = server_position player.position = server_position
player.set_character_name(player_name) 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 Global.player = player
player.controller = PlayerController.new() player.controller = PlayerController.new()
main_player_spawned.emit(player) main_player_spawned.emit(player)
@ -34,9 +38,5 @@ func handle_packet(data: PackedByteArray, _peer: PacketPeer):
player.controller.character = player player.controller.character = player
player.add_child(player.controller) player.add_child(player.controller)
func spawn_player(id: String) -> Player:
var player = player_scene.instantiate()
player.id = id
%Players.add(player) %Players.add(player)
return player return player

View File

@ -16,6 +16,10 @@ func handle_packet(data: PackedByteArray, _peer: PacketPeer):
var z := buffer.get_float() var z := buffer.get_float()
var player := Global.players.get_player(player_id) var player := Global.players.get_player(player_id)
if !player:
return
var controller := player.controller as ProxyController var controller := player.controller as ProxyController
controller.server_position.x = x controller.server_position.x = x
controller.server_position.z = z controller.server_position.z = z

View File

@ -11,6 +11,7 @@ enum Packet {
PLAYER_MOVE = 12, PLAYER_MOVE = 12,
PLAYER_JUMP = 13, PLAYER_JUMP = 13,
PLAYER_ATTACK = 14, PLAYER_ATTACK = 14,
CHAT = 20,
} }
@export var packet_type: Packet @export var packet_type: Packet

View File

@ -6,7 +6,10 @@ extends Node
var move: Vector2 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") 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 = (Global.camera.transform.basis * Vector3(move.x, 0, move.y))
character.direction.y = 0 character.direction.y = 0

View File

@ -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) , 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] [physics]

7
client/ui/ChatBox.gd Normal file
View File

@ -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")

21
client/ui/ChatInput.gd Normal file
View File

@ -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()

View File

@ -1,10 +1,15 @@
class_name UIManager
extends Control extends Control
signal chat_message_submitted(message: String)
var on_ping_changed: Signal var on_ping_changed: Signal
var on_download_changed: Signal var on_download_changed: Signal
var on_upload_changed: Signal var on_upload_changed: Signal
var on_message_received: Signal
func _enter_tree(): func _enter_tree():
on_ping_changed = %Ping.changed on_ping_changed = %Ping.changed
on_download_changed = %Client.download_changed on_download_changed = %Client.download_changed
on_upload_changed = %Client.upload_changed on_upload_changed = %Client.upload_changed
on_message_received = %Chat.message_received

View File

@ -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="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"] [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/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/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/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/UploadLabel.gd" id="7_cfnpx"]
[ext_resource type="Script" path="res://ui/debug/DownloadLabel.gd" id="8_ogt38"] [ext_resource type="Script" path="res://ui/debug/DownloadLabel.gd" id="8_ogt38"]
@ -35,21 +37,24 @@ script = ExtResource("3_xjdws")
anchors_preset = 2 anchors_preset = 2
anchor_top = 1.0 anchor_top = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
offset_top = -10.0 offset_top = -134.0
offset_right = 10.0 offset_right = 263.0
grow_vertical = 0 grow_vertical = 0
[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/BottomLeft"] [node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/BottomLeft"]
layout_mode = 2 layout_mode = 2
alignment = 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 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 layout_mode = 2
script = ExtResource("8_ogt38") script = ExtResource("6_70anv")
[node name="BottomRight" type="MarginContainer" parent="CanvasLayer"] [node name="BottomRight" type="MarginContainer" parent="CanvasLayer"]
anchors_preset = 3 anchors_preset = 3
@ -57,8 +62,8 @@ anchor_left = 1.0
anchor_top = 1.0 anchor_top = 1.0
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
offset_left = -79.0 offset_left = -76.0
offset_top = -102.0 offset_top = -54.0
grow_horizontal = 0 grow_horizontal = 0
grow_vertical = 0 grow_vertical = 0
@ -66,12 +71,37 @@ grow_vertical = 0
layout_mode = 2 layout_mode = 2
alignment = 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 layout_mode = 2
alignment = 2 alignment = 2
script = ExtResource("4_beqf6") 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 layout_mode = 2
alignment = 2 alignment = 2
script = ExtResource("5_8lm6a") 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"]

View File

@ -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://Game.gd" id="1_uxop2"]
[ext_resource type="Script" path="res://network/Client.gd" id="2_00qe8"] [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="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="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="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://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://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"] [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="Script" path="res://world/PlayerManager.gd" id="16_sjldq"]
[ext_resource type="Material" uid="uid://ddy5gkw0k16dq" path="res://shader/OutlineMaterial.tres" id="16_srvfy"] [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"] [sub_resource type="QuadMesh" id="QuadMesh_7yiqd"]
material = ExtResource("16_srvfy") material = ExtResource("16_srvfy")
flip_faces = true flip_faces = true
@ -68,6 +78,11 @@ packet_type = 12
script = ExtResource("8_p6kmr") script = ExtResource("8_p6kmr")
packet_type = 13 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"] [node name="Statistics" type="Timer" parent="Client"]
autostart = true autostart = true
@ -83,8 +98,6 @@ script = ExtResource("8_leyo3")
environment = ExtResource("9_4u3r5") environment = ExtResource("9_4u3r5")
camera_attributes = ExtResource("10_4uslp") camera_attributes = ExtResource("10_4uslp")
[node name="Arena" parent="World" instance=ExtResource("11_ffpbh")]
[node name="Trees" type="Node3D" parent="World"] [node name="Trees" type="Node3D" parent="World"]
[node name="Tree" parent="World/Trees" instance=ExtResource("12_x8kho")] [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")] [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) 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="."] [node name="Players" type="Node3D" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
script = ExtResource("16_sjldq") 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/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/Login/Timer" to="Client/Login" method="send_login"]
[connection signal="timeout" from="Client/Statistics" to="Client" method="update_statistics"] [connection signal="timeout" from="Client/Statistics" to="Client" method="update_statistics"]
[connection signal="chat_message_submitted" from="UI" to="Client/Chat" method="send_message"]

View File

@ -14,5 +14,8 @@ func get_player(id: String) -> Player:
return players[id] as Player return players[id] as Player
func remove(id: String): func remove(id: String):
if !players.has(id):
return
players[id].queue_free() players[id].queue_free()
players.erase(id) players.erase(id)

19
server/game/Chat.go Normal file
View File

@ -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
}

View File

@ -30,7 +30,15 @@ func (game *Game) Run() {
<-close <-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) { func (game *Game) BroadcastOthers(code byte, data []byte, exclude *Player) {
game.players.Each(func(other *Player) bool { game.players.Each(func(other *Player) bool {
if other == exclude { if other == exclude {
@ -55,6 +63,7 @@ func (game *Game) network() {
game.server.SetHandler(packet.Login, game.Login) game.server.SetHandler(packet.Login, game.Login)
game.server.SetHandler(packet.PlayerMove, game.Move) game.server.SetHandler(packet.PlayerMove, game.Move)
game.server.SetHandler(packet.PlayerJump, game.Jump) game.server.SetHandler(packet.PlayerJump, game.Jump)
game.server.SetHandler(packet.Chat, game.Chat)
game.server.Run(4242) game.server.Run(4242)
} }

View File

@ -8,3 +8,10 @@ func AppendString(data []byte, str string) []byte {
data = append(data, []byte(str)...) data = append(data, []byte(str)...)
return data 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
}

View File

@ -9,4 +9,5 @@ const (
PlayerMove = 12 PlayerMove = 12
PlayerJump = 13 PlayerJump = 13
PlayerAttack = 14 PlayerAttack = 14
Chat = 20
) )