diff --git a/README.md b/README.md index d0634fde..0b87d406 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ Example servers running Turanic - [ ] More thread/worker - [ ] Basic ChunkLoader System - [ ] Fast NBT Writer/reader - - [ ] Basic Redstone system (without lag) (Progress: %80) + - [ ] Basic Redstone system (without lag) (Progress: %10) - [ ] Update languages
***More to do...*** diff --git a/src/pocketmine/block/Block.php b/src/pocketmine/block/Block.php index a53443e9..db4eb26d 100644 --- a/src/pocketmine/block/Block.php +++ b/src/pocketmine/block/Block.php @@ -503,7 +503,7 @@ public function getFuelTime() : int{ */ public function getSide($side, $step = 1){ if($this->isValid()){ - return $this->getLevel()->getBlock(Vector3::getSide($side, $step)); + return $this->getLevel()->getBlockAt(...Vector3::getSide($side, $step)->toArray()); } return BlockFactory::get(Block::AIR, 0, Position::fromObject(Vector3::getSide($side, $step))); @@ -738,24 +738,41 @@ public function canNeighborBurn(){ public function isPlaceable(){ return $this->canBePlaced(); } - - public function getMaxStackSize() : int{ - return 64; + public function getMaxStackSize() : int{ + return 64; } - public function isNormal(){ - return !$this->isTransparent() && $this->isSolid() && !$this->isRedstoneSource(); + /** + * Kızıltaş kaynağı kontrolü + * + * @return bool + */ + public function isRedstoneSource() : bool{ + return false; } - public function isRedstoneSource(){ - return false; + /** + * Kızıltaş güç seviyesi + * NOT: Güç seviyesi isRedstoneSource fonksiyonundan bağımsız çalışır + * + * @return int + */ + public function getRedstonePower() : int{ + return 0; } - public function getWeakPower(int $side) : int{ - return 0; + /** + * Kızıltaş ile güncellenebilir mi ? + * + * @return bool + */ + public function canUpdateWithRedstone() : bool{ + return false; } - public function activate(){ // TODO : remove + // TODO : remove + + public function activate(){ return false; } diff --git a/src/pocketmine/block/BlockFactory.php b/src/pocketmine/block/BlockFactory.php index 72b2210f..318ffd7c 100644 --- a/src/pocketmine/block/BlockFactory.php +++ b/src/pocketmine/block/BlockFactory.php @@ -188,7 +188,7 @@ public static function init(bool $force = false){ self::registerBlock(new EndStone()); self::registerBlock(new DragonEgg()); self::registerBlock(new RedstoneLamp()); - self::registerBlock(new LitRedstoneLamp()); + self::registerBlock(new RedstoneLampLit()); self::registerBlock(new Dropper()); self::registerBlock(new ActivatorRail()); self::registerBlock(new CocoaBlock()); diff --git a/src/pocketmine/block/Button.php b/src/pocketmine/block/Button.php index e349ca05..fe55d039 100644 --- a/src/pocketmine/block/Button.php +++ b/src/pocketmine/block/Button.php @@ -26,8 +26,12 @@ namespace pocketmine\block; +use pocketmine\block\utils\RedstoneUtils; use pocketmine\item\Item; +use pocketmine\level\Level; +use pocketmine\level\Position; use pocketmine\math\Vector3; +use pocketmine\network\mcpe\protocol\LevelEventPacket; use pocketmine\Player; abstract class Button extends Flowable { @@ -51,7 +55,42 @@ public function place(Item $item, Block $blockReplace, Block $blockClicked, int } public function onActivate(Item $item, Player $player = null): bool{ - // TODO : Add Redstone System + if(!$this->isRedstoneSource()){ + $this->meta ^= 0x08; + $this->level->setBlock($this, $this, true, false); + $this->level->scheduleDelayedBlockUpdate($this, 30); + $this->level->broadcastLevelEvent($this, LevelEventPacket::EVENT_REDSTONE_TRIGGER); + RedstoneUtils::updateRedstone($this, null, true); + RedstoneUtils::updateRedstone($this->getOppositeSidePosition(), null, true, $this->asPosition()); + } return true; } + + public function onUpdate(int $type){ + switch($type){ + case Level::BLOCK_UPDATE_SCHEDULED: + if($this->isRedstoneSource()){ + $this->meta ^= 0x08; + $this->level->setBlock($this, $this, true, false); + $this->level->broadcastLevelEvent($this, LevelEventPacket::EVENT_REDSTONE_TRIGGER); + RedstoneUtils::updateRedstone($this, null, true); + RedstoneUtils::updateRedstone($this->getOppositeSidePosition(), null, true, $this->asPosition()); + } + break; + } + } + + public function isRedstoneSource(): bool{ + return (($this->meta & 0x08) === 0x08); + } + + + public function getRedstonePower(): int{ + return 15; + } + + public function getOppositeSidePosition(){ + $side = self::getOppositeSide($this->isRedstoneSource() ? $this->meta ^ 0x08 : $this->meta); + return Position::fromObject($this->asVector3()->getSide($side), $this->level); + } } \ No newline at end of file diff --git a/src/pocketmine/block/DaylightDetector.php b/src/pocketmine/block/DaylightDetector.php index 53a3ae8a..002aa39d 100644 --- a/src/pocketmine/block/DaylightDetector.php +++ b/src/pocketmine/block/DaylightDetector.php @@ -87,10 +87,6 @@ public function getFuelTime(): int{ return 300; } - public function isRedstoneSource(){ - return true; - } - public function getWeakPower(int $side): int{ return $this->getTile()->getLightByTime(); } diff --git a/src/pocketmine/block/DaylightDetectorInverted.php b/src/pocketmine/block/DaylightDetectorInverted.php index 52f252fb..46d78d39 100644 --- a/src/pocketmine/block/DaylightDetectorInverted.php +++ b/src/pocketmine/block/DaylightDetectorInverted.php @@ -36,10 +36,6 @@ public function onActivate(Item $item, Player $player = null) : bool{ return true; } - public function isRedstoneSource(){ - return false; - } - public function getWeakPower(int $side): int{ return 0; } diff --git a/src/pocketmine/block/Lever.php b/src/pocketmine/block/Lever.php index 18285ec9..c6fc2a76 100644 --- a/src/pocketmine/block/Lever.php +++ b/src/pocketmine/block/Lever.php @@ -24,10 +24,11 @@ namespace pocketmine\block; +use pocketmine\block\utils\RedstoneUtils; use pocketmine\item\Item; use pocketmine\level\Level; -use pocketmine\level\sound\ButtonClickSound; use pocketmine\math\Vector3; +use pocketmine\network\mcpe\protocol\LevelEventPacket; use pocketmine\Player; class Lever extends Flowable { @@ -96,4 +97,20 @@ public function place(Item $item, Block $blockReplace, Block $blockClicked, int return $this->level->setBlock($blockReplace, $this, true, true); } + + public function onActivate(Item $item, Player $player = null) : bool{ + $this->meta ^= 0x08; + $this->level->setBlock($this, $this, false, true); + $this->level->broadcastLevelEvent($this, LevelEventPacket::EVENT_REDSTONE_TRIGGER); + RedstoneUtils::updateRedstone($this); + return true; + } + + public function isRedstoneSource(): bool{ + return ($this->meta & 0x08) > 0; + } + + public function getRedstonePower(): int{ + return 15; + } } \ No newline at end of file diff --git a/src/pocketmine/block/PressurePlate.php b/src/pocketmine/block/PressurePlate.php index 95b196c8..634c9956 100644 --- a/src/pocketmine/block/PressurePlate.php +++ b/src/pocketmine/block/PressurePlate.php @@ -59,10 +59,6 @@ protected function recalculateCollisionBoxes(): array{ return [new AxisAlignedBB($this->x + 0.125, $this->y, $this->z + 0.125, $this->x + 0.875, $this->y + 0.25, $this->z + 0.875)]; } - public function isRedstoneSource(){ - return true; - } - public function hasEntityCollision() : bool{ return true; } diff --git a/src/pocketmine/block/Redstone.php b/src/pocketmine/block/Redstone.php index 4f717e00..aa079c5e 100644 --- a/src/pocketmine/block/Redstone.php +++ b/src/pocketmine/block/Redstone.php @@ -26,81 +26,53 @@ namespace pocketmine\block; +use pocketmine\block\utils\RedstoneUtils; use pocketmine\item\TieredTool; -use pocketmine\item\Item; -use pocketmine\math\Vector3; -use pocketmine\Player; +use pocketmine\level\Level; class Redstone extends Solid { protected $id = self::REDSTONE_BLOCK; - public function isActivated(Block $from = null){ - return true; + public function __construct(int $meta = 0){ + $this->meta = $meta; } - public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ - parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); - $kontrol = false; - foreach ([self::SIDE_NORTH, self::SIDE_SOUTH, self::SIDE_WEST, self::SIDE_EAST] as $side) { - /** @var RedstoneWire $wire */ - $wire = $this->getSide($side); - if($wire->getId() == $this->id){ - if($wire->isActivated()){ - $kontrol = true; // found redstone wire - break; - } - } - } - if(!$kontrol) - $this->level->updateAroundRedstone($this); - return true; - } - - public function __construct(int $meta = 0){ - $this->meta = $meta; - } - - public function getBlastResistance() : float{ - return 10; + public function getName() : string{ + return "Block of Redstone"; } public function getHardness() : float{ return 5; } - public function isRedstoneSource(){ - return true; - } - - public function getWeakPower(int $side): int{ - return 15; + public function getBlastResistance() : float{ + return 30; } - /** - * @return \pocketmine\math\AxisAlignedBB - */ - public function getBoundingBox(){ - return Block::getBoundingBox(); - } - - public function canBeFlowedInto() : bool{ + public function canBeFlowedInto() : bool{ return false; } - public function isSolid() : bool{ - return true; - } - - public function getToolType() : int{ + public function getToolType() : int{ return BlockToolType::TYPE_PICKAXE; } - public function getToolHarvestLevel(): int{ + public function getToolHarvestLevel(): int{ return TieredTool::TIER_WOODEN; } - public function getName() : string{ - return "Block of Redstone"; - } + public function isRedstoneSource() : bool{ + return true; + } + + public function getRedstonePower(): int{ + return 15; + } + + public function onUpdate(int $type){ + if($type == Level::BLOCK_UPDATE_NORMAL){ + RedstoneUtils::updateRedstone($this); + } + } } diff --git a/src/pocketmine/block/RedstoneDiode.php b/src/pocketmine/block/RedstoneDiode.php index 22933fa0..39e992b1 100644 --- a/src/pocketmine/block/RedstoneDiode.php +++ b/src/pocketmine/block/RedstoneDiode.php @@ -38,10 +38,6 @@ public function __construct($meta = 0){ parent::__construct($meta); } - public function isRedstoneSource(){ - return true; - } - abstract function getFacing() : int; public function onBreak(Item $item, Player $player = null) : bool{ diff --git a/src/pocketmine/block/RedstoneLamp.php b/src/pocketmine/block/RedstoneLamp.php index ad2515d8..4dc759eb 100644 --- a/src/pocketmine/block/RedstoneLamp.php +++ b/src/pocketmine/block/RedstoneLamp.php @@ -24,6 +24,7 @@ namespace pocketmine\block; +use pocketmine\block\utils\RedstoneUtils; use pocketmine\level\Level; class RedstoneLamp extends Solid { @@ -33,27 +34,23 @@ public function __construct(int $meta = 0){ $this->meta = $meta; } - public function getLightLevel() : int{ - return 0; - } + public function getName() : string{ + return "Redstone Lamp"; + } public function getHardness() : float{ return 0.3; } - public function getToolType() : int{ - return BlockToolType::TYPE_PICKAXE; - } - - public function getName() : string{ - return "Redstone Lamp"; - } - public function onUpdate(int $type){ if($type == Level::BLOCK_UPDATE_NORMAL || $type == Level::BLOCK_UPDATE_REDSTONE){ - if($this->level->isBlockPowered($this) or $this->level->isBlockPowered($this->getSide(self::SIDE_UP))){ - $this->level->setBlock($this, new LitRedstoneLamp(), false, false); + if(RedstoneUtils::isRedstonePowered($this->asPosition())){ + $this->level->setBlock($this, Block::get(Block::LIT_REDSTONE_LAMP)); } } } + + public function canUpdateWithRedstone(): bool{ + return true; + } } diff --git a/src/pocketmine/block/LitRedstoneLamp.php b/src/pocketmine/block/RedstoneLampLit.php similarity index 72% rename from src/pocketmine/block/LitRedstoneLamp.php rename to src/pocketmine/block/RedstoneLampLit.php index 36b72871..f55339eb 100644 --- a/src/pocketmine/block/LitRedstoneLamp.php +++ b/src/pocketmine/block/RedstoneLampLit.php @@ -24,11 +24,14 @@ namespace pocketmine\block; +use pocketmine\block\utils\RedstoneUtils; use pocketmine\level\Level; -class LitRedstoneLamp extends RedstoneLamp implements ElectricalAppliance, SolidLight{ +class RedstoneLampLit extends RedstoneLamp implements SolidLight{ protected $id = self::LIT_REDSTONE_LAMP; + /** @var bool */ + private $delayed = false; public function getName() : string{ return "Lit Redstone Lamp"; @@ -42,12 +45,13 @@ public function onUpdate(int $type){ switch($type){ case Level::BLOCK_UPDATE_NORMAL: case Level::BLOCK_UPDATE_REDSTONE: - if (!$this->level->isBlockPowered($this)) + if (!RedstoneUtils::isRedstonePowered($this)) + $this->delayed = true; $this->level->scheduleDelayedBlockUpdate($this, 4); break; case Level::BLOCK_UPDATE_SCHEDULED: - if (!$this->level->isBlockPowered($this)) - $this->level->setBlock($this, new RedstoneLamp(), false, false); + if($this->delayed or !RedstoneUtils::isRedstonePowered($this)) + $this->level->setBlock($this, Block::get(Block::REDSTONE_LAMP), false, false); break; } } diff --git a/src/pocketmine/block/RedstoneTorch.php b/src/pocketmine/block/RedstoneTorch.php index 84c565ef..6c87d8e6 100644 --- a/src/pocketmine/block/RedstoneTorch.php +++ b/src/pocketmine/block/RedstoneTorch.php @@ -94,10 +94,6 @@ public function getWeakPower(int $side): int{ return 15; } - public function isRedstoneSource(){ - return true; - } - public function getDropsForCompatibleTool(Item $item) : array{ return [ Item::get(Item::REDSTONE_TORCH) diff --git a/src/pocketmine/block/RedstoneWire.php b/src/pocketmine/block/RedstoneWire.php index d3b573c6..b54f0240 100644 --- a/src/pocketmine/block/RedstoneWire.php +++ b/src/pocketmine/block/RedstoneWire.php @@ -318,10 +318,6 @@ private function cantBePlacedOn($side = self::SIDE_DOWN){ return $down instanceof Transparent and $down->getId() != Block::REDSTONE_LAMP and $down->getId() != Block::LIT_REDSTONE_LAMP; } - public function isRedstoneSource(){ - return ($this->meta > 0); - } - public function getUnconnectedSide(){ $connected = []; $notConnected = []; diff --git a/src/pocketmine/block/TrappedChest.php b/src/pocketmine/block/TrappedChest.php index 26cf22ca..08d3d627 100644 --- a/src/pocketmine/block/TrappedChest.php +++ b/src/pocketmine/block/TrappedChest.php @@ -166,8 +166,4 @@ public function getWeakPower(int $side): int{ return $playerCount < 0 ? 0 : $playerCount > 15 ? 15 : $playerCount; } - - public function isRedstoneSource(){ - return true; - } } \ No newline at end of file diff --git a/src/pocketmine/block/utils/RedstoneUtils.php b/src/pocketmine/block/utils/RedstoneUtils.php new file mode 100644 index 00000000..480bceae --- /dev/null +++ b/src/pocketmine/block/utils/RedstoneUtils.php @@ -0,0 +1,79 @@ +getLevel(); + $vec = clone $position->asVector3(); + foreach($sides as $side){ + $blok = $level->getBlockAt(...$vec->getSide($side)->toArray()); + if($blok->canUpdateWithRedstone()){ + $blok->onUpdate(Level::BLOCK_UPDATE_REDSTONE); + if($cache){ + if($real === null) $real = $position; + self::$cacheRedstone[self::positionEncode($blok->asPosition())] = self::positionEncode($real); + } + } + } + } + + protected static function positionEncode(Position $position) : string{ + return implode(":", $position->toArray()); + } + + protected static function positionDecode(string $encode) : Position{ + $array = explode(":", $encode); + $array[3] = Server::getInstance()->getLevelByName($array[3]); + return new Position(...$array); + } + + public static function isRedstonePowered(Position $position, bool $checkCache = true) : bool{ + if($checkCache){ + $hash = self::positionEncode($position); + if(!empty(self::$cacheRedstone[$hash])){ + $decode = self::positionDecode(self::$cacheRedstone[$hash]); + $blok = $decode->getLevel()->getBlockAt(...$decode->asVector3()->toArray()); + if($blok->isRedstoneSource()){ + return true; + }else{ + unset(self::$cacheRedstone[$hash]); + } + } + } + + $level = $position->getLevel(); + foreach(self::$allSides as $side){ + $blok = $level->getBlockAt(...$position->getSide($side)->toArray()); + if($blok->isRedstoneSource() && $blok->getRedstonePower() > 0){ + return true; + } + } + + return false; + } +} \ No newline at end of file diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index edeea093..60fd43e3 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -3247,11 +3247,6 @@ public function adjustPosToNearbyEntity(Vector3 $pos){ } } - public function getRedstonePower(Vector3 $pos, int $face) : int{ - $block = $this->getBlockAt($pos->x, $pos->y, $pos->z); - return $block->getWeakPower($face); - } - public function isBlockPowered(Vector3 $pos) : bool{ $sides = [Vector3::SIDE_NORTH, Vector3::SIDE_SOUTH, Vector3::SIDE_WEST, Vector3::SIDE_EAST, Vector3::SIDE_DOWN, Vector3::SIDE_UP]; foreach($sides as $side){ diff --git a/src/pocketmine/level/Position.php b/src/pocketmine/level/Position.php index c4dc474f..e6b538ad 100644 --- a/src/pocketmine/level/Position.php +++ b/src/pocketmine/level/Position.php @@ -119,11 +119,7 @@ public function getSide($side, $step = 1){ public function __toString(){ return "Position(level=" . ($this->isValid() ? $this->getLevel()->getName() : "null") . ",x=" . $this->x . ",y=" . $this->y . ",z=" . $this->z . ")"; } - - public function toArray() : array{ - return [$this->x, $this->y, $this->z, $this->level->getFolderName()]; - } - + public function equals(Vector3 $v) : bool{ if($v instanceof Position){ return parent::equals($v) and $v->getLevel() === $this->getLevel(); @@ -131,4 +127,8 @@ public function equals(Vector3 $v) : bool{ return parent::equals($v); } + public function toArray() : array{ + return [$this->x, $this->y, $this->z, $this->level->getFolderName()]; + } + } \ No newline at end of file diff --git a/src/pocketmine/math/Vector3.php b/src/pocketmine/math/Vector3.php index 6bff5b3f..ddda9896 100644 --- a/src/pocketmine/math/Vector3.php +++ b/src/pocketmine/math/Vector3.php @@ -474,7 +474,7 @@ public function __toString(){ public function toArray() : array{ return [$this->x, $this->y, $this->z]; - } + } /** * @param Random $random