Added level-settings.auto-tick-rate property, added Level tick rate

This commit is contained in:
Shoghi Cervantes 2015-04-12 14:13:36 +02:00
parent 410f6ba618
commit 5e2a21fc26
No known key found for this signature in database
GPG Key ID: 78464DB0A7837F89
3 changed files with 60 additions and 57 deletions

View File

@ -196,6 +196,8 @@ class Server{
private $networkCompressionAsync = true; private $networkCompressionAsync = true;
private $networkCompressionLevel = 7; private $networkCompressionLevel = 7;
private $autoTickRate = true;
/** @var BaseLang */ /** @var BaseLang */
private $baseLang; private $baseLang;
@ -224,8 +226,6 @@ class Server{
/** @var Level[] */ /** @var Level[] */
private $levels = []; private $levels = [];
private $offendingLevels = [];
private $offendingTicks = [];
/** @var Level */ /** @var Level */
private $levelDefault = null; private $levelDefault = null;
@ -1530,6 +1530,8 @@ class Server{
$this->networkCompressionLevel = $this->getProperty("network.compression-level", 7); $this->networkCompressionLevel = $this->getProperty("network.compression-level", 7);
$this->networkCompressionAsync = $this->getProperty("network.async-compression", true); $this->networkCompressionAsync = $this->getProperty("network.async-compression", true);
$this->autoTickRate = $this->getProperty("level-settings.auto-tick-rate", true);
$this->scheduler = new ServerScheduler(); $this->scheduler = new ServerScheduler();
if($this->getConfigBoolean("enable-rcon", false) === true){ if($this->getConfigBoolean("enable-rcon", false) === true){
@ -2154,27 +2156,34 @@ class Server{
} }
private function checkTickUpdates($currentTick){ private function checkTickUpdates($currentTick){
$tickLimit = 50 / count($this->levels);
$levelTimes = [];
$startTime = microtime(true);
//Do level ticks //Do level ticks
foreach($this->getLevels() as $level){ foreach($this->getLevels() as $level){
if(isset($this->offendingLevels[$level->getId()]) and $this->offendingTicks[$level->getId()]-- > 0){ if($level->getTickRate() > 1 and --$level->tickRateCounter > 0){
continue; continue;
} }
try{ try{
$levelTime = microtime(true); $levelTime = microtime(true);
$level->doTick($currentTick); $level->doTick($currentTick);
$levelMs = (microtime(true) - $levelTime) * 1000; $tickMs = (microtime(true) - $levelTime) * 1000;
$levelTimes[$level->getId()] = $levelMs;
if(isset($this->offendingLevels[$level->getId()])){ if($this->autoTickRate){
if($levelMs < $tickLimit and --$this->offendingLevels[$level->getId()] <= 0){ if($tickMs < 50 and $level->getTickRate() > 1){
unset($this->offendingLevels[$level->getId()]); if($level->getTickRate() > 1){
unset($this->offendingTicks[$level->getId()]); $level->setTickRate($r = $level->getTickRate() - 1);
}else{ if($r > 1){
$this->offendingTicks[$level->getId()] = $this->offendingLevels[$level->getId()]; $level->tickRateCounter = $level->getTickRate();
}
$this->getLogger()->debug("Raising level \"".$level->getName()."\" tick rate to ".$level->getTickRate()." ticks");
}
}elseif($tickMs >= 50){
if($level->getTickRate() === 1){
$level->setTickRate(max(2, min(10, floor($tickMs / 50))));
$this->getLogger()->debug("Set level \"".$level->getName()."\" tick rate to ".$level->getTickRate()." ticks");
}elseif(($tickMs / $level->getTickRate()) >= 50 and $level->getTickRate() < 10){ //Limit?
$level->setTickRate($level->getTickRate() + 1);
$this->getLogger()->debug("Set level \"".$level->getName()."\" tick rate to ".$level->getTickRate()." ticks");
}
$level->tickRateCounter = $level->getTickRate();
} }
} }
}catch(\Exception $e){ }catch(\Exception $e){
@ -2184,26 +2193,6 @@ class Server{
} }
} }
} }
$totalTime = (microtime(true) - $startTime) * 1000;
if($totalTime > 50){
arsort($levelTimes);
foreach($levelTimes as $levelId => $t){
$totalTime -= $t;
if(!isset($this->offendingLevels[$levelId])){
$this->offendingLevels[$levelId] = max(1, min(10, floor($t / 50)));
}elseif($this->offendingLevels[$levelId] < 10){ //Limit?
++$this->offendingLevels[$levelId];
}
$this->offendingTicks[$levelId] = $this->offendingLevels[$levelId];
if($totalTime <= 50){
break;
}
}
}
} }
public function doAutoSave(){ public function doAutoSave(){

View File

@ -125,37 +125,37 @@ class Level implements ChunkManager, Metadatable{
const TIME_FULL = 24000; const TIME_FULL = 24000;
/** @var Tile[] */ /** @var Tile[] */
protected $tiles = []; private $tiles = [];
/** @var Player[] */ /** @var Player[] */
protected $players = []; private $players = [];
/** @var Entity[] */ /** @var Entity[] */
protected $entities = []; private $entities = [];
/** @var Entity[] */ /** @var Entity[] */
public $updateEntities = []; public $updateEntities = [];
/** @var Tile[] */ /** @var Tile[] */
public $updateTiles = []; public $updateTiles = [];
protected $blockCache = []; private $blockCache = [];
/** @var Server */ /** @var Server */
protected $server; private $server;
/** @var int */ /** @var int */
protected $levelId; private $levelId;
/** @var LevelProvider */ /** @var LevelProvider */
protected $provider; private $provider;
/** @var Player[][] */ /** @var Player[][] */
protected $usedChunks = []; private $usedChunks = [];
/** @var FullChunk[]|Chunk[] */ /** @var FullChunk[]|Chunk[] */
protected $unloadQueue; private $unloadQueue;
protected $time; private $time;
public $stopTime; public $stopTime;
private $folderName; private $folderName;
@ -164,7 +164,7 @@ class Level implements ChunkManager, Metadatable{
private $chunks = []; private $chunks = [];
/** @var Vector3[][] */ /** @var Vector3[][] */
protected $changedBlocks = []; private $changedBlocks = [];
/** @var ReversePriorityQueue */ /** @var ReversePriorityQueue */
private $updateQueue; private $updateQueue;
@ -196,11 +196,11 @@ class Level implements ChunkManager, Metadatable{
/** @var \SplFixedArray */ /** @var \SplFixedArray */
private $blockStates; private $blockStates;
protected $chunkTickRadius; private $chunkTickRadius;
protected $chunkTickList = []; private $chunkTickList = [];
protected $chunksPerTick; private $chunksPerTick;
protected $clearChunksOnTick; private $clearChunksOnTick;
protected $randomTickBlocks = [ private $randomTickBlocks = [
Block::GRASS => Grass::class, Block::GRASS => Grass::class,
Block::SAPLING => Sapling::class, Block::SAPLING => Sapling::class,
Block::LEAVES => Leaves::class, Block::LEAVES => Leaves::class,
@ -227,10 +227,13 @@ class Level implements ChunkManager, Metadatable{
/** @var LevelTimings */ /** @var LevelTimings */
public $timings; public $timings;
private $tickRate;
public $tickRateCounter = 0;
/** @var Generator */ /** @var Generator */
protected $generator; private $generator;
/** @var Generator */ /** @var Generator */
protected $generatorInstance; private $generatorInstance;
/** /**
* Returns the chunk unique hash/key * Returns the chunk unique hash/key
@ -317,6 +320,15 @@ class Level implements ChunkManager, Metadatable{
$this->timings = new LevelTimings($this); $this->timings = new LevelTimings($this);
$this->temporalPosition = new Position(0, 0, 0, $this); $this->temporalPosition = new Position(0, 0, 0, $this);
$this->temporalVector = new Vector3(0, 0, 0); $this->temporalVector = new Vector3(0, 0, 0);
$this->tickRate = 1;
}
public function getTickRate(){
return $this->tickRate;
}
public function setTickRate($tickRate){
$this->tickRate = (int) $tickRate;
} }
public function initLevel(){ public function initLevel(){
@ -1935,7 +1947,7 @@ class Level implements ChunkManager, Metadatable{
$this->chunkSendQueue[$index][spl_object_hash($player)] = $player; $this->chunkSendQueue[$index][spl_object_hash($player)] = $player;
} }
protected function processChunkRequest(){ private function processChunkRequest(){
if(count($this->chunkSendQueue) > 0){ if(count($this->chunkSendQueue) > 0){
$this->timings->syncChunkSendTimer->startTiming(); $this->timings->syncChunkSendTimer->startTiming();
@ -2088,7 +2100,7 @@ class Level implements ChunkManager, Metadatable{
return true; return true;
} }
protected function queueUnloadChunk($x, $z){ private function queueUnloadChunk($x, $z){
$this->unloadQueue[$index = Level::chunkHash($x, $z)] = microtime(true); $this->unloadQueue[$index = Level::chunkHash($x, $z)] = microtime(true);
unset($this->chunkTickList[$index]); unset($this->chunkTickList[$index]);
} }
@ -2384,7 +2396,7 @@ class Level implements ChunkManager, Metadatable{
$this->timings->doChunkGC->stopTiming(); $this->timings->doChunkGC->stopTiming();
} }
protected function unloadChunks(){ private function unloadChunks(){
if(count($this->unloadQueue) > 0){ if(count($this->unloadQueue) > 0){
$X = null; $X = null;
$Z = null; $Z = null;

View File

@ -44,6 +44,8 @@ level-settings:
#If true, converts from a format that is not the default to the default format on load #If true, converts from a format that is not the default to the default format on load
#NOTE: This is currently not implemented #NOTE: This is currently not implemented
convert-format: false convert-format: false
#Automatically change levels tick rate to maintain 20 ticks per second
auto-tick-rate: true
chunk-sending: chunk-sending:
#Amount of chunks sent to players per tick #Amount of chunks sent to players per tick