diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 5cd92a5638..3c10d0382c 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -688,6 +688,13 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef somethingChanged = true; _simulationOwner.clearCurrentOwner(); } + } else if (newSimOwner.matchesValidID(myNodeID) && !_hasBidOnSimulation) { + // entity-server tells us that we have simulation ownership while we never requested this for this EntityItem, + // this could happen when the user reloads the cache and entity tree. + _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + somethingChanged = true; + _simulationOwner.clearCurrentOwner(); + weOwnSimulation = false; } else if (_simulationOwner.set(newSimOwner)) { _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; somethingChanged = true; @@ -1278,7 +1285,7 @@ void EntityItem::grabSimulationOwnership() { auto nodeList = DependencyManager::get(); if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) { // we already own it - _simulationOwner.promotePriority(SCRIPT_POKE_SIMULATION_PRIORITY); + _simulationOwner.promotePriority(SCRIPT_GRAB_SIMULATION_PRIORITY); } else { // we don't own it yet _simulationOwner.setPendingPriority(SCRIPT_GRAB_SIMULATION_PRIORITY, usecTimestampNow()); @@ -1889,6 +1896,10 @@ void EntityItem::setPendingOwnershipPriority(quint8 priority, const quint64& tim _simulationOwner.setPendingPriority(priority, timestamp); } +void EntityItem::rememberHasSimulationOwnershipBid() const { + _hasBidOnSimulation = true; +} + QString EntityItem::actionsToDebugString() { QString result; QVector serializedActions; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index b203de203b..e69195d53d 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -321,6 +321,7 @@ public: void updateSimulationOwner(const SimulationOwner& owner); void clearSimulationOwnership(); void setPendingOwnershipPriority(quint8 priority, const quint64& timestamp); + void rememberHasSimulationOwnershipBid() const; const QString& getMarketplaceID() const { return _marketplaceID; } void setMarketplaceID(const QString& value) { _marketplaceID = value; } @@ -497,16 +498,16 @@ protected: mutable AABox _cachedAABox; mutable AACube _maxAACube; mutable AACube _minAACube; - mutable bool _recalcAABox = true; - mutable bool _recalcMinAACube = true; - mutable bool _recalcMaxAACube = true; + mutable bool _recalcAABox { true }; + mutable bool _recalcMinAACube { true }; + mutable bool _recalcMaxAACube { true }; float _localRenderAlpha; - float _density = ENTITY_ITEM_DEFAULT_DENSITY; // kg/m^3 + float _density { ENTITY_ITEM_DEFAULT_DENSITY }; // kg/m^3 // NOTE: _volumeMultiplier is used to allow some mass properties code exist in the EntityItem base class // rather than in all of the derived classes. If we ever collapse these classes to one we could do it a // different way. - float _volumeMultiplier = 1.0f; + float _volumeMultiplier { 1.0f }; glm::vec3 _gravity; glm::vec3 _acceleration; float _damping; @@ -516,7 +517,7 @@ protected: QString _script; /// the value of the script property QString _loadedScript; /// the value of _script when the last preload signal was sent - quint64 _scriptTimestamp{ ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP }; /// the script loaded property used for forced reload + quint64 _scriptTimestamp { ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP }; /// the script loaded property used for forced reload QString _serverScripts; /// keep track of time when _serverScripts property was last changed @@ -524,7 +525,7 @@ protected: /// the value of _scriptTimestamp when the last preload signal was sent // NOTE: on construction we want this to be different from _scriptTimestamp so we intentionally bump it - quint64 _loadedScriptTimestamp{ ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP + 1 }; + quint64 _loadedScriptTimestamp { ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP + 1 }; QString _collisionSoundURL; SharedSoundPointer _collisionSound; @@ -562,8 +563,8 @@ protected: uint32_t _dirtyFlags; // things that have changed from EXTERNAL changes (via script or packet) but NOT from simulation // these backpointers are only ever set/cleared by friends: - EntityTreeElementPointer _element = nullptr; // set by EntityTreeElement - void* _physicsInfo = nullptr; // set by EntitySimulation + EntityTreeElementPointer _element { nullptr }; // set by EntityTreeElement + void* _physicsInfo { nullptr }; // set by EntitySimulation bool _simulated; // set by EntitySimulation bool addActionInternal(EntitySimulationPointer simulation, EntityActionPointer action); @@ -580,12 +581,15 @@ protected: // are used to keep track of and work around this situation. void checkWaitingToRemove(EntitySimulationPointer simulation = nullptr); mutable QSet _actionsToRemove; - mutable bool _actionDataDirty = false; - mutable bool _actionDataNeedsTransmit = false; + mutable bool _actionDataDirty { false }; + mutable bool _actionDataNeedsTransmit { false }; // _previouslyDeletedActions is used to avoid an action being re-added due to server round-trip lag static quint64 _rememberDeletedActionTime; mutable QHash _previouslyDeletedActions; + // per entity keep state if it ever bid on simulation, so that we can ignore false simulation ownership + mutable bool _hasBidOnSimulation { false }; + QUuid _sourceUUID; /// the server node UUID we came from bool _clientOnly { false }; @@ -594,7 +598,7 @@ protected: // physics related changes from the network to suppress any duplicates and make // sure redundant applications are idempotent glm::vec3 _lastUpdatedPositionValue; - glm::quat _lastUpdatedRotationValue; + glm::quat _lastUpdatedRotationValue; glm::vec3 _lastUpdatedVelocityValue; glm::vec3 _lastUpdatedAngularVelocityValue; glm::vec3 _lastUpdatedAccelerationValue; diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 6fb5d14329..85c3fc74f6 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -231,6 +231,7 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties // and make note of it now, so we can act on it right away. propertiesWithSimID.setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY); entity->setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY); + entity->rememberHasSimulationOwnershipBid(); } entity->setLastBroadcast(usecTimestampNow()); @@ -444,6 +445,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& // we make a bid for simulation ownership properties.setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY); entity->pokeSimulationOwnership(); + entity->rememberHasSimulationOwnershipBid(); } } if (properties.parentRelatedPropertyChanged() && entity->computePuffedQueryAACube()) { diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index b0bdc34b52..02cee9a03a 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -582,6 +582,8 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ _nextOwnershipBid = now + USECS_BETWEEN_OWNERSHIP_BIDS; // copy _outgoingPriority into pendingPriority... _entity->setPendingOwnershipPriority(_outgoingPriority, now); + // don't forget to remember that we have made a bid + _entity->rememberHasSimulationOwnershipBid(); // ...then reset _outgoingPriority in preparation for the next frame _outgoingPriority = 0; } else if (_outgoingPriority != _entity->getSimulationPriority()) {