1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-13 13:31:48 +00:00

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

@@ -93,10 +93,42 @@ void PluginScriptInstance::notification(int p_notification) {
_desc->notification(_data, p_notification);
}
Vector<ScriptNetData> PluginScriptInstance::get_rpc_methods() const {
return _script->get_rpc_methods();
}
uint16_t PluginScriptInstance::get_rpc_method_id(const StringName &p_variable) const {
return _script->get_rpc_method_id(p_variable);
}
StringName PluginScriptInstance::get_rpc_method(uint16_t p_id) const {
return _script->get_rpc_method(p_id);
}
MultiplayerAPI::RPCMode PluginScriptInstance::get_rpc_mode_by_id(uint16_t p_id) const {
return _script->get_rpc_mode_by_id(p_id);
}
MultiplayerAPI::RPCMode PluginScriptInstance::get_rpc_mode(const StringName &p_method) const {
return _script->get_rpc_mode(p_method);
}
Vector<ScriptNetData> PluginScriptInstance::get_rset_properties() const {
return _script->get_rset_properties();
}
uint16_t PluginScriptInstance::get_rset_property_id(const StringName &p_variable) const {
return _script->get_rset_property_id(p_variable);
}
StringName PluginScriptInstance::get_rset_property(uint16_t p_id) const {
return _script->get_rset_property(p_id);
}
MultiplayerAPI::RPCMode PluginScriptInstance::get_rset_mode_by_id(uint16_t p_id) const {
return _script->get_rset_mode_by_id(p_id);
}
MultiplayerAPI::RPCMode PluginScriptInstance::get_rset_mode(const StringName &p_variable) const {
return _script->get_rset_mode(p_variable);
}

View File

@@ -76,7 +76,16 @@ public:
void set_path(const String &p_path);
virtual Vector<ScriptNetData> get_rpc_methods() const;
virtual uint16_t get_rpc_method_id(const StringName &p_method) const;
virtual StringName get_rpc_method(uint16_t p_id) const;
virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const;
virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
virtual Vector<ScriptNetData> get_rset_properties() const;
virtual uint16_t get_rset_property_id(const StringName &p_variable) const;
virtual StringName get_rset_property(uint16_t p_id) const;
virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const;
virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
virtual void refcount_incremented();

View File

@@ -34,6 +34,8 @@
#include "pluginscript_instance.h"
#include "pluginscript_script.h"
#include <stdint.h>
#ifdef DEBUG_ENABLED
#define __ASSERT_SCRIPT_REASON "Cannot retrieve PluginScript class for this script, is your code correct?"
#define ASSERT_SCRIPT_VALID() \
@@ -298,18 +300,31 @@ Error PluginScript::reload(bool p_keep_state) {
_member_lines[*key] = (*members)[*key];
}
Array *methods = (Array *)&manifest.methods;
_rpc_methods.clear();
_rpc_variables.clear();
if (_ref_base_parent.is_valid()) {
_rpc_methods = _ref_base_parent->get_rpc_methods();
_rpc_variables = _ref_base_parent->get_rset_properties();
}
for (int i = 0; i < methods->size(); ++i) {
Dictionary v = (*methods)[i];
MethodInfo mi = MethodInfo::from_dict(v);
_methods_info[mi.name] = mi;
// rpc_mode is passed as an optional field and is not part of MethodInfo
Variant var = v["rpc_mode"];
if (var == Variant()) {
_methods_rpc_mode[mi.name] = MultiplayerAPI::RPC_MODE_DISABLED;
} else {
_methods_rpc_mode[mi.name] = MultiplayerAPI::RPCMode(int(var));
if (var != Variant()) {
ScriptNetData nd;
nd.name = mi.name;
nd.mode = MultiplayerAPI::RPCMode(int(var));
if (_rpc_methods.find(nd) == -1) {
_rpc_methods.push_back(nd);
}
}
}
// Sort so we are 100% that they are always the same.
_rpc_methods.sort_custom<SortNetData>();
Array *signals = (Array *)&manifest.signals;
for (int i = 0; i < signals->size(); ++i) {
Variant v = (*signals)[i];
@@ -324,13 +339,19 @@ Error PluginScript::reload(bool p_keep_state) {
_properties_default_values[pi.name] = v["default_value"];
// rset_mode is passed as an optional field and is not part of PropertyInfo
Variant var = v["rset_mode"];
if (var == Variant()) {
_methods_rpc_mode[pi.name] = MultiplayerAPI::RPC_MODE_DISABLED;
} else {
_methods_rpc_mode[pi.name] = MultiplayerAPI::RPCMode(int(var));
if (var != Variant()) {
ScriptNetData nd;
nd.name = pi.name;
nd.mode = MultiplayerAPI::RPCMode(int(var));
if (_rpc_variables.find(nd) == -1) {
_rpc_variables.push_back(nd);
}
}
}
// Sort so we are 100% that they are always the same.
_rpc_variables.sort_custom<SortNetData>();
#ifdef TOOLS_ENABLED
/*for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) {
@@ -455,24 +476,70 @@ int PluginScript::get_member_line(const StringName &p_member) const {
return -1;
}
Vector<ScriptNetData> PluginScript::get_rpc_methods() const {
return _rpc_methods;
}
uint16_t PluginScript::get_rpc_method_id(const StringName &p_method) const {
ASSERT_SCRIPT_VALID_V(UINT16_MAX);
for (int i = 0; i < _rpc_methods.size(); i++) {
if (_rpc_methods[i].name == p_method) {
return i;
}
}
return UINT16_MAX;
}
StringName PluginScript::get_rpc_method(const uint16_t p_rpc_method_id) const {
ASSERT_SCRIPT_VALID_V(StringName());
if (p_rpc_method_id >= _rpc_methods.size())
return StringName();
return _rpc_methods[p_rpc_method_id].name;
}
MultiplayerAPI::RPCMode PluginScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED);
if (p_rpc_method_id >= _rpc_methods.size())
return MultiplayerAPI::RPC_MODE_DISABLED;
return _rpc_methods[p_rpc_method_id].mode;
}
MultiplayerAPI::RPCMode PluginScript::get_rpc_mode(const StringName &p_method) const {
ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED);
const Map<StringName, MultiplayerAPI::RPCMode>::Element *e = _methods_rpc_mode.find(p_method);
if (e != NULL) {
return e->get();
} else {
return MultiplayerAPI::RPC_MODE_DISABLED;
return get_rpc_mode_by_id(get_rpc_method_id(p_method));
}
Vector<ScriptNetData> PluginScript::get_rset_properties() const {
return _rpc_variables;
}
uint16_t PluginScript::get_rset_property_id(const StringName &p_property) const {
ASSERT_SCRIPT_VALID_V(UINT16_MAX);
for (int i = 0; i < _rpc_variables.size(); i++) {
if (_rpc_variables[i].name == p_property) {
return i;
}
}
return UINT16_MAX;
}
StringName PluginScript::get_rset_property(const uint16_t p_rset_property_id) const {
ASSERT_SCRIPT_VALID_V(StringName());
if (p_rset_property_id >= _rpc_variables.size())
return StringName();
return _rpc_variables[p_rset_property_id].name;
}
MultiplayerAPI::RPCMode PluginScript::get_rset_mode_by_id(const uint16_t p_rset_property_id) const {
ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED);
if (p_rset_property_id >= _rpc_variables.size())
return MultiplayerAPI::RPC_MODE_DISABLED;
return _rpc_variables[p_rset_property_id].mode;
}
MultiplayerAPI::RPCMode PluginScript::get_rset_mode(const StringName &p_variable) const {
ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED);
const Map<StringName, MultiplayerAPI::RPCMode>::Element *e = _variables_rset_mode.find(p_variable);
if (e != NULL) {
return e->get();
} else {
return MultiplayerAPI::RPC_MODE_DISABLED;
}
return get_rset_mode_by_id(get_rset_property_id(p_variable));
}
PluginScript::PluginScript() :

View File

@@ -60,8 +60,8 @@ private:
Map<StringName, PropertyInfo> _properties_info;
Map<StringName, MethodInfo> _signals_info;
Map<StringName, MethodInfo> _methods_info;
Map<StringName, MultiplayerAPI::RPCMode> _variables_rset_mode;
Map<StringName, MultiplayerAPI::RPCMode> _methods_rpc_mode;
Vector<ScriptNetData> _rpc_methods;
Vector<ScriptNetData> _rpc_variables;
Set<Object *> _instances;
//exported members
@@ -118,8 +118,17 @@ public:
virtual int get_member_line(const StringName &p_member) const;
MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
virtual Vector<ScriptNetData> get_rpc_methods() const;
virtual uint16_t get_rpc_method_id(const StringName &p_method) const;
virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const;
virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const;
virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
virtual Vector<ScriptNetData> get_rset_properties() const;
virtual uint16_t get_rset_property_id(const StringName &p_property) const;
virtual StringName get_rset_property(const uint16_t p_rset_property_id) const;
virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_rpc_method_id) const;
virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
PluginScript();
void init(PluginScriptLanguage *language);