Improved players disconnecting from the game. Implemented network ping measurnment and FPS display.
parent
26643f2696
commit
cec82c7738
|
@ -5,10 +5,15 @@ var impact_player = preload("res://Assets/Effects/ImpactBlood.tscn")
|
||||||
var max_health = 100
|
var max_health = 100
|
||||||
var health = max_health:
|
var health = max_health:
|
||||||
set(value):
|
set(value):
|
||||||
|
if not dead:
|
||||||
|
if main.player_list.players.has(self.get_multiplayer_authority()):
|
||||||
main.player_list.players[self.get_multiplayer_authority()].health = value
|
main.player_list.players[self.get_multiplayer_authority()].health = value
|
||||||
main.push_local_player_info()
|
main.push_local_player_info()
|
||||||
get:
|
get:
|
||||||
|
if not dead:
|
||||||
return main.player_list.players[self.get_multiplayer_authority()].health
|
return main.player_list.players[self.get_multiplayer_authority()].health
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
@export var mouse_sensitivity := 0.15
|
@export var mouse_sensitivity := 0.15
|
||||||
|
|
||||||
|
@ -380,8 +385,10 @@ func _process(delta):
|
||||||
crosshair.show()
|
crosshair.show()
|
||||||
|
|
||||||
@rpc(any_peer, call_local, reliable) func die(killer_pid: int):
|
@rpc(any_peer, call_local, reliable) func die(killer_pid: int):
|
||||||
dead = true
|
if killer_pid == -1: # we're disconnecting from the game
|
||||||
|
#main.chat.chat_notification("Player [/i][b][color=" + main.player_list.players[self.get_multiplayer_authority()].color.to_html() + "]" + main.player_list.players[self.get_multiplayer_authority()].name + "[/color][/b][i] left the game.")
|
||||||
|
pass
|
||||||
|
else:
|
||||||
var gibs = gibs_vfx.instantiate()
|
var gibs = gibs_vfx.instantiate()
|
||||||
get_tree().root.add_child(gibs)
|
get_tree().root.add_child(gibs)
|
||||||
gibs.global_transform = self.global_transform
|
gibs.global_transform = self.global_transform
|
||||||
|
@ -390,15 +397,6 @@ func _process(delta):
|
||||||
get_tree().root.add_child(decal)
|
get_tree().root.add_child(decal)
|
||||||
decal.global_transform = self.global_transform
|
decal.global_transform = self.global_transform
|
||||||
|
|
||||||
#if get_tree().get_rpc_sender_id() != get_multiplayer_authority():
|
|
||||||
# print ("Death requested by a non-master. Ignoring")
|
|
||||||
# return
|
|
||||||
#main.rpc(&'destroy_player', self.get_multiplayer_authority())
|
|
||||||
main.destroy_player(self.get_multiplayer_authority())
|
|
||||||
|
|
||||||
self.hide()
|
|
||||||
$Body.disabled = true
|
|
||||||
|
|
||||||
if is_multiplayer_authority(): # don't touch these on puppets
|
if is_multiplayer_authority(): # don't touch these on puppets
|
||||||
hud.pain = 3
|
hud.pain = 3
|
||||||
crosshair.hide()
|
crosshair.hide()
|
||||||
|
@ -416,6 +414,17 @@ func _process(delta):
|
||||||
view_zoom_target = 1.0
|
view_zoom_target = 1.0
|
||||||
view_zoom = 1
|
view_zoom = 1
|
||||||
|
|
||||||
|
dead = true
|
||||||
|
main.destroy_player(self.get_multiplayer_authority())
|
||||||
|
self.hide()
|
||||||
|
$Body.disabled = true
|
||||||
|
|
||||||
|
#if get_tree().get_rpc_sender_id() != get_multiplayer_authority():
|
||||||
|
# print ("Death requested by a non-master. Ignoring")
|
||||||
|
# return
|
||||||
|
#main.rpc(&'destroy_player', self.get_multiplayer_authority())
|
||||||
|
|
||||||
|
|
||||||
#queue_free()
|
#queue_free()
|
||||||
|
|
||||||
func update_player(info) -> void:
|
func update_player(info) -> void:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[gd_scene load_steps=23 format=3 uid="uid://bff5uslrxesjx"]
|
[gd_scene load_steps=24 format=3 uid="uid://bff5uslrxesjx"]
|
||||||
|
|
||||||
[ext_resource type="Texture2D" uid="uid://blnjjtjifk22i" path="res://Assets/HUD/Vignette.png" id="1"]
|
[ext_resource type="Texture2D" uid="uid://blnjjtjifk22i" path="res://Assets/HUD/Vignette.png" id="1"]
|
||||||
[ext_resource type="Script" path="res://Assets/HUD/HUD.gd" id="1_wc430"]
|
[ext_resource type="Script" path="res://Assets/HUD/HUD.gd" id="1_wc430"]
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
[ext_resource type="AudioStream" uid="uid://d36o2duyrij57" path="res://Assets/SFX/UI_Message.wav" id="9_ubwxw"]
|
[ext_resource type="AudioStream" uid="uid://d36o2duyrij57" path="res://Assets/SFX/UI_Message.wav" id="9_ubwxw"]
|
||||||
[ext_resource type="Texture2D" uid="uid://dvt25wji1pdyl" path="res://Assets/HUD/BarOver.svg" id="10_5i332"]
|
[ext_resource type="Texture2D" uid="uid://dvt25wji1pdyl" path="res://Assets/HUD/BarOver.svg" id="10_5i332"]
|
||||||
[ext_resource type="Texture2D" uid="uid://0j6rxd7ncmu1" path="res://Assets/HUD/BarProgress.svg" id="11_tlgqu"]
|
[ext_resource type="Texture2D" uid="uid://0j6rxd7ncmu1" path="res://Assets/HUD/BarProgress.svg" id="11_tlgqu"]
|
||||||
|
[ext_resource type="Script" path="res://Assets/HUD/Performance.gd" id="17_getmp"]
|
||||||
|
|
||||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_dxk5q"]
|
[sub_resource type="ShaderMaterial" id="ShaderMaterial_dxk5q"]
|
||||||
resource_local_to_scene = true
|
resource_local_to_scene = true
|
||||||
|
@ -459,4 +460,21 @@ stretch_margin_right = 16
|
||||||
stretch_margin_bottom = 16
|
stretch_margin_bottom = 16
|
||||||
script = null
|
script = null
|
||||||
|
|
||||||
|
[node name="Performance" type="Label" parent="."]
|
||||||
|
material = ExtResource( "4_f6eam" )
|
||||||
|
anchor_top = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 4.0
|
||||||
|
offset_top = -106.0
|
||||||
|
offset_right = 202.0
|
||||||
|
offset_bottom = -2.0
|
||||||
|
text = "FPS:
|
||||||
|
PING:"
|
||||||
|
valign = 2
|
||||||
|
structured_text_bidi_override_options = []
|
||||||
|
script = ExtResource( "17_getmp" )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
[connection signal="text_submitted" from="Chat/VBoxContainer/Typing/Editor" to="Chat" method="_on_Editor_text_submitted"]
|
[connection signal="text_submitted" from="Chat/VBoxContainer/Typing/Editor" to="Chat" method="_on_Editor_text_submitted"]
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
extends Label
|
||||||
|
|
||||||
|
# Declare member variables here. Examples:
|
||||||
|
# var a = 2
|
||||||
|
# var b = "text"
|
||||||
|
@onready var main = get_tree().root.get_node("Main")
|
||||||
|
|
||||||
|
# Called when the node enters the scene tree for the first time.
|
||||||
|
func _ready():
|
||||||
|
pass # Replace with function body.
|
||||||
|
|
||||||
|
|
||||||
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
|
func _process(delta):
|
||||||
|
|
||||||
|
if not get_tree().multiplayer.has_multiplayer_peer():
|
||||||
|
text = "Offline"
|
||||||
|
elif get_tree().multiplayer.is_server():
|
||||||
|
text = "Hosting"
|
||||||
|
else:
|
||||||
|
if main.ping_time >= 0:
|
||||||
|
text = "Ping: " + str(round(main.ping_time * 1000)) + " ms"
|
||||||
|
else:
|
||||||
|
text = "Ping unknown"
|
||||||
|
|
||||||
|
text += "\nFPS: " + str(Engine.get_frames_per_second())
|
||||||
|
text += "\nLiblast 0.1.1 pre-alpha"
|
|
@ -50,6 +50,18 @@ func apply_settings():
|
||||||
|
|
||||||
# These functions are for applying settings changes
|
# These functions are for applying settings changes
|
||||||
func quit_game():
|
func quit_game():
|
||||||
|
|
||||||
|
var main = get_tree().get_root().get_node("Main")
|
||||||
|
var pid = main.get_multiplayer_authority()
|
||||||
|
var player_node = main.get_node("Players").get_node(str(pid))
|
||||||
|
|
||||||
|
#main.get_node("HUD/Chat").rpc(&'chat_notification', "Player " + str(pid) +" left the game.")
|
||||||
|
#player_node.rpc(&'die', -1)
|
||||||
|
#main.rpc(&'disconnect_player', pid) # tell everyone we're leaving
|
||||||
|
#main.multiplayer = null
|
||||||
|
|
||||||
|
get_tree().multiplayer.multiplayer_peer = null
|
||||||
|
|
||||||
get_tree().quit()
|
get_tree().quit()
|
||||||
|
|
||||||
func toggle_fullscreen(is_fullscreen):
|
func toggle_fullscreen(is_fullscreen):
|
||||||
|
|
41
Game/Main.gd
41
Game/Main.gd
|
@ -10,6 +10,11 @@ const NET_SERVER = "localhost"
|
||||||
|
|
||||||
var peer = ENetMultiplayerPeer.new()
|
var peer = ENetMultiplayerPeer.new()
|
||||||
|
|
||||||
|
var ping_time = -1
|
||||||
|
var ping_sent = 0
|
||||||
|
var ping_recieved = 0
|
||||||
|
var ping_token = 0
|
||||||
|
|
||||||
var role = MultiplayerRole.NONE:
|
var role = MultiplayerRole.NONE:
|
||||||
set(new_role):
|
set(new_role):
|
||||||
role = new_role
|
role = new_role
|
||||||
|
@ -22,6 +27,23 @@ var player_scene = preload("res://Assets/Characters/Player.tscn")
|
||||||
@onready var chat = hud.get_node("Chat")
|
@onready var chat = hud.get_node("Chat")
|
||||||
var local_player: Node = null
|
var local_player: Node = null
|
||||||
|
|
||||||
|
@rpc(call_remote, any_peer, unreliable) func ping(token:int = -1):
|
||||||
|
if get_tree().multiplayer.is_server(): # we are the sever - reply to pinging client
|
||||||
|
# for i in range(0, 100):
|
||||||
|
# print(i)
|
||||||
|
rpc_id(get_tree().multiplayer.get_remote_sender_id(), &'ping', token)
|
||||||
|
else:
|
||||||
|
if get_tree().multiplayer.get_remote_sender_id() == 1: #recieve answer from server
|
||||||
|
if token == ping_token: # if the token is correct
|
||||||
|
ping_recieved = uptime
|
||||||
|
ping_time = ping_recieved - ping_sent
|
||||||
|
#else:
|
||||||
|
# ping_time = -1
|
||||||
|
elif token == -1: # send ping
|
||||||
|
ping_sent = uptime
|
||||||
|
ping_token = randi()
|
||||||
|
rpc_id(1, &'ping', ping_token)
|
||||||
|
|
||||||
class PlayerInfo:
|
class PlayerInfo:
|
||||||
var name: String
|
var name: String
|
||||||
var team: int
|
var team: int
|
||||||
|
@ -133,7 +155,10 @@ class PlayerList:
|
||||||
players[pid] = info
|
players[pid] = info
|
||||||
|
|
||||||
func get(pid: int) -> PlayerInfo:
|
func get(pid: int) -> PlayerInfo:
|
||||||
|
if players.has(pid):
|
||||||
return players[pid]
|
return players[pid]
|
||||||
|
else:
|
||||||
|
return PlayerInfo.new()
|
||||||
|
|
||||||
@onready var player_list = PlayerList.new()
|
@onready var player_list = PlayerList.new()
|
||||||
|
|
||||||
|
@ -184,7 +209,7 @@ func _input(_event) -> void:
|
||||||
|
|
||||||
@rpc(any_peer, call_local, reliable) func game_over(winner):
|
@rpc(any_peer, call_local, reliable) func game_over(winner):
|
||||||
if local_player:
|
if local_player:
|
||||||
local_player.rpc(&'set_dead', true)
|
local_player.die(-1)
|
||||||
hud.game_over(winner)
|
hud.game_over(winner)
|
||||||
|
|
||||||
spawn_queue.clear()
|
spawn_queue.clear()
|
||||||
|
@ -244,6 +269,9 @@ func update_hud():
|
||||||
@rpc(any_peer, reliable) func player_list_update(info, pid = get_tree().get_rpc_sender_id(), erase:=false):
|
@rpc(any_peer, reliable) func player_list_update(info, pid = get_tree().get_rpc_sender_id(), erase:=false):
|
||||||
if erase:
|
if erase:
|
||||||
player_list.erase(pid)
|
player_list.erase(pid)
|
||||||
|
spawn_queue.erase(pid)
|
||||||
|
get_node("Players").get_node(str(pid)).die(-1)
|
||||||
|
return
|
||||||
|
|
||||||
var new_info = PlayerInfo.new()
|
var new_info = PlayerInfo.new()
|
||||||
new_info.deserialize(info)
|
new_info.deserialize(info)
|
||||||
|
@ -268,6 +296,7 @@ func update_hud():
|
||||||
|
|
||||||
func push_local_player_info(): #
|
func push_local_player_info(): #
|
||||||
var pid = get_tree().multiplayer.get_unique_id()
|
var pid = get_tree().multiplayer.get_unique_id()
|
||||||
|
assert(pid >= 1, "Another server must be running. PID is 0, that means Enet did not initialize.")
|
||||||
rpc(&'player_list_update', player_list.get(pid).serialize(), pid)
|
rpc(&'player_list_update', player_list.get(pid).serialize(), pid)
|
||||||
|
|
||||||
@rpc(call_local, any_peer, reliable) func destroy_player(pid: int):
|
@rpc(call_local, any_peer, reliable) func destroy_player(pid: int):
|
||||||
|
@ -290,7 +319,9 @@ func push_local_player_info(): #
|
||||||
if destroy_free_player_crash_workaround:
|
if destroy_free_player_crash_workaround:
|
||||||
pass
|
pass
|
||||||
#print("Setting player ", pid, " as DEAD")
|
#print("Setting player ", pid, " as DEAD")
|
||||||
#player_node.set_dead(true)
|
if not player_node.dead: # disconnected, not killed
|
||||||
|
player_node.die(-1)
|
||||||
|
return # skip the rest - don't add to respawn queue
|
||||||
else: # regular method follows
|
else: # regular method follows
|
||||||
player_node.name = str(player_node.name) + "_dead" # avoids name collision when instancing another player scene
|
player_node.name = str(player_node.name) + "_dead" # avoids name collision when instancing another player scene
|
||||||
|
|
||||||
|
@ -298,6 +329,7 @@ func push_local_player_info(): #
|
||||||
player_node.queue_free()
|
player_node.queue_free()
|
||||||
print("after free")
|
print("after free")
|
||||||
# respawn queue applies ot both implementations of death
|
# respawn queue applies ot both implementations of death
|
||||||
|
if player_list.players.has(pid): # don't respawn players that are not there, lol
|
||||||
spawn_queue[pid] = uptime + respawn_delay
|
spawn_queue[pid] = uptime + respawn_delay
|
||||||
|
|
||||||
if pid == get_tree().multiplayer.get_unique_id():
|
if pid == get_tree().multiplayer.get_unique_id():
|
||||||
|
@ -443,7 +475,7 @@ func _player_connected(pid) -> void:
|
||||||
# if role in [MultiplayerRole.SERVER, MultiplayerRole.DEDICATED_SERVER]:
|
# if role in [MultiplayerRole.SERVER, MultiplayerRole.DEDICATED_SERVER]:
|
||||||
# rpc_id(id, "player_list_update", player_list)
|
# rpc_id(id, "player_list_update", player_list)
|
||||||
|
|
||||||
func _player_disconnected(pid) -> void:
|
@rpc(call_remote, any_peer, reliable) func disconnect_player(pid):
|
||||||
print("player disconnected, id: ", pid)
|
print("player disconnected, id: ", pid)
|
||||||
spawn_queue.erase(pid)
|
spawn_queue.erase(pid)
|
||||||
if get_tree().multiplayer.is_server():
|
if get_tree().multiplayer.is_server():
|
||||||
|
@ -452,6 +484,9 @@ func _player_disconnected(pid) -> void:
|
||||||
rpc(&'player_list_update', null, pid, true)
|
rpc(&'player_list_update', null, pid, true)
|
||||||
rpc(&'destroy_player', pid)
|
rpc(&'destroy_player', pid)
|
||||||
|
|
||||||
|
func _player_disconnected(pid) -> void:
|
||||||
|
disconnect_player(pid)
|
||||||
|
|
||||||
func _connected_ok() -> void:
|
func _connected_ok() -> void:
|
||||||
print("connected to server")
|
print("connected to server")
|
||||||
chat.chat_notification("Connected to server")
|
chat.chat_notification("Connected to server")
|
||||||
|
|
|
@ -241,6 +241,9 @@ offset_top = 49.0
|
||||||
custom_effects = []
|
custom_effects = []
|
||||||
structured_text_bidi_override_options = []
|
structured_text_bidi_override_options = []
|
||||||
|
|
||||||
|
[node name="Performance" parent="HUD" index="8"]
|
||||||
|
structured_text_bidi_override_options = []
|
||||||
|
|
||||||
[node name="GUI" parent="." instance=ExtResource( "2" )]
|
[node name="GUI" parent="." instance=ExtResource( "2" )]
|
||||||
|
|
||||||
[node name="Players" type="Node3D" parent="."]
|
[node name="Players" type="Node3D" parent="."]
|
||||||
|
@ -336,11 +339,16 @@ stream = ExtResource( "5_ilayd" )
|
||||||
bus = &"Announcer"
|
bus = &"Announcer"
|
||||||
script = ExtResource( "6_gcsgr" )
|
script = ExtResource( "6_gcsgr" )
|
||||||
|
|
||||||
|
[node name="PingTimer" type="Timer" parent="."]
|
||||||
|
autostart = true
|
||||||
|
script = null
|
||||||
|
|
||||||
[connection signal="toggled" from="NetworkTesting/CheckButton" to="." method="_on_CheckButton_toggled"]
|
[connection signal="toggled" from="NetworkTesting/CheckButton" to="." method="_on_CheckButton_toggled"]
|
||||||
[connection signal="pressed" from="NetworkTesting/Host" to="." method="_on_Host_pressed"]
|
[connection signal="pressed" from="NetworkTesting/Host" to="." method="_on_Host_pressed"]
|
||||||
[connection signal="pressed" from="NetworkTesting/Connect" to="." method="_on_Connect_pressed"]
|
[connection signal="pressed" from="NetworkTesting/Connect" to="." method="_on_Connect_pressed"]
|
||||||
[connection signal="text_submitted" from="NetworkTesting/TextEdit" to="." method="_on_TextEdit_text_submitted"]
|
[connection signal="text_submitted" from="NetworkTesting/TextEdit" to="." method="_on_TextEdit_text_submitted"]
|
||||||
[connection signal="color_changed" from="NetworkTesting/ColorPickerButton" to="." method="_on_ColorPickerButton_color_changed"]
|
[connection signal="color_changed" from="NetworkTesting/ColorPickerButton" to="." method="_on_ColorPickerButton_color_changed"]
|
||||||
[connection signal="pressed" from="NetworkTesting/Button" to="." method="_on_Button_pressed"]
|
[connection signal="pressed" from="NetworkTesting/Button" to="." method="_on_Button_pressed"]
|
||||||
|
[connection signal="timeout" from="PingTimer" to="." method="ping"]
|
||||||
|
|
||||||
[editable path="HUD"]
|
[editable path="HUD"]
|
||||||
|
|
Reference in New Issue