Godot Version
4.3
Background
So, I’m still refactoring my netcode. But I’ve gotten to the point where I’m starting to have a solid understanding of the code I’m working with and am starting to implement advanced features.
Before I ask my question, I need to explain how my netcode works. I’ll explain it in steps:
- The project has a main scene with 2 nodes. the
Client_Manager
andServer_Manager
, that manage the client and server respectively. - Upon opening the project, the game will check if the game file is a client or a server via
if OS.has_feature("dedicated_server"):
. - Depending on the result, one of the managers will be deleted. If it’s a client, delete the server manager. If it’s a server, delete the client manager. After that, the surviving node is renamed to
Network_Manager
. This is so the client and server can communicate between separate game files. - Execution is now split up between the client and server.
Client:
The client manager script simply allows the client to send inputs to the server via rpc_id(1)
and the id that sent it. This input is then received by the server and is applied to the client’s player.
@rpc("any_peer","call_remote","reliable",0)
func network_jump(Client_ID) -> void:
pass #to pass checksum
func _process(delta: float) -> void:
if Input.is_action_just_pressed("jump"):
network_jump.rpc_id(1, multiplayer.get_unique_id())
Server:
The server receives input from the client and applies to their player. However, this only happens on the server-side. This is intentional, as the server is the main source of truth.
# In the server network manager
@rpc("any_peer","call_remote","reliable",0)
func network_jump(Client_ID) -> void:
if not multiplayer.is_server(): return
if Player_Container.has_node(str(Client_ID)):
Player_Container.get_node(str(Client_ID)).jump()
else: return
# What the server calls in the player script
func jump() -> void:
if is_on_floor():
velocity.y = Jump_Force
Question
Now with the background out the way, I can explain what I want to do.
I want to collect the server-side player positions (+ other stats later), then use an RPC to broadcast the new player states all clients. I’m having trouble finding a method to capture a state.
I also need the player state capture to contain a history (in an array or dictionary) so I can implement client-side interpolate between those states, client-prediction, and server-side validation.
I do have a working server clock that ticks 60 times per second (same as _physics_process
), a way to retrieve a timestamp, and an array of client id’s and their players (Connected_Client_Players
). But I could still use some help with the rest.
Incomplete code
func collect_world_state() -> void:
if not multiplayer.is_server(): return
var Player_State = {}
for player in Connected_Client_Players:
Player_State = {
"Time": Server_Clock,
}
print(Player_State)
@rpc("authority","call_remote","reliable",0)
func broadcast_world_state() -> void:
if not multiplayer.is_server(): return
# ???