mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-22 08:44:01 +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;
|
||||
|
||||
use pocketmine\block\tile\Sign as TileSign;
|
||||
use pocketmine\block\utils\DyeColor;
|
||||
use pocketmine\block\utils\SignText;
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\block\utils\WoodType;
|
||||
use pocketmine\block\utils\WoodTypeTrait;
|
||||
use pocketmine\color\Color;
|
||||
use pocketmine\event\block\SignChangeEvent;
|
||||
use pocketmine\item\Dye;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemTypeIds;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\sound\DyeUseSound;
|
||||
use pocketmine\world\sound\InkSacUseSound;
|
||||
use function array_map;
|
||||
use function assert;
|
||||
use function strlen;
|
||||
@ -111,6 +117,55 @@ abstract class BaseSign extends Transparent{
|
||||
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.
|
||||
*/
|
||||
|
@ -24,9 +24,13 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block\tile;
|
||||
|
||||
use pocketmine\block\utils\SignText;
|
||||
use pocketmine\color\Color;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\ByteTag;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\world\World;
|
||||
use function array_pad;
|
||||
use function array_slice;
|
||||
@ -42,6 +46,13 @@ use function sprintf;
|
||||
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";
|
||||
/**
|
||||
* 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[]
|
||||
@ -60,7 +71,20 @@ class Sign extends Spawnable{
|
||||
|
||||
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'));
|
||||
$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{
|
||||
$text = [];
|
||||
for($i = 0; $i < SignText::LINE_COUNT; ++$i){
|
||||
@ -80,6 +104,9 @@ class Sign extends Spawnable{
|
||||
$textKey = sprintf(self::TAG_TEXT_LINE, $i + 1);
|
||||
$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{
|
||||
@ -108,5 +135,8 @@ class Sign extends Spawnable{
|
||||
|
||||
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||
$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;
|
||||
|
||||
use pocketmine\color\Color;
|
||||
use pocketmine\utils\Utils;
|
||||
use function array_fill;
|
||||
use function array_pad;
|
||||
@ -37,6 +38,8 @@ class SignText{
|
||||
|
||||
/** @var string[] */
|
||||
private array $lines;
|
||||
private Color $baseColor;
|
||||
private bool $glowing;
|
||||
|
||||
/**
|
||||
* @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 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, "");
|
||||
if($lines !== null){
|
||||
if(count($lines) > self::LINE_COUNT){
|
||||
@ -61,6 +64,8 @@ class SignText{
|
||||
$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
|
||||
*/
|
||||
public static function fromBlob(string $blob) : SignText{
|
||||
return new self(array_slice(array_pad(explode("\n", $blob), self::LINE_COUNT, ""), 0, self::LINE_COUNT));
|
||||
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), $baseColor, $glowing);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -103,4 +108,19 @@ class SignText{
|
||||
$this->checkLineIndex($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