*/ class Wall extends Transparent{ /** * @var WallConnectionType[] * @phpstan-var WallConnectionSet */ protected array $connections = []; protected bool $post = false; public function getRequiredStateDataBits() : int{ return 9; } protected function describeState(RuntimeDataDescriber $w) : void{ $w->wallConnections($this->connections); $w->bool($this->post); } /** * @return WallConnectionType[] * @phpstan-return WallConnectionSet */ public function getConnections() : array{ return $this->connections; } public function getConnection(int $face) : ?WallConnectionType{ return $this->connections[$face] ?? null; } /** * @param WallConnectionType[] $connections * @phpstan-param WallConnectionSet $connections * @return $this */ public function setConnections(array $connections) : self{ $this->connections = $connections; return $this; } /** @return $this */ public function setConnection(int $face, ?WallConnectionType $type) : self{ if($face !== Facing::NORTH && $face !== Facing::SOUTH && $face !== Facing::WEST && $face !== Facing::EAST){ throw new \InvalidArgumentException("Facing can only be north, east, south or west"); } if($type !== null){ $this->connections[$face] = $type; }else{ unset($this->connections[$face]); } return $this; } public function isPost() : bool{ return $this->post; } /** @return $this */ public function setPost(bool $post) : self{ $this->post = $post; return $this; } public function onNearbyBlockChange() : void{ if($this->recalculateConnections()){ $this->position->getWorld()->setBlock($this->position, $this); } } protected function recalculateConnections() : bool{ $changed = 0; //TODO: implement tall/short connections - right now we only support short as per pre-1.16 foreach(Facing::HORIZONTAL as $facing){ $block = $this->getSide($facing); if($block instanceof static || $block instanceof FenceGate || $block instanceof Thin || ($block->isSolid() && !$block->isTransparent())){ if(!isset($this->connections[$facing])){ $this->connections[$facing] = WallConnectionType::SHORT(); $changed++; } }elseif(isset($this->connections[$facing])){ unset($this->connections[$facing]); $changed++; } } $up = $this->getSide(Facing::UP)->getTypeId() !== BlockTypeIds::AIR; if($up !== $this->post){ $this->post = $up; $changed++; } return $changed > 0; } protected function recalculateCollisionBoxes() : array{ //walls don't have any special collision boxes like fences do $north = isset($this->connections[Facing::NORTH]); $south = isset($this->connections[Facing::SOUTH]); $west = isset($this->connections[Facing::WEST]); $east = isset($this->connections[Facing::EAST]); $inset = 0.25; if( !$this->post && //if there is a block on top, it stays as a post ( ($north && $south && !$west && !$east) || (!$north && !$south && $west && $east) ) ){ //If connected to two sides on the same axis but not any others, AND there is not a block on top, there is no post and the wall is thinner $inset = 0.3125; } return [ AxisAlignedBB::one() ->extend(Facing::UP, 0.5) ->trim(Facing::NORTH, $north ? 0 : $inset) ->trim(Facing::SOUTH, $south ? 0 : $inset) ->trim(Facing::WEST, $west ? 0 : $inset) ->trim(Facing::EAST, $east ? 0 : $inset) ]; } public function getSupportType(int $facing) : SupportType{ return Facing::axis($facing) === Axis::Y ? SupportType::CENTER() : SupportType::NONE(); } }