This commit is contained in:
Andrzej Kapolka 2014-11-03 14:01:08 -08:00
commit ce3133b8d4
3 changed files with 65 additions and 37 deletions

View file

@ -50,6 +50,7 @@ DomainServer::DomainServer(int argc, char* argv[]) :
_hostname(),
_webAuthenticationStateSet(),
_cookieSessionHash(),
_automaticNetworkingSetting(),
_settingsManager()
{
LogUtils::init();
@ -327,17 +328,17 @@ void DomainServer::setupAutomaticNetworking() {
return;
}
QString automaticNetworkValue =
_automaticNetworkingSetting =
_settingsManager.valueOrDefaultValueForKeyPath(METAVERSE_AUTOMATIC_NETWORKING_KEY_PATH).toString();
if (automaticNetworkValue == IP_ONLY_AUTOMATIC_NETWORKING_VALUE ||
automaticNetworkValue == FULL_AUTOMATIC_NETWORKING_VALUE) {
if (_automaticNetworkingSetting == IP_ONLY_AUTOMATIC_NETWORKING_VALUE ||
_automaticNetworkingSetting == FULL_AUTOMATIC_NETWORKING_VALUE) {
LimitedNodeList* nodeList = LimitedNodeList::getInstance();
const QUuid& domainID = nodeList->getSessionUUID();
if (!domainID.isNull()) {
qDebug() << "domain-server" << automaticNetworkValue << "automatic networking enabled for ID"
qDebug() << "domain-server" << _automaticNetworkingSetting << "automatic networking enabled for ID"
<< uuidStringWithoutCurlyBraces(domainID) << "via" << _oauthProviderURL.toString();
const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 30 * 1000;
@ -347,7 +348,7 @@ void DomainServer::setupAutomaticNetworking() {
QTimer* dynamicIPTimer = new QTimer(this);
connect(dynamicIPTimer, &QTimer::timeout, this, &DomainServer::requestCurrentPublicSocketViaSTUN);
if (automaticNetworkValue == IP_ONLY_AUTOMATIC_NETWORKING_VALUE) {
if (_automaticNetworkingSetting == IP_ONLY_AUTOMATIC_NETWORKING_VALUE) {
dynamicIPTimer->start(STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS);
// send public socket changes to the data server so nodes can find us at our new IP
@ -361,11 +362,11 @@ void DomainServer::setupAutomaticNetworking() {
iceHeartbeatTimer->start(ICE_HEARBEAT_INTERVAL_MSECS);
// call our sendHeartbeaToIceServer immediately anytime a local or public socket changes
connect(nodeList, &LimitedNodeList::localSockAddrChanged, this, &DomainServer::sendHearbeatToIceServer);
connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::sendHearbeatToIceServer);
connect(nodeList, &LimitedNodeList::localSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer);
connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer);
// tell the data server which type of automatic networking we are using
updateNetworkingInfoWithDataServer(automaticNetworkValue);
// send our heartbeat to data server so it knows what our network settings are
sendHeartbeatToDataServer();
}
// attempt to update our sockets now
@ -378,8 +379,17 @@ void DomainServer::setupAutomaticNetworking() {
return;
}
} else {
updateNetworkingInfoWithDataServer(automaticNetworkValue);
sendHeartbeatToDataServer();
}
qDebug() << "Updating automatic networking setting in domain-server to" << _automaticNetworkingSetting;
// no matter the auto networking settings we should heartbeat to the data-server every 15s
const int DOMAIN_SERVER_DATA_WEB_HEARTBEAT_MSECS = 15 * 1000;
QTimer* dataHeartbeatTimer = new QTimer(this);
connect(dataHeartbeatTimer, &QTimer::timeout, this, &DomainServer::sendHeartbeatToDataServer);
dataHeartbeatTimer->start(DOMAIN_SERVER_DATA_WEB_HEARTBEAT_MSECS);
}
void DomainServer::loginFailed() {
@ -1081,10 +1091,10 @@ QJsonObject jsonForDomainSocketUpdate(const HifiSockAddr& socket) {
const QString DOMAIN_UPDATE_AUTOMATIC_NETWORKING_KEY = "automatic_networking";
void DomainServer::performIPAddressUpdate(const HifiSockAddr& newPublicSockAddr) {
updateNetworkingInfoWithDataServer(IP_ONLY_AUTOMATIC_NETWORKING_VALUE, newPublicSockAddr.getAddress().toString());
updateDomainInDataServer(newPublicSockAddr.getAddress().toString());
}
void DomainServer::updateNetworkingInfoWithDataServer(const QString& newSetting, const QString& networkAddress) {
void DomainServer::updateDomainInDataServer(const QString& networkAddress) {
const QString DOMAIN_UPDATE = "/api/v1/domains/%1";
const QUuid& domainID = LimitedNodeList::getInstance()->getSessionUUID();
@ -1097,9 +1107,7 @@ void DomainServer::updateNetworkingInfoWithDataServer(const QString& newSetting,
domainObject[PUBLIC_NETWORK_ADDRESS_KEY] = networkAddress;
}
qDebug() << "Updating automatic networking setting in domain-server to" << newSetting;
domainObject[AUTOMATIC_NETWORKING_KEY] = newSetting;
domainObject[AUTOMATIC_NETWORKING_KEY] = _automaticNetworkingSetting;
QString domainUpdateJSON = QString("{\"domain\": %1 }").arg(QString(QJsonDocument(domainObject).toJson()));
@ -1112,11 +1120,11 @@ void DomainServer::updateNetworkingInfoWithDataServer(const QString& newSetting,
// todo: have data-web respond with ice-server hostname to use
void DomainServer::performICEUpdates() {
sendHearbeatToIceServer();
sendHeartbeatToIceServer();
sendICEPingPackets();
}
void DomainServer::sendHearbeatToIceServer() {
void DomainServer::sendHeartbeatToIceServer() {
const HifiSockAddr ICE_SERVER_SOCK_ADDR = HifiSockAddr("ice.highfidelity.io", ICE_SERVER_DEFAULT_PORT);
LimitedNodeList::getInstance()->sendHeartbeatToIceServer(ICE_SERVER_SOCK_ADDR);
}

View file

@ -66,7 +66,8 @@ private slots:
void requestCurrentPublicSocketViaSTUN();
void performIPAddressUpdate(const HifiSockAddr& newPublicSockAddr);
void performICEUpdates();
void sendHearbeatToIceServer();
void sendHeartbeatToDataServer() { updateDomainInDataServer(); }
void sendHeartbeatToIceServer();
void sendICEPingPackets();
private:
void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid());
@ -76,7 +77,7 @@ private:
bool optionallySetupAssignmentPayment();
void setupAutomaticNetworking();
void updateNetworkingInfoWithDataServer(const QString& newSetting, const QString& networkAddress = QString());
void updateDomainInDataServer(const QString& networkAddress = QString());
void processICEPingReply(const QByteArray& packet, const HifiSockAddr& senderSockAddr);
void processICEHeartbeatResponse(const QByteArray& packet);
@ -150,6 +151,8 @@ private:
QHash<QUuid, NetworkPeer> _connectingICEPeers;
QHash<QUuid, HifiSockAddr> _connectedICEPeers;
QString _automaticNetworkingSetting;
DomainServerSettingsManager _settingsManager;
};

View file

@ -1269,6 +1269,7 @@ glm::vec3 MyAvatar::applyKeyboardMotor(float deltaTime, const glm::vec3& localVe
_isPushing = false;
float motorEfficiency = glm::clamp(deltaTime / timescale, 0.0f, 1.0f);
glm::vec3 newLocalVelocity = localVelocity;
float keyboardInput = fabsf(_driveKeys[FWD] - _driveKeys[BACK]) +
(fabsf(_driveKeys[RIGHT] - _driveKeys[LEFT])) +
fabsf(_driveKeys[UP] - _driveKeys[DOWN]);
@ -1285,31 +1286,47 @@ glm::vec3 MyAvatar::applyKeyboardMotor(float deltaTime, const glm::vec3& localVe
if (directionLength > EPSILON) {
direction /= directionLength;
// Compute the target keyboard velocity (which ramps up slowly, and damps very quickly)
// the max magnitude of which depends on what we're doing:
float motorSpeed = glm::length(_keyboardMotorVelocity);
float finalMaxMotorSpeed = hasFloor ? _scale * MAX_WALKING_SPEED : _scale * MAX_KEYBOARD_MOTOR_SPEED;
float speedGrowthTimescale = 2.0f;
float speedIncreaseFactor = 1.8f;
motorSpeed *= 1.0f + glm::clamp(deltaTime / speedGrowthTimescale , 0.0f, 1.0f) * speedIncreaseFactor;
const float maxBoostSpeed = _scale * MAX_BOOST_SPEED;
if (motorSpeed < maxBoostSpeed) {
// an active keyboard motor should never be slower than this
float boostCoefficient = (maxBoostSpeed - motorSpeed) / maxBoostSpeed;
motorSpeed += MIN_AVATAR_SPEED * boostCoefficient;
motorEfficiency += (1.0f - motorEfficiency) * boostCoefficient;
} else if (motorSpeed > finalMaxMotorSpeed) {
motorSpeed = finalMaxMotorSpeed;
if (hasFloor) {
// we're walking --> simple exponential decay toward target walk speed
const float WALK_ACCELERATION_TIMESCALE = 0.7f; // seconds to decrease delta to 1/e
_keyboardMotorVelocity = MAX_WALKING_SPEED * direction;
motorEfficiency = glm::clamp(deltaTime / WALK_ACCELERATION_TIMESCALE, 0.0f, 1.0f);
} else {
// we're flying --> more complex curve
float motorSpeed = glm::length(_keyboardMotorVelocity);
float finalMaxMotorSpeed = _scale * MAX_KEYBOARD_MOTOR_SPEED;
float speedGrowthTimescale = 2.0f;
float speedIncreaseFactor = 1.8f;
motorSpeed *= 1.0f + glm::clamp(deltaTime / speedGrowthTimescale , 0.0f, 1.0f) * speedIncreaseFactor;
const float maxBoostSpeed = _scale * MAX_BOOST_SPEED;
if (motorSpeed < maxBoostSpeed) {
// an active keyboard motor should never be slower than this
float boostCoefficient = (maxBoostSpeed - motorSpeed) / maxBoostSpeed;
motorSpeed += MIN_AVATAR_SPEED * boostCoefficient;
motorEfficiency += (1.0f - motorEfficiency) * boostCoefficient;
} else if (motorSpeed > finalMaxMotorSpeed) {
motorSpeed = finalMaxMotorSpeed;
}
_keyboardMotorVelocity = motorSpeed * direction;
}
_keyboardMotorVelocity = motorSpeed * direction;
_isPushing = true;
}
newLocalVelocity = localVelocity + motorEfficiency * (_keyboardMotorVelocity - localVelocity);
} else {
_keyboardMotorVelocity = glm::vec3(0.0f);
newLocalVelocity = (1.0f - motorEfficiency) * localVelocity;
if (hasFloor && !_wasPushing) {
float speed = glm::length(newLocalVelocity);
if (speed > MIN_AVATAR_SPEED) {
// add small constant friction to help avatar drift to a stop sooner at low speeds
const float CONSTANT_FRICTION_DECELERATION = MIN_AVATAR_SPEED / 0.20f;
newLocalVelocity *= (speed - timescale * CONSTANT_FRICTION_DECELERATION) / speed;
}
}
}
// apply keyboard motor
return localVelocity + motorEfficiency * (_keyboardMotorVelocity - localVelocity);
return newLocalVelocity;
}
glm::vec3 MyAvatar::applyScriptedMotor(float deltaTime, const glm::vec3& localVelocity) {