Separate dye colour ID management from DyeColor enum

This commit is contained in:
Dylan K. Taylor 2020-07-05 19:04:22 +01:00
parent bf5da596f7
commit 68c408268c
9 changed files with 139 additions and 79 deletions

View File

@ -28,6 +28,7 @@ use pocketmine\block\tile\Banner as TileBanner;
use pocketmine\block\utils\BannerPattern;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\DyeColor;
use pocketmine\data\bedrock\DyeColorIdMap;
use pocketmine\item\Banner as ItemBanner;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
@ -176,7 +177,7 @@ class Banner extends Transparent{
}
public function asItem() : Item{
return ItemFactory::getInstance()->get(ItemIds::BANNER, $this->baseColor->getInvertedMagicNumber());
return ItemFactory::getInstance()->get(ItemIds::BANNER, DyeColorIdMap::getInstance()->toInvertedId($this->baseColor));
}
public function getDropsForCompatibleTool(Item $item) : array{

View File

@ -26,6 +26,7 @@ namespace pocketmine\block;
use pocketmine\block\tile\Bed as TileBed;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\DyeColor;
use pocketmine\data\bedrock\DyeColorIdMap;
use pocketmine\item\Bed as ItemBed;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
@ -193,7 +194,7 @@ class Bed extends Transparent{
}
public function asItem() : Item{
return ItemFactory::getInstance()->get($this->idInfo->getItemId(), $this->color->getMagicNumber());
return ItemFactory::getInstance()->get($this->idInfo->getItemId(), DyeColorIdMap::getInstance()->toId($this->color));
}
public function getAffectedBlocks() : array{

View File

@ -46,6 +46,7 @@ use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\InvalidBlockStateException;
use pocketmine\block\utils\PillarRotationTrait;
use pocketmine\block\utils\TreeType;
use pocketmine\data\bedrock\DyeColorIdMap;
use pocketmine\item\Item;
use pocketmine\item\ItemIds;
use pocketmine\item\ToolTier;
@ -451,17 +452,18 @@ class BlockFactory{
$this->register(new Opaque(new BID(Ids::RED_SANDSTONE, $variant), $prefix . "Red Sandstone", $sandstoneBreakInfo));
}
$colorIdMap = DyeColorIdMap::getInstance();
foreach(DyeColor::getAll() as $color){
$this->register(new Carpet(new BID(Ids::CARPET, $color->getMagicNumber()), $color->getDisplayName() . " Carpet"));
$this->register(new Concrete(new BID(Ids::CONCRETE, $color->getMagicNumber()), $color->getDisplayName() . " Concrete"));
$this->register(new ConcretePowder(new BID(Ids::CONCRETE_POWDER, $color->getMagicNumber()), $color->getDisplayName() . " Concrete Powder"));
$this->register(new Glass(new BID(Ids::STAINED_GLASS, $color->getMagicNumber()), $color->getDisplayName() . " Stained Glass"));
$this->register(new GlassPane(new BID(Ids::STAINED_GLASS_PANE, $color->getMagicNumber()), $color->getDisplayName() . " Stained Glass Pane"));
$this->register(new Carpet(new BID(Ids::CARPET, $colorIdMap->toId($color)), $color->getDisplayName() . " Carpet"));
$this->register(new Concrete(new BID(Ids::CONCRETE, $colorIdMap->toId($color)), $color->getDisplayName() . " Concrete"));
$this->register(new ConcretePowder(new BID(Ids::CONCRETE_POWDER, $colorIdMap->toId($color)), $color->getDisplayName() . " Concrete Powder"));
$this->register(new Glass(new BID(Ids::STAINED_GLASS, $colorIdMap->toId($color)), $color->getDisplayName() . " Stained Glass"));
$this->register(new GlassPane(new BID(Ids::STAINED_GLASS_PANE, $colorIdMap->toId($color)), $color->getDisplayName() . " Stained Glass Pane"));
$this->register(new GlazedTerracotta(BlockLegacyIdHelper::getGlazedTerracottaIdentifier($color), $color->getDisplayName() . " Glazed Terracotta"));
$this->register(new HardenedClay(new BID(Ids::STAINED_CLAY, $color->getMagicNumber()), $color->getDisplayName() . " Stained Clay"));
$this->register(new HardenedGlass(new BID(Ids::HARD_STAINED_GLASS, $color->getMagicNumber()), "Hardened " . $color->getDisplayName() . " Stained Glass"));
$this->register(new HardenedGlassPane(new BID(Ids::HARD_STAINED_GLASS_PANE, $color->getMagicNumber()), "Hardened " . $color->getDisplayName() . " Stained Glass Pane"));
$this->register(new Wool(new BID(Ids::WOOL, $color->getMagicNumber()), $color->getDisplayName() . " Wool"));
$this->register(new HardenedClay(new BID(Ids::STAINED_CLAY, $colorIdMap->toId($color)), $color->getDisplayName() . " Stained Clay"));
$this->register(new HardenedGlass(new BID(Ids::HARD_STAINED_GLASS, $colorIdMap->toId($color)), "Hardened " . $color->getDisplayName() . " Stained Glass"));
$this->register(new HardenedGlassPane(new BID(Ids::HARD_STAINED_GLASS_PANE, $colorIdMap->toId($color)), "Hardened " . $color->getDisplayName() . " Stained Glass Pane"));
$this->register(new Wool(new BID(Ids::WOOL, $colorIdMap->toId($color)), $color->getDisplayName() . " Wool"));
}
$this->register(new Wall(new BID(Ids::COBBLESTONE_WALL, Meta::WALL_ANDESITE), "Andesite Wall"));

View File

@ -26,6 +26,7 @@ namespace pocketmine\block\tile;
use Ds\Deque;
use pocketmine\block\utils\BannerPattern;
use pocketmine\block\utils\DyeColor;
use pocketmine\data\bedrock\DyeColorIdMap;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
@ -59,38 +60,41 @@ class Banner extends Spawnable{
}
public function readSaveData(CompoundTag $nbt) : void{
$colorIdMap = DyeColorIdMap::getInstance();
if($nbt->hasTag(self::TAG_BASE, IntTag::class)){
$this->baseColor = DyeColor::fromMagicNumber($nbt->getInt(self::TAG_BASE), true);
$this->baseColor = $colorIdMap->fromInvertedId($nbt->getInt(self::TAG_BASE));
}
$patterns = $nbt->getListTag(self::TAG_PATTERNS);
if($patterns !== null){
/** @var CompoundTag $pattern */
foreach($patterns as $pattern){
$this->patterns[] = new BannerPattern($pattern->getString(self::TAG_PATTERN_NAME), DyeColor::fromMagicNumber($pattern->getInt(self::TAG_PATTERN_COLOR), true));
$this->patterns[] = new BannerPattern($pattern->getString(self::TAG_PATTERN_NAME), $colorIdMap->fromInvertedId($pattern->getInt(self::TAG_PATTERN_COLOR)));
}
}
}
protected function writeSaveData(CompoundTag $nbt) : void{
$nbt->setInt(self::TAG_BASE, $this->baseColor->getInvertedMagicNumber());
$colorIdMap = DyeColorIdMap::getInstance();
$nbt->setInt(self::TAG_BASE, $colorIdMap->toInvertedId($this->baseColor));
$patterns = new ListTag();
foreach($this->patterns as $pattern){
$patterns->push(CompoundTag::create()
->setString(self::TAG_PATTERN_NAME, $pattern->getId())
->setInt(self::TAG_PATTERN_COLOR, $pattern->getColor()->getInvertedMagicNumber())
->setInt(self::TAG_PATTERN_COLOR, $colorIdMap->toInvertedId($pattern->getColor()))
);
}
$nbt->setTag(self::TAG_PATTERNS, $patterns);
}
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
$nbt->setInt(self::TAG_BASE, $this->baseColor->getInvertedMagicNumber());
$colorIdMap = DyeColorIdMap::getInstance();
$nbt->setInt(self::TAG_BASE, $colorIdMap->toInvertedId($this->baseColor));
$patterns = new ListTag();
foreach($this->patterns as $pattern){
$patterns->push(CompoundTag::create()
->setString(self::TAG_PATTERN_NAME, $pattern->getId())
->setInt(self::TAG_PATTERN_COLOR, $pattern->getColor()->getInvertedMagicNumber())
->setInt(self::TAG_PATTERN_COLOR, $colorIdMap->toInvertedId($pattern->getColor()))
);
}
$nbt->setTag(self::TAG_PATTERNS, $patterns);

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block\tile;
use pocketmine\block\utils\DyeColor;
use pocketmine\data\bedrock\DyeColorIdMap;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag;
@ -49,15 +50,15 @@ class Bed extends Spawnable{
public function readSaveData(CompoundTag $nbt) : void{
if($nbt->hasTag(self::TAG_COLOR, ByteTag::class)){
$this->color = DyeColor::fromMagicNumber($nbt->getByte(self::TAG_COLOR));
$this->color = DyeColorIdMap::getInstance()->fromId($nbt->getByte(self::TAG_COLOR));
}
}
protected function writeSaveData(CompoundTag $nbt) : void{
$nbt->setByte(self::TAG_COLOR, $this->color->getMagicNumber());
$nbt->setByte(self::TAG_COLOR, DyeColorIdMap::getInstance()->toId($this->color));
}
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
$nbt->setByte(self::TAG_COLOR, $this->color->getMagicNumber());
$nbt->setByte(self::TAG_COLOR, DyeColorIdMap::getInstance()->toId($this->color));
}
}

View File

@ -50,67 +50,38 @@ use pocketmine\utils\EnumTrait;
*/
final class DyeColor{
use EnumTrait {
register as Enum_register;
__construct as Enum___construct;
}
/** @var DyeColor[] */
private static $numericIdMap = [];
protected static function setup() : void{
self::registerAll(
new DyeColor("white", "White", 0, new Color(0xf0, 0xf0, 0xf0)),
new DyeColor("orange", "Orange", 1, new Color(0xf9, 0x80, 0x1d)),
new DyeColor("magenta", "Magenta", 2, new Color(0xc7, 0x4e, 0xbd)),
new DyeColor("light_blue", "Light Blue", 3, new Color(0x3a, 0xb3, 0xda)),
new DyeColor("yellow", "Yellow", 4, new Color(0xfe, 0xd8, 0x3d)),
new DyeColor("lime", "Lime", 5, new Color(0x80, 0xc7, 0x1f)),
new DyeColor("pink", "Pink", 6, new Color(0xf3, 0x8b, 0xaa)),
new DyeColor("gray", "Gray", 7, new Color(0x47, 0x4f, 0x52)),
new DyeColor("light_gray", "Light Gray", 8, new Color(0x9d, 0x9d, 0x97)),
new DyeColor("cyan", "Cyan", 9, new Color(0x16, 0x9c, 0x9c)),
new DyeColor("purple", "Purple", 10, new Color(0x89, 0x32, 0xb8)),
new DyeColor("blue", "Blue", 11, new Color(0x3c, 0x44, 0xaa)),
new DyeColor("brown", "Brown", 12, new Color(0x83, 0x54, 0x32)),
new DyeColor("green", "Green", 13, new Color(0x5e, 0x7c, 0x16)),
new DyeColor("red", "Red", 14, new Color(0xb0, 0x2e, 0x26)),
new DyeColor("black", "Black", 15, new Color(0x1d, 0x1d, 0x21))
new DyeColor("white", "White", new Color(0xf0, 0xf0, 0xf0)),
new DyeColor("orange", "Orange", new Color(0xf9, 0x80, 0x1d)),
new DyeColor("magenta", "Magenta", new Color(0xc7, 0x4e, 0xbd)),
new DyeColor("light_blue", "Light Blue", new Color(0x3a, 0xb3, 0xda)),
new DyeColor("yellow", "Yellow", new Color(0xfe, 0xd8, 0x3d)),
new DyeColor("lime", "Lime", new Color(0x80, 0xc7, 0x1f)),
new DyeColor("pink", "Pink", new Color(0xf3, 0x8b, 0xaa)),
new DyeColor("gray", "Gray", new Color(0x47, 0x4f, 0x52)),
new DyeColor("light_gray", "Light Gray", new Color(0x9d, 0x9d, 0x97)),
new DyeColor("cyan", "Cyan", new Color(0x16, 0x9c, 0x9c)),
new DyeColor("purple", "Purple", new Color(0x89, 0x32, 0xb8)),
new DyeColor("blue", "Blue", new Color(0x3c, 0x44, 0xaa)),
new DyeColor("brown", "Brown", new Color(0x83, 0x54, 0x32)),
new DyeColor("green", "Green", new Color(0x5e, 0x7c, 0x16)),
new DyeColor("red", "Red", new Color(0xb0, 0x2e, 0x26)),
new DyeColor("black", "Black", new Color(0x1d, 0x1d, 0x21))
);
}
protected static function register(DyeColor $color) : void{
self::Enum_register($color);
self::$numericIdMap[$color->getMagicNumber()] = $color;
}
/**
* Returns a DyeColor object matching the given magic number
* @internal
*
* @param bool $inverted Invert the ID before using it (useful for actual dye magic IDs)
*
* @throws \InvalidArgumentException
*/
public static function fromMagicNumber(int $magicNumber, bool $inverted = false) : DyeColor{
self::checkInit();
$real = $inverted ? ~$magicNumber & 0xf : $magicNumber;
if(!isset(self::$numericIdMap[$real])){
throw new \InvalidArgumentException("Unknown dye colour magic number $magicNumber");
}
return self::$numericIdMap[$real];
}
/** @var string */
private $displayName;
/** @var int */
private $magicNumber;
/** @var Color */
private $rgbValue;
private function __construct(string $enumName, string $displayName, int $magicNumber, Color $rgbValue){
private function __construct(string $enumName, string $displayName, Color $rgbValue){
$this->Enum___construct($enumName);
$this->displayName = $displayName;
$this->magicNumber = $magicNumber;
$this->rgbValue = $rgbValue;
}
@ -121,12 +92,4 @@ final class DyeColor{
public function getRgbValue() : Color{
return $this->rgbValue;
}
public function getMagicNumber() : int{
return $this->magicNumber;
}
public function getInvertedMagicNumber() : int{
return ~$this->magicNumber & 0xf;
}
}

View File

@ -0,0 +1,83 @@
<?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\data\bedrock;
use pocketmine\block\utils\DyeColor;
use pocketmine\utils\SingletonTrait;
final class DyeColorIdMap{
use SingletonTrait;
/**
* @var DyeColor[]
* @phpstan-var array<int, DyeColor>
*/
private $idToEnum = [];
/**
* @var int[]
* @phpstan-var array<int, int>
*/
private $enumToId = [];
private function __construct(){
$this->register(0, DyeColor::WHITE());
$this->register(1, DyeColor::ORANGE());
$this->register(2, DyeColor::MAGENTA());
$this->register(3, DyeColor::LIGHT_BLUE());
$this->register(4, DyeColor::YELLOW());
$this->register(5, DyeColor::LIME());
$this->register(6, DyeColor::PINK());
$this->register(7, DyeColor::GRAY());
$this->register(8, DyeColor::LIGHT_GRAY());
$this->register(9, DyeColor::CYAN());
$this->register(10, DyeColor::PURPLE());
$this->register(11, DyeColor::BLUE());
$this->register(12, DyeColor::BROWN());
$this->register(13, DyeColor::GREEN());
$this->register(14, DyeColor::RED());
$this->register(15, DyeColor::BLACK());
}
private function register(int $id, DyeColor $color) : void{
$this->idToEnum[$id] = $color;
$this->enumToId[$color->id()] = $id;
}
public function toId(DyeColor $color) : int{
return $this->enumToId[$color->id()]; //TODO: is it possible for this to be missing?
}
public function toInvertedId(DyeColor $color) : int{
return ~$this->toId($color) & 0xf;
}
public function fromId(int $id) : DyeColor{
return $this->idToEnum[$id]; //TODO: this might not be present (e.g. corrupted data)
}
public function fromInvertedId(int $id) : DyeColor{
return $this->fromId(~$id & 0xf);
}
}

View File

@ -29,6 +29,7 @@ use pocketmine\block\tile\Banner as TileBanner;
use pocketmine\block\utils\BannerPattern;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\VanillaBlocks;
use pocketmine\data\bedrock\DyeColorIdMap;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\ListTag;
@ -93,11 +94,12 @@ class Banner extends Item{
$this->patterns = new Deque();
$colorIdMap = DyeColorIdMap::getInstance();
$patterns = $tag->getListTag(self::TAG_PATTERNS);
if($patterns !== null){
/** @var CompoundTag $t */
foreach($patterns as $t){
$this->patterns->push(new BannerPattern($t->getString(self::TAG_PATTERN_NAME), DyeColor::fromMagicNumber($t->getInt(self::TAG_PATTERN_COLOR), true)));
$this->patterns->push(new BannerPattern($t->getString(self::TAG_PATTERN_NAME), $colorIdMap->fromInvertedId($t->getInt(self::TAG_PATTERN_COLOR))));
}
}
}
@ -107,11 +109,12 @@ class Banner extends Item{
if(!$this->patterns->isEmpty()){
$patterns = new ListTag();
$colorIdMap = DyeColorIdMap::getInstance();
/** @var BannerPattern $pattern */
foreach($this->patterns as $pattern){
$patterns->push(CompoundTag::create()
->setString(self::TAG_PATTERN_NAME, $pattern->getId())
->setInt(self::TAG_PATTERN_COLOR, $pattern->getColor()->getInvertedMagicNumber())
->setInt(self::TAG_PATTERN_COLOR, $colorIdMap->toInvertedId($pattern->getColor()))
);
}

View File

@ -29,6 +29,7 @@ use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\SkullType;
use pocketmine\block\utils\TreeType;
use pocketmine\block\VanillaBlocks;
use pocketmine\data\bedrock\DyeColorIdMap;
use pocketmine\entity\Entity;
use pocketmine\entity\Location;
use pocketmine\entity\Squid;
@ -243,12 +244,13 @@ class ItemFactory{
DyeColor::BLUE()->id() => 18,
DyeColor::WHITE()->id() => 19
];
$colorIdMap = DyeColorIdMap::getInstance();
foreach(DyeColor::getAll() as $color){
//TODO: use colour object directly
//TODO: add interface to dye-colour objects
$this->register(new Dye(new ItemIdentifier(ItemIds::DYE, $dyeMap[$color->id()] ?? $color->getInvertedMagicNumber()), $color->getDisplayName() . " Dye", $color));
$this->register(new Bed(new ItemIdentifier(ItemIds::BED, $color->getMagicNumber()), $color->getDisplayName() . " Bed", $color));
$this->register(new Banner(new ItemIdentifier(ItemIds::BANNER, $color->getInvertedMagicNumber()), $color->getDisplayName() . " Banner", $color));
$this->register(new Dye(new ItemIdentifier(ItemIds::DYE, $dyeMap[$color->id()] ?? $colorIdMap->toInvertedId($color)), $color->getDisplayName() . " Dye", $color));
$this->register(new Bed(new ItemIdentifier(ItemIds::BED, $colorIdMap->toId($color)), $color->getDisplayName() . " Bed", $color));
$this->register(new Banner(new ItemIdentifier(ItemIds::BANNER, $colorIdMap->toInvertedId($color)), $color->getDisplayName() . " Banner", $color));
}
foreach(Potion::ALL as $type){