Skip to content

Commit

Permalink
Refactored the mechanism to spawn Bots and Npcs.
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreaCatania committed Feb 7, 2024
1 parent d755626 commit 9744bee
Show file tree
Hide file tree
Showing 4 changed files with 8 additions and 114 deletions.
64 changes: 1 addition & 63 deletions core/peer_networked_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,60 +61,6 @@ const std::vector<ObjectData *> &PeerNetworkedController::get_sorted_controllabl
return _sorted_controllable_objects;
}

void PeerNetworkedController::set_server_controlled(bool p_server_controlled) {
if (server_controlled == p_server_controlled) {
// It's the same, nothing to do.
return;
}

if (is_networking_initialized()) {
if (is_server_controller()) {
// This is the server, let's start the procedure to switch controll mode.

#ifdef DEBUG_ENABLED
ASSERT_COND_MSG(scene_synchronizer, "When the `NetworkedController` is a server, the `scene_synchronizer` is always set.");
#endif

// First update the variable.
server_controlled = p_server_controlled;

// Notify the `SceneSynchronizer` about it.
scene_synchronizer->notify_controller_control_mode_changed(this);

// Tell the client to do the switch too.
if (authority_peer != 1) {
scene_synchronizer->call_rpc_set_server_controlled(
authority_peer,
authority_peer,
server_controlled);
} else {
SceneSynchronizerDebugger::singleton()->print(WARNING, "The peer_controller is owned by the server, there is no client that can control it; please assign the proper authority.", "CONTROLLER-" + std::to_string(authority_peer));
}

} else if (is_player_controller() || is_doll_controller()) {
SceneSynchronizerDebugger::singleton()->print(WARNING, "You should never call the function `set_server_controlled` on the client, this has an effect only if called on the server.", "CONTROLLER-" + std::to_string(authority_peer));

} else if (is_nonet_controller()) {
// There is no networking, the same instance is both the client and the
// server already, nothing to do.
server_controlled = p_server_controlled;

} else {
#ifdef DEBUG_ENABLED
ASSERT_NO_ENTRY_MSG("Unreachable, all the cases are handled.");
#endif
}
} else {
// This called during initialization or on the editor, nothing special just
// set it.
server_controlled = p_server_controlled;
}
}

bool PeerNetworkedController::get_server_controlled() const {
return server_controlled;
}

void PeerNetworkedController::set_max_redundant_inputs(int p_max) {
max_redundant_inputs = p_max;
}
Expand Down Expand Up @@ -305,14 +251,6 @@ void PeerNetworkedController::notify_receive_inputs(const Vector<uint8_t> &p_dat
}
}

void PeerNetworkedController::notify_set_server_controlled(bool p_server_controlled) {
ENSURE_MSG(is_player_controller(), "This function is supposed to be called on the server.");
server_controlled = p_server_controlled;

ENSURE_MSG(scene_synchronizer, "The server controller is supposed to be set on the client at this point.");
scene_synchronizer->notify_controller_control_mode_changed(this);
}

void PeerNetworkedController::player_set_has_new_input(bool p_has) {
has_player_new_input = p_has;
}
Expand Down Expand Up @@ -793,7 +731,7 @@ AutonomousServerController::AutonomousServerController(
}

bool AutonomousServerController::receive_inputs(const Vector<uint8_t> &p_data) {
SceneSynchronizerDebugger::singleton()->print(WARNING, "`receive_input` called on the `AutonomousServerController` - If this is called just after `set_server_controlled(true)` is called, you can ignore this warning, as the client is not aware about the switch for a really small window after this function call.", "CONTROLLER-" + std::to_string(peer_controller->authority_peer));
SceneSynchronizerDebugger::singleton()->print(ERROR, "`receive_input` called on the `AutonomousServerController` it should not happen by design. This is a bug.", "CONTROLLER-" + std::to_string(peer_controller->authority_peer));
return false;
}

Expand Down
16 changes: 0 additions & 16 deletions core/peer_networked_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,6 @@ class PeerNetworkedController final {
};

private:
/// When `true`, this controller is controlled by the server: All the clients
/// see it as a `Doll`.
/// This property is really useful to implement bots (Character controlled by
/// the AI).
///
/// NOTICE: Generally you specify this property on the editor, in addition
/// it's possible to change this at runtime: this will cause the server to
/// notify all the clients; so the switch is not immediate. This feature can be
/// used to switch the Character possession between the AI (Server) and
/// PlayerController (Client) without the need to re-instantiate the Character.
bool server_controlled = false;

/// Amount of time an inputs is re-sent to each peer.
/// Resenging inputs is necessary because the packets may be lost since as
/// they are sent in an unreliable way.
Expand Down Expand Up @@ -108,9 +96,6 @@ class PeerNetworkedController final {

const std::vector<ObjectData *> &get_sorted_controllable_objects();

void set_server_controlled(bool p_server_controlled);
bool get_server_controlled() const;

void set_max_redundant_inputs(int p_max);
int get_max_redundant_inputs() const;

Expand Down Expand Up @@ -171,7 +156,6 @@ class PeerNetworkedController final {
void controllable_process(double p_delta, DataBuffer &p_data_buffer);

void notify_receive_inputs(const Vector<uint8_t> &p_data);
void notify_set_server_controlled(bool p_server_controlled);

private:
void player_set_has_new_input(bool p_has);
Expand Down
37 changes: 7 additions & 30 deletions scene_synchronizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,6 @@ void SceneSynchronizerBase::setup(SynchronizerManager &p_synchronizer_interface)
false,
false);

rpc_handle_set_server_controlled =
network_interface->rpc_config(
std::function<void(int, bool)>(std::bind(&SceneSynchronizerBase::rpc_set_server_controlled, this, std::placeholders::_1, std::placeholders::_2)),
true,
false);

clear();
reset_synchronizer_mode();

Expand Down Expand Up @@ -151,7 +145,6 @@ void SceneSynchronizerBase::conclude() {
rpc_handler_trickled_sync_data.reset();
rpc_handle_notify_netstats.reset();
rpc_handle_receive_input.reset();
rpc_handle_set_server_controlled.reset();
}

void SceneSynchronizerBase::process(double p_delta) {
Expand Down Expand Up @@ -1129,12 +1122,6 @@ void SceneSynchronizerBase::clear() {
process_functions__clear();
}

void SceneSynchronizerBase::notify_controller_control_mode_changed(PeerNetworkedController *controller) {
if (controller) {
reset_controller(*controller);
}
}

void SceneSynchronizerBase::rpc_receive_state(DataBuffer &p_snapshot) {
ENSURE_MSG(is_client(), "Only clients are suposed to receive the server snapshot.");
static_cast<ClientSynchronizer *>(synchronizer)->receive_snapshot(p_snapshot);
Expand Down Expand Up @@ -1264,28 +1251,13 @@ void SceneSynchronizerBase::call_rpc_receive_inputs(int p_recipient, int p_peer,
p_data);
}

void SceneSynchronizerBase::call_rpc_set_server_controlled(int p_recipient, int p_peer, bool p_server_controlled) {
rpc_handle_set_server_controlled.rpc(
get_network_interface(),
p_recipient,
p_peer,
p_server_controlled);
}

void SceneSynchronizerBase::rpc_receive_inputs(int p_peer, const Vector<uint8_t> &p_data) {
PeerData *pd = MapFunc::get_or_null(peer_data, p_peer);
if (pd && pd->get_controller()) {
pd->get_controller()->notify_receive_inputs(p_data);
}
}

void SceneSynchronizerBase::rpc_set_server_controlled(int p_peer, bool p_server_controlled) {
PeerData *pd = MapFunc::get_or_null(peer_data, p_peer);
if (pd && pd->get_controller()) {
pd->get_controller()->notify_set_server_controlled(p_server_controlled);
}
}

void SceneSynchronizerBase::clear_peers() {
// Copy, so we can safely remove the peers from `peer_data`.
std::vector<int> peers_tmp;
Expand Down Expand Up @@ -1653,17 +1625,22 @@ void SceneSynchronizerBase::reset_controller(PeerNetworkedController &p_controll
if (!network_interface->is_local_peer_networked()) {
p_controller.controller_type = PeerNetworkedController::CONTROLLER_TYPE_NONETWORK;
p_controller.controller = memnew(NoNetController(&p_controller));

} else if (network_interface->is_local_peer_server()) {
if (p_controller.get_server_controlled()) {
if (p_controller.get_authority_peer() == get_network_interface().get_server_peer()) {
// This is the server controller that is used to control the BOTs / NPCs.
p_controller.controller_type = PeerNetworkedController::CONTROLLER_TYPE_AUTONOMOUS_SERVER;
p_controller.controller = memnew(AutonomousServerController(&p_controller));

} else {
p_controller.controller_type = PeerNetworkedController::CONTROLLER_TYPE_SERVER;
p_controller.controller = memnew(ServerController(&p_controller));
}
} else if (get_network_interface().fetch_local_peer_id() == p_controller.get_authority_peer() && p_controller.get_server_controlled() == false) {

} else if (get_network_interface().fetch_local_peer_id() == p_controller.get_authority_peer()) {
p_controller.controller_type = PeerNetworkedController::CONTROLLER_TYPE_PLAYER;
p_controller.controller = memnew(PlayerController(&p_controller));

} else {
p_controller.controller_type = PeerNetworkedController::CONTROLLER_TYPE_DOLL;
p_controller.controller = memnew(DollController(&p_controller));
Expand Down
5 changes: 0 additions & 5 deletions scene_synchronizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ class SceneSynchronizerBase {

// Controller RPCs.
RpcHandle<int, const Vector<uint8_t> &> rpc_handle_receive_input;
RpcHandle<int, bool> rpc_handle_set_server_controlled;

/// Fixed rate at which the NetSync has to produce frames.
int frames_per_seconds = 60;
Expand Down Expand Up @@ -389,10 +388,8 @@ class SceneSynchronizerBase {
void rpc_notify_netstats(DataBuffer &p_data);

void call_rpc_receive_inputs(int p_recipient, int p_peer, const Vector<uint8_t> &p_data);
void call_rpc_set_server_controlled(int p_recipient, int p_peer, bool p_server_controlled);

void rpc_receive_inputs(int p_peer, const Vector<uint8_t> &p_data);
void rpc_set_server_controlled(int p_peer, bool p_server_controlled);

public: // ---------------------------------------------------------------- APIs
void set_settings(Settings &p_settings);
Expand Down Expand Up @@ -526,8 +523,6 @@ class SceneSynchronizerBase {
void reset_synchronizer_mode();
void clear();

void notify_controller_control_mode_changed(PeerNetworkedController *controller);

void clear_peers();

void detect_and_signal_changed_variables(int p_flags);
Expand Down

0 comments on commit 9744bee

Please sign in to comment.