class_name MultiplayerData extends Node var is_multiplayer_active: bool = false var multiplayer_synchronizer: MultiplayerSynchronizer = MultiplayerSynchronizer.new() var synchronizer_config: SceneReplicationConfig = SceneReplicationConfig.new() var current_turn_player_id: int = -1 func _init() -> void: Globals.multiplayer_data = self multiplayer_synchronizer.name = "multiplayer_synchronizer" multiplayer_synchronizer.replication_config = synchronizer_config multiplayer_synchronizer.root_path = "/root/billiards" @rpc("authority", "call_local", "reliable") func set_multiplayer_active() -> void: is_multiplayer_active = true @rpc("authority", "call_local", "reliable") func set_active_player_id(id: int) -> void: push_warning("Server assigned active player: ", id) current_turn_player_id = id func reset() -> void: multiplayer_synchronizer = MultiplayerSynchronizer.new() synchronizer_config = SceneReplicationConfig.new() current_turn_player_id = -1 is_multiplayer_active = true multiplayer_synchronizer.name = "multiplayer_synchronizer" multiplayer_synchronizer.replication_config = synchronizer_config multiplayer_synchronizer.root_path = "/root/billiards" func init_match() -> void: var match_entry = Dictionary() match_entry.set("type", Globals.game_data.game_mode) rpc("set_active_player_id", Globals.game_data.client1) MessageBus.emit_propagation_clients_only.rpc_id( Globals.game_data.client1, "match_list_entry_load_match", [match_entry, true], true ) MessageBus.emit_propagation_clients_only.rpc_id( Globals.game_data.client2, "match_list_entry_load_match", [match_entry, false], true ) func set_multiplayer_inactive() -> void: is_multiplayer_active = false func can_do_request_server_only() -> bool: return can_do_request(true) # NOTE: Clients could be modified to pass checks; but, because we are server authority based # it wouldn't matter because server should/will override any state of balls/scores and # checks which player is active when processing input. This is mostly patterned # to reduce client side overhead. func can_do_request(server_only: bool = false) -> bool: # NOTE: If request is local and not multiplayer if not is_multiplayer_active: return true # NOTE: If request is server only; checkable by client and server side # server_only check must return so CANNOT do if 'server_only and multiplayer.is_server()' ... if server_only: return multiplayer.is_server() # NOTE: If request is local or server side if current_turn_player_id == multiplayer.get_unique_id(): return true # NOTE: If request is on server and checking active player if current_turn_player_id == multiplayer.get_remote_sender_id(): return true return false func set_tracking_of_cue(path: String) -> void: path = str(path).trim_prefix(str(multiplayer_synchronizer.root_path) + "/") var position_pth = NodePath( path + ":position" ) var rotation_pth = NodePath( path + ":rotation" ) synchronizer_config.add_property(position_pth) synchronizer_config.add_property(rotation_pth) synchronizer_config.property_set_replication_mode( position_pth, SceneReplicationConfig.REPLICATION_MODE_ON_CHANGE ) synchronizer_config.property_set_replication_mode( rotation_pth, SceneReplicationConfig.REPLICATION_MODE_ON_CHANGE ) func set_tracking_of_ball(path: String) -> void: path = str(path).trim_prefix(str(multiplayer_synchronizer.root_path) + "/") var position_pth = NodePath( path + ":position" ) var rotation_pth = NodePath( path + ":rotation" ) var linear_velocity_pth = NodePath( path + ":linear_velocity" ) synchronizer_config.add_property(position_pth) synchronizer_config.add_property(rotation_pth) synchronizer_config.add_property(linear_velocity_pth) synchronizer_config.property_set_replication_mode( position_pth, SceneReplicationConfig.REPLICATION_MODE_ON_CHANGE ) synchronizer_config.property_set_replication_mode( rotation_pth, SceneReplicationConfig.REPLICATION_MODE_ON_CHANGE ) synchronizer_config.property_set_replication_mode( linear_velocity_pth, SceneReplicationConfig.REPLICATION_MODE_ON_CHANGE ) func remove_tracking_of_ball(path: String) -> void: path = str(path).trim_prefix(str(multiplayer_synchronizer.root_path) + "/") var position_pth = NodePath( path + ":position" ) var rotation_pth = NodePath( path + ":rotation" ) var linear_velocity_pth = NodePath( path + ":linear_velocity" ) if synchronizer_config.has_property(position_pth): synchronizer_config.remove_property(position_pth) if synchronizer_config.has_property(rotation_pth): synchronizer_config.remove_property(rotation_pth) if synchronizer_config.has_property(linear_velocity_pth): synchronizer_config.remove_property(linear_velocity_pth)