From d3fea94540a618d3de276a54dbcc3402d248e044 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 3 Dec 2018 18:13:31 -0800 Subject: [PATCH] send AvatarEntities via raw data packet --- .../src/avatars-renderer/Avatar.cpp | 25 ++++++++------- .../entities/src/EntityEditPacketSender.cpp | 24 ++++++-------- libraries/entities/src/EntityItem.cpp | 5 +++ libraries/octree/src/OctreePacketData.cpp | 31 ++++++++++++------- libraries/octree/src/OctreePacketData.h | 4 +++ 5 files changed, 53 insertions(+), 36 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index dbf5899386..2c52bc69ea 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -378,19 +378,22 @@ void Avatar::updateAvatarEntities() { } ++dataItr; - // see EntityEditPacketSender::queueEditEntityMessage for the other end of this. unpack properties - // and either add or update the entity. - QJsonDocument jsonProperties = QJsonDocument::fromBinaryData(data); - if (!jsonProperties.isObject()) { - qCDebug(avatars_renderer) << "got bad avatarEntity json" << QString(data.toHex()); - continue; + EntityItemProperties properties; + { + // create a temporary EntityItem to unpack the data + int32_t bytesLeftToRead = data.size(); + unsigned char* dataAt = (unsigned char*)(data.data()); + ReadBitstreamToTreeParams args; + EntityItemPointer tempEntity = EntityTypes::constructEntityItem(dataAt, bytesLeftToRead, args); + if (!tempEntity) { + continue; + } + tempEntity->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args); + + // extract the properties from tempEntity + properties = tempEntity->getProperties(); } - QVariant variantProperties = jsonProperties.toVariant(); - QVariantMap asMap = variantProperties.toMap(); - QScriptValue scriptProperties = variantMapToScriptValue(asMap, scriptEngine); - EntityItemProperties properties; - EntityItemPropertiesFromScriptValueIgnoreReadOnly(scriptProperties, properties); properties.setEntityHostType(entity::HostType::AVATAR); properties.setOwningAvatarID(getID()); diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index c414a7a4ac..8d0348bae6 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -54,27 +54,23 @@ void EntityEditPacketSender::queueEditAvatarEntityMessage(PacketType type, return; } - // the properties that get serialized into the avatar identity packet should be the entire set + // serialize ALL properties in an "AvatarEntity" packet // rather than just the ones being edited. EntityItemProperties entityProperties = entity->getProperties(); entityProperties.merge(properties); - std::lock_guard lock(_mutex); - QScriptValue scriptProperties = EntityItemNonDefaultPropertiesToScriptValue(&_scriptEngine, entityProperties); - QVariant variantProperties = scriptProperties.toVariant(); - QJsonDocument jsonProperties = QJsonDocument::fromVariant(variantProperties); + OctreePacketData packetData(false, AvatarTraits::MAXIMUM_TRAIT_SIZE); + EncodeBitstreamParams params; + EntityTreeElementExtraEncodeDataPointer extra { nullptr }; + OctreeElement::AppendState appendState = entity->appendEntityData(&packetData, params, extra); - // the ID of the parent/avatar changes from session to session. use a special UUID to indicate the avatar - QJsonObject jsonObject = jsonProperties.object(); - if (jsonObject.contains("parentID")) { - if (QUuid(jsonObject["parentID"].toString()) == _myAvatar->getID()) { - jsonObject["parentID"] = AVATAR_SELF_ID.toString(); - } + if (appendState != OctreeElement::COMPLETED) { + // this entity is too big + return; } - jsonProperties = QJsonDocument(jsonObject); - QByteArray binaryProperties = jsonProperties.toBinaryData(); - _myAvatar->updateAvatarEntity(entityItemID, binaryProperties); + packetData.shrinkByteArrays(); + _myAvatar->updateAvatarEntity(entityItemID, packetData.getUncompressedByteArray()); entity->setLastBroadcast(usecTimestampNow()); } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 498f0ff066..5b7a152318 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -179,6 +179,11 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet EntityPropertyFlags propertyFlags(PROP_LAST_ITEM); EntityPropertyFlags requestedProperties = getEntityProperties(params); + // the values of these two properties are known to the receiver by context + // therefore they don't need to be packed + requestedProperties -= PROP_ENTITY_HOST_TYPE; + requestedProperties -= PROP_OWNING_AVATAR_ID; + // If we are being called for a subsequent pass at appendEntityData() that failed to completely encode this item, // then our entityTreeElementExtraEncodeData should include data about which properties we need to append. if (entityTreeElementExtraEncodeData && entityTreeElementExtraEncodeData->entities.contains(getEntityItemID())) { diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 6c0bba5ec6..60b0e6fbad 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -38,7 +38,11 @@ void OctreePacketData::changeSettings(bool enableCompression, unsigned int targe _enableCompression = enableCompression; _targetSize = targetSize; _uncompressedByteArray.resize(_targetSize); - _compressedByteArray.resize(_targetSize); + if (_enableCompression) { + _compressedByteArray.resize(_targetSize); + } else { + _compressedByteArray.resize(0); + } _uncompressed = (unsigned char*)_uncompressedByteArray.data(); _compressed = (unsigned char*)_compressedByteArray.data(); @@ -586,13 +590,10 @@ bool OctreePacketData::appendRawData(QByteArray data) { AtomicUIntStat OctreePacketData::_compressContentTime { 0 }; AtomicUIntStat OctreePacketData::_compressContentCalls { 0 }; -bool OctreePacketData::compressContent() { +bool OctreePacketData::compressContent() { PerformanceWarning warn(false, "OctreePacketData::compressContent()", false, &_compressContentTime, &_compressContentCalls); - - // without compression, we always pass... - if (!_enableCompression) { - return true; - } + assert(_dirty); + assert(_enableCompression); _bytesInUseLastCheck = _bytesInUse; @@ -605,13 +606,13 @@ bool OctreePacketData::compressContent() { QByteArray compressedData = qCompress(uncompressedData, uncompressedSize, MAX_COMPRESSION); - if (compressedData.size() < (int)MAX_OCTREE_PACKET_DATA_SIZE) { + if (compressedData.size() < _compressedByteArray.size()) { _compressedBytes = compressedData.size(); memcpy(_compressed, compressedData.constData(), _compressedBytes); _dirty = false; success = true; } else { - qCWarning(octree) << "OctreePacketData::compressContent -- compressedData.size >= MAX_OCTREE_PACKET_DATA_SIZE"; + qCWarning(octree) << "OctreePacketData::compressContent -- compressedData.size >= " << _compressedByteArray.size(); assert(false); } return success; @@ -644,8 +645,7 @@ void OctreePacketData::loadFinalizedContent(const unsigned char* data, int lengt memcpy(_uncompressed, uncompressedData.constData(), _bytesInUse); } else { memcpy(_uncompressed, data, length); - memcpy(_compressed, data, length); - _bytesInUse = _compressedBytes = length; + _bytesInUse = length; } } else { if (_debug) { @@ -654,6 +654,15 @@ void OctreePacketData::loadFinalizedContent(const unsigned char* data, int lengt } } +void OctreePacketData::shrinkByteArrays() { + _uncompressedByteArray.resize(_bytesInUse); + _compressedByteArray.resize(_compressedBytes); + // if you call this method then you are expected to be done packing to raw pointers + // and you just want the ByteArrays + // therefore we reset + reset(); +} + void OctreePacketData::debugContent() { qCDebug(octree, "OctreePacketData::debugContent()... COMPRESSED DATA.... size=%d",_compressedBytes); int perline=0; diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index bd1abf8744..cca78e19b3 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -220,6 +220,8 @@ public: /// get pointer to the uncompressed stream buffer at the byteOffset const unsigned char* getUncompressedData(int byteOffset = 0) { return &_uncompressed[byteOffset]; } + const QByteArray& getUncompressedByteArray() { return _uncompressedByteArray; } + /// the size of the packet in uncompressed form int getUncompressedSize() { return _bytesInUse; } @@ -243,6 +245,8 @@ public: int getBytesAvailable() { return _bytesAvailable; } + void shrinkByteArrays(); + /// displays contents for debugging void debugContent(); void debugBytes();