Working Threaded Generation

This commit is contained in:
Shoghi Cervantes 2014-06-10 20:45:09 +02:00
parent 392eb74901
commit fa50cbf4b3
56 changed files with 1631 additions and 1733 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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{

View File

@ -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;

View File

@ -22,7 +22,6 @@
namespace pocketmine\event\player;
use pocketmine\event\Cancellable;
use pocketmine\item\Item;
use pocketmine\Player;
/**

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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();
}
}

View File

@ -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);
/**

View File

@ -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();
}

View 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;
}
}

View File

@ -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);
}

View File

@ -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]);
}
}
}

View File

@ -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);
}
/**

View File

@ -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
});
}

View File

@ -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){

View File

@ -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");
}
}

View File

@ -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);
}
/**

View File

@ -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");
}
}

View File

@ -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()];
}
}

View File

@ -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;
}

View File

@ -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));

View 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();
}
}

View File

@ -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];

View File

@ -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);

View File

@ -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{

View File

@ -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;

View File

@ -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;

View File

@ -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{

View File

@ -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;

View File

@ -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{

View File

@ -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{

View File

@ -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;

View File

@ -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{

View File

@ -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{

View File

@ -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{

View File

@ -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{

View File

@ -25,7 +25,6 @@
namespace pocketmine\level\generator\populator;
use pocketmine\level\ChunkManager;
use pocketmine\level\Level;
use pocketmine\utils\Random;
abstract class Populator{

View File

@ -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{

View File

@ -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{

View File

@ -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});
}

View File

@ -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();
}
}

View File

@ -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;

View File

@ -21,8 +21,8 @@
namespace pocketmine\plugin;
use \Logger;
use \LogLevel;
use Logger;
use LogLevel;
use pocketmine\utils\MainLogger;
class PluginLogger implements Logger{

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -22,7 +22,6 @@
namespace pocketmine\tile;
use pocketmine\level\format\Chunk;
use pocketmine\level\Level;
use pocketmine\nbt\tag\Compound;
use pocketmine\Player;

View File

@ -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;
}

View File

@ -20,7 +20,8 @@
*/
namespace pocketmine\utils;
use \LogLevel;
use LogLevel;
class MainLogger extends \ThreadedLogger{
protected $logFile;