Split client and server
This commit is contained in:
parent
532a1faa21
commit
26c52a00b3
1
.gitignore
vendored
1
.gitignore
vendored
@ -16,3 +16,4 @@
|
|||||||
!.gitattributes
|
!.gitattributes
|
||||||
!project.godot
|
!project.godot
|
||||||
.godot/
|
.godot/
|
||||||
|
server/shared/
|
||||||
|
@ -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
14
client/network/Spawn.gd
Normal 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
|
@ -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"]]
|
@ -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
9
client/shared/Account.gd
Normal 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
|
@ -4,5 +4,6 @@ enum {
|
|||||||
PING = 1,
|
PING = 1,
|
||||||
LOGIN = 2,
|
LOGIN = 2,
|
||||||
LOGOUT = 3,
|
LOGOUT = 3,
|
||||||
MOVE = 10,
|
STATE = 10,
|
||||||
|
MOVE = 11,
|
||||||
}
|
}
|
@ -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"
|
Before Width: | Height: | Size: 950 B After Width: | Height: | Size: 950 B |
@ -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
5
client/world/Sun.gd
Normal 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
28
client/world/World.tscn
Normal 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)
|
@ -1,6 +0,0 @@
|
|||||||
class_name Account
|
|
||||||
|
|
||||||
var password: String
|
|
||||||
|
|
||||||
func _init(pw: String):
|
|
||||||
password = pw
|
|
@ -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
12
server/Database.gd
Normal 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]
|
@ -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
27
server/Server.tscn
Normal 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
3
server/grid/Cell.gd
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
class_name Cell
|
||||||
|
|
||||||
|
var player_list := [] as Array[Player]
|
31
server/grid/Grid.gd
Normal file
31
server/grid/Grid.gd
Normal 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)
|
@ -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"
|
|
@ -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
24
server/player/Player.gd
Normal 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
14
server/player/Player.tscn
Normal 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
38
server/project.godot
Normal 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
|
@ -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)
|
|
Loading…
Reference in New Issue
Block a user