mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-13 15:05:33 +00:00
Dye now can be used to change Sign text color (#4690)
This commit is contained in:
parent
1ecb10acba
commit
fedd541663
@ -24,17 +24,23 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\tile\Sign as TileSign;
|
use pocketmine\block\tile\Sign as TileSign;
|
||||||
|
use pocketmine\block\utils\DyeColor;
|
||||||
use pocketmine\block\utils\SignText;
|
use pocketmine\block\utils\SignText;
|
||||||
use pocketmine\block\utils\SupportType;
|
use pocketmine\block\utils\SupportType;
|
||||||
use pocketmine\block\utils\WoodType;
|
use pocketmine\block\utils\WoodType;
|
||||||
use pocketmine\block\utils\WoodTypeTrait;
|
use pocketmine\block\utils\WoodTypeTrait;
|
||||||
|
use pocketmine\color\Color;
|
||||||
use pocketmine\event\block\SignChangeEvent;
|
use pocketmine\event\block\SignChangeEvent;
|
||||||
|
use pocketmine\item\Dye;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\item\ItemTypeIds;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
use pocketmine\utils\TextFormat;
|
use pocketmine\utils\TextFormat;
|
||||||
use pocketmine\world\BlockTransaction;
|
use pocketmine\world\BlockTransaction;
|
||||||
|
use pocketmine\world\sound\DyeUseSound;
|
||||||
|
use pocketmine\world\sound\InkSacUseSound;
|
||||||
use function array_map;
|
use function array_map;
|
||||||
use function assert;
|
use function assert;
|
||||||
use function strlen;
|
use function strlen;
|
||||||
@ -111,6 +117,55 @@ abstract class BaseSign extends Transparent{
|
|||||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function doSignChange(SignText $newText, Player $player, Item $item) : bool{
|
||||||
|
$ev = new SignChangeEvent($this, $player, $newText);
|
||||||
|
$ev->call();
|
||||||
|
if(!$ev->isCancelled()){
|
||||||
|
$this->text = $ev->getNewText();
|
||||||
|
$this->position->getWorld()->setBlock($this->position, $this);
|
||||||
|
$item->pop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function changeSignGlowingState(bool $glowing, Player $player, Item $item) : bool{
|
||||||
|
if($this->text->isGlowing() !== $glowing && $this->doSignChange(new SignText($this->text->getLines(), $this->text->getBaseColor(), $glowing), $player, $item)){
|
||||||
|
$this->position->getWorld()->addSound($this->position, new InkSacUseSound());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||||
|
if($player === null){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$dyeColor = $item instanceof Dye ? $item->getColor() : match($item->getTypeId()){
|
||||||
|
ItemTypeIds::BONE_MEAL => DyeColor::WHITE(),
|
||||||
|
ItemTypeIds::LAPIS_LAZULI => DyeColor::BLUE(),
|
||||||
|
ItemTypeIds::COCOA_BEANS => DyeColor::BROWN(),
|
||||||
|
default => null
|
||||||
|
};
|
||||||
|
if($dyeColor !== null){
|
||||||
|
$color = $dyeColor->equals(DyeColor::BLACK()) ? new Color(0, 0, 0) : $dyeColor->getRgbValue();
|
||||||
|
if($color->toARGB() === $this->text->getBaseColor()->toARGB()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->doSignChange(new SignText($this->text->getLines(), $color, $this->text->isGlowing()), $player, $item)){
|
||||||
|
$this->position->getWorld()->addSound($this->position, new DyeUseSound());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}elseif($item->getTypeId() === ItemTypeIds::INK_SAC){
|
||||||
|
return $this->changeSignGlowingState(false, $player, $item);
|
||||||
|
}elseif($item->getTypeId() === ItemTypeIds::GLOW_INK_SAC){
|
||||||
|
return $this->changeSignGlowingState(true, $player, $item);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an object containing information about the sign text.
|
* Returns an object containing information about the sign text.
|
||||||
*/
|
*/
|
||||||
|
@ -24,9 +24,13 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block\tile;
|
namespace pocketmine\block\tile;
|
||||||
|
|
||||||
use pocketmine\block\utils\SignText;
|
use pocketmine\block\utils\SignText;
|
||||||
|
use pocketmine\color\Color;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
|
use pocketmine\nbt\tag\ByteTag;
|
||||||
use pocketmine\nbt\tag\CompoundTag;
|
use pocketmine\nbt\tag\CompoundTag;
|
||||||
|
use pocketmine\nbt\tag\IntTag;
|
||||||
use pocketmine\nbt\tag\StringTag;
|
use pocketmine\nbt\tag\StringTag;
|
||||||
|
use pocketmine\utils\Binary;
|
||||||
use pocketmine\world\World;
|
use pocketmine\world\World;
|
||||||
use function array_pad;
|
use function array_pad;
|
||||||
use function array_slice;
|
use function array_slice;
|
||||||
@ -42,6 +46,13 @@ use function sprintf;
|
|||||||
class Sign extends Spawnable{
|
class Sign extends Spawnable{
|
||||||
public const TAG_TEXT_BLOB = "Text";
|
public const TAG_TEXT_BLOB = "Text";
|
||||||
public const TAG_TEXT_LINE = "Text%d"; //sprintf()able
|
public const TAG_TEXT_LINE = "Text%d"; //sprintf()able
|
||||||
|
public const TAG_TEXT_COLOR = "SignTextColor";
|
||||||
|
public const TAG_GLOWING_TEXT = "IgnoreLighting";
|
||||||
|
/**
|
||||||
|
* 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";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string[]
|
* @return string[]
|
||||||
@ -60,7 +71,20 @@ class Sign extends Spawnable{
|
|||||||
|
|
||||||
public function readSaveData(CompoundTag $nbt) : void{
|
public function readSaveData(CompoundTag $nbt) : void{
|
||||||
if(($textBlobTag = $nbt->getTag(self::TAG_TEXT_BLOB)) instanceof StringTag){ //MCPE 1.2 save format
|
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'));
|
$baseColor = new Color(0, 0, 0);
|
||||||
|
$glowingText = false;
|
||||||
|
if(($baseColorTag = $nbt->getTag(self::TAG_TEXT_COLOR)) instanceof IntTag){
|
||||||
|
$baseColor = Color::fromARGB(Binary::unsignInt($baseColorTag->getValue()));
|
||||||
|
}
|
||||||
|
if(
|
||||||
|
($glowingTextTag = $nbt->getTag(self::TAG_GLOWING_TEXT)) instanceof ByteTag &&
|
||||||
|
($lightingBugResolvedTag = $nbt->getTag(self::TAG_LEGACY_BUG_RESOLVE)) instanceof ByteTag
|
||||||
|
){
|
||||||
|
//both of these must be 1 - if only one is set, it's a leftover from 1.16.210 experimental features
|
||||||
|
//see https://bugs.mojang.com/browse/MCPE-117835
|
||||||
|
$glowingText = $glowingTextTag->getValue() !== 0 && $lightingBugResolvedTag->getValue() !== 0;
|
||||||
|
}
|
||||||
|
$this->text = SignText::fromBlob(mb_scrub($textBlobTag->getValue(), 'UTF-8'), $baseColor, $glowingText);
|
||||||
}else{
|
}else{
|
||||||
$text = [];
|
$text = [];
|
||||||
for($i = 0; $i < SignText::LINE_COUNT; ++$i){
|
for($i = 0; $i < SignText::LINE_COUNT; ++$i){
|
||||||
@ -80,6 +104,9 @@ class Sign extends Spawnable{
|
|||||||
$textKey = sprintf(self::TAG_TEXT_LINE, $i + 1);
|
$textKey = sprintf(self::TAG_TEXT_LINE, $i + 1);
|
||||||
$nbt->setString($textKey, $this->text->getLine($i));
|
$nbt->setString($textKey, $this->text->getLine($i));
|
||||||
}
|
}
|
||||||
|
$nbt->setInt(self::TAG_TEXT_COLOR, Binary::signInt($this->text->getBaseColor()->toARGB()));
|
||||||
|
$nbt->setByte(self::TAG_GLOWING_TEXT, $this->text->isGlowing() ? 1 : 0);
|
||||||
|
$nbt->setByte(self::TAG_LEGACY_BUG_RESOLVE, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getText() : SignText{
|
public function getText() : SignText{
|
||||||
@ -108,5 +135,8 @@ class Sign extends Spawnable{
|
|||||||
|
|
||||||
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||||
$nbt->setString(self::TAG_TEXT_BLOB, implode("\n", $this->text->getLines()));
|
$nbt->setString(self::TAG_TEXT_BLOB, implode("\n", $this->text->getLines()));
|
||||||
|
$nbt->setInt(self::TAG_TEXT_COLOR, Binary::signInt($this->text->getBaseColor()->toARGB()));
|
||||||
|
$nbt->setByte(self::TAG_GLOWING_TEXT, $this->text->isGlowing() ? 1 : 0);
|
||||||
|
$nbt->setByte(self::TAG_LEGACY_BUG_RESOLVE, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block\utils;
|
namespace pocketmine\block\utils;
|
||||||
|
|
||||||
|
use pocketmine\color\Color;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
use function array_fill;
|
use function array_fill;
|
||||||
use function array_pad;
|
use function array_pad;
|
||||||
@ -37,6 +38,8 @@ class SignText{
|
|||||||
|
|
||||||
/** @var string[] */
|
/** @var string[] */
|
||||||
private array $lines;
|
private array $lines;
|
||||||
|
private Color $baseColor;
|
||||||
|
private bool $glowing;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string[]|null $lines index-sensitive; omitting an index will leave it unchanged
|
* @param string[]|null $lines index-sensitive; omitting an index will leave it unchanged
|
||||||
@ -45,7 +48,7 @@ class SignText{
|
|||||||
* @throws \InvalidArgumentException if invalid keys (out of bounds or string) are found in the array
|
* @throws \InvalidArgumentException if invalid keys (out of bounds or string) are found in the array
|
||||||
* @throws \InvalidArgumentException if any line is not valid UTF-8 or contains a newline
|
* @throws \InvalidArgumentException if any line is not valid UTF-8 or contains a newline
|
||||||
*/
|
*/
|
||||||
public function __construct(?array $lines = null){
|
public function __construct(?array $lines = null, ?Color $baseColor = null, bool $glowing = false){
|
||||||
$this->lines = array_fill(0, self::LINE_COUNT, "");
|
$this->lines = array_fill(0, self::LINE_COUNT, "");
|
||||||
if($lines !== null){
|
if($lines !== null){
|
||||||
if(count($lines) > self::LINE_COUNT){
|
if(count($lines) > self::LINE_COUNT){
|
||||||
@ -61,6 +64,8 @@ class SignText{
|
|||||||
$this->lines[$k] = $line;
|
$this->lines[$k] = $line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$this->baseColor = $baseColor ?? new Color(0, 0, 0);
|
||||||
|
$this->glowing = $glowing;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,8 +74,8 @@ class SignText{
|
|||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException if the text is not valid UTF-8
|
* @throws \InvalidArgumentException if the text is not valid UTF-8
|
||||||
*/
|
*/
|
||||||
public static function fromBlob(string $blob) : SignText{
|
public static function fromBlob(string $blob, ?Color $baseColor = null, bool $glowing = false) : SignText{
|
||||||
return new self(array_slice(array_pad(explode("\n", $blob), self::LINE_COUNT, ""), 0, self::LINE_COUNT));
|
return new self(array_slice(array_pad(explode("\n", $blob), self::LINE_COUNT, ""), 0, self::LINE_COUNT), $baseColor, $glowing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,4 +108,19 @@ class SignText{
|
|||||||
$this->checkLineIndex($index);
|
$this->checkLineIndex($index);
|
||||||
return $this->lines[$index];
|
return $this->lines[$index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the base text color of sign. Color codes using the § escape character will override this color when used.
|
||||||
|
*/
|
||||||
|
public function getBaseColor() : Color{
|
||||||
|
return $this->baseColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the sign text is glowing. When true, the text will have an outline (usually a darker tone of the
|
||||||
|
* base color, or white for black text), and will glow in the dark, making it readable without any light sources.
|
||||||
|
*/
|
||||||
|
public function isGlowing() : bool{
|
||||||
|
return $this->glowing;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
35
src/world/sound/DyeUseSound.php
Normal file
35
src/world/sound/DyeUseSound.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?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\world\sound;
|
||||||
|
|
||||||
|
use pocketmine\math\Vector3;
|
||||||
|
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\LevelEvent;
|
||||||
|
|
||||||
|
final class DyeUseSound implements Sound{
|
||||||
|
|
||||||
|
public function encode(Vector3 $pos) : array{
|
||||||
|
return [LevelEventPacket::create(LevelEvent::SOUND_DYE_USED, 0, $pos)];
|
||||||
|
}
|
||||||
|
}
|
35
src/world/sound/InkSacUseSound.php
Normal file
35
src/world/sound/InkSacUseSound.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?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\world\sound;
|
||||||
|
|
||||||
|
use pocketmine\math\Vector3;
|
||||||
|
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\LevelEvent;
|
||||||
|
|
||||||
|
final class InkSacUseSound implements Sound{
|
||||||
|
|
||||||
|
public function encode(Vector3 $pos) : array{
|
||||||
|
return [LevelEventPacket::create(LevelEvent::SOUND_INK_SAC_USED, 0, $pos)];
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user