mirror of
https://github.com/lubosz/overte.git
synced 2025-08-28 15:06:36 +02:00
reduce sim ownership priority when releasing grab
This commit is contained in:
parent
926014b43f
commit
00e360aff0
9 changed files with 160 additions and 146 deletions
|
@ -76,7 +76,7 @@ void addAvatarEntities(const QVariantList& avatarEntities) {
|
|||
|
||||
entity->setLastBroadcast(usecTimestampNow());
|
||||
// since we're creating this object we will immediately volunteer to own its simulation
|
||||
entity->flagForOwnershipBid(VOLUNTEER_SIMULATION_PRIORITY);
|
||||
entity->setScriptSimulationPriority(VOLUNTEER_SIMULATION_PRIORITY);
|
||||
entityProperties.setLastEdited(entity->getLastEdited());
|
||||
} else {
|
||||
qCDebug(entities) << "AvatarEntitiesBookmark failed to add new Entity to local Octree";
|
||||
|
|
|
@ -353,6 +353,10 @@ int EntityItem::expectedBytes() {
|
|||
return MINIMUM_HEADER_BYTES;
|
||||
}
|
||||
|
||||
const uint8_t PENDING_STATE_NOTHING = 0;
|
||||
const uint8_t PENDING_STATE_TAKE = 1;
|
||||
const uint8_t PENDING_STATE_RELEASE = 2;
|
||||
|
||||
// clients use this method to unpack FULL updates from entity-server
|
||||
int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) {
|
||||
setSourceUUID(args.sourceUUID);
|
||||
|
@ -664,7 +668,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
// setters to ignore what the server says.
|
||||
filterRejection = newSimOwner.getID().isNull();
|
||||
if (weOwnSimulation) {
|
||||
if (newSimOwner.getID().isNull() && !_simulationOwner.pendingRelease(lastEditedFromBufferAdjusted)) {
|
||||
if (newSimOwner.getID().isNull() && !pendingRelease(lastEditedFromBufferAdjusted)) {
|
||||
// entity-server is trying to clear our ownership (probably at our own request)
|
||||
// but we actually want to own it, therefore we ignore this clear event
|
||||
// and pretend that we own it (e.g. we assume we'll receive ownership soon)
|
||||
|
@ -679,32 +683,53 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
// recompute weOwnSimulation for later
|
||||
weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
|
||||
}
|
||||
} else if (_simulationOwner.pendingTake(now - maxPingRoundTrip)) {
|
||||
// we sent a bid already but maybe before this packet was sent from the server
|
||||
weOwnSimulation = true;
|
||||
} else if (_pendingOwnershipState == PENDING_STATE_TAKE) {
|
||||
// we're waiting to receive acceptance of a bid
|
||||
// this ownership data either satisifies our bid or does not
|
||||
bool bidIsSatisfied = newSimOwner.getID() == myNodeID &&
|
||||
(newSimOwner.getPriority() == _pendingOwnershipPriority ||
|
||||
(_pendingOwnershipPriority == VOLUNTEER_SIMULATION_PRIORITY &&
|
||||
newSimOwner.getPriority() == RECRUIT_SIMULATION_PRIORITY));
|
||||
|
||||
if (newSimOwner.getID().isNull()) {
|
||||
// the entity-server is trying to clear someone else's ownership
|
||||
// the entity-server is clearing someone else's ownership
|
||||
if (!_simulationOwner.isNull()) {
|
||||
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
|
||||
somethingChanged = true;
|
||||
_simulationOwner.clearCurrentOwner();
|
||||
}
|
||||
} else if (newSimOwner.getID() == myNodeID) {
|
||||
// the entity-server is awarding us ownership which is what we want
|
||||
_simulationOwner.set(newSimOwner);
|
||||
} else {
|
||||
if (newSimOwner.getID() != _simulationOwner.getID()) {
|
||||
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
|
||||
}
|
||||
if (_simulationOwner.set(newSimOwner)) {
|
||||
// the entity-server changed ownership
|
||||
somethingChanged = true;
|
||||
}
|
||||
}
|
||||
if (bidIsSatisfied || _pendingOwnershipTimestamp < now - maxPingRoundTrip) {
|
||||
// the bid has been satisfied, or it has been invalidated by data sent AFTER the bid should have been received
|
||||
// in either case: accept our fate and clear pending state
|
||||
_pendingOwnershipState = PENDING_STATE_NOTHING;
|
||||
_pendingOwnershipPriority = 0;
|
||||
}
|
||||
weOwnSimulation = bidIsSatisfied || (_simulationOwner.getID() == myNodeID);
|
||||
} else {
|
||||
// we are not waiting to take ownership
|
||||
if (newSimOwner.getID() != _simulationOwner.getID()) {
|
||||
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
|
||||
}
|
||||
if (_simulationOwner.set(newSimOwner)) {
|
||||
// the entity-server changed ownership...
|
||||
somethingChanged = true;
|
||||
if (newSimOwner.getID() == myNodeID) {
|
||||
// we have recieved ownership
|
||||
weOwnSimulation = true;
|
||||
// accept our fate and clear pendingState (just in case)
|
||||
_pendingOwnershipState = PENDING_STATE_NOTHING;
|
||||
_pendingOwnershipPriority = 0;
|
||||
}
|
||||
}
|
||||
} else if (newSimOwner.matchesValidID(myNodeID) && !_simulationOwner.pendingTake(now)) {
|
||||
// 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.
|
||||
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
|
||||
somethingChanged = true;
|
||||
_simulationOwner.clearCurrentOwner();
|
||||
weOwnSimulation = false;
|
||||
} else if (_simulationOwner.set(newSimOwner)) {
|
||||
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
|
||||
somethingChanged = true;
|
||||
// recompute weOwnSimulation for later
|
||||
weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1305,6 +1330,7 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c
|
|||
properties._accelerationChanged = true;
|
||||
}
|
||||
|
||||
/*
|
||||
void EntityItem::flagForOwnershipBid(uint8_t priority) {
|
||||
markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY);
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
@ -1316,6 +1342,40 @@ void EntityItem::flagForOwnershipBid(uint8_t priority) {
|
|||
_simulationOwner.setPendingPriority(priority, usecTimestampNow());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void EntityItem::setScriptSimulationPriority(uint8_t priority) {
|
||||
uint8_t newPriority = stillHasGrabActions() ? glm::max(priority, SCRIPT_GRAB_SIMULATION_PRIORITY) : priority;
|
||||
if (newPriority != _scriptSimulationPriority) {
|
||||
// set the dirty flag to trigger a bid or ownership update
|
||||
markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY);
|
||||
_scriptSimulationPriority = newPriority;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::clearScriptSimulationPriority() {
|
||||
// DO NOT markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY) here, because this
|
||||
// is only ever called from the code that actually handles the dirty flags, and it knows best.
|
||||
_scriptSimulationPriority = stillHasGrabActions() ? SCRIPT_GRAB_SIMULATION_PRIORITY : 0;
|
||||
}
|
||||
|
||||
void EntityItem::setPendingOwnershipPriority(uint8_t priority) {
|
||||
_pendingOwnershipTimestamp = usecTimestampNow();
|
||||
_pendingOwnershipPriority = priority;
|
||||
_pendingOwnershipState = (_pendingOwnershipPriority == 0) ? PENDING_STATE_RELEASE : PENDING_STATE_TAKE;
|
||||
}
|
||||
|
||||
bool EntityItem::pendingRelease(uint64_t timestamp) const {
|
||||
return _pendingOwnershipPriority == 0 &&
|
||||
_pendingOwnershipState == PENDING_STATE_RELEASE &&
|
||||
_pendingOwnershipTimestamp >= timestamp;
|
||||
}
|
||||
|
||||
bool EntityItem::stillWaitingToTakeOwnership(uint64_t timestamp) const {
|
||||
return _pendingOwnershipPriority > 0 &&
|
||||
_pendingOwnershipState == PENDING_STATE_TAKE &&
|
||||
_pendingOwnershipTimestamp >= timestamp;
|
||||
}
|
||||
|
||||
bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
||||
bool somethingChanged = false;
|
||||
|
@ -1941,10 +2001,6 @@ void EntityItem::clearSimulationOwnership() {
|
|||
|
||||
}
|
||||
|
||||
void EntityItem::setPendingOwnershipPriority(uint8_t priority, const quint64& timestamp) {
|
||||
_simulationOwner.setPendingPriority(priority, timestamp);
|
||||
}
|
||||
|
||||
QString EntityItem::actionsToDebugString() {
|
||||
QString result;
|
||||
QVector<QByteArray> serializedActions;
|
||||
|
@ -2040,6 +2096,7 @@ bool EntityItem::updateAction(EntitySimulationPointer simulation, const QUuid& a
|
|||
}
|
||||
|
||||
bool EntityItem::removeAction(EntitySimulationPointer simulation, const QUuid& actionID) {
|
||||
// TODO: some action
|
||||
bool success = false;
|
||||
withWriteLock([&] {
|
||||
checkWaitingToRemove(simulation);
|
||||
|
|
|
@ -308,14 +308,21 @@ public:
|
|||
const SimulationOwner& getSimulationOwner() const { return _simulationOwner; }
|
||||
void setSimulationOwner(const QUuid& id, uint8_t priority);
|
||||
void setSimulationOwner(const SimulationOwner& owner);
|
||||
void promoteSimulationPriority(uint8_t priority);
|
||||
|
||||
uint8_t getSimulationPriority() const { return _simulationOwner.getPriority(); }
|
||||
QUuid getSimulatorID() const { return _simulationOwner.getID(); }
|
||||
void clearSimulationOwnership();
|
||||
void setPendingOwnershipPriority(uint8_t priority, const quint64& timestamp);
|
||||
uint8_t getPendingOwnershipPriority() const { return _simulationOwner.getPendingPriority(); }
|
||||
void rememberHasSimulationOwnershipBid() const;
|
||||
|
||||
// TODO: move this "ScriptSimulationPriority" and "PendingOwnership" stuff into EntityMotionState
|
||||
// but first would need to do some other cleanup. In the meantime these live here as "scratch space"
|
||||
// to allow libs that don't know about each other to communicate.
|
||||
void setScriptSimulationPriority(uint8_t priority);
|
||||
void clearScriptSimulationPriority();
|
||||
uint8_t getScriptSimulationPriority() const { return _scriptSimulationPriority; }
|
||||
void setPendingOwnershipPriority(uint8_t priority);
|
||||
uint8_t getPendingOwnershipPriority() const { return _pendingOwnershipPriority; }
|
||||
bool pendingRelease(uint64_t timestamp) const;
|
||||
bool stillWaitingToTakeOwnership(uint64_t timestamp) const;
|
||||
|
||||
// Certifiable Properties
|
||||
QString getItemName() const;
|
||||
|
@ -395,7 +402,6 @@ public:
|
|||
|
||||
void getAllTerseUpdateProperties(EntityItemProperties& properties) const;
|
||||
|
||||
void flagForOwnershipBid(uint8_t priority);
|
||||
void flagForMotionStateChange() { _flags |= Simulation::DIRTY_MOTION_TYPE; }
|
||||
|
||||
QString actionsToDebugString();
|
||||
|
@ -654,6 +660,15 @@ protected:
|
|||
|
||||
float _boundingRadius { 0.0f };
|
||||
int32_t _spaceIndex { -1 }; // index to proxy in workload::Space
|
||||
|
||||
// TODO: move this "scriptSimulationPriority" and "pendingOwnership" stuff into EntityMotionState
|
||||
// but first would need to do some other cleanup. In the meantime these live here as "scratch space"
|
||||
// to allow libs that don't know about each other to communicate.
|
||||
uint64_t _pendingOwnershipTimestamp { 0 }; // timestamp of last owenership change request
|
||||
uint8_t _pendingOwnershipPriority { 0 }; // priority of last ownership change request
|
||||
uint8_t _pendingOwnershipState { 0 }; // TAKE or RELEASE
|
||||
uint8_t _scriptSimulationPriority { 0 }; // target priority based on script operations
|
||||
|
||||
bool _cauterized { false }; // if true, don't draw because it would obscure 1st-person camera
|
||||
|
||||
private:
|
||||
|
|
|
@ -327,7 +327,7 @@ public:
|
|||
void clearSimulationOwner();
|
||||
void setSimulationOwner(const QUuid& id, uint8_t priority);
|
||||
void setSimulationOwner(const QByteArray& data);
|
||||
void promoteSimulationPriority(uint8_t priority) { _simulationOwner.promotePriority(priority); }
|
||||
void setSimulationPriority(uint8_t priority) { _simulationOwner.setPriority(priority); }
|
||||
|
||||
void setActionDataDirty() { _actionDataChanged = true; }
|
||||
|
||||
|
|
|
@ -277,7 +277,7 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties
|
|||
|
||||
entity->setLastBroadcast(usecTimestampNow());
|
||||
// since we're creating this object we will immediately volunteer to own its simulation
|
||||
entity->flagForOwnershipBid(VOLUNTEER_SIMULATION_PRIORITY);
|
||||
entity->setScriptSimulationPriority(VOLUNTEER_SIMULATION_PRIORITY);
|
||||
propertiesWithSimID.setLastEdited(entity->getLastEdited());
|
||||
} else {
|
||||
qCDebug(entities) << "script failed to add new Entity to local Octree";
|
||||
|
@ -465,7 +465,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
|
|||
} else {
|
||||
// we make a bid for simulation ownership
|
||||
properties.setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY);
|
||||
entity->flagForOwnershipBid(SCRIPT_POKE_SIMULATION_PRIORITY);
|
||||
entity->setScriptSimulationPriority(SCRIPT_POKE_SIMULATION_PRIORITY);
|
||||
}
|
||||
}
|
||||
if (properties.queryAACubeRelatedPropertyChanged()) {
|
||||
|
@ -1334,7 +1334,7 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString,
|
|||
}
|
||||
action->setIsMine(true);
|
||||
success = entity->addAction(simulation, action);
|
||||
entity->flagForOwnershipBid(SCRIPT_GRAB_SIMULATION_PRIORITY);
|
||||
entity->setScriptSimulationPriority(SCRIPT_GRAB_SIMULATION_PRIORITY);
|
||||
return false; // Physics will cause a packet to be sent, so don't send from here.
|
||||
});
|
||||
if (success) {
|
||||
|
@ -1350,7 +1350,7 @@ bool EntityScriptingInterface::updateAction(const QUuid& entityID, const QUuid&
|
|||
return actionWorker(entityID, [&](EntitySimulationPointer simulation, EntityItemPointer entity) {
|
||||
bool success = entity->updateAction(simulation, actionID, arguments);
|
||||
if (success) {
|
||||
entity->flagForOwnershipBid(SCRIPT_GRAB_SIMULATION_PRIORITY);
|
||||
entity->setScriptSimulationPriority(SCRIPT_GRAB_SIMULATION_PRIORITY);
|
||||
}
|
||||
return success;
|
||||
});
|
||||
|
@ -1364,7 +1364,7 @@ bool EntityScriptingInterface::deleteAction(const QUuid& entityID, const QUuid&
|
|||
success = entity->removeAction(simulation, actionID);
|
||||
if (success) {
|
||||
// reduce from grab to poke
|
||||
entity->flagForOwnershipBid(SCRIPT_POKE_SIMULATION_PRIORITY);
|
||||
entity->setScriptSimulationPriority(SCRIPT_POKE_SIMULATION_PRIORITY);
|
||||
}
|
||||
return false; // Physics will cause a packet to be sent, so don't send from here.
|
||||
});
|
||||
|
|
|
@ -16,29 +16,20 @@
|
|||
|
||||
#include <NumericalConstants.h>
|
||||
|
||||
const uint8_t PENDING_STATE_NOTHING = 0;
|
||||
const uint8_t PENDING_STATE_TAKE = 1;
|
||||
const uint8_t PENDING_STATE_RELEASE = 2;
|
||||
|
||||
// static
|
||||
const int SimulationOwner::NUM_BYTES_ENCODED = NUM_BYTES_RFC4122_UUID + 1;
|
||||
|
||||
SimulationOwner::SimulationOwner() :
|
||||
_id(),
|
||||
_expiry(0),
|
||||
_pendingBidTimestamp(0),
|
||||
_priority(0),
|
||||
_pendingBidPriority(0),
|
||||
_pendingState(PENDING_STATE_NOTHING)
|
||||
_priority(0)
|
||||
{
|
||||
}
|
||||
|
||||
SimulationOwner::SimulationOwner(const QUuid& id, uint8_t priority) :
|
||||
_id(id),
|
||||
_expiry(0),
|
||||
_pendingBidTimestamp(0),
|
||||
_priority(priority),
|
||||
_pendingBidPriority(0)
|
||||
_priority(priority)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -61,22 +52,13 @@ bool SimulationOwner::fromByteArray(const QByteArray& data) {
|
|||
void SimulationOwner::clear() {
|
||||
_id = QUuid();
|
||||
_expiry = 0;
|
||||
_pendingBidTimestamp = 0;
|
||||
_priority = 0;
|
||||
_pendingBidPriority = 0;
|
||||
_pendingState = PENDING_STATE_NOTHING;
|
||||
}
|
||||
|
||||
void SimulationOwner::setPriority(uint8_t priority) {
|
||||
_priority = priority;
|
||||
}
|
||||
|
||||
void SimulationOwner::promotePriority(uint8_t priority) {
|
||||
if (priority > _priority) {
|
||||
_priority = priority;
|
||||
}
|
||||
}
|
||||
|
||||
bool SimulationOwner::setID(const QUuid& id) {
|
||||
if (_id != id) {
|
||||
_id = id;
|
||||
|
@ -101,25 +83,11 @@ bool SimulationOwner::set(const SimulationOwner& owner) {
|
|||
return setID(owner._id) || oldPriority != _priority;
|
||||
}
|
||||
|
||||
void SimulationOwner::setPendingPriority(uint8_t priority, uint64_t timestamp) {
|
||||
_pendingBidPriority = priority;
|
||||
_pendingBidTimestamp = timestamp;
|
||||
_pendingState = (_pendingBidPriority == 0) ? PENDING_STATE_RELEASE : PENDING_STATE_TAKE;
|
||||
}
|
||||
|
||||
void SimulationOwner::updateExpiry() {
|
||||
const uint64_t OWNERSHIP_LOCKOUT_EXPIRY = 200 * USECS_PER_MSEC;
|
||||
_expiry = usecTimestampNow() + OWNERSHIP_LOCKOUT_EXPIRY;
|
||||
}
|
||||
|
||||
bool SimulationOwner::pendingRelease(uint64_t timestamp) {
|
||||
return _pendingBidPriority == 0 && _pendingState == PENDING_STATE_RELEASE && _pendingBidTimestamp >= timestamp;
|
||||
}
|
||||
|
||||
bool SimulationOwner::pendingTake(uint64_t timestamp) {
|
||||
return _pendingBidPriority > 0 && _pendingState == PENDING_STATE_TAKE && _pendingBidTimestamp >= timestamp;
|
||||
}
|
||||
|
||||
void SimulationOwner::clearCurrentOwner() {
|
||||
_id = QUuid();
|
||||
_expiry = 0;
|
||||
|
|
|
@ -120,24 +120,18 @@ public:
|
|||
void clear();
|
||||
|
||||
void setPriority(uint8_t priority);
|
||||
void promotePriority(uint8_t priority);
|
||||
|
||||
// return true if id is changed
|
||||
bool setID(const QUuid& id);
|
||||
bool set(const QUuid& id, uint8_t priority);
|
||||
bool set(const SimulationOwner& owner);
|
||||
void setPendingPriority(uint8_t priority, uint64_t timestamp);
|
||||
|
||||
bool isNull() const { return _id.isNull(); }
|
||||
bool matchesValidID(const QUuid& id) const { return _id == id && !_id.isNull(); }
|
||||
|
||||
void updateExpiry();
|
||||
|
||||
bool hasExpired() const { return usecTimestampNow() > _expiry; }
|
||||
|
||||
uint8_t getPendingPriority() const { return _pendingBidPriority; }
|
||||
bool pendingRelease(uint64_t timestamp); // return true if valid pending RELEASE
|
||||
bool pendingTake(uint64_t timestamp); // return true if valid pending TAKE
|
||||
void clearCurrentOwner();
|
||||
|
||||
bool operator>=(uint8_t priority) const { return _priority >= priority; }
|
||||
|
@ -154,10 +148,7 @@ public:
|
|||
private:
|
||||
QUuid _id; // owner
|
||||
uint64_t _expiry; // time when ownership can transition at equal priority
|
||||
uint64_t _pendingBidTimestamp; // time when pending bid was set
|
||||
uint8_t _priority; // priority of current owner
|
||||
uint8_t _pendingBidPriority; // priority at which we'd like to own it
|
||||
uint8_t _pendingState; // NOTHING, TAKE, or RELEASE
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -79,7 +79,6 @@ EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItemPointer
|
|||
// rather than pass the legit shape pointer to the ObjectMotionState ctor above.
|
||||
setShape(shape);
|
||||
|
||||
_bidPriority = _entity->getPendingOwnershipPriority();
|
||||
if (_entity->getClientOnly() && _entity->getOwningAvatarID() != Physics::getSessionUUID()) {
|
||||
// client-only entities are always thus, so we cache this fact in _ownershipState
|
||||
_ownershipState = EntityMotionState::OwnershipState::Unownable;
|
||||
|
@ -140,30 +139,21 @@ void EntityMotionState::handleEasyChanges(uint32_t& flags) {
|
|||
// simulation ownership has been removed
|
||||
if (glm::length2(_entity->getWorldVelocity()) == 0.0f) {
|
||||
// TODO: also check angularVelocity
|
||||
// this object is coming to rest --> clear the ACTIVATION flag and _bidPriority
|
||||
// this object is coming to rest
|
||||
flags &= ~Simulation::DIRTY_PHYSICS_ACTIVATION;
|
||||
_body->setActivationState(WANTS_DEACTIVATION);
|
||||
_bidPriority = 0;
|
||||
const float ACTIVATION_EXPIRY = 3.0f; // something larger than the 2.0 hard coded in Bullet
|
||||
_body->setDeactivationTime(ACTIVATION_EXPIRY);
|
||||
} else {
|
||||
// disowned object is still moving --> start timer for ownership bid
|
||||
// TODO? put a delay in here proportional to distance from object?
|
||||
computeNewBidPriority(VOLUNTEER_SIMULATION_PRIORITY);
|
||||
_bumpedPriority = glm::max(_bumpedPriority, VOLUNTEER_SIMULATION_PRIORITY);
|
||||
_nextBidExpiry = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS;
|
||||
}
|
||||
_loopsWithoutOwner = 0;
|
||||
_numInactiveUpdates = 0;
|
||||
} else if (isLocallyOwned()) {
|
||||
// we just received ownership, or the priority of our existing ownership has changed
|
||||
computeNewBidPriority(_entity->getSimulationPriority());
|
||||
} else {
|
||||
} else if (!isLocallyOwned()) {
|
||||
// the entity is owned by someone else
|
||||
// we are always willing to volunteer for nearby objects
|
||||
// otherwise we zero _bidPriority here
|
||||
// (it's possible _bidPriority will be promoted in subsequent frames
|
||||
// when local scripts or owned simulation interact with it)
|
||||
_bidPriority = (_region == workload::Region::R1) ? VOLUNTEER_SIMULATION_PRIORITY : 0;
|
||||
_nextBidExpiry = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS;
|
||||
_numInactiveUpdates = 0;
|
||||
}
|
||||
|
@ -172,9 +162,6 @@ void EntityMotionState::handleEasyChanges(uint32_t& flags) {
|
|||
// The DIRTY_SIMULATOR_OWNERSHIP_PRIORITY bit means one of the following:
|
||||
// (1) we own it but may need to change the priority OR...
|
||||
// (2) we don't own it but should bid (because a local script has been changing physics properties)
|
||||
uint8_t newPriority = isLocallyOwned() ? _entity->getSimulationOwner().getPriority() : _entity->getSimulationOwner().getPendingPriority();
|
||||
computeNewBidPriority(newPriority);
|
||||
|
||||
// reset bid expiry so that we bid ASAP
|
||||
_nextBidExpiry = 0;
|
||||
}
|
||||
|
@ -302,7 +289,7 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
|
|||
if (_entity->getSimulatorID().isNull()) {
|
||||
_loopsWithoutOwner++;
|
||||
if (_loopsWithoutOwner > LOOPS_FOR_SIMULATION_ORPHAN && usecTimestampNow() > _nextBidExpiry) {
|
||||
computeNewBidPriority(VOLUNTEER_SIMULATION_PRIORITY);
|
||||
_bumpedPriority = glm::max(_bumpedPriority, VOLUNTEER_SIMULATION_PRIORITY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -338,11 +325,8 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
|||
// WIP: print info whenever _bidPriority mismatches what is known to the entity
|
||||
|
||||
if (_entity->dynamicDataNeedsTransmit()) {
|
||||
uint8_t priority = _entity->hasActions() ? SCRIPT_GRAB_SIMULATION_PRIORITY : SCRIPT_POKE_SIMULATION_PRIORITY;
|
||||
computeNewBidPriority(priority);
|
||||
return true;
|
||||
}
|
||||
computeNewBidPriority(_entity->getSimulationPriority());
|
||||
|
||||
bool parentTransformSuccess;
|
||||
Transform localToWorld = _entity->getParentTransform(parentTransformSuccess);
|
||||
|
@ -470,6 +454,7 @@ void EntityMotionState::updateSendVelocities() {
|
|||
if (!_body->isActive()) {
|
||||
// make sure all derivatives are zero
|
||||
clearObjectVelocities();
|
||||
// we pretend we sent the inactive update for this object
|
||||
_numInactiveUpdates = 1;
|
||||
} else {
|
||||
glm::vec3 gravity = _entity->getGravity();
|
||||
|
@ -534,10 +519,10 @@ void EntityMotionState::sendBid(OctreeEditPacketSender* packetSender, uint32_t s
|
|||
properties.setLastEdited(now);
|
||||
|
||||
// we don't own the simulation for this entity yet, but we're sending a bid for it
|
||||
uint8_t bidPriority = glm::max<uint8_t>(_bidPriority, VOLUNTEER_SIMULATION_PRIORITY);
|
||||
properties.setSimulationOwner(Physics::getSessionUUID(), bidPriority);
|
||||
// copy _bidPriority into pendingPriority...
|
||||
_entity->setPendingOwnershipPriority(_bidPriority, now);
|
||||
uint8_t finalBidPriority = computeFinalBidPriority();
|
||||
_entity->clearScriptSimulationPriority();
|
||||
properties.setSimulationOwner(Physics::getSessionUUID(), finalBidPriority);
|
||||
_entity->setPendingOwnershipPriority(finalBidPriority);
|
||||
|
||||
EntityTreeElementPointer element = _entity->getElement();
|
||||
EntityTreePointer tree = element ? element->getTree() : nullptr;
|
||||
|
@ -556,10 +541,10 @@ void EntityMotionState::sendBid(OctreeEditPacketSender* packetSender, uint32_t s
|
|||
_lastStep = step;
|
||||
_nextBidExpiry = now + USECS_BETWEEN_OWNERSHIP_BIDS;
|
||||
|
||||
// after sending the bid we try to clear _bidPriority
|
||||
// after sending a bid/update we clear _bumpedPriority
|
||||
// which might get promoted again next frame (after local script or simulation interaction)
|
||||
// or we might win the bid
|
||||
computeNewBidPriority(0);
|
||||
_bumpedPriority = 0;
|
||||
}
|
||||
|
||||
void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_t step) {
|
||||
|
@ -598,22 +583,26 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
|
|||
properties.setLastEdited(now);
|
||||
_entity->setSimulationOwnershipExpiry(now + MAX_OUTGOING_SIMULATION_UPDATE_PERIOD);
|
||||
|
||||
if (_numInactiveUpdates > 0) {
|
||||
if (_numInactiveUpdates > 0 && _entity->getScriptSimulationPriority() == 0) {
|
||||
// the entity is stopped and inactive so we tell the server we're clearing simulatorID
|
||||
// but we remember we do still own it... and rely on the server to tell us we don't
|
||||
properties.clearSimulationOwner();
|
||||
_bidPriority = 0;
|
||||
_entity->setPendingOwnershipPriority(_bidPriority, now);
|
||||
} else if (_bidPriority != _entity->getSimulationPriority()) {
|
||||
// our desired priority has changed
|
||||
if (_bidPriority == 0) {
|
||||
// we should release ownership
|
||||
properties.clearSimulationOwner();
|
||||
} else {
|
||||
// we just need to change the priority
|
||||
properties.setSimulationOwner(Physics::getSessionUUID(), _bidPriority);
|
||||
_entity->setPendingOwnershipPriority(0);
|
||||
} else {
|
||||
uint8_t finalBidPriority = computeFinalBidPriority();
|
||||
_entity->clearScriptSimulationPriority();
|
||||
if (finalBidPriority != _entity->getSimulationPriority() &&
|
||||
!(finalBidPriority == VOLUNTEER_SIMULATION_PRIORITY && _entity->getSimulationPriority() == RECRUIT_SIMULATION_PRIORITY)) {
|
||||
// our desired priority has changed
|
||||
if (finalBidPriority == 0) {
|
||||
// we should release ownership
|
||||
properties.clearSimulationOwner();
|
||||
} else {
|
||||
// we just need to change the priority
|
||||
properties.setSimulationOwner(Physics::getSessionUUID(), finalBidPriority);
|
||||
}
|
||||
_entity->setPendingOwnershipPriority(finalBidPriority);
|
||||
}
|
||||
_entity->setPendingOwnershipPriority(_bidPriority, now);
|
||||
}
|
||||
|
||||
EntityItemID id(_entity->getID());
|
||||
|
@ -648,6 +637,11 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
|
|||
});
|
||||
|
||||
_lastStep = step;
|
||||
|
||||
// after sending a bid/update we clear _bumpedPriority
|
||||
// which might get promoted again next frame (after local script or simulation interaction)
|
||||
// or we might win the bid
|
||||
_bumpedPriority = 0;
|
||||
}
|
||||
|
||||
uint32_t EntityMotionState::getIncomingDirtyFlags() {
|
||||
|
@ -694,7 +688,7 @@ uint8_t EntityMotionState::getSimulationPriority() const {
|
|||
}
|
||||
|
||||
void EntityMotionState::slaveBidPriority() {
|
||||
computeNewBidPriority(_entity->getSimulationPriority());
|
||||
_bumpedPriority = glm::max(_bumpedPriority, _entity->getSimulationPriority());
|
||||
}
|
||||
|
||||
// virtual
|
||||
|
@ -705,7 +699,7 @@ QUuid EntityMotionState::getSimulatorID() const {
|
|||
|
||||
void EntityMotionState::bump(uint8_t priority) {
|
||||
assert(priority != 0);
|
||||
computeNewBidPriority(glm::max(VOLUNTEER_SIMULATION_PRIORITY, --priority));
|
||||
_bumpedPriority = glm::max(_bumpedPriority, --priority);
|
||||
}
|
||||
|
||||
void EntityMotionState::resetMeasuredBodyAcceleration() {
|
||||
|
@ -771,7 +765,6 @@ void EntityMotionState::setMotionType(PhysicsMotionType motionType) {
|
|||
resetMeasuredBodyAcceleration();
|
||||
}
|
||||
|
||||
|
||||
// virtual
|
||||
QString EntityMotionState::getName() const {
|
||||
assert(entityTreeIsLocked());
|
||||
|
@ -784,15 +777,14 @@ void EntityMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& ma
|
|||
}
|
||||
|
||||
bool EntityMotionState::shouldSendBid() {
|
||||
// NOTE: this method is only ever called when the entity simulation is NOT locally owned
|
||||
if (_bidPriority > glm::max(_entity->getSimulationPriority(), YIELD_SIMULATION_PRIORITY)) {
|
||||
return true;
|
||||
} else {
|
||||
// NOTE: this 'else' case has a side-effect: it clears _bidPriority
|
||||
// which might get promoted again next frame (after local script or simulation interaction)
|
||||
_bidPriority = 0;
|
||||
return false;
|
||||
}
|
||||
// NOTE: this method is only ever called when the entity's simulation is NOT locally owned
|
||||
return _body->isActive() && (_region == workload::Region::R1) &&
|
||||
glm::max(glm::max(VOLUNTEER_SIMULATION_PRIORITY, _bumpedPriority), _entity->getScriptSimulationPriority()) >= _entity->getSimulationPriority();
|
||||
}
|
||||
|
||||
uint8_t EntityMotionState::computeFinalBidPriority() const {
|
||||
return (_region == workload::Region::R1) ?
|
||||
glm::max(glm::max(VOLUNTEER_SIMULATION_PRIORITY, _bumpedPriority), _entity->getScriptSimulationPriority()) : 0;
|
||||
}
|
||||
|
||||
bool EntityMotionState::isLocallyOwned() const {
|
||||
|
@ -802,15 +794,15 @@ bool EntityMotionState::isLocallyOwned() const {
|
|||
bool EntityMotionState::isLocallyOwnedOrShouldBe() const {
|
||||
// this method could also be called "shouldGenerateCollisionEventForLocalScripts()"
|
||||
// because that is the only reason it's used
|
||||
return (_bidPriority > VOLUNTEER_SIMULATION_PRIORITY && _bidPriority >= _entity->getSimulationPriority()) ||
|
||||
_entity->getSimulatorID() == Physics::getSessionUUID();
|
||||
if (_entity->getSimulatorID() == Physics::getSessionUUID()) {
|
||||
return true;
|
||||
} else {
|
||||
return computeFinalBidPriority() > glm::max(VOLUNTEER_SIMULATION_PRIORITY, _entity->getSimulationPriority());
|
||||
}
|
||||
}
|
||||
|
||||
void EntityMotionState::setRegion(uint8_t region) {
|
||||
_region = region;
|
||||
if (_region == workload::Region::R1 && _bidPriority < VOLUNTEER_SIMULATION_PRIORITY && !isLocallyOwned()) {
|
||||
_bidPriority = VOLUNTEER_SIMULATION_PRIORITY;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityMotionState::initForBid() {
|
||||
|
@ -823,14 +815,6 @@ void EntityMotionState::initForOwned() {
|
|||
_ownershipState = EntityMotionState::OwnershipState::LocallyOwned;
|
||||
}
|
||||
|
||||
void EntityMotionState::computeNewBidPriority(uint8_t newPriority) {
|
||||
if (_region == workload::Region::R1) {
|
||||
_bidPriority = glm::max<uint8_t>(VOLUNTEER_SIMULATION_PRIORITY, glm::max<uint8_t>(_bidPriority, newPriority));
|
||||
} else {
|
||||
_bidPriority = glm::min<uint8_t>(YIELD_SIMULATION_PRIORITY, newPriority);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityMotionState::clearObjectVelocities() const {
|
||||
// If transform or velocities are flagged as dirty it means a network or scripted change
|
||||
// occured between the beginning and end of the stepSimulation() and we DON'T want to apply
|
||||
|
|
|
@ -88,6 +88,8 @@ public:
|
|||
virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override;
|
||||
|
||||
bool shouldSendBid();
|
||||
uint8_t computeFinalBidPriority() const;
|
||||
|
||||
bool isLocallyOwned() const override;
|
||||
bool isLocallyOwnedOrShouldBe() const override; // aka shouldEmitCollisionEvents()
|
||||
|
||||
|
@ -105,9 +107,6 @@ protected:
|
|||
void updateServerPhysicsVariables();
|
||||
bool remoteSimulationOutOfSync(uint32_t simulationStep);
|
||||
|
||||
// computes _bidPriority using newPriority and special case rules
|
||||
void computeNewBidPriority(uint8_t newPriority);
|
||||
|
||||
void slaveBidPriority(); // computeNewBidPriority() with value stored in _entity
|
||||
|
||||
void clearObjectVelocities() const;
|
||||
|
@ -156,7 +155,7 @@ protected:
|
|||
uint8_t _loopsWithoutOwner;
|
||||
mutable uint8_t _accelerationNearlyGravityCount;
|
||||
uint8_t _numInactiveUpdates { 1 };
|
||||
uint8_t _bidPriority { 0 };
|
||||
uint8_t _bumpedPriority { 0 }; // the target simulation priority according to collision history
|
||||
uint8_t _region { workload::Region::INVALID };
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue