first cut at using erase entity message to delete entities

This commit is contained in:
ZappoMan 2014-08-13 14:11:56 -07:00
parent 4bdb8765f5
commit 49e616dd49
15 changed files with 207 additions and 233 deletions

View file

@ -78,7 +78,7 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin
return;
}
bool debugProcessPacket = _myServer->wantsVerboseDebug();
bool debugProcessPacket = true;// _myServer->wantsVerboseDebug();
if (debugProcessPacket) {
qDebug("OctreeInboundPacketProcessor::processPacket() packetData=%p packetLength=%d", &packet, packet.size());
@ -103,7 +103,7 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin
quint64 processTime = 0;
quint64 lockWaitTime = 0;
if (_myServer->wantsDebugReceiving()) {
if (debugProcessPacket || _myServer->wantsDebugReceiving()) {
qDebug() << "PROCESSING THREAD: got '" << packetType << "' packet - " << _receivedPacketCount
<< " command from client receivedBytes=" << packet.size()
<< " sequence=" << sequence << " transitTime=" << transitTime << " usecs";
@ -126,6 +126,12 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin
reinterpret_cast<const unsigned char*>(packet.data()),
packet.size(),
editData, maxSize, sendingNode);
if (debugProcessPacket) {
qDebug() << "OctreeInboundPacketProcessor::processPacket() after processEditPacketData()..."
<< "editDataBytesRead=" << editDataBytesRead;
}
_myServer->getOctree()->unlock();
quint64 endProcess = usecTimestampNow();

View file

@ -17,32 +17,10 @@
#include "EntityItem.h"
void EntityEditPacketSender::sendEditEntityMessage(PacketType type, EntityItemID modelID, const EntityItemProperties& properties) {
// allows app to disable sending if for example voxels have been disabled
if (!_shouldSend) {
return; // bail early
}
static unsigned char bufferOut[MAX_PACKET_SIZE];
int sizeOut = 0;
// This encodes the voxel edit message into a buffer...
if (EntityItemProperties::encodeEntityEditPacket(type, modelID, properties, &bufferOut[0], _maxPacketSize, sizeOut)){
// If we don't have voxel jurisdictions, then we will simply queue up these packets and wait till we have
// jurisdictions for processing
if (!serversExist()) {
queuePendingPacketToNodes(type, bufferOut, sizeOut);
} else {
queuePacketToNodes(bufferOut, sizeOut);
}
}
}
void EntityEditPacketSender::adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew) {
EntityItem::adjustEditPacketForClockSkew(codeColorBuffer, length, clockSkew);
}
void EntityEditPacketSender::queueEditEntityMessage(PacketType type, EntityItemID modelID,
const EntityItemProperties& properties) {
if (!_shouldSend) {
@ -58,3 +36,23 @@ void EntityEditPacketSender::queueEditEntityMessage(PacketType type, EntityItemI
}
}
void EntityEditPacketSender::queueEraseEntityMessage(const EntityItemID& entityItemID) {
if (!_shouldSend) {
return; // bail early
}
qDebug() << "EntityEditPacketSender::queueEraseEntityMessage() entityItemID=" << entityItemID;
// use MAX_PACKET_SIZE since it's static and guaranteed to be larger than _maxPacketSize
static unsigned char bufferOut[MAX_PACKET_SIZE];
size_t sizeOut = 0;
qDebug() << " _maxPacketSize=" << _maxPacketSize;
if (EntityItemProperties::encodeEraseEntityMessage(entityItemID, &bufferOut[0], _maxPacketSize, sizeOut)) {
qDebug() << " encodeEraseEntityMessage()... sizeOut=" << sizeOut;
queueOctreeEditMessage(PacketTypeEntityErase, bufferOut, sizeOut);
}
}

View file

@ -20,16 +20,14 @@
class EntityEditPacketSender : public OctreeEditPacketSender {
Q_OBJECT
public:
/// Send model add message immediately
/// NOTE: EntityItemProperties assumes that all distances are in meter units
void sendEditEntityMessage(PacketType type, EntityItemID modelID, const EntityItemProperties& properties);
/// Queues an array of several voxel edit messages. Will potentially send a pending multi-command packet. Determines
/// which voxel-server node or nodes the packet should be sent to. Can be called even before voxel servers are known, in
/// which case up to MaxPendingMessages will be buffered and processed when voxel servers are known.
/// NOTE: EntityItemProperties assumes that all distances are in meter units
void queueEditEntityMessage(PacketType type, EntityItemID modelID, const EntityItemProperties& properties);
void queueEraseEntityMessage(const EntityItemID& entityItemID);
// My server type is the model server
virtual char getMyNodeType() const { return NodeType::EntityServer; }
virtual void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew);

View file

@ -54,7 +54,6 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) {
_position = glm::vec3(0,0,0);
_radius = 0;
_rotation = ENTITY_DEFAULT_ROTATION;
_shouldBeDeleted = false;
_glowLevel = DEFAULT_GLOW_LEVEL;
_mass = DEFAULT_MASS;
@ -220,26 +219,6 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
propertiesDidntFit -= PROP_ROTATION;
}
// PROP_SHOULD_BE_DELETED
if (requestedProperties.getHasProperty(PROP_SHOULD_BE_DELETED)) {
//qDebug() << "PROP_SHOULD_BE_DELETED requested...";
LevelDetails propertyLevel = packetData->startLevel();
successPropertyFits = packetData->appendValue(getShouldBeDeleted());
if (successPropertyFits) {
propertyFlags |= PROP_SHOULD_BE_DELETED;
propertiesDidntFit -= PROP_SHOULD_BE_DELETED;
propertyCount++;
packetData->endLevel(propertyLevel);
} else {
//qDebug() << "PROP_SHOULD_BE_DELETED didn't fit...";
packetData->discardLevel(propertyLevel);
appendState = OctreeElement::PARTIAL;
}
} else {
//qDebug() << "PROP_SHOULD_BE_DELETED NOT requested...";
propertiesDidntFit -= PROP_SHOULD_BE_DELETED;
}
// PROP_MASS,
if (requestedProperties.getHasProperty(PROP_MASS)) {
LevelDetails propertyLevel = packetData->startLevel();
@ -545,17 +524,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
}
}
// PROP_SHOULD_BE_DELETED
if (propertyFlags.getHasProperty(PROP_SHOULD_BE_DELETED)) {
bool shouldBeDeleted;
memcpy(&shouldBeDeleted, dataAt, sizeof(shouldBeDeleted));
dataAt += sizeof(shouldBeDeleted);
bytesRead += sizeof(shouldBeDeleted);
if (overwriteLocalData) {
_shouldBeDeleted = shouldBeDeleted;
}
}
// PROP_MASS,
if (propertyFlags.getHasProperty(PROP_MASS)) {
float value;
@ -641,7 +609,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
void EntityItem::debugDump() const {
qDebug() << "EntityItem id:" << getEntityItemID();
qDebug(" edited ago:%f", getEditedAgo());
qDebug(" should die:%s", debug::valueOf(getShouldBeDeleted()));
qDebug(" position:%f,%f,%f", _position.x, _position.y, _position.z);
qDebug(" radius:%f", getRadius());
}
@ -802,7 +769,6 @@ EntityItemProperties EntityItem::getProperties() const {
properties._position = getPosition() * (float) TREE_SCALE;
properties._radius = getRadius() * (float) TREE_SCALE;
properties._rotation = getRotation();
properties._shouldBeDeleted = getShouldBeDeleted();
properties._mass = getMass();
properties._velocity = getVelocity() * (float) TREE_SCALE;
@ -814,7 +780,6 @@ EntityItemProperties EntityItem::getProperties() const {
properties._positionChanged = false;
properties._radiusChanged = false;
properties._rotationChanged = false;
properties._shouldBeDeletedChanged = false;
properties._massChanged = false;
properties._velocityChanged = false;
properties._gravityChanged = false;
@ -848,11 +813,6 @@ void EntityItem::setProperties(const EntityItemProperties& properties, bool forc
somethingChanged = true;
}
if (properties._shouldBeDeletedChanged || forceCopy) {
setShouldBeDeleted(properties._shouldBeDeleted);
somethingChanged = true;
}
if (properties._massChanged || forceCopy) {
setMass(properties._mass);
somethingChanged = true;

View file

@ -111,9 +111,6 @@ public:
const glm::quat& getRotation() const { return _rotation; }
void setRotation(const glm::quat& rotation) { _rotation = rotation; }
bool getShouldBeDeleted() const { return _shouldBeDeleted; }
void setShouldBeDeleted(bool shouldBeDeleted) { _shouldBeDeleted = shouldBeDeleted; }
static const float DEFAULT_GLOW_LEVEL;
float getGlowLevel() const { return _glowLevel; }
void setGlowLevel(float glowLevel) { _glowLevel = glowLevel; }
@ -182,7 +179,6 @@ protected:
glm::vec3 _position;
float _radius;
glm::quat _rotation;
bool _shouldBeDeleted;
float _glowLevel;
float _mass;
glm::vec3 _velocity;

View file

@ -28,7 +28,6 @@ EntityItemProperties::EntityItemProperties() :
_position(0),
_radius(ENTITY_DEFAULT_RADIUS),
_rotation(ENTITY_DEFAULT_ROTATION),
_shouldBeDeleted(false),
_mass(EntityItem::DEFAULT_MASS),
_velocity(EntityItem::DEFAULT_VELOCITY),
_gravity(EntityItem::DEFAULT_GRAVITY),
@ -39,7 +38,6 @@ EntityItemProperties::EntityItemProperties() :
_positionChanged(false),
_radiusChanged(false),
_rotationChanged(false),
_shouldBeDeletedChanged(false),
_massChanged(false),
_velocityChanged(false),
_gravityChanged(false),
@ -89,11 +87,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
changedProperties += PROP_ROTATION;
}
if (_shouldBeDeletedChanged) {
changedProperties += PROP_SHOULD_BE_DELETED;
}
if (_massChanged) {
changedProperties += PROP_MASS;
}
@ -161,7 +154,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons
properties.setProperty("radius", _radius);
QScriptValue rotation = quatToScriptValue(engine, _rotation);
properties.setProperty("rotation", rotation);
properties.setProperty("shouldBeDeleted", _shouldBeDeleted);
properties.setProperty("mass", _mass);
QScriptValue velocity = vec3toScriptValue(engine, _velocity);
properties.setProperty("velocity", velocity);
@ -251,16 +243,6 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) {
}
}
QScriptValue shouldBeDeleted = object.property("shouldBeDeleted");
if (shouldBeDeleted.isValid()) {
bool newShouldBeDeleted;
newShouldBeDeleted = shouldBeDeleted.toVariant().toBool();
if (_defaultSettings || newShouldBeDeleted != _shouldBeDeleted) {
_shouldBeDeleted = newShouldBeDeleted;
_shouldBeDeletedChanged = true;
}
}
QScriptValue mass = object.property("mass");
if (mass.isValid()) {
float newValue;
@ -600,26 +582,6 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
propertiesDidntFit -= PROP_ROTATION;
}
// PROP_SHOULD_BE_DELETED
if (requestedProperties.getHasProperty(PROP_SHOULD_BE_DELETED)) {
//qDebug() << "PROP_SHOULD_BE_DELETED requested...";
LevelDetails propertyLevel = packetData.startLevel();
successPropertyFits = packetData.appendValue(properties.getShouldBeDeleted());
if (successPropertyFits) {
propertyFlags |= PROP_SHOULD_BE_DELETED;
propertiesDidntFit -= PROP_SHOULD_BE_DELETED;
propertyCount++;
packetData.endLevel(propertyLevel);
} else {
//qDebug() << "PROP_SHOULD_BE_DELETED didn't fit...";
packetData.discardLevel(propertyLevel);
appendState = OctreeElement::PARTIAL;
}
} else {
//qDebug() << "PROP_SHOULD_BE_DELETED NOT requested...";
propertiesDidntFit -= PROP_SHOULD_BE_DELETED;
}
// PROP_MASS,
if (requestedProperties.getHasProperty(PROP_MASS)) {
LevelDetails propertyLevel = packetData.startLevel();
@ -913,7 +875,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
EntityItemID& entityID, EntityItemProperties& properties) {
bool valid = false;
bool wantDebug = false;
bool wantDebug = true;
if (wantDebug) {
qDebug() << "EntityItemProperties::decodeEntityEditPacket() bytesToRead=" << bytesToRead;
}
@ -1045,15 +1007,6 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
properties.setRotation(rotation);
}
// PROP_SHOULD_BE_DELETED
if (propertyFlags.getHasProperty(PROP_SHOULD_BE_DELETED)) {
bool shouldBeDeleted;
memcpy(&shouldBeDeleted, dataAt, sizeof(shouldBeDeleted));
dataAt += sizeof(shouldBeDeleted);
processedBytes += sizeof(shouldBeDeleted);
properties.setShouldBeDeleted(shouldBeDeleted);
}
// PROP_MASS,
if (propertyFlags.getHasProperty(PROP_MASS)) {
float value;
@ -1186,4 +1139,35 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
}
return valid;
}
// NOTE: This version will only encode the portion of the edit message immediately following the
// header it does not include the send times and sequence number because that is handled by the
// edit packet sender...
bool EntityItemProperties::encodeEraseEntityMessage(const EntityItemID& entityItemID,
unsigned char* outputBuffer, size_t maxLength, size_t& outputLength) {
qDebug() << "EntityItemProperties::encodeEraseEntityMessage()";
unsigned char* copyAt = outputBuffer;
uint16_t numberOfIds = 1; // only one entity ID in this message
memcpy(copyAt, &numberOfIds, sizeof(numberOfIds));
copyAt += sizeof(numberOfIds);
outputLength += sizeof(numberOfIds);
qDebug() << " numberOfIds=" << numberOfIds;
QUuid entityID = entityItemID.id;
QByteArray encodedEntityID = entityID.toRfc4122();
memcpy(copyAt, encodedEntityID.constData(), NUM_BYTES_RFC4122_UUID);
copyAt += NUM_BYTES_RFC4122_UUID;
outputLength += NUM_BYTES_RFC4122_UUID;
qDebug() << " entityID=" << entityID;
qDebug() << " outputLength=" << outputLength;
return true;
}

View file

@ -63,8 +63,8 @@ enum EntityPropertyList {
PROP_ANIMATION_FPS,
PROP_ANIMATION_FRAME_INDEX,
PROP_ANIMATION_PLAYING,
PROP_SHOULD_BE_DELETED,
PROP_LAST_ITEM = PROP_SHOULD_BE_DELETED
PROP_LAST_ITEM = PROP_ANIMATION_PLAYING
};
typedef PropertyFlags<EntityPropertyList> EntityPropertyFlags;
@ -122,14 +122,12 @@ public:
float getMaxDimension() const { return _radius * 2.0f; }
glm::vec3 getDimensions() const { return glm::vec3(_radius, _radius, _radius) * 2.0f; }
const glm::quat& getRotation() const { return _rotation; }
bool getShouldBeDeleted() const { return _shouldBeDeleted; }
void setType(EntityTypes::EntityType type) { _type = type; }
/// set position in meter units
void setPosition(const glm::vec3& value) { _position = value; _positionChanged = true; }
void setRadius(float value) { _radius = value; _radiusChanged = true; }
void setRotation(const glm::quat& rotation) { _rotation = rotation; _rotationChanged = true; }
void setShouldBeDeleted(bool shouldBeDeleted) { _shouldBeDeleted = shouldBeDeleted; _shouldBeDeletedChanged = true; }
float getMass() const { return _mass; }
void setMass(float value) { _mass = value; _massChanged = true; }
@ -175,6 +173,10 @@ public:
static bool encodeEntityEditPacket(PacketType command, EntityItemID id, const EntityItemProperties& properties,
unsigned char* bufferOut, int sizeIn, int& sizeOut);
static bool encodeEraseEntityMessage(const EntityItemID& entityItemID,
unsigned char* outputBuffer, size_t maxLength, size_t& outputLength);
static bool decodeEntityEditPacket(const unsigned char* data, int bytesToRead, int& processedBytes,
EntityItemID& entityID, EntityItemProperties& properties);
@ -189,7 +191,6 @@ private:
glm::vec3 _position;
float _radius;
glm::quat _rotation;
bool _shouldBeDeleted;
float _mass;
glm::vec3 _velocity;
glm::vec3 _gravity;
@ -200,7 +201,6 @@ private:
bool _positionChanged;
bool _radiusChanged;
bool _rotationChanged;
bool _shouldBeDeletedChanged;
bool _massChanged;
bool _velocityChanged;
bool _gravityChanged;

View file

@ -123,10 +123,6 @@ EntityItemID EntityScriptingInterface::editEntity(EntityItemID entityID, const E
// message which takes a list of model id's to delete.
void EntityScriptingInterface::deleteEntity(EntityItemID entityID) {
// setup properties to kill the model
EntityItemProperties properties;
properties.setShouldBeDeleted(true);
EntityItemID actualID = entityID;
// if the model is unknown, attempt to look it up
@ -138,8 +134,13 @@ void EntityScriptingInterface::deleteEntity(EntityItemID entityID) {
if (actualID.id != UNKNOWN_ENTITY_ID) {
entityID.id = actualID.id;
entityID.isKnownID = true;
//qDebug() << "EntityScriptingInterface::deleteEntity()... isKnownID=" << entityID.isKnownID << "id=" << entityID.id << "creatorTokenID=" << entityID.creatorTokenID;
queueEntityMessage(PacketTypeEntityAddOrEdit, entityID, properties);
qDebug() << "EntityScriptingInterface::deleteEntity()... "
<< "isKnownID=" << entityID.isKnownID
<< "id=" << entityID.id
<< "creatorTokenID=" << entityID.creatorTokenID;
getEntityPacketSender()->queueEraseEntityMessage(entityID);
}
// If we have a local model tree set, then also update it.

View file

@ -302,9 +302,9 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree,
// does this entity tree element contain the old entity
bool UpdateEntityOperator::subTreeContainsOldEntity(OctreeElement* element) {
bool elementContainsOldBox = element->getAACube().contains(_oldEntityBox);
bool elementContainsOldCube = element->getAACube().contains(_oldEntityCube);
/*
bool elementContainsOldCube = element->getAACube().contains(_oldEntityCube);
qDebug() << "UpdateEntityOperator::subTreeContainsOldEntity()....";
qDebug() << " element->getAACube()=" << element->getAACube();
qDebug() << " _oldEntityCube=" << _oldEntityCube;
@ -318,9 +318,9 @@ bool UpdateEntityOperator::subTreeContainsOldEntity(OctreeElement* element) {
bool UpdateEntityOperator::subTreeContainsNewEntity(OctreeElement* element) {
bool elementContainsNewBox = element->getAACube().contains(_newEntityBox);
bool elementContainsNewCube = element->getAACube().contains(_newEntityCube);
/*
bool elementContainsNewCube = element->getAACube().contains(_newEntityCube);
qDebug() << "UpdateEntityOperator::subTreeContainsNewEntity()....";
qDebug() << " element->getAACube()=" << element->getAACube();
qDebug() << " _newEntityCube=" << _newEntityCube;
@ -511,7 +511,10 @@ bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp
// You should not call this on existing entities that are already part of the tree! Call updateEntity()
EntityTreeElement* containingElement = getContainingElement(entityID);
if (!containingElement) {
assert(containingElement); // don't call updateEntity() on entity items that don't exist
//assert(containingElement); // don't call updateEntity() on entity items that don't exist
qDebug() << "UNEXPECTED!!!! EntityTree::updateEntity() entityID doesn't exist!!! entityID=" << entityID;
return false;
}
@ -633,10 +636,23 @@ void DeleteEntityOperator::addEntityIDToDeleteList(const EntityItemID& searchEnt
details.cube = details.containingElement->getAACube();
_entitiesToDelete << details;
_lookingCount++;
_tree->trackDeletedEntity(searchEntityID);
}
}
}
void EntityTree::trackDeletedEntity(const EntityItemID& entityID) {
// this is only needed on the server to send delete messages for recently deleted entities to the viewers
if (getIsServer()) {
// set up the deleted entities ID
quint64 deletedAt = usecTimestampNow();
_recentlyDeletedEntitiesLock.lockForWrite();
_recentlyDeletedEntityItemIDs.insert(deletedAt, entityID.id);
_recentlyDeletedEntitiesLock.unlock();
}
}
// does this entity tree element contain the old entity
bool DeleteEntityOperator::subTreeContainsSomeEntitiesToDelete(OctreeElement* element) {
@ -1046,8 +1062,15 @@ int EntityTree::processEditPacketData(PacketType packetType, const unsigned char
int processedBytes = 0;
// we handle these types of "edit" packets
switch (packetType) {
case PacketTypeEntityErase: {
qDebug() << "EntityTree::processEditPacketData().... PacketTypeEntityErase ****** packetLength=" << packetLength;
QByteArray dataByteArray((const char*)packetData, packetLength);
processEraseMessageDetails(dataByteArray, senderNode);
break;
}
case PacketTypeEntityAddOrEdit: {
//qDebug() << "EntityTree::processEditPacketData()....";
qDebug() << "EntityTree::processEditPacketData()....";
EntityItemID entityItemID;
EntityItemProperties properties;
@ -1071,21 +1094,10 @@ int EntityTree::processEditPacketData(PacketType packetType, const unsigned char
qDebug() << "User attempted to edit an unknown entity.";
}
} else {
//
// NOTE: We need to fix this... we can't have the creator tokens in the server side map... because if we do that
// then we will have multiple creator tokens with the same id from different editors... since assignEntityID()
// checks for the ID already existing in the map, this will assert/abort.
//
// But we do want the creator tokens in the client side version of the map...
// so maybe the fix is just to ....
// this is a new entity... assign a new entityID
qDebug() << "EntityTree::processEditPacketData() ... BEFORE assignEntityID()... entityItemID=" << entityItemID;
qDebug() << "EntityTree::processEditPacketData() ... BEFORE assignEntityID()... entityItemID=" << entityItemID;
entityItemID = assignEntityID(entityItemID);
qDebug() << "EntityTree::processEditPacketData() ... AFTER assignEntityID()... entityItemID=" << entityItemID;
qDebug() << "EntityTree::processEditPacketData() ... AFTER assignEntityID()... entityItemID=" << entityItemID;
EntityItem* newEntity = addEntity(entityItemID, properties);
if (newEntity) {
@ -1130,13 +1142,6 @@ void EntityTree::removeNewlyCreatedHook(NewlyCreatedEntityHook* hook) {
}
bool EntityTree::updateOperation(OctreeElement* element, void* extraData) {
EntityTreeUpdateArgs* args = static_cast<EntityTreeUpdateArgs*>(extraData);
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
entityTreeElement->update(*args);
return true;
}
void EntityTree::changeEntityState(EntityItem* const entity, EntityItem::SimuationState oldState, EntityItem::SimuationState newState) {
bool wantDebug = false;
@ -1302,7 +1307,7 @@ bool EntityTree::hasEntitiesDeletedSince(quint64 sinceTime) {
bool hasSomethingNewer = false;
_recentlyDeletedEntitiesLock.lockForRead();
QMultiMap<quint64, uint32_t>::const_iterator iterator = _recentlyDeletedEntityItemIDs.constBegin();
QMultiMap<quint64, QUuid>::const_iterator iterator = _recentlyDeletedEntityItemIDs.constBegin();
while (iterator != _recentlyDeletedEntityItemIDs.constEnd()) {
//qDebug() << "considering... time/key:" << iterator.key();
if (iterator.key() > sinceTime) {
@ -1357,28 +1362,30 @@ qDebug() << "EntityTree::encodeEntitiesDeletedSince()";
// we keep a multi map of entity IDs to timestamps, we only want to include the entity IDs that have been
// deleted since we last sent to this node
_recentlyDeletedEntitiesLock.lockForRead();
QMultiMap<quint64, uint32_t>::const_iterator iterator = _recentlyDeletedEntityItemIDs.constBegin();
QMultiMap<quint64, QUuid>::const_iterator iterator = _recentlyDeletedEntityItemIDs.constBegin();
while (iterator != _recentlyDeletedEntityItemIDs.constEnd()) {
QList<uint32_t> values = _recentlyDeletedEntityItemIDs.values(iterator.key());
QList<QUuid> values = _recentlyDeletedEntityItemIDs.values(iterator.key());
for (int valueItem = 0; valueItem < values.size(); ++valueItem) {
// if the timestamp is more recent then out last sent time, include it
if (iterator.key() > sinceTime) {
uint32_t entityID = values.at(valueItem);
memcpy(copyAt, &entityID, sizeof(entityID));
copyAt += sizeof(entityID);
outputLength += sizeof(entityID);
QUuid entityID = values.at(valueItem);
QByteArray encodedEntityID = entityID.toRfc4122();
memcpy(copyAt, encodedEntityID.constData(), NUM_BYTES_RFC4122_UUID);
copyAt += NUM_BYTES_RFC4122_UUID;
outputLength += NUM_BYTES_RFC4122_UUID;
numberOfIds++;
// check to make sure we have room for one more id...
if (outputLength + sizeof(uint32_t) > maxLength) {
if (outputLength + NUM_BYTES_RFC4122_UUID > maxLength) {
break;
}
}
}
// check to make sure we have room for one more id...
if (outputLength + sizeof(uint32_t) > maxLength) {
if (outputLength + NUM_BYTES_RFC4122_UUID > maxLength) {
// let our caller know how far we got
sinceTime = iterator.key();
@ -1398,14 +1405,14 @@ qDebug() << "EntityTree::encodeEntitiesDeletedSince()";
return hasMoreToSend;
}
// called by the server when it knows all nodes have been sent deleted packets
// called by the server when it knows all nodes have been sent deleted packets
void EntityTree::forgetEntitiesDeletedBefore(quint64 sinceTime) {
//qDebug() << "forgetEntitiesDeletedBefore()";
QSet<quint64> keysToRemove;
_recentlyDeletedEntitiesLock.lockForWrite();
QMultiMap<quint64, uint32_t>::iterator iterator = _recentlyDeletedEntityItemIDs.begin();
QMultiMap<quint64, QUuid>::iterator iterator = _recentlyDeletedEntityItemIDs.begin();
// First find all the keys in the map that are older and need to be deleted
while (iterator != _recentlyDeletedEntityItemIDs.end()) {
@ -1426,10 +1433,6 @@ void EntityTree::forgetEntitiesDeletedBefore(quint64 sinceTime) {
void EntityTree::processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) {
#if 0 ///////////////
qDebug() << "EntityTree::processEraseMessage()...";
const unsigned char* packetData = (const unsigned char*)dataByteArray.constData();
@ -1449,18 +1452,25 @@ void EntityTree::processEraseMessage(const QByteArray& dataByteArray, const Shar
dataAt += sizeof(numberOfIds);
processedBytes += sizeof(numberOfIds);
qDebug() << "EntityTree::processEraseMessage().... numberOfIds=" << numberOfIds;
qDebug() << "EntityTree::processEraseMessage().... processedBytes=" << processedBytes;
qDebug() << "EntityTree::processEraseMessage().... packetLength=" << packetLength;
if (numberOfIds > 0) {
QSet<EntityItemID> entityItemIDsToDelete;
for (size_t i = 0; i < numberOfIds; i++) {
if (processedBytes + sizeof(uint32_t) > packetLength) {
if (processedBytes + NUM_BYTES_RFC4122_UUID > packetLength) {
qDebug() << "EntityTree::processEraseMessage().... bailing because not enough bytes in buffer";
break; // bail to prevent buffer overflow
}
uint32_t entityID = 0; // placeholder for now
memcpy(&entityID, dataAt, sizeof(entityID));
dataAt += sizeof(entityID);
processedBytes += sizeof(entityID);
QByteArray encodedID = dataByteArray.mid(processedBytes, NUM_BYTES_RFC4122_UUID);
QUuid entityID = QUuid::fromRfc4122(encodedID);
dataAt += encodedID.size();
processedBytes += encodedID.size();
EntityItemID entityItemID(entityID);
entityItemIDsToDelete << entityItemID;
@ -1469,9 +1479,49 @@ void EntityTree::processEraseMessage(const QByteArray& dataByteArray, const Shar
qDebug() << "EntityTree::processEraseMessage()... deleteEntities(entityItemIDsToDelete)";
deleteEntities(entityItemIDsToDelete);
}
#endif // 0 ///////////////
}
// This version skips over the header
void EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) {
qDebug() << "EntityTree::processEraseMessageDetails()...";
const unsigned char* packetData = (const unsigned char*)dataByteArray.constData();
const unsigned char* dataAt = packetData;
size_t packetLength = dataByteArray.size();
size_t processedBytes = 0;
uint16_t numberOfIds = 0; // placeholder for now
memcpy(&numberOfIds, dataAt, sizeof(numberOfIds));
dataAt += sizeof(numberOfIds);
processedBytes += sizeof(numberOfIds);
qDebug() << "EntityTree::processEraseMessageDetails().... numberOfIds=" << numberOfIds;
qDebug() << "EntityTree::processEraseMessageDetails().... processedBytes=" << processedBytes;
qDebug() << "EntityTree::processEraseMessageDetails().... packetLength=" << packetLength;
if (numberOfIds > 0) {
QSet<EntityItemID> entityItemIDsToDelete;
for (size_t i = 0; i < numberOfIds; i++) {
if (processedBytes + NUM_BYTES_RFC4122_UUID > packetLength) {
qDebug() << "EntityTree::processEraseMessageDetails().... bailing because not enough bytes in buffer";
break; // bail to prevent buffer overflow
}
QByteArray encodedID = dataByteArray.mid(processedBytes, NUM_BYTES_RFC4122_UUID);
QUuid entityID = QUuid::fromRfc4122(encodedID);
dataAt += encodedID.size();
processedBytes += encodedID.size();
EntityItemID entityItemID(entityID);
entityItemIDsToDelete << entityItemID;
qDebug() << "EntityTree::processEraseMessageDetails()... entityItemIDsToDelete << entityItemID=" << entityItemID;
}
qDebug() << "EntityTree::processEraseMessageDetails()... deleteEntities(entityItemIDsToDelete)";
deleteEntities(entityItemIDsToDelete);
}
}

View file

@ -101,6 +101,7 @@ public:
void forgetEntitiesDeletedBefore(quint64 sinceTime);
void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode);
void processEraseMessageDetails(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode);
void handleAddEntityResponse(const QByteArray& packet);
EntityItemFBXService* getFBXService() const { return _fbxService; }
@ -119,9 +120,10 @@ public:
void changeEntityState(EntityItem* const entity, EntityItem::SimuationState oldState, EntityItem::SimuationState newState);
void trackDeletedEntity(const EntityItemID& entityID);
private:
static bool updateOperation(OctreeElement* element, void* extraData);
static bool findAndUpdateOperation(OctreeElement* element, void* extraData);
static bool findAndUpdateWithIDandPropertiesOperation(OctreeElement* element, void* extraData);
static bool findNearPointOperation(OctreeElement* element, void* extraData);
@ -137,8 +139,9 @@ private:
QReadWriteLock _newlyCreatedHooksLock;
QVector<NewlyCreatedEntityHook*> _newlyCreatedHooks;
QReadWriteLock _recentlyDeletedEntitiesLock;
QMultiMap<quint64, uint32_t> _recentlyDeletedEntityItemIDs;
QMultiMap<quint64, QUuid> _recentlyDeletedEntityItemIDs;
EntityItemFBXService* _fbxService;
QHash<EntityItemID, EntityTreeElement*> _entityToElementMap;

View file

@ -280,51 +280,6 @@ bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3
return false;
}
void EntityTreeElement::update(EntityTreeUpdateArgs& args) {
args._totalElements++;
// update our contained entities
QList<EntityItem*>::iterator entityItr = _entityItems->begin();
while(entityItr != _entityItems->end()) {
EntityItem* entity = (*entityItr);
args._totalItems++;
// TODO: this _lastChanged isn't actually changing because we're not marking this element as changed.
// how do we want to handle this??? We really only want to consider an element changed when it is
// edited... not just animated...
entity->update(_lastChanged);
// If the entity wants to die, or if it's left our bounding box, then move it
// into the arguments moving entities. These will be added back or deleted completely
if (entity->getShouldBeDeleted() || !bestFitEntityBounds(entity)) {
qDebug() << "EntityTreeElement::update()... OLD DELETE LOGIC CALLED BUT NOT IMPLEMENTED...";
/***
// TODO: What to do about this???
args._movingEntities.push_back(entity);
// erase this entity
entityItr = _entityItems->erase(entityItr);
args._movingItems++;
// this element has changed so mark it...
markWithChangedTime();
// TODO: is this a good place to change the containing element map???
qDebug() << "EntityTreeElement::update()... calling _myTree->setContainingElement(entity.getEntityItemID(), NULL); ********";
_myTree->setContainingElement(entity->getEntityItemID(), NULL);
**/
} else {
++entityItr;
}
}
}
bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
void** intersectedObject) {

View file

@ -114,7 +114,6 @@ public:
QList<EntityItem*>& getEntities() { return *_entityItems; }
bool hasEntities() const { return _entityItems ? _entityItems->size() > 0 : false; }
void update(EntityTreeUpdateArgs& args);
void setTree(EntityTree* tree) { _myTree = tree; }
bool updateEntity(const EntityItem& entity);

View file

@ -255,10 +255,16 @@ int ModelEntityItem::oldVersionReadEntityDataFromBuffer(const unsigned char* dat
dataAt += sizeof(_color);
bytesRead += sizeof(_color);
// TODO: how to handle this? Presumable, this would only ever be true if the model file was saved with
// a model being in a shouldBeDeleted state. Which seems unlikely. But if it happens, maybe we should delete the entity after loading?
// shouldBeDeleted
memcpy(&_shouldBeDeleted, dataAt, sizeof(_shouldBeDeleted));
dataAt += sizeof(_shouldBeDeleted);
bytesRead += sizeof(_shouldBeDeleted);
bool shouldBeDeleted = false;
memcpy(&shouldBeDeleted, dataAt, sizeof(shouldBeDeleted));
dataAt += sizeof(shouldBeDeleted);
bytesRead += sizeof(shouldBeDeleted);
if (shouldBeDeleted) {
qDebug() << "UNEXPECTED - read shouldBeDeleted=TRUE from an old format file";
}
// modelURL
uint16_t modelURLLength;

View file

@ -77,7 +77,7 @@ PacketVersion versionForPacketType(PacketType type) {
case PacketTypeEntityData:
return VERSION_ENTITIES_SUPPORT_SPLIT_MTU;
case PacketTypeEntityErase:
return 1;
return 2;
case PacketTypeAudioStreamStats:
return 1;
default:

View file

@ -251,8 +251,10 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType type, unsigned ch
if (node->getActiveSocket() && node->getType() == getMyNodeType()) {
QUuid nodeUUID = node->getUUID();
bool isMyJurisdiction = true;
if (_serverJurisdictions) {
if (type == PacketTypeEntityErase) {
isMyJurisdiction = true; // send erase messages to all servers
} else if (_serverJurisdictions) {
// we need to get the jurisdiction for this
// here we need to get the "pending packet" for this server
_serverJurisdictions->lockForRead();
@ -265,6 +267,9 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType type, unsigned ch
_serverJurisdictions->unlock();
}
if (isMyJurisdiction) {
qDebug() << "OctreeEditPacketSender::queueOctreeEditMessage()... isMyJurisidiction....";
EditPacketBuffer& packetBuffer = _pendingEditPackets[nodeUUID];
packetBuffer._nodeUUID = nodeUUID;
@ -272,11 +277,17 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType type, unsigned ch
if ((type != packetBuffer._currentType && packetBuffer._currentSize > 0) ||
(packetBuffer._currentSize + length >= _maxPacketSize)) {
releaseQueuedPacket(packetBuffer);
qDebug() << "OctreeEditPacketSender::queueOctreeEditMessage()... SWITCHING TYPE...initializePacket()....";
initializePacket(packetBuffer, type);
}
// If the buffer is empty and not correctly initialized for our type...
if (type != packetBuffer._currentType && packetBuffer._currentSize == 0) {
qDebug() << "OctreeEditPacketSender::queueOctreeEditMessage()... SWITCHING TYPE...initializePacket()....";
initializePacket(packetBuffer, type);
}
@ -285,12 +296,19 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType type, unsigned ch
// We call this virtual function that allows our specific type of EditPacketSender to
// fixup the buffer for any clock skew
if (node->getClockSkewUsec() != 0) {
qDebug() << "OctreeEditPacketSender::queueOctreeEditMessage()... adjustEditPacketForClockSkew()....";
adjustEditPacketForClockSkew(editPacketBuffer, length, node->getClockSkewUsec());
}
qDebug() << "OctreeEditPacketSender::queueOctreeEditMessage()... memcpy(&packetBuffer...)....";
qDebug() << " BEFORE packetBuffer._currentSize=" << packetBuffer._currentSize;
memcpy(&packetBuffer._currentBuffer[packetBuffer._currentSize], editPacketBuffer, length);
packetBuffer._currentSize += length;
packetBuffer._satoshiCost += satoshiCost;
qDebug() << " AFTER packetBuffer._currentSize=" << packetBuffer._currentSize;
}
}
}