Firehose auto-tick-rate anti-feature, closes #2665

This commit is contained in:
Dylan K. Taylor 2019-03-03 13:24:53 +00:00
parent d9880de2ef
commit 6bd43a8215
4 changed files with 4 additions and 65 deletions

View File

@ -108,12 +108,11 @@ class StatusCommand extends VanillaCommand{
foreach($server->getLevelManager()->getLevels() as $level){
$levelName = $level->getFolderName() !== $level->getDisplayName() ? " (" . $level->getDisplayName() . ")" : "";
$timeColor = ($level->getTickRate() > 1 or $level->getTickRateTime() > 40) ? TextFormat::RED : TextFormat::YELLOW;
$tickRate = $level->getTickRate() > 1 ? " (tick rate " . $level->getTickRate() . ")" : "";
$timeColor = $level->getTickRateTime() > 40 ? TextFormat::RED : TextFormat::YELLOW;
$sender->sendMessage(TextFormat::GOLD . "World \"{$level->getFolderName()}\"$levelName: " .
TextFormat::RED . number_format(count($level->getChunks())) . TextFormat::GREEN . " chunks, " .
TextFormat::RED . number_format(count($level->getEntities())) . TextFormat::GREEN . " entities. " .
"Time $timeColor" . round($level->getTickRateTime(), 2) . "ms" . $tickRate
"Time $timeColor" . round($level->getTickRateTime(), 2) . "ms"
);
}

View File

@ -1422,7 +1422,8 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
assert(abs($dx) <= 20 and abs($dy) <= 20 and abs($dz) <= 20, "Movement distance is excessive: dx=$dx, dy=$dy, dz=$dz");
$list = $this->level->getCollisionBoxes($this, $this->level->getTickRate() > 1 ? $this->boundingBox->offsetCopy($dx, $dy, $dz) : $this->boundingBox->addCoord($dx, $dy, $dz), false);
//TODO: bad hack here will cause unexpected behaviour under heavy lag
$list = $this->level->getCollisionBoxes($this, $this->level->getTickRateTime() > 50 ? $this->boundingBox->offsetCopy($dx, $dy, $dz) : $this->boundingBox->addCoord($dx, $dy, $dz), false);
foreach($list as $bb){
$dy = $bb->calculateYOffset($this->boundingBox, $dy);

View File

@ -256,12 +256,8 @@ class Level implements ChunkManager, Metadatable{
/** @var LevelTimings */
public $timings;
/** @var int */
private $tickRate;
/** @var int */
public $tickRateTime = 0;
/** @var int */
public $tickRateCounter = 0;
/** @var bool */
private $doingTick = false;
@ -401,21 +397,12 @@ class Level implements ChunkManager, Metadatable{
$this->timings = new LevelTimings($this);
$this->temporalPosition = new Position(0, 0, 0, $this);
$this->temporalVector = new Vector3(0, 0, 0);
$this->tickRate = 1;
}
public function getTickRate() : int{
return $this->tickRate;
}
public function getTickRateTime() : float{
return $this->tickRateTime;
}
public function setTickRate(int $tickRate){
$this->tickRate = $tickRate;
}
public function registerGeneratorToWorker(int $worker) : void{
$this->generatorRegisteredWorkers[$worker] = true;
$this->server->getAsyncPool()->submitTaskToWorker(new GeneratorRegisterTask($this, $this->generator, $this->provider->getLevelData()->getGeneratorOptions()), $worker);

View File

@ -40,11 +40,8 @@ use function array_shift;
use function asort;
use function assert;
use function count;
use function floor;
use function implode;
use function max;
use function microtime;
use function min;
use function random_int;
use function round;
use function sprintf;
@ -61,31 +58,17 @@ class LevelManager{
/** @var Server */
private $server;
/** @var bool */
private $autoTickRate = true;
/** @var int */
private $autoTickRateLimit = 20;
/** @var bool */
private $alwaysTickPlayers = false;
/** @var int */
private $baseTickRate = 1;
/** @var bool */
private $autoSave = true;
/** @var int */
private $autoSaveTicks = 6000;
/** @var int */
private $autoSaveTicker = 0;
public function __construct(Server $server){
$this->server = $server;
$this->autoTickRate = (bool) $this->server->getProperty("level-settings.auto-tick-rate", $this->autoTickRate);
$this->autoTickRateLimit = (int) $this->server->getProperty("level-settings.auto-tick-rate-limit", $this->autoTickRateLimit);
$this->alwaysTickPlayers = (bool) $this->server->getProperty("level-settings.always-tick-players", $this->alwaysTickPlayers);
$this->baseTickRate = (int) $this->server->getProperty("level-settings.base-tick-rate", $this->baseTickRate);
$this->autoSave = $this->server->getConfigBool("auto-save", $this->autoSave);
$this->autoSaveTicks = (int) $this->server->getProperty("ticks-per.autosave", 6000);
}
@ -239,7 +222,6 @@ class LevelManager{
}
$this->levels[$level->getId()] = $level;
$level->setTickRate($this->baseTickRate);
$level->setAutoSave($this->autoSave);
(new LevelLoadEvent($level))->call();
@ -278,7 +260,6 @@ class LevelManager{
$level = new Level($this->server, $name, new $providerClass($path));
$this->levels[$level->getId()] = $level;
$level->setTickRate($this->baseTickRate);
$level->setAutoSave($this->autoSave);
(new LevelInitEvent($level))->call();
@ -360,40 +341,11 @@ class LevelManager{
// Level unloaded during the tick of a level earlier in this loop, perhaps by plugin
continue;
}
if($level->getTickRate() > $this->baseTickRate and --$level->tickRateCounter > 0){
if($this->alwaysTickPlayers){
foreach($level->getPlayers() as $p){
if($p->spawned){
$p->onUpdate($currentTick);
}
}
}
continue;
}
$levelTime = microtime(true);
$level->doTick($currentTick);
$tickMs = (microtime(true) - $levelTime) * 1000;
$level->tickRateTime = $tickMs;
if($this->autoTickRate){
if($tickMs < 50 and $level->getTickRate() > $this->baseTickRate){
$level->setTickRate($r = $level->getTickRate() - 1);
if($r > $this->baseTickRate){
$level->tickRateCounter = $level->getTickRate();
}
$this->server->getLogger()->debug("Raising world \"{$level->getDisplayName()}\" tick rate to {$level->getTickRate()} ticks");
}elseif($tickMs >= 50){
if($level->getTickRate() === $this->baseTickRate){
$level->setTickRate(max($this->baseTickRate + 1, min($this->autoTickRateLimit, (int) floor($tickMs / 50))));
$this->server->getLogger()->debug(sprintf("World \"%s\" took %gms, setting tick rate to %d ticks", $level->getDisplayName(), (int) round($tickMs, 2), $level->getTickRate()));
}elseif(($tickMs / $level->getTickRate()) >= 50 and $level->getTickRate() < $this->autoTickRateLimit){
$level->setTickRate($level->getTickRate() + 1);
$this->server->getLogger()->debug(sprintf("World \"%s\" took %gms, setting tick rate to %d ticks", $level->getDisplayName(), (int) round($tickMs, 2), $level->getTickRate()));
}
$level->tickRateCounter = $level->getTickRate();
}
}
}
if($this->autoSave and ++$this->autoSaveTicker >= $this->autoSaveTicks){