send AvatarEntities via raw data packet

This commit is contained in:
Andrew Meadows 2018-12-03 18:13:31 -08:00
parent 816de0d684
commit d3fea94540
5 changed files with 53 additions and 36 deletions

View file

@ -378,19 +378,22 @@ void Avatar::updateAvatarEntities() {
} }
++dataItr; ++dataItr;
// see EntityEditPacketSender::queueEditEntityMessage for the other end of this. unpack properties EntityItemProperties properties;
// and either add or update the entity. {
QJsonDocument jsonProperties = QJsonDocument::fromBinaryData(data); // create a temporary EntityItem to unpack the data
if (!jsonProperties.isObject()) { int32_t bytesLeftToRead = data.size();
qCDebug(avatars_renderer) << "got bad avatarEntity json" << QString(data.toHex()); unsigned char* dataAt = (unsigned char*)(data.data());
continue; 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.setEntityHostType(entity::HostType::AVATAR);
properties.setOwningAvatarID(getID()); properties.setOwningAvatarID(getID());

View file

@ -54,27 +54,23 @@ void EntityEditPacketSender::queueEditAvatarEntityMessage(PacketType type,
return; 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. // rather than just the ones being edited.
EntityItemProperties entityProperties = entity->getProperties(); EntityItemProperties entityProperties = entity->getProperties();
entityProperties.merge(properties); entityProperties.merge(properties);
std::lock_guard<std::mutex> lock(_mutex); OctreePacketData packetData(false, AvatarTraits::MAXIMUM_TRAIT_SIZE);
QScriptValue scriptProperties = EntityItemNonDefaultPropertiesToScriptValue(&_scriptEngine, entityProperties); EncodeBitstreamParams params;
QVariant variantProperties = scriptProperties.toVariant(); EntityTreeElementExtraEncodeDataPointer extra { nullptr };
QJsonDocument jsonProperties = QJsonDocument::fromVariant(variantProperties); 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 if (appendState != OctreeElement::COMPLETED) {
QJsonObject jsonObject = jsonProperties.object(); // this entity is too big
if (jsonObject.contains("parentID")) { return;
if (QUuid(jsonObject["parentID"].toString()) == _myAvatar->getID()) {
jsonObject["parentID"] = AVATAR_SELF_ID.toString();
}
} }
jsonProperties = QJsonDocument(jsonObject);
QByteArray binaryProperties = jsonProperties.toBinaryData(); packetData.shrinkByteArrays();
_myAvatar->updateAvatarEntity(entityItemID, binaryProperties); _myAvatar->updateAvatarEntity(entityItemID, packetData.getUncompressedByteArray());
entity->setLastBroadcast(usecTimestampNow()); entity->setLastBroadcast(usecTimestampNow());
} }

View file

@ -179,6 +179,11 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
EntityPropertyFlags propertyFlags(PROP_LAST_ITEM); EntityPropertyFlags propertyFlags(PROP_LAST_ITEM);
EntityPropertyFlags requestedProperties = getEntityProperties(params); 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, // 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. // then our entityTreeElementExtraEncodeData should include data about which properties we need to append.
if (entityTreeElementExtraEncodeData && entityTreeElementExtraEncodeData->entities.contains(getEntityItemID())) { if (entityTreeElementExtraEncodeData && entityTreeElementExtraEncodeData->entities.contains(getEntityItemID())) {

View file

@ -38,7 +38,11 @@ void OctreePacketData::changeSettings(bool enableCompression, unsigned int targe
_enableCompression = enableCompression; _enableCompression = enableCompression;
_targetSize = targetSize; _targetSize = targetSize;
_uncompressedByteArray.resize(_targetSize); _uncompressedByteArray.resize(_targetSize);
_compressedByteArray.resize(_targetSize); if (_enableCompression) {
_compressedByteArray.resize(_targetSize);
} else {
_compressedByteArray.resize(0);
}
_uncompressed = (unsigned char*)_uncompressedByteArray.data(); _uncompressed = (unsigned char*)_uncompressedByteArray.data();
_compressed = (unsigned char*)_compressedByteArray.data(); _compressed = (unsigned char*)_compressedByteArray.data();
@ -588,11 +592,8 @@ AtomicUIntStat OctreePacketData::_compressContentCalls { 0 };
bool OctreePacketData::compressContent() { bool OctreePacketData::compressContent() {
PerformanceWarning warn(false, "OctreePacketData::compressContent()", false, &_compressContentTime, &_compressContentCalls); PerformanceWarning warn(false, "OctreePacketData::compressContent()", false, &_compressContentTime, &_compressContentCalls);
assert(_dirty);
// without compression, we always pass... assert(_enableCompression);
if (!_enableCompression) {
return true;
}
_bytesInUseLastCheck = _bytesInUse; _bytesInUseLastCheck = _bytesInUse;
@ -605,13 +606,13 @@ bool OctreePacketData::compressContent() {
QByteArray compressedData = qCompress(uncompressedData, uncompressedSize, MAX_COMPRESSION); QByteArray compressedData = qCompress(uncompressedData, uncompressedSize, MAX_COMPRESSION);
if (compressedData.size() < (int)MAX_OCTREE_PACKET_DATA_SIZE) { if (compressedData.size() < _compressedByteArray.size()) {
_compressedBytes = compressedData.size(); _compressedBytes = compressedData.size();
memcpy(_compressed, compressedData.constData(), _compressedBytes); memcpy(_compressed, compressedData.constData(), _compressedBytes);
_dirty = false; _dirty = false;
success = true; success = true;
} else { } else {
qCWarning(octree) << "OctreePacketData::compressContent -- compressedData.size >= MAX_OCTREE_PACKET_DATA_SIZE"; qCWarning(octree) << "OctreePacketData::compressContent -- compressedData.size >= " << _compressedByteArray.size();
assert(false); assert(false);
} }
return success; return success;
@ -644,8 +645,7 @@ void OctreePacketData::loadFinalizedContent(const unsigned char* data, int lengt
memcpy(_uncompressed, uncompressedData.constData(), _bytesInUse); memcpy(_uncompressed, uncompressedData.constData(), _bytesInUse);
} else { } else {
memcpy(_uncompressed, data, length); memcpy(_uncompressed, data, length);
memcpy(_compressed, data, length); _bytesInUse = length;
_bytesInUse = _compressedBytes = length;
} }
} else { } else {
if (_debug) { 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() { void OctreePacketData::debugContent() {
qCDebug(octree, "OctreePacketData::debugContent()... COMPRESSED DATA.... size=%d",_compressedBytes); qCDebug(octree, "OctreePacketData::debugContent()... COMPRESSED DATA.... size=%d",_compressedBytes);
int perline=0; int perline=0;

View file

@ -220,6 +220,8 @@ public:
/// get pointer to the uncompressed stream buffer at the byteOffset /// get pointer to the uncompressed stream buffer at the byteOffset
const unsigned char* getUncompressedData(int byteOffset = 0) { return &_uncompressed[byteOffset]; } const unsigned char* getUncompressedData(int byteOffset = 0) { return &_uncompressed[byteOffset]; }
const QByteArray& getUncompressedByteArray() { return _uncompressedByteArray; }
/// the size of the packet in uncompressed form /// the size of the packet in uncompressed form
int getUncompressedSize() { return _bytesInUse; } int getUncompressedSize() { return _bytesInUse; }
@ -243,6 +245,8 @@ public:
int getBytesAvailable() { return _bytesAvailable; } int getBytesAvailable() { return _bytesAvailable; }
void shrinkByteArrays();
/// displays contents for debugging /// displays contents for debugging
void debugContent(); void debugContent();
void debugBytes(); void debugBytes();