mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-02 16:23:04 +00:00
this doesn't support editing the rear side of a sign, since the 1.12 format doesn't allow us to represent the rear text, and it would necessitate API breaks to support anyway. However, we can quite trivially support APIs for the sign GUI, which plugins can use to enable editing signs. PocketMine-MP doesn't currently permit this, since it's currently an experimental feature in 1.20, but plugins can simply use Player->openSignEditor() to mimic it. This is, however, a byproduct of the fact that APIs needed to be added in order to facilitate the use of OpenSignPacket in 1.19.80.
146 lines
5.2 KiB
PHP
146 lines
5.2 KiB
PHP
<?php
|
|
|
|
/*
|
|
*
|
|
* ____ _ _ __ __ _ __ __ ____
|
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* @author PocketMine Team
|
|
* @link http://www.pocketmine.net/
|
|
*
|
|
*
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace pocketmine\block\tile;
|
|
|
|
use pocketmine\block\utils\SignText;
|
|
use pocketmine\math\Vector3;
|
|
use pocketmine\nbt\tag\CompoundTag;
|
|
use pocketmine\nbt\tag\StringTag;
|
|
use pocketmine\utils\Binary;
|
|
use pocketmine\world\World;
|
|
use function array_pad;
|
|
use function array_slice;
|
|
use function explode;
|
|
use function implode;
|
|
use function mb_scrub;
|
|
use function sprintf;
|
|
|
|
/**
|
|
* @deprecated
|
|
* @see \pocketmine\block\BaseSign
|
|
*/
|
|
class Sign extends Spawnable{
|
|
public const TAG_TEXT_BLOB = "Text";
|
|
public const TAG_TEXT_LINE = "Text%d"; //sprintf()able
|
|
public const TAG_TEXT_COLOR = "SignTextColor";
|
|
public const TAG_GLOWING_TEXT = "IgnoreLighting";
|
|
public const TAG_PERSIST_FORMATTING = "PersistFormatting"; //TAG_Byte
|
|
/**
|
|
* This tag is set to indicate that MCPE-117835 has been addressed in whatever version this sign was created.
|
|
* @see https://bugs.mojang.com/browse/MCPE-117835
|
|
*/
|
|
public const TAG_LEGACY_BUG_RESOLVE = "TextIgnoreLegacyBugResolved";
|
|
|
|
public const TAG_FRONT_TEXT = "FrontText"; //TAG_Compound
|
|
public const TAG_BACK_TEXT = "BackText"; //TAG_Compound
|
|
public const TAG_WAXED = "IsWaxed"; //TAG_Byte
|
|
public const TAG_LOCKED_FOR_EDITING_BY = "LockedForEditingBy"; //TAG_Long
|
|
|
|
/**
|
|
* @return string[]
|
|
*/
|
|
public static function fixTextBlob(string $blob) : array{
|
|
return array_slice(array_pad(explode("\n", $blob), 4, ""), 0, 4);
|
|
}
|
|
|
|
/** @var SignText */
|
|
protected $text;
|
|
|
|
/** @var int|null */
|
|
protected $editorEntityRuntimeId = null;
|
|
|
|
public function __construct(World $world, Vector3 $pos){
|
|
$this->text = new SignText();
|
|
parent::__construct($world, $pos);
|
|
}
|
|
|
|
public function readSaveData(CompoundTag $nbt) : void{
|
|
if(($textBlobTag = $nbt->getTag(self::TAG_TEXT_BLOB)) instanceof StringTag){ //MCPE 1.2 save format
|
|
$this->text = SignText::fromBlob(mb_scrub($textBlobTag->getValue(), 'UTF-8'));
|
|
}else{
|
|
$text = [];
|
|
for($i = 0; $i < SignText::LINE_COUNT; ++$i){
|
|
$textKey = sprintf(self::TAG_TEXT_LINE, $i + 1);
|
|
if(($lineTag = $nbt->getTag($textKey)) instanceof StringTag){
|
|
$text[$i] = mb_scrub($lineTag->getValue(), 'UTF-8');
|
|
}
|
|
}
|
|
$this->text = new SignText($text);
|
|
}
|
|
}
|
|
|
|
protected function writeSaveData(CompoundTag $nbt) : void{
|
|
$nbt->setString(self::TAG_TEXT_BLOB, implode("\n", $this->text->getLines()));
|
|
|
|
for($i = 0; $i < SignText::LINE_COUNT; ++$i){ //Backwards-compatibility
|
|
$textKey = sprintf(self::TAG_TEXT_LINE, $i + 1);
|
|
$nbt->setString($textKey, $this->text->getLine($i));
|
|
}
|
|
}
|
|
|
|
public function getText() : SignText{
|
|
return $this->text;
|
|
}
|
|
|
|
public function setText(SignText $text) : void{
|
|
$this->text = $text;
|
|
}
|
|
|
|
/**
|
|
* Returns the entity runtime ID of the player who placed this sign. Only the player whose entity ID matches this
|
|
* one may edit the sign text.
|
|
* This is needed because as of 1.16.220, there is still no reliable way to detect when the MCPE client closed the
|
|
* sign edit GUI, so we have no way to know when the text is finalized. This limits editing of the text to only the
|
|
* player who placed it, and only while that player is online.
|
|
* We can say for sure that the sign is finalized if either of the following occurs:
|
|
* - The player quits (after rejoin, the player's entity runtimeID will be different).
|
|
* - The chunk is unloaded (on next load, the entity runtimeID will be null, because it's not saved).
|
|
*/
|
|
public function getEditorEntityRuntimeId() : ?int{ return $this->editorEntityRuntimeId; }
|
|
|
|
public function setEditorEntityRuntimeId(?int $editorEntityRuntimeId) : void{
|
|
$this->editorEntityRuntimeId = $editorEntityRuntimeId;
|
|
}
|
|
|
|
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
|
$textPolyfill = function(CompoundTag $textTag) : CompoundTag{
|
|
//the following are not yet used by the server, but needed to roll back any changes to glowing state or colour
|
|
//if the client uses dye on the sign
|
|
return $textTag
|
|
->setInt(self::TAG_TEXT_COLOR, Binary::signInt(0xff_00_00_00))
|
|
->setByte(self::TAG_GLOWING_TEXT, 0)
|
|
->setByte(self::TAG_PERSIST_FORMATTING, 1); //TODO: not sure what this is used for
|
|
};
|
|
$nbt->setTag(self::TAG_FRONT_TEXT, $textPolyfill(CompoundTag::create()
|
|
->setString(self::TAG_TEXT_BLOB, implode("\n", $this->text->getLines()))
|
|
));
|
|
//TODO: this is not yet used by the server, but needed to rollback any client-side changes to the back text
|
|
$nbt->setTag(self::TAG_BACK_TEXT, $textPolyfill(CompoundTag::create()
|
|
->setString(self::TAG_TEXT_BLOB, "")
|
|
));
|
|
$nbt->setByte(self::TAG_WAXED, 0);
|
|
$nbt->setLong(self::TAG_LOCKED_FOR_EDITING_BY, $this->editorEntityRuntimeId ?? -1);
|
|
}
|
|
}
|