Use MultiplayerAPI class for high level networking

Remove networking related logic from Node and SceneTree.
SceneTree now simply relay all networking related stuff to
MultiplayerAPI for compatibility
This commit is contained in:
Fabio Alessandrelli
2018-03-03 18:30:11 +01:00
parent df391cc5be
commit 5081ced57f
4 changed files with 89 additions and 676 deletions

View File

@@ -477,7 +477,7 @@ bool Node::is_network_master() const {
ERR_FAIL_COND_V(!is_inside_tree(), false);
return get_tree()->get_network_unique_id() == data.network_master;
return get_multiplayer_api()->get_network_unique_id() == data.network_master;
}
/***** RPC CONFIG ********/
@@ -667,200 +667,16 @@ Variant Node::_rpc_unreliable_id_bind(const Variant **p_args, int p_argcount, Va
}
void Node::rpcp(int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount) {
ERR_FAIL_COND(!is_inside_tree());
get_multiplayer_api()->rpcp(this, p_peer_id, p_unreliable, p_method, p_arg, p_argcount);
}
bool skip_rpc = false;
bool call_local_native = false;
bool call_local_script = false;
if (p_peer_id == 0 || p_peer_id == get_tree()->get_network_unique_id() || (p_peer_id < 0 && p_peer_id != -get_tree()->get_network_unique_id())) {
//check that send mode can use local call
Map<StringName, RPCMode>::Element *E = data.rpc_methods.find(p_method);
if (E) {
switch (E->get()) {
case RPC_MODE_DISABLED: {
//do nothing
} break;
case RPC_MODE_REMOTE: {
//do nothing also, no need to call local
} break;
case RPC_MODE_SYNC: {
//call it, sync always results in call
call_local_native = true;
} break;
case RPC_MODE_MASTER: {
call_local_native = is_network_master();
if (call_local_native) {
skip_rpc = true; //no other master so..
}
} break;
case RPC_MODE_SLAVE: {
call_local_native = !is_network_master();
} break;
}
}
if (call_local_native) {
// done below
} else if (get_script_instance()) {
//attempt with script
ScriptInstance::RPCMode rpc_mode = get_script_instance()->get_rpc_mode(p_method);
switch (rpc_mode) {
case ScriptInstance::RPC_MODE_DISABLED: {
//do nothing
} break;
case ScriptInstance::RPC_MODE_REMOTE: {
//do nothing also, no need to call local
} break;
case ScriptInstance::RPC_MODE_SYNC: {
//call it, sync always results in call
call_local_script = true;
} break;
case ScriptInstance::RPC_MODE_MASTER: {
call_local_script = is_network_master();
if (call_local_script) {
skip_rpc = true; //no other master so..
}
} break;
case ScriptInstance::RPC_MODE_SLAVE: {
call_local_script = !is_network_master();
} break;
}
}
}
if (!skip_rpc) {
get_tree()->_rpc(this, p_peer_id, p_unreliable, false, p_method, p_arg, p_argcount);
}
if (call_local_native) {
Variant::CallError ce;
call(p_method, p_arg, p_argcount, ce);
if (ce.error != Variant::CallError::CALL_OK) {
String error = Variant::get_call_error_text(this, p_method, p_arg, p_argcount, ce);
error = "rpc() aborted in local call: - " + error;
ERR_PRINTS(error);
return;
}
}
if (call_local_script) {
Variant::CallError ce;
ce.error = Variant::CallError::CALL_OK;
get_script_instance()->call(p_method, p_arg, p_argcount, ce);
if (ce.error != Variant::CallError::CALL_OK) {
String error = Variant::get_call_error_text(this, p_method, p_arg, p_argcount, ce);
error = "rpc() aborted in script local call: - " + error;
ERR_PRINTS(error);
return;
}
}
void Node::rsetp(int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value) {
ERR_FAIL_COND(!is_inside_tree());
get_multiplayer_api()->rsetp(this, p_peer_id, p_unreliable, p_property, p_value);
}
/******** RSET *********/
void Node::rsetp(int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value) {
ERR_FAIL_COND(!is_inside_tree());
bool skip_rset = false;
if (p_peer_id == 0 || p_peer_id == get_tree()->get_network_unique_id() || (p_peer_id < 0 && p_peer_id != -get_tree()->get_network_unique_id())) {
//check that send mode can use local call
bool set_local = false;
Map<StringName, RPCMode>::Element *E = data.rpc_properties.find(p_property);
if (E) {
switch (E->get()) {
case RPC_MODE_DISABLED: {
//do nothing
} break;
case RPC_MODE_REMOTE: {
//do nothing also, no need to call local
} break;
case RPC_MODE_SYNC: {
//call it, sync always results in call
set_local = true;
} break;
case RPC_MODE_MASTER: {
set_local = is_network_master();
if (set_local) {
skip_rset = true;
}
} break;
case RPC_MODE_SLAVE: {
set_local = !is_network_master();
} break;
}
}
if (set_local) {
bool valid;
set(p_property, p_value, &valid);
if (!valid) {
String error = "rset() aborted in local set, property not found: - " + String(p_property);
ERR_PRINTS(error);
return;
}
} else if (get_script_instance()) {
//attempt with script
ScriptInstance::RPCMode rpc_mode = get_script_instance()->get_rset_mode(p_property);
switch (rpc_mode) {
case ScriptInstance::RPC_MODE_DISABLED: {
//do nothing
} break;
case ScriptInstance::RPC_MODE_REMOTE: {
//do nothing also, no need to call local
} break;
case ScriptInstance::RPC_MODE_SYNC: {
//call it, sync always results in call
set_local = true;
} break;
case ScriptInstance::RPC_MODE_MASTER: {
set_local = is_network_master();
if (set_local) {
skip_rset = true;
}
} break;
case ScriptInstance::RPC_MODE_SLAVE: {
set_local = !is_network_master();
} break;
}
if (set_local) {
bool valid = get_script_instance()->set(p_property, p_value);
if (!valid) {
String error = "rset() aborted in local script set, property not found: - " + String(p_property);
ERR_PRINTS(error);
return;
}
}
}
}
if (skip_rset)
return;
const Variant *vptr = &p_value;
get_tree()->_rpc(this, p_peer_id, p_unreliable, true, p_property, &vptr, 1);
}
void Node::rset(const StringName &p_property, const Variant &p_value) {
rsetp(0, false, p_property, p_value);
@@ -882,6 +698,30 @@ void Node::rset_unreliable_id(int p_peer_id, const StringName &p_property, const
}
//////////// end of rpc
Ref<MultiplayerAPI> Node::get_multiplayer_api() const {
if (multiplayer_api.is_valid())
return multiplayer_api;
if (!is_inside_tree())
return Ref<MultiplayerAPI>();
return get_tree()->get_multiplayer_api();
}
Ref<MultiplayerAPI> Node::get_custom_multiplayer_api() const {
return multiplayer_api;
}
void Node::set_custom_multiplayer_api(Ref<MultiplayerAPI> p_multiplayer_api) {
multiplayer_api = p_multiplayer_api;
}
const Map<StringName, Node::RPCMode>::Element *Node::get_node_rpc_mode(const StringName &p_method) {
return data.rpc_methods.find(p_method);
}
const Map<StringName, Node::RPCMode>::Element *Node::get_node_rset_mode(const StringName &p_property) {
return data.rpc_properties.find(p_property);
}
bool Node::can_call_rpc(const StringName &p_method, int p_from) const {
@@ -2886,6 +2726,9 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_network_master"), &Node::is_network_master);
ClassDB::bind_method(D_METHOD("get_multiplayer_api"), &Node::get_multiplayer_api);
ClassDB::bind_method(D_METHOD("get_custom_multiplayer_api"), &Node::get_custom_multiplayer_api);
ClassDB::bind_method(D_METHOD("set_custom_multiplayer_api", "api"), &Node::set_custom_multiplayer_api);
ClassDB::bind_method(D_METHOD("rpc_config", "method", "mode"), &Node::rpc_config);
ClassDB::bind_method(D_METHOD("rset_config", "property", "mode"), &Node::rset_config);
@@ -2967,6 +2810,8 @@ void Node::_bind_methods() {
ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "name", PROPERTY_HINT_NONE, "", 0), "set_name", "get_name");
ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "filename", PROPERTY_HINT_NONE, "", 0), "set_filename", "get_filename");
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "owner", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_owner", "get_owner");
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "multiplayer_api", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", 0), "", "get_multiplayer_api");
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "custom_multiplayer_api", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", 0), "set_custom_multiplayer_api", "get_custom_multiplayer_api");
BIND_VMETHOD(MethodInfo("_process", PropertyInfo(Variant::REAL, "delta")));
BIND_VMETHOD(MethodInfo("_physics_process", PropertyInfo(Variant::REAL, "delta")));