Optmized data sent during RPC and RSet calls.

- Now is sent the method ID rather the full function name.
- The passed IDs (Node and Method) are compressed so to use less possible space.
- The variant (INT and BOOL) is now encoded and compressed so to use much less data.
- Optimized RPCMode retrieval for GDScript functions.
- Added checksum to assert the methods are the same across peers.

This work has been kindly sponsored by IMVU.
This commit is contained in:
Andrea Catania 2020-02-12 11:51:50 +01:00
parent 70dd7f4e1a
commit eb07e87981
19 changed files with 1580 additions and 292 deletions

View file

@ -30,6 +30,8 @@
#include "nativescript.h"
#include <stdint.h>
#include "gdnative/gdnative.h"
#include "core/core_string_names.h"
@ -402,6 +404,262 @@ void NativeScript::get_script_property_list(List<PropertyInfo> *p_list) const {
}
}
Vector<ScriptNetData> NativeScript::get_rpc_methods() const {
Vector<ScriptNetData> v;
NativeScriptDesc *script_data = get_script_desc();
while (script_data) {
for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) {
if (E->get().rpc_mode != GODOT_METHOD_RPC_MODE_DISABLED) {
ScriptNetData nd;
nd.name = E->key();
nd.mode = MultiplayerAPI::RPCMode(E->get().rpc_mode);
v.push_back(nd);
}
}
script_data = script_data->base_data;
}
return v;
}
uint16_t NativeScript::get_rpc_method_id(const StringName &p_method) const {
NativeScriptDesc *script_data = get_script_desc();
while (script_data) {
Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method);
if (E) {
return E->get().rpc_method_id;
}
script_data = script_data->base_data;
}
return UINT16_MAX;
}
StringName NativeScript::get_rpc_method(uint16_t p_id) const {
ERR_FAIL_COND_V(p_id == UINT16_MAX, StringName());
NativeScriptDesc *script_data = get_script_desc();
while (script_data) {
for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) {
if (E->get().rpc_method_id == p_id) {
return E->key();
}
}
script_data = script_data->base_data;
}
return StringName();
}
MultiplayerAPI::RPCMode NativeScript::get_rpc_mode_by_id(uint16_t p_id) const {
ERR_FAIL_COND_V(p_id == UINT16_MAX, MultiplayerAPI::RPC_MODE_DISABLED);
NativeScriptDesc *script_data = get_script_desc();
while (script_data) {
for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) {
if (E->get().rpc_method_id == p_id) {
switch (E->get().rpc_mode) {
case GODOT_METHOD_RPC_MODE_DISABLED:
return MultiplayerAPI::RPC_MODE_DISABLED;
case GODOT_METHOD_RPC_MODE_REMOTE:
return MultiplayerAPI::RPC_MODE_REMOTE;
case GODOT_METHOD_RPC_MODE_MASTER:
return MultiplayerAPI::RPC_MODE_MASTER;
case GODOT_METHOD_RPC_MODE_PUPPET:
return MultiplayerAPI::RPC_MODE_PUPPET;
case GODOT_METHOD_RPC_MODE_REMOTESYNC:
return MultiplayerAPI::RPC_MODE_REMOTESYNC;
case GODOT_METHOD_RPC_MODE_MASTERSYNC:
return MultiplayerAPI::RPC_MODE_MASTERSYNC;
case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
default:
return MultiplayerAPI::RPC_MODE_DISABLED;
}
}
}
script_data = script_data->base_data;
}
return MultiplayerAPI::RPC_MODE_DISABLED;
}
MultiplayerAPI::RPCMode NativeScript::get_rpc_mode(const StringName &p_method) const {
NativeScriptDesc *script_data = get_script_desc();
while (script_data) {
Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method);
if (E) {
switch (E->get().rpc_mode) {
case GODOT_METHOD_RPC_MODE_DISABLED:
return MultiplayerAPI::RPC_MODE_DISABLED;
case GODOT_METHOD_RPC_MODE_REMOTE:
return MultiplayerAPI::RPC_MODE_REMOTE;
case GODOT_METHOD_RPC_MODE_MASTER:
return MultiplayerAPI::RPC_MODE_MASTER;
case GODOT_METHOD_RPC_MODE_PUPPET:
return MultiplayerAPI::RPC_MODE_PUPPET;
case GODOT_METHOD_RPC_MODE_REMOTESYNC:
return MultiplayerAPI::RPC_MODE_REMOTESYNC;
case GODOT_METHOD_RPC_MODE_MASTERSYNC:
return MultiplayerAPI::RPC_MODE_MASTERSYNC;
case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
default:
return MultiplayerAPI::RPC_MODE_DISABLED;
}
}
script_data = script_data->base_data;
}
return MultiplayerAPI::RPC_MODE_DISABLED;
}
Vector<ScriptNetData> NativeScript::get_rset_properties() const {
Vector<ScriptNetData> v;
NativeScriptDesc *script_data = get_script_desc();
while (script_data) {
for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) {
if (E.get().rset_mode != GODOT_METHOD_RPC_MODE_DISABLED) {
ScriptNetData nd;
nd.name = E.key();
nd.mode = MultiplayerAPI::RPCMode(E.get().rset_mode);
v.push_back(nd);
}
}
script_data = script_data->base_data;
}
return v;
}
uint16_t NativeScript::get_rset_property_id(const StringName &p_variable) const {
NativeScriptDesc *script_data = get_script_desc();
while (script_data) {
OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.find(p_variable);
if (E) {
return E.get().rset_property_id;
}
script_data = script_data->base_data;
}
return UINT16_MAX;
}
StringName NativeScript::get_rset_property(uint16_t p_id) const {
ERR_FAIL_COND_V(p_id == UINT16_MAX, StringName());
NativeScriptDesc *script_data = get_script_desc();
while (script_data) {
for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) {
if (E.get().rset_property_id == p_id) {
return E.key();
}
}
script_data = script_data->base_data;
}
return StringName();
}
MultiplayerAPI::RPCMode NativeScript::get_rset_mode_by_id(uint16_t p_id) const {
ERR_FAIL_COND_V(p_id == UINT16_MAX, MultiplayerAPI::RPC_MODE_DISABLED);
NativeScriptDesc *script_data = get_script_desc();
while (script_data) {
for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) {
if (E.get().rset_property_id == p_id) {
switch (E.get().rset_mode) {
case GODOT_METHOD_RPC_MODE_DISABLED:
return MultiplayerAPI::RPC_MODE_DISABLED;
case GODOT_METHOD_RPC_MODE_REMOTE:
return MultiplayerAPI::RPC_MODE_REMOTE;
case GODOT_METHOD_RPC_MODE_MASTER:
return MultiplayerAPI::RPC_MODE_MASTER;
case GODOT_METHOD_RPC_MODE_PUPPET:
return MultiplayerAPI::RPC_MODE_PUPPET;
case GODOT_METHOD_RPC_MODE_REMOTESYNC:
return MultiplayerAPI::RPC_MODE_REMOTESYNC;
case GODOT_METHOD_RPC_MODE_MASTERSYNC:
return MultiplayerAPI::RPC_MODE_MASTERSYNC;
case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
default:
return MultiplayerAPI::RPC_MODE_DISABLED;
}
}
}
script_data = script_data->base_data;
}
return MultiplayerAPI::RPC_MODE_DISABLED;
}
MultiplayerAPI::RPCMode NativeScript::get_rset_mode(const StringName &p_variable) const {
NativeScriptDesc *script_data = get_script_desc();
while (script_data) {
OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.find(p_variable);
if (E) {
switch (E.get().rset_mode) {
case GODOT_METHOD_RPC_MODE_DISABLED:
return MultiplayerAPI::RPC_MODE_DISABLED;
case GODOT_METHOD_RPC_MODE_REMOTE:
return MultiplayerAPI::RPC_MODE_REMOTE;
case GODOT_METHOD_RPC_MODE_MASTER:
return MultiplayerAPI::RPC_MODE_MASTER;
case GODOT_METHOD_RPC_MODE_PUPPET:
return MultiplayerAPI::RPC_MODE_PUPPET;
case GODOT_METHOD_RPC_MODE_REMOTESYNC:
return MultiplayerAPI::RPC_MODE_REMOTESYNC;
case GODOT_METHOD_RPC_MODE_MASTERSYNC:
return MultiplayerAPI::RPC_MODE_MASTERSYNC;
case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
default:
return MultiplayerAPI::RPC_MODE_DISABLED;
}
}
script_data = script_data->base_data;
}
return MultiplayerAPI::RPC_MODE_DISABLED;
}
String NativeScript::get_class_documentation() const {
NativeScriptDesc *script_data = get_script_desc();
@ -803,72 +1061,44 @@ Ref<Script> NativeScriptInstance::get_script() const {
return script;
}
Vector<ScriptNetData> NativeScriptInstance::get_rpc_methods() const {
return script->get_rpc_methods();
}
uint16_t NativeScriptInstance::get_rpc_method_id(const StringName &p_method) const {
return script->get_rpc_method_id(p_method);
}
StringName NativeScriptInstance::get_rpc_method(uint16_t p_id) const {
return script->get_rpc_method(p_id);
}
MultiplayerAPI::RPCMode NativeScriptInstance::get_rpc_mode_by_id(uint16_t p_id) const {
return script->get_rpc_mode_by_id(p_id);
}
MultiplayerAPI::RPCMode NativeScriptInstance::get_rpc_mode(const StringName &p_method) const {
return script->get_rpc_mode(p_method);
}
NativeScriptDesc *script_data = GET_SCRIPT_DESC();
Vector<ScriptNetData> NativeScriptInstance::get_rset_properties() const {
return script->get_rset_properties();
}
while (script_data) {
uint16_t NativeScriptInstance::get_rset_property_id(const StringName &p_variable) const {
return script->get_rset_property_id(p_variable);
}
Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method);
if (E) {
switch (E->get().rpc_mode) {
case GODOT_METHOD_RPC_MODE_DISABLED:
return MultiplayerAPI::RPC_MODE_DISABLED;
case GODOT_METHOD_RPC_MODE_REMOTE:
return MultiplayerAPI::RPC_MODE_REMOTE;
case GODOT_METHOD_RPC_MODE_MASTER:
return MultiplayerAPI::RPC_MODE_MASTER;
case GODOT_METHOD_RPC_MODE_PUPPET:
return MultiplayerAPI::RPC_MODE_PUPPET;
case GODOT_METHOD_RPC_MODE_REMOTESYNC:
return MultiplayerAPI::RPC_MODE_REMOTESYNC;
case GODOT_METHOD_RPC_MODE_MASTERSYNC:
return MultiplayerAPI::RPC_MODE_MASTERSYNC;
case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
default:
return MultiplayerAPI::RPC_MODE_DISABLED;
}
}
StringName NativeScriptInstance::get_rset_property(uint16_t p_id) const {
return script->get_rset_property(p_id);
}
script_data = script_data->base_data;
}
return MultiplayerAPI::RPC_MODE_DISABLED;
MultiplayerAPI::RPCMode NativeScriptInstance::get_rset_mode_by_id(uint16_t p_id) const {
return script->get_rset_mode_by_id(p_id);
}
MultiplayerAPI::RPCMode NativeScriptInstance::get_rset_mode(const StringName &p_variable) const {
NativeScriptDesc *script_data = GET_SCRIPT_DESC();
while (script_data) {
OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.find(p_variable);
if (E) {
switch (E.get().rset_mode) {
case GODOT_METHOD_RPC_MODE_DISABLED:
return MultiplayerAPI::RPC_MODE_DISABLED;
case GODOT_METHOD_RPC_MODE_REMOTE:
return MultiplayerAPI::RPC_MODE_REMOTE;
case GODOT_METHOD_RPC_MODE_MASTER:
return MultiplayerAPI::RPC_MODE_MASTER;
case GODOT_METHOD_RPC_MODE_PUPPET:
return MultiplayerAPI::RPC_MODE_PUPPET;
case GODOT_METHOD_RPC_MODE_REMOTESYNC:
return MultiplayerAPI::RPC_MODE_REMOTESYNC;
case GODOT_METHOD_RPC_MODE_MASTERSYNC:
return MultiplayerAPI::RPC_MODE_MASTERSYNC;
case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
default:
return MultiplayerAPI::RPC_MODE_DISABLED;
}
}
script_data = script_data->base_data;
}
return MultiplayerAPI::RPC_MODE_DISABLED;
return script->get_rset_mode(p_variable);
}
ScriptLanguage *NativeScriptInstance::get_language() {