Merge pull request #63049 from Faless/mp/4.x_as_module

This commit is contained in:
Rémi Verschelde 2022-07-28 20:46:31 +02:00 committed by GitHub
commit 14d021287b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
80 changed files with 1819 additions and 1388 deletions

View file

@ -954,8 +954,8 @@ void GDScript::get_members(HashSet<StringName> *p_members) {
}
}
const Vector<Multiplayer::RPCConfig> GDScript::get_rpc_methods() const {
return rpc_functions;
const Variant GDScript::get_rpc_config() const {
return rpc_config;
}
Variant GDScript::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
@ -1212,9 +1212,9 @@ void GDScript::_save_orphaned_subclasses() {
void GDScript::_init_rpc_methods_properties() {
// Copy the base rpc methods so we don't mask their IDs.
rpc_functions.clear();
rpc_config.clear();
if (base.is_valid()) {
rpc_functions = base->rpc_functions;
rpc_config = base->rpc_config.duplicate();
}
GDScript *cscript = this;
@ -1222,12 +1222,9 @@ void GDScript::_init_rpc_methods_properties() {
while (cscript) {
// RPC Methods
for (KeyValue<StringName, GDScriptFunction *> &E : cscript->member_functions) {
Multiplayer::RPCConfig config = E.value->get_rpc_config();
if (config.rpc_mode != Multiplayer::RPC_MODE_DISABLED) {
config.name = E.value->get_name();
if (rpc_functions.find(config) == -1) {
rpc_functions.push_back(config);
}
Variant config = E.value->get_rpc_config();
if (config.get_type() != Variant::NIL) {
rpc_config[E.value->get_name()] = config;
}
}
@ -1241,9 +1238,6 @@ void GDScript::_init_rpc_methods_properties() {
cscript = nullptr;
}
}
// Sort so we are 100% that they are always the same.
rpc_functions.sort_custom<Multiplayer::SortRPCConfig>();
}
GDScript::~GDScript() {
@ -1408,9 +1402,7 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
while (sl) {
HashMap<StringName, GDScriptFunction *>::ConstIterator E = sl->member_functions.find(p_name);
if (E) {
Multiplayer::RPCConfig config;
config.name = p_name;
if (sptr->rpc_functions.find(config) != -1) {
if (sptr->rpc_config.has(p_name)) {
r_ret = Callable(memnew(GDScriptRPCCallable(this->owner, E->key)));
} else {
r_ret = Callable(this->owner, E->key);
@ -1629,8 +1621,8 @@ ScriptLanguage *GDScriptInstance::get_language() {
return GDScriptLanguage::get_singleton();
}
const Vector<Multiplayer::RPCConfig> GDScriptInstance::get_rpc_methods() const {
return script->get_rpc_methods();
const Variant GDScriptInstance::get_rpc_config() const {
return script->get_rpc_config();
}
void GDScriptInstance::reload_members() {

View file

@ -87,7 +87,7 @@ class GDScript : public Script {
HashMap<StringName, MemberInfo> member_indices; //members are just indices to the instantiated script.
HashMap<StringName, Ref<GDScript>> subclasses;
HashMap<StringName, Vector<StringName>> _signals;
Vector<Multiplayer::RPCConfig> rpc_functions;
Dictionary rpc_config;
#ifdef TOOLS_ENABLED
@ -250,7 +250,7 @@ public:
virtual void get_constants(HashMap<StringName, Variant> *p_constants) override;
virtual void get_members(HashSet<StringName> *p_members) override;
virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override;
virtual const Variant get_rpc_config() const override;
#ifdef TOOLS_ENABLED
virtual bool is_placeholder_fallback_enabled() const override { return placeholder_fallback_enabled; }
@ -304,7 +304,7 @@ public:
void reload_members();
virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const;
virtual const Variant get_rpc_config() const;
GDScriptInstance();
~GDScriptInstance();

View file

@ -158,7 +158,7 @@ void GDScriptByteCodeGenerator::end_parameters() {
function->default_arguments.reverse();
}
void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Multiplayer::RPCConfig p_rpc_config, const GDScriptDataType &p_return_type) {
void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Variant p_rpc_config, const GDScriptDataType &p_return_type) {
function = memnew(GDScriptFunction);
debug_stack = EngineDebugger::is_active();

View file

@ -419,7 +419,7 @@ public:
virtual void start_block() override;
virtual void end_block() override;
virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Multiplayer::RPCConfig p_rpc_config, const GDScriptDataType &p_return_type) override;
virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Variant p_rpc_config, const GDScriptDataType &p_return_type) override;
virtual GDScriptFunction *write_end() override;
#ifdef DEBUG_ENABLED

View file

@ -31,7 +31,6 @@
#ifndef GDSCRIPT_CODEGEN_H
#define GDSCRIPT_CODEGEN_H
#include "core/multiplayer/multiplayer.h"
#include "core/string/string_name.h"
#include "core/variant/variant.h"
#include "gdscript_function.h"
@ -80,7 +79,7 @@ public:
virtual void start_block() = 0;
virtual void end_block() = 0;
virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Multiplayer::RPCConfig p_rpc_config, const GDScriptDataType &p_return_type) = 0;
virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Variant p_rpc_config, const GDScriptDataType &p_return_type) = 0;
virtual GDScriptFunction *write_end() = 0;
#ifdef DEBUG_ENABLED

View file

@ -1975,7 +1975,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
StringName func_name;
bool is_static = false;
Multiplayer::RPCConfig rpc_config;
Variant rpc_config;
GDScriptDataType return_type;
return_type.has_type = true;
return_type.kind = GDScriptDataType::BUILTIN;

View file

@ -477,7 +477,7 @@ private:
int _initial_line = 0;
bool _static = false;
Multiplayer::RPCConfig rpc_config;
Variant rpc_config;
GDScript *_script = nullptr;
@ -599,7 +599,7 @@ public:
void disassemble(const Vector<String> &p_code_lines) const;
#endif
_FORCE_INLINE_ Multiplayer::RPCConfig get_rpc_config() const { return rpc_config; }
_FORCE_INLINE_ const Variant get_rpc_config() const { return rpc_config; }
GDScriptFunction();
~GDScriptFunction();
};

View file

@ -35,6 +35,7 @@
#include "core/io/resource_loader.h"
#include "core/math/math_defs.h"
#include "gdscript.h"
#include "scene/main/multiplayer_api.h"
#ifdef DEBUG_ENABLED
#include "core/os/os.h"
@ -145,7 +146,7 @@ GDScriptParser::GDScriptParser() {
// Warning annotations.
register_annotation(MethodInfo("@warning_ignore", PropertyInfo(Variant::STRING, "warning")), AnnotationInfo::CLASS | AnnotationInfo::VARIABLE | AnnotationInfo::SIGNAL | AnnotationInfo::CONSTANT | AnnotationInfo::FUNCTION | AnnotationInfo::STATEMENT, &GDScriptParser::warning_annotations, varray(), true);
// Networking.
register_annotation(MethodInfo("@rpc", PropertyInfo(Variant::STRING, "mode"), PropertyInfo(Variant::STRING, "sync"), PropertyInfo(Variant::STRING, "transfer_mode"), PropertyInfo(Variant::INT, "transfer_channel")), AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<Multiplayer::RPC_MODE_AUTHORITY>, varray("", "", "", 0), true);
register_annotation(MethodInfo("@rpc", PropertyInfo(Variant::STRING, "mode"), PropertyInfo(Variant::STRING, "sync"), PropertyInfo(Variant::STRING, "transfer_mode"), PropertyInfo(Variant::INT, "transfer_channel")), AnnotationInfo::FUNCTION, &GDScriptParser::rpc_annotation, varray("", "", "", 0), true);
}
GDScriptParser::~GDScriptParser() {
@ -3867,16 +3868,21 @@ bool GDScriptParser::warning_annotations(const AnnotationNode *p_annotation, Nod
#endif // DEBUG_ENABLED
}
template <Multiplayer::RPCMode t_mode>
bool GDScriptParser::network_annotations(const AnnotationNode *p_annotation, Node *p_node) {
ERR_FAIL_COND_V_MSG(p_node->type != Node::VARIABLE && p_node->type != Node::FUNCTION, false, vformat(R"("%s" annotation can only be applied to variables and functions.)", p_annotation->name));
bool GDScriptParser::rpc_annotation(const AnnotationNode *p_annotation, Node *p_node) {
ERR_FAIL_COND_V_MSG(p_node->type != Node::FUNCTION, false, vformat(R"("%s" annotation can only be applied to functions.)", p_annotation->name));
Multiplayer::RPCConfig rpc_config;
rpc_config.rpc_mode = t_mode;
FunctionNode *function = static_cast<FunctionNode *>(p_node);
if (function->rpc_config.get_type() != Variant::NIL) {
push_error(R"(RPC annotations can only be used once per function.)", p_annotation);
return false;
}
Dictionary rpc_config;
rpc_config["rpc_mode"] = MultiplayerAPI::RPC_MODE_AUTHORITY;
if (p_annotation->resolved_arguments.size()) {
int last = p_annotation->resolved_arguments.size() - 1;
if (p_annotation->resolved_arguments[last].get_type() == Variant::INT) {
rpc_config.channel = p_annotation->resolved_arguments[last].operator int();
rpc_config["channel"] = p_annotation->resolved_arguments[last].operator int();
last -= 1;
}
if (last > 3) {
@ -3886,37 +3892,25 @@ bool GDScriptParser::network_annotations(const AnnotationNode *p_annotation, Nod
for (int i = last; i >= 0; i--) {
String mode = p_annotation->resolved_arguments[i].operator String();
if (mode == "any_peer") {
rpc_config.rpc_mode = Multiplayer::RPC_MODE_ANY_PEER;
rpc_config["rpc_mode"] = MultiplayerAPI::RPC_MODE_ANY_PEER;
} else if (mode == "authority") {
rpc_config.rpc_mode = Multiplayer::RPC_MODE_AUTHORITY;
rpc_config["rpc_mode"] = MultiplayerAPI::RPC_MODE_AUTHORITY;
} else if (mode == "call_local") {
rpc_config.call_local = true;
rpc_config["call_local"] = true;
} else if (mode == "call_remote") {
rpc_config.call_local = false;
rpc_config["call_local"] = false;
} else if (mode == "reliable") {
rpc_config.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE;
rpc_config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_RELIABLE;
} else if (mode == "unreliable") {
rpc_config.transfer_mode = Multiplayer::TRANSFER_MODE_UNRELIABLE;
rpc_config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_UNRELIABLE;
} else if (mode == "unreliable_ordered") {
rpc_config.transfer_mode = Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED;
rpc_config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_UNRELIABLE_ORDERED;
} else {
push_error(R"(Invalid RPC argument. Must be one of: 'call_local'/'call_remote' (local calls), 'any_peer'/'authority' (permission), 'reliable'/'unreliable'/'unreliable_ordered' (transfer mode).)", p_annotation);
}
}
}
switch (p_node->type) {
case Node::FUNCTION: {
FunctionNode *function = static_cast<FunctionNode *>(p_node);
if (function->rpc_config.rpc_mode != Multiplayer::RPC_MODE_DISABLED) {
push_error(R"(RPC annotations can only be used once per function.)", p_annotation);
return false;
}
function->rpc_config = rpc_config;
break;
}
default:
return false; // Unreachable.
}
function->rpc_config = rpc_config;
return true;
}

View file

@ -32,7 +32,6 @@
#define GDSCRIPT_PARSER_H
#include "core/io/resource.h"
#include "core/multiplayer/multiplayer.h"
#include "core/object/ref_counted.h"
#include "core/object/script_language.h"
#include "core/string/string_name.h"
@ -750,7 +749,7 @@ public:
SuiteNode *body = nullptr;
bool is_static = false;
bool is_coroutine = false;
Multiplayer::RPCConfig rpc_config;
Variant rpc_config;
MethodInfo info;
LambdaNode *source_lambda = nullptr;
#ifdef TOOLS_ENABLED
@ -1371,8 +1370,7 @@ private:
template <PropertyUsageFlags t_usage>
bool export_group_annotations(const AnnotationNode *p_annotation, Node *p_target);
bool warning_annotations(const AnnotationNode *p_annotation, Node *p_target);
template <Multiplayer::RPCMode t_mode>
bool network_annotations(const AnnotationNode *p_annotation, Node *p_target);
bool rpc_annotation(const AnnotationNode *p_annotation, Node *p_target);
// Statements.
Node *parse_statement();
VariableNode *parse_variable();

View file

@ -76,11 +76,11 @@ GDScriptRPCCallable::GDScriptRPCCallable(Object *p_object, const StringName &p_m
ERR_FAIL_COND_MSG(!node, "RPC can only be defined on class that extends Node.");
}
void GDScriptRPCCallable::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
Error GDScriptRPCCallable::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
if (unlikely(!node)) {
r_call_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
return;
return ERR_UNCONFIGURED;
}
r_call_error.error = Callable::CallError::CALL_OK;
node->rpcp(p_peer_id, method, p_arguments, p_argcount);
return node->rpcp(p_peer_id, method, p_arguments, p_argcount);
}

View file

@ -52,7 +52,7 @@ public:
CompareLessFunc get_compare_less_func() const override;
ObjectID get_object() const override;
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
void rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override;
Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override;
GDScriptRPCCallable(Object *p_object, const StringName &p_method);
virtual ~GDScriptRPCCallable() = default;

View file

@ -690,9 +690,7 @@ Dictionary ExtendGDScriptParser::dump_function_api(const GDScriptParser::Functio
ERR_FAIL_NULL_V(p_func, func);
func["name"] = p_func->identifier->name;
func["return_type"] = p_func->get_datatype().to_string();
func["rpc_mode"] = p_func->rpc_config.rpc_mode;
func["rpc_transfer_mode"] = p_func->rpc_config.transfer_mode;
func["rpc_transfer_channel"] = p_func->rpc_config.channel;
func["rpc_config"] = p_func->rpc_config;
Array parameters;
for (int i = 0; i < p_func->parameters.size(); i++) {
Dictionary arg;