mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-06 17:59:48 +00:00
Merge 'minor-next' into 'major-next'
Automatic merge performed by: https://github.com/pmmp/RestrictedActions/actions/runs/13191240897
This commit is contained in:
@ -375,6 +375,8 @@ class World implements ChunkManager{
|
||||
|
||||
private \Logger $logger;
|
||||
|
||||
private RuntimeBlockStateRegistry $blockStateRegistry;
|
||||
|
||||
/**
|
||||
* @phpstan-return ChunkPosHash
|
||||
*/
|
||||
@ -488,6 +490,7 @@ class World implements ChunkManager{
|
||||
$this->displayName = $this->provider->getWorldData()->getName();
|
||||
$this->logger = new \PrefixedLogger($server->getLogger(), "World: $this->displayName");
|
||||
|
||||
$this->blockStateRegistry = RuntimeBlockStateRegistry::getInstance();
|
||||
$this->minY = $this->provider->getWorldMinY();
|
||||
$this->maxY = $this->provider->getWorldMaxY();
|
||||
|
||||
@ -559,7 +562,7 @@ class World implements ChunkManager{
|
||||
}catch(BlockStateDeserializeException){
|
||||
continue;
|
||||
}
|
||||
$block = RuntimeBlockStateRegistry::getInstance()->fromStateId(GlobalBlockStateHandlers::getDeserializer()->deserialize($blockStateData));
|
||||
$block = $this->blockStateRegistry->fromStateId(GlobalBlockStateHandlers::getDeserializer()->deserialize($blockStateData));
|
||||
}else{
|
||||
//TODO: we probably ought to log an error here
|
||||
continue;
|
||||
@ -570,7 +573,7 @@ class World implements ChunkManager{
|
||||
}
|
||||
}
|
||||
|
||||
foreach(RuntimeBlockStateRegistry::getInstance()->getAllKnownStates() as $state){
|
||||
foreach($this->blockStateRegistry->getAllKnownStates() as $state){
|
||||
$dontTickName = $dontTickBlocks[$state->getTypeId()] ?? null;
|
||||
if($dontTickName === null && $state->ticksRandomly()){
|
||||
$this->randomTickBlocks[$state->getStateId()] = true;
|
||||
@ -1394,7 +1397,7 @@ class World implements ChunkManager{
|
||||
$entity->onRandomUpdate();
|
||||
}
|
||||
|
||||
$blockFactory = RuntimeBlockStateRegistry::getInstance();
|
||||
$blockFactory = $this->blockStateRegistry;
|
||||
foreach($chunk->getSubChunks() as $Y => $subChunk){
|
||||
if(!$subChunk->isEmptyFast()){
|
||||
$k = 0;
|
||||
@ -1528,13 +1531,18 @@ class World implements ChunkManager{
|
||||
|
||||
$collides = [];
|
||||
|
||||
$collisionInfo = $this->blockStateRegistry->collisionInfo;
|
||||
if($targetFirst){
|
||||
for($z = $minZ; $z <= $maxZ; ++$z){
|
||||
for($x = $minX; $x <= $maxX; ++$x){
|
||||
for($y = $minY; $y <= $maxY; ++$y){
|
||||
$block = $this->getBlockAt($x, $y, $z);
|
||||
if($block->collidesWithBB($bb)){
|
||||
return [$block];
|
||||
$stateCollisionInfo = $this->getBlockCollisionInfo($x, $y, $z, $collisionInfo);
|
||||
if(match($stateCollisionInfo){
|
||||
RuntimeBlockStateRegistry::COLLISION_CUBE => true,
|
||||
RuntimeBlockStateRegistry::COLLISION_NONE => false,
|
||||
default => $this->getBlockAt($x, $y, $z)->collidesWithBB($bb)
|
||||
}){
|
||||
return [$this->getBlockAt($x, $y, $z)];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1543,9 +1551,13 @@ class World implements ChunkManager{
|
||||
for($z = $minZ; $z <= $maxZ; ++$z){
|
||||
for($x = $minX; $x <= $maxX; ++$x){
|
||||
for($y = $minY; $y <= $maxY; ++$y){
|
||||
$block = $this->getBlockAt($x, $y, $z);
|
||||
if($block->collidesWithBB($bb)){
|
||||
$collides[] = $block;
|
||||
$stateCollisionInfo = $this->getBlockCollisionInfo($x, $y, $z, $collisionInfo);
|
||||
if(match($stateCollisionInfo){
|
||||
RuntimeBlockStateRegistry::COLLISION_CUBE => true,
|
||||
RuntimeBlockStateRegistry::COLLISION_NONE => false,
|
||||
default => $this->getBlockAt($x, $y, $z)->collidesWithBB($bb)
|
||||
}){
|
||||
$collides[] = $this->getBlockAt($x, $y, $z);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1555,24 +1567,64 @@ class World implements ChunkManager{
|
||||
return $collides;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $collisionInfo
|
||||
* @phpstan-param array<int, int> $collisionInfo
|
||||
*/
|
||||
private function getBlockCollisionInfo(int $x, int $y, int $z, array $collisionInfo) : int{
|
||||
if(!$this->isInWorld($x, $y, $z)){
|
||||
return RuntimeBlockStateRegistry::COLLISION_NONE;
|
||||
}
|
||||
$chunk = $this->getChunk($x >> Chunk::COORD_BIT_SIZE, $z >> Chunk::COORD_BIT_SIZE);
|
||||
if($chunk === null){
|
||||
return RuntimeBlockStateRegistry::COLLISION_NONE;
|
||||
}
|
||||
$stateId = $chunk
|
||||
->getSubChunk($y >> SubChunk::COORD_BIT_SIZE)
|
||||
->getBlockStateId(
|
||||
$x & SubChunk::COORD_MASK,
|
||||
$y & SubChunk::COORD_MASK,
|
||||
$z & SubChunk::COORD_MASK
|
||||
);
|
||||
return $collisionInfo[$stateId];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all block AABBs which overlap the full block area at the given coordinates.
|
||||
* This checks a padding of 1 block around the coordinates to account for oversized AABBs of blocks like fences.
|
||||
* Larger AABBs (>= 2 blocks on any axis) are not accounted for.
|
||||
*
|
||||
* @param int[] $collisionInfo
|
||||
* @phpstan-param array<int, int> $collisionInfo
|
||||
*
|
||||
* @return AxisAlignedBB[]
|
||||
* @phpstan-return list<AxisAlignedBB>
|
||||
*/
|
||||
private function getBlockCollisionBoxesForCell(int $x, int $y, int $z) : array{
|
||||
$block = $this->getBlockAt($x, $y, $z);
|
||||
$boxes = $block->getCollisionBoxes();
|
||||
private function getBlockCollisionBoxesForCell(int $x, int $y, int $z, array $collisionInfo) : array{
|
||||
$stateCollisionInfo = $this->getBlockCollisionInfo($x, $y, $z, $collisionInfo);
|
||||
$boxes = match($stateCollisionInfo){
|
||||
RuntimeBlockStateRegistry::COLLISION_NONE => [],
|
||||
RuntimeBlockStateRegistry::COLLISION_CUBE => [AxisAlignedBB::one()->offset($x, $y, $z)],
|
||||
default => $this->getBlockAt($x, $y, $z)->getCollisionBoxes()
|
||||
};
|
||||
|
||||
$cellBB = AxisAlignedBB::one()->offset($x, $y, $z);
|
||||
foreach(Facing::OFFSET as [$dx, $dy, $dz]){
|
||||
$extraBoxes = $this->getBlockAt($x + $dx, $y + $dy, $z + $dz)->getCollisionBoxes();
|
||||
foreach($extraBoxes as $extraBox){
|
||||
if($extraBox->intersectsWith($cellBB)){
|
||||
$boxes[] = $extraBox;
|
||||
//overlapping AABBs can't make any difference if this is a cube, so we can save some CPU cycles in this common case
|
||||
if($stateCollisionInfo !== RuntimeBlockStateRegistry::COLLISION_CUBE){
|
||||
$cellBB = null;
|
||||
foreach(Facing::OFFSET as [$dx, $dy, $dz]){
|
||||
$offsetX = $x + $dx;
|
||||
$offsetY = $y + $dy;
|
||||
$offsetZ = $z + $dz;
|
||||
$stateCollisionInfo = $this->getBlockCollisionInfo($offsetX, $offsetY, $offsetZ, $collisionInfo);
|
||||
if($stateCollisionInfo === RuntimeBlockStateRegistry::COLLISION_MAY_OVERFLOW){
|
||||
//avoid allocating this unless it's needed
|
||||
$cellBB ??= AxisAlignedBB::one()->offset($x, $y, $z);
|
||||
$extraBoxes = $this->getBlockAt($offsetX, $offsetY, $offsetZ)->getCollisionBoxes();
|
||||
foreach($extraBoxes as $extraBox){
|
||||
if($extraBox->intersectsWith($cellBB)){
|
||||
$boxes[] = $extraBox;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1594,13 +1646,15 @@ class World implements ChunkManager{
|
||||
|
||||
$collides = [];
|
||||
|
||||
$collisionInfo = $this->blockStateRegistry->collisionInfo;
|
||||
|
||||
for($z = $minZ; $z <= $maxZ; ++$z){
|
||||
for($x = $minX; $x <= $maxX; ++$x){
|
||||
$chunkPosHash = World::chunkHash($x >> Chunk::COORD_BIT_SIZE, $z >> Chunk::COORD_BIT_SIZE);
|
||||
for($y = $minY; $y <= $maxY; ++$y){
|
||||
$relativeBlockHash = World::chunkBlockHash($x, $y, $z);
|
||||
|
||||
$boxes = $this->blockCollisionBoxCache[$chunkPosHash][$relativeBlockHash] ??= $this->getBlockCollisionBoxesForCell($x, $y, $z);
|
||||
$boxes = $this->blockCollisionBoxCache[$chunkPosHash][$relativeBlockHash] ??= $this->getBlockCollisionBoxesForCell($x, $y, $z, $collisionInfo);
|
||||
|
||||
foreach($boxes as $blockBB){
|
||||
if($blockBB->intersectsWith($bb)){
|
||||
@ -1776,7 +1830,7 @@ class World implements ChunkManager{
|
||||
return;
|
||||
}
|
||||
|
||||
$blockFactory = RuntimeBlockStateRegistry::getInstance();
|
||||
$blockFactory = $this->blockStateRegistry;
|
||||
$this->timings->doBlockSkyLightUpdates->startTiming();
|
||||
if($this->skyLightUpdate === null){
|
||||
$this->skyLightUpdate = new SkyLightUpdate(new SubChunkExplorer($this), $blockFactory->lightFilter, $blockFactory->blocksDirectSkyLight);
|
||||
@ -1895,7 +1949,7 @@ class World implements ChunkManager{
|
||||
|
||||
$chunk = $this->chunks[$chunkHash] ?? null;
|
||||
if($chunk !== null){
|
||||
$block = RuntimeBlockStateRegistry::getInstance()->fromStateId($chunk->getBlockStateId($x & Chunk::COORD_MASK, $y, $z & Chunk::COORD_MASK));
|
||||
$block = $this->blockStateRegistry->fromStateId($chunk->getBlockStateId($x & Chunk::COORD_MASK, $y, $z & Chunk::COORD_MASK));
|
||||
}else{
|
||||
$addToCache = false;
|
||||
$block = VanillaBlocks::AIR();
|
||||
@ -2554,7 +2608,7 @@ class World implements ChunkManager{
|
||||
$localY = $tilePosition->getFloorY();
|
||||
$localZ = $tilePosition->getFloorZ() & Chunk::COORD_MASK;
|
||||
|
||||
$newBlock = RuntimeBlockStateRegistry::getInstance()->fromStateId($chunk->getBlockStateId($localX, $localY, $localZ));
|
||||
$newBlock = $this->blockStateRegistry->fromStateId($chunk->getBlockStateId($localX, $localY, $localZ));
|
||||
$expectedTileClass = $newBlock->getIdInfo()->getTileClass();
|
||||
if(
|
||||
$expectedTileClass === null || //new block doesn't expect a tile
|
||||
|
Reference in New Issue
Block a user