Finished basic server-side player list implementation.

unbroken
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() get_tree().get_root().set_input_as_handled()
# doesn't work over network due to missing RPC implementation in Godot 4 # 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: @remotesync func chat_message(sender_pid: int, recipient_team, message: String) -> void:
var sender_info = main.player_list[sender_id] 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]') 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): func _on_Editor_text_submitted(new_text):

View File

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