|
@@ -33,8 +33,28 @@
|
|
|
#include "reference.h"
|
|
|
#include <stdio.h>
|
|
|
|
|
|
+void EncodedObjectAsID::_bind_methods() {
|
|
|
+ ClassDB::bind_method(D_METHOD("set_object_id", "id"), &EncodedObjectAsID::set_object_id);
|
|
|
+ ClassDB::bind_method(D_METHOD("get_object_id"), &EncodedObjectAsID::get_object_id);
|
|
|
+}
|
|
|
+
|
|
|
+void EncodedObjectAsID::set_object_id(ObjectID p_id) {
|
|
|
+ id = p_id;
|
|
|
+}
|
|
|
+
|
|
|
+ObjectID EncodedObjectAsID::get_object_id() const {
|
|
|
+
|
|
|
+ return id;
|
|
|
+}
|
|
|
+
|
|
|
+EncodedObjectAsID::EncodedObjectAsID() {
|
|
|
+
|
|
|
+ id = 0;
|
|
|
+}
|
|
|
+
|
|
|
#define ENCODE_MASK 0xFF
|
|
|
#define ENCODE_FLAG_64 1 << 16
|
|
|
+#define ENCODE_FLAG_OBJECT_AS_ID 1 << 16
|
|
|
|
|
|
static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r_string) {
|
|
|
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
|
@@ -381,56 +401,74 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|
|
} break;
|
|
|
case Variant::OBJECT: {
|
|
|
|
|
|
- ERR_FAIL_COND_V(!p_allow_objects, ERR_UNAUTHORIZED);
|
|
|
-
|
|
|
- String str;
|
|
|
- Error err = _decode_string(buf, len, r_len, str);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
+ if (type & ENCODE_FLAG_OBJECT_AS_ID) {
|
|
|
+ //this _is_ allowed
|
|
|
+ ObjectID val = decode_uint64(buf);
|
|
|
+ if (r_len)
|
|
|
+ (*r_len) += 8;
|
|
|
|
|
|
- if (str == String()) {
|
|
|
- r_variant = (Object *)NULL;
|
|
|
- } else {
|
|
|
+ if (val == 0) {
|
|
|
+ r_variant = (Object *)NULL;
|
|
|
+ } else {
|
|
|
+ Ref<EncodedObjectAsID> obj_as_id;
|
|
|
+ obj_as_id.instance();
|
|
|
+ obj_as_id->set_object_id(val);
|
|
|
|
|
|
- Object *obj = ClassDB::instance(str);
|
|
|
+ r_variant = obj_as_id;
|
|
|
+ }
|
|
|
|
|
|
- ERR_FAIL_COND_V(!obj, ERR_UNAVAILABLE);
|
|
|
- ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
|
|
+ } else {
|
|
|
+ ERR_FAIL_COND_V(!p_allow_objects, ERR_UNAUTHORIZED);
|
|
|
|
|
|
- int32_t count = decode_uint32(buf);
|
|
|
- buf += 4;
|
|
|
- len -= 4;
|
|
|
- if (r_len) {
|
|
|
- (*r_len) += 4;
|
|
|
- }
|
|
|
+ String str;
|
|
|
+ Error err = _decode_string(buf, len, r_len, str);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
|
|
|
- for (int i = 0; i < count; i++) {
|
|
|
+ if (str == String()) {
|
|
|
+ r_variant = (Object *)NULL;
|
|
|
+ } else {
|
|
|
|
|
|
- str = String();
|
|
|
- err = _decode_string(buf, len, r_len, str);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
+ Object *obj = ClassDB::instance(str);
|
|
|
|
|
|
- Variant value;
|
|
|
- int used;
|
|
|
- err = decode_variant(value, buf, len, &used, p_allow_objects);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
+ ERR_FAIL_COND_V(!obj, ERR_UNAVAILABLE);
|
|
|
+ ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
|
|
|
|
|
|
- buf += used;
|
|
|
- len -= used;
|
|
|
+ int32_t count = decode_uint32(buf);
|
|
|
+ buf += 4;
|
|
|
+ len -= 4;
|
|
|
if (r_len) {
|
|
|
- (*r_len) += used;
|
|
|
+ (*r_len) += 4;
|
|
|
}
|
|
|
|
|
|
- obj->set(str, value);
|
|
|
- }
|
|
|
+ for (int i = 0; i < count; i++) {
|
|
|
|
|
|
- if (obj->cast_to<Reference>()) {
|
|
|
- REF ref = REF(obj->cast_to<Reference>());
|
|
|
- r_variant = ref;
|
|
|
- } else {
|
|
|
- r_variant = obj;
|
|
|
+ str = String();
|
|
|
+ err = _decode_string(buf, len, r_len, str);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ Variant value;
|
|
|
+ int used;
|
|
|
+ err = decode_variant(value, buf, len, &used, p_allow_objects);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ buf += used;
|
|
|
+ len -= used;
|
|
|
+ if (r_len) {
|
|
|
+ (*r_len) += used;
|
|
|
+ }
|
|
|
+
|
|
|
+ obj->set(str, value);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (obj->cast_to<Reference>()) {
|
|
|
+ REF ref = REF(obj->cast_to<Reference>());
|
|
|
+ r_variant = ref;
|
|
|
+ } else {
|
|
|
+ r_variant = obj;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -776,7 +814,7 @@ static void _encode_string(const String &p_string, uint8_t *&buf, int &r_len) {
|
|
|
r_len++; //pad
|
|
|
}
|
|
|
|
|
|
-Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len) {
|
|
|
+Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_object_as_id) {
|
|
|
|
|
|
uint8_t *buf = r_buffer;
|
|
|
|
|
@@ -800,6 +838,11 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len) {
|
|
|
flags |= ENCODE_FLAG_64; //always encode real as double
|
|
|
}
|
|
|
} break;
|
|
|
+ case Variant::OBJECT: {
|
|
|
+ if (p_object_as_id) {
|
|
|
+ flags |= ENCODE_FLAG_OBJECT_AS_ID;
|
|
|
+ }
|
|
|
+ } break;
|
|
|
}
|
|
|
|
|
|
if (buf) {
|
|
@@ -1071,49 +1114,66 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len) {
|
|
|
} break;
|
|
|
case Variant::OBJECT: {
|
|
|
|
|
|
- Object *obj = p_variant;
|
|
|
- if (!obj) {
|
|
|
+ if (p_object_as_id) {
|
|
|
+
|
|
|
if (buf) {
|
|
|
- encode_uint32(0, buf);
|
|
|
- buf += 4;
|
|
|
- r_len += 4;
|
|
|
+
|
|
|
+ Object *obj = p_variant;
|
|
|
+ ObjectID id = 0;
|
|
|
+ if (obj && ObjectDB::instance_validate(obj)) {
|
|
|
+ id = obj->get_instance_id();
|
|
|
+ }
|
|
|
+
|
|
|
+ encode_uint64(id, buf);
|
|
|
}
|
|
|
+
|
|
|
+ r_len += 8;
|
|
|
+
|
|
|
} else {
|
|
|
- _encode_string(obj->get_class(), buf, r_len);
|
|
|
+ Object *obj = p_variant;
|
|
|
+ if (!obj) {
|
|
|
+ if (buf) {
|
|
|
+ encode_uint32(0, buf);
|
|
|
+ buf += 4;
|
|
|
+ r_len += 4;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ _encode_string(obj->get_class(), buf, r_len);
|
|
|
|
|
|
- List<PropertyInfo> props;
|
|
|
- obj->get_property_list(&props);
|
|
|
+ List<PropertyInfo> props;
|
|
|
+ obj->get_property_list(&props);
|
|
|
|
|
|
- int pc = 0;
|
|
|
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
|
|
|
+ int pc = 0;
|
|
|
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
|
|
|
|
|
|
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
|
|
|
- continue;
|
|
|
- pc++;
|
|
|
- }
|
|
|
+ if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
|
|
|
+ continue;
|
|
|
+ pc++;
|
|
|
+ }
|
|
|
|
|
|
- if (buf) {
|
|
|
- encode_uint32(pc, buf);
|
|
|
- buf += 4;
|
|
|
- }
|
|
|
+ if (buf) {
|
|
|
+ encode_uint32(pc, buf);
|
|
|
+ buf += 4;
|
|
|
+ }
|
|
|
|
|
|
- r_len += 4;
|
|
|
+ r_len += 4;
|
|
|
|
|
|
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
|
|
|
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
|
|
|
|
|
|
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
|
|
|
- continue;
|
|
|
+ if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
|
|
|
+ continue;
|
|
|
|
|
|
- _encode_string(E->get().name, buf, r_len);
|
|
|
+ _encode_string(E->get().name, buf, r_len);
|
|
|
|
|
|
- int len;
|
|
|
- Error err = encode_variant(obj->get(E->get().name), buf, len);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
- ERR_FAIL_COND_V(len % 4, ERR_BUG);
|
|
|
- r_len += len;
|
|
|
- if (buf)
|
|
|
- buf += len;
|
|
|
+ int len;
|
|
|
+ Error err = encode_variant(obj->get(E->get().name), buf, len, p_object_as_id);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+ ERR_FAIL_COND_V(len % 4, ERR_BUG);
|
|
|
+ r_len += len;
|
|
|
+ if (buf)
|
|
|
+ buf += len;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1147,12 +1207,12 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len) {
|
|
|
r_len++; //pad
|
|
|
*/
|
|
|
int len;
|
|
|
- encode_variant(E->get(), buf, len);
|
|
|
+ encode_variant(E->get(), buf, len, p_object_as_id);
|
|
|
ERR_FAIL_COND_V(len % 4, ERR_BUG);
|
|
|
r_len += len;
|
|
|
if (buf)
|
|
|
buf += len;
|
|
|
- encode_variant(d[E->get()], buf, len);
|
|
|
+ encode_variant(d[E->get()], buf, len, p_object_as_id);
|
|
|
ERR_FAIL_COND_V(len % 4, ERR_BUG);
|
|
|
r_len += len;
|
|
|
if (buf)
|
|
@@ -1174,7 +1234,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len) {
|
|
|
for (int i = 0; i < v.size(); i++) {
|
|
|
|
|
|
int len;
|
|
|
- encode_variant(v.get(i), buf, len);
|
|
|
+ encode_variant(v.get(i), buf, len, p_object_as_id);
|
|
|
ERR_FAIL_COND_V(len % 4, ERR_BUG);
|
|
|
r_len += len;
|
|
|
if (buf)
|