mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-15 02:09:42 +00:00
Working Threaded Generation
This commit is contained in:
parent
392eb74901
commit
fa50cbf4b3
@ -519,16 +519,16 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
unset($this->chunksLoaded[$index]);
|
||||
}
|
||||
}else{*/
|
||||
foreach($this->getLevel()->getChunkEntities($this->lastChunk[0], $this->lastChunk[1]) as $entity){
|
||||
if($entity !== $this){
|
||||
$entity->spawnTo($this);
|
||||
}
|
||||
foreach($this->getLevel()->getChunkEntities($this->lastChunk[0], $this->lastChunk[1]) as $entity){
|
||||
if($entity !== $this){
|
||||
$entity->spawnTo($this);
|
||||
}
|
||||
foreach($this->getLevel()->getChunkTiles($this->lastChunk[0], $this->lastChunk[1]) as $tile){
|
||||
if($tile instanceof Spawnable){
|
||||
$tile->spawnTo($this);
|
||||
}
|
||||
}
|
||||
foreach($this->getLevel()->getChunkTiles($this->lastChunk[0], $this->lastChunk[1]) as $tile){
|
||||
if($tile instanceof Spawnable){
|
||||
$tile->spawnTo($this);
|
||||
}
|
||||
}
|
||||
//}
|
||||
$this->lastChunk = false;
|
||||
}
|
||||
@ -696,6 +696,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
if($needACK and $identifier !== null){
|
||||
$this->needACK[$identifier] = false;
|
||||
|
||||
return $identifier;
|
||||
}
|
||||
|
||||
@ -721,6 +722,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
if($needACK and $identifier !== null){
|
||||
$this->needACK[$identifier] = false;
|
||||
|
||||
return $identifier;
|
||||
}
|
||||
|
||||
@ -970,6 +972,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
return $i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1157,6 +1160,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->server->getPluginManager()->callEvent($ev = new PlayerLoginEvent($this, "Plugin reason"));
|
||||
if($ev->isCancelled()){
|
||||
$this->close($ev->getKickMessage(), "Plugin reason");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -65,8 +65,8 @@ namespace {
|
||||
}
|
||||
|
||||
namespace pocketmine {
|
||||
use LogLevel;
|
||||
use pocketmine\utils\Binary;
|
||||
use \LogLevel;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\wizard\Installer;
|
||||
|
@ -26,8 +26,6 @@
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\Chest;
|
||||
use pocketmine\block\Furnace;
|
||||
use pocketmine\command\CommandReader;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\ConsoleCommandSender;
|
||||
@ -40,10 +38,9 @@ use pocketmine\inventory\CraftingManager;
|
||||
use pocketmine\inventory\InventoryType;
|
||||
use pocketmine\inventory\Recipe;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\format\pmf\LevelFormat;
|
||||
use pocketmine\level\generator\Flat;
|
||||
use pocketmine\level\format\LevelProviderManager;
|
||||
use pocketmine\level\generator\GenerationRequestManager;
|
||||
use pocketmine\level\generator\Generator;
|
||||
use pocketmine\level\generator\Normal;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\level\LevelImport;
|
||||
use pocketmine\level\WorldGenerator;
|
||||
@ -61,10 +58,11 @@ use pocketmine\nbt\tag\Long;
|
||||
use pocketmine\nbt\tag\Short;
|
||||
use pocketmine\nbt\tag\String;
|
||||
use pocketmine\network\protocol\DataPacket;
|
||||
use pocketmine\network\protocol\Info;
|
||||
use pocketmine\network\query\QueryHandler;
|
||||
use pocketmine\network\query\QueryPacket;
|
||||
use pocketmine\network\RakLibInterface;
|
||||
use pocketmine\network\rcon\RCON;
|
||||
use pocketmine\network\SourceInterface;
|
||||
use pocketmine\network\upnp\UPnP;
|
||||
use pocketmine\permission\BanList;
|
||||
use pocketmine\permission\DefaultPermissions;
|
||||
@ -75,7 +73,6 @@ use pocketmine\scheduler\CallbackTask;
|
||||
use pocketmine\scheduler\SendUsageTask;
|
||||
use pocketmine\scheduler\ServerScheduler;
|
||||
use pocketmine\scheduler\TickScheduler;
|
||||
use pocketmine\tile\Sign;
|
||||
use pocketmine\tile\Tile;
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\Config;
|
||||
@ -83,7 +80,6 @@ use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\VersionString;
|
||||
use pocketmine\network\SourceInterface;
|
||||
|
||||
/**
|
||||
* The class that manages everything
|
||||
@ -116,6 +112,9 @@ class Server{
|
||||
/** @var ServerScheduler */
|
||||
private $scheduler = null;
|
||||
|
||||
/** @var GenerationRequestManager */
|
||||
private $generationManager = null;
|
||||
|
||||
/** @var TickScheduler */
|
||||
private $tickScheduler = null;
|
||||
|
||||
@ -493,6 +492,13 @@ class Server{
|
||||
return $this->scheduler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return GenerationRequestManager
|
||||
*/
|
||||
public function getGenerationManager(){
|
||||
return $this->generationManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
@ -781,17 +787,32 @@ class Server{
|
||||
* @return bool
|
||||
*/
|
||||
public function isLevelLoaded($name){
|
||||
return isset($this->levels[$name]);
|
||||
return $this->getLevelByName($name) instanceof Level;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param int $levelId
|
||||
*
|
||||
* @return Level
|
||||
*/
|
||||
public function getLevel($name){
|
||||
if(isset($this->levels[$name])){
|
||||
return $this->levels[$name];
|
||||
public function getLevel($levelId){
|
||||
if(isset($this->levels[$levelId])){
|
||||
return $this->levels[$levelId];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return Level
|
||||
*/
|
||||
public function getLevelByName($name){
|
||||
foreach($this->getLevels() as $level){
|
||||
if($level->getName() === $name){
|
||||
return $level;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -802,8 +823,8 @@ class Server{
|
||||
* @param bool $forceUnload
|
||||
*/
|
||||
public function unloadLevel(Level $level, $forceUnload = false){
|
||||
if((!$level->isLoaded() or $level->unload($forceUnload) === true) and $this->isLevelLoaded($level->getName())){
|
||||
unset($this->levels[$level->getName()]);
|
||||
if($level->unload($forceUnload) === true and $this->isLevelLoaded($level->getName())){
|
||||
unset($this->levels[$level->getID()]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -829,20 +850,20 @@ class Server{
|
||||
}
|
||||
|
||||
$path = $this->getDataPath() . "worlds/" . $name . "/";
|
||||
$this->logger->info("Preparing level \"" . $name . "\"");
|
||||
$level = new LevelFormat($path . "level.pmf");
|
||||
if(!$level->isLoaded){
|
||||
|
||||
$provider = LevelProviderManager::getProvider($path);
|
||||
if($provider === null){
|
||||
$this->logger->error("Could not load level \"" . $name . "\"");
|
||||
|
||||
return false;
|
||||
}
|
||||
//$entities = new Config($path."entities.yml", Config::YAML);
|
||||
if(file_exists($path . "tileEntities.yml")){
|
||||
@rename($path . "tileEntities.yml", $path . "tiles.yml");
|
||||
}
|
||||
//if(file_exists($path . "tileEntities.yml")){
|
||||
// @rename($path . "tileEntities.yml", $path . "tiles.yml");
|
||||
//}
|
||||
|
||||
$level = new Level($this, $level, $name);
|
||||
$this->levels[$level->getName()] = $level;
|
||||
$level = new Level($this, $path, $provider);
|
||||
$this->levels[$level->getID()] = $level;
|
||||
/*foreach($entities->getAll() as $entity){
|
||||
if(!isset($entity["id"])){
|
||||
break;
|
||||
@ -872,7 +893,7 @@ class Server{
|
||||
}
|
||||
}*/
|
||||
|
||||
if(file_exists($path . "tiles.yml")){
|
||||
/*if(file_exists($path . "tiles.yml")){
|
||||
$tiles = new Config($path . "tiles.yml", Config::YAML);
|
||||
foreach($tiles->getAll() as $tile){
|
||||
if(!isset($tile["id"])){
|
||||
@ -934,7 +955,7 @@ class Server{
|
||||
}
|
||||
unlink($path . "tiles.yml");
|
||||
$level->save(true, true);
|
||||
}
|
||||
}*/
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -954,20 +975,32 @@ class Server{
|
||||
return false;
|
||||
}
|
||||
|
||||
$seed = $seed === null ? Binary::readInt(Utils::getRandomBytes(4, false)) : (int) $seed;
|
||||
|
||||
if($generator !== null and class_exists($generator) and is_subclass_of($generator, "pocketmine\\level\\generator\\Generator")){
|
||||
$generator = new $generator($options);
|
||||
}else{
|
||||
if(strtoupper($this->getLevelType()) == "FLAT"){
|
||||
$generator = new Flat($options);
|
||||
$generator = Generator::getGenerator("flat");
|
||||
$options["preset"] = $this->getConfigString("generator-settings", "");
|
||||
}else{
|
||||
$generator = new Normal($options);
|
||||
$generator = Generator::getGenerator("normal");
|
||||
}
|
||||
}
|
||||
|
||||
$gen = new WorldGenerator($this, $generator, $name, $seed === null ? Binary::readInt(Utils::getRandomBytes(4, false)) : (int) $seed);
|
||||
$gen->generate();
|
||||
$gen->close();
|
||||
$provider = "pocketmine\\level\\format\\anvil\\Anvil";
|
||||
|
||||
$path = $this->getDataPath() . "worlds/" . $name . "/";
|
||||
/** @var \pocketmine\level\format\LevelProvider $provider */
|
||||
$provider::generate($path, $name, $seed, $generator, $options);
|
||||
|
||||
$level = new Level($this, $path, $provider);
|
||||
$this->levels[$level->getID()] = $level;
|
||||
for($Z = 6; $Z <= 10; ++$Z){
|
||||
for($X = 6; $X <= 10; ++$X){
|
||||
$level->generateChunk($X, $Z);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -982,7 +1015,7 @@ class Server{
|
||||
return false;
|
||||
}
|
||||
$path = $this->getDataPath() . "worlds/" . $name . "/";
|
||||
if(!($this->getLevel($name) instanceof Level) and !file_exists($path . "level.pmf")){
|
||||
if(!($this->getLevelByName($name) instanceof Level) and !file_exists($path . "level.pmf")){
|
||||
if(file_exists($path)){
|
||||
$level = new LevelImport($path);
|
||||
if($level->import() === false){ //Try importing a world
|
||||
@ -1318,6 +1351,10 @@ class Server{
|
||||
|
||||
$this->enablePlugins(PluginLoadOrder::STARTUP);
|
||||
|
||||
$this->generationManager = new GenerationRequestManager($this);
|
||||
|
||||
LevelProviderManager::addProvider($this, "pocketmine\\level\\format\\anvil\\Anvil");
|
||||
|
||||
|
||||
Generator::addGenerator("pocketmine\\level\\generator\\Flat", "flat");
|
||||
Generator::addGenerator("pocketmine\\level\\generator\\Normal", "normal");
|
||||
@ -1333,10 +1370,9 @@ class Server{
|
||||
if($this->loadLevel($default) === false){
|
||||
$seed = $this->getConfigInt("level-seed", time());
|
||||
$this->generateLevel($default, $seed === 0 ? time() : $seed);
|
||||
$this->loadLevel($default);
|
||||
}
|
||||
|
||||
$this->setDefaultLevel($this->getLevel($default));
|
||||
$this->setDefaultLevel($this->getLevelByName($default));
|
||||
}
|
||||
|
||||
|
||||
@ -1564,6 +1600,7 @@ class Server{
|
||||
foreach($this->getLevels() as $level){
|
||||
$this->unloadLevel($level, true);
|
||||
}
|
||||
$this->generationManager->shutdown();
|
||||
|
||||
HandlerList::unregisterAll();
|
||||
$this->scheduler->cancelAllTasks();
|
||||
@ -1629,6 +1666,7 @@ class Server{
|
||||
$lastLoop = 0;
|
||||
}
|
||||
}
|
||||
$this->generationManager->handlePackets();
|
||||
|
||||
if(($ticks = $this->tick()) !== true){
|
||||
++$lastLoop;
|
||||
@ -1717,7 +1755,7 @@ class Server{
|
||||
$dump .= "server.properties: " . var_export($p, true) . "\r\n\r\n\r\n";
|
||||
if(class_exists("pocketmine\\plugin\\PluginManager", false)){
|
||||
$dump .= "Loaded plugins:\r\n";
|
||||
foreach(PluginManager::getPlugins() as $p){
|
||||
foreach($this->getPluginManager()->getPlugins() as $p){
|
||||
$d = $p->getDescription();
|
||||
$dump .= $d->getName() . " " . $d->getVersion() . " by " . implode(", ", $d->getAuthors()) . "\r\n";
|
||||
}
|
||||
@ -1751,6 +1789,7 @@ class Server{
|
||||
$lastLoop = 0;
|
||||
}
|
||||
}
|
||||
$this->generationManager->handlePackets();
|
||||
|
||||
if(($ticks = $this->tick()) !== true){
|
||||
++$lastLoop;
|
||||
|
@ -43,12 +43,12 @@ use pocketmine\nbt\tag\Byte;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
use pocketmine\nbt\tag\Float;
|
||||
use pocketmine\nbt\tag\Short;
|
||||
use pocketmine\Network;
|
||||
use pocketmine\network\protocol\MoveEntityPacket_PosRot;
|
||||
use pocketmine\network\protocol\MovePlayerPacket;
|
||||
use pocketmine\network\protocol\RemoveEntityPacket;
|
||||
use pocketmine\network\protocol\SetEntityMotionPacket;
|
||||
use pocketmine\network\protocol\SetTimePacket;
|
||||
use pocketmine\Network;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\plugin\Plugin;
|
||||
use pocketmine\Server;
|
||||
|
@ -29,10 +29,10 @@ use pocketmine\nbt\tag\Byte;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
use pocketmine\nbt\tag\Enum;
|
||||
use pocketmine\nbt\tag\Short;
|
||||
use pocketmine\Network;
|
||||
use pocketmine\network\protocol\AddPlayerPacket;
|
||||
use pocketmine\network\protocol\RemovePlayerPacket;
|
||||
use pocketmine\network\protocol\SetEntityMotionPacket;
|
||||
use pocketmine\Network;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
|
@ -25,7 +25,6 @@ use pocketmine\entity\Entity;
|
||||
use pocketmine\event\Cancellable;
|
||||
use pocketmine\Event;
|
||||
use pocketmine\level\Position;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
|
||||
class EntityTeleportEvent extends EntityEvent implements Cancellable{
|
||||
public static $handlerList = null;
|
||||
|
@ -22,7 +22,6 @@
|
||||
namespace pocketmine\event\player;
|
||||
|
||||
use pocketmine\event\Cancellable;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\Player;
|
||||
|
||||
/**
|
||||
|
@ -21,8 +21,8 @@
|
||||
|
||||
namespace pocketmine\event\player;
|
||||
|
||||
use pocketmine\event\Cancellable;
|
||||
use pocketmine\Event;
|
||||
use pocketmine\event\Cancellable;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\Player;
|
||||
|
||||
|
@ -21,8 +21,8 @@
|
||||
|
||||
namespace pocketmine\event\server;
|
||||
|
||||
use pocketmine\event;
|
||||
use pocketmine\event\Cancellable;
|
||||
use pocketmine\event;
|
||||
use pocketmine\network\protocol\DataPacket;
|
||||
use pocketmine\Player;
|
||||
|
||||
|
@ -21,8 +21,8 @@
|
||||
|
||||
namespace pocketmine\event\server;
|
||||
|
||||
use pocketmine\event;
|
||||
use pocketmine\event\Cancellable;
|
||||
use pocketmine\event;
|
||||
use pocketmine\network\protocol\DataPacket;
|
||||
use pocketmine\Player;
|
||||
|
||||
|
@ -34,7 +34,6 @@ class Painting extends Item{
|
||||
|
||||
public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
|
||||
if($target->isTransparent === false and $face > 1 and $block->isSolid === false){
|
||||
$server = Server::getInstance();
|
||||
$faces = array(
|
||||
2 => 1,
|
||||
3 => 3,
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,77 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\level;
|
||||
|
||||
use pocketmine\level\format\pmf\LevelFormat;
|
||||
use pocketmine\level\generator\Generator;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\Random;
|
||||
use pocketmine\utils\Utils;
|
||||
|
||||
class WorldGenerator{
|
||||
private $seed, $level, $path, $random, $generator, $server;
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param Generator $generator
|
||||
* @param string $name
|
||||
* @param int $seed
|
||||
*/
|
||||
public function __construct(Server $server, Generator $generator, $name, $seed = null){
|
||||
$this->seed = $seed !== null ? (int) $seed : Binary::readInt(Utils::getRandomBytes(4, false));
|
||||
$this->random = new Random($this->seed);
|
||||
$this->server = $server;
|
||||
$this->path = $this->server->getDataPath() . "worlds/" . $name . "/";
|
||||
$this->generator = $generator;
|
||||
$level = new LevelFormat($this->path . "level.pmf", array(
|
||||
"name" => $name,
|
||||
"seed" => $this->seed,
|
||||
"time" => 0,
|
||||
"spawnX" => 128,
|
||||
"spawnY" => 128,
|
||||
"spawnZ" => 128,
|
||||
"height" => 8,
|
||||
"generator" => $this->generator->getName(),
|
||||
"generatorSettings" => $this->generator->getSettings(),
|
||||
"extra" => ""
|
||||
));
|
||||
$this->level = new Level($this->server, $level, $name);
|
||||
}
|
||||
|
||||
public function generate(){
|
||||
$this->generator->init($this->level, $this->random);
|
||||
|
||||
for($Z = 6; $Z <= 10; ++$Z){
|
||||
for($X = 6; $X <= 10; ++$X){
|
||||
$this->level->level->loadChunk($X, $Z);
|
||||
}
|
||||
}
|
||||
|
||||
$this->level->setSpawn($this->generator->getSpawn());
|
||||
}
|
||||
|
||||
public function close(){
|
||||
$this->level->close();
|
||||
}
|
||||
|
||||
}
|
@ -151,13 +151,24 @@ interface Chunk{
|
||||
*/
|
||||
public function getChunkSnapshot($includeMaxBlockY = true, $includeBiome = false, $includeBiomeTemp = false);
|
||||
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
*/
|
||||
public function addEntity(Entity $entity);
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
*/
|
||||
public function removeEntity(Entity $entity);
|
||||
|
||||
/**
|
||||
* @param Tile $tile
|
||||
*/
|
||||
public function addTile(Tile $tile);
|
||||
|
||||
/**
|
||||
* @param Tile $tile
|
||||
*/
|
||||
public function removeTile(Tile $tile);
|
||||
|
||||
/**
|
||||
|
@ -45,6 +45,29 @@ interface LevelProvider{
|
||||
*/
|
||||
public static function isValid($path);
|
||||
|
||||
/**
|
||||
* Generate the needed files in the path given
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $name
|
||||
* @param int $seed
|
||||
* @param string $generator
|
||||
* @param array[] $options
|
||||
*/
|
||||
public static function generate($path, $name, $seed, $generator, array $options = []);
|
||||
|
||||
/**
|
||||
* Returns the generator name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGenerator();
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getGeneratorOptions();
|
||||
|
||||
/**
|
||||
* Gets the Chunk object
|
||||
* This method must be implemented by all the level formats.
|
||||
@ -92,6 +115,14 @@ interface LevelProvider{
|
||||
*/
|
||||
public function isChunkGenerated($X, $Z);
|
||||
|
||||
/**
|
||||
* @param int $X
|
||||
* @param int $Z
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isChunkPopulated($X, $Z);
|
||||
|
||||
/**
|
||||
* @param int $X
|
||||
* @param int $Z
|
||||
@ -100,6 +131,15 @@ interface LevelProvider{
|
||||
*/
|
||||
public function isChunkLoaded($X, $Z);
|
||||
|
||||
/**
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
* @param SimpleChunk $chunk
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function setChunk($chunkX, $chunkZ, SimpleChunk $chunk);
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
@ -115,6 +155,16 @@ interface LevelProvider{
|
||||
*/
|
||||
public function setTime($value);
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getSeed();
|
||||
|
||||
/**
|
||||
* @param int $value
|
||||
*/
|
||||
public function setSeed($value);
|
||||
|
||||
/**
|
||||
* @return Vector3
|
||||
*/
|
||||
@ -135,4 +185,6 @@ interface LevelProvider{
|
||||
*/
|
||||
public function getLevel();
|
||||
|
||||
public function close();
|
||||
|
||||
}
|
59
src/pocketmine/level/format/LevelProviderManager.php
Normal file
59
src/pocketmine/level/format/LevelProviderManager.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\level\format;
|
||||
|
||||
use pocketmine\Server;
|
||||
|
||||
abstract class LevelProviderManager{
|
||||
protected static $providers = [];
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param string $class
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function addProvider(Server $server, $class){
|
||||
if(!is_subclass_of($class, "pocketmine\\level\\format\\LevelProvider")){
|
||||
throw new \Exception("Class is not a subclass of LevelProvider");
|
||||
}
|
||||
self::$providers[strtolower($class)] = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a LevelProvider class for this path, or null
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getProvider($path){
|
||||
foreach(self::$providers as $provider){
|
||||
/** @var $provider LevelProvider */
|
||||
if($provider::isValid($path)){
|
||||
return $provider;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -125,9 +125,9 @@ class SimpleChunk{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-127
|
||||
* @param int $z 0-15
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-127
|
||||
* @param int $z 0-15
|
||||
* @param int $blockId 0-255
|
||||
*/
|
||||
public function setBlockId($x, $y, $z, $blockId){
|
||||
@ -151,9 +151,9 @@ class SimpleChunk{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-127
|
||||
* @param int $z 0-15
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-127
|
||||
* @param int $z 0-15
|
||||
* @param int $data 0-15
|
||||
*/
|
||||
public function setBlockData($x, $y, $z, $data){
|
||||
@ -236,6 +236,7 @@ class SimpleChunk{
|
||||
$offset += 2048;
|
||||
}
|
||||
}
|
||||
|
||||
return new SimpleChunk($chunkX, $chunkZ, $flags, $ids, $meta);
|
||||
}
|
||||
|
||||
|
@ -22,12 +22,21 @@
|
||||
namespace pocketmine\level\format\anvil;
|
||||
|
||||
use pocketmine\level\format\generic\BaseLevelProvider;
|
||||
use pocketmine\level\format\SimpleChunk;
|
||||
use pocketmine\level\generator\Generator;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\Byte;
|
||||
use pocketmine\nbt\tag\ByteArray;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
use pocketmine\nbt\tag\Int;
|
||||
use pocketmine\nbt\tag\Long;
|
||||
use pocketmine\nbt\tag\String;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Anvil extends BaseLevelProvider{
|
||||
|
||||
/** @var RegionLoader */
|
||||
/** @var RegionLoader[] */
|
||||
protected $regions = [];
|
||||
|
||||
/** @var Chunk[] */
|
||||
@ -38,6 +47,37 @@ class Anvil extends BaseLevelProvider{
|
||||
return file_exists(realpath($path) . "level.dat") and file_exists(realpath($path) . "region/");
|
||||
}
|
||||
|
||||
public static function generate($path, $name, $seed, $generator, array $options = []){
|
||||
@mkdir($path, 0777, true);
|
||||
@mkdir($path . "/region", 0777);
|
||||
//TODO, add extra details
|
||||
$levelData = new Compound("Data", [
|
||||
"hardcore" => new Byte("hardcore", 0),
|
||||
"initialized" => new Byte("initialized", 1),
|
||||
"GameType" => new Int("GameType", 0),
|
||||
"generatorVersion" => new Int("generatorVersion", 1), //2 in MCPE
|
||||
"SpawnX" => new Int("SpawnX", 128),
|
||||
"SpawnY" => new Int("SpawnY", 70),
|
||||
"SpawnZ" => new Int("SpawnZ", 128),
|
||||
"version" => new Int("version", 19133),
|
||||
"DayTime" => new Int("DayTime", 0),
|
||||
"LastPlayed" => new Long("LastPlayed", microtime(true) * 1000),
|
||||
"RandomSeed" => new Long("RandomSeed", $seed),
|
||||
"SizeOnDisk" => new Long("SizeOnDisk", 0),
|
||||
"Time" => new Long("Time", 0),
|
||||
"generatorName" => new String("generatorName", Generator::getGeneratorName($generator)),
|
||||
"generatorOptions" => new String("generatorOptions", isset($options["preset"]) ? $options["preset"] : ""),
|
||||
"LevelName" => new String("LevelName", $name),
|
||||
"GameRules" => new Compound("GameRules", [])
|
||||
]);
|
||||
$nbt = new NBT(NBT::BIG_ENDIAN);
|
||||
$nbt->setData(new Compound(null, [
|
||||
"Data" => $levelData
|
||||
]));
|
||||
$buffer = $nbt->writeCompressed();
|
||||
@file_put_contents($path . "level.dat", $buffer);
|
||||
}
|
||||
|
||||
public static function getRegionIndex($chunkX, $chunkZ, &$x, &$z){
|
||||
$x = $chunkX >> 5;
|
||||
$z = $chunkZ >> 5;
|
||||
@ -47,6 +87,14 @@ class Anvil extends BaseLevelProvider{
|
||||
$this->chunks = [];
|
||||
}
|
||||
|
||||
public function getGenerator(){
|
||||
return $this->levelData["generatorName"];
|
||||
}
|
||||
|
||||
public function getGeneratorOptions(){
|
||||
return ["preset" => $this->levelData["generatorOptions"]];
|
||||
}
|
||||
|
||||
public function getLoadedChunks(){
|
||||
return $this->chunks;
|
||||
}
|
||||
@ -88,12 +136,14 @@ class Anvil extends BaseLevelProvider{
|
||||
}
|
||||
|
||||
unset($this->chunks[Level::chunkHash($x, $z)]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function saveChunk($x, $z){
|
||||
if($this->isChunkLoaded($x, $z)){
|
||||
$this->getRegion($x >> 5, $z >> 5)->writeChunk($this->getChunk($x, $z));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -107,10 +157,18 @@ class Anvil extends BaseLevelProvider{
|
||||
* @return RegionLoader
|
||||
*/
|
||||
protected function getRegion($x, $z){
|
||||
$index = $x.":".$z;
|
||||
$index = $x . ":" . $z;
|
||||
|
||||
return isset($this->regions[$index]) ? $this->regions[$index] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
* @param bool $create
|
||||
*
|
||||
* @return Chunk
|
||||
*/
|
||||
public function getChunk($chunkX, $chunkZ, $create = false){
|
||||
$index = Level::chunkHash($chunkX, $chunkZ);
|
||||
if(isset($this->chunks[$index])){
|
||||
@ -120,18 +178,55 @@ class Anvil extends BaseLevelProvider{
|
||||
}
|
||||
|
||||
$this->loadChunk($chunkX, $chunkZ);
|
||||
|
||||
return $this->getChunk($chunkX, $chunkZ, false);
|
||||
}
|
||||
|
||||
public function setChunk($chunkX, $chunkZ, SimpleChunk $chunk){
|
||||
if($chunk->isGenerated() === false){
|
||||
$this->unloadChunk($chunkX, $chunkZ, false);
|
||||
$region = $this->getRegion($chunkX >> 4, $chunkZ >> 4);
|
||||
$region->removeChunk($chunkX - $region->getX() * 32, $chunkZ - $region->getZ() * 32);
|
||||
$this->loadChunk($chunkX, $chunkZ);
|
||||
}else{
|
||||
$newChunk = $this->getChunk($chunkX, $chunkZ, true);
|
||||
for($y = 0; $y < 8; ++$y){
|
||||
$section = new ChunkSection(new Compound(null, [
|
||||
"Y" => new Byte("Y", $y),
|
||||
"Blocks" => new ByteArray("Blocks", $chunk->getSectionIds($y)),
|
||||
"Data" => new ByteArray("Data", $chunk->getSectionData($y)),
|
||||
"BlockLight" => new ByteArray("BlockLight", str_repeat("\xff", 2048)), //TODO
|
||||
"SkyLight" => new ByteArray("SkyLight", str_repeat("\x00", 2048)) //TODO
|
||||
]));
|
||||
$newChunk->setSection($y, $section);
|
||||
}
|
||||
if($chunk->isPopulated()){
|
||||
$newChunk->setPopulated(1);
|
||||
}
|
||||
$this->chunks[Level::chunkHash($chunkX, $chunkZ)] = $newChunk;
|
||||
$this->saveChunk($chunkX, $chunkZ);
|
||||
}
|
||||
}
|
||||
|
||||
public function isChunkGenerated($chunkX, $chunkZ){
|
||||
if(($region = $this->getRegion($chunkX >> 5, $chunkZ >> 5)) instanceof RegionLoader){
|
||||
return $region->chunkExists($chunkX - $region->getX() * 32, $chunkZ - $region->getZ() * 32);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isChunkPopulated($chunkX, $chunkZ){
|
||||
$chunk = $this->getChunk($chunkX, $chunkZ);
|
||||
if($chunk instanceof Chunk){
|
||||
return $chunk->isPopulated();
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function loadRegion($x, $z){
|
||||
$index = $x.":".$z;
|
||||
$index = $x . ":" . $z;
|
||||
if(isset($this->regions[$index])){
|
||||
return true;
|
||||
}
|
||||
@ -140,4 +235,13 @@ class Anvil extends BaseLevelProvider{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function close(){
|
||||
$this->unloadChunks();
|
||||
foreach($this->regions as $index => $region){
|
||||
$region->doSlowCleanUp();
|
||||
$region->close();
|
||||
unset($this->regions[$index]);
|
||||
}
|
||||
}
|
||||
}
|
@ -24,8 +24,8 @@ namespace pocketmine\level\format\anvil;
|
||||
use pocketmine\level\format\generic\BaseChunk;
|
||||
use pocketmine\level\format\generic\EmptyChunkSection;
|
||||
use pocketmine\level\format\LevelProvider;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\Byte;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
use pocketmine\nbt\tag\Enum;
|
||||
|
||||
@ -68,11 +68,33 @@ class Chunk extends BaseChunk{
|
||||
$sections = [];
|
||||
foreach($this->nbt->Sections as $section){
|
||||
if($section instanceof Compound){
|
||||
$sections[(int) $section["Y"]] = new ChunkSection($section);
|
||||
$y = (int) $section["Y"];
|
||||
if($y < 8){
|
||||
$sections[$y] = new ChunkSection($section);
|
||||
}
|
||||
}
|
||||
}
|
||||
for($y = 0; $y < 8; ++$y){
|
||||
if(!isset($sections[$y])){
|
||||
$sections[$y] = new EmptyChunkSection($y);
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct($level, $this->nbt["xPos"], $this->nbt["zPos"], $sections, $this->nbt["Entities"], $this->nbt["TileEntities"]);
|
||||
parent::__construct($level, $this->nbt["xPos"], $this->nbt["zPos"], $sections, $this->nbt->Entities->getValue(), $this->nbt->TileEntities->getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isPopulated(){
|
||||
return $this->nbt["TerrainPopulated"] > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $value
|
||||
*/
|
||||
public function setPopulated($value = 1){
|
||||
$this->nbt->TerrainPopulated = new Byte("TerrainPopulated", $value);
|
||||
}
|
||||
|
||||
public function getChunkSnapshot($includeMaxBlockY = true, $includeBiome = false, $includeBiomeTemp = false){
|
||||
@ -103,7 +125,7 @@ class Chunk extends BaseChunk{
|
||||
//TODO: maxBlockY, biomeMap, biomeTemp
|
||||
|
||||
//TODO: time
|
||||
return new ChunkSnapshot($this->getX(), $this->getZ(), $this->getLevel()->getName(), 0/*$this->getLevel()->getTime()*/, $blockId, $blockData, $blockSkyLight, $blockLight, $emptySections, null, null, null, null);
|
||||
return new ChunkSnapshot($this->getX(), $this->getZ(), $this->getLevel()->getName(), 0 /*$this->getLevel()->getTime()*/, $blockId, $blockData, $blockSkyLight, $blockLight, $emptySections, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,8 +27,8 @@ class ChunkSnapshot extends BaseChunkSnapshot{
|
||||
|
||||
public function getBlockId($x, $y, $z){
|
||||
return ord($this->blockId{
|
||||
(($y >> 4) << 12) //get section index
|
||||
+ ($y << 8) + ($z << 4) + $x //get block index in section
|
||||
(($y >> 4) << 12) //get section index
|
||||
+ ($y << 8) + ($z << 4) + $x //get block index in section
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -103,6 +103,9 @@ class RegionLoader{
|
||||
|
||||
if($length <= 0){ //Not yet generated
|
||||
$this->generateChunk($x, $z);
|
||||
fseek($this->filePointer, $this->locationTable[$index][0] << 12);
|
||||
$length = Binary::readInt(fread($this->filePointer, 4));
|
||||
$compression = ord(fgetc($this->filePointer));
|
||||
}
|
||||
|
||||
if($length > ($this->locationTable[$index][1] << 12)){ //Invalid chunk, bigger than defined number of sectors
|
||||
@ -133,7 +136,7 @@ class RegionLoader{
|
||||
public function generateChunk($x, $z){
|
||||
$nbt = new Compound("Level", []);
|
||||
$nbt->xPos = new Int("xPos", ($this->getX() * 32) + $x);
|
||||
$nbt->zPos = new Int("xPos", ($this->getZ() * 32) + $z);
|
||||
$nbt->zPos = new Int("zPos", ($this->getZ() * 32) + $z);
|
||||
$nbt->LastUpdate = new Long("LastUpdate", 0);
|
||||
$nbt->LightPopulated = new Byte("LightPopulated", 0);
|
||||
$nbt->TerrainPopulated = new Byte("TerrainPopulated", 0);
|
||||
@ -170,6 +173,12 @@ class RegionLoader{
|
||||
fwrite($this->filePointer, str_pad(Binary::writeInt($length) . chr(self::COMPRESSION_ZLIB) . $chunkData, $sectors << 12, "\x00", STR_PAD_RIGHT));
|
||||
}
|
||||
|
||||
public function removeChunk($x, $z){
|
||||
$index = self::getChunkOffset($x, $z);
|
||||
$this->locationTable[$index][0] = 0;
|
||||
$this->locationTable[$index][1] = 0;
|
||||
}
|
||||
|
||||
public function writeChunk(Chunk $chunk){
|
||||
$nbt = $chunk->getNBT();
|
||||
$nbt->Sections = new Enum("Sections", []);
|
||||
@ -215,6 +224,11 @@ class RegionLoader{
|
||||
return $x + ($z << 5);
|
||||
}
|
||||
|
||||
public function close(){
|
||||
flock($this->filePointer, LOCK_UN);
|
||||
fclose($this->filePointer);
|
||||
}
|
||||
|
||||
public function doSlowCleanUp(){
|
||||
for($i = 0; $i < 1024; ++$i){
|
||||
if($this->locationTable[$i][0] === 0 or $this->locationTable[$i][1] === 0){
|
||||
|
@ -26,7 +26,6 @@ use pocketmine\entity\Entity;
|
||||
use pocketmine\level\format\Chunk;
|
||||
use pocketmine\level\format\ChunkSection;
|
||||
use pocketmine\level\format\LevelProvider;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
use pocketmine\nbt\tag\String;
|
||||
use pocketmine\tile\Chest;
|
||||
@ -58,6 +57,8 @@ abstract class BaseChunk implements Chunk{
|
||||
* @param ChunkSection[] $sections
|
||||
* @param Compound[] $entities
|
||||
* @param Compound[] $tiles
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function __construct(LevelProvider $level, $x, $z, array $sections, array $entities = [], array $tiles = []){
|
||||
$this->level = new \WeakRef($level);
|
||||
@ -68,14 +69,11 @@ abstract class BaseChunk implements Chunk{
|
||||
$this->sections[$Y] = $section;
|
||||
}else{
|
||||
trigger_error("Received invalid ChunkSection instance", E_USER_ERROR);
|
||||
|
||||
return;
|
||||
throw new \Exception("Received invalid ChunkSection instance");
|
||||
}
|
||||
|
||||
if($section >= self::SECTION_COUNT){
|
||||
trigger_error("Invalid amount of chunks", E_USER_WARNING);
|
||||
|
||||
return;
|
||||
if($Y >= self::SECTION_COUNT){
|
||||
throw new \Exception("Invalid amount of chunks");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
namespace pocketmine\level\format\generic;
|
||||
|
||||
use pocketmine\level\format\LevelProvider;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
@ -73,14 +74,22 @@ abstract class BaseLevelProvider implements LevelProvider{
|
||||
$this->levelData->Time = new Int("Time", (int) $value);
|
||||
}
|
||||
|
||||
public function getSeed(){
|
||||
return $this->levelData["RandomSeed"];
|
||||
}
|
||||
|
||||
public function setSeed($value){
|
||||
$this->levelData->RandomSeed = new Int("RandomSeed", (int) $value);
|
||||
}
|
||||
|
||||
public function getSpawn(){
|
||||
return new Vector3($this->levelData["SpawnX"], $this->levelData["SpawnY"], $this->levelData["SpawnZ"]);
|
||||
}
|
||||
|
||||
public function setSpawn(Vector3 $pos){
|
||||
$this->levelData->SpawnX = new Int("SpawnX", $pos->x);
|
||||
$this->levelData->SpawnY = new Int("SpawnY", $pos->y);
|
||||
$this->levelData->SpawnZ = new Int("SpawnZ", $pos->z);
|
||||
$this->levelData->SpawnX = new Int("SpawnX", (int) $pos->x);
|
||||
$this->levelData->SpawnY = new Int("SpawnY", (int) $pos->y);
|
||||
$this->levelData->SpawnZ = new Int("SpawnZ", (int) $pos->z);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,6 +27,17 @@ use pocketmine\level\format\ChunkSection;
|
||||
* Stub used to detect empty chunks
|
||||
*/
|
||||
class EmptyChunkSection implements ChunkSection{
|
||||
|
||||
private $y;
|
||||
|
||||
public function __construct($y){
|
||||
$this->y = $y;
|
||||
}
|
||||
|
||||
final public function getY(){
|
||||
return $this->y;
|
||||
}
|
||||
|
||||
final public function getBlockId($x, $y, $z){
|
||||
return 0;
|
||||
}
|
||||
@ -39,6 +50,15 @@ class EmptyChunkSection implements ChunkSection{
|
||||
return "\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
}
|
||||
|
||||
final public function getBlock($x, $y, $z, &$id = null, &$meta = null){
|
||||
$id = 0;
|
||||
$meta = 0;
|
||||
}
|
||||
|
||||
final public function setBlock($x, $y, $z, $id = null, $meta = null){
|
||||
throw new \Exception("Tried to modify an empty Chunk");
|
||||
}
|
||||
|
||||
public function getIdArray(){
|
||||
return str_repeat("\x00", 4096);
|
||||
}
|
||||
@ -56,7 +76,7 @@ class EmptyChunkSection implements ChunkSection{
|
||||
}
|
||||
|
||||
final public function setBlockId($x, $y, $z, $id){
|
||||
|
||||
throw new \Exception("Tried to modify an empty Chunk");
|
||||
}
|
||||
|
||||
final public function getBlockData($x, $y, $z){
|
||||
@ -64,7 +84,7 @@ class EmptyChunkSection implements ChunkSection{
|
||||
}
|
||||
|
||||
final public function setBlockData($x, $y, $z, $data){
|
||||
|
||||
throw new \Exception("Tried to modify an empty Chunk");
|
||||
}
|
||||
|
||||
final public function getBlockLight($x, $y, $z){
|
||||
@ -72,7 +92,7 @@ class EmptyChunkSection implements ChunkSection{
|
||||
}
|
||||
|
||||
final public function setBlockLight($x, $y, $z, $level){
|
||||
|
||||
throw new \Exception("Tried to modify an empty Chunk");
|
||||
}
|
||||
|
||||
final public function getBlockSkyLight($x, $y, $z){
|
||||
@ -80,6 +100,6 @@ class EmptyChunkSection implements ChunkSection{
|
||||
}
|
||||
|
||||
final public function setBlockSkyLight($x, $y, $z, $level){
|
||||
|
||||
throw new \Exception("Tried to modify an empty Chunk");
|
||||
}
|
||||
}
|
@ -21,7 +21,6 @@
|
||||
|
||||
namespace pocketmine\level\generator;
|
||||
|
||||
use pocketmine\level\generator\populator\Populator;
|
||||
use pocketmine\block\CoalOre;
|
||||
use pocketmine\block\DiamondOre;
|
||||
use pocketmine\block\Dirt;
|
||||
@ -33,7 +32,7 @@ use pocketmine\block\RedstoneOre;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\format\SimpleChunk;
|
||||
use pocketmine\level\generator\populator\Ore;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\level\generator\populator\Populator;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
@ -100,7 +99,7 @@ class Flat extends Generator{
|
||||
$b = Item::fromString($b);
|
||||
$cnt = $matches[2][$i] === "" ? 1 : intval($matches[2][$i]);
|
||||
for($cY = $y, $y += $cnt; $cY < $y; ++$cY){
|
||||
$this->structure[$cY] = [$b->getID(),$b->getDamage()];
|
||||
$this->structure[$cY] = [$b->getID(), $b->getDamage()];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,6 @@ namespace pocketmine\level\generator;
|
||||
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\level\format\SimpleChunk;
|
||||
use pocketmine\level\generator\Generator;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
@ -77,6 +76,7 @@ class GenerationChunkManager implements ChunkManager{
|
||||
*/
|
||||
public function getChunk($chunkX, $chunkZ){
|
||||
$index = Level::chunkHash($chunkX, $chunkZ);
|
||||
|
||||
return !isset($this->chunks[$index]) ? $this->requestChunk($chunkX, $chunkZ) : $this->chunks[$index];
|
||||
}
|
||||
|
||||
@ -112,6 +112,7 @@ class GenerationChunkManager implements ChunkManager{
|
||||
protected function requestChunk($chunkX, $chunkZ){
|
||||
$chunk = $this->manager->requestChunk($this->levelID, $chunkX, $chunkZ);
|
||||
$this->chunks[Level::chunkHash($chunkX, $chunkZ)] = $chunk;
|
||||
|
||||
return $chunk;
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,6 @@ class GenerationManager{
|
||||
const PACKET_SHUTDOWN = 0xff;
|
||||
|
||||
|
||||
|
||||
protected $socket;
|
||||
/** @var \Logger */
|
||||
protected $logger;
|
||||
@ -138,6 +137,9 @@ class GenerationManager{
|
||||
protected function generateChunk($levelID, $chunkX, $chunkZ){
|
||||
if(isset($this->levels[$levelID])){
|
||||
$this->levels[$levelID]->populateChunk($chunkX, $chunkZ); //Request population directly
|
||||
if(isset($this->levels[$levelID])){
|
||||
$this->sendChunk($levelID, $this->levels[$levelID]->getChunk($chunkX, $chunkZ));
|
||||
}
|
||||
//TODO: wait for queue generation (to wait for extra chunk changes)
|
||||
}
|
||||
}
|
||||
@ -171,7 +173,7 @@ class GenerationManager{
|
||||
*/
|
||||
public function requestChunk($levelID, $chunkX, $chunkZ){
|
||||
$this->needsChunk = [$levelID, $chunkX, $chunkZ];
|
||||
$binary = chr(self::PACKET_REQUEST_CHUNK . Binary::writeInt($levelID) . Binary::writeInt($chunkX) . Binary::writeInt($chunkZ));
|
||||
$binary = chr(self::PACKET_REQUEST_CHUNK) . Binary::writeInt($levelID) . Binary::writeInt($chunkX) . Binary::writeInt($chunkZ);
|
||||
@socket_write($this->socket, Binary::writeInt(strlen($binary)) . $binary);
|
||||
do{
|
||||
$this->readPacket();
|
||||
@ -187,14 +189,14 @@ class GenerationManager{
|
||||
}
|
||||
|
||||
public function sendChunk($levelID, SimpleChunk $chunk){
|
||||
$binary = chr(self::PACKET_SEND_CHUNK . Binary::writeInt($levelID) . $chunk->toBinary());
|
||||
$binary = chr(self::PACKET_SEND_CHUNK) . Binary::writeInt($levelID) . $chunk->toBinary();
|
||||
@socket_write($this->socket, Binary::writeInt(strlen($binary)) . $binary);
|
||||
}
|
||||
|
||||
protected function readPacket(){
|
||||
$len = socket_read($this->socket, 4);
|
||||
$len = @socket_read($this->socket, 4);
|
||||
if($len === false or $len === ""){
|
||||
usleep(5000);
|
||||
$this->shutdown = true;
|
||||
return;
|
||||
}
|
||||
$packet = socket_read($this->socket, Binary::readInt($len));
|
||||
|
140
src/pocketmine/level/generator/GenerationRequestManager.php
Normal file
140
src/pocketmine/level/generator/GenerationRequestManager.php
Normal file
@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\level\generator;
|
||||
|
||||
use pocketmine\level\format\SimpleChunk;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\Binary;
|
||||
|
||||
class GenerationRequestManager{
|
||||
|
||||
protected $socket;
|
||||
/** @var Server */
|
||||
protected $server;
|
||||
/** @var GenerationThread */
|
||||
protected $generationThread;
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
*/
|
||||
public function __construct(Server $server){
|
||||
$this->server = $server;
|
||||
$this->generationThread = new GenerationThread($server->getLogger(), $server->getLoader());
|
||||
$this->socket = $this->generationThread->getExternalSocket();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Level $level
|
||||
* @param string $generator
|
||||
* @param array $options
|
||||
*/
|
||||
public function openLevel(Level $level, $generator, array $options = []){
|
||||
$buffer = chr(GenerationManager::PACKET_OPEN_LEVEL) . Binary::writeInt($level->getID()) . Binary::writeInt($level->getSeed()) .
|
||||
Binary::writeShort(strlen($generator)) . $generator . serialize($options);
|
||||
|
||||
@socket_write($this->socket, Binary::writeInt(strlen($buffer)) . $buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Level $level
|
||||
*/
|
||||
public function closeLevel(Level $level){
|
||||
$buffer = chr(GenerationManager::PACKET_CLOSE_LEVEL) . Binary::writeInt($level->getID());
|
||||
@socket_write($this->socket, Binary::writeInt(strlen($buffer)) . $buffer);
|
||||
}
|
||||
|
||||
public function addNamespace($namespace, $path){
|
||||
$buffer = chr(GenerationManager::PACKET_ADD_NAMESPACE) . Binary::writeShort(strlen($namespace)) . $namespace . $path;
|
||||
@socket_write($this->socket, Binary::writeInt(strlen($buffer)) . $buffer);
|
||||
}
|
||||
|
||||
protected function socketRead($len){
|
||||
$buffer = "";
|
||||
while(strlen($buffer) < $len){
|
||||
$buffer .= @socket_read($this->socket, $len - strlen($buffer));
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
protected function sendChunk($levelID, SimpleChunk $chunk){
|
||||
$binary = chr(GenerationManager::PACKET_SEND_CHUNK) . Binary::writeInt($levelID) . $chunk->toBinary();
|
||||
@socket_write($this->socket, Binary::writeInt(strlen($binary)) . $binary);
|
||||
}
|
||||
|
||||
public function requestChunk(Level $level, $chunkX, $chunkZ){
|
||||
$buffer = chr(GenerationManager::PACKET_REQUEST_CHUNK) . Binary::writeInt($level->getID()) . Binary::writeInt($chunkX) . Binary::writeInt($chunkZ);
|
||||
@socket_write($this->socket, Binary::writeInt(strlen($buffer)) . $buffer);
|
||||
}
|
||||
|
||||
protected function handleRequest($levelID, $chunkX, $chunkZ){
|
||||
if(($level = $this->server->getLevel($levelID)) instanceof Level){
|
||||
$this->sendChunk($levelID, $level->getChunk($chunkX, $chunkZ, false));
|
||||
}else{
|
||||
$buffer = chr(GenerationManager::PACKET_CLOSE_LEVEL) . Binary::writeInt($levelID);
|
||||
@socket_write($this->socket, Binary::writeInt(strlen($buffer)) . $buffer);
|
||||
}
|
||||
}
|
||||
|
||||
protected function receiveChunk($levelID, SimpleChunk $chunk){
|
||||
if(($level = $this->server->getLevel($levelID)) instanceof Level){
|
||||
$level->setChunk($chunk->getX(), $chunk->getZ(), $chunk);
|
||||
}else{
|
||||
$buffer = chr(GenerationManager::PACKET_CLOSE_LEVEL) . Binary::writeInt($levelID);
|
||||
@socket_write($this->socket, Binary::writeInt(strlen($buffer)) . $buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public function handlePackets(){
|
||||
if(($len = @socket_read($this->socket, 4)) !== false){
|
||||
if(strlen($len) < 4){
|
||||
$len .= $this->socketRead(4 - strlen($len));
|
||||
}
|
||||
$packet = $this->socketRead(Binary::readInt($len));
|
||||
$pid = ord($packet{0});
|
||||
$offset = 1;
|
||||
|
||||
if($pid === GenerationManager::PACKET_REQUEST_CHUNK){
|
||||
$levelID = Binary::readInt(substr($packet, $offset, 4));
|
||||
$offset += 4;
|
||||
$chunkX = Binary::readInt(substr($packet, $offset, 4));
|
||||
$offset += 4;
|
||||
$chunkZ = Binary::readInt(substr($packet, $offset, 4));
|
||||
$this->handleRequest($levelID, $chunkX, $chunkZ);
|
||||
}elseif($pid === GenerationManager::PACKET_SEND_CHUNK){
|
||||
$levelID = Binary::readInt(substr($packet, $offset, 4));
|
||||
$offset += 4;
|
||||
$chunk = SimpleChunk::fromBinary(substr($packet, $offset));
|
||||
$this->receiveChunk($levelID, $chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function shutdown(){
|
||||
$buffer = chr(GenerationManager::PACKET_SHUTDOWN);
|
||||
@socket_write($this->socket, Binary::writeInt(strlen($buffer)) . $buffer);
|
||||
$this->generationThread->join();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -50,6 +50,7 @@ class GenerationThread extends \Thread{
|
||||
|
||||
public function __construct(\ThreadedLogger $logger, \SplAutoloader $loader){
|
||||
$this->loader = $loader;
|
||||
$this->logger = $logger;
|
||||
$loadPaths = [];
|
||||
$this->addDependency($loadPaths, new \ReflectionClass($this->logger));
|
||||
$this->addDependency($loadPaths, new \ReflectionClass($this->loader));
|
||||
@ -57,7 +58,7 @@ class GenerationThread extends \Thread{
|
||||
|
||||
$sockets = [];
|
||||
if(!socket_create_pair((strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? AF_INET : AF_UNIX), SOCK_STREAM, 0, $sockets)){
|
||||
throw new \Exception("Could not create IPC sockets. Reason: ".socket_strerror(socket_last_error()));
|
||||
throw new \Exception("Could not create IPC sockets. Reason: " . socket_strerror(socket_last_error()));
|
||||
}
|
||||
|
||||
$this->internalSocket = $sockets[0];
|
||||
|
@ -24,7 +24,6 @@
|
||||
*/
|
||||
namespace pocketmine\level\generator;
|
||||
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
abstract class Generator{
|
||||
@ -48,6 +47,16 @@ abstract class Generator{
|
||||
return "pocketmine\\level\\generator\\Normal";
|
||||
}
|
||||
|
||||
public static function getGeneratorName($class){
|
||||
foreach(Generator::$list as $name => $c){
|
||||
if($c === $class){
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
public abstract function __construct(array $settings = []);
|
||||
|
||||
public abstract function init(GenerationChunkManager $level, Random $random);
|
||||
|
@ -32,12 +32,11 @@ use pocketmine\block\RedstoneOre;
|
||||
use pocketmine\level\generator\noise\Simplex;
|
||||
use pocketmine\level\generator\object\OreType;
|
||||
use pocketmine\level\generator\populator\Ore;
|
||||
use pocketmine\level\generator\populator\Populator;
|
||||
use pocketmine\level\generator\populator\TallGrass;
|
||||
use pocketmine\level\generator\populator\Tree;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\utils\Random;
|
||||
use pocketmine\level\generator\populator\Populator;
|
||||
|
||||
class Normal extends Generator{
|
||||
|
||||
|
@ -22,8 +22,6 @@
|
||||
namespace pocketmine\level\generator\object;
|
||||
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
|
||||
class BigTree extends Tree{
|
||||
private $trunkHeightMultiplier = 0.618;
|
||||
|
@ -22,8 +22,6 @@
|
||||
namespace pocketmine\level\generator\object;
|
||||
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\math\VectorMath;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
|
@ -21,13 +21,8 @@
|
||||
|
||||
namespace pocketmine\level\generator\object;
|
||||
|
||||
use pocketmine\block\Dirt;
|
||||
use pocketmine\block\Leaves;
|
||||
use pocketmine\block\Wood;
|
||||
use pocketmine\item\Block;
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
class PineTree extends Tree{
|
||||
|
@ -23,7 +23,6 @@ namespace pocketmine\level\generator\object;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
|
@ -21,13 +21,8 @@
|
||||
|
||||
namespace pocketmine\level\generator\object;
|
||||
|
||||
use pocketmine\block\Dirt;
|
||||
use pocketmine\block\Leaves;
|
||||
use pocketmine\block\Wood;
|
||||
use pocketmine\item\Block;
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
class SmallTree extends Tree{
|
||||
|
@ -21,13 +21,8 @@
|
||||
|
||||
namespace pocketmine\level\generator\object;
|
||||
|
||||
use pocketmine\block\Dirt;
|
||||
use pocketmine\block\Leaves;
|
||||
use pocketmine\block\Wood;
|
||||
use pocketmine\item\Block;
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
class SpruceTree extends Tree{
|
||||
|
@ -23,7 +23,6 @@ namespace pocketmine\level\generator\object;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
|
@ -23,8 +23,6 @@ namespace pocketmine\level\generator\object;
|
||||
|
||||
use pocketmine\block\Sapling;
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
class Tree{
|
||||
|
@ -22,7 +22,6 @@
|
||||
namespace pocketmine\level\generator\populator;
|
||||
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
class Mineshaft extends Populator{
|
||||
|
@ -23,8 +23,6 @@ namespace pocketmine\level\generator\populator;
|
||||
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\level\generator\object\Ore as ObjectOre;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
class Ore extends Populator{
|
||||
|
@ -23,8 +23,6 @@ namespace pocketmine\level\generator\populator;
|
||||
|
||||
use pocketmine\block\Water;
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
class Pond extends Populator{
|
||||
|
@ -25,7 +25,6 @@
|
||||
namespace pocketmine\level\generator\populator;
|
||||
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
abstract class Populator{
|
||||
|
@ -22,10 +22,7 @@
|
||||
namespace pocketmine\level\generator\populator;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\TallGrass as BlockTallGrass;
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
class TallGrass extends Populator{
|
||||
|
@ -25,8 +25,6 @@ use pocketmine\block\Block;
|
||||
use pocketmine\block\Sapling;
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\level\generator\object\Tree as ObjectTree;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
class Tree extends Populator{
|
||||
|
@ -35,6 +35,16 @@ class Enum extends NamedTag implements \ArrayAccess{
|
||||
}
|
||||
}
|
||||
|
||||
public function &getValue(){
|
||||
$value = [];
|
||||
foreach($this as $k => $v){
|
||||
if($v instanceof Tag){
|
||||
$value[$k] = $v;
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function offsetExists($offset){
|
||||
return isset($this->{$offset});
|
||||
}
|
||||
|
@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\network\protocol;
|
||||
|
||||
|
||||
class DisconnectPacket extends DataPacket{
|
||||
public function pid(){
|
||||
return Info::DISCONNECT_PACKET;
|
||||
}
|
||||
|
||||
public function decode(){
|
||||
|
||||
}
|
||||
|
||||
public function encode(){
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
}
|
@ -21,8 +21,7 @@
|
||||
|
||||
namespace pocketmine\network\query;
|
||||
|
||||
use pocketmine\network\Packet;
|
||||
use pocketmine\utils\Binary;
|
||||
se pocketmine\utils\Binary;
|
||||
|
||||
class QueryPacket extends Packet{
|
||||
const HANDSHAKE = 9;
|
||||
|
@ -21,8 +21,8 @@
|
||||
|
||||
namespace pocketmine\plugin;
|
||||
|
||||
use \Logger;
|
||||
use \LogLevel;
|
||||
use Logger;
|
||||
use LogLevel;
|
||||
use pocketmine\utils\MainLogger;
|
||||
|
||||
class PluginLogger implements Logger{
|
||||
|
@ -26,7 +26,6 @@ use pocketmine\inventory\DoubleChestInventory;
|
||||
use pocketmine\inventory\InventoryHolder;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\format\Chunk;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\Byte;
|
||||
|
@ -27,7 +27,6 @@ use pocketmine\inventory\FurnaceRecipe;
|
||||
use pocketmine\inventory\InventoryHolder;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\format\Chunk;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\Byte;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
|
@ -22,7 +22,6 @@
|
||||
namespace pocketmine\tile;
|
||||
|
||||
use pocketmine\level\format\Chunk;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
use pocketmine\nbt\tag\Int;
|
||||
|
@ -22,7 +22,6 @@
|
||||
namespace pocketmine\tile;
|
||||
|
||||
use pocketmine\level\format\Chunk;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
use pocketmine\Player;
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
||||
namespace pocketmine\tile;
|
||||
|
||||
use pocketmine\level\format\Chunk;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\level\Position;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
|
||||
@ -58,11 +57,6 @@ abstract class Tile extends Position{
|
||||
protected $lastUpdate;
|
||||
protected $server;
|
||||
|
||||
public function getID(){
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
|
||||
public function __construct(Chunk $chunk, Compound $nbt){
|
||||
$this->server = $chunk->getLevel()->getLevel()->getServer();
|
||||
$this->chunk = $chunk;
|
||||
@ -80,6 +74,10 @@ abstract class Tile extends Position{
|
||||
$this->getLevel()->addTile($this);
|
||||
}
|
||||
|
||||
public function getID(){
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function saveNBT(){
|
||||
$this->namedtag["x"] = $this->x;
|
||||
$this->namedtag["y"] = $this->y;
|
||||
@ -94,6 +92,10 @@ abstract class Tile extends Position{
|
||||
Tile::$needUpdate[$this->id] = $this;
|
||||
}
|
||||
|
||||
public function __destruct(){
|
||||
$this->close();
|
||||
}
|
||||
|
||||
public function close(){
|
||||
if($this->closed === false){
|
||||
$this->closed = true;
|
||||
@ -103,10 +105,6 @@ abstract class Tile extends Position{
|
||||
}
|
||||
}
|
||||
|
||||
public function __destruct(){
|
||||
$this->close();
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
return $this->name;
|
||||
}
|
||||
|
@ -20,7 +20,8 @@
|
||||
*/
|
||||
|
||||
namespace pocketmine\utils;
|
||||
use \LogLevel;
|
||||
|
||||
use LogLevel;
|
||||
|
||||
class MainLogger extends \ThreadedLogger{
|
||||
protected $logFile;
|
||||
|
Loading…
x
Reference in New Issue
Block a user