Split client and server

This commit is contained in:
Eduard Urbach 2024-01-24 00:09:50 +01:00
parent 532a1faa21
commit 26c52a00b3
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
59 changed files with 335 additions and 142 deletions

1
.gitignore vendored
View File

@ -16,3 +16,4 @@
!.gitattributes !.gitattributes
!project.godot !project.godot
.godot/ .godot/
server/shared/

View File

@ -1,7 +1,5 @@
extends PacketHandler extends PacketHandler
@export var playerScene: PackedScene
var auth_token: String var auth_token: String
func _ready(): func _ready():
@ -16,7 +14,6 @@ func handle_packet(data: PackedByteArray, _peer: PacketPeer):
print("[Client] Login succeeded.") print("[Client] Login succeeded.")
auth_token = data.slice(1).get_string_from_ascii() auth_token = data.slice(1).get_string_from_ascii()
print("[Client] Auth token: %s" % auth_token) print("[Client] Auth token: %s" % auth_token)
Global.player = spawn_player()
func send_login(): func send_login():
if is_logged_in(): if is_logged_in():
@ -30,8 +27,3 @@ func send_login():
func is_logged_in() -> bool: func is_logged_in() -> bool:
return auth_token != "" return auth_token != ""
func spawn_player() -> Player:
var player = playerScene.instantiate()
%Players.add_child(player)
return player

14
client/network/Spawn.gd Normal file
View File

@ -0,0 +1,14 @@
extends PacketHandler
@export var player_scene: PackedScene
func _ready():
%Client.set_handler(Packet.SPAWN, self)
func handle_packet(_data: PackedByteArray, _peer: PacketPeer):
Global.player = spawn_player()
func spawn_player() -> Player:
var player = player_scene.instantiate()
%Players.add_child(player)
return player

View File

@ -8,7 +8,7 @@
size = Vector3(0.5, 1.6, 0.5) size = Vector3(0.5, 1.6, 0.5)
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_2f50n"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_2f50n"]
radius = 0.23 radius = 0.25
height = 1.6 height = 1.6
[node name="Player" type="CharacterBody3D" node_paths=PackedStringArray("model") groups=["player"]] [node name="Player" type="CharacterBody3D" node_paths=PackedStringArray("model") groups=["player"]]

View File

@ -10,8 +10,8 @@ config_version=5
[application] [application]
config/name="Battle of Mages" config/name="Client"
run/main_scene="res://world/Game.tscn" run/main_scene="res://world/Client.tscn"
config/features=PackedStringArray("4.2", "Forward Plus") config/features=PackedStringArray("4.2", "Forward Plus")
config/icon="res://ui/icon.svg" config/icon="res://ui/icon.svg"
@ -96,3 +96,4 @@ menu={
[physics] [physics]
3d/run_on_separate_thread=true 3d/run_on_separate_thread=true
common/physics_ticks_per_second=100

9
client/shared/Account.gd Normal file
View File

@ -0,0 +1,9 @@
class_name Account
var username: String
var password: String
var position: Vector3
func _init(name: String, pw: String):
username = name
password = pw

View File

@ -4,5 +4,6 @@ enum {
PING = 1, PING = 1,
LOGIN = 2, LOGIN = 2,
LOGOUT = 3, LOGOUT = 3,
MOVE = 10, STATE = 10,
MOVE = 11,
} }

View File

@ -4,4 +4,4 @@ func _ready():
%Ping.connect("changed", on_ping_changed) %Ping.connect("changed", on_ping_changed)
func on_ping_changed(ping): func on_ping_changed(ping):
text = str(snapped(ping * 1000, 0.1)) + " ms" text = str(snapped(ping * 1000, 1)) + " ms"

View File

Before

Width:  |  Height:  |  Size: 950 B

After

Width:  |  Height:  |  Size: 950 B

View File

@ -1,89 +1,67 @@
[gd_scene load_steps=23 format=3 uid="uid://b40y7iuskv1ar"] [gd_scene load_steps=19 format=3 uid="uid://b40y7iuskv1ar"]
[ext_resource type="Script" path="res://world/Game.gd" id="1_xmqq4"] [ext_resource type="Script" path="res://world/Game.gd" id="1_pux6q"]
[ext_resource type="Script" path="res://network/client/Client.gd" id="4_ao4cj"] [ext_resource type="Script" path="res://network/Client.gd" id="2_1ofik"]
[ext_resource type="Script" path="res://network/client/Ping.gd" id="4_vx388"] [ext_resource type="Script" path="res://network/Ping.gd" id="3_4h5la"]
[ext_resource type="PackedScene" uid="uid://2lcnu3dy54lx" path="res://player/Player.tscn" id="5_6c2x8"] [ext_resource type="Script" path="res://network/Login.gd" id="4_k8n1i"]
[ext_resource type="Environment" uid="uid://dixa0yso2s1u3" path="res://world/Environment.tres" id="5_bll74"] [ext_resource type="Script" path="res://network/Spawn.gd" id="5_7n5ie"]
[ext_resource type="Script" path="res://world/Sun.gd" id="5_pf5uw"] [ext_resource type="PackedScene" uid="uid://2lcnu3dy54lx" path="res://player/Player.tscn" id="5_22pku"]
[ext_resource type="CameraAttributesPractical" uid="uid://b835orxyqq6w5" path="res://world/CameraAttributes.tres" id="6_8wfwf"] [ext_resource type="PackedScene" uid="uid://mgyg01l21t0j" path="res://world/World.tscn" id="7_fb4vs"]
[ext_resource type="PackedScene" uid="uid://cch67vqpsmtej" path="res://ui/debug/DebugLabel.tscn" id="6_076g5"] [ext_resource type="Environment" uid="uid://dixa0yso2s1u3" path="res://world/Environment.tres" id="8_5uta8"]
[ext_resource type="Script" path="res://network/client/Login.gd" id="6_augbg"] [ext_resource type="PackedScene" uid="uid://cch67vqpsmtej" path="res://ui/debug/DebugLabel.tscn" id="8_jr2jn"]
[ext_resource type="Script" path="res://ui/debug/FPSLabel.gd" id="7_3qgww"] [ext_resource type="Script" path="res://ui/debug/FPSLabel.gd" id="9_0imyg"]
[ext_resource type="Script" path="res://network/server/Ping.gd" id="7_8mtv7"] [ext_resource type="CameraAttributesPractical" uid="uid://b835orxyqq6w5" path="res://world/CameraAttributes.tres" id="9_w4cdu"]
[ext_resource type="Script" path="res://ui/debug/PingLabel.gd" id="7_kmy1y"] [ext_resource type="Script" path="res://world/Sun.gd" id="10_mlmor"]
[ext_resource type="Script" path="res://network/server/Login.gd" id="8_1y1wq"] [ext_resource type="Script" path="res://ui/debug/PingLabel.gd" id="10_pu6sd"]
[ext_resource type="Script" path="res://ui/debug/PositionLabel.gd" id="8_fge13"] [ext_resource type="Script" path="res://ui/debug/PositionLabel.gd" id="11_k0017"]
[ext_resource type="Script" path="res://ui/debug/VelocityLabel.gd" id="9_f25hg"] [ext_resource type="Script" path="res://ui/debug/VelocityLabel.gd" id="12_dgr41"]
[ext_resource type="Script" path="res://world/Camera.gd" id="9_qfhy4"] [ext_resource type="Script" path="res://world/Camera.gd" id="13_y4waa"]
[ext_resource type="Material" uid="uid://ddy5gkw0k16dq" path="res://shader/OutlineMaterial.tres" id="10_dii8l"] [ext_resource type="Material" uid="uid://ddy5gkw0k16dq" path="res://shader/OutlineMaterial.tres" id="14_hobco"]
[ext_resource type="PackedScene" uid="uid://hnn0n1xc2qt7" path="res://world/Tree.blend" id="15_csh38"]
[ext_resource type="PackedScene" uid="uid://cb2t7bvvf3gwh" path="res://enemy/Slime.tscn" id="16_fuixr"]
[ext_resource type="PackedScene" uid="uid://tgmbtt7u172g" path="res://world/Arena.blend" id="17_q45cd"]
[ext_resource type="Script" path="res://network/server/Server.gd" id="19_bwh1t"]
[sub_resource type="QuadMesh" id="QuadMesh_7yiqd"] [sub_resource type="QuadMesh" id="QuadMesh_7yiqd"]
material = ExtResource("10_dii8l") material = ExtResource("14_hobco")
flip_faces = true flip_faces = true
size = Vector2(2, 2) size = Vector2(2, 2)
[node name="Game" type="Node"] [node name="Main" type="Node"]
script = ExtResource("1_xmqq4") script = ExtResource("1_pux6q")
[node name="Client" type="Node" parent="."] [node name="Client" type="Node" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
script = ExtResource("4_ao4cj") script = ExtResource("2_1ofik")
ip = null
port = null
[node name="Ping" type="Node" parent="Client"] [node name="Ping" type="Node" parent="Client"]
unique_name_in_owner = true unique_name_in_owner = true
script = ExtResource("4_vx388") script = ExtResource("3_4h5la")
[node name="Timer" type="Timer" parent="Client/Ping"] [node name="Timer" type="Timer" parent="Client/Ping"]
autostart = true autostart = true
[node name="Login" type="Node" parent="Client"] [node name="Login" type="Node" parent="Client"]
script = ExtResource("6_augbg") script = ExtResource("4_k8n1i")
playerScene = ExtResource("5_6c2x8")
[node name="Timer" type="Timer" parent="Client/Login"] [node name="Timer" type="Timer" parent="Client/Login"]
wait_time = 10.0 wait_time = 10.0
autostart = true autostart = true
[node name="Server" type="Node" parent="."] [node name="Spawn" type="Node" parent="Client"]
unique_name_in_owner = true script = ExtResource("5_7n5ie")
script = ExtResource("19_bwh1t") player_scene = ExtResource("5_22pku")
[node name="Ping" type="Node" parent="Server"]
script = ExtResource("7_8mtv7")
[node name="Login" type="Node" parent="Server"]
script = ExtResource("8_1y1wq")
[node name="Players" type="Node3D" parent="."] [node name="Players" type="Node3D" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
[node name="Enemies" type="Node3D" parent="."] [node name="World" parent="." instance=ExtResource("7_fb4vs")]
[node name="Slime" parent="Enemies" instance=ExtResource("16_fuixr")] [node name="Sun" type="DirectionalLight3D" parent="World"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.53558, 1.28057, -3.79687) transform = Transform3D(0.984808, 0.122788, -0.122788, 0, 0.707107, 0.707107, 0.173648, -0.696364, 0.696364, 0, 10, 0)
shadow_enabled = true
directional_shadow_mode = 0
script = ExtResource("10_mlmor")
[node name="Slime2" parent="Enemies" instance=ExtResource("16_fuixr")] [node name="Environment" type="WorldEnvironment" parent="World"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.00829, 1.28057, -1.95247) environment = ExtResource("8_5uta8")
camera_attributes = ExtResource("9_w4cdu")
[node name="Slime3" parent="Enemies" instance=ExtResource("16_fuixr")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.53558, 1.28057, -0.306177)
[node name="Objects" type="Node3D" parent="."]
[node name="Tree" parent="Objects" instance=ExtResource("15_csh38")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5.11323, 0, -4.64839)
[node name="Tree2" parent="Objects" instance=ExtResource("15_csh38")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5.11323, 0, 5.35161)
[node name="Arena" parent="Objects" instance=ExtResource("17_q45cd")]
[node name="UI" type="Control" parent="."] [node name="UI" type="Control" parent="."]
layout_mode = 3 layout_mode = 3
@ -98,13 +76,13 @@ offset_bottom = 50.0
[node name="VBoxContainer" type="VBoxContainer" parent="UI/CanvasLayer/TopLeftMargin"] [node name="VBoxContainer" type="VBoxContainer" parent="UI/CanvasLayer/TopLeftMargin"]
layout_mode = 2 layout_mode = 2
[node name="FPS" parent="UI/CanvasLayer/TopLeftMargin/VBoxContainer" instance=ExtResource("6_076g5")] [node name="FPS" parent="UI/CanvasLayer/TopLeftMargin/VBoxContainer" instance=ExtResource("8_jr2jn")]
layout_mode = 2 layout_mode = 2
script = ExtResource("7_3qgww") script = ExtResource("9_0imyg")
[node name="Ping" parent="UI/CanvasLayer/TopLeftMargin/VBoxContainer" instance=ExtResource("6_076g5")] [node name="Ping" parent="UI/CanvasLayer/TopLeftMargin/VBoxContainer" instance=ExtResource("8_jr2jn")]
layout_mode = 2 layout_mode = 2
script = ExtResource("7_kmy1y") script = ExtResource("10_pu6sd")
[node name="BottomLeftMargin" type="MarginContainer" parent="UI/CanvasLayer"] [node name="BottomLeftMargin" type="MarginContainer" parent="UI/CanvasLayer"]
anchors_preset = 2 anchors_preset = 2
@ -117,13 +95,13 @@ grow_vertical = 0
[node name="VBoxContainer" type="VBoxContainer" parent="UI/CanvasLayer/BottomLeftMargin"] [node name="VBoxContainer" type="VBoxContainer" parent="UI/CanvasLayer/BottomLeftMargin"]
layout_mode = 2 layout_mode = 2
[node name="Position" parent="UI/CanvasLayer/BottomLeftMargin/VBoxContainer" instance=ExtResource("6_076g5")] [node name="Position" parent="UI/CanvasLayer/BottomLeftMargin/VBoxContainer" instance=ExtResource("8_jr2jn")]
layout_mode = 2 layout_mode = 2
script = ExtResource("8_fge13") script = ExtResource("11_k0017")
[node name="Velocity" parent="UI/CanvasLayer/BottomLeftMargin/VBoxContainer" instance=ExtResource("6_076g5")] [node name="Velocity" parent="UI/CanvasLayer/BottomLeftMargin/VBoxContainer" instance=ExtResource("8_jr2jn")]
layout_mode = 2 layout_mode = 2
script = ExtResource("9_f25hg") script = ExtResource("12_dgr41")
[node name="Viewport" type="SubViewportContainer" parent="."] [node name="Viewport" type="SubViewportContainer" parent="."]
texture_filter = 1 texture_filter = 1
@ -148,7 +126,7 @@ current = true
fov = 90.0 fov = 90.0
size = 10.0 size = 10.0
far = 100.0 far = 100.0
script = ExtResource("9_qfhy4") script = ExtResource("13_y4waa")
center = NodePath("..") center = NodePath("..")
follow_speed = 5.0 follow_speed = 5.0
@ -157,15 +135,5 @@ unique_name_in_owner = true
extra_cull_margin = 16384.0 extra_cull_margin = 16384.0
mesh = SubResource("QuadMesh_7yiqd") mesh = SubResource("QuadMesh_7yiqd")
[node name="Sun" type="DirectionalLight3D" parent="Viewport/SubViewport"]
transform = Transform3D(0.984808, 0.122788, -0.122788, 0, 0.707107, 0.707107, 0.173648, -0.696364, 0.696364, 0, 10, 0)
shadow_enabled = true
directional_shadow_mode = 0
script = ExtResource("5_pf5uw")
[node name="Environment" type="WorldEnvironment" parent="Viewport/SubViewport"]
environment = ExtResource("5_bll74")
camera_attributes = ExtResource("6_8wfwf")
[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"]

5
client/world/Sun.gd Normal file
View File

@ -0,0 +1,5 @@
@tool
extends DirectionalLight3D
# func _process(_delta):
# (%PostProcessing as MeshInstance3D).mesh.surface_get_material(0).set_shader_parameter("light_direction", -global_basis.z)

28
client/world/World.tscn Normal file
View File

@ -0,0 +1,28 @@
[gd_scene load_steps=4 format=3 uid="uid://mgyg01l21t0j"]
[ext_resource type="PackedScene" uid="uid://tgmbtt7u172g" path="res://world/Arena.blend" id="1_1sh4g"]
[ext_resource type="PackedScene" uid="uid://hnn0n1xc2qt7" path="res://world/Tree.blend" id="2_lunhk"]
[ext_resource type="PackedScene" uid="uid://cb2t7bvvf3gwh" path="res://enemy/Slime.tscn" id="3_uuodv"]
[node name="World" type="Node3D"]
[node name="Arena" parent="." instance=ExtResource("1_1sh4g")]
[node name="Trees" type="Node3D" parent="."]
[node name="Tree" parent="Trees" instance=ExtResource("2_lunhk")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5.11323, 0, -4.64839)
[node name="Tree2" parent="Trees" instance=ExtResource("2_lunhk")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5.11323, 0, 5.35161)
[node name="Enemies" type="Node3D" parent="."]
[node name="Slime" parent="Enemies" instance=ExtResource("3_uuodv")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.53558, 1.28057, -3.79687)
[node name="Slime2" parent="Enemies" instance=ExtResource("3_uuodv")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.00829, 1.28057, -1.95247)
[node name="Slime3" parent="Enemies" instance=ExtResource("3_uuodv")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.53558, 1.28057, -0.306177)

View File

@ -1,6 +0,0 @@
class_name Account
var password: String
func _init(pw: String):
password = pw

View File

@ -5,6 +5,11 @@ var address: String
var last_packet: int var last_packet: int
var auth_token: String var auth_token: String
var account: Account var account: Account
var player: Player
func _init(p: PacketPeerUDP, a: String):
peer = p
address = a
func is_logged_in() -> bool: func is_logged_in() -> bool:
return auth_token != "" return auth_token != ""

12
server/Database.gd Normal file
View File

@ -0,0 +1,12 @@
extends Node
var accounts := {
"user1": Account.new("user1", "password"),
"user2": Account.new("user2", "password"),
}
func get_account(username: String):
if !accounts.has(username):
return null
return accounts[username]

View File

@ -1,3 +1,4 @@
class_name Server
extends NetworkNode extends NetworkNode
## Port number. ## Port number.
@ -10,7 +11,6 @@ extends NetworkNode
@export var max_pending_connections := 4096 @export var max_pending_connections := 4096
var server := UDPServer.new() var server := UDPServer.new()
var last_statistics := Time.get_ticks_msec()
var clients := {} var clients := {}
var packet_count := 0 var packet_count := 0
var now := 0 var now := 0
@ -19,15 +19,19 @@ func _init():
super._init() super._init()
server.set_max_pending_connections(max_pending_connections) server.set_max_pending_connections(max_pending_connections)
server.listen(port) server.listen(port)
Performance.add_custom_monitor("Server/Clients", get_client_count)
Performance.add_custom_monitor("Server/Packets", get_packet_count)
func _process(_delta): func _process(_delta):
server.poll() server.poll()
func _physics_process(_delta):
now = Time.get_ticks_msec() now = Time.get_ticks_msec()
# Accept new connections # Accept new connections
while server.is_connection_available(): while server.is_connection_available():
var peer: PacketPeerUDP = server.take_connection() var peer := server.take_connection()
peer_to_client(peer).last_packet = now peer_to_client(peer)
# Process packets from clients # Process packets from clients
for address in clients: for address in clients:
@ -35,42 +39,60 @@ func _process(_delta):
var peer = client.peer var peer = client.peer
while peer.get_available_packet_count() > 0: while peer.get_available_packet_count() > 0:
client.last_packet = now
var packet = peer.get_packet() var packet = peer.get_packet()
handle_packet(packet, peer) handle_packet(packet, peer)
client.last_packet = now
packet_count += 1 packet_count += 1
# Show statistics # Disconnect
if now > last_statistics + 1000:
for address in clients.keys(): for address in clients.keys():
var last_packet_time = clients[address].last_packet var client = clients[address]
var last_packet_time = client.last_packet
if now - last_packet_time > timeout: if now - last_packet_time > timeout:
peer_disconnected(address) peer_disconnected(client)
clients.erase(address) clients.erase(address)
print("[Server] %d clients | %d packets" % [clients.size(), packet_count]) func broadcast(packet: PackedByteArray):
for address in clients:
clients[address].peer.put_packet(packet)
func broadcast_others(packet: PackedByteArray, exclude: Client):
for address in clients:
var client = clients[address]
if client == exclude:
continue
client.peer.put_packet(packet)
func get_client_count() -> int:
return clients.size()
func get_packet_count() -> int:
var tmp := packet_count
packet_count = 0 packet_count = 0
last_statistics = Time.get_ticks_msec() return tmp
func peer_address(peer: PacketPeerUDP): func peer_address(peer: PacketPeerUDP):
return "%s:%d" % [peer.get_packet_ip(), peer.get_packet_port()] return "%s:%d" % [peer.get_packet_ip(), peer.get_packet_port()]
func peer_connected(c: Client):
print("[%s] Connected." % c.address)
func peer_disconnected(c: Client):
print("[%s] Disconnected." % c.address)
if c.player:
c.player.queue_free()
func peer_to_client(peer: PacketPeerUDP) -> Client: func peer_to_client(peer: PacketPeerUDP) -> Client:
var address = peer_address(peer) var address = peer_address(peer)
if !clients.has(address): if !clients.has(address):
var client = Client.new() var client = Client.new(peer, address)
client.peer = peer
client.address = address
clients[address] = client clients[address] = client
peer_connected(client) peer_connected(client)
return client return client
return clients[address] return clients[address]
func peer_connected(c: Client):
print("[Server] Connected: ", c.address)
func peer_disconnected(c: Client):
print("[Server] Disconnected: ", c.address)

27
server/Server.tscn Normal file
View File

@ -0,0 +1,27 @@
[gd_scene load_steps=6 format=3 uid="uid://b0e7n717sqeo6"]
[ext_resource type="Script" path="res://Database.gd" id="1_58s18"]
[ext_resource type="Script" path="res://Server.gd" id="1_gwiwx"]
[ext_resource type="Script" path="res://handler/Ping.gd" id="3_l2i5g"]
[ext_resource type="Script" path="res://handler/Login.gd" id="4_7aotg"]
[ext_resource type="PackedScene" uid="uid://148x2hp1hjq0" path="res://player/Player.tscn" id="5_26wo2"]
[node name="Main" type="Node"]
[node name="Server" type="Node" parent="."]
unique_name_in_owner = true
script = ExtResource("1_gwiwx")
[node name="Database" type="Node" parent="."]
unique_name_in_owner = true
script = ExtResource("1_58s18")
[node name="Ping" type="Node" parent="."]
script = ExtResource("3_l2i5g")
[node name="Login" type="Node" parent="."]
script = ExtResource("4_7aotg")
player_scene = ExtResource("5_26wo2")
[node name="Players" type="Node3D" parent="."]
unique_name_in_owner = true

3
server/grid/Cell.gd Normal file
View File

@ -0,0 +1,3 @@
class_name Cell
var player_list := [] as Array[Player]

31
server/grid/Grid.gd Normal file
View File

@ -0,0 +1,31 @@
extends Node
## Width of the grid in cells.
const width := 100
## Height of the grid in cells.
const height := 100
## The size of a single cell.
const cell_size := 10.0
var cells: Array[Cell]
func _init():
cells.resize(width * height)
for i in cells.size():
cells[i] = Cell.new()
func notify_cell_changed(player: Player, old_pos: Vector2i, new_pos: Vector2i):
print(player.name, " cell changed! ", old_pos, " ", new_pos)
add_player(player, new_pos)
remove_player(player, old_pos)
func add_player(player: Player, coords: Vector2i):
var cell := cells[coords.x + coords.y * height]
cell.player_list.append(player)
func remove_player(player: Player, coords: Vector2i):
var cell := cells[coords.x + coords.y * height]
cell.player_list.erase(player)

View File

@ -5,10 +5,8 @@ enum {
FAIL = 1, FAIL = 1,
} }
var accounts := { ## Player scene instantiated for each client.
"user1": Account.new("password"), @export var player_scene: PackedScene
"user2": Account.new("password"),
}
func _ready(): func _ready():
%Server.set_handler(Packet.LOGIN, self) %Server.set_handler(Packet.LOGIN, self)
@ -23,33 +21,45 @@ func handle_packet(data: PackedByteArray, peer: PacketPeer):
var login_request = JSON.parse_string(data_string) var login_request = JSON.parse_string(data_string)
if login_request.size() < 2: if login_request.size() < 2:
fail_login(peer) login_fail(peer)
return return
var username = login_request[0] var username = login_request[0]
var password = login_request[1] var password = login_request[1]
var account = %Database.get_account(username)
if !accounts.has(username): if account == null || account.password != password:
fail_login(peer) login_fail(peer)
return
if accounts[username].password != password:
fail_login(peer)
return return
client.auth_token = generate_auth_token() client.auth_token = generate_auth_token()
client.account = account
spawn_player(client)
login_success(peer, client.auth_token)
func spawn_player(client: Client):
var player := player_scene.instantiate()
player.client = client
player.server = %Server
player.name = client.address
client.player = player
%Players.add_child(player)
func generate_auth_token() -> String:
var crypto = Crypto.new()
var buffer = crypto.generate_random_bytes(32)
return Marshalls.raw_to_base64(buffer)
func login_success(peer: PacketPeer, auth_token: String):
var buffer := StreamPeerBuffer.new() var buffer := StreamPeerBuffer.new()
buffer.put_8(Packet.LOGIN) buffer.put_8(Packet.LOGIN)
buffer.put_8(SUCCESS) buffer.put_8(SUCCESS)
buffer.put_data(client.auth_token.to_ascii_buffer()) buffer.put_data(auth_token.to_ascii_buffer())
peer.put_packet(buffer.data_array) peer.put_packet(buffer.data_array)
func fail_login(peer: PacketPeer): func login_fail(peer: PacketPeer):
var buffer := StreamPeerBuffer.new() var buffer := StreamPeerBuffer.new()
buffer.put_8(Packet.LOGIN) buffer.put_8(Packet.LOGIN)
buffer.put_8(FAIL) buffer.put_8(FAIL)
peer.put_packet(buffer.data_array) peer.put_packet(buffer.data_array)
func generate_auth_token() -> String:
return "secret"

View File

@ -11,4 +11,3 @@ func handle_packet(data: PackedByteArray, peer: PacketPeer):
buffer.put_8(data[0]) buffer.put_8(data[0])
peer.put_packet(buffer.data_array) peer.put_packet(buffer.data_array)

24
server/player/Player.gd Normal file
View File

@ -0,0 +1,24 @@
class_name Player
extends CharacterBody3D
var client: Client
var server: Server
var cell: Vector2i
func _ready():
print("Server player spawned")
Grid.notify_cell_changed(self, cell, cell)
# var buffer := StreamPeerBuffer.new()
# buffer.put_8(Packet.STATE)
# server.broadcast(buffer.data_array)
func _physics_process(_delta):
move_and_slide()
update_grid()
func update_grid():
var new_cell := Vector2i(int(position.x / Grid.cell_size), int(position.z / Grid.cell_size))
if new_cell != cell:
Grid.notify_cell_changed(self, cell, new_cell)
cell = new_cell

14
server/player/Player.tscn Normal file
View File

@ -0,0 +1,14 @@
[gd_scene load_steps=3 format=3 uid="uid://148x2hp1hjq0"]
[ext_resource type="Script" path="res://player/Player.gd" id="1_46xlc"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_y8kaq"]
radius = 0.25
height = 1.6
[node name="Player" type="CharacterBody3D"]
script = ExtResource("1_46xlc")
[node name="Collision" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.8, 0)
shape = SubResource("CapsuleShape3D_y8kaq")

38
server/project.godot Normal file
View File

@ -0,0 +1,38 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[application]
config/name="Server"
run/main_scene="res://Server.tscn"
config/features=PackedStringArray("4.2", "Forward Plus")
run/max_fps=100
run/low_processor_mode_sleep_usec=1
[audio]
driver/driver="Dummy"
[autoload]
Grid="*res://grid/Grid.gd"
[debug]
settings/stdout/verbose_stdout=true
[editor]
run/main_run_args="--headless --text-driver Dummy"
[physics]
3d/run_on_separate_thread=true
common/physics_ticks_per_second=100

View File

@ -1,5 +0,0 @@
@tool
extends DirectionalLight3D
func _process(_delta):
(%PostProcessing as MeshInstance3D).mesh.surface_get_material(0).set_shader_parameter("light_direction", -global_basis.z)