mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-14 17:59:41 +00:00
Merge branch 'release/3.1'
This commit is contained in:
commit
340de1c478
@ -200,6 +200,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
private $chunkPopulationLock = [];
|
||||
/** @var int */
|
||||
private $chunkPopulationQueueSize = 2;
|
||||
/** @var bool[] */
|
||||
private $generatorRegisteredWorkers = [];
|
||||
|
||||
/** @var bool */
|
||||
private $autoSave = true;
|
||||
@ -245,9 +247,6 @@ class Level implements ChunkManager, Metadatable{
|
||||
/** @var bool */
|
||||
private $closed = false;
|
||||
|
||||
/** @var \Closure */
|
||||
private $asyncPoolStartHook;
|
||||
|
||||
public static function chunkHash(int $x, int $z) : int{
|
||||
return (($x & 0xFFFFFFFF) << 32) | ($z & 0xFFFFFFFF);
|
||||
}
|
||||
@ -363,10 +362,6 @@ class Level implements ChunkManager, Metadatable{
|
||||
$this->temporalPosition = new Position(0, 0, 0, $this);
|
||||
$this->temporalVector = new Vector3(0, 0, 0);
|
||||
$this->tickRate = 1;
|
||||
|
||||
$this->server->getAsyncPool()->addWorkerStartHook($this->asyncPoolStartHook = function(int $worker) : void{
|
||||
$this->registerGeneratorToWorker($worker);
|
||||
});
|
||||
}
|
||||
|
||||
public function getTickRate() : int{
|
||||
@ -382,15 +377,16 @@ class Level implements ChunkManager, Metadatable{
|
||||
}
|
||||
|
||||
public function registerGeneratorToWorker(int $worker) : void{
|
||||
$this->generatorRegisteredWorkers[$worker] = true;
|
||||
$this->server->getAsyncPool()->submitTaskToWorker(new GeneratorRegisterTask($this, $this->generator, $this->provider->getGeneratorOptions()), $worker);
|
||||
}
|
||||
|
||||
public function unregisterGenerator(){
|
||||
$pool = $this->server->getAsyncPool();
|
||||
$pool->removeWorkerStartHook($this->asyncPoolStartHook);
|
||||
foreach($pool->getRunningWorkers() as $i){
|
||||
foreach($this->generatorRegisteredWorkers as $i => $bool){
|
||||
$pool->submitTaskToWorker(new GeneratorUnregisterTask($this), $i);
|
||||
}
|
||||
$this->generatorRegisteredWorkers = [];
|
||||
}
|
||||
|
||||
public function getBlockMetadata() : BlockMetadataStore{
|
||||
@ -2955,7 +2951,11 @@ class Level implements ChunkManager, Metadatable{
|
||||
}
|
||||
}
|
||||
$task = new PopulationTask($this, $chunk);
|
||||
$this->server->getAsyncPool()->submitTask($task);
|
||||
$workerId = $this->server->getAsyncPool()->selectWorker();
|
||||
if(!isset($this->generatorRegisteredWorkers[$workerId])){
|
||||
$this->registerGeneratorToWorker($workerId);
|
||||
}
|
||||
$this->server->getAsyncPool()->submitTaskToWorker($task, $workerId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,11 +26,13 @@ namespace pocketmine\level\generator;
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\BlockFactory;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\level\format\Chunk;
|
||||
use pocketmine\level\generator\object\OreType;
|
||||
use pocketmine\level\generator\populator\Ore;
|
||||
use pocketmine\level\generator\populator\Populator;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
class Flat extends Generator{
|
||||
/** @var Chunk */
|
||||
@ -41,6 +43,8 @@ class Flat extends Generator{
|
||||
private $structure;
|
||||
/** @var int */
|
||||
private $floorLevel;
|
||||
/** @var int */
|
||||
private $biome;
|
||||
/** @var mixed[] */
|
||||
private $options;
|
||||
/** @var string */
|
||||
@ -55,9 +59,15 @@ class Flat extends Generator{
|
||||
}
|
||||
|
||||
public function __construct(array $options = []){
|
||||
$this->preset = "2;7,2x3,2;1;";
|
||||
//$this->preset = "2;7,59x1,3x3,2;1;spawn(radius=10 block=89),decoration(treecount=80 grasscount=45)";
|
||||
$this->options = $options;
|
||||
if(isset($this->options["preset"]) and $this->options["preset"] != ""){
|
||||
$this->preset = $this->options["preset"];
|
||||
}else{
|
||||
$this->preset = "2;7,2x3,2;1;";
|
||||
//$this->preset = "2;7,59x1,3x3,2;1;spawn(radius=10 block=89),decoration(treecount=80 grasscount=45)";
|
||||
}
|
||||
|
||||
$this->parsePreset();
|
||||
|
||||
if(isset($this->options["decoration"])){
|
||||
$ores = new Ore();
|
||||
@ -90,39 +100,14 @@ class Flat extends Generator{
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function generateBaseChunk(string $preset) : void{
|
||||
$this->preset = $preset;
|
||||
$preset = explode(";", $preset);
|
||||
$version = (int) $preset[0];
|
||||
protected function parsePreset() : void{
|
||||
$preset = explode(";", $this->preset);
|
||||
$blocks = (string) ($preset[1] ?? "");
|
||||
$biome = (int) ($preset[2] ?? 1);
|
||||
$this->biome = (int) ($preset[2] ?? 1);
|
||||
$options = (string) ($preset[3] ?? "");
|
||||
$this->structure = self::parseLayers($blocks);
|
||||
|
||||
$this->floorLevel = $y = count($this->structure);
|
||||
|
||||
$this->chunk = new Chunk(0, 0);
|
||||
$this->chunk->setGenerated();
|
||||
|
||||
for($Z = 0; $Z < 16; ++$Z){
|
||||
for($X = 0; $X < 16; ++$X){
|
||||
$this->chunk->setBiomeId($X, $Z, $biome);
|
||||
}
|
||||
}
|
||||
|
||||
$count = count($this->structure);
|
||||
for($sy = 0; $sy < $count; $sy += 16){
|
||||
$subchunk = $this->chunk->getSubChunk($sy >> 4, true);
|
||||
for($y = 0; $y < 16 and isset($this->structure[$y | $sy]); ++$y){
|
||||
list($id, $meta) = $this->structure[$y | $sy];
|
||||
|
||||
for($Z = 0; $Z < 16; ++$Z){
|
||||
for($X = 0; $X < 16; ++$X){
|
||||
$subchunk->setBlock($X, $y, $Z, $id, $meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->floorLevel = count($this->structure);
|
||||
|
||||
preg_match_all('#(([0-9a-z_]{1,})\(?([0-9a-z_ =:]{0,})\)?),?#', $options, $matches);
|
||||
foreach($matches[2] as $i => $option){
|
||||
@ -141,14 +126,37 @@ class Flat extends Generator{
|
||||
}
|
||||
}
|
||||
|
||||
public function generateChunk(int $chunkX, int $chunkZ) : void{
|
||||
if($this->chunk === null){
|
||||
if(isset($this->options["preset"]) and $this->options["preset"] != ""){
|
||||
$this->generateBaseChunk($this->options["preset"]);
|
||||
}else{
|
||||
$this->generateBaseChunk($this->preset);
|
||||
protected function generateBaseChunk() : void{
|
||||
$this->chunk = new Chunk(0, 0);
|
||||
$this->chunk->setGenerated();
|
||||
|
||||
for($Z = 0; $Z < 16; ++$Z){
|
||||
for($X = 0; $X < 16; ++$X){
|
||||
$this->chunk->setBiomeId($X, $Z, $this->biome);
|
||||
}
|
||||
}
|
||||
|
||||
$count = count($this->structure);
|
||||
for($sy = 0; $sy < $count; $sy += 16){
|
||||
$subchunk = $this->chunk->getSubChunk($sy >> 4, true);
|
||||
for($y = 0; $y < 16 and isset($this->structure[$y | $sy]); ++$y){
|
||||
list($id, $meta) = $this->structure[$y | $sy];
|
||||
|
||||
for($Z = 0; $Z < 16; ++$Z){
|
||||
for($X = 0; $X < 16; ++$X){
|
||||
$subchunk->setBlock($X, $y, $Z, $id, $meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function init(ChunkManager $level, Random $random) : void{
|
||||
parent::init($level, $random);
|
||||
$this->generateBaseChunk();
|
||||
}
|
||||
|
||||
public function generateChunk(int $chunkX, int $chunkZ) : void{
|
||||
$chunk = clone $this->chunk;
|
||||
$chunk->setX($chunkX);
|
||||
$chunk->setZ($chunkZ);
|
||||
|
@ -168,18 +168,15 @@ class AsyncPool{
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits an AsyncTask to the worker with the least load. If all workers are busy and the pool is not full, a new
|
||||
* worker may be started.
|
||||
* Selects a worker ID to run a task.
|
||||
*
|
||||
* @param AsyncTask $task
|
||||
* - if an idle worker is found, it will be selected
|
||||
* - else, if the worker pool is not full, a new worker will be selected
|
||||
* - else, the worker with the smallest backlog is chosen.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function submitTask(AsyncTask $task) : int{
|
||||
if($task->getTaskId() !== null){
|
||||
throw new \InvalidArgumentException("Cannot submit the same AsyncTask instance more than once");
|
||||
}
|
||||
|
||||
public function selectWorker() : int{
|
||||
$worker = null;
|
||||
$minUsage = PHP_INT_MAX;
|
||||
foreach($this->workerUsage as $i => $usage){
|
||||
@ -202,7 +199,23 @@ class AsyncPool{
|
||||
}
|
||||
|
||||
assert($worker !== null);
|
||||
return $worker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits an AsyncTask to the worker with the least load. If all workers are busy and the pool is not full, a new
|
||||
* worker may be started.
|
||||
*
|
||||
* @param AsyncTask $task
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function submitTask(AsyncTask $task) : int{
|
||||
if($task->getTaskId() !== null){
|
||||
throw new \InvalidArgumentException("Cannot submit the same AsyncTask instance more than once");
|
||||
}
|
||||
|
||||
$worker = $this->selectWorker();
|
||||
$this->submitTaskToWorker($task, $worker);
|
||||
return $worker;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user