mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-30 07:09:56 +00:00
Block light bug fixes (#454)
* Fixed an age-old light calculation bug causing solid blocks to filter their own light, fixed #375, probably fixed #288 Light spread reduction should be done based on the _target's_ light filter level, not the source. * Revert "Fix Glowing Obsidian lighting" This hack is no longer necessary. This reverts commit 35c33ba980887e9680d62bbcb65f8537bb063f2c. * Fixed wrong light levels for torch and redstone torch * Take adjacent light levels and opacity changes into account, block light will now spread when an obstruction is removed, close #455 * Added timings for Level->setBlock() and lighting updates
This commit is contained in:
parent
0750b3ab59
commit
5926bab323
@ -22,7 +22,7 @@
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
|
|
||||||
class GlowingObsidian extends Transparent{
|
class GlowingObsidian extends Solid{
|
||||||
|
|
||||||
protected $id = self::GLOWING_OBSIDIAN;
|
protected $id = self::GLOWING_OBSIDIAN;
|
||||||
|
|
||||||
|
@ -32,4 +32,8 @@ class RedstoneTorch extends Torch{
|
|||||||
public function getName(){
|
public function getName(){
|
||||||
return "Redstone Torch";
|
return "Redstone Torch";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getLightLevel(){
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ class Torch extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getLightLevel(){
|
public function getLightLevel(){
|
||||||
return 15;
|
return 14;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName(){
|
public function getName(){
|
||||||
|
@ -25,6 +25,13 @@ use pocketmine\level\Level;
|
|||||||
|
|
||||||
class LevelTimings{
|
class LevelTimings{
|
||||||
|
|
||||||
|
/** @var TimingsHandler */
|
||||||
|
public $setBlock;
|
||||||
|
/** @var TimingsHandler */
|
||||||
|
public $doBlockLightUpdates;
|
||||||
|
/** @var TimingsHandler */
|
||||||
|
public $doBlockSkyLightUpdates;
|
||||||
|
|
||||||
/** @var TimingsHandler */
|
/** @var TimingsHandler */
|
||||||
public $mobSpawn;
|
public $mobSpawn;
|
||||||
/** @var TimingsHandler */
|
/** @var TimingsHandler */
|
||||||
@ -79,6 +86,10 @@ class LevelTimings{
|
|||||||
public function __construct(Level $level){
|
public function __construct(Level $level){
|
||||||
$name = $level->getFolderName() . " - ";
|
$name = $level->getFolderName() . " - ";
|
||||||
|
|
||||||
|
$this->setBlock = new TimingsHandler("** " . $name . "setBlock");
|
||||||
|
$this->doBlockLightUpdates = new TimingsHandler("** " . $name . "doBlockLightUpdates");
|
||||||
|
$this->doBlockSkyLightUpdates = new TimingsHandler("** " . $name . "doBlockSkyLightUpdates");
|
||||||
|
|
||||||
$this->mobSpawn = new TimingsHandler("** " . $name . "mobSpawn");
|
$this->mobSpawn = new TimingsHandler("** " . $name . "mobSpawn");
|
||||||
$this->doChunkUnload = new TimingsHandler("** " . $name . "doChunkUnload");
|
$this->doChunkUnload = new TimingsHandler("** " . $name . "doChunkUnload");
|
||||||
$this->doTickPending = new TimingsHandler("** " . $name . "doTickPending");
|
$this->doTickPending = new TimingsHandler("** " . $name . "doTickPending");
|
||||||
|
@ -1286,17 +1286,42 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function updateBlockSkyLight(int $x, int $y, int $z){
|
public function updateBlockSkyLight(int $x, int $y, int $z){
|
||||||
|
$this->timings->doBlockSkyLightUpdates->startTiming();
|
||||||
//TODO
|
//TODO
|
||||||
|
$this->timings->doBlockSkyLightUpdates->stopTiming();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the highest light level available in the positions adjacent to the specified block coordinates.
|
||||||
|
*
|
||||||
|
* @param int $x
|
||||||
|
* @param int $y
|
||||||
|
* @param int $z
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getHighestAdjacentBlockLight(int $x, int $y, int $z) : int{
|
||||||
|
return max([
|
||||||
|
$this->getBlockLightAt($x + 1, $y, $z),
|
||||||
|
$this->getBlockLightAt($x - 1, $y, $z),
|
||||||
|
$this->getBlockLightAt($x, $y + 1, $z),
|
||||||
|
$this->getBlockLightAt($x, $y - 1, $z),
|
||||||
|
$this->getBlockLightAt($x, $y, $z + 1),
|
||||||
|
$this->getBlockLightAt($x, $y, $z - 1)
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateBlockLight(int $x, int $y, int $z){
|
public function updateBlockLight(int $x, int $y, int $z){
|
||||||
|
$this->timings->doBlockLightUpdates->startTiming();
|
||||||
|
|
||||||
$lightPropagationQueue = new \SplQueue();
|
$lightPropagationQueue = new \SplQueue();
|
||||||
$lightRemovalQueue = new \SplQueue();
|
$lightRemovalQueue = new \SplQueue();
|
||||||
$visited = [];
|
$visited = [];
|
||||||
$removalVisited = [];
|
$removalVisited = [];
|
||||||
|
|
||||||
|
$id = $this->getBlockIdAt($x, $y, $z);
|
||||||
$oldLevel = $this->getBlockLightAt($x, $y, $z);
|
$oldLevel = $this->getBlockLightAt($x, $y, $z);
|
||||||
$newLevel = (int) Block::$light[$this->getBlockIdAt($x, $y, $z)];
|
$newLevel = max(Block::$light[$id], $this->getHighestAdjacentBlockLight($x, $y, $z) - Block::$lightFilter[$id]);
|
||||||
|
|
||||||
if($oldLevel !== $newLevel){
|
if($oldLevel !== $newLevel){
|
||||||
$this->setBlockLightAt($x, $y, $z, $newLevel);
|
$this->setBlockLightAt($x, $y, $z, $newLevel);
|
||||||
@ -1328,7 +1353,7 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
/** @var Vector3 $node */
|
/** @var Vector3 $node */
|
||||||
$node = $lightPropagationQueue->dequeue();
|
$node = $lightPropagationQueue->dequeue();
|
||||||
|
|
||||||
$lightLevel = $this->getBlockLightAt($node->x, $node->y, $node->z) - (int) Block::$lightFilter[$this->getBlockIdAt($node->x, $node->y, $node->z)];
|
$lightLevel = $this->getBlockLightAt($node->x, $node->y, $node->z);
|
||||||
|
|
||||||
if($lightLevel >= 1){
|
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);
|
||||||
@ -1339,6 +1364,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
$this->computeSpreadBlockLight($node->x, $node->y, $node->z + 1, $lightLevel, $lightPropagationQueue, $visited);
|
$this->computeSpreadBlockLight($node->x, $node->y, $node->z + 1, $lightLevel, $lightPropagationQueue, $visited);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->timings->doBlockLightUpdates->stopTiming();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function computeRemoveBlockLight(int $x, int $y, int $z, int $currentLight, \SplQueue $queue, \SplQueue $spreadQueue, array &$visited, array &$spreadVisited){
|
private function computeRemoveBlockLight(int $x, int $y, int $z, int $currentLight, \SplQueue $queue, \SplQueue $spreadQueue, array &$visited, array &$spreadVisited){
|
||||||
@ -1365,6 +1392,7 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
private function computeSpreadBlockLight(int $x, int $y, int $z, int $currentLight, \SplQueue $queue, array &$visited){
|
private function computeSpreadBlockLight(int $x, int $y, int $z, int $currentLight, \SplQueue $queue, array &$visited){
|
||||||
if($y < 0) return;
|
if($y < 0) return;
|
||||||
$current = $this->getBlockLightAt($x, $y, $z);
|
$current = $this->getBlockLightAt($x, $y, $z);
|
||||||
|
$currentLight -= Block::$lightFilter[$this->getBlockIdAt($x, $y, $z)];
|
||||||
|
|
||||||
if($current < $currentLight){
|
if($current < $currentLight){
|
||||||
$this->setBlockLightAt($x, $y, $z, $currentLight);
|
$this->setBlockLightAt($x, $y, $z, $currentLight);
|
||||||
@ -1402,6 +1430,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->timings->setBlock->startTiming();
|
||||||
|
|
||||||
if($this->getChunk($pos->x >> 4, $pos->z >> 4, true)->setBlock($pos->x & 0x0f, $pos->y & Level::Y_MASK, $pos->z & 0x0f, $block->getId(), $block->getDamage())){
|
if($this->getChunk($pos->x >> 4, $pos->z >> 4, true)->setBlock($pos->x & 0x0f, $pos->y & Level::Y_MASK, $pos->z & 0x0f, $block->getId(), $block->getDamage())){
|
||||||
if(!($pos instanceof Position)){
|
if(!($pos instanceof Position)){
|
||||||
$pos = $this->temporalPosition->setComponents($pos->x, $pos->y, $pos->z);
|
$pos = $this->temporalPosition->setComponents($pos->x, $pos->y, $pos->z);
|
||||||
@ -1441,9 +1471,13 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
$this->updateAround($pos);
|
$this->updateAround($pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->timings->setBlock->stopTiming();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->timings->setBlock->stopTiming();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user