Files
watrbx-game-engine/App/v8datamodel/PhysicsInstructions.cpp
T
2025-09-18 17:55:52 -04:00

185 lines
5.6 KiB
C++

/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#include "stdafx.h"
#include "V8DataModel/PhysicsInstructions.h" // TODO - minimize these includes, and in the .h file
#include "V8DataModel/Workspace.h"
#include "v8datamodel/PhysicsSettings.h"
#include "V8World/World.h"
#include "Network/Player.h"
LOGGROUP(CyclicExecutiveThrottling)
namespace RBX {
PhysicsInstructions::PhysicsInstructions()
: timeSinceLastRadiusChange(0.0)
, throttleTimer(0.0)
, throttleAdjustTime(PhysicsSettings::singleton().getThrottleAdjustTime())
, averageDt(30, 1.0) // 7 samples should be enough ~= 1/4 second
, averageDutyDt(30, 1.0)
, averageCyclicDt(30, 1.0)
, requestedDutyPercent(0.0)
, bandwidthExceeded(false)
, networkBufferHealth(1.0)
{
}
double PhysicsInstructions::dPhysicsServerDutyPercent()
{
// 3/11/09 - changed from 0.15 to 0.10
// 11/28/12 - changed from 0.10 to 0.40 under a FASTFLAG to ease up iPad players' lives
return 0.60;
}
/*
EThrottle:
averageFps instantFps instantDuty
Good Good Good up
Good Bad Good up
Good Bad Bad down
Good Good Bad down
Bad Good Good down
Bad Bad Good down
Bad Bad Bad down
Bad Good Bad down
*/
void PhysicsInstructions::changeSimulationRadius(RBX::Network::Player* dPhysPlayer, float change)
{
timeSinceLastRadiusChange = 0.0;
RBXASSERT(dPhysPlayer);
float currentRadius = dPhysPlayer->getSimulationRadius();
float newRadius = change * currentRadius;
dPhysPlayer->updateSimulationRadius(newRadius);
}
void PhysicsInstructions::changeMaxSimulationRadius(RBX::Network::Player* dPhysPlayer, float change)
{
RBXASSERT(dPhysPlayer);
float currentMaxRadius = dPhysPlayer->getMaxSimulationRadius();
float newRadius = change * currentMaxRadius;
dPhysPlayer->setMaxSimulationRadius(newRadius);
}
#pragma optimize( "", off )
double PhysicsInstructions::dPhysicsClientDutyPercent() {return 0.40;} // note this is higher than normal
double PhysicsInstructions::dPhysicsClientEThrottleDutyPercent() {return 0.60;} // note this is higher than normal
// dt : timespanSinceLastStep.seconds();
// dutyDt : timespanOfLastStep.seconds();
void PhysicsInstructions::setThrottlesBase(RBX::Network::Player* dPhysPlayer, Workspace* workspace, bool realTimePerfOK, bool dutyPerfOK, double avgDutyPercent, double dt)
{
if (realTimePerfOK)
{
if (!dutyPerfOK)
{
throttleTimer += dt;
if (throttleTimer >= throttleAdjustTime)
{
throttleTimer = 0.0;
workspace->getWorld()->getEThrottle().increaseLoad(false);
}
}
else
{
throttleTimer = 0.0;
workspace->getWorld()->getEThrottle().increaseLoad(true);
}
}
else // react immediately to low frame rate
{
throttleTimer = 0.0;
workspace->getWorld()->getEThrottle().increaseLoad(false);
}
FASTLOG1F(FLog::CyclicExecutiveThrottling, "ThrottleTimer= %f", throttleTimer);
//StandardOut::singleton()->printf(MESSAGE_INFO, "%f", workspace->getWorld()->getEnvironmentSpeed());
if (!dPhysPlayer)
return;
if ((timeSinceLastRadiusChange += dt) < throttleAdjustTime)
return;
if (bandwidthExceeded)
changeSimulationRadius(dPhysPlayer, 0.7);
else if (!realTimePerfOK || avgDutyPercent > dPhysicsClientDutyPercent())
changeSimulationRadius(dPhysPlayer, 0.7);
else if (realTimePerfOK && avgDutyPercent < dPhysicsClientDutyPercent() - 0.2)
changeSimulationRadius(dPhysPlayer, 1.05);
if (networkBufferHealth <= 0.5)
changeMaxSimulationRadius(dPhysPlayer, 0.95);
else if (networkBufferHealth >= 0.9)
changeMaxSimulationRadius(dPhysPlayer, 1.05);
}
void PhysicsInstructions::setCyclicThrottles(RBX::Network::Player* dPhysPlayer, Workspace* workspace, double cyclicDt, double dt, double dutyDt)
{
averageCyclicDt.sample(cyclicDt);
averageDt.sample(dt);
averageDutyDt.sample(dutyDt);
double avgCyclicDt = averageCyclicDt.getAverage(); // average world steps per dt
double avgDt = averageDt.getAverage(); // average delta time between steps
double avgDuty = averageDutyDt.getAverage(); // average time per step
FASTLOG1F(FLog::CyclicExecutiveThrottling, "avgWorldStepFreq= %f", avgCyclicDt);
bool stepsOK = ((avgCyclicDt/avgDt) > 0.6);
// percentage of time the previous step took over the average frame time
double prevDutyPercent = dutyDt / avgDt;
// ratio of avg time per step over avg delta time between steps, i.e. on average, what percentage of time per frame was occupied by physics step
double avgDutyPercent = avgDuty / avgDt;
bool dutyOK = ((prevDutyPercent < requestedDutyPercent) && (avgDutyPercent < requestedDutyPercent));
setThrottlesBase(dPhysPlayer, workspace, stepsOK, dutyOK, avgDutyPercent, dt);
}
void PhysicsInstructions::setThrottles(RBX::Network::Player* dPhysPlayer, Workspace* workspace, double dt, double dutyDt)
{
averageDt.sample(dt);
averageDutyDt.sample(dutyDt);
double avgDt = averageDt.getAverage(); // average delta time between steps
double avgDuty = averageDutyDt.getAverage(); // average time per step
double avgFps = 1.0 / avgDt;
// percentage of time the previous step took over the average frame time
double prevDutyPercent = dutyDt / avgDt;
// ratio of avg time per step over avg delta time between steps, i.e. on average, what percentage of time per frame was occupied by physics step
double avgDutyPercent = avgDuty / avgDt;
bool fpsOK = (avgFps > 40);
bool dutyOK = ((prevDutyPercent < requestedDutyPercent) && (avgDutyPercent < requestedDutyPercent));
setThrottlesBase(dPhysPlayer, workspace, fpsOK, dutyOK, avgDutyPercent, dt);
}
#pragma optimize( "", on )
} // namespace
// Randomized Locations for hackflags
namespace RBX
{
namespace Security
{
unsigned int hackFlag6 = 0;
};
};