Finished basic server-side player list implementation.

This commit is contained in:
unfa 2021-08-22 23:33:33 +02:00
parent 49f4e7c70f
commit df861143a4
2 changed files with 96 additions and 67 deletions

View file

@ -52,8 +52,8 @@ func _unhandled_input(_event) -> void:
get_tree().get_root().set_input_as_handled()
# doesn't work over network due to missing RPC implementation in Godot 4
@remotesync func chat_message(sender_id: int, recipient_team, message: String) -> void:
var sender_info = main.player_list[sender_id]
@remotesync func chat_message(sender_pid: int, recipient_team, message: String) -> void:
var sender_info = main.player_list.get(sender_pid)
chat_history.append_bbcode('\n' + '[b][color=' + sender_info.color.to_html() +']' + str(sender_info.name) + '[/color][/b] : [i]' + message + '[/i]')
func _on_Editor_text_submitted(new_text):

View file

@ -25,19 +25,22 @@ class PlayerInfo:
var team: int
var color: Color
var focus: GameFocus
func _init():#name: String, team: int, color: Color):
# self.name = name
# self.team = team
# self.color = color
# self.focus = 0
var health: int
func _init():#name: String, team: int, color: Color):
var player_name = ""
for i in range(0, 4):
player_name += ['a','b','c', 'd', 'e', 'f'][randi() % 5]
self.name = player_name
self.color = Color(randf(),randf(),randf())
self.team = 0
self.focus = 999
self.health = 100
# else:
# self.name = name
# self.team = team
# self.color = color
# self.focus = 0
func serialize():
return {
@ -45,52 +48,59 @@ class PlayerInfo:
'team': str(self.team),
'color': self.color.to_html(),
'focus': self.focus,
'health': self.health
}
func set(name: String, team: int, color: Color, focus: int):
func set(name: String, team: int, color: Color, focus: int, health: int):
self.name = name
self.team = team
self.color = color
self.focus = focus
self.health = health
func deserialize(info):
#var info_parsed = info.parse_json(info)
self.name = info['name']
self.team = info['team'].to_int()
self.color = Color.html(info['color'])
self.focus = info['focus']
self.health = info['health']
#func generate():
func _process(delta):
$Label.text = "player_list: \n"
for i in player_list.keys():
$Label.text += str(i) + str(player_list[i].serialize()) + "\n"
for i in player_list.players.keys():
if player_list.players[i]:
$Label.text += str(i) + " = " + str(player_list.get(i).serialize()) + "\n"
else:
$Label.text += str(i) + " = ???"
var local_player_info: PlayerInfo
#class PlayerList:
# var items = {}
class PlayerList:
var players = {}
#
# func store(pid, item):
# items[pid] = item
#
# func erase(pid):
# items.erase(pid)
#
# func update(pid, item):
# if items[pid]:
# items[pid] = item
#
# func get():
# return items
func erase(pid):
players.erase(pid)
func set(pid: int, info: PlayerInfo):
# if info is PlayerInfo:
players[pid] = info
# else:
# var new_info = PlayerInfo.deserialize(info)
# players[pid] = new_info
func get(pid: int) -> PlayerInfo:
return players[pid]
var player_list = {}:
set(player_list):
if role in [NetworkRole.SERVER, NetworkRole.DEDICATED_SERVER]:
for i in player_list:
rpc(&'player_list_update', i.serialize())
else:
rpc_id(1, &'player_list_update', player_list.serialize())
# func update():
# if get_tree().network_peer.get_unique_id() == 1:
# for i in players.keys:
# rpc(&'player_list_update', i, players[i].serialize())
# else:
# rpc_id(1, &'player_list_update', players[get_tree().network_peer.get_unique_id()].serialize())
@onready var player_list = PlayerList.new()
var focus = GameFocus.MENU :
set(new_focus):
@ -135,48 +145,65 @@ func _input(_event) -> void:
#@remote func update_player_list(player_list):
# self.player_list = player_list
@remotesync func player_list_update(info):
var new_info = PlayerInfo.deserialize(info)
var id = get_tree().get_rpc_sender_id()
print("Updating player_list wit hnew info: ", new_info)
player_list[id] = new_info
print("Player list: ", player_list)
print("Player list item for id ", id, ": ", player_list[id])
@remote func player_list_update(info, pid = get_tree().get_rpc_sender_id()):
if get_tree().network_peer.get_unique_id() == 1: # if we're server, we should store this
pid = get_tree().get_rpc_sender_id() #disallow clients setting player_info for other players than themselves
var new_info = PlayerInfo.new()
new_info.deserialize(info)
player_list.set(pid, new_info)
rpc(&'player_list_update', info, pid) # broadcast the new entry to clients
else: #we are client, so we're getting data relayed from the server
var new_info = PlayerInfo.new()
new_info.deserialize(info)
player_list.set(pid, new_info) # server relays other PID's data
func create_player(id: int, is_local: bool) -> void:
# if not id:
# id = get_tree().get_rpc_sender_id()
#
# print_debug("player_list_update ", info)
# if info is PlayerInfo:
# player_list.set(id, info)
# else:
# var new_info = PlayerInfo.deserialize(info)
# player_list.set(id, new_info)
# print("Updating player_list wit hnew info: ", new_info)
#
# print("Player list: ", player_list)
# print("Player list item for id ", id, ": ", player_list[id])
func create_player(pid: int, is_local: bool) -> void:
var new_player
new_player = player_scene.instantiate()
var spawnpoint = $Map/SpawnPoints.get_children()[randi() % len($Map/SpawnPoints.get_children())]
new_player.name = str(id)
new_player.name = str(pid)
new_player.global_transform = spawnpoint.global_transform
new_player.set_network_master(id)
new_player.set_network_master(pid)
$Players.add_child(new_player)
if is_local:
local_player = new_player #$Players.get_node(str(id))
local_player.get_node("Head/Camera").current = true
var new_info = PlayerInfo.new()
#new_info.generate()
local_player_info = new_info
rpc_id(id, &'player_list_update', local_player_info.serialize()) # send player_info to others
player_list[id] = local_player_info
player_list.set(pid, new_info)
$NetworkTesting/TextEdit.text = local_player_info.name
$NetworkTesting/ColorPickerButton.color = local_player_info.color
if get_tree().network_peer.get_unique_id() != 1: #if we're not the server
rpc_id(1, &'player_list_update', new_info.serialize()) # send local player info to the server
$NetworkTesting/TextEdit.text = new_info.name
$NetworkTesting/ColorPickerButton.color = new_info.color
else: # make sure we use the right camera
new_player.get_node("Head/Camera").current = false
if local_player:
if local_player: #if there is a local player, use it's camera
local_player.get_node("Head/Camera").current = true
func start_dedicated_server():
func start_dedicated_server(): # start server without creating a local player
role = NetworkRole.DEDICATED_SERVER
peer.create_server(NET_PORT, 16)
get_tree().network_peer = peer
#create_player(1, true)
func _on_Host_pressed():
func _on_Host_pressed(): # start server and create a local player
role = NetworkRole.SERVER
$NetworkTesting/Host.disabled = true
$NetworkTesting/Connect.disabled = true
@ -193,36 +220,38 @@ func _on_Connect_pressed():
peer.create_client(NET_SERVER, NET_PORT)
get_tree().network_peer = peer
func _player_connected(id) -> void:
print("player connected, id: ", id)
create_player(id, false)
func _player_connected(pid) -> void:
print("player connected, id: ", pid)
create_player(pid, false)
if get_tree().network_peer.get_unique_id() == 1: # if we're the server
for i in player_list.players.keys(): # send each player info entry to the newly connected client
rpc_id(pid, &'player_list_update', player_list.get(i).serialize(), i) # send local player info to the server
# if local_player:
# local_player.rpc(&"update_info")
#
# if role in [NetworkRole.SERVER, NetworkRole.DEDICATED_SERVER]:
# rpc_id(id, "player_list_update", player_list)
func _player_disconnected(id) -> void:
print("player disconnected, id: ", id)
func _player_disconnected(pid) -> void:
print("player disconnected, id: ", pid)
func _connected_ok() -> void:
print("connected to server")
var id = get_tree().get_network_unique_id()
create_player(id, true)
var pid = get_tree().get_network_unique_id()
create_player(pid, true)
focus = GameFocus.GAME
role = NetworkRole.CLIENT
# todo pull player list from server
func _connected_fail() -> void:
print("connection to server failed")
func _server_disconnected() -> void:
print("server disconnected")
role = NetworkRole.NONE
func _ready() -> void:
print("Commandline arguments: ", OS.get_cmdline_args())
get_tree().connect("network_peer_connected", self._player_connected)
@ -233,7 +262,7 @@ func _ready() -> void:
func _on_TextEdit_text_submitted(new_text):
local_player_info.name = new_text
player_list.players[get_tree().network_peer.get_unique_id()].name = new_text
func _on_ColorPickerButton_color_changed(color):
local_player_info.color = color
player_list.players[get_tree().network_peer.get_unique_id()].color = color