mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-11 08:19:45 +00:00
Flatten Item variants, remove Item->setDamage()
This commit is contained in:
parent
14ef4558c2
commit
5fb7825485
@ -329,6 +329,15 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
self::$saveNames[$className] = $saveNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all registered entity classpaths.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getKnownEntityTypes() : array{
|
||||
return array_unique(self::$knownEntities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function which creates minimal NBT needed to spawn an entity.
|
||||
*
|
||||
|
@ -34,16 +34,20 @@ use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Bucket extends Item implements Consumable{
|
||||
public function __construct(int $meta = 0){
|
||||
parent::__construct(self::BUCKET, $meta, "Bucket");
|
||||
/** @var int|null */
|
||||
protected $blockId;
|
||||
|
||||
public function __construct(int $id, int $meta, string $name, ?int $blockId){
|
||||
parent::__construct($id, $meta, $name);
|
||||
$this->blockId = $blockId;
|
||||
}
|
||||
|
||||
public function getMaxStackSize() : int{
|
||||
return $this->meta === Block::AIR ? 16 : 1; //empty buckets stack to 16
|
||||
return $this->blockId === Block::AIR ? 16 : 1; //empty buckets stack to 16
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
if($this->meta === Block::LAVA or $this->meta === Block::FLOWING_LAVA){
|
||||
if($this->blockId === Block::LAVA or $this->blockId === Block::FLOWING_LAVA){
|
||||
return 20000;
|
||||
}
|
||||
|
||||
@ -51,7 +55,10 @@ class Bucket extends Item implements Consumable{
|
||||
}
|
||||
|
||||
public function onActivate(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector) : bool{
|
||||
$resultBlock = BlockFactory::get($this->meta);
|
||||
if($this->blockId === null){
|
||||
return false;
|
||||
}
|
||||
$resultBlock = BlockFactory::get($this->blockId);
|
||||
|
||||
if($resultBlock instanceof Air){
|
||||
if($blockClicked instanceof Liquid and $blockClicked->isSource()){
|
||||
@ -108,7 +115,7 @@ class Bucket extends Item implements Consumable{
|
||||
}
|
||||
|
||||
public function canBeConsumed() : bool{
|
||||
return $this->meta === 1; //Milk
|
||||
return $this->blockId === null; //Milk
|
||||
}
|
||||
|
||||
public function onConsume(Living $consumer){
|
||||
|
@ -25,12 +25,6 @@ namespace pocketmine\item;
|
||||
|
||||
|
||||
class Coal extends Item{
|
||||
public function __construct(int $meta = 0){
|
||||
parent::__construct(self::COAL, $meta, "Coal");
|
||||
if($this->meta === 1){
|
||||
$this->name = "Charcoal";
|
||||
}
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
return 1600;
|
||||
|
@ -28,6 +28,9 @@ use pocketmine\nbt\tag\ByteTag;
|
||||
|
||||
abstract class Durable extends Item{
|
||||
|
||||
/** @var int */
|
||||
protected $damage = 0;
|
||||
|
||||
/**
|
||||
* Returns whether this item will take damage when used.
|
||||
* @return bool
|
||||
@ -57,7 +60,7 @@ abstract class Durable extends Item{
|
||||
|
||||
$amount -= $this->getUnbreakingDamageReduction($amount);
|
||||
|
||||
$this->meta = min($this->meta + $amount, $this->getMaxDurability());
|
||||
$this->damage = min($this->damage + $amount, $this->getMaxDurability());
|
||||
if($this->isBroken()){
|
||||
$this->onBroken();
|
||||
}
|
||||
@ -65,6 +68,18 @@ abstract class Durable extends Item{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDamage() : int{
|
||||
return $this->damage;
|
||||
}
|
||||
|
||||
public function setDamage(int $meta) : Item{
|
||||
if($meta < 0 or $meta > $this->getMaxDurability()){
|
||||
throw new \InvalidArgumentException("Damage must be in range 0 - " , $this->getMaxDurability());
|
||||
}
|
||||
$this->damage = $meta;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getUnbreakingDamageReduction(int $amount) : int{
|
||||
if(($unbreakingLevel = $this->getEnchantmentLevel(Enchantment::UNBREAKING)) > 0){
|
||||
$negated = 0;
|
||||
@ -101,6 +116,6 @@ abstract class Durable extends Item{
|
||||
* @return bool
|
||||
*/
|
||||
public function isBroken() : bool{
|
||||
return $this->meta >= $this->getMaxDurability();
|
||||
return $this->damage >= $this->getMaxDurability();
|
||||
}
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
throw new \InvalidArgumentException("ID must be in range " . -0x8000 . " - " . 0x7fff);
|
||||
}
|
||||
$this->id = $id;
|
||||
$this->setDamage($meta);
|
||||
$this->meta = $meta !== -1 ? $meta & 0x7FFF : -1;
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
@ -663,20 +663,10 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
final public function getDamage() : int{
|
||||
public function getDamage() : int{
|
||||
return $this->meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $meta
|
||||
* @return Item
|
||||
*/
|
||||
public function setDamage(int $meta) : Item{
|
||||
$this->meta = $meta !== -1 ? $meta & 0x7FFF : -1;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this item can match any item with an equivalent ID with any meta value.
|
||||
* Used in crafting recipes which accept multiple variants of the same item, for example crafting tables recipes.
|
||||
@ -856,7 +846,7 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
* @return string
|
||||
*/
|
||||
final public function __toString() : string{
|
||||
return "Item " . $this->name . " (" . $this->id . ":" . ($this->hasAnyDamageValue() ? "?" : $this->meta) . ")x" . $this->count . ($this->hasCompoundTag() ? " tags:0x" . bin2hex($this->getCompoundTag()) : "");
|
||||
return "Item " . $this->name . " (" . $this->id . ":" . ($this->hasAnyDamageValue() ? "?" : $this->getDamage()) . ")x" . $this->count . ($this->hasCompoundTag() ? " tags:0x" . bin2hex($this->getCompoundTag()) : "");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -921,7 +911,7 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
$result = new CompoundTag($tagName, [
|
||||
new ShortTag("id", $this->id),
|
||||
new ByteTag("Count", Binary::signByte($this->count)),
|
||||
new ShortTag("Damage", $this->meta)
|
||||
new ShortTag("Damage", $this->getDamage())
|
||||
]);
|
||||
|
||||
if($this->hasCompoundTag()){
|
||||
@ -957,12 +947,11 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
$item = ItemFactory::get($idTag->getValue(), $meta, $count);
|
||||
}elseif($idTag instanceof StringTag){ //PC item save format
|
||||
try{
|
||||
$item = ItemFactory::fromString($idTag->getValue());
|
||||
$item = ItemFactory::fromString($idTag->getValue() . ":$meta");
|
||||
}catch(\InvalidArgumentException $e){
|
||||
//TODO: improve error handling
|
||||
return ItemFactory::get(Item::AIR, 0, 0);
|
||||
}
|
||||
$item->setDamage($meta);
|
||||
$item->setCount($count);
|
||||
}else{
|
||||
throw new \InvalidArgumentException("Item CompoundTag ID must be an instance of StringTag or ShortTag, " . get_class($idTag) . " given");
|
||||
|
@ -46,7 +46,7 @@ class ItemBlock extends Item{
|
||||
$blockId = 255 - $blockId;
|
||||
}
|
||||
$this->blockId = $blockId;
|
||||
$this->setDamage($meta);
|
||||
$this->meta = $meta;
|
||||
|
||||
parent::__construct($itemId ?? $blockId, $meta, $this->getBlock()->getName());
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ namespace pocketmine\item;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\BlockFactory;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\Living;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
|
||||
/**
|
||||
@ -45,7 +47,8 @@ class ItemFactory{
|
||||
self::registerItem(new Apple());
|
||||
self::registerItem(new Bow());
|
||||
self::registerItem(new Arrow());
|
||||
self::registerItem(new Coal());
|
||||
self::registerItem(new Coal(Item::COAL, 0, "Coal"));
|
||||
self::registerItem(new Coal(Item::COAL, 1, "Charcoal"));
|
||||
self::registerItem(new Item(Item::DIAMOND, 0, "Diamond"));
|
||||
self::registerItem(new Item(Item::IRON_INGOT, 0, "Iron Ingot"));
|
||||
self::registerItem(new Item(Item::GOLD_INGOT, 0, "Gold Ingot"));
|
||||
@ -107,13 +110,19 @@ class ItemFactory{
|
||||
self::registerItem(new GoldenApple());
|
||||
self::registerItem(new Sign());
|
||||
self::registerItem(new ItemBlock(Block::OAK_DOOR_BLOCK, 0, Item::OAK_DOOR));
|
||||
self::registerItem(new Bucket());
|
||||
self::registerItem(new Bucket(Item::BUCKET, 0, "Bucket", Block::AIR));
|
||||
self::registerItem(new Bucket(Item::BUCKET, 1, "Milk Bucket", null)); //TODO: this ought to get its own class, it has completely different behaviour
|
||||
//TODO: fix metadata for buckets with still liquid in them
|
||||
//the meta values are intentionally hardcoded because block IDs will change in the future
|
||||
self::registerItem(new Bucket(Item::BUCKET, 8, "Water Bucket", Block::FLOWING_WATER));
|
||||
self::registerItem(new Bucket(Item::BUCKET, 10, "Lava Bucket", Block::FLOWING_LAVA));
|
||||
|
||||
self::registerItem(new Minecart());
|
||||
//TODO: SADDLE
|
||||
self::registerItem(new ItemBlock(Block::IRON_DOOR_BLOCK, 0, Item::IRON_DOOR));
|
||||
self::registerItem(new Redstone());
|
||||
self::registerItem(new Snowball());
|
||||
|
||||
self::registerItem(new Boat());
|
||||
self::registerItem(new Item(Item::LEATHER, 0, "Leather"));
|
||||
//TODO: KELP
|
||||
@ -132,7 +141,10 @@ class ItemFactory{
|
||||
self::registerItem(new Item(Item::GLOWSTONE_DUST, 0, "Glowstone Dust"));
|
||||
self::registerItem(new RawFish());
|
||||
self::registerItem(new CookedFish());
|
||||
self::registerItem(new Dye());
|
||||
for($i = 0; $i < 16; ++$i){
|
||||
//TODO: add colour constants (this is messy)
|
||||
self::registerItem(new Dye($i));
|
||||
}
|
||||
self::registerItem(new Item(Item::BONE, 0, "Bone"));
|
||||
self::registerItem(new Item(Item::SUGAR, 0, "Sugar"));
|
||||
self::registerItem(new ItemBlock(Block::CAKE_BLOCK, 0, Item::CAKE));
|
||||
@ -154,7 +166,12 @@ class ItemFactory{
|
||||
self::registerItem(new Item(Item::GHAST_TEAR, 0, "Ghast Tear"));
|
||||
self::registerItem(new Item(Item::GOLD_NUGGET, 0, "Gold Nugget"));
|
||||
self::registerItem(new ItemBlock(Block::NETHER_WART_PLANT, 0, Item::NETHER_WART));
|
||||
self::registerItem(new Potion());
|
||||
|
||||
foreach(Potion::ALL as $type){
|
||||
self::registerItem(new Potion($type));
|
||||
self::registerItem(new SplashPotion($type));
|
||||
//TODO: LINGERING_POTION
|
||||
}
|
||||
self::registerItem(new GlassBottle());
|
||||
self::registerItem(new SpiderEye());
|
||||
self::registerItem(new Item(Item::FERMENTED_SPIDER_EYE, 0, "Fermented Spider Eye"));
|
||||
@ -164,7 +181,14 @@ class ItemFactory{
|
||||
self::registerItem(new ItemBlock(Block::CAULDRON_BLOCK, 0, Item::CAULDRON));
|
||||
//TODO: ENDER_EYE
|
||||
self::registerItem(new Item(Item::GLISTERING_MELON, 0, "Glistering Melon"));
|
||||
self::registerItem(new SpawnEgg());
|
||||
|
||||
foreach(Entity::getKnownEntityTypes() as $className){
|
||||
/** @var Living $className */
|
||||
if(is_a($className, Living::class, true) and $className::NETWORK_ID !== -1){
|
||||
self::registerItem(new SpawnEgg(Item::SPAWN_EGG, $className::NETWORK_ID, "Spawn Egg"));
|
||||
}
|
||||
}
|
||||
|
||||
self::registerItem(new ExperienceBottle());
|
||||
//TODO: FIREBALL
|
||||
self::registerItem(new WritableBook());
|
||||
@ -217,9 +241,7 @@ class ItemFactory{
|
||||
self::registerItem(new Item(Item::CHORUS_FRUIT_POPPED, 0, "Popped Chorus Fruit"));
|
||||
|
||||
self::registerItem(new Item(Item::DRAGON_BREATH, 0, "Dragon's Breath"));
|
||||
self::registerItem(new SplashPotion());
|
||||
|
||||
//TODO: LINGERING_POTION
|
||||
//TODO: SPARKLER
|
||||
//TODO: COMMAND_BLOCK_MINECART
|
||||
//TODO: ELYTRA
|
||||
@ -279,11 +301,19 @@ class ItemFactory{
|
||||
*/
|
||||
public static function registerItem(Item $item, bool $override = false){
|
||||
$id = $item->getId();
|
||||
if(!$override and self::isRegistered($id)){
|
||||
$variant = $item->getDamage();
|
||||
|
||||
if(!$override and self::isRegistered($id, $variant)){
|
||||
throw new \RuntimeException("Trying to overwrite an already registered item");
|
||||
}
|
||||
|
||||
self::$list[self::getListOffset($id)] = clone $item;
|
||||
$offset = self::getListOffset($id);
|
||||
$sublist = self::$list[$offset] ?? new \SplFixedArray();
|
||||
if($sublist->getSize() < $variant + 1){
|
||||
$sublist->setSize($variant + 1);
|
||||
}
|
||||
$sublist[$variant] = clone $item;
|
||||
self::$list[$offset] = $sublist;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -303,24 +333,28 @@ class ItemFactory{
|
||||
}
|
||||
|
||||
try{
|
||||
$sublist = self::$list[self::getListOffset($id)];
|
||||
|
||||
/** @var Item|null $listed */
|
||||
$listed = self::$list[self::getListOffset($id)];
|
||||
if($listed !== null){
|
||||
$item = clone $listed;
|
||||
if($sublist !== null and isset($sublist[$meta])){
|
||||
$item = clone $sublist[$meta];
|
||||
}elseif($id < 256){ //intentionally includes negatives, for extended block IDs
|
||||
/* Blocks must have a damage value 0-15, but items can have damage value -1 to indicate that they are
|
||||
* crafting ingredients with any-damage. */
|
||||
$item = new ItemBlock($id, $meta);
|
||||
}else{
|
||||
//negative damage values will fallthru to here, to avoid crazy shit with crafting wildcard hacks
|
||||
$item = new Item($id, $meta);
|
||||
}
|
||||
}catch(\RuntimeException $e){
|
||||
throw new \InvalidArgumentException("Item ID $id is invalid or out of bounds");
|
||||
}
|
||||
|
||||
$item->setDamage($meta);
|
||||
$item->setCount($count);
|
||||
$item->setCompoundTag($tags);
|
||||
if($item instanceof Durable){ //nasty, but necessary for BC reasons
|
||||
$item->setDamage($meta);
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
@ -376,13 +410,17 @@ class ItemFactory{
|
||||
* Returns whether the specified item ID is already registered in the item factory.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $variant
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isRegistered(int $id) : bool{
|
||||
public static function isRegistered(int $id, int $variant = 0) : bool{
|
||||
if($id < 256){
|
||||
return BlockFactory::isRegistered($id);
|
||||
}
|
||||
return self::$list[self::getListOffset($id)] !== null;
|
||||
|
||||
$sublist = self::$list[self::getListOffset($id)];
|
||||
return $sublist !== null and isset($sublist[$variant]);
|
||||
}
|
||||
|
||||
private static function getListOffset(int $id) : int{
|
||||
|
@ -67,6 +67,46 @@ class Potion extends Item implements Consumable{
|
||||
public const LONG_WEAKNESS = 35;
|
||||
public const WITHER = 36;
|
||||
|
||||
public const ALL = [
|
||||
self::WATER,
|
||||
self::MUNDANE,
|
||||
self::LONG_MUNDANE,
|
||||
self::THICK,
|
||||
self::AWKWARD,
|
||||
self::NIGHT_VISION,
|
||||
self::LONG_NIGHT_VISION,
|
||||
self::INVISIBILITY,
|
||||
self::LONG_INVISIBILITY,
|
||||
self::LEAPING,
|
||||
self::LONG_LEAPING,
|
||||
self::STRONG_LEAPING,
|
||||
self::FIRE_RESISTANCE,
|
||||
self::LONG_FIRE_RESISTANCE,
|
||||
self::SWIFTNESS,
|
||||
self::LONG_SWIFTNESS,
|
||||
self::STRONG_SWIFTNESS,
|
||||
self::SLOWNESS,
|
||||
self::LONG_SLOWNESS,
|
||||
self::WATER_BREATHING,
|
||||
self::LONG_WATER_BREATHING,
|
||||
self::HEALING,
|
||||
self::STRONG_HEALING,
|
||||
self::HARMING,
|
||||
self::STRONG_HARMING,
|
||||
self::POISON,
|
||||
self::LONG_POISON,
|
||||
self::STRONG_POISON,
|
||||
self::REGENERATION,
|
||||
self::LONG_REGENERATION,
|
||||
self::STRONG_REGENERATION,
|
||||
self::STRENGTH,
|
||||
self::LONG_STRENGTH,
|
||||
self::STRONG_STRENGTH,
|
||||
self::WEAKNESS,
|
||||
self::LONG_WEAKNESS,
|
||||
self::WITHER
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns a list of effects applied by potions with the specified ID.
|
||||
*
|
||||
|
@ -29,9 +29,6 @@ use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class SpawnEgg extends Item{
|
||||
public function __construct(int $meta = 0){
|
||||
parent::__construct(self::SPAWN_EGG, $meta, "Spawn Egg");
|
||||
}
|
||||
|
||||
public function onActivate(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector) : bool{
|
||||
$nbt = Entity::createBaseNBT($blockReplace->add(0.5, 0, 0.5), null, lcg_value() * 360, 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user