diff options
111 files changed, 2221 insertions, 599 deletions
diff --git a/core/func_ref.cpp b/core/func_ref.cpp index 2dffb30bab..e20188c813 100644 --- a/core/func_ref.cpp +++ b/core/func_ref.cpp @@ -32,7 +32,7 @@ Variant FuncRef::call_func(const Variant **p_args, int p_argcount, Variant::CallError &r_error) { - if (id == 0) { + if (id.is_null()) { r_error.error = Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL; return Variant(); } @@ -48,7 +48,7 @@ Variant FuncRef::call_func(const Variant **p_args, int p_argcount, Variant::Call Variant FuncRef::call_funcv(const Array &p_args) { - ERR_FAIL_COND_V(id == 0, Variant()); + ERR_FAIL_COND_V(id.is_null(), Variant()); Object *obj = ObjectDB::get_instance(id); @@ -69,7 +69,7 @@ void FuncRef::set_function(const StringName &p_func) { } bool FuncRef::is_valid() const { - if (id == 0) + if (id.is_null()) return false; Object *obj = ObjectDB::get_instance(id); @@ -95,6 +95,5 @@ void FuncRef::_bind_methods() { ClassDB::bind_method(D_METHOD("is_valid"), &FuncRef::is_valid); } -FuncRef::FuncRef() : - id(0) { +FuncRef::FuncRef() { } diff --git a/core/hashfuncs.h b/core/hashfuncs.h index 647e8a40b2..d6cf04e560 100644 --- a/core/hashfuncs.h +++ b/core/hashfuncs.h @@ -34,10 +34,10 @@ #include "core/math/math_defs.h" #include "core/math/math_funcs.h" #include "core/node_path.h" +#include "core/object_id.h" #include "core/string_name.h" #include "core/typedefs.h" #include "core/ustring.h" - /** * Hashing functions */ @@ -137,6 +137,7 @@ struct HashMapHasherDefault { static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); } static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); } static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); } + static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); } static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); } static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); } diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index e847a9cf0c..fdce9db2a0 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -53,8 +53,7 @@ ObjectID EncodedObjectAsID::get_object_id() const { return id; } -EncodedObjectAsID::EncodedObjectAsID() : - id(0) { +EncodedObjectAsID::EncodedObjectAsID() { } #define _S(a) ((int32_t)a) @@ -386,11 +385,11 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int if (type & ENCODE_FLAG_OBJECT_AS_ID) { //this _is_ allowed ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA); - ObjectID val = decode_uint64(buf); + ObjectID val = ObjectID(decode_uint64(buf)); if (r_len) (*r_len) += 8; - if (val == 0) { + if (val.is_null()) { r_variant = (Object *)NULL; } else { Ref<EncodedObjectAsID> obj_as_id; @@ -1129,7 +1128,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo if (buf) { Object *obj = p_variant; - ObjectID id = 0; + ObjectID id; if (obj && ObjectDB::instance_validate(obj)) { id = obj->get_instance_id(); } diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp index fbed460a4e..ce641dd0f5 100644 --- a/core/io/multiplayer_api.cpp +++ b/core/io/multiplayer_api.cpp @@ -32,6 +32,7 @@ #include "core/io/marshalls.h" #include "scene/main/node.h" +#include <stdint.h> #ifdef DEBUG_ENABLED #include "core/os/os.h" @@ -180,7 +181,8 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_ } #endif - uint8_t packet_type = p_packet[0]; + // Extract the `packet_type` from the LSB three bits: + uint8_t packet_type = p_packet[0] & 7; switch (packet_type) { @@ -197,31 +199,80 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_ case NETWORK_COMMAND_REMOTE_CALL: case NETWORK_COMMAND_REMOTE_SET: { - ERR_FAIL_COND_MSG(p_packet_len < 6, "Invalid packet received. Size too small."); - - Node *node = _process_get_node(p_from, p_packet, p_packet_len); + // Extract packet meta + int packet_min_size = 1; + int name_id_offset = 1; + ERR_FAIL_COND_MSG(p_packet_len < packet_min_size, "Invalid packet received. Size too small."); + // Compute the meta size, which depends on the compression level. + int node_id_compression = (p_packet[0] & 24) >> 3; + int name_id_compression = (p_packet[0] & 32) >> 5; + + switch (node_id_compression) { + case NETWORK_NODE_ID_COMPRESSION_8: + packet_min_size += 1; + name_id_offset += 1; + break; + case NETWORK_NODE_ID_COMPRESSION_16: + packet_min_size += 2; + name_id_offset += 2; + break; + case NETWORK_NODE_ID_COMPRESSION_32: + packet_min_size += 4; + name_id_offset += 4; + break; + default: + ERR_FAIL_MSG("Was not possible to extract the node id compression mode."); + } + switch (name_id_compression) { + case NETWORK_NAME_ID_COMPRESSION_8: + packet_min_size += 1; + break; + case NETWORK_NAME_ID_COMPRESSION_16: + packet_min_size += 2; + break; + default: + ERR_FAIL_MSG("Was not possible to extract the name id compression mode."); + } + ERR_FAIL_COND_MSG(p_packet_len < packet_min_size, "Invalid packet received. Size too small."); + uint32_t node_target = 0; + switch (node_id_compression) { + case NETWORK_NODE_ID_COMPRESSION_8: + node_target = p_packet[1]; + break; + case NETWORK_NODE_ID_COMPRESSION_16: + node_target = decode_uint16(p_packet + 1); + break; + case NETWORK_NODE_ID_COMPRESSION_32: + node_target = decode_uint32(p_packet + 1); + break; + default: + // Unreachable, checked before. + CRASH_NOW(); + } + Node *node = _process_get_node(p_from, p_packet, node_target, p_packet_len); ERR_FAIL_COND_MSG(node == NULL, "Invalid packet received. Requested node was not found."); - // Detect cstring end. - int len_end = 5; - for (; len_end < p_packet_len; len_end++) { - if (p_packet[len_end] == 0) { + uint16_t name_id = 0; + switch (name_id_compression) { + case NETWORK_NAME_ID_COMPRESSION_8: + name_id = p_packet[name_id_offset]; break; - } + case NETWORK_NAME_ID_COMPRESSION_16: + name_id = decode_uint16(p_packet + name_id_offset); + break; + default: + // Unreachable, checked before. + CRASH_NOW(); } - ERR_FAIL_COND_MSG(len_end >= p_packet_len, "Invalid packet received. Size too small."); - - StringName name = String::utf8((const char *)&p_packet[5]); - if (packet_type == NETWORK_COMMAND_REMOTE_CALL) { - _process_rpc(node, name, p_from, p_packet, p_packet_len, len_end + 1); + _process_rpc(node, name_id, p_from, p_packet, p_packet_len, packet_min_size); } else { - _process_rset(node, name, p_from, p_packet, p_packet_len, len_end + 1); + _process_rset(node, name_id, p_from, p_packet, p_packet_len, packet_min_size); } } break; @@ -233,15 +284,14 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_ } } -Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, int p_packet_len) { +Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, uint32_t p_node_target, int p_packet_len) { - uint32_t target = decode_uint32(&p_packet[1]); Node *node = NULL; - if (target & 0x80000000) { + if (p_node_target & 0x80000000) { // Use full path (not cached yet). - int ofs = target & 0x7FFFFFFF; + int ofs = p_node_target & 0x7FFFFFFF; ERR_FAIL_COND_V_MSG(ofs >= p_packet_len, NULL, "Invalid packet received. Size smaller than declared."); @@ -256,7 +306,7 @@ Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, int ERR_PRINT("Failed to get path from RPC: " + String(np) + "."); } else { // Use cached path. - int id = target; + int id = p_node_target; Map<int, PathGetCache>::Element *E = path_get_cache.find(p_from); ERR_FAIL_COND_V_MSG(!E, NULL, "Invalid packet received. Requests invalid peer cache."); @@ -274,21 +324,21 @@ Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, int return node; } -void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { +void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small."); // Check that remote can call the RPC on this node. - RPCMode rpc_mode = RPC_MODE_DISABLED; - const Map<StringName, RPCMode>::Element *E = p_node->get_node_rpc_mode(p_name); - if (E) { - rpc_mode = E->get(); - } else if (p_node->get_script_instance()) { - rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_name); + StringName name = p_node->get_node_rpc_method(p_rpc_method_id); + RPCMode rpc_mode = p_node->get_node_rpc_mode_by_id(p_rpc_method_id); + if (name == StringName() && p_node->get_script_instance()) { + name = p_node->get_script_instance()->get_rpc_method(p_rpc_method_id); + rpc_mode = p_node->get_script_instance()->get_rpc_mode_by_id(p_rpc_method_id); } + ERR_FAIL_COND(name == StringName()); bool can_call = _can_call_mode(p_node, rpc_mode, p_from); - ERR_FAIL_COND_MSG(!can_call, "RPC '" + String(p_name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rpc_mode) + ", master is " + itos(p_node->get_network_master()) + "."); + ERR_FAIL_COND_MSG(!can_call, "RPC '" + String(name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rpc_mode) + ", master is " + itos(p_node->get_network_master()) + "."); int argc = p_packet[p_offset]; Vector<Variant> args; @@ -311,7 +361,7 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_ ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small."); int vlen; - Error err = decode_variant(args.write[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen, allow_object_decoding || network_peer->is_object_decoding_allowed()); + Error err = _decode_and_decompress_variant(args.write[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen); ERR_FAIL_COND_MSG(err != OK, "Invalid packet received. Unable to decode RPC argument."); argp.write[i] = &args[i]; @@ -320,29 +370,29 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_ Variant::CallError ce; - p_node->call(p_name, (const Variant **)argp.ptr(), argc, ce); + p_node->call(name, (const Variant **)argp.ptr(), argc, ce); if (ce.error != Variant::CallError::CALL_OK) { - String error = Variant::get_call_error_text(p_node, p_name, (const Variant **)argp.ptr(), argc, ce); + String error = Variant::get_call_error_text(p_node, name, (const Variant **)argp.ptr(), argc, ce); error = "RPC - " + error; ERR_PRINT(error); } } -void MultiplayerAPI::_process_rset(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { +void MultiplayerAPI::_process_rset(Node *p_node, const uint16_t p_rpc_property_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small."); // Check that remote can call the RSET on this node. - RPCMode rset_mode = RPC_MODE_DISABLED; - const Map<StringName, RPCMode>::Element *E = p_node->get_node_rset_mode(p_name); - if (E) { - rset_mode = E->get(); - } else if (p_node->get_script_instance()) { - rset_mode = p_node->get_script_instance()->get_rset_mode(p_name); + StringName name = p_node->get_node_rset_property(p_rpc_property_id); + RPCMode rset_mode = p_node->get_node_rset_mode_by_id(p_rpc_property_id); + if (name == StringName() && p_node->get_script_instance()) { + name = p_node->get_script_instance()->get_rset_property(p_rpc_property_id); + rset_mode = p_node->get_script_instance()->get_rset_mode_by_id(p_rpc_property_id); } + ERR_FAIL_COND(name == StringName()); bool can_call = _can_call_mode(p_node, rset_mode, p_from); - ERR_FAIL_COND_MSG(!can_call, "RSET '" + String(p_name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rset_mode) + ", master is " + itos(p_node->get_network_master()) + "."); + ERR_FAIL_COND_MSG(!can_call, "RSET '" + String(name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rset_mode) + ", master is " + itos(p_node->get_network_master()) + "."); #ifdef DEBUG_ENABLED if (profiling) { @@ -353,26 +403,33 @@ void MultiplayerAPI::_process_rset(Node *p_node, const StringName &p_name, int p #endif Variant value; - Error err = decode_variant(value, &p_packet[p_offset], p_packet_len - p_offset, NULL, allow_object_decoding || network_peer->is_object_decoding_allowed()); + Error err = _decode_and_decompress_variant(value, &p_packet[p_offset], p_packet_len - p_offset, NULL); ERR_FAIL_COND_MSG(err != OK, "Invalid packet received. Unable to decode RSET value."); bool valid; - p_node->set(p_name, value, &valid); + p_node->set(name, value, &valid); if (!valid) { - String error = "Error setting remote property '" + String(p_name) + "', not found in object of type " + p_node->get_class() + "."; + String error = "Error setting remote property '" + String(name) + "', not found in object of type " + p_node->get_class() + "."; ERR_PRINT(error); } } void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) { - ERR_FAIL_COND_MSG(p_packet_len < 5, "Invalid packet received. Size too small."); - int id = decode_uint32(&p_packet[1]); + ERR_FAIL_COND_MSG(p_packet_len < 38, "Invalid packet received. Size too small."); + int ofs = 1; + + String methods_md5; + methods_md5.parse_utf8((const char *)(p_packet + ofs), 32); + ofs += 33; + + int id = decode_uint32(&p_packet[ofs]); + ofs += 4; String paths; - paths.parse_utf8((const char *)&p_packet[5], p_packet_len - 5); + paths.parse_utf8((const char *)(p_packet + ofs), p_packet_len - ofs); NodePath path = paths; @@ -380,9 +437,15 @@ void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, path_get_cache[p_from] = PathGetCache(); } + Node *node = root_node->get_node(path); + ERR_FAIL_COND(node == NULL); + const bool valid_rpc_checksum = node->get_rpc_md5() == methods_md5; + if (valid_rpc_checksum == false) { + ERR_PRINT("The rpc node checksum failed. Make sure to have the same methods on both nodes. Node path: " + path); + } + PathGetCache::NodeInfo ni; ni.path = path; - ni.instance = 0; path_get_cache[p_from].nodes[id] = ni; @@ -392,9 +455,10 @@ void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, Vector<uint8_t> packet; - packet.resize(1 + len); + packet.resize(1 + 1 + len); packet.write[0] = NETWORK_COMMAND_CONFIRM_PATH; - encode_cstring(pname.get_data(), &packet.write[1]); + packet.write[1] = valid_rpc_checksum; + encode_cstring(pname.get_data(), &packet.write[2]); network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); network_peer->set_target_peer(p_from); @@ -403,13 +467,19 @@ void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) { - ERR_FAIL_COND_MSG(p_packet_len < 2, "Invalid packet received. Size too small."); + ERR_FAIL_COND_MSG(p_packet_len < 3, "Invalid packet received. Size too small."); + + const bool valid_rpc_checksum = p_packet[1]; String paths; - paths.parse_utf8((const char *)&p_packet[1], p_packet_len - 1); + paths.parse_utf8((const char *)&p_packet[2], p_packet_len - 2); NodePath path = paths; + if (valid_rpc_checksum == false) { + ERR_PRINT("The rpc node checksum failed. Make sure to have the same methods on both nodes. Node path: " + path); + } + PathSentCache *psc = path_send_cache.getptr(path); ERR_FAIL_COND_MSG(!psc, "Invalid packet received. Tries to confirm a path which was not found in cache."); @@ -418,7 +488,7 @@ void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet, E->get() = true; } -bool MultiplayerAPI::_send_confirm_path(NodePath p_path, PathSentCache *psc, int p_target) { +bool MultiplayerAPI::_send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, int p_target) { bool has_all_peers = true; List<int> peers_to_add; // If one is missing, take note to add it. @@ -443,31 +513,192 @@ bool MultiplayerAPI::_send_confirm_path(NodePath p_path, PathSentCache *psc, int } } - // Those that need to be added, send a message for this. + if (peers_to_add.size() > 0) { - for (List<int>::Element *E = peers_to_add.front(); E; E = E->next()) { + // Those that need to be added, send a message for this. // Encode function name. - CharString pname = String(p_path).utf8(); - int len = encode_cstring(pname.get_data(), NULL); + const CharString path = String(p_path).utf8(); + const int path_len = encode_cstring(path.get_data(), NULL); + + // Extract MD5 from rpc methods list. + const String methods_md5 = p_node->get_rpc_md5(); + const int methods_md5_len = 33; // 32 + 1 for the `0` that is added by the encoder. Vector<uint8_t> packet; + packet.resize(1 + 4 + path_len + methods_md5_len); + int ofs = 0; + + packet.write[ofs] = NETWORK_COMMAND_SIMPLIFY_PATH; + ofs += 1; + + ofs += encode_cstring(methods_md5.utf8().get_data(), &packet.write[ofs]); + + ofs += encode_uint32(psc->id, &packet.write[ofs]); + + ofs += encode_cstring(path.get_data(), &packet.write[ofs]); - packet.resize(1 + 4 + len); - packet.write[0] = NETWORK_COMMAND_SIMPLIFY_PATH; - encode_uint32(psc->id, &packet.write[1]); - encode_cstring(pname.get_data(), &packet.write[5]); + for (List<int>::Element *E = peers_to_add.front(); E; E = E->next()) { - network_peer->set_target_peer(E->get()); // To all of you. - network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); - network_peer->put_packet(packet.ptr(), packet.size()); + network_peer->set_target_peer(E->get()); // To all of you. + network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); + network_peer->put_packet(packet.ptr(), packet.size()); - psc->confirmed_peers.insert(E->get(), false); // Insert into confirmed, but as false since it was not confirmed. + psc->confirmed_peers.insert(E->get(), false); // Insert into confirmed, but as false since it was not confirmed. + } } return has_all_peers; } +// The variant is compressed and encoded; The first byte contains all the meta +// information and the format is: +// - The first LSB 5 bits are used for the variant type. +// - The next two bits are used to store the encoding mode. +// - The most significant is used to store the boolean value. +#define VARIANT_META_TYPE_MASK 0x1F +#define VARIANT_META_EMODE_MASK 0x60 +#define VARIANT_META_BOOL_MASK 0x80 +#define ENCODE_8 0 << 5 +#define ENCODE_16 1 << 5 +#define ENCODE_32 2 << 5 +#define ENCODE_64 3 << 5 +Error MultiplayerAPI::_encode_and_compress_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len) { + + // Unreachable because `VARIANT_MAX` == 27 and `ENCODE_VARIANT_MASK` == 31 + CRASH_COND(p_variant.get_type() > VARIANT_META_TYPE_MASK); + + uint8_t *buf = r_buffer; + r_len = 0; + uint8_t encode_mode = 0; + + switch (p_variant.get_type()) { + case Variant::BOOL: { + if (buf) { + // We still have 1 free bit in the meta, so let's use it. + buf[0] = (p_variant.operator bool()) ? (1 << 7) : 0; + buf[0] |= encode_mode | p_variant.get_type(); + } + r_len += 1; + } break; + case Variant::INT: { + if (buf) { + // Reserve the first byte for the meta. + buf += 1; + } + r_len += 1; + int64_t val = p_variant; + if (val <= (int64_t)INT8_MAX && val >= (int64_t)INT8_MIN) { + // Use 8 bit + encode_mode = ENCODE_8; + if (buf) { + buf[0] = val; + } + r_len += 1; + } else if (val <= (int64_t)INT16_MAX && val >= (int64_t)INT16_MIN) { + // Use 16 bit + encode_mode = ENCODE_16; + if (buf) { + encode_uint16(val, buf); + } + r_len += 2; + } else if (val <= (int64_t)INT32_MAX && val >= (int64_t)INT32_MIN) { + // Use 32 bit + encode_mode = ENCODE_32; + if (buf) { + encode_uint32(val, buf); + } + r_len += 4; + } else { + // Use 64 bit + encode_mode = ENCODE_64; + if (buf) { + encode_uint64(val, buf); + } + r_len += 8; + } + // Store the meta + if (buf) { + buf -= 1; + buf[0] = encode_mode | p_variant.get_type(); + } + } break; + default: + // Any other case is not yet compressed. + Error err = encode_variant(p_variant, r_buffer, r_len, allow_object_decoding || network_peer->is_object_decoding_allowed()); + if (err != OK) + return err; + if (r_buffer) { + // The first byte is not used by the marshaling, so store the type + // so we know how to decompress and decode this variant. + r_buffer[0] = p_variant.get_type(); + } + } + + return OK; +} +Error MultiplayerAPI::_decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len) { + + const uint8_t *buf = p_buffer; + int len = p_len; + + ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA); + uint8_t type = buf[0] & VARIANT_META_TYPE_MASK; + uint8_t encode_mode = buf[0] & VARIANT_META_EMODE_MASK; + + ERR_FAIL_COND_V(type >= Variant::VARIANT_MAX, ERR_INVALID_DATA); + + switch (type) { + case Variant::BOOL: { + bool val = (buf[0] & VARIANT_META_BOOL_MASK) > 0; + r_variant = val; + if (r_len) + *r_len = 1; + } break; + case Variant::INT: { + buf += 1; + len -= 1; + if (r_len) + *r_len = 1; + if (encode_mode == ENCODE_8) { + // 8 bits. + ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA); + int8_t val = buf[0]; + r_variant = val; + if (r_len) + (*r_len) += 1; + } else if (encode_mode == ENCODE_16) { + // 16 bits. + ERR_FAIL_COND_V(len < 2, ERR_INVALID_DATA); + int16_t val = decode_uint16(buf); + r_variant = val; + if (r_len) + (*r_len) += 2; + } else if (encode_mode == ENCODE_32) { + // 32 bits. + ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); + int32_t val = decode_uint32(buf); + r_variant = val; + if (r_len) + (*r_len) += 4; + } else { + // 64 bits. + ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA); + int64_t val = decode_uint64(buf); + r_variant = val; + if (r_len) + (*r_len) += 8; + } + } break; + default: + Error err = decode_variant(r_variant, p_buffer, p_len, r_len, allow_object_decoding || network_peer->is_object_decoding_allowed()); + if (err != OK) + return err; + } + + return OK; +} + void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount) { ERR_FAIL_COND_MSG(network_peer.is_null(), "Attempt to remote call/set when networking is not active in SceneTree."); @@ -496,6 +727,9 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p psc->id = last_send_cache_id++; } + // See if all peers have cached path (if so, call can be fast). + const bool has_all_peers = _send_confirm_path(p_from, from_path, psc, p_to); + // Create base packet, lots of hardcode because it must be tight. int ofs = 0; @@ -503,45 +737,125 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p #define MAKE_ROOM(m_amount) \ if (packet_cache.size() < m_amount) packet_cache.resize(m_amount); - // Encode type. + // Encode meta. + // The meta is composed by a single byte that contains (starting from the least segnificant bit): + // - `NetworkCommands` in the first three bits. + // - `NetworkNodeIdCompression` in the next 2 bits. + // - `NetworkNameIdCompression` in the next 1 bit. + // - So we still have the last two bits free! + uint8_t command_type = p_set ? NETWORK_COMMAND_REMOTE_SET : NETWORK_COMMAND_REMOTE_CALL; + uint8_t node_id_compression = UINT8_MAX; + uint8_t name_id_compression = UINT8_MAX; + MAKE_ROOM(1); - packet_cache.write[0] = p_set ? NETWORK_COMMAND_REMOTE_SET : NETWORK_COMMAND_REMOTE_CALL; + // The meta is composed along the way, so just set 0 for now. + packet_cache.write[0] = 0; ofs += 1; - // Encode ID. - MAKE_ROOM(ofs + 4); - encode_uint32(psc->id, &(packet_cache.write[ofs])); - ofs += 4; - - // Encode function name. - CharString name = String(p_name).utf8(); - int len = encode_cstring(name.get_data(), NULL); - MAKE_ROOM(ofs + len); - encode_cstring(name.get_data(), &(packet_cache.write[ofs])); - ofs += len; + // Encode Node ID. + if (has_all_peers) { + // Compress the node ID only if all the target peers already know it. + if (psc->id >= 0 && psc->id <= 255) { + // We can encode the id in 1 byte + node_id_compression = NETWORK_NODE_ID_COMPRESSION_8; + MAKE_ROOM(ofs + 1); + packet_cache.write[ofs] = static_cast<uint8_t>(psc->id); + ofs += 1; + } else if (psc->id >= 0 && psc->id <= 65535) { + // We can encode the id in 2 bytes + node_id_compression = NETWORK_NODE_ID_COMPRESSION_16; + MAKE_ROOM(ofs + 2); + encode_uint16(static_cast<uint16_t>(psc->id), &(packet_cache.write[ofs])); + ofs += 2; + } else { + // Too big, let's use 4 bytes. + node_id_compression = NETWORK_NODE_ID_COMPRESSION_32; + MAKE_ROOM(ofs + 4); + encode_uint32(psc->id, &(packet_cache.write[ofs])); + ofs += 4; + } + } else { + // The targets doesn't know the node yet, so we need to use 32 bits int. + node_id_compression = NETWORK_NODE_ID_COMPRESSION_32; + MAKE_ROOM(ofs + 4); + encode_uint32(psc->id, &(packet_cache.write[ofs])); + ofs += 4; + } if (p_set) { + + // Take the rpc property ID + uint16_t property_id = p_from->get_node_rset_property_id(p_name); + if (property_id == UINT16_MAX && p_from->get_script_instance()) { + property_id = p_from->get_script_instance()->get_rset_property_id(p_name); + } + ERR_FAIL_COND_MSG(property_id == UINT16_MAX, "Unable to take the `property_id` for the property:" + p_name + ". this can happen only if this property is not marked as `remote`."); + + if (property_id <= UINT8_MAX) { + // The ID fits in 1 byte + name_id_compression = NETWORK_NAME_ID_COMPRESSION_8; + MAKE_ROOM(ofs + 1); + packet_cache.write[ofs] = static_cast<uint8_t>(property_id); + ofs += 1; + } else { + // The ID is larger, let's use 2 bytes + name_id_compression = NETWORK_NAME_ID_COMPRESSION_16; + MAKE_ROOM(ofs + 2); + encode_uint16(property_id, &(packet_cache.write[ofs])); + ofs += 2; + } + // Set argument. - Error err = encode_variant(*p_arg[0], NULL, len, allow_object_decoding || network_peer->is_object_decoding_allowed()); + int len(0); + Error err = _encode_and_compress_variant(*p_arg[0], NULL, len); ERR_FAIL_COND_MSG(err != OK, "Unable to encode RSET value. THIS IS LIKELY A BUG IN THE ENGINE!"); MAKE_ROOM(ofs + len); - encode_variant(*p_arg[0], &(packet_cache.write[ofs]), len, allow_object_decoding || network_peer->is_object_decoding_allowed()); + _encode_and_compress_variant(*p_arg[0], &(packet_cache.write[ofs]), len); ofs += len; } else { + // Take the rpc method ID + uint16_t method_id = p_from->get_node_rpc_method_id(p_name); + if (method_id == UINT16_MAX && p_from->get_script_instance()) { + method_id = p_from->get_script_instance()->get_rpc_method_id(p_name); + } + ERR_FAIL_COND_MSG(method_id == UINT16_MAX, "Unable to take the `method_id` for the function:" + p_name + ". this can happen only if this method is not marked as `remote`."); + + if (method_id <= UINT8_MAX) { + // The ID fits in 1 byte + name_id_compression = NETWORK_NAME_ID_COMPRESSION_8; + MAKE_ROOM(ofs + 1); + packet_cache.write[ofs] = static_cast<uint8_t>(method_id); + ofs += 1; + } else { + // The ID is larger, let's use 2 bytes + name_id_compression = NETWORK_NAME_ID_COMPRESSION_16; + MAKE_ROOM(ofs + 2); + encode_uint16(method_id, &(packet_cache.write[ofs])); + ofs += 2; + } + // Call arguments. MAKE_ROOM(ofs + 1); packet_cache.write[ofs] = p_argcount; ofs += 1; for (int i = 0; i < p_argcount; i++) { - Error err = encode_variant(*p_arg[i], NULL, len, allow_object_decoding || network_peer->is_object_decoding_allowed()); + int len(0); + Error err = _encode_and_compress_variant(*p_arg[i], NULL, len); ERR_FAIL_COND_MSG(err != OK, "Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!"); MAKE_ROOM(ofs + len); - encode_variant(*p_arg[i], &(packet_cache.write[ofs]), len, allow_object_decoding || network_peer->is_object_decoding_allowed()); + _encode_and_compress_variant(*p_arg[i], &(packet_cache.write[ofs]), len); ofs += len; } } + ERR_FAIL_COND(command_type > 7); + ERR_FAIL_COND(node_id_compression > 3); + ERR_FAIL_COND(name_id_compression > 1); + + // We can now set the meta + packet_cache.write[0] = command_type + (node_id_compression << 3) + (name_id_compression << 5); + #ifdef DEBUG_ENABLED if (profiling) { bandwidth_outgoing_data.write[bandwidth_outgoing_pointer].timestamp = OS::get_singleton()->get_ticks_msec(); @@ -550,9 +864,6 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p } #endif - // See if all peers have cached path (is so, call can be fast). - bool has_all_peers = _send_confirm_path(from_path, psc, p_to); - // Take chance and set transfer mode, since all send methods will use it. network_peer->set_transfer_mode(p_unreliable ? NetworkedMultiplayerPeer::TRANSFER_MODE_UNRELIABLE : NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); @@ -562,6 +873,9 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p network_peer->set_target_peer(p_to); // To all of you. network_peer->put_packet(packet_cache.ptr(), ofs); // A message with love. } else { + // Unreachable because the node ID is never compressed if the peers doesn't know it. + CRASH_COND(node_id_compression != NETWORK_NODE_ID_COMPRESSION_32); + // Not all verified path, so send one by one. // Append path at the end, since we will need it for some packets. @@ -647,16 +961,14 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) { // Check that send mode can use local call. - const Map<StringName, RPCMode>::Element *E = p_node->get_node_rpc_mode(p_method); - if (E) { - call_local_native = _should_call_local(E->get(), is_master, skip_rpc); - } + RPCMode rpc_mode = p_node->get_node_rpc_mode(p_method); + call_local_native = _should_call_local(rpc_mode, is_master, skip_rpc); if (call_local_native) { // Done below. } else if (p_node->get_script_instance()) { // Attempt with script. - RPCMode rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_method); + rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_method); call_local_script = _should_call_local(rpc_mode, is_master, skip_rpc); } } @@ -719,11 +1031,8 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) { // Check that send mode can use local call. - const Map<StringName, RPCMode>::Element *E = p_node->get_node_rset_mode(p_property); - if (E) { - - set_local = _should_call_local(E->get(), is_master, skip_rset); - } + RPCMode rpc_mode = p_node->get_node_rset_mode(p_property); + set_local = _should_call_local(rpc_mode, is_master, skip_rset); if (set_local) { bool valid; @@ -740,7 +1049,7 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const } } else if (p_node->get_script_instance()) { // Attempt with script. - RPCMode rpc_mode = p_node->get_script_instance()->get_rset_mode(p_property); + rpc_mode = p_node->get_script_instance()->get_rset_mode(p_property); set_local = _should_call_local(rpc_mode, is_master, skip_rset); diff --git a/core/io/multiplayer_api.h b/core/io/multiplayer_api.h index c9f127b6b2..6672cfe155 100644 --- a/core/io/multiplayer_api.h +++ b/core/io/multiplayer_api.h @@ -98,23 +98,37 @@ protected: void _process_packet(int p_from, const uint8_t *p_packet, int p_packet_len); void _process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len); void _process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len); - Node *_process_get_node(int p_from, const uint8_t *p_packet, int p_packet_len); - void _process_rpc(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset); - void _process_rset(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset); + Node *_process_get_node(int p_from, const uint8_t *p_packet, uint32_t p_node_target, int p_packet_len); + void _process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset); + void _process_rset(Node *p_node, const uint16_t p_rpc_property_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset); void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len); void _send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount); - bool _send_confirm_path(NodePath p_path, PathSentCache *psc, int p_target); + bool _send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, int p_target); + + Error _encode_and_compress_variant(const Variant &p_variant, uint8_t *p_buffer, int &r_len); + Error _decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len); public: enum NetworkCommands { - NETWORK_COMMAND_REMOTE_CALL, + NETWORK_COMMAND_REMOTE_CALL = 0, NETWORK_COMMAND_REMOTE_SET, NETWORK_COMMAND_SIMPLIFY_PATH, NETWORK_COMMAND_CONFIRM_PATH, NETWORK_COMMAND_RAW, }; + enum NetworkNodeIdCompression { + NETWORK_NODE_ID_COMPRESSION_8 = 0, + NETWORK_NODE_ID_COMPRESSION_16, + NETWORK_NODE_ID_COMPRESSION_32, + }; + + enum NetworkNameIdCompression { + NETWORK_NAME_ID_COMPRESSION_8 = 0, + NETWORK_NAME_ID_COMPRESSION_16, + }; + enum RPCMode { RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default) diff --git a/core/method_ptrcall.h b/core/method_ptrcall.h index 0f2458d982..118970de80 100644 --- a/core/method_ptrcall.h +++ b/core/method_ptrcall.h @@ -32,6 +32,7 @@ #define METHOD_PTRCALL_H #include "core/math/transform_2d.h" +#include "core/object_id.h" #include "core/typedefs.h" #include "core/variant.h" @@ -167,6 +168,21 @@ struct PtrToArg<const T *> { } }; +//this is for ObjectID + +template <> +struct PtrToArg<ObjectID> { + _FORCE_INLINE_ static const ObjectID convert(const void *p_ptr) { + + return ObjectID(*reinterpret_cast<const uint64_t *>(p_ptr)); + } + + _FORCE_INLINE_ static void encode(const ObjectID &p_val, void *p_ptr) { + + *((uint64_t *)p_ptr) = p_val; + } +}; + //this is for the special cases used by Variant #define MAKE_VECARG(m_type) \ diff --git a/core/object.cpp b/core/object.cpp index 937b1ae8d4..dc1dc2c41f 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -1916,7 +1916,6 @@ Object::Object() { _class_ptr = NULL; _block_signals = false; _predelete_ok = 0; - _instance_id = 0; _instance_id = ObjectDB::add_instance(this); _can_translate = true; _is_queued_for_deletion = false; @@ -1972,7 +1971,7 @@ Object::~Object() { } ObjectDB::remove_instance(this); - _instance_id = 0; + _instance_id = ObjectID(); _predelete_ok = 2; if (!ScriptServer::are_languages_finished()) { @@ -1995,14 +1994,14 @@ void postinitialize_handler(Object *p_object) { } HashMap<ObjectID, Object *> ObjectDB::instances; -ObjectID ObjectDB::instance_counter = 1; +uint64_t ObjectDB::instance_counter = 1; HashMap<Object *, ObjectID, ObjectDB::ObjectPtrHash> ObjectDB::instance_checks; ObjectID ObjectDB::add_instance(Object *p_object) { - ERR_FAIL_COND_V(p_object->get_instance_id() != 0, 0); + ERR_FAIL_COND_V(p_object->get_instance_id().is_valid(), ObjectID()); rw_lock->write_lock(); - ObjectID instance_id = ++instance_counter; + ObjectID instance_id = ObjectID(++instance_counter); instances[instance_id] = p_object; instance_checks[p_object] = instance_id; diff --git a/core/object.h b/core/object.h index 865c155764..312fe07a17 100644 --- a/core/object.h +++ b/core/object.h @@ -34,6 +34,7 @@ #include "core/hash_map.h" #include "core/list.h" #include "core/map.h" +#include "core/object_id.h" #include "core/os/rw_lock.h" #include "core/set.h" #include "core/variant.h" @@ -89,6 +90,7 @@ enum PropertyHint { PROPERTY_HINT_OBJECT_TOO_BIG, ///< object is too big to send PROPERTY_HINT_NODE_PATH_VALID_TYPES, PROPERTY_HINT_SAVE_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,". This opens a save dialog + PROPERTY_HINT_INT_IS_OBJECTID, PROPERTY_HINT_MAX, // When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit }; @@ -397,7 +399,6 @@ public: \ private: class ScriptInstance; -typedef uint64_t ObjectID; class Object { public: @@ -452,7 +453,7 @@ private: _id(p_id), method(p_method) { } - Target() { _id = 0; } + Target() { _id = ObjectID(); } }; struct Slot { @@ -775,7 +776,7 @@ class ObjectDB { static HashMap<ObjectID, Object *> instances; static HashMap<Object *, ObjectID, ObjectPtrHash> instance_checks; - static ObjectID instance_counter; + static uint64_t instance_counter; friend class Object; friend void unregister_core_types(); diff --git a/core/object_id.h b/core/object_id.h new file mode 100644 index 0000000000..f0ff2a24f5 --- /dev/null +++ b/core/object_id.h @@ -0,0 +1,32 @@ +#ifndef OBJECT_ID_H +#define OBJECT_ID_H + +#include "core/typedefs.h" + +// Class to store an object ID (int64) +// needs to be compatile with int64 because this is what Variant uses +// Also, need to be explicitly only castable to 64 bits integer types +// to avoid bugs due to loss of precision + +class ObjectID { + uint64_t id = 0; + +public: + _ALWAYS_INLINE_ bool is_valid() const { return id != 0; } + _ALWAYS_INLINE_ bool is_null() const { return id == 0; } + _ALWAYS_INLINE_ operator uint64_t() const { return id; } + _ALWAYS_INLINE_ operator int64_t() const { return id; } + + _ALWAYS_INLINE_ bool operator==(const ObjectID &p_id) const { return id == p_id.id; } + _ALWAYS_INLINE_ bool operator!=(const ObjectID &p_id) const { return id != p_id.id; } + _ALWAYS_INLINE_ bool operator<(const ObjectID &p_id) const { return id < p_id.id; } + + _ALWAYS_INLINE_ void operator=(int64_t p_int64) { id = p_int64; } + _ALWAYS_INLINE_ void operator=(uint64_t p_uint64) { id = p_uint64; } + + _ALWAYS_INLINE_ ObjectID() {} + _ALWAYS_INLINE_ explicit ObjectID(const uint64_t p_id) { id = p_id; } + _ALWAYS_INLINE_ explicit ObjectID(const int64_t p_id) { id = p_id; } +}; + +#endif // OBJECT_ID_H diff --git a/core/reference.cpp b/core/reference.cpp index b24b2a3ec0..5c211fe301 100644 --- a/core/reference.cpp +++ b/core/reference.cpp @@ -113,7 +113,7 @@ Reference::~Reference() { Variant WeakRef::get_ref() const { - if (ref == 0) + if (ref.is_null()) return Variant(); Object *obj = ObjectDB::get_instance(ref); @@ -129,16 +129,15 @@ Variant WeakRef::get_ref() const { } void WeakRef::set_obj(Object *p_object) { - ref = p_object ? p_object->get_instance_id() : 0; + ref = p_object ? p_object->get_instance_id() : ObjectID(); } void WeakRef::set_ref(const REF &p_ref) { - ref = p_ref.is_valid() ? p_ref->get_instance_id() : 0; + ref = p_ref.is_valid() ? p_ref->get_instance_id() : ObjectID(); } -WeakRef::WeakRef() : - ref(0) { +WeakRef::WeakRef() { } void WeakRef::_bind_methods() { diff --git a/core/script_language.cpp b/core/script_language.cpp index 7392e7a0af..1149feac38 100644 --- a/core/script_language.cpp +++ b/core/script_language.cpp @@ -32,6 +32,7 @@ #include "core/core_string_names.h" #include "core/project_settings.h" +#include <stdint.h> ScriptLanguage *ScriptServer::_languages[MAX_LANGUAGES]; int ScriptServer::_language_count = 0; @@ -644,6 +645,14 @@ Variant PlaceHolderScriptInstance::property_get_fallback(const StringName &p_nam return Variant(); } +uint16_t PlaceHolderScriptInstance::get_rpc_method_id(const StringName &p_method) const { + return UINT16_MAX; +} + +uint16_t PlaceHolderScriptInstance::get_rset_property_id(const StringName &p_method) const { + return UINT16_MAX; +} + PlaceHolderScriptInstance::PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner) : owner(p_owner), language(p_language), diff --git a/core/script_language.h b/core/script_language.h index 22f83080bc..788f5d6976 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -40,6 +40,21 @@ class ScriptLanguage; typedef void (*ScriptEditRequestFunction)(const String &p_path); +struct ScriptNetData { + StringName name; + MultiplayerAPI::RPCMode mode; + bool operator==(ScriptNetData const &p_other) const { + return name == p_other.name; + } +}; + +struct SortNetData { + StringName::AlphCompare compare; + bool operator()(const ScriptNetData &p_a, const ScriptNetData &p_b) const { + return compare(p_a.name, p_b.name); + } +}; + class ScriptServer { enum { @@ -154,6 +169,18 @@ public: virtual bool is_placeholder_fallback_enabled() const { return false; } + virtual Vector<ScriptNetData> get_rpc_methods() const = 0; + virtual uint16_t get_rpc_method_id(const StringName &p_method) const = 0; + virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const = 0; + virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const = 0; + virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const = 0; + + virtual Vector<ScriptNetData> get_rset_properties() const = 0; + virtual uint16_t get_rset_property_id(const StringName &p_property) const = 0; + virtual StringName get_rset_property(const uint16_t p_rset_property_id) const = 0; + virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_rpc_method_id) const = 0; + virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const = 0; + Script() {} }; @@ -195,7 +222,16 @@ public: virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid); virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid); + virtual Vector<ScriptNetData> get_rpc_methods() const = 0; + virtual uint16_t get_rpc_method_id(const StringName &p_method) const = 0; + virtual StringName get_rpc_method(uint16_t p_id) const = 0; + virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const = 0; virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const = 0; + + virtual Vector<ScriptNetData> get_rset_properties() const = 0; + virtual uint16_t get_rset_property_id(const StringName &p_variable) const = 0; + virtual StringName get_rset_property(uint16_t p_id) const = 0; + virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const = 0; virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const = 0; virtual ScriptLanguage *get_language() = 0; @@ -409,7 +445,16 @@ public: virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid = NULL); virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid = NULL); + virtual Vector<ScriptNetData> get_rpc_methods() const { return Vector<ScriptNetData>(); } + virtual uint16_t get_rpc_method_id(const StringName &p_method) const; + virtual StringName get_rpc_method(uint16_t p_id) const { return StringName(); } + virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const { return MultiplayerAPI::RPC_MODE_DISABLED; } virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const { return MultiplayerAPI::RPC_MODE_DISABLED; } + + virtual Vector<ScriptNetData> get_rset_properties() const { return Vector<ScriptNetData>(); } + virtual uint16_t get_rset_property_id(const StringName &p_variable) const; + virtual StringName get_rset_property(uint16_t p_id) const { return StringName(); } + virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const { return MultiplayerAPI::RPC_MODE_DISABLED; } virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const { return MultiplayerAPI::RPC_MODE_DISABLED; } PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner); diff --git a/core/type_info.h b/core/type_info.h index 68bc1cc554..b9e5b61a6a 100644 --- a/core/type_info.h +++ b/core/type_info.h @@ -187,6 +187,16 @@ struct GetTypeInfo<const RefPtr &> { } }; +//objectID +template <> +struct GetTypeInfo<ObjectID> { + static const Variant::Type VARIANT_TYPE = Variant::INT; + static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; + static inline PropertyInfo get_class_info() { + return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_OBJECTID); + } +}; + //for variant template <> struct GetTypeInfo<Variant> { diff --git a/core/variant.cpp b/core/variant.cpp index f4e4cd5341..0f04710d13 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -1248,6 +1248,14 @@ Variant::operator uint64_t() const { } } +Variant::operator ObjectID() const { + if (type == INT) { + return ObjectID(_data._int); + } else { + return ObjectID(); + } +} + #ifdef NEED_LONG_INT Variant::operator signed long() const { @@ -2193,6 +2201,11 @@ Variant::Variant(double p_double) { _data._real = p_double; } +Variant::Variant(const ObjectID &p_id) { + type = INT; + _data._int = p_id; +} + Variant::Variant(const StringName &p_string) { type = STRING; diff --git a/core/variant.h b/core/variant.h index 06be914408..d8007f9e12 100644 --- a/core/variant.h +++ b/core/variant.h @@ -44,6 +44,7 @@ #include "core/math/transform_2d.h" #include "core/math/vector3.h" #include "core/node_path.h" +#include "core/object_id.h" #include "core/pool_vector.h" #include "core/ref_ptr.h" #include "core/rid.h" @@ -177,6 +178,8 @@ public: operator unsigned long() const; #endif + operator ObjectID() const; + operator CharType() const; operator float() const; operator double() const; @@ -248,6 +251,7 @@ public: Variant(uint64_t p_int); Variant(float p_float); Variant(double p_double); + Variant(const ObjectID &p_id); Variant(const String &p_string); Variant(const StringName &p_string); Variant(const char *const p_cstring); diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 08047935bd..620fcdbdca 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -332,6 +332,11 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener } struct_code += " "; struct_code += m->name; + if (m->array_size > 0) { + struct_code += "["; + struct_code += itos(m->array_size); + struct_code += "]"; + } struct_code += ";\n"; } struct_code += "}"; @@ -558,6 +563,26 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener } } } break; + case SL::Node::TYPE_ARRAY_CONSTRUCT: { + SL::ArrayConstructNode *arr_con_node = (SL::ArrayConstructNode *)p_node; + int sz = arr_con_node->initializer.size(); + if (acnode->datatype == SL::TYPE_STRUCT) { + code += _mkid(arr_con_node->struct_name); + } else { + code += _typestr(arr_con_node->datatype); + } + code += "["; + code += itos(arr_con_node->initializer.size()); + code += "]"; + code += "("; + for (int i = 0; i < sz; i++) { + code += _dump_node_code(arr_con_node->initializer[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + if (i != sz - 1) { + code += ", "; + } + } + code += ")"; + } break; case SL::Node::TYPE_ARRAY_DECLARATION: { SL::ArrayDeclarationNode *arr_dec_node = (SL::ArrayDeclarationNode *)p_node; @@ -898,6 +923,11 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener code += _dump_node_code(member_node->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); code += "."; code += member_node->name; + if (member_node->index_expression != NULL) { + code += "["; + code += _dump_node_code(member_node->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += "]"; + } } break; } diff --git a/editor/dictionary_property_edit.cpp b/editor/dictionary_property_edit.cpp index bb01fadb72..82db639379 100644 --- a/editor/dictionary_property_edit.cpp +++ b/editor/dictionary_property_edit.cpp @@ -190,5 +190,4 @@ bool DictionaryPropertyEdit::_get(const StringName &p_name, Variant &r_ret) cons } DictionaryPropertyEdit::DictionaryPropertyEdit() { - obj = 0; } diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index d7c610f109..5cb7720170 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -156,8 +156,8 @@ bool EditorHistory::is_history_obj_inspector_only(int p_obj) const { } ObjectID EditorHistory::get_history_obj(int p_obj) const { - ERR_FAIL_INDEX_V(p_obj, history.size(), 0); - ERR_FAIL_INDEX_V(history[p_obj].level, history[p_obj].path.size(), 0); + ERR_FAIL_INDEX_V(p_obj, history.size(), ObjectID()); + ERR_FAIL_INDEX_V(history[p_obj].level, history[p_obj].path.size(), ObjectID()); return history[p_obj].path[history[p_obj].level].object; } @@ -204,12 +204,12 @@ bool EditorHistory::is_current_inspector_only() const { ObjectID EditorHistory::get_current() { if (current < 0 || current >= history.size()) - return 0; + return ObjectID(); History &h = history.write[current]; Object *obj = ObjectDB::get_instance(h.path[h.level].object); if (!obj) - return 0; + return ObjectID(); return obj->get_instance_id(); } @@ -226,15 +226,15 @@ int EditorHistory::get_path_size() const { ObjectID EditorHistory::get_path_object(int p_index) const { if (current < 0 || current >= history.size()) - return 0; + return ObjectID(); const History &h = history[current]; - ERR_FAIL_INDEX_V(p_index, h.path.size(), 0); + ERR_FAIL_INDEX_V(p_index, h.path.size(), ObjectID()); Object *obj = ObjectDB::get_instance(h.path[p_index].object); if (!obj) - return 0; + return ObjectID(); return obj->get_instance_id(); } diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 4440a747be..a6172faeaa 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1558,7 +1558,7 @@ void EditorNode::_dialog_action(String p_file) { save_resource_in_path(saving_resource, p_file); saving_resource = Ref<Resource>(); ObjectID current = editor_history.get_current(); - Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL; + Object *current_obj = current.is_valid() ? ObjectDB::get_instance(current) : NULL; ERR_FAIL_COND(!current_obj); current_obj->_change_notify(); } break; @@ -1711,7 +1711,7 @@ void EditorNode::push_item(Object *p_object, const String &p_property, bool p_in return; } - uint32_t id = p_object->get_instance_id(); + ObjectID id = p_object->get_instance_id(); if (id != editor_history.get_current()) { if (p_inspector_only) { @@ -1767,8 +1767,8 @@ static bool overrides_external_editor(Object *p_object) { void EditorNode::_edit_current() { - uint32_t current = editor_history.get_current(); - Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL; + ObjectID current = editor_history.get_current(); + Object *current_obj = current.is_valid() ? ObjectDB::get_instance(current) : NULL; bool inspector_only = editor_history.is_current_inspector_only(); this->current = current_obj; diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 0794940cb1..905e928c5a 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -388,13 +388,13 @@ void EditorPropertyMember::_property_select() { } else if (hint == MEMBER_METHOD_OF_INSTANCE) { - Object *instance = ObjectDB::get_instance(hint_text.to_int64()); + Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); if (instance) selector->select_method_from_instance(instance, current); } else if (hint == MEMBER_METHOD_OF_SCRIPT) { - Object *obj = ObjectDB::get_instance(hint_text.to_int64()); + Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); if (Object::cast_to<Script>(obj)) { selector->select_method_from_script(Object::cast_to<Script>(obj), current); } @@ -420,13 +420,13 @@ void EditorPropertyMember::_property_select() { } else if (hint == MEMBER_PROPERTY_OF_INSTANCE) { - Object *instance = ObjectDB::get_instance(hint_text.to_int64()); + Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); if (instance) selector->select_property_from_instance(instance, current); } else if (hint == MEMBER_PROPERTY_OF_SCRIPT) { - Object *obj = ObjectDB::get_instance(hint_text.to_int64()); + Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); if (Object::cast_to<Script>(obj)) { selector->select_property_from_script(Object::cast_to<Script>(obj), current); } @@ -858,7 +858,7 @@ void EditorPropertyObjectID::update_property() { type = "Object"; ObjectID id = get_edited_object()->get(get_edited_property()); - if (id != 0) { + if (id.is_valid()) { edit->set_text(type + " ID: " + itos(id)); edit->set_disabled(false); edit->set_icon(EditorNode::get_singleton()->get_class_icon(type)); diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp index 2090c12c91..c4a84bfcdc 100644 --- a/editor/editor_sectioned_inspector.cpp +++ b/editor/editor_sectioned_inspector.cpp @@ -177,7 +177,7 @@ String SectionedInspector::get_full_item_path(const String &p_item) { void SectionedInspector::edit(Object *p_object) { if (!p_object) { - obj = 0; + obj = ObjectID(); sections->clear(); filter->set_edited(NULL); @@ -308,7 +308,6 @@ EditorInspector *SectionedInspector::get_inspector() { } SectionedInspector::SectionedInspector() : - obj(0), sections(memnew(Tree)), filter(memnew(SectionedInspectorFilter)), inspector(memnew(EditorInspector)), diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index c681cdd033..954a941a96 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -166,8 +166,8 @@ void InspectorDock::_resource_file_selected(String p_file) { } void InspectorDock::_save_resource(bool save_as) const { - uint32_t current = EditorNode::get_singleton()->get_editor_history()->get_current(); - Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL; + ObjectID current = EditorNode::get_singleton()->get_editor_history()->get_current(); + Object *current_obj = current.is_valid() ? ObjectDB::get_instance(current) : NULL; ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj)); @@ -180,8 +180,8 @@ void InspectorDock::_save_resource(bool save_as) const { } void InspectorDock::_unref_resource() const { - uint32_t current = EditorNode::get_singleton()->get_editor_history()->get_current(); - Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL; + ObjectID current = EditorNode::get_singleton()->get_editor_history()->get_current(); + Object *current_obj = current.is_valid() ? ObjectDB::get_instance(current) : NULL; ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj)); @@ -191,8 +191,8 @@ void InspectorDock::_unref_resource() const { } void InspectorDock::_copy_resource() const { - uint32_t current = EditorNode::get_singleton()->get_editor_history()->get_current(); - Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL; + ObjectID current = EditorNode::get_singleton()->get_editor_history()->get_current(); + Object *current_obj = current.is_valid() ? ObjectDB::get_instance(current) : NULL; ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj)); diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp index 8dc7e4638d..a729c90160 100644 --- a/editor/plugins/animation_tree_editor_plugin.cpp +++ b/editor/plugins/animation_tree_editor_plugin.cpp @@ -59,7 +59,7 @@ void AnimationTreeEditor::edit(AnimationTree *p_tree) { path = tree->get_meta("_tree_edit_path"); edit_path(path); } else { - current_root = 0; + current_root = ObjectID(); } } @@ -128,7 +128,7 @@ void AnimationTreeEditor::edit_path(const Vector<String> &p_path) { } } } else { - current_root = 0; + current_root = ObjectID(); edited_path = button_path; } @@ -151,7 +151,7 @@ void AnimationTreeEditor::_about_to_show_root() { void AnimationTreeEditor::_notification(int p_what) { if (p_what == NOTIFICATION_PROCESS) { - ObjectID root = 0; + ObjectID root; if (tree && tree->get_tree_root().is_valid()) { root = tree->get_tree_root()->get_instance_id(); } @@ -242,7 +242,6 @@ AnimationTreeEditor::AnimationTreeEditor() { add_child(memnew(HSeparator)); - current_root = 0; singleton = this; editor_base = memnew(PanelContainer); editor_base->set_v_size_flags(SIZE_EXPAND_FILL); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 27ba518f01..f7a3b50052 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -3659,7 +3659,7 @@ bool CanvasItemEditor::_build_bones_list(Node *p_node) { // Add a last bone if the Bone2D has no Bone2D child BoneKey bk; bk.from = canvas_item->get_instance_id(); - bk.to = 0; + bk.to = ObjectID(); if (!bone_list.has(bk)) { BoneList b; b.length = 0; diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 88376f6ce6..cf6c8feaed 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -252,7 +252,7 @@ void SpatialEditorViewport::_clear_selected() { void SpatialEditorViewport::_select_clicked(bool p_append, bool p_single, bool p_allow_locked) { - if (!clicked) + if (clicked.is_null()) return; Node *node = Object::cast_to<Node>(ObjectDB::get_instance(clicked)); @@ -309,7 +309,7 @@ ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, Set<Ref<EditorSpatialGizmo> > found_gizmos; Node *edited_scene = get_tree()->get_edited_scene_root(); - ObjectID closest = 0; + ObjectID closest; Node *item = NULL; float closest_dist = 1e20; int selected_handle = -1; @@ -356,7 +356,7 @@ ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, } if (!item) - return 0; + return ObjectID(); if (!editor_selection->is_selected(item) || (r_gizmo_handle && selected_handle >= 0)) { @@ -850,9 +850,9 @@ void SpatialEditorViewport::_list_select(Ref<InputEventMouseButton> b) { clicked = selection_results[0].item->get_instance_id(); selection_results.clear(); - if (clicked) { + if (clicked.is_valid()) { _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() != SpatialEditor::TOOL_MODE_LIST_SELECT); - clicked = 0; + clicked = ObjectID(); } } else if (!selection_results.empty()) { @@ -1095,7 +1095,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (_gizmo_select(_edit.mouse_pos)) break; - clicked = 0; + clicked = ObjectID(); clicked_includes_current = false; if ((spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT && b->get_control()) || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_ROTATE) { @@ -1139,7 +1139,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { clicked_wants_append = b->get_shift(); - if (!clicked) { + if (clicked.is_null()) { if (!clicked_wants_append) _clear_selected(); @@ -1150,7 +1150,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { cursor.region_end = b->get_position(); } - if (clicked && gizmo_handle >= 0) { + if (clicked.is_valid() && gizmo_handle >= 0) { Spatial *spa = Object::cast_to<Spatial>(ObjectDB::get_instance(clicked)); if (spa) { @@ -1175,10 +1175,10 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { _edit.gizmo = Ref<EditorSpatialGizmo>(); break; } - if (clicked) { + if (clicked.is_valid()) { _select_clicked(clicked_wants_append, true); // Processing was deferred. - clicked = 0; + clicked = ObjectID(); } if (cursor.region_select) { @@ -1279,7 +1279,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } else if (nav_scheme == NAVIGATION_MODO && m->get_alt()) { nav_mode = NAVIGATION_ORBIT; } else { - if (clicked) { + if (clicked.is_valid()) { if (!clicked_includes_current) { @@ -1288,7 +1288,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } _compute_edit(_edit.mouse_pos); - clicked = 0; + clicked = ObjectID(); _edit.mode = TRANSFORM_TRANSLATE; } @@ -2945,9 +2945,9 @@ void SpatialEditorViewport::_selection_result_pressed(int p_result) { clicked = selection_results[p_result].item->get_instance_id(); - if (clicked) { + if (clicked.is_valid()) { _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() != SpatialEditor::TOOL_MODE_LIST_SELECT); - clicked = 0; + clicked = ObjectID(); } } @@ -3581,7 +3581,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed editor_data = editor->get_scene_tree_dock()->get_editor_data(); editor_selection = editor->get_editor_selection(); undo_redo = editor->get_undo_redo(); - clicked = 0; + clicked_includes_current = false; orthogonal = false; lock_rotation = false; diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 63f0b02a40..1691ce3a63 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -639,7 +639,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: MAKE_PROPSELECT - Object *instance = ObjectDB::get_instance(hint_text.to_int64()); + Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); if (instance) property_select->select_method_from_instance(instance, v); updating = false; @@ -648,7 +648,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } else if (hint == PROPERTY_HINT_METHOD_OF_SCRIPT) { MAKE_PROPSELECT - Object *obj = ObjectDB::get_instance(hint_text.to_int64()); + Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); if (Object::cast_to<Script>(obj)) { property_select->select_method_from_script(Object::cast_to<Script>(obj), v); } @@ -688,7 +688,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: MAKE_PROPSELECT - Object *instance = ObjectDB::get_instance(hint_text.to_int64()); + Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); if (instance) property_select->select_property_from_instance(instance, v); @@ -698,7 +698,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } else if (hint == PROPERTY_HINT_PROPERTY_OF_SCRIPT) { MAKE_PROPSELECT - Object *obj = ObjectDB::get_instance(hint_text.to_int64()); + Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); if (Object::cast_to<Script>(obj)) { property_select->select_property_from_script(Object::cast_to<Script>(obj), v); } diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp index fdb1ce3e62..1de5099c4a 100644 --- a/editor/property_selector.cpp +++ b/editor/property_selector.cpp @@ -404,7 +404,7 @@ void PropertySelector::select_method_from_base_type(const String &p_base, const base_type = p_base; selected = p_current; type = Variant::NIL; - script = 0; + script = ObjectID(); properties = false; instance = NULL; virtuals_only = p_virtuals_only; @@ -437,7 +437,7 @@ void PropertySelector::select_method_from_basic_type(Variant::Type p_type, const base_type = ""; selected = p_current; type = p_type; - script = 0; + script = ObjectID(); properties = false; instance = NULL; virtuals_only = false; @@ -453,7 +453,7 @@ void PropertySelector::select_method_from_instance(Object *p_instance, const Str base_type = p_instance->get_class(); selected = p_current; type = Variant::NIL; - script = 0; + script = ObjectID(); { Ref<Script> scr = p_instance->get_script(); if (scr.is_valid()) @@ -474,7 +474,7 @@ void PropertySelector::select_property_from_base_type(const String &p_base, cons base_type = p_base; selected = p_current; type = Variant::NIL; - script = 0; + script = ObjectID(); properties = true; instance = NULL; virtuals_only = false; @@ -509,7 +509,7 @@ void PropertySelector::select_property_from_basic_type(Variant::Type p_type, con base_type = ""; selected = p_current; type = p_type; - script = 0; + script = ObjectID(); properties = true; instance = NULL; virtuals_only = false; @@ -525,7 +525,7 @@ void PropertySelector::select_property_from_instance(Object *p_instance, const S base_type = ""; selected = p_current; type = Variant::NIL; - script = 0; + script = ObjectID(); properties = true; instance = p_instance; virtuals_only = false; diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index 3aec50528f..2b28aa87a3 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -172,7 +172,7 @@ public: } String get_title() { - if (remote_object_id) + if (remote_object_id.is_valid()) return TTR("Remote ") + String(type_name) + ": " + itos(remote_object_id); else return "<null>"; @@ -197,7 +197,6 @@ public: } ScriptEditorDebuggerInspectedObject() { - remote_object_id = 0; } }; @@ -302,7 +301,7 @@ void ScriptEditorDebugger::_scene_tree_selected() { return; } - inspected_object_id = item->get_metadata(0); + inspected_object_id = item->get_metadata(0).operator ObjectID(); Array msg; msg.push_back("inspect_object"); @@ -434,7 +433,7 @@ int ScriptEditorDebugger::_update_scene_tree(TreeItem *parent, const Array &node TreeItem *item = inspect_scene_tree->create_item(parent); item->set_text(0, item_text); item->set_tooltip(0, TTR("Type:") + " " + item_type); - ObjectID id = ObjectID(nodes[current_index + 3]); + ObjectID id = nodes[current_index + 3].operator ObjectID(); Ref<Texture2D> icon = EditorNode::get_singleton()->get_class_icon(nodes[current_index + 2], ""); if (icon.is_valid()) { item->set_icon(0, icon); @@ -1107,7 +1106,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da int frame_size = 6; for (int i = 0; i < p_data.size(); i += frame_size) { MultiplayerAPI::ProfilingInfo pi; - pi.node = p_data[i + 0]; + pi.node = p_data[i + 0].operator ObjectID(); pi.node_path = p_data[i + 1]; pi.incoming_rpc = p_data[i + 2]; pi.incoming_rset = p_data[i + 3]; @@ -1253,7 +1252,7 @@ void ScriptEditorDebugger::_notification(int p_what) { inspect_edited_object_timeout -= get_process_delta_time(); if (inspect_edited_object_timeout < 0) { inspect_edited_object_timeout = EditorSettings::get_singleton()->get("debugger/remote_inspect_refresh_interval"); - if (inspected_object_id) { + if (inspected_object_id.is_valid()) { if (ScriptEditorDebuggerInspectedObject *obj = Object::cast_to<ScriptEditorDebuggerInspectedObject>(ObjectDB::get_instance(editor->get_editor_history()->get_current()))) { if (obj->remote_object_id == inspected_object_id) { //take the chance and re-inspect selected object @@ -2486,7 +2485,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { auto_switch_remote_scene_tree = EDITOR_DEF("debugger/auto_switch_to_remote_scene_tree", false); inspect_scene_tree_timeout = EDITOR_DEF("debugger/remote_scene_tree_refresh_interval", 1.0); inspect_edited_object_timeout = EDITOR_DEF("debugger/remote_inspect_refresh_interval", 0.2); - inspected_object_id = 0; + inspected_object_id = ObjectID(); updating_scene_tree = false; } diff --git a/modules/bullet/area_bullet.cpp b/modules/bullet/area_bullet.cpp index 8d03a99556..7806145390 100644 --- a/modules/bullet/area_bullet.cpp +++ b/modules/bullet/area_bullet.cpp @@ -107,7 +107,7 @@ void AreaBullet::call_event(CollisionObjectBullet *p_otherObject, PhysicsServer: Object *areaGodoObject = ObjectDB::get_instance(event.event_callback_id); if (!areaGodoObject) { - event.event_callback_id = 0; + event.event_callback_id = ObjectID(); return; } @@ -279,7 +279,7 @@ void AreaBullet::set_event_callback(Type p_callbackObjectType, ObjectID p_id, co ev.event_callback_method = p_method; /// Set if monitoring - if (eventsCallbacks[0].event_callback_id || eventsCallbacks[1].event_callback_id) { + if (eventsCallbacks[0].event_callback_id.is_valid() || eventsCallbacks[1].event_callback_id.is_valid()) { set_godot_object_flags(get_godot_object_flags() | GOF_IS_MONITORING_AREA); } else { set_godot_object_flags(get_godot_object_flags() & (~GOF_IS_MONITORING_AREA)); @@ -287,7 +287,7 @@ void AreaBullet::set_event_callback(Type p_callbackObjectType, ObjectID p_id, co } bool AreaBullet::has_event_callback(Type p_callbackObjectType) { - return eventsCallbacks[static_cast<int>(p_callbackObjectType)].event_callback_id; + return eventsCallbacks[static_cast<int>(p_callbackObjectType)].event_callback_id.is_valid(); } void AreaBullet::on_enter_area(AreaBullet *p_area) { diff --git a/modules/bullet/area_bullet.h b/modules/bullet/area_bullet.h index f770c63bcc..18888c6725 100644 --- a/modules/bullet/area_bullet.h +++ b/modules/bullet/area_bullet.h @@ -50,8 +50,7 @@ public: ObjectID event_callback_id; StringName event_callback_method; - InOutEventCallback() : - event_callback_id(0) {} + InOutEventCallback() {} }; enum OverlapState { diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index fceb5d2b4b..89868babc6 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -359,7 +359,7 @@ void BulletPhysicsServer::area_attach_object_instance_id(RID p_area, ObjectID p_ ObjectID BulletPhysicsServer::area_get_object_instance_id(RID p_area) const { if (space_owner.owns(p_area)) { - return 0; + return ObjectID(); } AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND_V(!area, ObjectID()); @@ -428,14 +428,14 @@ void BulletPhysicsServer::area_set_monitor_callback(RID p_area, Object *p_receiv AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); - area->set_event_callback(CollisionObjectBullet::TYPE_RIGID_BODY, p_receiver ? p_receiver->get_instance_id() : 0, p_method); + area->set_event_callback(CollisionObjectBullet::TYPE_RIGID_BODY, p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); } void BulletPhysicsServer::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); - area->set_event_callback(CollisionObjectBullet::TYPE_AREA, p_receiver ? p_receiver->get_instance_id() : 0, p_method); + area->set_event_callback(CollisionObjectBullet::TYPE_AREA, p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); } void BulletPhysicsServer::area_set_ray_pickable(RID p_area, bool p_enable) { @@ -569,16 +569,16 @@ void BulletPhysicsServer::body_clear_shapes(RID p_body) { body->remove_all_shapes(); } -void BulletPhysicsServer::body_attach_object_instance_id(RID p_body, uint32_t p_id) { +void BulletPhysicsServer::body_attach_object_instance_id(RID p_body, ObjectID p_id) { CollisionObjectBullet *body = get_collisin_object(p_body); ERR_FAIL_COND(!body); body->set_instance_id(p_id); } -uint32_t BulletPhysicsServer::body_get_object_instance_id(RID p_body) const { +ObjectID BulletPhysicsServer::body_get_object_instance_id(RID p_body) const { CollisionObjectBullet *body = get_collisin_object(p_body); - ERR_FAIL_COND_V(!body, 0); + ERR_FAIL_COND_V(!body, ObjectID()); return body->get_instance_id(); } @@ -844,7 +844,7 @@ bool BulletPhysicsServer::body_is_omitting_force_integration(RID p_body) const { void BulletPhysicsServer::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); - body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(0), p_method, p_udata); + body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method, p_udata); } void BulletPhysicsServer::body_set_ray_pickable(RID p_body, bool p_enable) { diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h index 22032d32e3..6ea9a7a974 100644 --- a/modules/bullet/bullet_physics_server.h +++ b/modules/bullet/bullet_physics_server.h @@ -189,8 +189,8 @@ public: virtual void body_clear_shapes(RID p_body); // Used for Rigid and Soft Bodies - virtual void body_attach_object_instance_id(RID p_body, uint32_t p_id); - virtual uint32_t body_get_object_instance_id(RID p_body) const; + virtual void body_attach_object_instance_id(RID p_body, ObjectID p_id); + virtual ObjectID body_get_object_instance_id(RID p_body) const; virtual void body_set_enable_continuous_collision_detection(RID p_body, bool p_enable); virtual bool body_is_continuous_collision_detection_enabled(RID p_body) const; diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp index c916c65d2b..5b7e7281e4 100644 --- a/modules/bullet/collision_object_bullet.cpp +++ b/modules/bullet/collision_object_bullet.cpp @@ -90,7 +90,7 @@ void CollisionObjectBullet::ShapeWrapper::claim_bt_shape(const btVector3 &body_s CollisionObjectBullet::CollisionObjectBullet(Type p_type) : RIDBullet(), type(p_type), - instance_id(0), + instance_id(ObjectID()), collisionLayer(0), collisionMask(0), collisionsEnabled(true), diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp index 6e54d10abf..20467e3ef3 100644 --- a/modules/bullet/godot_result_callbacks.cpp +++ b/modules/bullet/godot_result_callbacks.cpp @@ -112,7 +112,7 @@ btScalar GodotAllConvexResultCallback::addSingleResult(btCollisionWorld::LocalCo result.shape = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID result.rid = gObj->get_self(); result.collider_id = gObj->get_instance_id(); - result.collider = 0 == result.collider_id ? NULL : ObjectDB::get_instance(result.collider_id); + result.collider = result.collider_id.is_null() ? NULL : ObjectDB::get_instance(result.collider_id); ++count; return 1; // not used by bullet @@ -220,7 +220,7 @@ btScalar GodotAllContactResultCallback::addSingleResult(btManifoldPoint &cp, con } result.collider_id = colObj->get_instance_id(); - result.collider = 0 == result.collider_id ? NULL : ObjectDB::get_instance(result.collider_id); + result.collider = result.collider_id.is_null() ? NULL : ObjectDB::get_instance(result.collider_id); result.rid = colObj->get_self(); ++m_count; } diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index dfc9647813..e5804fbde8 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -366,7 +366,7 @@ void RigidBodyBullet::dispatch_callbacks() { Object *obj = ObjectDB::get_instance(force_integration_callback->id); if (!obj) { // Remove integration callback - set_force_integration_callback(0, StringName()); + set_force_integration_callback(ObjectID(), StringName()); } else { const Variant *vp[2] = { &variantBodyDirect, &force_integration_callback->udata }; @@ -395,7 +395,7 @@ void RigidBodyBullet::set_force_integration_callback(ObjectID p_id, const String force_integration_callback = NULL; } - if (p_id != 0) { + if (p_id.is_valid()) { force_integration_callback = memnew(ForceIntegrationCallback); force_integration_callback->id = p_id; force_integration_callback->method = p_method; diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 69f3d1b393..0e4c4b4731 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -108,7 +108,7 @@ bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const V r_result.shape = btResult.m_shapeId; r_result.rid = gObj->get_self(); r_result.collider_id = gObj->get_instance_id(); - r_result.collider = 0 == r_result.collider_id ? NULL : ObjectDB::get_instance(r_result.collider_id); + r_result.collider = r_result.collider_id.is_null() ? NULL : ObjectDB::get_instance(r_result.collider_id); } else { WARN_PRINT("The raycast performed has hit a collision object that is not part of Godot scene, please check it."); } diff --git a/modules/gdnative/gdnative/gdnative.cpp b/modules/gdnative/gdnative/gdnative.cpp index 06334556d9..119bb80659 100644 --- a/modules/gdnative/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative/gdnative.cpp @@ -171,7 +171,7 @@ bool GDAPI godot_is_instance_valid(const godot_object *p_object) { } godot_object GDAPI *godot_instance_from_id(godot_int p_instance_id) { - return (godot_object *)ObjectDB::get_instance((ObjectID)p_instance_id); + return (godot_object *)ObjectDB::get_instance(ObjectID((uint64_t)p_instance_id)); } void *godot_get_class_tag(const godot_string_name *p_class) { diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp index 414b9b9eaf..59901f6139 100644 --- a/modules/gdnative/gdnative/string.cpp +++ b/modules/gdnative/gdnative/string.cpp @@ -250,7 +250,12 @@ godot_int GDAPI godot_string_findmk_from_in_place(const godot_string *p_self, co keys.write[i] = (*keys_proxy)[i]; } - return self->findmk(keys, p_from, r_key); + int key; + int ret = self->findmk(keys, p_from, &key); + if (r_key) { + *r_key = key; + } + return ret; } godot_int GDAPI godot_string_findn(const godot_string *p_self, godot_string p_what) { diff --git a/modules/gdnative/nativescript/godot_nativescript.cpp b/modules/gdnative/nativescript/godot_nativescript.cpp index e19e675344..f953206a34 100644 --- a/modules/gdnative/nativescript/godot_nativescript.cpp +++ b/modules/gdnative/nativescript/godot_nativescript.cpp @@ -36,6 +36,7 @@ #include "core/project_settings.h" #include "core/variant.h" #include "gdnative/gdnative.h" +#include <stdint.h> #include "nativescript.h" @@ -67,6 +68,14 @@ void GDAPI godot_nativescript_register_class(void *p_gdnative_handle, const char if (classes->has(p_base)) { desc.base_data = &(*classes)[p_base]; desc.base_native_type = desc.base_data->base_native_type; + + const NativeScriptDesc *b = desc.base_data; + while (b) { + desc.rpc_count += b->rpc_count; + desc.rset_count += b->rset_count; + b = b->base_data; + } + } else { desc.base_data = NULL; desc.base_native_type = p_base; @@ -87,10 +96,20 @@ void GDAPI godot_nativescript_register_tool_class(void *p_gdnative_handle, const desc.destroy_func = p_destroy_func; desc.is_tool = true; desc.base = p_base; + desc.rpc_count = 0; + desc.rset_count = 0; if (classes->has(p_base)) { desc.base_data = &(*classes)[p_base]; desc.base_native_type = desc.base_data->base_native_type; + + const NativeScriptDesc *b = desc.base_data; + while (b) { + desc.rpc_count += b->rpc_count; + desc.rset_count += b->rset_count; + b = b->base_data; + } + } else { desc.base_data = NULL; desc.base_native_type = p_base; @@ -109,6 +128,11 @@ void GDAPI godot_nativescript_register_method(void *p_gdnative_handle, const cha NativeScriptDesc::Method method; method.method = p_method; method.rpc_mode = p_attr.rpc_type; + method.rpc_method_id = UINT16_MAX; + if (p_attr.rpc_type != GODOT_METHOD_RPC_MODE_DISABLED) { + method.rpc_method_id = E->get().rpc_count; + E->get().rpc_count += 1; + } method.info = MethodInfo(p_function_name); E->get().methods.insert(p_function_name, method); @@ -125,6 +149,10 @@ void GDAPI godot_nativescript_register_property(void *p_gdnative_handle, const c property.default_value = *(Variant *)&p_attr->default_value; property.getter = p_get_func; property.rset_mode = p_attr->rset_type; + if (p_attr->rset_type != GODOT_METHOD_RPC_MODE_DISABLED) { + property.rset_property_id = E->get().rset_count; + E->get().rset_count += 1; + } property.setter = p_set_func; property.info = PropertyInfo((Variant::Type)p_attr->type, p_path, diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index 8b06af6c7b..df85155ff5 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -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; } -MultiplayerAPI::RPCMode NativeScriptInstance::get_rpc_mode(const StringName &p_method) const { - - NativeScriptDesc *script_data = GET_SCRIPT_DESC(); - - while (script_data) { +Vector<ScriptNetData> NativeScriptInstance::get_rpc_methods() const { + return script->get_rpc_methods(); +} - 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; - } - } +uint16_t NativeScriptInstance::get_rpc_method_id(const StringName &p_method) const { + return script->get_rpc_method_id(p_method); +} - script_data = script_data->base_data; - } +StringName NativeScriptInstance::get_rpc_method(uint16_t p_id) const { + return script->get_rpc_method(p_id); +} - return MultiplayerAPI::RPC_MODE_DISABLED; +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_rset_mode(const StringName &p_variable) const { +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); +} - 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; - } - } +StringName NativeScriptInstance::get_rset_property(uint16_t p_id) const { + return script->get_rset_property(p_id); +} - script_data = script_data->base_data; - } +MultiplayerAPI::RPCMode NativeScriptInstance::get_rset_mode_by_id(uint16_t p_id) const { + return script->get_rset_mode_by_id(p_id); +} - return MultiplayerAPI::RPC_MODE_DISABLED; +MultiplayerAPI::RPCMode NativeScriptInstance::get_rset_mode(const StringName &p_variable) const { + return script->get_rset_mode(p_variable); } ScriptLanguage *NativeScriptInstance::get_language() { diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h index cf787e1f6a..2ff08e32cd 100644 --- a/modules/gdnative/nativescript/nativescript.h +++ b/modules/gdnative/nativescript/nativescript.h @@ -54,6 +54,7 @@ struct NativeScriptDesc { godot_instance_method method; MethodInfo info; int rpc_mode; + uint16_t rpc_method_id; String documentation; }; struct Property { @@ -62,6 +63,7 @@ struct NativeScriptDesc { PropertyInfo info; Variant default_value; int rset_mode; + uint16_t rset_property_id; String documentation; }; @@ -70,7 +72,9 @@ struct NativeScriptDesc { String documentation; }; + uint16_t rpc_count; Map<StringName, Method> methods; + uint16_t rset_count; OrderedHashMap<StringName, Property> properties; Map<StringName, Signal> signals_; // QtCreator doesn't like the name signals StringName base; @@ -86,7 +90,9 @@ struct NativeScriptDesc { bool is_tool; inline NativeScriptDesc() : + rpc_count(0), methods(), + rset_count(0), properties(), signals_(), base(), @@ -174,6 +180,18 @@ public: virtual void get_script_method_list(List<MethodInfo> *p_list) const; virtual void get_script_property_list(List<PropertyInfo> *p_list) 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(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; + String get_class_documentation() const; String get_method_documentation(const StringName &p_method) const; String get_signal_documentation(const StringName &p_signal_name) const; @@ -210,8 +228,19 @@ public: virtual void notification(int p_notification); String to_string(bool *r_valid); virtual Ref<Script> get_script() 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(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 ScriptLanguage *get_language(); virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount); diff --git a/modules/gdnative/pluginscript/pluginscript_instance.cpp b/modules/gdnative/pluginscript/pluginscript_instance.cpp index 0d6dac3268..26a1d5f47a 100644 --- a/modules/gdnative/pluginscript/pluginscript_instance.cpp +++ b/modules/gdnative/pluginscript/pluginscript_instance.cpp @@ -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); } diff --git a/modules/gdnative/pluginscript/pluginscript_instance.h b/modules/gdnative/pluginscript/pluginscript_instance.h index dc1229a44d..154bebd72a 100644 --- a/modules/gdnative/pluginscript/pluginscript_instance.h +++ b/modules/gdnative/pluginscript/pluginscript_instance.h @@ -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(); diff --git a/modules/gdnative/pluginscript/pluginscript_script.cpp b/modules/gdnative/pluginscript/pluginscript_script.cpp index cc5bdee0a1..c370062262 100644 --- a/modules/gdnative/pluginscript/pluginscript_script.cpp +++ b/modules/gdnative/pluginscript/pluginscript_script.cpp @@ -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; } -MultiplayerAPI::RPCMode PluginScript::get_rpc_mode(const StringName &p_method) const { +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); - const Map<StringName, MultiplayerAPI::RPCMode>::Element *e = _methods_rpc_mode.find(p_method); - if (e != NULL) { - return e->get(); - } else { + 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); + 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; } -MultiplayerAPI::RPCMode PluginScript::get_rset_mode(const StringName &p_variable) const { +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); - const Map<StringName, MultiplayerAPI::RPCMode>::Element *e = _variables_rset_mode.find(p_variable); - if (e != NULL) { - return e->get(); - } else { + 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); + return get_rset_mode_by_id(get_rset_property_id(p_variable)); } PluginScript::PluginScript() : diff --git a/modules/gdnative/pluginscript/pluginscript_script.h b/modules/gdnative/pluginscript/pluginscript_script.h index f67c88c794..f6bca8a9cb 100644 --- a/modules/gdnative/pluginscript/pluginscript_script.h +++ b/modules/gdnative/pluginscript/pluginscript_script.h @@ -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); diff --git a/modules/gdnavigation/gd_navigation_server.cpp b/modules/gdnavigation/gd_navigation_server.cpp index ddfb3c10fa..2780e2a931 100644 --- a/modules/gdnavigation/gd_navigation_server.cpp +++ b/modules/gdnavigation/gd_navigation_server.cpp @@ -374,7 +374,7 @@ COMMAND_4(agent_set_callback, RID, p_agent, Object *, p_receiver, StringName, p_ RvoAgent *agent = agent_owner.getornull(p_agent); ERR_FAIL_COND(agent == NULL); - agent->set_callback(p_receiver == NULL ? 0 : p_receiver->get_instance_id(), p_method, p_udata); + agent->set_callback(p_receiver == NULL ? ObjectID() : p_receiver->get_instance_id(), p_method, p_udata); if (agent->get_map()) { if (p_receiver == NULL) { diff --git a/modules/gdnavigation/rvo_agent.cpp b/modules/gdnavigation/rvo_agent.cpp index eb66eb3a05..4d19bc15af 100644 --- a/modules/gdnavigation/rvo_agent.cpp +++ b/modules/gdnavigation/rvo_agent.cpp @@ -38,7 +38,7 @@ RvoAgent::RvoAgent() : map(NULL) { - callback.id = ObjectID(0); + callback.id = ObjectID(); } void RvoAgent::set_map(NavMap *p_map) { @@ -62,16 +62,16 @@ void RvoAgent::set_callback(ObjectID p_id, const StringName p_method, const Vari } bool RvoAgent::has_callback() const { - return callback.id != 0; + return callback.id.is_valid(); } void RvoAgent::dispatch_callback() { - if (callback.id == 0) { + if (callback.id.is_null()) { return; } Object *obj = ObjectDB::get_instance(callback.id); if (obj == NULL) { - callback.id = ObjectID(0); + callback.id = ObjectID(); } Variant::CallError responseCallError; diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index a255b92257..e4da60b5b9 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -30,6 +30,8 @@ #include "gdscript.h" +#include <stdint.h> + #include "core/core_string_names.h" #include "core/engine.h" #include "core/global_constants.h" @@ -610,6 +612,53 @@ Error GDScript::reload(bool p_keep_state) { _set_subclass_path(E->get(), path); } + // Copy the base rpc methods so we don't mask their IDs. + rpc_functions.clear(); + rpc_variables.clear(); + if (base.is_valid()) { + rpc_functions = base->rpc_functions; + rpc_variables = base->rpc_variables; + } + + GDScript *cscript = this; + Map<StringName, Ref<GDScript> >::Element *sub_E = subclasses.front(); + while (cscript) { + // RPC Methods + for (Map<StringName, GDScriptFunction *>::Element *E = cscript->member_functions.front(); E; E = E->next()) { + if (E->get()->get_rpc_mode() != MultiplayerAPI::RPC_MODE_DISABLED) { + ScriptNetData nd; + nd.name = E->key(); + nd.mode = E->get()->get_rpc_mode(); + if (-1 == rpc_functions.find(nd)) { + rpc_functions.push_back(nd); + } + } + } + // RSet + for (Map<StringName, MemberInfo>::Element *E = cscript->member_indices.front(); E; E = E->next()) { + if (E->get().rpc_mode != MultiplayerAPI::RPC_MODE_DISABLED) { + ScriptNetData nd; + nd.name = E->key(); + nd.mode = E->get().rpc_mode; + if (-1 == rpc_variables.find(nd)) { + rpc_variables.push_back(nd); + } + } + } + + if (cscript != this) + sub_E = sub_E->next(); + + if (sub_E) + cscript = sub_E->get().ptr(); + else + cscript = NULL; + } + + // Sort so we are 100% that they are always the same. + rpc_functions.sort_custom<SortNetData>(); + rpc_variables.sort_custom<SortNetData>(); + return OK; } @@ -635,6 +684,60 @@ void GDScript::get_members(Set<StringName> *p_members) { } } +Vector<ScriptNetData> GDScript::get_rpc_methods() const { + return rpc_functions; +} + +uint16_t GDScript::get_rpc_method_id(const StringName &p_method) const { + for (int i = 0; i < rpc_functions.size(); i++) { + if (rpc_functions[i].name == p_method) { + return i; + } + } + return UINT16_MAX; +} + +StringName GDScript::get_rpc_method(const uint16_t p_rpc_method_id) const { + ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), StringName()); + return rpc_functions[p_rpc_method_id].name; +} + +MultiplayerAPI::RPCMode GDScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const { + ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED); + return rpc_functions[p_rpc_method_id].mode; +} + +MultiplayerAPI::RPCMode GDScript::get_rpc_mode(const StringName &p_method) const { + return get_rpc_mode_by_id(get_rpc_method_id(p_method)); +} + +Vector<ScriptNetData> GDScript::get_rset_properties() const { + return rpc_variables; +} + +uint16_t GDScript::get_rset_property_id(const StringName &p_variable) const { + for (int i = 0; i < rpc_variables.size(); i++) { + if (rpc_variables[i].name == p_variable) { + return i; + } + } + return UINT16_MAX; +} + +StringName GDScript::get_rset_property(const uint16_t p_rset_member_id) const { + ERR_FAIL_COND_V(p_rset_member_id >= rpc_variables.size(), StringName()); + return rpc_variables[p_rset_member_id].name; +} + +MultiplayerAPI::RPCMode GDScript::get_rset_mode_by_id(const uint16_t p_rset_member_id) const { + ERR_FAIL_COND_V(p_rset_member_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED); + return rpc_functions[p_rset_member_id].mode; +} + +MultiplayerAPI::RPCMode GDScript::get_rset_mode(const StringName &p_variable) const { + return get_rset_mode_by_id(get_rset_property_id(p_variable)); +} + Variant GDScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) { GDScript *top = this; @@ -1291,40 +1394,44 @@ ScriptLanguage *GDScriptInstance::get_language() { return GDScriptLanguage::get_singleton(); } -MultiplayerAPI::RPCMode GDScriptInstance::get_rpc_mode(const StringName &p_method) const { +Vector<ScriptNetData> GDScriptInstance::get_rpc_methods() const { + return script->get_rpc_methods(); +} - const GDScript *cscript = script.ptr(); +uint16_t GDScriptInstance::get_rpc_method_id(const StringName &p_method) const { + return script->get_rpc_method_id(p_method); +} - while (cscript) { - const Map<StringName, GDScriptFunction *>::Element *E = cscript->member_functions.find(p_method); - if (E) { +StringName GDScriptInstance::get_rpc_method(const uint16_t p_rpc_method_id) const { + return script->get_rpc_method(p_rpc_method_id); +} - if (E->get()->get_rpc_mode() != MultiplayerAPI::RPC_MODE_DISABLED) { - return E->get()->get_rpc_mode(); - } - } - cscript = cscript->_base; - } +MultiplayerAPI::RPCMode GDScriptInstance::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const { + return script->get_rpc_mode_by_id(p_rpc_method_id); +} - return MultiplayerAPI::RPC_MODE_DISABLED; +MultiplayerAPI::RPCMode GDScriptInstance::get_rpc_mode(const StringName &p_method) const { + return script->get_rpc_mode(p_method); } -MultiplayerAPI::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_variable) const { +Vector<ScriptNetData> GDScriptInstance::get_rset_properties() const { + return script->get_rset_properties(); +} - const GDScript *cscript = script.ptr(); +uint16_t GDScriptInstance::get_rset_property_id(const StringName &p_variable) const { + return script->get_rset_property_id(p_variable); +} - while (cscript) { - const Map<StringName, GDScript::MemberInfo>::Element *E = cscript->member_indices.find(p_variable); - if (E) { +StringName GDScriptInstance::get_rset_property(const uint16_t p_rset_member_id) const { + return script->get_rset_property(p_rset_member_id); +} - if (E->get().rpc_mode) { - return E->get().rpc_mode; - } - } - cscript = cscript->_base; - } +MultiplayerAPI::RPCMode GDScriptInstance::get_rset_mode_by_id(const uint16_t p_rset_member_id) const { + return script->get_rset_mode_by_id(p_rset_member_id); +} - return MultiplayerAPI::RPC_MODE_DISABLED; +MultiplayerAPI::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_variable) const { + return script->get_rset_mode(p_variable); } void GDScriptInstance::reload_members() { diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 4ae52238ce..4af574cd9d 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -85,6 +85,8 @@ class GDScript : public Script { Map<StringName, MemberInfo> member_indices; //members are just indices to the instanced script. Map<StringName, Ref<GDScript> > subclasses; Map<StringName, Vector<StringName> > _signals; + Vector<ScriptNetData> rpc_functions; + Vector<ScriptNetData> rpc_variables; #ifdef TOOLS_ENABLED @@ -213,6 +215,18 @@ public: virtual void get_constants(Map<StringName, Variant> *p_constants); virtual void get_members(Set<StringName> *p_members); + 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_variable) const; + virtual StringName get_rset_property(const uint16_t p_variable_id) const; + virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_variable_id) const; + virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const; + #ifdef TOOLS_ENABLED virtual bool is_placeholder_fallback_enabled() const { return placeholder_fallback_enabled; } #endif @@ -264,7 +278,16 @@ public: void reload_members(); + 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_variable) const; + virtual StringName get_rset_property(const uint16_t p_variable_id) const; + virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_variable_id) const; virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const; GDScriptInstance(); diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index 452b1933eb..7392bbc10a 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -1274,7 +1274,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a gdfs->state.script = Ref<GDScript>(_script); gdfs->state.ip = ip + ipofs; gdfs->state.line = line; - gdfs->state.instance_id = (p_instance && p_instance->get_owner()) ? p_instance->get_owner()->get_instance_id() : 0; + gdfs->state.instance_id = (p_instance && p_instance->get_owner()) ? p_instance->get_owner()->get_instance_id() : ObjectID(); //gdfs->state.result_pos=ip+ipofs-1; gdfs->state.defarg = defarg; gdfs->state.instance = p_instance; @@ -1829,7 +1829,7 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const { if (p_extended_check) { //class instance gone? - if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) + if (state.instance_id.is_valid() && !ObjectDB::get_instance(state.instance_id)) return false; } @@ -1839,7 +1839,7 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const { Variant GDScriptFunctionState::resume(const Variant &p_arg) { ERR_FAIL_COND_V(!function, Variant()); - if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) { + if (state.instance_id.is_valid() && !ObjectDB::get_instance(state.instance_id)) { #ifdef DEBUG_ENABLED ERR_FAIL_V_MSG(Variant(), "Resumed function '" + String(function->get_name()) + "()' after yield, but class instance is gone. At script: " + state.script->get_path() + ":" + itos(state.line)); #else diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp index c398633dc5..27d67fda6d 100644 --- a/modules/gdscript/gdscript_functions.cpp +++ b/modules/gdscript/gdscript_functions.cpp @@ -1374,7 +1374,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ break; } - uint32_t id = *p_args[0]; + ObjectID id = *p_args[0]; r_ret = ObjectDB::get_instance(id); } break; diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 2847f3b414..10bc3dcb49 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -31,6 +31,7 @@ #include "csharp_script.h" #include <mono/metadata/threads.h> +#include <stdint.h> #include "core/io/json.h" #include "core/os/file_access.h" @@ -161,11 +162,11 @@ void CSharpLanguage::finish() { #ifdef DEBUG_ENABLED for (Map<ObjectID, int>::Element *E = unsafe_object_references.front(); E; E = E->next()) { - const ObjectID &id = E->get(); + const ObjectID &id = E->key(); Object *obj = ObjectDB::get_instance(id); if (obj) { - ERR_PRINT("Leaked unsafe reference to object: " + obj->get_class() + ":" + itos(id)); + ERR_PRINT("Leaked unsafe reference to object: " + obj->to_string()); } else { ERR_PRINT("Leaked unsafe reference to deleted object: " + itos(id)); } @@ -1979,67 +1980,44 @@ bool CSharpInstance::refcount_decremented() { return ref_dying; } -MultiplayerAPI::RPCMode CSharpInstance::_member_get_rpc_mode(IMonoClassMember *p_member) const { - - if (p_member->has_attribute(CACHED_CLASS(RemoteAttribute))) - return MultiplayerAPI::RPC_MODE_REMOTE; - if (p_member->has_attribute(CACHED_CLASS(MasterAttribute))) - return MultiplayerAPI::RPC_MODE_MASTER; - if (p_member->has_attribute(CACHED_CLASS(PuppetAttribute))) - return MultiplayerAPI::RPC_MODE_PUPPET; - if (p_member->has_attribute(CACHED_CLASS(SlaveAttribute))) - return MultiplayerAPI::RPC_MODE_PUPPET; - if (p_member->has_attribute(CACHED_CLASS(RemoteSyncAttribute))) - return MultiplayerAPI::RPC_MODE_REMOTESYNC; - if (p_member->has_attribute(CACHED_CLASS(SyncAttribute))) - return MultiplayerAPI::RPC_MODE_REMOTESYNC; - if (p_member->has_attribute(CACHED_CLASS(MasterSyncAttribute))) - return MultiplayerAPI::RPC_MODE_MASTERSYNC; - if (p_member->has_attribute(CACHED_CLASS(PuppetSyncAttribute))) - return MultiplayerAPI::RPC_MODE_PUPPETSYNC; +Vector<ScriptNetData> CSharpInstance::get_rpc_methods() const { + return script->get_rpc_methods(); +} - return MultiplayerAPI::RPC_MODE_DISABLED; +uint16_t CSharpInstance::get_rpc_method_id(const StringName &p_method) const { + return script->get_rpc_method_id(p_method); } -MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) const { +StringName CSharpInstance::get_rpc_method(const uint16_t p_rpc_method_id) const { + return script->get_rpc_method(p_rpc_method_id); +} - GD_MONO_SCOPE_THREAD_ATTACH; +MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const { + return script->get_rpc_mode_by_id(p_rpc_method_id); +} - GDMonoClass *top = script->script_class; +MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) const { + return script->get_rpc_mode(p_method); +} - while (top && top != script->native) { - GDMonoMethod *method = top->get_fetched_method_unknown_params(p_method); +Vector<ScriptNetData> CSharpInstance::get_rset_properties() const { + return script->get_rset_properties(); +} - if (method && !method->is_static()) - return _member_get_rpc_mode(method); +uint16_t CSharpInstance::get_rset_property_id(const StringName &p_variable) const { + return script->get_rset_property_id(p_variable); +} - top = top->get_parent_class(); - } +StringName CSharpInstance::get_rset_property(const uint16_t p_rset_member_id) const { + return script->get_rset_property(p_rset_member_id); +} - return MultiplayerAPI::RPC_MODE_DISABLED; +MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode_by_id(const uint16_t p_rset_member_id) const { + return script->get_rset_mode_by_id(p_rset_member_id); } MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variable) const { - - GD_MONO_SCOPE_THREAD_ATTACH; - - GDMonoClass *top = script->script_class; - - while (top && top != script->native) { - GDMonoField *field = top->get_field(p_variable); - - if (field && !field->is_static()) - return _member_get_rpc_mode(field); - - GDMonoProperty *property = top->get_property(p_variable); - - if (property && !property->is_static()) - return _member_get_rpc_mode(property); - - top = top->get_parent_class(); - } - - return MultiplayerAPI::RPC_MODE_DISABLED; + return script->get_rset_mode(p_variable); } void CSharpInstance::notification(int p_notification) { @@ -3251,6 +3229,69 @@ Error CSharpScript::reload(bool p_keep_state) { _update_exports(); } + rpc_functions.clear(); + rpc_variables.clear(); + + GDMonoClass *top = script_class; + while (top && top != native) { + { + Vector<GDMonoMethod *> methods = top->get_all_methods(); + for (int i = 0; i < methods.size(); i++) { + if (!methods[i]->is_static()) { + MultiplayerAPI::RPCMode mode = _member_get_rpc_mode(methods[i]); + if (MultiplayerAPI::RPC_MODE_DISABLED != mode) { + ScriptNetData nd; + nd.name = methods[i]->get_name(); + nd.mode = mode; + if (-1 == rpc_functions.find(nd)) { + rpc_functions.push_back(nd); + } + } + } + } + } + + { + Vector<GDMonoField *> fields = top->get_all_fields(); + for (int i = 0; i < fields.size(); i++) { + if (!fields[i]->is_static()) { + MultiplayerAPI::RPCMode mode = _member_get_rpc_mode(fields[i]); + if (MultiplayerAPI::RPC_MODE_DISABLED != mode) { + ScriptNetData nd; + nd.name = fields[i]->get_name(); + nd.mode = mode; + if (-1 == rpc_variables.find(nd)) { + rpc_variables.push_back(nd); + } + } + } + } + } + + { + Vector<GDMonoProperty *> properties = top->get_all_properties(); + for (int i = 0; i < properties.size(); i++) { + if (!properties[i]->is_static()) { + MultiplayerAPI::RPCMode mode = _member_get_rpc_mode(properties[i]); + if (MultiplayerAPI::RPC_MODE_DISABLED != mode) { + ScriptNetData nd; + nd.name = properties[i]->get_name(); + nd.mode = mode; + if (-1 == rpc_variables.find(nd)) { + rpc_variables.push_back(nd); + } + } + } + } + } + + top = top->get_parent_class(); + } + + // Sort so we are 100% that they are always the same. + rpc_functions.sort_custom<SortNetData>(); + rpc_variables.sort_custom<SortNetData>(); + return OK; } @@ -3324,6 +3365,82 @@ int CSharpScript::get_member_line(const StringName &p_member) const { return -1; } +MultiplayerAPI::RPCMode CSharpScript::_member_get_rpc_mode(IMonoClassMember *p_member) const { + + if (p_member->has_attribute(CACHED_CLASS(RemoteAttribute))) + return MultiplayerAPI::RPC_MODE_REMOTE; + if (p_member->has_attribute(CACHED_CLASS(MasterAttribute))) + return MultiplayerAPI::RPC_MODE_MASTER; + if (p_member->has_attribute(CACHED_CLASS(PuppetAttribute))) + return MultiplayerAPI::RPC_MODE_PUPPET; + if (p_member->has_attribute(CACHED_CLASS(SlaveAttribute))) + return MultiplayerAPI::RPC_MODE_PUPPET; + if (p_member->has_attribute(CACHED_CLASS(RemoteSyncAttribute))) + return MultiplayerAPI::RPC_MODE_REMOTESYNC; + if (p_member->has_attribute(CACHED_CLASS(SyncAttribute))) + return MultiplayerAPI::RPC_MODE_REMOTESYNC; + if (p_member->has_attribute(CACHED_CLASS(MasterSyncAttribute))) + return MultiplayerAPI::RPC_MODE_MASTERSYNC; + if (p_member->has_attribute(CACHED_CLASS(PuppetSyncAttribute))) + return MultiplayerAPI::RPC_MODE_PUPPETSYNC; + + return MultiplayerAPI::RPC_MODE_DISABLED; +} + +Vector<ScriptNetData> CSharpScript::get_rpc_methods() const { + return rpc_functions; +} + +uint16_t CSharpScript::get_rpc_method_id(const StringName &p_method) const { + for (int i = 0; i < rpc_functions.size(); i++) { + if (rpc_functions[i].name == p_method) { + return i; + } + } + return UINT16_MAX; +} + +StringName CSharpScript::get_rpc_method(const uint16_t p_rpc_method_id) const { + ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), StringName()); + return rpc_functions[p_rpc_method_id].name; +} + +MultiplayerAPI::RPCMode CSharpScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const { + ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED); + return rpc_functions[p_rpc_method_id].mode; +} + +MultiplayerAPI::RPCMode CSharpScript::get_rpc_mode(const StringName &p_method) const { + return get_rpc_mode_by_id(get_rpc_method_id(p_method)); +} + +Vector<ScriptNetData> CSharpScript::get_rset_properties() const { + return rpc_variables; +} + +uint16_t CSharpScript::get_rset_property_id(const StringName &p_variable) const { + for (int i = 0; i < rpc_variables.size(); i++) { + if (rpc_variables[i].name == p_variable) { + return i; + } + } + return UINT16_MAX; +} + +StringName CSharpScript::get_rset_property(const uint16_t p_rset_member_id) const { + ERR_FAIL_COND_V(p_rset_member_id >= rpc_variables.size(), StringName()); + return rpc_variables[p_rset_member_id].name; +} + +MultiplayerAPI::RPCMode CSharpScript::get_rset_mode_by_id(const uint16_t p_rset_member_id) const { + ERR_FAIL_COND_V(p_rset_member_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED); + return rpc_functions[p_rset_member_id].mode; +} + +MultiplayerAPI::RPCMode CSharpScript::get_rset_mode(const StringName &p_variable) const { + return get_rset_mode_by_id(get_rset_property_id(p_variable)); +} + Error CSharpScript::load_source_code(const String &p_path) { Error ferr = read_all_file_utf8(p_path, source); diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index f244bc4119..32a5b30c18 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -113,6 +113,9 @@ class CSharpScript : public Script { Map<StringName, Vector<Argument> > _signals; bool signals_invalidated; + Vector<ScriptNetData> rpc_functions; + Vector<ScriptNetData> rpc_variables; + #ifdef TOOLS_ENABLED List<PropertyInfo> exported_members_cache; // members_cache Map<StringName, Variant> exported_members_defval_cache; // member_default_values_cache @@ -146,6 +149,8 @@ class CSharpScript : public Script { static Ref<CSharpScript> create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native); static void initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native); + MultiplayerAPI::RPCMode _member_get_rpc_mode(IMonoClassMember *p_member) const; + protected: static void _bind_methods(); @@ -187,6 +192,18 @@ public: virtual int get_member_line(const StringName &p_member) 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_variable) const; + virtual StringName get_rset_property(const uint16_t p_variable_id) const; + virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_variable_id) const; + virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const; + #ifdef TOOLS_ENABLED virtual bool is_placeholder_fallback_enabled() const { return placeholder_fallback_enabled; } #endif @@ -232,8 +249,6 @@ class CSharpInstance : public ScriptInstance { void _call_multilevel(MonoObject *p_mono_object, const StringName &p_method, const Variant **p_args, int p_argcount); - MultiplayerAPI::RPCMode _member_get_rpc_mode(IMonoClassMember *p_member) const; - void get_properties_state_for_reloading(List<Pair<StringName, Variant> > &r_state); public: @@ -265,7 +280,16 @@ public: virtual void refcount_incremented(); virtual bool refcount_decremented(); + 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_variable) const; + virtual StringName get_rset_property(const uint16_t p_variable_id) const; + virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_variable_id) const; virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const; virtual void notification(int p_notification); diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp index d3226762ea..b85d5f2fd9 100644 --- a/modules/mono/signal_awaiter_utils.cpp +++ b/modules/mono/signal_awaiter_utils.cpp @@ -68,7 +68,7 @@ Error connect_signal_awaiter(Object *p_source, const String &p_signal, Object *p Variant SignalAwaiterHandle::_signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error) { #ifdef DEBUG_ENABLED - ERR_FAIL_COND_V_MSG(conn_target_id && !ObjectDB::get_instance(conn_target_id), Variant(), + ERR_FAIL_COND_V_MSG(conn_target_id.is_valid() && !ObjectDB::get_instance(conn_target_id), Variant(), "Resumed after await, but class instance is gone."); #endif @@ -116,12 +116,7 @@ void SignalAwaiterHandle::_bind_methods() { } SignalAwaiterHandle::SignalAwaiterHandle(MonoObject *p_managed) : - MonoGCHandle(MonoGCHandle::new_strong_handle(p_managed), STRONG_HANDLE) { - -#ifdef DEBUG_ENABLED - conn_target_id = 0; -#endif -} + MonoGCHandle(MonoGCHandle::new_strong_handle(p_managed), STRONG_HANDLE) {} SignalAwaiterHandle::~SignalAwaiterHandle() { diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index c591e3b5c2..e712190344 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -30,6 +30,8 @@ #include "visual_script.h" +#include <stdint.h> + #include "core/core_string_names.h" #include "core/os/os.h" #include "core/project_settings.h" @@ -1102,6 +1104,60 @@ bool VisualScript::are_subnodes_edited() const { } #endif +Vector<ScriptNetData> VisualScript::get_rpc_methods() const { + return rpc_functions; +} + +uint16_t VisualScript::get_rpc_method_id(const StringName &p_method) const { + for (int i = 0; i < rpc_functions.size(); i++) { + if (rpc_functions[i].name == p_method) { + return i; + } + } + return UINT16_MAX; +} + +StringName VisualScript::get_rpc_method(const uint16_t p_rpc_method_id) const { + ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), StringName()); + return rpc_functions[p_rpc_method_id].name; +} + +MultiplayerAPI::RPCMode VisualScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const { + ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED); + return rpc_functions[p_rpc_method_id].mode; +} + +MultiplayerAPI::RPCMode VisualScript::get_rpc_mode(const StringName &p_method) const { + return get_rpc_mode_by_id(get_rpc_method_id(p_method)); +} + +Vector<ScriptNetData> VisualScript::get_rset_properties() const { + return rpc_variables; +} + +uint16_t VisualScript::get_rset_property_id(const StringName &p_variable) const { + for (int i = 0; i < rpc_variables.size(); i++) { + if (rpc_variables[i].name == p_variable) { + return i; + } + } + return UINT16_MAX; +} + +StringName VisualScript::get_rset_property(const uint16_t p_rset_property_id) const { + ERR_FAIL_COND_V(p_rset_property_id >= rpc_variables.size(), StringName()); + return rpc_variables[p_rset_property_id].name; +} + +MultiplayerAPI::RPCMode VisualScript::get_rset_mode_by_id(const uint16_t p_rset_variable_id) const { + ERR_FAIL_COND_V(p_rset_variable_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED); + return rpc_functions[p_rset_variable_id].mode; +} + +MultiplayerAPI::RPCMode VisualScript::get_rset_mode(const StringName &p_variable) const { + return get_rset_mode_by_id(get_rset_property_id(p_variable)); +} + void VisualScript::_set_data(const Dictionary &p_data) { Dictionary d = p_data; @@ -1206,6 +1262,30 @@ void VisualScript::_set_data(const Dictionary &p_data) { is_tool_script = d["is_tool_script"]; else is_tool_script = false; + + // Takes all the rpc methods + rpc_functions.clear(); + rpc_variables.clear(); + for (Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) { + if (E->get().function_id >= 0 && E->get().nodes.find(E->get().function_id)) { + Ref<VisualScriptFunction> vsf = E->get().nodes[E->get().function_id].node; + if (vsf.is_valid()) { + if (vsf->get_rpc_mode() != MultiplayerAPI::RPC_MODE_DISABLED) { + ScriptNetData nd; + nd.name = E->key(); + nd.mode = vsf->get_rpc_mode(); + if (rpc_functions.find(nd) == -1) { + rpc_functions.push_back(nd); + } + } + } + } + } + + // Visual script doesn't have rset :( + + // Sort so we are 100% that they are always the same. + rpc_functions.sort_custom<SortNetData>(); } Dictionary VisualScript::_get_data() const { @@ -2043,31 +2123,44 @@ Ref<Script> VisualScriptInstance::get_script() const { return script; } -MultiplayerAPI::RPCMode VisualScriptInstance::get_rpc_mode(const StringName &p_method) const { +Vector<ScriptNetData> VisualScriptInstance::get_rpc_methods() const { + return script->get_rpc_methods(); +} - if (p_method == script->get_default_func()) - return MultiplayerAPI::RPC_MODE_DISABLED; +uint16_t VisualScriptInstance::get_rpc_method_id(const StringName &p_method) const { + return script->get_rpc_method_id(p_method); +} - const Map<StringName, VisualScript::Function>::Element *E = script->functions.find(p_method); - if (!E) { - return MultiplayerAPI::RPC_MODE_DISABLED; - } +StringName VisualScriptInstance::get_rpc_method(const uint16_t p_rpc_method_id) const { + return script->get_rpc_method(p_rpc_method_id); +} - if (E->get().function_id >= 0 && E->get().nodes.has(E->get().function_id)) { +MultiplayerAPI::RPCMode VisualScriptInstance::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const { + return script->get_rpc_mode_by_id(p_rpc_method_id); +} - Ref<VisualScriptFunction> vsf = E->get().nodes[E->get().function_id].node; - if (vsf.is_valid()) { +MultiplayerAPI::RPCMode VisualScriptInstance::get_rpc_mode(const StringName &p_method) const { + return script->get_rpc_mode(p_method); +} - return vsf->get_rpc_mode(); - } - } +Vector<ScriptNetData> VisualScriptInstance::get_rset_properties() const { + return script->get_rset_properties(); +} - return MultiplayerAPI::RPC_MODE_DISABLED; +uint16_t VisualScriptInstance::get_rset_property_id(const StringName &p_variable) const { + return script->get_rset_property_id(p_variable); } -MultiplayerAPI::RPCMode VisualScriptInstance::get_rset_mode(const StringName &p_variable) const { +StringName VisualScriptInstance::get_rset_property(const uint16_t p_rset_property_id) const { + return script->get_rset_property(p_rset_property_id); +} - return MultiplayerAPI::RPC_MODE_DISABLED; +MultiplayerAPI::RPCMode VisualScriptInstance::get_rset_mode_by_id(const uint16_t p_rset_variable_id) const { + return script->get_rset_mode_by_id(p_rset_variable_id); +} + +MultiplayerAPI::RPCMode VisualScriptInstance::get_rset_mode(const StringName &p_variable) const { + return script->get_rset_mode(p_variable); } void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_owner) { @@ -2321,8 +2414,8 @@ Variant VisualScriptFunctionState::_signal_callback(const Variant **p_args, int #ifdef DEBUG_ENABLED - ERR_FAIL_COND_V_MSG(instance_id && !ObjectDB::get_instance(instance_id), Variant(), "Resumed after yield, but class instance is gone."); - ERR_FAIL_COND_V_MSG(script_id && !ObjectDB::get_instance(script_id), Variant(), "Resumed after yield, but script is gone."); + ERR_FAIL_COND_V_MSG(instance_id.is_valid() && !ObjectDB::get_instance(instance_id), Variant(), "Resumed after yield, but class instance is gone."); + ERR_FAIL_COND_V_MSG(script_id.is_valid() && !ObjectDB::get_instance(script_id), Variant(), "Resumed after yield, but script is gone."); #endif @@ -2383,8 +2476,8 @@ Variant VisualScriptFunctionState::resume(Array p_args) { ERR_FAIL_COND_V(function == StringName(), Variant()); #ifdef DEBUG_ENABLED - ERR_FAIL_COND_V_MSG(instance_id && !ObjectDB::get_instance(instance_id), Variant(), "Resumed after yield, but class instance is gone."); - ERR_FAIL_COND_V_MSG(script_id && !ObjectDB::get_instance(script_id), Variant(), "Resumed after yield, but script is gone."); + ERR_FAIL_COND_V_MSG(instance_id.is_valid() && !ObjectDB::get_instance(instance_id), Variant(), "Resumed after yield, but class instance is gone."); + ERR_FAIL_COND_V_MSG(script_id.is_valid() && !ObjectDB::get_instance(script_id), Variant(), "Resumed after yield, but script is gone."); #endif diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index 9305226dc6..d3569bb040 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -245,6 +245,8 @@ private: Map<StringName, Function> functions; Map<StringName, Variable> variables; Map<StringName, Vector<Argument> > custom_signals; + Vector<ScriptNetData> rpc_functions; + Vector<ScriptNetData> rpc_variables; Map<Object *, VisualScriptInstance *> instances; @@ -362,6 +364,18 @@ public: virtual int get_member_line(const StringName &p_member) 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; + #ifdef TOOLS_ENABLED virtual bool are_subnodes_edited() const; #endif @@ -441,7 +455,16 @@ public: virtual ScriptLanguage *get_language(); + 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; VisualScriptInstance(); diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp index e629175094..e8c02a41c4 100644 --- a/modules/visual_script/visual_script_property_selector.cpp +++ b/modules/visual_script/visual_script_property_selector.cpp @@ -529,7 +529,6 @@ void VisualScriptPropertySelector::select_method_from_base_type(const String &p_ base_type = p_base; selected = p_current; type = Variant::NIL; - script = 0; properties = false; instance = NULL; virtuals_only = p_virtuals_only; @@ -554,7 +553,6 @@ void VisualScriptPropertySelector::select_from_base_type(const String &p_base, c base_type = p_base; selected = p_current; type = Variant::NIL; - script = 0; properties = true; visual_script_generic = false; instance = NULL; @@ -601,7 +599,6 @@ void VisualScriptPropertySelector::select_from_basic_type(Variant::Type p_type, base_type = ""; selected = p_current; type = p_type; - script = 0; properties = true; visual_script_generic = false; instance = NULL; @@ -623,7 +620,6 @@ void VisualScriptPropertySelector::select_from_action(const String &p_type, cons base_type = p_type; selected = p_current; type = Variant::NIL; - script = 0; properties = false; visual_script_generic = false; instance = NULL; @@ -645,7 +641,6 @@ void VisualScriptPropertySelector::select_from_instance(Object *p_instance, cons base_type = p_basetype; selected = p_current; type = Variant::NIL; - script = 0; properties = true; visual_script_generic = false; instance = p_instance; @@ -667,7 +662,6 @@ void VisualScriptPropertySelector::select_from_visual_script(const String &p_bas base_type = p_base; selected = ""; type = Variant::NIL; - script = 0; properties = true; visual_script_generic = true; instance = NULL; diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 338194fcae..1fd91ec3c1 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -240,6 +240,11 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a //!!!!!!!!!!!!!!!!!!!!!!!!!! //TODO - do Vulkan and GLES2 support checks, driver selection and fallback video_driver_index = p_video_driver; +#ifndef _MSC_VER +#warning Forcing vulkan video driver because OpenGL not implemented yet +#endif + video_driver_index = VIDEO_DRIVER_VULKAN; + print_verbose("Driver: " + String(get_video_driver_name(video_driver_index)) + " [" + itos(video_driver_index) + "]"); //!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 8302ba5336..b661db2e52 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -148,7 +148,7 @@ void Area2D::_body_exit_tree(ObjectID p_id) { } } -void Area2D::_body_inout(int p_status, const RID &p_body, int p_instance, int p_body_shape, int p_area_shape) { +void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_area_shape) { bool body_in = p_status == Physics2DServer::AREA_BODY_ADDED; ObjectID objid = p_instance; @@ -251,7 +251,7 @@ void Area2D::_area_exit_tree(ObjectID p_id) { } } -void Area2D::_area_inout(int p_status, const RID &p_area, int p_instance, int p_area_shape, int p_self_shape) { +void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, int p_area_shape, int p_self_shape) { bool area_in = p_status == Physics2DServer::AREA_BODY_ADDED; ObjectID objid = p_instance; diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h index 6d9386c535..c5e6635412 100644 --- a/scene/2d/area_2d.h +++ b/scene/2d/area_2d.h @@ -62,7 +62,7 @@ private: bool monitorable; bool locked; - void _body_inout(int p_status, const RID &p_body, int p_instance, int p_body_shape, int p_area_shape); + void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_area_shape); void _body_enter_tree(ObjectID p_id); void _body_exit_tree(ObjectID p_id); @@ -94,7 +94,7 @@ private: Map<ObjectID, BodyState> body_map; - void _area_inout(int p_status, const RID &p_area, int p_instance, int p_area_shape, int p_self_shape); + void _area_inout(int p_status, const RID &p_area, ObjectID p_instance, int p_area_shape, int p_self_shape); void _area_enter_tree(ObjectID p_id); void _area_exit_tree(ObjectID p_id); diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index e9f8c5dff2..7ec770597e 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -608,7 +608,7 @@ void Camera2D::set_custom_viewport(Node *p_viewport) { if (custom_viewport) { custom_viewport_id = custom_viewport->get_instance_id(); } else { - custom_viewport_id = 0; + custom_viewport_id = ObjectID(); } if (is_inside_tree()) { @@ -795,7 +795,7 @@ Camera2D::Camera2D() { smoothing_enabled = false; limit_smoothing_enabled = false; custom_viewport = NULL; - custom_viewport_id = 0; + process_mode = CAMERA2D_PROCESS_IDLE; smoothing = 5.0; diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index eff58a4fb3..aca0c4c959 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -997,7 +997,7 @@ ObjectID CanvasItem::get_canvas_layer_instance_id() const { if (canvas_layer) { return canvas_layer->get_instance_id(); } else { - return 0; + return ObjectID(); } } diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index 3e9e63a7f0..4af2e846f7 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -95,9 +95,9 @@ void CollisionObject2D::_notification(int p_what) { case NOTIFICATION_EXIT_CANVAS: { if (area) - Physics2DServer::get_singleton()->area_attach_canvas_instance_id(rid, 0); + Physics2DServer::get_singleton()->area_attach_canvas_instance_id(rid, ObjectID()); else - Physics2DServer::get_singleton()->body_attach_canvas_instance_id(rid, 0); + Physics2DServer::get_singleton()->body_attach_canvas_instance_id(rid, ObjectID()); } break; } } diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index d42bd6adaf..d1fe5caf7e 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -1544,7 +1544,7 @@ Object *KinematicCollision2D::get_local_shape() const { Object *KinematicCollision2D::get_collider() const { - if (collision.collider) { + if (collision.collider.is_valid()) { return ObjectDB::get_instance(collision.collider); } @@ -1608,7 +1608,7 @@ void KinematicCollision2D::_bind_methods() { } KinematicCollision2D::KinematicCollision2D() { - collision.collider = 0; + collision.collider_shape = 0; collision.local_shape = 0; owner = NULL; diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index dc953b2d7d..ba5b7d29e7 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -108,7 +108,7 @@ void Polygon2D::_notification(int p_what) { skeleton_node = Object::cast_to<Skeleton2D>(get_node(skeleton)); } - ObjectID new_skeleton_id = 0; + ObjectID new_skeleton_id; if (skeleton_node) { VS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), skeleton_node->get_skeleton()); @@ -734,7 +734,7 @@ Polygon2D::Polygon2D() { color = Color(1, 1, 1); rect_cache_dirty = true; internal_vertices = 0; - current_skeleton_id = 0; + specular_color = Color(1, 1, 1, 1); shininess = 1.0; } diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index 3252e02e38..fd6e0aebcc 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -78,7 +78,7 @@ bool RayCast2D::is_colliding() const { } Object *RayCast2D::get_collider() const { - if (against == 0) + if (against.is_null()) return NULL; return ObjectDB::get_instance(against); @@ -225,7 +225,7 @@ void RayCast2D::_update_raycast_state() { against_shape = rr.shape; } else { collided = false; - against = 0; + against = ObjectID(); against_shape = 0; } } @@ -339,7 +339,7 @@ void RayCast2D::_bind_methods() { RayCast2D::RayCast2D() { enabled = false; - against = 0; + collided = false; against_shape = 0; collision_mask = 1; diff --git a/scene/2d/remote_transform_2d.cpp b/scene/2d/remote_transform_2d.cpp index 53072f942d..ec50f5f922 100644 --- a/scene/2d/remote_transform_2d.cpp +++ b/scene/2d/remote_transform_2d.cpp @@ -33,7 +33,7 @@ void RemoteTransform2D::_update_cache() { - cache = 0; + cache = ObjectID(); if (has_node(remote_node)) { Node *node = get_node(remote_node); if (!node || this == node || node->is_a_parent_of(this) || this->is_a_parent_of(node)) { @@ -49,7 +49,7 @@ void RemoteTransform2D::_update_remote() { if (!is_inside_tree()) return; - if (!cache) + if (cache.is_null()) return; Node2D *n = Object::cast_to<Node2D>(ObjectDB::get_instance(cache)); @@ -119,7 +119,7 @@ void RemoteTransform2D::_notification(int p_what) { if (!is_inside_tree()) break; - if (cache) { + if (cache.is_valid()) { _update_remote(); } @@ -225,6 +225,5 @@ RemoteTransform2D::RemoteTransform2D() { update_remote_rotation = true; update_remote_scale = true; - cache = 0; set_notify_transform(true); } diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index 67f57a1aa3..62908e2b0f 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -147,7 +147,7 @@ void Area::_body_exit_tree(ObjectID p_id) { } } -void Area::_body_inout(int p_status, const RID &p_body, int p_instance, int p_body_shape, int p_area_shape) { +void Area::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_area_shape) { bool body_in = p_status == PhysicsServer::AREA_BODY_ADDED; ObjectID objid = p_instance; @@ -340,7 +340,7 @@ void Area::_area_exit_tree(ObjectID p_id) { } } -void Area::_area_inout(int p_status, const RID &p_area, int p_instance, int p_area_shape, int p_self_shape) { +void Area::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, int p_area_shape, int p_self_shape) { bool area_in = p_status == PhysicsServer::AREA_BODY_ADDED; ObjectID objid = p_instance; diff --git a/scene/3d/area.h b/scene/3d/area.h index ca66f41f60..7fe61430fa 100644 --- a/scene/3d/area.h +++ b/scene/3d/area.h @@ -62,7 +62,7 @@ private: bool monitorable; bool locked; - void _body_inout(int p_status, const RID &p_body, int p_instance, int p_body_shape, int p_area_shape); + void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_area_shape); void _body_enter_tree(ObjectID p_id); void _body_exit_tree(ObjectID p_id); @@ -94,7 +94,7 @@ private: Map<ObjectID, BodyState> body_map; - void _area_inout(int p_status, const RID &p_area, int p_instance, int p_area_shape, int p_self_shape); + void _area_inout(int p_status, const RID &p_area, ObjectID p_instance, int p_area_shape, int p_self_shape); void _area_enter_tree(ObjectID p_id); void _area_exit_tree(ObjectID p_id); diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index fbfd372272..5d5cb4dfce 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -1493,7 +1493,7 @@ Object *KinematicCollision::get_local_shape() const { Object *KinematicCollision::get_collider() const { - if (collision.collider) { + if (collision.collider.is_valid()) { return ObjectDB::get_instance(collision.collider); } @@ -1557,7 +1557,7 @@ void KinematicCollision::_bind_methods() { } KinematicCollision::KinematicCollision() { - collision.collider = 0; + collision.collider_shape = 0; collision.local_shape = 0; owner = NULL; diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp index 0c976b9fb1..be1426f13c 100644 --- a/scene/3d/ray_cast.cpp +++ b/scene/3d/ray_cast.cpp @@ -80,7 +80,7 @@ bool RayCast::is_colliding() const { } Object *RayCast::get_collider() const { - if (against == 0) + if (against.is_null()) return NULL; return ObjectDB::get_instance(against); @@ -219,7 +219,7 @@ void RayCast::_update_raycast_state() { against_shape = rr.shape; } else { collided = false; - against = 0; + against = ObjectID(); against_shape = 0; } } @@ -393,7 +393,7 @@ void RayCast::_clear_debug_shape() { RayCast::RayCast() { enabled = false; - against = 0; + collided = false; against_shape = 0; collision_mask = 1; diff --git a/scene/3d/remote_transform.cpp b/scene/3d/remote_transform.cpp index 983af7a9ec..9ef43647ba 100644 --- a/scene/3d/remote_transform.cpp +++ b/scene/3d/remote_transform.cpp @@ -31,7 +31,7 @@ #include "remote_transform.h" void RemoteTransform::_update_cache() { - cache = 0; + cache = ObjectID(); if (has_node(remote_node)) { Node *node = get_node(remote_node); if (!node || this == node || node->is_a_parent_of(this) || this->is_a_parent_of(node)) { @@ -47,7 +47,7 @@ void RemoteTransform::_update_remote() { if (!is_inside_tree()) return; - if (!cache) + if (cache.is_null()) return; Spatial *n = Object::cast_to<Spatial>(ObjectDB::get_instance(cache)); @@ -114,7 +114,7 @@ void RemoteTransform::_notification(int p_what) { if (!is_inside_tree()) break; - if (cache) { + if (cache.is_valid()) { _update_remote(); } @@ -219,6 +219,5 @@ RemoteTransform::RemoteTransform() { update_remote_rotation = true; update_remote_scale = true; - cache = 0; set_notify_transform(true); } diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 3e4cd54664..aa5c439f8a 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -138,7 +138,7 @@ bool Skeleton::_get(const StringName &p_path, Variant &r_ret) const { else if (what == "bound_children") { Array children; - for (const List<uint32_t>::Element *E = bones[which].nodes_bound.front(); E; E = E->next()) { + for (const List<ObjectID>::Element *E = bones[which].nodes_bound.front(); E; E = E->next()) { Object *obj = ObjectDB::get_instance(E->get()); ERR_CONTINUE(!obj); @@ -302,7 +302,7 @@ void Skeleton::_notification(int p_what) { b.global_pose_override_amount = 0.0; } - for (List<uint32_t>::Element *E = b.nodes_bound.front(); E; E = E->next()) { + for (List<ObjectID>::Element *E = b.nodes_bound.front(); E; E = E->next()) { Object *obj = ObjectDB::get_instance(E->get()); ERR_CONTINUE(!obj); @@ -505,9 +505,9 @@ void Skeleton::bind_child_node_to_bone(int p_bone, Node *p_node) { ERR_FAIL_NULL(p_node); ERR_FAIL_INDEX(p_bone, bones.size()); - uint32_t id = p_node->get_instance_id(); + ObjectID id = p_node->get_instance_id(); - for (const List<uint32_t>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { + for (const List<ObjectID>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { if (E->get() == id) return; // already here @@ -520,14 +520,14 @@ void Skeleton::unbind_child_node_from_bone(int p_bone, Node *p_node) { ERR_FAIL_NULL(p_node); ERR_FAIL_INDEX(p_bone, bones.size()); - uint32_t id = p_node->get_instance_id(); + ObjectID id = p_node->get_instance_id(); bones.write[p_bone].nodes_bound.erase(id); } void Skeleton::get_bound_child_nodes_to_bone(int p_bone, List<Node *> *p_bound) const { ERR_FAIL_INDEX(p_bone, bones.size()); - for (const List<uint32_t>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { + for (const List<ObjectID>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { Object *obj = ObjectDB::get_instance(E->get()); ERR_CONTINUE(!obj); diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h index 9599510850..b42c2112e3 100644 --- a/scene/3d/skeleton.h +++ b/scene/3d/skeleton.h @@ -99,7 +99,7 @@ private: PhysicalBone *cache_parent_physical_bone; #endif // _3D_DISABLED - List<uint32_t> nodes_bound; + List<ObjectID> nodes_bound; Bone() { parent = -1; diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 7ec7037dd7..740dad9a1a 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -249,7 +249,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) { Vector<StringName> leftover_path; Node *child = parent->get_node_and_resource(a->track_get_path(i), resource, leftover_path); ERR_CONTINUE_MSG(!child, "On Animation: '" + p_anim->name + "', couldn't resolve track: '" + String(a->track_get_path(i)) + "'."); // couldn't find the child node - uint32_t id = resource.is_valid() ? resource->get_instance_id() : child->get_instance_id(); + ObjectID id = resource.is_valid() ? resource->get_instance_id() : child->get_instance_id(); int bone_idx = -1; if (a->track_get_path(i).get_subname_count() == 1 && Object::cast_to<Skeleton>(child)) { diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 06f762e63e..48829b02b9 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -159,17 +159,15 @@ private: struct TrackNodeCacheKey { - uint32_t id; + ObjectID id; int bone_idx; inline bool operator<(const TrackNodeCacheKey &p_right) const { - if (id < p_right.id) - return true; - else if (id > p_right.id) - return false; - else + if (id == p_right.id) return bone_idx < p_right.bone_idx; + else + return id < p_right.id; } }; diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index c28f8dc824..a08cc0927b 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -767,7 +767,7 @@ void AnimationTree::_process_graph(float p_delta) { AnimationPlayer *player = Object::cast_to<AnimationPlayer>(get_node(animation_player)); - ObjectID current_animation_player = 0; + ObjectID current_animation_player; if (player) { current_animation_player = player->get_instance_id(); @@ -775,7 +775,7 @@ void AnimationTree::_process_graph(float p_delta) { if (last_animation_player != current_animation_player) { - if (last_animation_player) { + if (last_animation_player.is_valid()) { Object *old_player = ObjectDB::get_instance(last_animation_player); if (old_player) { old_player->disconnect("caches_cleared", this, "_clear_caches"); @@ -1296,7 +1296,7 @@ void AnimationTree::_notification(int p_what) { if (p_what == NOTIFICATION_EXIT_TREE) { _clear_caches(); - if (last_animation_player) { + if (last_animation_player.is_valid()) { Object *player = ObjectDB::get_instance(last_animation_player); if (player) { @@ -1304,7 +1304,7 @@ void AnimationTree::_notification(int p_what) { } } } else if (p_what == NOTIFICATION_ENTER_TREE) { - if (last_animation_player) { + if (last_animation_player.is_valid()) { Object *player = ObjectDB::get_instance(last_animation_player); if (player) { @@ -1584,7 +1584,6 @@ AnimationTree::AnimationTree() { process_pass = 1; started = true; properties_dirty = true; - last_animation_player = 0; } AnimationTree::~AnimationTree() { diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index 0a8dc8109f..8769e2c61d 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -187,7 +187,6 @@ private: setup_pass = 0; process_pass = 0; object = NULL; - object_id = 0; } virtual ~TrackCache() {} }; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index be211504a6..b7bc2f9c9e 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -705,12 +705,12 @@ void Control::set_drag_forwarding(Control *p_target) { if (p_target) data.drag_owner = p_target->get_instance_id(); else - data.drag_owner = 0; + data.drag_owner = ObjectID(); } Variant Control::get_drag_data(const Point2 &p_point) { - if (data.drag_owner) { + if (data.drag_owner.is_valid()) { Object *obj = ObjectDB::get_instance(data.drag_owner); if (obj) { Control *c = Object::cast_to<Control>(obj); @@ -732,7 +732,7 @@ Variant Control::get_drag_data(const Point2 &p_point) { bool Control::can_drop_data(const Point2 &p_point, const Variant &p_data) const { - if (data.drag_owner) { + if (data.drag_owner.is_valid()) { Object *obj = ObjectDB::get_instance(data.drag_owner); if (obj) { Control *c = Object::cast_to<Control>(obj); @@ -753,7 +753,7 @@ bool Control::can_drop_data(const Point2 &p_point, const Variant &p_data) const } void Control::drop_data(const Point2 &p_point, const Variant &p_data) { - if (data.drag_owner) { + if (data.drag_owner.is_valid()) { Object *obj = ObjectDB::get_instance(data.drag_owner); if (obj) { Control *c = Object::cast_to<Control>(obj); @@ -2224,7 +2224,7 @@ void Control::_modal_stack_remove() { get_viewport()->_gui_remove_from_modal_stack(element, data.modal_prev_focus_owner); - data.modal_prev_focus_owner = 0; + data.modal_prev_focus_owner = ObjectID(); } void Control::_propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool p_assign) { @@ -3110,7 +3110,7 @@ Control::Control() { data.rotation = 0; data.parent_canvas_item = NULL; data.scale = Vector2(1, 1); - data.drag_owner = 0; + data.modal_frame = 0; data.block_minimum_size_adjust = false; data.disable_visibility_clip = false; @@ -3125,7 +3125,6 @@ Control::Control() { data.margin[i] = 0; } data.focus_mode = FOCUS_NONE; - data.modal_prev_focus_owner = 0; } Control::~Control() { diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 7bfe060065..08835be9fd 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1399,7 +1399,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 } break; case TreeItem::CELL_MODE_CUSTOM: { - if (p_item->cells[i].custom_draw_obj) { + if (p_item->cells[i].custom_draw_obj.is_valid()) { Object *cdo = ObjectDB::get_instance(p_item->cells[i].custom_draw_obj); if (cdo) diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 2072d0fd13..b58f937c57 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -112,7 +112,7 @@ private: Cell() { - custom_draw_obj = 0; + custom_draw_obj = ObjectID(); custom_button = false; mode = TreeItem::CELL_MODE_STRING; min = 0; diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp index 4ae018a79a..04cf5c6338 100644 --- a/scene/main/canvas_layer.cpp +++ b/scene/main/canvas_layer.cpp @@ -200,7 +200,7 @@ void CanvasLayer::set_custom_viewport(Node *p_viewport) { if (custom_viewport) { custom_viewport_id = custom_viewport->get_instance_id(); } else { - custom_viewport_id = 0; + custom_viewport_id = ObjectID(); } if (is_inside_tree()) { @@ -327,7 +327,7 @@ CanvasLayer::CanvasLayer() { layer = 1; canvas = VS::get_singleton()->canvas_create(); custom_viewport = NULL; - custom_viewport_id = 0; + sort_index = 0; follow_viewport = false; follow_viewport_scale = 1.0; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 761fe3f90f..6a7971ddb3 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -30,6 +30,8 @@ #include "node.h" +#include <stdint.h> + #include "core/core_string_names.h" #include "core/io/resource_loader.h" #include "core/message_queue.h" @@ -498,22 +500,38 @@ bool Node::is_network_master() const { /***** RPC CONFIG ********/ -void Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_mode) { +uint16_t Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_mode) { - if (p_mode == MultiplayerAPI::RPC_MODE_DISABLED) { - data.rpc_methods.erase(p_method); + uint16_t mid = get_node_rpc_method_id(p_method); + if (mid == UINT16_MAX) { + // It's new + NetData nd; + nd.name = p_method; + nd.mode = p_mode; + data.rpc_methods.push_back(nd); + return ((uint16_t)data.rpc_properties.size() - 1) | (1 << 15); } else { - data.rpc_methods[p_method] = p_mode; - }; + int c_mid = (~(1 << 15)) & mid; + data.rpc_methods.write[c_mid].mode = p_mode; + return mid; + } } -void Node::rset_config(const StringName &p_property, MultiplayerAPI::RPCMode p_mode) { +uint16_t Node::rset_config(const StringName &p_property, MultiplayerAPI::RPCMode p_mode) { - if (p_mode == MultiplayerAPI::RPC_MODE_DISABLED) { - data.rpc_properties.erase(p_property); + uint16_t pid = get_node_rset_property_id(p_property); + if (pid == UINT16_MAX) { + // It's new + NetData nd; + nd.name = p_property; + nd.mode = p_mode; + data.rpc_properties.push_back(nd); + return ((uint16_t)data.rpc_properties.size() - 1) | (1 << 15); } else { - data.rpc_properties[p_property] = p_mode; - }; + int c_pid = (~(1 << 15)) & pid; + data.rpc_properties.write[c_pid].mode = p_mode; + return pid; + } } /***** RPC FUNCTIONS ********/ @@ -731,12 +749,94 @@ void Node::set_custom_multiplayer(Ref<MultiplayerAPI> p_multiplayer) { multiplayer = p_multiplayer; } -const Map<StringName, MultiplayerAPI::RPCMode>::Element *Node::get_node_rpc_mode(const StringName &p_method) { - return data.rpc_methods.find(p_method); +uint16_t Node::get_node_rpc_method_id(const StringName &p_method) const { + for (int i = 0; i < data.rpc_methods.size(); i++) { + if (data.rpc_methods[i].name == p_method) { + // Returns `i` with the high bit set to 1 so we know that this id comes + // from the node and not the script. + return i | (1 << 15); + } + } + return UINT16_MAX; +} + +StringName Node::get_node_rpc_method(const uint16_t p_rpc_method_id) const { + // Make sure this is a node generated ID. + if (((1 << 15) & p_rpc_method_id) > 0) { + int mid = (~(1 << 15)) & p_rpc_method_id; + if (mid < data.rpc_methods.size()) + return data.rpc_methods[mid].name; + } + return StringName(); +} + +MultiplayerAPI::RPCMode Node::get_node_rpc_mode_by_id(const uint16_t p_rpc_method_id) const { + // Make sure this is a node generated ID. + if (((1 << 15) & p_rpc_method_id) > 0) { + int mid = (~(1 << 15)) & p_rpc_method_id; + if (mid < data.rpc_methods.size()) + return data.rpc_methods[mid].mode; + } + return MultiplayerAPI::RPC_MODE_DISABLED; +} + +MultiplayerAPI::RPCMode Node::get_node_rpc_mode(const StringName &p_method) const { + return get_node_rpc_mode_by_id(get_node_rpc_method_id(p_method)); } -const Map<StringName, MultiplayerAPI::RPCMode>::Element *Node::get_node_rset_mode(const StringName &p_property) { - return data.rpc_properties.find(p_property); +uint16_t Node::get_node_rset_property_id(const StringName &p_property) const { + for (int i = 0; i < data.rpc_properties.size(); i++) { + if (data.rpc_properties[i].name == p_property) { + // Returns `i` with the high bit set to 1 so we know that this id comes + // from the node and not the script. + return i | (1 << 15); + } + } + return UINT16_MAX; +} + +StringName Node::get_node_rset_property(const uint16_t p_rset_property_id) const { + // Make sure this is a node generated ID. + if (((1 << 15) & p_rset_property_id) > 0) { + int mid = (~(1 << 15)) & p_rset_property_id; + if (mid < data.rpc_properties.size()) + return data.rpc_properties[mid].name; + } + return StringName(); +} + +MultiplayerAPI::RPCMode Node::get_node_rset_mode_by_id(const uint16_t p_rset_property_id) const { + if (((1 << 15) & p_rset_property_id) > 0) { + int mid = (~(1 << 15)) & p_rset_property_id; + if (mid < data.rpc_properties.size()) + return data.rpc_properties[mid].mode; + } + return MultiplayerAPI::RPC_MODE_DISABLED; +} + +MultiplayerAPI::RPCMode Node::get_node_rset_mode(const StringName &p_property) const { + return get_node_rset_mode_by_id(get_node_rset_property_id(p_property)); +} + +String Node::get_rpc_md5() const { + String rpc_list; + for (int i = 0; i < data.rpc_methods.size(); i += 1) { + rpc_list += String(data.rpc_methods[i].name); + } + for (int i = 0; i < data.rpc_properties.size(); i += 1) { + rpc_list += String(data.rpc_properties[i].name); + } + if (get_script_instance()) { + Vector<ScriptNetData> rpc = get_script_instance()->get_rpc_methods(); + for (int i = 0; i < rpc.size(); i += 1) { + rpc_list += String(rpc[i].name); + } + rpc = get_script_instance()->get_rset_properties(); + for (int i = 0; i < rpc.size(); i += 1) { + rpc_list += String(rpc[i].name); + } + } + return rpc_list.md5_text(); } bool Node::can_process_notification(int p_what) const { diff --git a/scene/main/node.h b/scene/main/node.h index 6f5544d654..02c828e8ff 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -85,6 +85,11 @@ private: GroupData() { persistent = false; } }; + struct NetData { + StringName name; + MultiplayerAPI::RPCMode mode; + }; + struct Data { String filename; @@ -118,8 +123,8 @@ private: Node *pause_owner; int network_master; - Map<StringName, MultiplayerAPI::RPCMode> rpc_methods; - Map<StringName, MultiplayerAPI::RPCMode> rpc_properties; + Vector<NetData> rpc_methods; + Vector<NetData> rpc_properties; // variables used to properly sort the node when processing, ignored otherwise //should move all the stuff below to bits @@ -427,8 +432,8 @@ public: int get_network_master() const; bool is_network_master() const; - void rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_mode); // config a local method for RPC - void rset_config(const StringName &p_property, MultiplayerAPI::RPCMode p_mode); // config a local property for RPC + uint16_t rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_mode); // config a local method for RPC + uint16_t rset_config(const StringName &p_property, MultiplayerAPI::RPCMode p_mode); // config a local property for RPC void rpc(const StringName &p_method, VARIANT_ARG_LIST); //rpc call, honors RPCMode void rpc_unreliable(const StringName &p_method, VARIANT_ARG_LIST); //rpc call, honors RPCMode @@ -446,8 +451,22 @@ public: Ref<MultiplayerAPI> get_multiplayer() const; Ref<MultiplayerAPI> get_custom_multiplayer() const; void set_custom_multiplayer(Ref<MultiplayerAPI> p_multiplayer); - const Map<StringName, MultiplayerAPI::RPCMode>::Element *get_node_rpc_mode(const StringName &p_method); - const Map<StringName, MultiplayerAPI::RPCMode>::Element *get_node_rset_mode(const StringName &p_property); + + /// Returns the rpc method ID, otherwise UINT32_MAX + uint16_t get_node_rpc_method_id(const StringName &p_method) const; + StringName get_node_rpc_method(const uint16_t p_rpc_method_id) const; + MultiplayerAPI::RPCMode get_node_rpc_mode_by_id(const uint16_t p_rpc_method_id) const; + MultiplayerAPI::RPCMode get_node_rpc_mode(const StringName &p_method) const; + + /// Returns the rpc property ID, otherwise UINT32_MAX + uint16_t get_node_rset_property_id(const StringName &p_property) const; + StringName get_node_rset_property(const uint16_t p_rset_property_id) const; + MultiplayerAPI::RPCMode get_node_rset_mode_by_id(const uint16_t p_rpc_method_id) const; + MultiplayerAPI::RPCMode get_node_rset_mode(const StringName &p_property) const; + + /// Can be used to check if the rpc methods and the rset properties are the + /// same across the peers. + String get_rpc_md5() const; Node(); ~Node(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index dad2ec4010..748a713110 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -412,7 +412,7 @@ void Viewport::_notification(int p_what) { #ifndef _3D_DISABLED Vector2 last_pos(1e20, 1e20); CollisionObject *last_object = NULL; - ObjectID last_id = 0; + ObjectID last_id; #endif PhysicsDirectSpaceState::RayResult result; Physics2DDirectSpaceState *ss2d = Physics2DServer::get_singleton()->space_get_direct_state(find_world_2d()->get_space()); @@ -532,7 +532,7 @@ void Viewport::_notification(int p_what) { } else { // This Viewport's builtin canvas canvas_transform = get_canvas_transform(); - canvas_layer_id = 0; + canvas_layer_id = ObjectID(); } Vector2 point = canvas_transform.affine_inverse().xform(pos); @@ -540,7 +540,7 @@ void Viewport::_notification(int p_what) { int rc = ss2d->intersect_point_on_canvas(point, canvas_layer_id, res, 64, Set<RID>(), 0xFFFFFFFF, true, true, true); for (int i = 0; i < rc; i++) { - if (res[i].collider_id && res[i].collider) { + if (res[i].collider_id.is_valid() && res[i].collider) { CollisionObject2D *co = Object::cast_to<CollisionObject2D>(res[i].collider); if (co) { bool send_event = true; @@ -594,18 +594,18 @@ void Viewport::_notification(int p_what) { #ifndef _3D_DISABLED bool captured = false; - if (physics_object_capture != 0) { + if (physics_object_capture.is_valid()) { CollisionObject *co = Object::cast_to<CollisionObject>(ObjectDB::get_instance(physics_object_capture)); if (co && camera) { _collision_object_input_event(co, camera, ev, Vector3(), Vector3(), 0); captured = true; if (mb.is_valid() && mb->get_button_index() == 1 && !mb->is_pressed()) { - physics_object_capture = 0; + physics_object_capture = ObjectID(); } } else { - physics_object_capture = 0; + physics_object_capture = ObjectID(); } } @@ -613,7 +613,7 @@ void Viewport::_notification(int p_what) { //none } else if (pos == last_pos) { - if (last_id) { + if (last_id.is_valid()) { if (ObjectDB::get_instance(last_id) && last_object) { //good, exists _collision_object_input_event(last_object, camera, ev, result.position, result.normal, result.shape); @@ -633,7 +633,7 @@ void Viewport::_notification(int p_what) { if (space) { bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true, true, true); - ObjectID new_collider = 0; + ObjectID new_collider; if (col) { CollisionObject *co = Object::cast_to<CollisionObject>(result.collider); @@ -651,7 +651,7 @@ void Viewport::_notification(int p_what) { if (is_mouse && new_collider != physics_object_over) { - if (physics_object_over) { + if (physics_object_over.is_valid()) { CollisionObject *co = Object::cast_to<CollisionObject>(ObjectDB::get_instance(physics_object_over)); if (co) { @@ -659,7 +659,7 @@ void Viewport::_notification(int p_what) { } } - if (new_collider) { + if (new_collider.is_valid()) { CollisionObject *co = Object::cast_to<CollisionObject>(ObjectDB::get_instance(new_collider)); if (co) { @@ -2504,7 +2504,7 @@ void Viewport::_gui_remove_from_modal_stack(List<Control *>::Element *MI, Object gui.modal_stack.erase(MI); - if (p_prev_focus_owner) { + if (p_prev_focus_owner.is_valid()) { // for previous window in stack, pass the focus so it feels more // natural @@ -2701,14 +2701,15 @@ void Viewport::_drop_physics_mouseover() { } #ifndef _3D_DISABLED - if (physics_object_over) { + if (physics_object_over.is_valid()) { CollisionObject *co = Object::cast_to<CollisionObject>(ObjectDB::get_instance(physics_object_over)); if (co) { co->_mouse_exit(); } } - physics_object_over = physics_object_capture = 0; + physics_object_over = ObjectID(); + physics_object_capture = ObjectID(); #endif } @@ -2718,7 +2719,7 @@ List<Control *>::Element *Viewport::_gui_show_modal(Control *p_control) { if (gui.key_focus) p_control->_modal_set_prev_focus_owner(gui.key_focus->get_instance_id()); else - p_control->_modal_set_prev_focus_owner(0); + p_control->_modal_set_prev_focus_owner(ObjectID()); if (gui.mouse_focus && !p_control->is_a_parent_of(gui.mouse_focus) && !gui.mouse_click_grabber) { @@ -3334,8 +3335,6 @@ Viewport::Viewport() { update_mode = UPDATE_WHEN_VISIBLE; physics_object_picking = false; - physics_object_capture = 0; - physics_object_over = 0; physics_has_last_mousepos = false; physics_last_mousepos = Vector2(Math_INF, Math_INF); @@ -3385,7 +3384,6 @@ Viewport::Viewport() { physics_last_mouse_state.mouse_mask = 0; local_input_handled = false; handle_input_locally = true; - physics_last_id = 0; //ensures first time there will be a check default_canvas_item_texture_filter = DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR; default_canvas_item_texture_repeat = DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; diff --git a/servers/physics/area_sw.cpp b/servers/physics/area_sw.cpp index 398849edb8..1016afcaba 100644 --- a/servers/physics/area_sw.cpp +++ b/servers/physics/area_sw.cpp @@ -175,7 +175,7 @@ void AreaSW::set_monitorable(bool p_monitorable) { void AreaSW::call_queries() { - if (monitor_callback_id && !monitored_bodies.empty()) { + if (monitor_callback_id.is_valid() && !monitored_bodies.empty()) { Variant res[5]; Variant *resptr[5]; @@ -185,7 +185,7 @@ void AreaSW::call_queries() { Object *obj = ObjectDB::get_instance(monitor_callback_id); if (!obj) { monitored_bodies.clear(); - monitor_callback_id = 0; + monitor_callback_id = ObjectID(); return; } @@ -207,7 +207,7 @@ void AreaSW::call_queries() { monitored_bodies.clear(); - if (area_monitor_callback_id && !monitored_areas.empty()) { + if (area_monitor_callback_id.is_valid() && !monitored_areas.empty()) { Variant res[5]; Variant *resptr[5]; @@ -217,7 +217,7 @@ void AreaSW::call_queries() { Object *obj = ObjectDB::get_instance(area_monitor_callback_id); if (!obj) { monitored_areas.clear(); - area_monitor_callback_id = 0; + area_monitor_callback_id = ObjectID(); return; } @@ -257,8 +257,6 @@ AreaSW::AreaSW() : linear_damp = 0.1; priority = 0; set_ray_pickable(false); - monitor_callback_id = 0; - area_monitor_callback_id = 0; monitorable = false; } diff --git a/servers/physics/area_sw.h b/servers/physics/area_sw.h index 846243a133..4da2b00d20 100644 --- a/servers/physics/area_sw.h +++ b/servers/physics/area_sw.h @@ -111,10 +111,10 @@ public: //_FORCE_INLINE_ SpaceSW* get_owner() { return owner; } void set_monitor_callback(ObjectID p_id, const StringName &p_method); - _FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id; } + _FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id.is_valid(); } void set_area_monitor_callback(ObjectID p_id, const StringName &p_method); - _FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id; } + _FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id.is_valid(); } _FORCE_INLINE_ void add_body_to_query(BodySW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); _FORCE_INLINE_ void remove_body_from_query(BodySW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp index 64e07e1155..b71c9772df 100644 --- a/servers/physics/body_sw.cpp +++ b/servers/physics/body_sw.cpp @@ -709,7 +709,7 @@ void BodySW::call_queries() { Object *obj = ObjectDB::get_instance(fi_callback->id); if (!obj) { - set_force_integration_callback(0, StringName()); + set_force_integration_callback(ObjectID(), StringName()); } else { const Variant *vp[2] = { &v, &fi_callback->udata }; @@ -749,7 +749,7 @@ void BodySW::set_force_integration_callback(ObjectID p_id, const StringName &p_m fi_callback = NULL; } - if (p_id != 0) { + if (p_id.is_valid()) { fi_callback = memnew(ForceIntegrationCallback); fi_callback->id = p_id; diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h index ee4dd0b310..d712b09878 100644 --- a/servers/physics/body_sw.h +++ b/servers/physics/body_sw.h @@ -451,7 +451,7 @@ public: return body->contacts[p_contact_idx].collider_pos; } virtual ObjectID get_contact_collider_id(int p_contact_idx) const { - ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, 0); + ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, ObjectID()); return body->contacts[p_contact_idx].collider_instance_id; } virtual int get_contact_collider_shape(int p_contact_idx) const { diff --git a/servers/physics/collision_object_sw.cpp b/servers/physics/collision_object_sw.cpp index cdae26078c..3cabf75ab6 100644 --- a/servers/physics/collision_object_sw.cpp +++ b/servers/physics/collision_object_sw.cpp @@ -232,7 +232,7 @@ CollisionObjectSW::CollisionObjectSW(Type p_type) : _static = true; type = p_type; space = NULL; - instance_id = 0; + collision_layer = 1; collision_mask = 1; ray_pickable = true; diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp index cd6fc6c0a5..6024e9ab7f 100644 --- a/servers/physics/physics_server_sw.cpp +++ b/servers/physics/physics_server_sw.cpp @@ -374,7 +374,7 @@ ObjectID PhysicsServerSW::area_get_object_instance_id(RID p_area) const { p_area = space->get_default_area()->get_self(); } AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, 0); + ERR_FAIL_COND_V(!area, ObjectID()); return area->get_instance_id(); } @@ -446,7 +446,7 @@ void PhysicsServerSW::area_set_monitor_callback(RID p_area, Object *p_receiver, AreaSW *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); - area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : 0, p_method); + area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); } void PhysicsServerSW::area_set_ray_pickable(RID p_area, bool p_enable) { @@ -470,7 +470,7 @@ void PhysicsServerSW::area_set_area_monitor_callback(RID p_area, Object *p_recei AreaSW *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); - area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : 0, p_method); + area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); } /* BODY API */ @@ -665,7 +665,7 @@ uint32_t PhysicsServerSW::body_get_collision_mask(RID p_body) const { return body->get_collision_mask(); } -void PhysicsServerSW::body_attach_object_instance_id(RID p_body, uint32_t p_id) { +void PhysicsServerSW::body_attach_object_instance_id(RID p_body, ObjectID p_id) { BodySW *body = body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -673,10 +673,10 @@ void PhysicsServerSW::body_attach_object_instance_id(RID p_body, uint32_t p_id) body->set_instance_id(p_id); }; -uint32_t PhysicsServerSW::body_get_object_instance_id(RID p_body) const { +ObjectID PhysicsServerSW::body_get_object_instance_id(RID p_body) const { BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0); + ERR_FAIL_COND_V(!body, ObjectID()); return body->get_instance_id(); }; @@ -934,7 +934,7 @@ void PhysicsServerSW::body_set_force_integration_callback(RID p_body, Object *p_ BodySW *body = body_owner.getornull(p_body); ERR_FAIL_COND(!body); - body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(0), p_method, p_udata); + body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method, p_udata); } void PhysicsServerSW::body_set_ray_pickable(RID p_body, bool p_enable) { diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h index 37ebfb09c0..459c7688f0 100644 --- a/servers/physics/physics_server_sw.h +++ b/servers/physics/physics_server_sw.h @@ -177,8 +177,8 @@ public: virtual void body_remove_shape(RID p_body, int p_shape_idx); virtual void body_clear_shapes(RID p_body); - virtual void body_attach_object_instance_id(RID p_body, uint32_t p_id); - virtual uint32_t body_get_object_instance_id(RID p_body) const; + virtual void body_attach_object_instance_id(RID p_body, ObjectID p_id); + virtual ObjectID body_get_object_instance_id(RID p_body) const; virtual void body_set_enable_continuous_collision_detection(RID p_body, bool p_enable); virtual bool body_is_continuous_collision_detection_enabled(RID p_body) const; diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp index 49e1a57879..03dca8b9ec 100644 --- a/servers/physics/space_sw.cpp +++ b/servers/physics/space_sw.cpp @@ -80,7 +80,7 @@ int PhysicsDirectSpaceStateSW::intersect_point(const Vector3 &p_point, ShapeResu continue; r_results[cc].collider_id = col_obj->get_instance_id(); - if (r_results[cc].collider_id != 0) + if (r_results[cc].collider_id.is_valid()) r_results[cc].collider = ObjectDB::get_instance(r_results[cc].collider_id); else r_results[cc].collider = NULL; @@ -159,7 +159,7 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3 &p_from, const Vecto return false; r_result.collider_id = res_obj->get_instance_id(); - if (r_result.collider_id != 0) + if (r_result.collider_id.is_valid()) r_result.collider = ObjectDB::get_instance(r_result.collider_id); else r_result.collider = NULL; @@ -208,7 +208,7 @@ int PhysicsDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transfo if (r_results) { r_results[cc].collider_id = col_obj->get_instance_id(); - if (r_results[cc].collider_id != 0) + if (r_results[cc].collider_id.is_valid()) r_results[cc].collider = ObjectDB::get_instance(r_results[cc].collider_id); else r_results[cc].collider = NULL; @@ -705,7 +705,7 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve //but is it right? who knows at this point.. if (r_result) { - r_result->collider_id = 0; + r_result->collider_id = ObjectID(); r_result->collider_shape = 0; } AABB body_aabb; diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp index 6f09041af8..c67d870b2a 100644 --- a/servers/physics_2d/area_2d_sw.cpp +++ b/servers/physics_2d/area_2d_sw.cpp @@ -175,7 +175,7 @@ void Area2DSW::set_monitorable(bool p_monitorable) { void Area2DSW::call_queries() { - if (monitor_callback_id && !monitored_bodies.empty()) { + if (monitor_callback_id.is_valid() && !monitored_bodies.empty()) { Variant res[5]; Variant *resptr[5]; @@ -185,7 +185,7 @@ void Area2DSW::call_queries() { Object *obj = ObjectDB::get_instance(monitor_callback_id); if (!obj) { monitored_bodies.clear(); - monitor_callback_id = 0; + monitor_callback_id = ObjectID(); return; } @@ -207,7 +207,7 @@ void Area2DSW::call_queries() { monitored_bodies.clear(); - if (area_monitor_callback_id && !monitored_areas.empty()) { + if (area_monitor_callback_id.is_valid() && !monitored_areas.empty()) { Variant res[5]; Variant *resptr[5]; @@ -217,7 +217,7 @@ void Area2DSW::call_queries() { Object *obj = ObjectDB::get_instance(area_monitor_callback_id); if (!obj) { monitored_areas.clear(); - area_monitor_callback_id = 0; + area_monitor_callback_id = ObjectID(); return; } @@ -258,8 +258,6 @@ Area2DSW::Area2DSW() : angular_damp = 1.0; linear_damp = 0.1; priority = 0; - monitor_callback_id = 0; - area_monitor_callback_id = 0; monitorable = false; } diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h index 31bc0f6f23..54ffd9763d 100644 --- a/servers/physics_2d/area_2d_sw.h +++ b/servers/physics_2d/area_2d_sw.h @@ -110,10 +110,10 @@ public: //_FORCE_INLINE_ SpaceSW* get_owner() { return owner; } void set_monitor_callback(ObjectID p_id, const StringName &p_method); - _FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id; } + _FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id.is_valid(); } void set_area_monitor_callback(ObjectID p_id, const StringName &p_method); - _FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id; } + _FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id.is_valid(); } _FORCE_INLINE_ void add_body_to_query(Body2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); _FORCE_INLINE_ void remove_body_from_query(Body2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index b973fa75a9..4de52cacbd 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -610,7 +610,7 @@ void Body2DSW::call_queries() { Object *obj = ObjectDB::get_instance(fi_callback->id); if (!obj) { - set_force_integration_callback(0, StringName()); + set_force_integration_callback(ObjectID(), StringName()); } else { Variant::CallError ce; if (fi_callback->callback_udata.get_type() != Variant::NIL) { @@ -653,7 +653,7 @@ void Body2DSW::set_force_integration_callback(ObjectID p_id, const StringName &p fi_callback = NULL; } - if (p_id != 0) { + if (p_id.is_valid()) { fi_callback = memnew(ForceIntegrationCallback); fi_callback->id = p_id; diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index 06cc447526..ea07b8260c 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -400,7 +400,7 @@ public: return body->contacts[p_contact_idx].collider_pos; } virtual ObjectID get_contact_collider_id(int p_contact_idx) const { - ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, 0); + ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, ObjectID()); return body->contacts[p_contact_idx].collider_instance_id; } virtual int get_contact_collider_shape(int p_contact_idx) const { diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp index 85f7b8467a..8fb3296be6 100644 --- a/servers/physics_2d/collision_object_2d_sw.cpp +++ b/servers/physics_2d/collision_object_2d_sw.cpp @@ -267,8 +267,6 @@ CollisionObject2DSW::CollisionObject2DSW(Type p_type) : _static = true; type = p_type; space = NULL; - instance_id = 0; - canvas_instance_id = 0; collision_mask = 1; collision_layer = 1; pickable = true; diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index 65873d9612..aa374aa6bc 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -470,7 +470,7 @@ ObjectID Physics2DServerSW::area_get_object_instance_id(RID p_area) const { p_area = space->get_default_area()->get_self(); } Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, 0); + ERR_FAIL_COND_V(!area, ObjectID()); return area->get_instance_id(); } @@ -491,7 +491,7 @@ ObjectID Physics2DServerSW::area_get_canvas_instance_id(RID p_area) const { p_area = space->get_default_area()->get_self(); } Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, 0); + ERR_FAIL_COND_V(!area, ObjectID()); return area->get_canvas_instance_id(); } @@ -570,7 +570,7 @@ void Physics2DServerSW::area_set_monitor_callback(RID p_area, Object *p_receiver Area2DSW *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); - area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : 0, p_method); + area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); } void Physics2DServerSW::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { @@ -578,7 +578,7 @@ void Physics2DServerSW::area_set_area_monitor_callback(RID p_area, Object *p_rec Area2DSW *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); - area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : 0, p_method); + area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); } /* BODY API */ @@ -756,7 +756,7 @@ Physics2DServerSW::CCDMode Physics2DServerSW::body_get_continuous_collision_dete return body->get_continuous_collision_detection_mode(); } -void Physics2DServerSW::body_attach_object_instance_id(RID p_body, uint32_t p_id) { +void Physics2DServerSW::body_attach_object_instance_id(RID p_body, ObjectID p_id) { Body2DSW *body = body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -764,15 +764,15 @@ void Physics2DServerSW::body_attach_object_instance_id(RID p_body, uint32_t p_id body->set_instance_id(p_id); }; -uint32_t Physics2DServerSW::body_get_object_instance_id(RID p_body) const { +ObjectID Physics2DServerSW::body_get_object_instance_id(RID p_body) const { Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0); + ERR_FAIL_COND_V(!body, ObjectID()); return body->get_instance_id(); }; -void Physics2DServerSW::body_attach_canvas_instance_id(RID p_body, uint32_t p_id) { +void Physics2DServerSW::body_attach_canvas_instance_id(RID p_body, ObjectID p_id) { Body2DSW *body = body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -780,10 +780,10 @@ void Physics2DServerSW::body_attach_canvas_instance_id(RID p_body, uint32_t p_id body->set_canvas_instance_id(p_id); }; -uint32_t Physics2DServerSW::body_get_canvas_instance_id(RID p_body) const { +ObjectID Physics2DServerSW::body_get_canvas_instance_id(RID p_body) const { Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0); + ERR_FAIL_COND_V(!body, ObjectID()); return body->get_canvas_instance_id(); }; @@ -1025,7 +1025,7 @@ void Physics2DServerSW::body_set_force_integration_callback(RID p_body, Object * Body2DSW *body = body_owner.getornull(p_body); ERR_FAIL_COND(!body); - body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(0), p_method, p_udata); + body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method, p_udata); } bool Physics2DServerSW::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) { diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index 6a636bb72a..a95a2ea0dd 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -195,11 +195,11 @@ public: virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled); virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, float p_margin); - virtual void body_attach_object_instance_id(RID p_body, uint32_t p_id); - virtual uint32_t body_get_object_instance_id(RID p_body) const; + virtual void body_attach_object_instance_id(RID p_body, ObjectID p_id); + virtual ObjectID body_get_object_instance_id(RID p_body) const; - virtual void body_attach_canvas_instance_id(RID p_body, uint32_t p_id); - virtual uint32_t body_get_canvas_instance_id(RID p_body) const; + virtual void body_attach_canvas_instance_id(RID p_body, ObjectID p_id); + virtual ObjectID body_get_canvas_instance_id(RID p_body) const; virtual void body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode); virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const; diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h index 6bd0a09de5..9a01344390 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.h +++ b/servers/physics_2d/physics_2d_server_wrap_mt.h @@ -199,11 +199,11 @@ public: FUNC2(body_remove_shape, RID, int); FUNC1(body_clear_shapes, RID); - FUNC2(body_attach_object_instance_id, RID, uint32_t); - FUNC1RC(uint32_t, body_get_object_instance_id, RID); + FUNC2(body_attach_object_instance_id, RID, ObjectID); + FUNC1RC(ObjectID, body_get_object_instance_id, RID); - FUNC2(body_attach_canvas_instance_id, RID, uint32_t); - FUNC1RC(uint32_t, body_get_canvas_instance_id, RID); + FUNC2(body_attach_canvas_instance_id, RID, ObjectID); + FUNC1RC(ObjectID, body_get_canvas_instance_id, RID); FUNC2(body_set_continuous_collision_detection_mode, RID, CCDMode); FUNC1RC(CCDMode, body_get_continuous_collision_detection_mode, RID); diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 150fda4322..83bcae4607 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -91,7 +91,7 @@ int Physics2DDirectSpaceStateSW::_intersect_point_impl(const Vector2 &p_point, S continue; r_results[cc].collider_id = col_obj->get_instance_id(); - if (r_results[cc].collider_id != 0) + if (r_results[cc].collider_id.is_valid()) r_results[cc].collider = ObjectDB::get_instance(r_results[cc].collider_id); r_results[cc].rid = col_obj->get_self(); r_results[cc].shape = shape_idx; @@ -182,7 +182,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vec return false; r_result.collider_id = res_obj->get_instance_id(); - if (r_result.collider_id != 0) + if (r_result.collider_id.is_valid()) r_result.collider = ObjectDB::get_instance(r_result.collider_id); r_result.normal = res_normal; r_result.metadata = res_obj->get_shape_metadata(res_shape); @@ -226,7 +226,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Trans continue; r_results[cc].collider_id = col_obj->get_instance_id(); - if (r_results[cc].collider_id != 0) + if (r_results[cc].collider_id.is_valid()) r_results[cc].collider = ObjectDB::get_instance(r_results[cc].collider_id); r_results[cc].rid = col_obj->get_self(); r_results[cc].shape = shape_idx; @@ -697,7 +697,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co //but is it right? who knows at this point.. if (r_result) { - r_result->collider_id = 0; + r_result->collider_id = ObjectID(); r_result->collider_shape = 0; } Rect2 body_aabb; diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index ba068e9a37..919c65d849 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -45,7 +45,7 @@ class Physics2DDirectSpaceStateSW : public Physics2DDirectSpaceState { GDCLASS(Physics2DDirectSpaceStateSW, Physics2DDirectSpaceState); - int _intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = 0); + int _intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = ObjectID()); public: Space2DSW *space; diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index 71e3bf8ae8..925af52eeb 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -523,7 +523,7 @@ void Physics2DTestMotionResult::_bind_methods() { Physics2DTestMotionResult::Physics2DTestMotionResult() { colliding = false; - result.collider_id = 0; + result.collider_shape = 0; } diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index 40c58ecac5..c923ef16b7 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -149,7 +149,7 @@ class Physics2DDirectSpaceState : public Object { Dictionary _intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); Array _intersect_point(const Vector2 &p_point, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); Array _intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - Array _intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclud, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = 0); + Array _intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclud, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = ObjectID()); Array _intersect_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query, int p_max_results = 32); Array _cast_motion(const Ref<Physics2DShapeQueryParameters> &p_shape_query); Array _collide_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query, int p_max_results = 32); @@ -404,11 +404,11 @@ public: virtual void body_remove_shape(RID p_body, int p_shape_idx) = 0; virtual void body_clear_shapes(RID p_body) = 0; - virtual void body_attach_object_instance_id(RID p_body, uint32_t p_id) = 0; - virtual uint32_t body_get_object_instance_id(RID p_body) const = 0; + virtual void body_attach_object_instance_id(RID p_body, ObjectID p_id) = 0; + virtual ObjectID body_get_object_instance_id(RID p_body) const = 0; - virtual void body_attach_canvas_instance_id(RID p_body, uint32_t p_id) = 0; - virtual uint32_t body_get_canvas_instance_id(RID p_body) const = 0; + virtual void body_attach_canvas_instance_id(RID p_body, ObjectID p_id) = 0; + virtual ObjectID body_get_canvas_instance_id(RID p_body) const = 0; enum CCDMode { CCD_MODE_DISABLED, @@ -509,7 +509,7 @@ public: MotionResult() { collision_local_shape = 0; collider_shape = 0; - collider_id = 0; + collider_id = ObjectID(); } }; diff --git a/servers/physics_server.h b/servers/physics_server.h index 6a66763b2f..f1388c8758 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -385,8 +385,8 @@ public: virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) = 0; - virtual void body_attach_object_instance_id(RID p_body, uint32_t p_id) = 0; - virtual uint32_t body_get_object_instance_id(RID p_body) const = 0; + virtual void body_attach_object_instance_id(RID p_body, ObjectID p_id) = 0; + virtual ObjectID body_get_object_instance_id(RID p_body) const = 0; virtual void body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) = 0; virtual bool body_is_continuous_collision_detection_enabled(RID p_body) const = 0; @@ -495,7 +495,7 @@ public: Variant collider_metadata; MotionResult() { collision_local_shape = 0; - collider_id = 0; + collider_id = ObjectID(); collider_shape = 0; } }; diff --git a/servers/visual/rasterizer_rd/shader_compiler_rd.cpp b/servers/visual/rasterizer_rd/shader_compiler_rd.cpp index 851deb367f..b2cbac8a09 100644 --- a/servers/visual/rasterizer_rd/shader_compiler_rd.cpp +++ b/servers/visual/rasterizer_rd/shader_compiler_rd.cpp @@ -390,6 +390,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge } struct_code += " "; struct_code += m->name; + if (m->array_size > 0) { + struct_code += "["; + struct_code += itos(m->array_size); + struct_code += "]"; + } struct_code += ";\n"; } struct_code += "}"; @@ -701,6 +706,26 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge } } break; + case SL::Node::TYPE_ARRAY_CONSTRUCT: { + SL::ArrayConstructNode *acnode = (SL::ArrayConstructNode *)p_node; + int sz = acnode->initializer.size(); + if (acnode->datatype == SL::TYPE_STRUCT) { + code += _mkid(acnode->struct_name); + } else { + code += _typestr(acnode->datatype); + } + code += "["; + code += itos(acnode->initializer.size()); + code += "]"; + code += "("; + for (int i = 0; i < sz; i++) { + code += _dump_node_code(acnode->initializer[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + if (i != sz - 1) { + code += ", "; + } + } + code += ")"; + } break; case SL::Node::TYPE_ARRAY_DECLARATION: { SL::ArrayDeclarationNode *adnode = (SL::ArrayDeclarationNode *)p_node; @@ -1000,6 +1025,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge case SL::Node::TYPE_MEMBER: { SL::MemberNode *mnode = (SL::MemberNode *)p_node; code = _dump_node_code(mnode->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + "." + mnode->name; + if (mnode->index_expression != NULL) { + code += "["; + code += _dump_node_code(mnode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += "]"; + } } break; } diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index c2bdc6d7e4..2a0492709c 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -3200,17 +3200,159 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons func->arguments.push_back(funcname); for (int i = 0; i < pstruct->members.size(); i++) { - Node *nexpr = _parse_and_reduce_expression(p_block, p_builtin_types); - if (!nexpr) { - return NULL; - } - Node *node = pstruct->members[i]; + Node *nexpr; - if (!_compare_datatypes_in_nodes(pstruct->members[i], nexpr)) { - String type_name = nexpr->get_datatype() == TYPE_STRUCT ? nexpr->get_datatype_name() : get_datatype_name(nexpr->get_datatype()); - String type_name2 = node->get_datatype() == TYPE_STRUCT ? node->get_datatype_name() : get_datatype_name(node->get_datatype()); - _set_error("Invalid assignment of '" + type_name + "' to '" + type_name2 + "'"); - return NULL; + if (pstruct->members[i]->array_size != 0) { + + DataType type = pstruct->members[i]->get_datatype(); + String struct_name = pstruct->members[i]->struct_name; + int array_size = pstruct->members[i]->array_size; + + DataType type2; + String struct_name2 = ""; + int array_size2 = 0; + + bool auto_size = false; + + tk = _get_token(); + + if (tk.type == TK_CURLY_BRACKET_OPEN) { + auto_size = true; + } else { + + if (shader->structs.has(tk.text)) { + type2 = TYPE_STRUCT; + struct_name2 = tk.text; + } else { + if (!is_token_variable_datatype(tk.type)) { + _set_error("Invalid data type for array"); + return NULL; + } + type2 = get_token_datatype(tk.type); + } + + tk = _get_token(); + if (tk.type == TK_BRACKET_OPEN) { + TkPos pos2 = _get_tkpos(); + tk = _get_token(); + if (tk.type == TK_BRACKET_CLOSE) { + array_size2 = array_size; + tk = _get_token(); + } else { + _set_tkpos(pos2); + + Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) { + _set_error("Expected single integer constant > 0"); + return NULL; + } + + ConstantNode *cnode = (ConstantNode *)n; + if (cnode->values.size() == 1) { + array_size2 = cnode->values[0].sint; + if (array_size2 <= 0) { + _set_error("Expected single integer constant > 0"); + return NULL; + } + } else { + _set_error("Expected single integer constant > 0"); + return NULL; + } + + tk = _get_token(); + if (tk.type != TK_BRACKET_CLOSE) { + _set_error("Expected ']'"); + return NULL; + } else { + tk = _get_token(); + } + } + } else { + _set_error("Expected '['"); + return NULL; + } + + if (type != type2 || struct_name != struct_name2 || array_size != array_size2) { + String error_str = "Cannot convert from '"; + if (type2 == TYPE_STRUCT) { + error_str += struct_name2; + } else { + error_str += get_datatype_name(type2); + } + error_str += "["; + error_str += itos(array_size2); + error_str += "]'"; + error_str += " to '"; + if (type == TYPE_STRUCT) { + error_str += struct_name; + } else { + error_str += get_datatype_name(type); + } + error_str += "["; + error_str += itos(array_size); + error_str += "]'"; + _set_error(error_str); + return NULL; + } + } + + ArrayConstructNode *an = alloc_node<ArrayConstructNode>(); + an->datatype = type; + an->struct_name = struct_name; + + if (tk.type == TK_PARENTHESIS_OPEN || auto_size) { // initialization + while (true) { + + Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!n) { + return NULL; + } + + if (type != n->get_datatype() || struct_name != n->get_datatype_name()) { + _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (type == TYPE_STRUCT ? struct_name : get_datatype_name(type)) + "'"); + return NULL; + } + + tk = _get_token(); + if (tk.type == TK_COMMA) { + an->initializer.push_back(n); + continue; + } else if (!auto_size && tk.type == TK_PARENTHESIS_CLOSE) { + an->initializer.push_back(n); + break; + } else if (auto_size && tk.type == TK_CURLY_BRACKET_CLOSE) { + an->initializer.push_back(n); + break; + } else { + if (auto_size) + _set_error("Expected '}' or ','"); + else + _set_error("Expected ')' or ','"); + return NULL; + } + } + if (an->initializer.size() != array_size) { + _set_error("Array size mismatch"); + return NULL; + } + } else { + _set_error("Expected array initialization!"); + return NULL; + } + + nexpr = an; + } else { + nexpr = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!nexpr) { + return NULL; + } + Node *node = pstruct->members[i]; + if (!_compare_datatypes_in_nodes(pstruct->members[i], nexpr)) { + String type_name = nexpr->get_datatype() == TYPE_STRUCT ? nexpr->get_datatype_name() : get_datatype_name(nexpr->get_datatype()); + String type_name2 = node->get_datatype() == TYPE_STRUCT ? node->get_datatype_name() : get_datatype_name(node->get_datatype()); + _set_error("Invalid assignment of '" + type_name + "' to '" + type_name2 + "'"); + return NULL; + } } if (i + 1 < pstruct->members.size()) { @@ -3463,7 +3605,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expr = varname; } } - } else if (tk.type == TK_OP_ADD) { continue; //this one does nothing } else if (tk.type == TK_OP_SUB || tk.type == TK_OP_NOT || tk.type == TK_OP_BIT_INVERT || tk.type == TK_OP_INCREMENT || tk.type == TK_OP_DECREMENT) { @@ -3482,7 +3623,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expression.push_back(e); continue; - } else { _set_error("Expected expression, found: " + get_token_text(tk)); return NULL; @@ -3526,6 +3666,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons bool ok = true; DataType member_type = TYPE_VOID; StringName member_struct_name = ""; + int array_size = 0; switch (dt) { case TYPE_STRUCT: { ok = false; @@ -3535,6 +3676,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons for (List<MemberNode *>::Element *E = n->members.front(); E; E = E->next()) { if (String(E->get()->name) == member_name) { member_type = E->get()->datatype; + array_size = E->get()->array_size; if (member_type == TYPE_STRUCT) { member_struct_name = E->get()->struct_name; } @@ -3673,8 +3815,52 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons mn->datatype = member_type; mn->base_struct_name = st; mn->struct_name = member_struct_name; + mn->array_size = array_size; mn->name = ident; mn->owner = expr; + if (array_size > 0) { + + tk = _get_token(); + if (tk.type == TK_PERIOD) { + _set_error("Nested array length() is not yet implemented"); + return NULL; + } else if (tk.type == TK_BRACKET_OPEN) { + + Node *index_expression = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!index_expression) + return NULL; + + if (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT) { + _set_error("Only integer expressions are allowed for indexing"); + return NULL; + } + + if (index_expression->type == Node::TYPE_CONSTANT) { + ConstantNode *cnode = (ConstantNode *)index_expression; + if (cnode) { + if (!cnode->values.empty()) { + int value = cnode->values[0].sint; + if (value < 0 || value >= array_size) { + _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1)); + return NULL; + } + } + } + } + + tk = _get_token(); + if (tk.type != TK_BRACKET_CLOSE) { + _set_error("Expected ']'"); + return NULL; + } + mn->index_expression = index_expression; + + } else { + _set_error("Expected '[' or '.'"); + return NULL; + } + } + expr = mn; //todo @@ -3769,7 +3955,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } break; default: { - _set_error("Object of type '" + get_datatype_name(expr->get_datatype()) + "' can't be indexed"); + _set_error("Object of type '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' can't be indexed"); return NULL; } } @@ -5353,11 +5539,33 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct member->datatype = type; member->struct_name = struct_name; member->name = tk.text; - st_node->members.push_back(member); tk = _get_token(); + if (tk.type == TK_BRACKET_OPEN) { + tk = _get_token(); + if (tk.type == TK_INT_CONSTANT && tk.constant > 0) { + member->array_size = (int)tk.constant; + + tk = _get_token(); + if (tk.type == TK_BRACKET_CLOSE) { + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + _set_error("Expected ';'"); + return ERR_PARSE_ERROR; + } + } else { + _set_error("Expected ']'"); + return ERR_PARSE_ERROR; + } + } else { + _set_error("Expected single integer constant > 0"); + return ERR_PARSE_ERROR; + } + } + st_node->members.push_back(member); + if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';'"); + _set_error("Expected ']' or ';'"); return ERR_PARSE_ERROR; } member_count++; diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index 4d474086a6..aac5795e85 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -332,6 +332,7 @@ public: TYPE_MEMBER, TYPE_ARRAY, TYPE_ARRAY_DECLARATION, + TYPE_ARRAY_CONSTRUCT, TYPE_STRUCT, }; @@ -427,6 +428,17 @@ public: is_const(false) {} }; + struct ArrayConstructNode : public Node { + DataType datatype; + String struct_name; + Vector<Node *> initializer; + + ArrayConstructNode() : + Node(TYPE_ARRAY_CONSTRUCT), + datatype(TYPE_VOID) { + } + }; + struct ArrayDeclarationNode : public Node { DataPrecision precision; DataType datatype; @@ -520,9 +532,11 @@ public: StringName base_struct_name; DataPrecision precision; DataType datatype; + int array_size; StringName struct_name; StringName name; Node *owner; + Node *index_expression; virtual DataType get_datatype() const { return datatype; } virtual String get_datatype_name() const { return String(struct_name); } @@ -531,7 +545,9 @@ public: Node(TYPE_MEMBER), basetype(TYPE_VOID), datatype(TYPE_VOID), - owner(NULL) {} + array_size(0), + owner(NULL), + index_expression(NULL) {} }; struct StructNode : public Node { diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index 0df8853f12..61c885cba3 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -805,7 +805,7 @@ Vector<ObjectID> VisualServerScene::instances_cull_aabb(const AABB &p_aabb, RID Instance *instance = cull[i]; ERR_CONTINUE(!instance); - if (instance->object_id == 0) + if (instance->object_id.is_null()) continue; instances.push_back(instance->object_id); @@ -827,7 +827,7 @@ Vector<ObjectID> VisualServerScene::instances_cull_ray(const Vector3 &p_from, co for (int i = 0; i < culled; i++) { Instance *instance = cull[i]; ERR_CONTINUE(!instance); - if (instance->object_id == 0) + if (instance->object_id.is_null()) continue; instances.push_back(instance->object_id); @@ -851,7 +851,7 @@ Vector<ObjectID> VisualServerScene::instances_cull_convex(const Vector<Plane> &p Instance *instance = cull[i]; ERR_CONTINUE(!instance); - if (instance->object_id == 0) + if (instance->object_id.is_null()) continue; instances.push_back(instance->object_id); diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h index a811e8b27a..8dbd60d3ff 100644 --- a/servers/visual/visual_server_scene.h +++ b/servers/visual/visual_server_scene.h @@ -162,7 +162,7 @@ public: AABB *custom_aabb; // <Zylann> would using aabb directly with a bool be better? float extra_margin; - uint32_t object_id; + ObjectID object_id; float lod_begin; float lod_end; @@ -203,7 +203,6 @@ public: extra_margin = 0; - object_id = 0; visible = true; lod_begin = 0; |