Compare commits

..

16 Commits

Author SHA1 Message Date
e44ed4da3b Enabled batch block sending again 2014-11-29 12:58:31 +01:00
a72488d41e Updated player movement processing and event handling 2014-11-29 12:43:34 +01:00
3930f379cf Updated light filter values 2014-11-29 11:58:50 +01:00
66ba327e62 Improved light spread algorithm even more 2014-11-29 11:27:22 +01:00
329ca62465 Improved light spread algorithm 2014-11-28 19:54:25 +01:00
26e47ef694 Removed old revert flag from Player->processMovement() 2014-11-28 14:49:06 +01:00
61ea149ff0 API 1.8.0 2014-11-28 14:44:56 +01:00
b3c3f896a3 Implemented light population, added Level->getFullLight() 2014-11-28 14:44:27 +01:00
d139e5f342 Removed temporal pthreads workaround 2014-11-28 13:01:25 +01:00
3abf36ad07 Fixed invalid worlds property being set by users 2014-11-28 12:47:28 +01:00
0bc9a9bdab Fixed armor dropping twice 2014-11-27 23:19:46 +01:00
98340522d9 Fixed items getting added on the same empty slot 2014-11-27 20:49:18 +01:00
6d09754ea7 Improved Inventory->addItem(), fixed breaking containers duplicating the last slot, removed not necessary slot changes 2014-11-27 20:10:55 +01:00
a3b1d318cc Fixed ladder crafting recipe 2014-11-27 20:02:38 +01:00
f866efb622 Removed unused Block->isLiquid property 2014-11-27 17:26:43 +01:00
b1c4578726 Fixed #2340 2014-11-27 16:18:43 +01:00
21 changed files with 303 additions and 95 deletions

View File

@ -1098,7 +1098,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$dz = $this->newPosition->z - $this->z;
//$this->inBlock = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z);
$revert = !$this->move($dx, $dy, $dz);
$this->move($dx, $dy, $dz);
$diffX = $this->x - $this->newPosition->x;
$diffZ = $this->z - $this->newPosition->z;
@ -1130,6 +1130,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$deltaAngle = abs($this->lastYaw - $to->yaw) + abs($this->lastPitch - $to->pitch);
if(!$revert and ($delta > (1 / 16) or $deltaAngle > 10)){
$isFirst = ($this->lastX === null or $this->lastY === null or $this->lastZ === null);
$this->lastX = $to->x;
$this->lastY = $to->y;
$this->lastZ = $to->z;
@ -1137,29 +1140,39 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->lastYaw = $to->yaw;
$this->lastPitch = $to->pitch;
$ev = new PlayerMoveEvent($this, $from, $to);
if(!$isFirst){
$ev = new PlayerMoveEvent($this, $from, $to);
$this->server->getPluginManager()->callEvent($ev);
$this->server->getPluginManager()->callEvent($ev);
if(!($revert = $ev->isCancelled())){ //Yes, this is intended
if($to->distance($ev->getTo()) > 0.1){ //If plugins modify the destination
$this->teleport($ev->getTo());
}else{
$pk = new MovePlayerPacket();
$pk->eid = $this->id;
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
$pk->yaw = $this->yaw;
$pk->pitch = $this->pitch;
$pk->bodyYaw = $this->yaw;
if(!($revert = $ev->isCancelled())){ //Yes, this is intended
if($to->distance($ev->getTo()) > 0.1){ //If plugins modify the destination
$this->teleport($ev->getTo());
}else{
$pk = new MovePlayerPacket();
$pk->eid = $this->id;
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
$pk->yaw = $this->yaw;
$pk->pitch = $this->pitch;
$pk->bodyYaw = $this->yaw;
Server::broadcastPacket($this->hasSpawned, $pk);
Server::broadcastPacket($this->hasSpawned, $pk);
}
}
}
}
if($revert){
$this->lastX = $from->x;
$this->lastY = $from->y;
$this->lastZ = $from->z;
$this->lastYaw = $from->yaw;
$this->lastPitch = $from->pitch;
$pk = new MovePlayerPacket();
$pk->eid = 0;
$pk->x = $from->x;
@ -1628,10 +1641,13 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->inventory->sendHeldItem($this);
}else{
$item = $this->inventory->getItemInHand();
$oldItem = clone $item;
//TODO: Implement adventure mode checks
if($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this) === true){
$this->inventory->setItemInHand($item, $this);
$this->inventory->sendHeldItem($this->hasSpawned);
if(!$item->equals($oldItem, true) or $item->getCount() !== $oldItem->getCount()){
$this->inventory->setItemInHand($item, $this);
$this->inventory->sendHeldItem($this->hasSpawned);
}
break;
}
}
@ -1802,13 +1818,17 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
if($this->isCreative()){
$item = $this->inventory->getItemInHand();
}else{
$item = clone $this->inventory->getItemInHand();
$item = $this->inventory->getItemInHand();
}
$oldItem = clone $item;
if($this->level->useBreakOn($vector, $item, $this) === true){
if($this->isSurvival()){
$this->inventory->setItemInHand($item, $this);
$this->inventory->sendHeldItem($this->hasSpawned);
if(!$item->equals($oldItem, true) or $item->getCount() !== $oldItem->getCount()){
$this->inventory->setItemInHand($item, $this);
$this->inventory->sendHeldItem($this->hasSpawned);
}
}
break;
}

View File

@ -71,7 +71,7 @@ namespace pocketmine {
use pocketmine\wizard\Installer;
const VERSION = "Alpha_1.4dev";
const API_VERSION = "1.7.1";
const API_VERSION = "1.8.0";
const CODENAME = "絶好(Zekkou)ケーキ(Cake)";
const MINECRAFT_VERSION = "v0.10.4 alpha";
@ -367,8 +367,8 @@ namespace pocketmine {
if(substr_count($pthreads_version, ".") < 2){
$pthreads_version = "0.$pthreads_version";
}
if(version_compare($pthreads_version, "2.0.8") < 0){
$logger->critical("pthreads >= 2.0.8 is required, while you have $pthreads_version.");
if(version_compare($pthreads_version, "2.0.9") < 0){
$logger->critical("pthreads >= 2.0.9 is required, while you have $pthreads_version.");
++$errors;
}

View File

@ -299,7 +299,7 @@ class Server{
* @return int
*/
public function getViewDistance(){
return max(56, $this->getProperty("chunk-sending.max-chunks"));
return max(56, $this->getProperty("chunk-sending.max-chunks", 96));
}
/**
@ -313,7 +313,7 @@ class Server{
* @return string
*/
public function getServerName(){
return $this->getConfigString("motd", "Unknown server");
return $this->getConfigString("motd", "Minecraft: PE Server");
}
/**
@ -1615,14 +1615,7 @@ class Server{
Generator::addGenerator(Normal::class, "normal");
Generator::addGenerator(Normal::class, "default");
//Temporal workaround, pthreads static property nullification test
if(PluginManager::$pluginParentTimer === null or Timings::$serverTickTimer === null){
$this->getLogger()->emergency("You are using an invalid pthreads version. Please update your binaries.");
kill(getmypid());
return;
}
foreach($this->getProperty("worlds", []) as $name => $worldSetting){
foreach((array) $this->getProperty("worlds", []) as $name => $worldSetting){
if($this->loadLevel($name) === false){
$seed = $this->getProperty("worlds.$name.seed", time());
$options = explode(":", $this->getProperty("worlds.$name.generator", Generator::getGenerator("default")));

View File

@ -528,6 +528,14 @@ class Block extends Position implements Metadatable{
/** @var \SplFixedArray */
public static $list = null;
/** @var \SplFixedArray */
public static $light = null;
/** @var \SplFixedArray */
public static $lightFilter = null;
/** @var \SplFixedArray */
public static $solid = null;
/** @var \SplFixedArray */
public static $transparent = null;
protected $id;
protected $meta;
protected $name = "Unknown";
@ -542,8 +550,8 @@ class Block extends Position implements Metadatable{
public $isReplaceable = false;
public $isPlaceable = true;
public $hasPhysics = false;
public $isLiquid = false;
public $isFullBlock = true;
public $lightLevel = 0;
public $x = 0;
public $y = 0;
public $z = 0;
@ -555,6 +563,10 @@ class Block extends Position implements Metadatable{
public static function init(){
if(self::$list === null){
self::$list = new \SplFixedArray(256);
self::$light = new \SplFixedArray(256);
self::$lightFilter = new \SplFixedArray(256);
self::$solid = new \SplFixedArray(256);
self::$transparent = new \SplFixedArray(256);
self::$list[self::AIR] = Air::class;;
self::$list[self::STONE] = Stone::class;;
self::$list[self::GRASS] = Grass::class;;
@ -697,11 +709,37 @@ class Block extends Position implements Metadatable{
self::$list[self::FENCE_JUNGLE] = FenceJungle::class;
self::$list[self::FENCE_ACACIA] = FenceAcacia::class;
self::$list[self::PODZOL] = Podzol::class;;
self::$list[self::BEETROOT_BLOCK] = Beetroot::class;;
self::$list[self::STONECUTTER] = Stonecutter::class;;
self::$list[self::GLOWING_OBSIDIAN] = GlowingObsidian::class;;
self::$list[self::NETHER_REACTOR] = NetherReactor::class;;
self::$list[self::PODZOL] = Podzol::class;
self::$list[self::BEETROOT_BLOCK] = Beetroot::class;
self::$list[self::STONECUTTER] = Stonecutter::class;
self::$list[self::GLOWING_OBSIDIAN] = GlowingObsidian::class;
self::$list[self::NETHER_REACTOR] = NetherReactor::class;
foreach(self::$list as $id => $class){
if($class !== null){
/** @var Block $block */
$block = new $class();
self::$solid[$id] = (bool) $block->isSolid;
self::$transparent[$id] = (bool) $block->isTransparent;
self::$light[$id] = (int) $block->lightLevel;
if($block->isSolid){
if($block->isTransparent){
if($block instanceof Liquid or $block instanceof Ice){
self::$lightFilter[$id] = 2;
}else{
self::$lightFilter[$id] = 1;
}
}else{
self::$lightFilter[$id] = 15;
}
}else{
self::$lightFilter[$id] = 1;
}
}else{
self::$lightFilter[$id] = 1;
}
}
}
}

View File

@ -26,6 +26,9 @@ use pocketmine\level\Level;
use pocketmine\Player;
class BrownMushroom extends Flowable{
public $lightLevel = 1;
public function __construct(){
parent::__construct(self::BROWN_MUSHROOM, 0, "Brown Mushroom");
$this->hardness = 0;

View File

@ -32,6 +32,9 @@ use pocketmine\tile\Furnace;
use pocketmine\tile\Tile;
class BurningFurnace extends Solid{
public $lightLevel = 13;
public function __construct($meta = 0){
parent::__construct(self::BURNING_FURNACE, $meta, "Burning Furnace");
$this->isActivable = true;

View File

@ -24,6 +24,9 @@ namespace pocketmine\block;
use pocketmine\math\AxisAlignedBB;
class EndPortal extends Solid{
public $lightLevel = 1;
public function __construct($meta = 0){
parent::__construct(self::END_PORTAL, $meta, "End Portal");
$this->hardness = 18000000;

View File

@ -32,6 +32,7 @@ use pocketmine\Server;
class Fire extends Flowable{
public $hasEntityCollision = true;
public $lightLevel = 15;
public function __construct($meta = 0){
parent::__construct(self::FIRE, $meta, "Fire");

View File

@ -23,6 +23,9 @@ namespace pocketmine\block;
class GlowingObsidian extends Solid{
public $lightLevel = 12;
public function __construct($meta = 0){
parent::__construct(self::GLOWING_OBSIDIAN, $meta, "Glowing Obsidian");
}

View File

@ -25,6 +25,9 @@ use pocketmine\item\Item;
use pocketmine\level\Level;
class GlowingRedstoneOre extends Solid{
public $lightLevel = 9;
public function __construct(){
parent::__construct(self::GLOWING_REDSTONE_ORE, 0, "Glowing Redstone Ore");
$this->hardness = 15;

View File

@ -24,6 +24,9 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Glowstone extends Transparent{
public $lightLevel = 15;
public function __construct(){
parent::__construct(self::GLOWSTONE_BLOCK, 0, "Glowstone");
$this->hardness = 1.5;

View File

@ -31,6 +31,8 @@ use pocketmine\Server;
class Lava extends Liquid{
public $lightLevel = 15;
public function __construct($meta = 0){
parent::__construct(self::LAVA, $meta, "Lava");
$this->hardness = 0;

View File

@ -30,7 +30,6 @@ use pocketmine\math\Vector3;
abstract class Liquid extends Transparent{
public $hasEntityCollision = true;
public $isLiquid = true;
public $breakable = false;
public $isReplaceable = true;
public $isSolid = false;

View File

@ -25,6 +25,9 @@ use pocketmine\item\Item;
use pocketmine\Player;
class LitPumpkin extends Solid{
public $lightLevel = 15;
public function __construct(){
parent::__construct(self::LIT_PUMPKIN, "Jack o'Lantern");
$this->hardness = 5;

View File

@ -26,6 +26,9 @@ use pocketmine\level\Level;
use pocketmine\Player;
class Torch extends Flowable{
public $lightLevel = 15;
public function __construct($meta = 0){
parent::__construct(self::TORCH, $meta, "Torch");
$this->hardness = 0;

View File

@ -90,9 +90,9 @@ abstract class Entity extends Location implements Metadatable{
protected $lastDamageCause = null;
public $lastX;
public $lastY;
public $lastZ;
public $lastX = null;
public $lastY = null;
public $lastZ = null;
public $motionX;
public $motionY;

View File

@ -85,10 +85,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
foreach($this->inventory->getContents() as $item){
$drops[] = $item;
}
foreach($this->inventory->getArmorContents() as $item){
$drops[] = $item;
}
}
return $drops;
@ -208,13 +204,10 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
public function close(){
if(!$this->closed){
if(!($this instanceof Player) or $this->loggedIn){
foreach($this->getInventory()->getViewers() as $player){
$this->getInventory()->close($player);
foreach($this->inventory->getViewers() as $viewer){
$viewer->removeWindow($this->inventory);
}
}
foreach($this->inventory->getViewers() as $viewer){
$viewer->removeWindow($this->inventory);
}
parent::close();
}
}

View File

@ -233,41 +233,59 @@ abstract class BaseInventory implements Inventory{
$source = null;
}
/** @var Item[] $itemSlots */
/** @var Item[] $slots */
foreach($slots as $i => $slot){
$slots[$i] = clone $slot;
$itemSlots = [];
foreach($slots as $slot){
if($slot->getId() !== 0 and $slot->getCount() > 0){
$itemSlots[] = clone $slot;
}
}
$emptySlots = [];
for($i = 0; $i < $this->getSize(); ++$i){
$item = $this->getItem($i);
foreach($slots as $index => $slot){
if($item->getID() === Item::AIR or $item->getCount() <= 0){
$amount = min($slot->getMaxStackSize(), $slot->getCount(), $this->getMaxStackSize());
$slot->setCount($slot->getCount() - $amount);
$item = clone $slot;
$item->setCount($amount);
$this->setItem($i, $item, $source);
$item = $this->getItem($i);
if($slot->getCount() <= 0){
unset($slots[$index]);
}
}elseif($slot->equals($item, true) and $item->getCount() < $item->getMaxStackSize()){
if($item->getId() === Item::AIR or $item->getCount() <= 0){
$emptySlots[] = $i;
}
foreach($itemSlots as $index => $slot){
if($slot->equals($item, true) and $item->getCount() < $item->getMaxStackSize()){
$amount = min($item->getMaxStackSize() - $item->getCount(), $slot->getCount(), $this->getMaxStackSize());
$slot->setCount($slot->getCount() - $amount);
$item->setCount($item->getCount() + $amount);
$this->setItem($i, $item, $source);
if($slot->getCount() <= 0){
unset($slots[$index]);
if($amount > 0){
$slot->setCount($slot->getCount() - $amount);
$item->setCount($item->getCount() + $amount);
$this->setItem($i, $item, $source);
if($slot->getCount() <= 0){
unset($itemSlots[$index]);
}
}
}
}
if(count($slots) === 0){
if(count($itemSlots) === 0){
break;
}
}
return $slots;
if(count($itemSlots) > 0 and count($emptySlots) > 0){
foreach($emptySlots as $slotIndex){
foreach($itemSlots as $index => $slot){
$amount = min($slot->getMaxStackSize(), $slot->getCount(), $this->getMaxStackSize());
$slot->setCount($slot->getCount() - $amount);
$item = clone $slot;
$item->setCount($amount);
$this->setItem($slotIndex, $item, $source);
if($slot->getCount() <= 0){
unset($itemSlots[$index]);
}
break;
}
}
}
return $itemSlots;
}
public function removeItem(...$slots){
@ -279,31 +297,39 @@ abstract class BaseInventory implements Inventory{
$source = null;
}
/** @var Item[] $itemSlots */
/** @var Item[] $slots */
$itemSlots = [];
foreach($slots as $slot){
if($slot->getId() !== 0 and $slot->getCount() > 0){
$itemSlots[] = clone $slot;
}
}
for($i = 0; $i < $this->getSize(); ++$i){
$item = $this->getItem($i);
if($item->getID() === Item::AIR){
if($item->getId() === Item::AIR or $item->getCount() <= 0){
continue;
}
foreach($slots as $index => $slot){
foreach($itemSlots as $index => $slot){
if($slot->equals($item, $slot->getDamage() === null ? false : true)){
$amount = min($item->getCount(), $slot->getCount());
$slot->setCount($slot->getCount() - $amount);
$item->setCount($item->getCount() - $amount);
$this->setItem($i, $item, $source);
if($slot->getCount() <= 0){
unset($slots[$index]);
unset($itemSlots[$index]);
}
}
}
if(count($slots) === 0){
if(count($itemSlots) === 0){
break;
}
}
return $slots;
return $itemSlots;
}
public function clear($index, $source = null){

View File

@ -85,7 +85,7 @@ class CraftingManager{
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE_GATE_ACACIA, 0, 1)))->addIngredient(Item::get(Item::STICK, 0, 4))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::ACACIA, 2))->addIngredient(Item::get(Item::STICK, 0, 4)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FURNACE, 0, 1)))->addIngredient(Item::get(Item::COBBLESTONE, 0, 8)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::GLASS_PANE, 0, 16)))->addIngredient(Item::get(Item::GLASS, 0, 6)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::LADDER, 0, 3)))->addIngredient(Item::get(Item::STICK, 0, 7)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::LADDER, 0, 2)))->addIngredient(Item::get(Item::STICK, 0, 7)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::NETHER_REACTOR, 0, 1)))->addIngredient(Item::get(Item::DIAMOND, 0, 3))->addIngredient(Item::get(Item::IRON_INGOT, 0, 6)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::TRAPDOOR, 0, 2)))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 6)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::WOODEN_DOOR, 0, 1)))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 6)));

View File

@ -625,7 +625,7 @@ class Item{
}
final public function __toString(){
return "Item " . $this->name . " (" . $this->id . ":" . ($this->meta === null ? "?" : $this->meta) . ")";
return "Item " . $this->name . " (" . $this->id . ":" . ($this->meta === null ? "?" : $this->meta) . ")x".$this->count;
}
public function getDestroySpeed(Block $block, Player $player){

View File

@ -514,7 +514,7 @@ class Level implements ChunkManager, Metadatable{
if(($mini & (1 << $Y)) === 0){
continue;
}
if(count($this->changedBlocks[$index][$Y]) < 582){ //Optimal value, calculated using the relation between minichunks and single packets
if(count($this->changedBlocks[$index][$Y]) < 256){
continue;
}else{
$X = null;
@ -574,13 +574,13 @@ class Level implements ChunkManager, Metadatable{
$x = $player->x >> 4;
$z = $player->z >> 4;
$index = "$x:$z";
$index = Level::chunkHash($x, $z);
$existingPlayers = max(0, isset($this->chunkTickList[$index]) ? $this->chunkTickList[$index] : 0);
$this->chunkTickList[$index] = $existingPlayers + 1;
for($chunk = 0; $chunk < $chunksPerPlayer; ++$chunk){
$dx = mt_rand(-$randRange, $randRange);
$dz = mt_rand(-$randRange, $randRange);
$hash = ($dx + $x) .":". ($dz + $z);
$hash = Level::chunkHash($dx + $x, $dz + $z);
if(!isset($this->chunkTickList[$hash]) and $this->isChunkLoaded($dx + $x, $dz + $z)){
$this->chunkTickList[$hash] = -1;
}
@ -881,6 +881,20 @@ class Level implements ChunkManager, Metadatable{
}
*/
public function getFullLight(Vector3 $pos){
$chunk = $this->getChunk($pos->x >> 4, $pos->z >> 4, true);
$level = 0;
if($chunk instanceof FullChunk){
$level = $chunk->getBlockSkyLight($pos->x & 0x0f, $pos->y & 0x7f, $pos->z & 0x0f);
//TODO: decrease light level by time of day
if($level < 15){
$level = max($chunk->getBlockLight($pos->x & 0x0f, $pos->y & 0x7f, $pos->z & 0x0f));
}
}
return $level;
}
/**
* Gets the Block object on the Vector3 location
*
@ -911,6 +925,102 @@ class Level implements ChunkManager, Metadatable{
return $this->blockCache[$index] = Block::get($blockId, $meta, $this->temporalPosition->setComponents($pos->x, $pos->y, $pos->z));
}
public function updateAllLight(Vector3 $pos){
$this->updateBlockSkyLight($pos->x, $pos->y, $pos->z);
$this->updateBlockLight($pos->x, $pos->y, $pos->z);
}
public function updateBlockSkyLight($x, $y, $z){
//TODO
}
public function updateBlockLight($x, $y, $z){
$lightPropagationQueue = new \SplQueue();
$lightRemovalQueue = new \SplQueue();
$visited = [];
$removalVisited = [];
$oldLevel = $this->getBlockLightAt($x, $y, $z);
$newLevel = (int) Block::$light[$this->getBlockIdAt($x, $y, $z)];
if($oldLevel !== $newLevel){
$this->setBlockLightAt($x, $y, $z, $newLevel);
if($newLevel < $oldLevel){
$removalVisited["$x:$y:$z"] = true;
$lightRemovalQueue->enqueue([new Vector3($x, $y, $z), $oldLevel]);
}else{
$visited["$x:$y:$z"] = true;
$lightPropagationQueue->enqueue(new Vector3($x, $y, $z));
}
}
while(!$lightRemovalQueue->isEmpty()){
/** @var Vector3 $node */
$val = $lightRemovalQueue->dequeue();
$node = $val[0];
$lightLevel = $val[1];
$this->computeRemoveBlockLight($node->x - 1, $node->y, $node->z, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
$this->computeRemoveBlockLight($node->x + 1, $node->y, $node->z, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
$this->computeRemoveBlockLight($node->x, $node->y - 1, $node->z, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
$this->computeRemoveBlockLight($node->x, $node->y + 1, $node->z, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
$this->computeRemoveBlockLight($node->x, $node->y, $node->z - 1, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
$this->computeRemoveBlockLight($node->x, $node->y, $node->z + 1, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
}
while(!$lightPropagationQueue->isEmpty()){
/** @var Vector3 $node */
$node = $lightPropagationQueue->dequeue();
$lightLevel = $this->getBlockLightAt($node->x, $node->y, $node->z) - (int) Block::$lightFilter[$this->getBlockIdAt($node->x, $node->y, $node->z)];
if($lightLevel >= 1){
$this->computeSpreadBlockLight($node->x - 1, $node->y, $node->z, $lightLevel, $lightPropagationQueue, $visited);
$this->computeSpreadBlockLight($node->x + 1, $node->y, $node->z, $lightLevel, $lightPropagationQueue, $visited);
$this->computeSpreadBlockLight($node->x, $node->y - 1, $node->z, $lightLevel, $lightPropagationQueue, $visited);
$this->computeSpreadBlockLight($node->x, $node->y + 1, $node->z, $lightLevel, $lightPropagationQueue, $visited);
$this->computeSpreadBlockLight($node->x, $node->y, $node->z - 1, $lightLevel, $lightPropagationQueue, $visited);
$this->computeSpreadBlockLight($node->x, $node->y, $node->z + 1, $lightLevel, $lightPropagationQueue, $visited);
}
}
}
private function computeRemoveBlockLight($x, $y, $z, $currentLight, \SplQueue $queue, \SplQueue $spreadQueue, array &$visited, array &$spreadVisited){
$current = $this->getBlockLightAt($x, $y, $z);
if($current !== 0 and $current < $currentLight){
$this->setBlockLightAt($x, $y, $z, 0);
if(!isset($visited[$index = "$x:$y:$z"])){
$visited[$index] = true;
if($current > 1){
$queue->enqueue([new Vector3($x, $y, $z), $current]);
}
}
}elseif($current >= $currentLight){
if(!isset($spreadVisited[$index = "$x:$y:$z"])){
$spreadVisited[$index] = true;
$spreadQueue->enqueue(new Vector3($x, $y, $z));
}
}
}
private function computeSpreadBlockLight($x, $y, $z, $currentLight, \SplQueue $queue, array &$visited){
$current = $this->getBlockLightAt($x, $y, $z);
if($current < $currentLight){
$this->setBlockLightAt($x, $y, $z, $currentLight);
if(!isset($visited[$index = "$x:$y:$z"])){
$visited[$index] = true;
if($currentLight > 1){
$queue->enqueue(new Vector3($x, $y, $z));
}
}
}
}
/**
* Sets on Vector3 the data from a Block object,
* does block updates and puts the changes to the send queue.
@ -946,7 +1056,7 @@ class Level implements ChunkManager, Metadatable{
Cache::remove("world:" . $this->getID() . ":" . $index);
}
//if($direct === true){
if($direct === true){
$pk = new UpdateBlockPacket();
$pk->x = $pos->x;
$pk->y = $pos->y;
@ -955,7 +1065,7 @@ class Level implements ChunkManager, Metadatable{
$pk->meta = $block->getDamage();
Server::broadcastPacket($this->getUsingChunk($pos->x >> 4, $pos->z >> 4), $pk);
/*}else{
}else{
if(!($pos instanceof Position)){
$pos = $this->temporalPosition->setComponents($pos->x, $pos->y, $pos->z);
}
@ -970,9 +1080,11 @@ class Level implements ChunkManager, Metadatable{
$this->changedCount[$index] |= 1 << $Y;
}
$this->changedBlocks[$index][$Y][] = clone $block;
}*/
}
if($update === true){
$this->updateAllLight($block);
$this->updateAround($pos);
$this->server->getPluginManager()->callEvent($ev = new BlockUpdateEvent($block));
if(!$ev->isCancelled()){
@ -1091,8 +1203,8 @@ class Level implements ChunkManager, Metadatable{
$tile->unpair();
}
foreach($tile->getInventory()->getContents() as $item){
$this->dropItem($target, $item);
foreach($tile->getInventory()->getContents() as $chestItem){
$this->dropItem($target, $chestItem);
}
}
@ -1552,7 +1664,7 @@ class Level implements ChunkManager, Metadatable{
* @return Chunk
*/
public function getChunk($x, $z, $create = false){
if(isset($this->chunks[$index = "$x:$z"])){
if(isset($this->chunks[$index = Level::chunkHash($x, $z)])){
return $this->chunks[$index];
}elseif($this->loadChunk($x, $z, $create) and $this->chunks[$index] instanceof FullChunk){
return $this->chunks[$index];
@ -1576,7 +1688,7 @@ class Level implements ChunkManager, Metadatable{
public function generateChunkCallback($x, $z, FullChunk $chunk){
$oldChunk = $this->getChunk($x, $z);
unset($this->chunkGenerationQueue["$x:$z"]);
unset($this->chunkGenerationQueue[Level::chunkHash($x, $z)]);
$this->setChunk($x, $z, $chunk);
$chunk = $this->getChunk($x, $z);
if($chunk instanceof FullChunk and (!($oldChunk instanceof FullChunk) or $oldChunk->isPopulated() === false) and $chunk->isPopulated()){
@ -1597,7 +1709,7 @@ class Level implements ChunkManager, Metadatable{
$this->chunks[$index] = $chunk;
}
if(ADVANCED_CACHE == true){
Cache::remove("world:" . $this->getID() . ":$x:$z");
Cache::remove("world:" . $this->getID() . ":". Level::chunkHash($x, $z));
}
$chunk->setChanged();
}
@ -1625,7 +1737,7 @@ class Level implements ChunkManager, Metadatable{
* @return bool
*/
public function isChunkLoaded($x, $z){
return isset($this->chunks["$x:$z"]) or $this->provider->isChunkLoaded($x, $z);
return isset($this->chunks[Level::chunkHash($x, $z)]) or $this->provider->isChunkLoaded($x, $z);
}
/**
@ -2045,8 +2157,8 @@ class Level implements ChunkManager, Metadatable{
public function generateChunk($x, $z){
if(!isset($this->chunkGenerationQueue["$x:$z"])){
$this->chunkGenerationQueue["$x:$z"] = true;
if(!isset($this->chunkGenerationQueue[Level::chunkHash($x, $z)])){
$this->chunkGenerationQueue[Level::chunkHash($x, $z)] = true;
$this->server->getGenerationManager()->requestChunk($this, $x, $z);
}
}