PocketMine-MP  1.4 - API 1.10.0
 All Classes Namespaces Functions Variables Pages
GenerationChunkManager.php
1 <?php
2 
3 /*
4  *
5  * ____ _ _ __ __ _ __ __ ____
6  * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7  * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8  * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9  * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * @author PocketMine Team
17  * @link http://www.pocketmine.net/
18  *
19  *
20 */
21 
22 namespace pocketmine\level\generator;
23 
29 
31 
32  protected $levelID;
33 
35  protected $chunks = [];
36 
38  protected $generator;
39 
41  protected $manager;
42 
43  protected $seed;
44 
45  protected $changes = [];
46 
47  public function __construct(GenerationManager $manager, $levelID, $seed, $class, array $options){
48  if(!class_exists($class, true) or !is_subclass_of($class, Generator::class)){
49  throw new \InvalidStateException("Class $class does not exists or is not a subclass of Generator");
50  }
51 
52  $this->levelID = $levelID;
53  $this->seed = $seed;
54  $this->manager = $manager;
55  $this->generator = new $class($options);
56  $this->generator->init($this, new Random($seed));
57  }
58 
62  public function getSeed(){
63  return $this->seed;
64  }
65 
69  public function getId(){
70  return $this->levelID;
71  }
72 
81  public function getChunk($chunkX, $chunkZ){
82  $index = Level::chunkHash($chunkX, $chunkZ);
83  $chunk = !isset($this->chunks[$index]) ? $this->requestChunk($chunkX, $chunkZ) : $this->chunks[$index];
84  if($chunk === null){
85  throw new ChunkException("null Chunk received");
86  }
87 
88  return $chunk;
89  }
90 
94  public function getChangedChunks(){
95  return $this->changes;
96  }
97 
98  public function cleanChangedChunks(){
99  $this->changes = [];
100  }
101 
102  public function cleanChangedChunk($index){
103  unset($this->changes[$index]);
104  }
105 
106  public function doGarbageCollection(){
107  $count = 0;
108 
109  foreach($this->chunks as $index => $chunk){
110  if(!isset($this->changes[$index]) or $chunk->isPopulated()){
111  unset($this->chunks[$index]);
112  unset($this->changes[$index]);
113  ++$count;
114  }
115  }
116 
117  return $count;
118  }
119 
120  public function generateChunk($chunkX, $chunkZ){
121  try{
122  $this->getChunk($chunkX, $chunkZ);
123  $this->generator->generateChunk($chunkX, $chunkZ);
124  $this->setChunkGenerated($chunkX, $chunkZ);
125  }catch(\Exception $e){
126  }
127  }
128 
129  public function populateChunk($chunkX, $chunkZ){
130  if(!$this->isChunkGenerated($chunkX, $chunkZ)){
131  $this->generateChunk($chunkX, $chunkZ);
132  }
133 
134  for($z = $chunkZ - 1; $z <= $chunkZ + 1; ++$z){
135  for($x = $chunkX - 1; $x <= $chunkX + 1; ++$x){
136  if(!$this->isChunkGenerated($x, $z)){
137  $this->generateChunk($x, $z);
138  }
139  }
140  }
141 
142  $this->generator->populateChunk($chunkX, $chunkZ);
143  $this->setChunkPopulated($chunkX, $chunkZ);
144  }
145 
146  public function isChunkGenerated($chunkX, $chunkZ){
147  try{
148  return $this->getChunk($chunkX, $chunkZ)->isGenerated();
149  }catch(\Exception $e){
150  return false;
151  }
152  }
153 
154  public function isChunkPopulated($chunkX, $chunkZ){
155  try{
156  return $this->getChunk($chunkX, $chunkZ)->isPopulated();
157  }catch(\Exception $e){
158  return false;
159  }
160  }
161 
162  public function setChunkGenerated($chunkX, $chunkZ){
163  try{
164  $chunk = $this->getChunk($chunkX, $chunkZ);
165  $chunk->setGenerated(true);
166  $this->changes[Level::chunkHash($chunkX, $chunkZ)] = $chunk;
167  }catch(\Exception $e){
168  }
169  }
170 
171  public function setChunkPopulated($chunkX, $chunkZ){
172  try{
173  $chunk = $this->getChunk($chunkX, $chunkZ);
174  $chunk->setPopulated(true);
175  $this->changes[Level::chunkHash($chunkX, $chunkZ)] = $chunk;
176  }catch(\Exception $e){
177  }
178  }
179 
180  protected function requestChunk($chunkX, $chunkZ){
181  $chunk = $this->manager->requestChunk($this->levelID, $chunkX, $chunkZ);
182  $this->chunks[Level::chunkHash($chunkX, $chunkZ)] = $chunk;
183 
184  return $chunk;
185  }
186 
192  public function setChunk($chunkX, $chunkZ, FullChunk $chunk){
193  $this->chunks[$index = Level::chunkHash($chunkX, $chunkZ)] = $chunk;
194  $this->changes[$index] = $chunk;
195  if($chunk->isPopulated()){
196  //TODO: Queue to be sent
197  }
198  }
199 
209  public function getBlockIdAt($x, $y, $z){
210  try{
211  return $this->getChunk($x >> 4, $z >> 4)->getBlockId($x & 0x0f, $y & 0x7f, $z & 0x0f);
212  }catch(\Exception $e){
213  return 0;
214  }
215  }
216 
225  public function setBlockIdAt($x, $y, $z, $id){
226  try{
227  $this->getChunk($x >> 4, $z >> 4)->setBlockId($x & 0x0f, $y & 0x7f, $z & 0x0f, $id & 0xff);
228  }catch(\Exception $e){
229  }
230  }
231 
241  public function getBlockDataAt($x, $y, $z){
242  try{
243  return $this->getChunk($x >> 4, $z >> 4)->getBlockData($x & 0x0f, $y & 0x7f, $z & 0x0f);
244  }catch(\Exception $e){
245  return 0;
246  }
247  }
248 
257  public function setBlockDataAt($x, $y, $z, $data){
258  try{
259  $this->getChunk($x >> 4, $z >> 4)->setBlockData($x & 0x0f, $y & 0x7f, $z & 0x0f, $data & 0x0f);
260  }catch(\Exception $e){
261  }
262  }
263 
264  public function shutdown(){
265  foreach($this->chunks as $chunk){
266  //TODO: send generated chunks to be saved
267  }
268  }
269 
270 
271 }
static chunkHash($x, $z)
Definition: Level.php:230