mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 04:12:46 +02:00
Merge pull request #10696 from AndrewMeadows/avoid-ownership-bid-race
ignore remote update younger than recent ownership bid
This commit is contained in:
commit
428dc81083
3 changed files with 43 additions and 25 deletions
|
@ -386,7 +386,13 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 clockSkew = args.sourceNode ? args.sourceNode->getClockSkewUsec() : 0;
|
int64_t clockSkew = 0;
|
||||||
|
uint64_t maxPingRoundTrip = 33333; // two frames periods at 60 fps
|
||||||
|
if (args.sourceNode) {
|
||||||
|
clockSkew = args.sourceNode->getClockSkewUsec();
|
||||||
|
const float MSECS_PER_USEC = 1000;
|
||||||
|
maxPingRoundTrip += args.sourceNode->getPingMs() * MSECS_PER_USEC;
|
||||||
|
}
|
||||||
|
|
||||||
BufferParser parser(data, bytesLeftToRead);
|
BufferParser parser(data, bytesLeftToRead);
|
||||||
|
|
||||||
|
@ -653,7 +659,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
const QUuid& myNodeID = nodeList->getSessionUUID();
|
const QUuid& myNodeID = nodeList->getSessionUUID();
|
||||||
bool weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
|
bool weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
|
||||||
|
|
||||||
|
|
||||||
// pack SimulationOwner and terse update properties near each other
|
// pack SimulationOwner and terse update properties near each other
|
||||||
// NOTE: the server is authoritative for changes to simOwnerID so we always unpack ownership data
|
// NOTE: the server is authoritative for changes to simOwnerID so we always unpack ownership data
|
||||||
// even when we would otherwise ignore the rest of the packet.
|
// even when we would otherwise ignore the rest of the packet.
|
||||||
|
@ -678,7 +683,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
if (newSimOwner.getID().isNull() && !_simulationOwner.pendingRelease(lastEditedFromBufferAdjusted)) {
|
if (newSimOwner.getID().isNull() && !_simulationOwner.pendingRelease(lastEditedFromBufferAdjusted)) {
|
||||||
// entity-server is trying to clear our ownership (probably at our own request)
|
// 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
|
// but we actually want to own it, therefore we ignore this clear event
|
||||||
// and pretend that we own it (we assume we'll recover it soon)
|
// and pretend that we own it (e.g. we assume we'll receive ownership soon)
|
||||||
|
|
||||||
// However, for now, when the server uses a newer time than what we sent, listen to what we're told.
|
// However, for now, when the server uses a newer time than what we sent, listen to what we're told.
|
||||||
if (overwriteLocalData) {
|
if (overwriteLocalData) {
|
||||||
|
@ -690,16 +695,19 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
// recompute weOwnSimulation for later
|
// recompute weOwnSimulation for later
|
||||||
weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
|
weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
|
||||||
}
|
}
|
||||||
} else if (newSimOwner.getID().isNull() && _simulationOwner.pendingTake(lastEditedFromBufferAdjusted)) {
|
} else if (_simulationOwner.pendingTake(now - maxPingRoundTrip)) {
|
||||||
// entity-server is trying to clear someone else's ownership
|
// we sent a bid before this packet could have been sent from the server
|
||||||
// but we want to own it, therefore we ignore this clear event
|
// so we ignore it and pretend we own the object's simulation
|
||||||
// and pretend that we own it (we assume we'll get it soon)
|
|
||||||
weOwnSimulation = true;
|
weOwnSimulation = true;
|
||||||
if (!_simulationOwner.isNull()) {
|
if (newSimOwner.getID().isNull()) {
|
||||||
// someone else really did own it
|
// entity-server is trying to clear someone else's ownership
|
||||||
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
|
// but we want to own it, therefore we ignore this clear event
|
||||||
somethingChanged = true;
|
if (!_simulationOwner.isNull()) {
|
||||||
_simulationOwner.clearCurrentOwner();
|
// someone else really did own it
|
||||||
|
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
|
||||||
|
somethingChanged = true;
|
||||||
|
_simulationOwner.clearCurrentOwner();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (newSimOwner.matchesValidID(myNodeID) && !_hasBidOnSimulation) {
|
} else if (newSimOwner.matchesValidID(myNodeID) && !_hasBidOnSimulation) {
|
||||||
// entity-server tells us that we have simulation ownership while we never requested this for this EntityItem,
|
// entity-server tells us that we have simulation ownership while we never requested this for this EntityItem,
|
||||||
|
|
|
@ -23,14 +23,16 @@ const uint16_t ObjectActionTractor::tractorVersion = 1;
|
||||||
|
|
||||||
ObjectActionTractor::ObjectActionTractor(const QUuid& id, EntityItemPointer ownerEntity) :
|
ObjectActionTractor::ObjectActionTractor(const QUuid& id, EntityItemPointer ownerEntity) :
|
||||||
ObjectAction(DYNAMIC_TYPE_TRACTOR, id, ownerEntity),
|
ObjectAction(DYNAMIC_TYPE_TRACTOR, id, ownerEntity),
|
||||||
_positionalTarget(glm::vec3(0.0f)),
|
_positionalTarget(0.0f),
|
||||||
_desiredPositionalTarget(glm::vec3(0.0f)),
|
_desiredPositionalTarget(0.0f),
|
||||||
_linearTimeScale(FLT_MAX),
|
_linearTimeScale(FLT_MAX),
|
||||||
_positionalTargetSet(true),
|
_positionalTargetSet(false),
|
||||||
_rotationalTarget(glm::quat()),
|
_rotationalTarget(),
|
||||||
_desiredRotationalTarget(glm::quat()),
|
_desiredRotationalTarget(),
|
||||||
_angularTimeScale(FLT_MAX),
|
_angularTimeScale(FLT_MAX),
|
||||||
_rotationalTargetSet(true) {
|
_rotationalTargetSet(true),
|
||||||
|
_linearVelocityTarget(0.0f)
|
||||||
|
{
|
||||||
#if WANT_DEBUG
|
#if WANT_DEBUG
|
||||||
qCDebug(physics) << "ObjectActionTractor::ObjectActionTractor";
|
qCDebug(physics) << "ObjectActionTractor::ObjectActionTractor";
|
||||||
#endif
|
#endif
|
||||||
|
@ -77,7 +79,6 @@ bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) {
|
||||||
|
|
||||||
glm::quat rotation;
|
glm::quat rotation;
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
glm::vec3 linearVelocity;
|
|
||||||
glm::vec3 angularVelocity;
|
glm::vec3 angularVelocity;
|
||||||
|
|
||||||
bool linearValid = false;
|
bool linearValid = false;
|
||||||
|
@ -117,7 +118,6 @@ bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) {
|
||||||
linearValid = true;
|
linearValid = true;
|
||||||
linearTractorCount++;
|
linearTractorCount++;
|
||||||
position += positionForAction;
|
position += positionForAction;
|
||||||
linearVelocity += linearVelocityForAction;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,9 +126,18 @@ bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) {
|
||||||
withWriteLock([&]{
|
withWriteLock([&]{
|
||||||
if (linearValid && linearTractorCount > 0) {
|
if (linearValid && linearTractorCount > 0) {
|
||||||
position /= linearTractorCount;
|
position /= linearTractorCount;
|
||||||
linearVelocity /= linearTractorCount;
|
if (_positionalTargetSet) {
|
||||||
|
_lastPositionTarget = _positionalTarget;
|
||||||
|
} else {
|
||||||
|
_lastPositionTarget = position;
|
||||||
|
}
|
||||||
_positionalTarget = position;
|
_positionalTarget = position;
|
||||||
_linearVelocityTarget = linearVelocity;
|
if (deltaTimeStep > EPSILON) {
|
||||||
|
// blend the new velocity with the old (low-pass filter)
|
||||||
|
glm::vec3 newVelocity = (1.0f / deltaTimeStep) * (position - _lastPositionTarget);
|
||||||
|
const float blend = 0.25f;
|
||||||
|
_linearVelocityTarget = (1.0f - blend) * _linearVelocityTarget + blend * newVelocity;
|
||||||
|
}
|
||||||
_positionalTargetSet = true;
|
_positionalTargetSet = true;
|
||||||
_active = true;
|
_active = true;
|
||||||
}
|
}
|
||||||
|
@ -169,19 +178,19 @@ void ObjectActionTractor::updateActionWorker(btScalar deltaTimeStep) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_linearTimeScale < MAX_TRACTOR_TIMESCALE) {
|
if (_linearTimeScale < MAX_TRACTOR_TIMESCALE) {
|
||||||
btVector3 targetVelocity(0.0f, 0.0f, 0.0f);
|
btVector3 offsetVelocity(0.0f, 0.0f, 0.0f);
|
||||||
btVector3 offset = rigidBody->getCenterOfMassPosition() - glmToBullet(_positionalTarget);
|
btVector3 offset = rigidBody->getCenterOfMassPosition() - glmToBullet(_positionalTarget);
|
||||||
float offsetLength = offset.length();
|
float offsetLength = offset.length();
|
||||||
if (offsetLength > FLT_EPSILON) {
|
if (offsetLength > FLT_EPSILON) {
|
||||||
float speed = glm::min(offsetLength / _linearTimeScale, TRACTOR_MAX_SPEED);
|
float speed = glm::min(offsetLength / _linearTimeScale, TRACTOR_MAX_SPEED);
|
||||||
targetVelocity = (-speed / offsetLength) * offset;
|
offsetVelocity = (-speed / offsetLength) * offset;
|
||||||
if (speed > rigidBody->getLinearSleepingThreshold()) {
|
if (speed > rigidBody->getLinearSleepingThreshold()) {
|
||||||
forceBodyNonStatic();
|
forceBodyNonStatic();
|
||||||
rigidBody->activate();
|
rigidBody->activate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// this action is aggresively critically damped and defeats the current velocity
|
// this action is aggresively critically damped and defeats the current velocity
|
||||||
rigidBody->setLinearVelocity(targetVelocity);
|
rigidBody->setLinearVelocity(glmToBullet(_linearVelocityTarget) + offsetVelocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_angularTimeScale < MAX_TRACTOR_TIMESCALE) {
|
if (_angularTimeScale < MAX_TRACTOR_TIMESCALE) {
|
||||||
|
|
|
@ -36,6 +36,7 @@ protected:
|
||||||
|
|
||||||
glm::vec3 _positionalTarget;
|
glm::vec3 _positionalTarget;
|
||||||
glm::vec3 _desiredPositionalTarget;
|
glm::vec3 _desiredPositionalTarget;
|
||||||
|
glm::vec3 _lastPositionTarget;
|
||||||
float _linearTimeScale;
|
float _linearTimeScale;
|
||||||
bool _positionalTargetSet;
|
bool _positionalTargetSet;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue