Skip to content

Commit 0c7b2c8

Browse files
committed
ワールド生成時にどのくらいチャンクを生成するかを指定できるように
1 parent 8e91f66 commit 0c7b2c8

File tree

3 files changed

+100
-4
lines changed

3 files changed

+100
-4
lines changed

plugin.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: MiniatureWorld
2-
version: 0.0.11
2+
version: 0.0.12
33
main: NeiroNetwork\MiniatureWorld\Main
44
api: 4.0.0
55
depend:

src/NeiroNetwork/MiniatureWorld/ui/form/CreateWorldForm.php

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
namespace NeiroNetwork\MiniatureWorld\ui\form;
66

77
use dktapps\pmforms\CustomFormResponse;
8+
use dktapps\pmforms\element\Slider;
89
use NeiroNetwork\MiniatureWorld\ui\invmenu\WorldListViewer;
10+
use NeiroNetwork\MiniatureWorld\world\WorldGenerator;
911
use pocketmine\nbt\tag\CompoundTag;
1012
use pocketmine\player\Player;
1113
use pocketmine\world\generator\FlatGeneratorOptions;
@@ -17,12 +19,19 @@ class CreateWorldForm extends BaseWorldForm{
1719

1820
public function __construct(){
1921
parent::__construct("新規ワールド作成");
22+
23+
// HACK & FIXME
24+
$property = (new \ReflectionClass($this))->getParentClass()->getParentClass()->getProperty("elements");
25+
$property->setAccessible(true);
26+
$property->setValue($this, array_merge($this->getAllElements(), [
27+
new Slider("chunk_generation", "生成するチャンク数", 2, 64, 1, 8)
28+
]));
2029
}
2130

2231
protected function onSubmit(Player $player, CustomFormResponse $response) : void{
2332
$validatedResponse = $this->validateResponse($player, $response);
2433
if($validatedResponse === false) return;
25-
[$name, $type, $presets] = $validatedResponse;
34+
[$name, $type, $presets, $radius] = $validatedResponse;
2635

2736
$options = WorldCreationOptions::create()
2837
->setGeneratorClass(GeneratorManager::getInstance()->getGenerator($type)->getGeneratorClass())
@@ -34,12 +43,12 @@ protected function onSubmit(Player $player, CustomFormResponse $response) : void
3443
$options->setSpawnPosition($spawn);
3544
}
3645

37-
if(!$player->getServer()->getWorldManager()->generateWorld($name, $options)){
46+
if(!WorldGenerator::generate($name, $options, $radius, fn() => $player->sendMessage("ワールド「{$name}」のチャンク生成が完了しました"))){
3847
$this->resendForm($player, $response, "ワールド「{$name}」はすでに存在しています");
3948
return;
4049
}
4150

42-
$player->sendMessage("ワールド「{$name}を作成しました");
51+
$player->sendMessage("ワールド「{$name}を作成します");
4352

4453
$world = $player->getServer()->getWorldManager()->getWorldByName($name);
4554
$world->setTime(World::TIME_NOON);
@@ -53,4 +62,10 @@ protected function onSubmit(Player $player, CustomFormResponse $response) : void
5362
protected function onClose(Player $player) : void{
5463
(new WorldListViewer())->sendTo($player);
5564
}
65+
66+
protected function validateResponse(Player $player, CustomFormResponse $response) : bool|array{
67+
if(is_bool($result = parent::validateResponse($player, $response))) return $result;
68+
$result[] = (int) $response->getFloat("chunk_generation");
69+
return $result;
70+
}
5671
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
namespace NeiroNetwork\MiniatureWorld\world;
4+
5+
use pocketmine\event\world\WorldInitEvent;
6+
use pocketmine\event\world\WorldLoadEvent;
7+
use pocketmine\player\ChunkSelector;
8+
use pocketmine\Server;
9+
use pocketmine\world\format\Chunk;
10+
use pocketmine\world\World;
11+
use pocketmine\world\WorldCreationOptions;
12+
use pocketmine\world\WorldManager;
13+
14+
final class WorldGenerator{
15+
16+
/**
17+
* @see WorldManager::generateWorld()
18+
*/
19+
public static function generate(string $name, WorldCreationOptions $options, int $chunkRadius = 8, ?\Closure $onCompletion = null) : bool{
20+
$manager = ($server = Server::getInstance())->getWorldManager();
21+
22+
if(trim($name) === "" || $manager->isWorldGenerated($name)){
23+
return false;
24+
}
25+
26+
$providerEntry = $manager->getProviderManager()->getDefault();
27+
28+
$path = self::getWorldPath($name);
29+
$providerEntry->generate($path, $name, $options);
30+
31+
$world = new World($server, $name, $providerEntry->fromPath($path), $server->getAsyncPool());
32+
self::addWorldToManager($world);
33+
34+
$world->setAutoSave($manager->getAutoSave());
35+
36+
(new WorldInitEvent($world))->call();
37+
38+
(new WorldLoadEvent($world))->call();
39+
40+
$spawnLocation = $world->getSpawnLocation();
41+
$centerX = $spawnLocation->getFloorX() >> Chunk::COORD_BIT_SIZE;
42+
$centerZ = $spawnLocation->getFloorZ() >> Chunk::COORD_BIT_SIZE;
43+
44+
$selected = iterator_to_array((new ChunkSelector())->selectChunks($chunkRadius - 1, $centerX, $centerZ));
45+
$done = 0;
46+
$total = count($selected);
47+
foreach($selected as $index){
48+
World::getXZ($index, $chunkX, $chunkZ);
49+
$world->orderChunkPopulation($chunkX, $chunkZ, null)->onCompletion(
50+
static function() use (&$done, $total, $onCompletion) : void{
51+
if(++$done === $total) $onCompletion();
52+
},
53+
static function() : void{}
54+
);
55+
}
56+
57+
return true;
58+
}
59+
60+
/**
61+
* @see WorldManager::getWorldPath()
62+
*/
63+
private static function getWorldPath(string $name) : string{
64+
$manager = Server::getInstance()->getWorldManager();
65+
$method = (new \ReflectionClass($manager))->getMethod("getWorldPath");
66+
$method->setAccessible(true);
67+
return $method->invokeArgs($manager, [$name]);
68+
}
69+
70+
private static function addWorldToManager(World $world) : void{
71+
$manager = Server::getInstance()->getWorldManager();
72+
73+
$property = (new \ReflectionClass($manager))->getProperty("worlds");
74+
$property->setAccessible(true);
75+
76+
$worlds = $property->getValue($manager);
77+
$worlds[$world->getId()] = $world;
78+
79+
$property->setValue($manager, $worlds);
80+
}
81+
}

0 commit comments

Comments
 (0)