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 $networkCompressionLevel = 7;
private $autoTickRate = true;
/** @var BaseLang */
private $baseLang;
@ -224,8 +226,6 @@ class Server{
/** @var Level[] */
private $levels = [];
private $offendingLevels = [];
private $offendingTicks = [];
/** @var Level */
private $levelDefault = null;
@ -1530,6 +1530,8 @@ class Server{
$this->networkCompressionLevel = $this->getProperty("network.compression-level", 7);
$this->networkCompressionAsync = $this->getProperty("network.async-compression", true);
$this->autoTickRate = $this->getProperty("level-settings.auto-tick-rate", true);
$this->scheduler = new ServerScheduler();
if($this->getConfigBoolean("enable-rcon", false) === true){
@ -2154,27 +2156,34 @@ class Server{
}
private function checkTickUpdates($currentTick){
$tickLimit = 50 / count($this->levels);
$levelTimes = [];
$startTime = microtime(true);
//Do level ticks
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;
}
try{
$levelTime = microtime(true);
$level->doTick($currentTick);
$levelMs = (microtime(true) - $levelTime) * 1000;
$levelTimes[$level->getId()] = $levelMs;
if(isset($this->offendingLevels[$level->getId()])){
if($levelMs < $tickLimit and --$this->offendingLevels[$level->getId()] <= 0){
unset($this->offendingLevels[$level->getId()]);
unset($this->offendingTicks[$level->getId()]);
}else{
$this->offendingTicks[$level->getId()] = $this->offendingLevels[$level->getId()];
$tickMs = (microtime(true) - $levelTime) * 1000;
if($this->autoTickRate){
if($tickMs < 50 and $level->getTickRate() > 1){
if($level->getTickRate() > 1){
$level->setTickRate($r = $level->getTickRate() - 1);
if($r > 1){
$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){
@ -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(){

View File

@ -125,37 +125,37 @@ class Level implements ChunkManager, Metadatable{
const TIME_FULL = 24000;
/** @var Tile[] */
protected $tiles = [];
private $tiles = [];
/** @var Player[] */
protected $players = [];
private $players = [];
/** @var Entity[] */
protected $entities = [];
private $entities = [];
/** @var Entity[] */
public $updateEntities = [];
/** @var Tile[] */
public $updateTiles = [];
protected $blockCache = [];
private $blockCache = [];
/** @var Server */
protected $server;
private $server;
/** @var int */
protected $levelId;
private $levelId;
/** @var LevelProvider */
protected $provider;
private $provider;
/** @var Player[][] */
protected $usedChunks = [];
private $usedChunks = [];
/** @var FullChunk[]|Chunk[] */
protected $unloadQueue;
private $unloadQueue;
protected $time;
private $time;
public $stopTime;
private $folderName;
@ -164,7 +164,7 @@ class Level implements ChunkManager, Metadatable{
private $chunks = [];
/** @var Vector3[][] */
protected $changedBlocks = [];
private $changedBlocks = [];
/** @var ReversePriorityQueue */
private $updateQueue;
@ -196,11 +196,11 @@ class Level implements ChunkManager, Metadatable{
/** @var \SplFixedArray */
private $blockStates;
protected $chunkTickRadius;
protected $chunkTickList = [];
protected $chunksPerTick;
protected $clearChunksOnTick;
protected $randomTickBlocks = [
private $chunkTickRadius;
private $chunkTickList = [];
private $chunksPerTick;
private $clearChunksOnTick;
private $randomTickBlocks = [
Block::GRASS => Grass::class,
Block::SAPLING => Sapling::class,
Block::LEAVES => Leaves::class,
@ -227,10 +227,13 @@ class Level implements ChunkManager, Metadatable{
/** @var LevelTimings */
public $timings;
private $tickRate;
public $tickRateCounter = 0;
/** @var Generator */
protected $generator;
private $generator;
/** @var Generator */
protected $generatorInstance;
private $generatorInstance;
/**
* Returns the chunk unique hash/key
@ -317,6 +320,15 @@ 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(){
return $this->tickRate;
}
public function setTickRate($tickRate){
$this->tickRate = (int) $tickRate;
}
public function initLevel(){
@ -1935,7 +1947,7 @@ class Level implements ChunkManager, Metadatable{
$this->chunkSendQueue[$index][spl_object_hash($player)] = $player;
}
protected function processChunkRequest(){
private function processChunkRequest(){
if(count($this->chunkSendQueue) > 0){
$this->timings->syncChunkSendTimer->startTiming();
@ -2088,7 +2100,7 @@ class Level implements ChunkManager, Metadatable{
return true;
}
protected function queueUnloadChunk($x, $z){
private function queueUnloadChunk($x, $z){
$this->unloadQueue[$index = Level::chunkHash($x, $z)] = microtime(true);
unset($this->chunkTickList[$index]);
}
@ -2384,7 +2396,7 @@ class Level implements ChunkManager, Metadatable{
$this->timings->doChunkGC->stopTiming();
}
protected function unloadChunks(){
private function unloadChunks(){
if(count($this->unloadQueue) > 0){
$X = 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
#NOTE: This is currently not implemented
convert-format: false
#Automatically change levels tick rate to maintain 20 ticks per second
auto-tick-rate: true
chunk-sending:
#Amount of chunks sent to players per tick