Added support for more NBT data, renaming inventories, fixed tags not being saved, added support for tags in /give

This commit is contained in:
Shoghi Cervantes 2015-08-07 16:27:30 +02:00
parent d1bfb304cb
commit 75b7b03857
42 changed files with 244 additions and 51 deletions

View File

@ -2481,7 +2481,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
if($slot->getId() === Item::MUSHROOM_STEW or $slot->getId() === Item::BEETROOT_SOUP){
$this->inventory->addItem(Item::get(Item::BOWL, 0, 1));
}elseif($slot->getId() === Item::RAW_FISH and $slot->getDamage() === 3){ //Pufferfish
//$this->addEffect(Effect::getEffect(Effect::HUNGER)->setAmplifier(2)->setDuration(15 * 20));
$this->addEffect(Effect::getEffect(Effect::HUNGER)->setAmplifier(2)->setDuration(15 * 20));
$this->addEffect(Effect::getEffect(Effect::NAUSEA)->setAmplifier(1)->setDuration(15 * 20));
$this->addEffect(Effect::getEffect(Effect::POISON)->setAmplifier(3)->setDuration(60 * 20));
}
@ -2888,10 +2888,11 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->dataPacket($pk->setChannel(Network::CHANNEL_TEXT));
}
public function sendPopup($message){
public function sendPopup($message, $subtitle = ""){
$pk = new TextPacket();
$pk->type = TextPacket::TYPE_POPUP;
$pk->message = $message;
$pk->source = $message;
$pk->message = $subtitle;
$this->dataPacket($pk->setChannel(Network::CHANNEL_TEXT));
}

View File

@ -77,6 +77,11 @@ class BurningFurnace extends Solid{
new Int("z", $this->z)
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
if($item->hasCustomName()){
$nbt->CustomName = new String("CustomName", $item->getCustomName());
}
Tile::createTile("Furnace", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
return true;

View File

@ -104,6 +104,11 @@ class Chest extends Transparent{
new Int("z", $this->z)
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
if($item->hasCustomName()){
$nbt->CustomName = new String("CustomName", $item->getCustomName());
}
$tile = Tile::createTile("Chest", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
if($chest instanceof TileChest and $tile instanceof TileChest){

View File

@ -47,6 +47,11 @@ class EnchantingTable extends Transparent{
new Int("y", $this->y),
new Int("z", $this->z)
]);
if($item->hasCustomName()){
$nbt->CustomName = new String("CustomName", $item->getCustomName());
}
Tile::createTile(Tile::ENCHANT_TABLE, $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
return true;

View File

@ -25,6 +25,8 @@ use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\event\TranslationContainer;
use pocketmine\item\Item;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\Compound;
use pocketmine\Player;
use pocketmine\utils\TextFormat;
@ -59,6 +61,27 @@ class GiveCommand extends VanillaCommand{
$item->setCount((int) $args[2]);
}
if(isset($args[3])){
$data = implode(" ", array_slice($args, 3));
$data = preg_replace("/([A-Za-z0-9_]+[ ]*):/", '"$1":', $data);
$tags = @json_decode($data, true);
if(!is_array($tags)){
$sender->sendMessage(new TranslationContainer("commands.give.tagError", [json_last_error_msg()]));
return true;
}
$nbt = new NBT();
$nbt->setArray($tags);
$tag = $nbt->getData();
if(!($tag instanceof Compound)){
$sender->sendMessage(new TranslationContainer("commands.give.tagError", ["Invalid tag conversion"]));
return true;
}
$item->setNamedTag($tag);
}
if($player instanceof Player){
if($item->getId() === 0){
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.give.item.notFound", [$args[1]]));

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class AngryVillagerParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 29);
parent::__construct($pos, Particle::TYPE_VILLAGER_ANGRY);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class BubbleParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 1);
parent::__construct($pos, Particle::TYPE_BUBBLE);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class CriticalParticle extends GenericParticle{
public function __construct(Vector3 $pos, $scale = 2){
parent::__construct($pos, 2, $scale);
parent::__construct($pos, Particle::TYPE_CRITICAL, $scale);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class DustParticle extends GenericParticle{
public function __construct(Vector3 $pos, $r, $g, $b, $a = 255){
parent::__construct($pos, 22, (($a & 0xff) << 24) | (($r & 0xff) << 16) | (($g & 0xff) << 8) | ($b & 0xff));
parent::__construct($pos, Particle::TYPE_DUST, (($a & 0xff) << 24) | (($r & 0xff) << 16) | (($g & 0xff) << 8) | ($b & 0xff));
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class EnchantParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 23);
parent::__construct($pos, Particle::TYPE_MOB_SPELL);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class EnchantmentTableParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 31);
parent::__construct($pos, Particle::TYPE_ENCHANTMENT_TABLE);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class EntityFlameParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 13);
parent::__construct($pos, Particle::TYPE_MOB_FLAME);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class ExplodeParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 4);
parent::__construct($pos, Particle::TYPE_EXPLODE);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class FlameParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 5);
parent::__construct($pos, Particle::TYPE_FLAME);
}
}

View File

@ -35,6 +35,11 @@ class FloatingTextParticle extends Particle{
protected $entityId;
protected $invisible = false;
/**
* @param Vector3 $pos
* @param int $text
* @param string $title
*/
public function __construct(Vector3 $pos, $text, $title = ""){
parent::__construct($pos->x, $pos->y, $pos->z);
$this->text = $text;

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class HappyVillagerParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 30);
parent::__construct($pos, Particle::TYPE_VILLAGER_HAPPY);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class HeartParticle extends GenericParticle{
public function __construct(Vector3 $pos, $scale = 0){
parent::__construct($pos, 14, $scale);
parent::__construct($pos, Particle::TYPE_HEART, $scale);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class HugeExplodeParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 12);
parent::__construct($pos, Particle::TYPE_HUGE_EXPLODE);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class InkParticle extends GenericParticle{
public function __construct(Vector3 $pos, $scale = 0){
parent::__construct($pos, 26, $scale);
parent::__construct($pos, Particle::TYPE_INK, $scale);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class InstantEnchantParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 25);
parent::__construct($pos, Particle::TYPE_MOB_SPELL_INSTANTANEOUS);
}
}

View File

@ -26,6 +26,6 @@ use pocketmine\item\Item;
class ItemBreakParticle extends GenericParticle{
public function __construct(Vector3 $pos, Item $item){
parent::__construct($pos, 9, ($item->getId() << 16) | $item->getDamage());
parent::__construct($pos, Particle::TYPE_ITEM_BREAK, ($item->getId() << 16) | $item->getDamage());
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class LargeExplodeParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 11);
parent::__construct($pos, Particle::TYPE_LARGE_EXPLODE);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class LavaDripParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 21);
parent::__construct($pos, Particle::TYPE_DRIP_LAVA);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class LavaParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 6);
parent::__construct($pos, Particle::TYPE_LAVA);
}
}

View File

@ -26,6 +26,39 @@ use pocketmine\network\protocol\DataPacket;
abstract class Particle extends Vector3{
const TYPE_BUBBLE = 1;
const TYPE_CRITICAL = 2;
const TYPE_SMOKE = 3;
const TYPE_EXPLODE = 4;
const TYPE_WHITE_SMOKE = 5;
const TYPE_FLAME = 6;
const TYPE_LAVA = 7;
const TYPE_LARGE_SMOKE = 8;
const TYPE_REDSTONE = 9;
const TYPE_ITEM_BREAK = 10;
const TYPE_SNOWBALL_POOF = 11;
const TYPE_LARGE_EXPLODE = 12;
const TYPE_HUGE_EXPLODE = 13;
const TYPE_MOB_FLAME = 14;
const TYPE_HEART = 15;
const TYPE_TERRAIN = 16;
const TYPE_TOWN_AURA = 17;
const TYPE_PORTAL = 18;
const TYPE_WATER_SPLASH = 19;
const TYPE_WATER_WAKE = 20;
const TYPE_DRIP_WATER = 21;
const TYPE_DRIP_LAVA = 22;
const TYPE_DUST = 23;
const TYPE_MOB_SPELL = 24;
const TYPE_MOB_SPELL_AMBIENT = 25;
const TYPE_MOB_SPELL_INSTANTANEOUS = 26;
const TYPE_INK = 27;
const TYPE_SLIME = 28;
const TYPE_RAIN_SPLASH = 29;
const TYPE_VILLAGER_ANGRY = 30;
const TYPE_VILLAGER_HAPPY = 31;
const TYPE_ENCHANTMENT_TABLE = 32;
/**
* @return DataPacket|DataPacket[]
*/

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class PortalParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 17);
parent::__construct($pos, Particle::TYPE_PORTAL);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class RainSplashParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 28);
parent::__construct($pos, Particle::TYPE_RAIN_SPLASH);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class RedstoneParticle extends GenericParticle{
public function __construct(Vector3 $pos, $lifetime = 1){
parent::__construct($pos, 8, $lifetime);
parent::__construct($pos, Particle::TYPE_REDSTONE, $lifetime);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class SmokeParticle extends GenericParticle{
public function __construct(Vector3 $pos, $scale = 0){
parent::__construct($pos, 3, (int) $scale);
parent::__construct($pos, Particle::TYPE_SMOKE, (int) $scale);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class SplashParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 18);
parent::__construct($pos, Particle::TYPE_WATER_SPLASH);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class SporeParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 16);
parent::__construct($pos, Particle::TYPE_TOWN_AURA);
}
}

View File

@ -26,6 +26,6 @@ use pocketmine\math\Vector3;
class TerrainParticle extends GenericParticle{
public function __construct(Vector3 $pos, Block $b){
parent::__construct($pos, 15, ($b->getDamage() << 8) | $b->getId());
parent::__construct($pos, Particle::TYPE_TERRAIN, ($b->getDamage() << 8) | $b->getId());
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class WaterDripParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 20);
parent::__construct($pos, Particle::TYPE_DRIP_WATER);
}
}

View File

@ -25,6 +25,6 @@ use pocketmine\math\Vector3;
class WaterParticle extends GenericParticle{
public function __construct(Vector3 $pos){
parent::__construct($pos, 19);
parent::__construct($pos, Particle::TYPE_WATER_WAKE);
}
}

View File

@ -100,17 +100,18 @@ class NBT{
}
/**
* @param Compound $item
* @param Compound $tag
* @return Item
*/
public static function getItemHelper(Compound $item){
if(!isset($item->id) or !isset($item->Damage) or !isset($item->Count)){
public static function getItemHelper(Compound $tag){
if(!isset($tag->id) or !isset($tag->Damage) or !isset($tag->Count)){
return Item::get(0);
}
$item = Item::get($item->id->getValue(), $item->Damage->getValue(), $item->Count->getValue());
if(isset($item->tag)){
$item->setNamedTag($item->tag);
$item = Item::get($tag->id->getValue(), $tag->Damage->getValue(), $tag->Count->getValue());
if(isset($tag->tag) and $tag->tag instanceof Compound){
$item->setNamedTag($tag->tag);
}
return $item;
@ -162,6 +163,8 @@ class NBT{
*/
public function write(){
$this->offset = 0;
$this->buffer = "";
if($this->data instanceof Compound){
$this->writeTag($this->data);
@ -306,22 +309,22 @@ class NBT{
public function getArray(){
$data = [];
$this->toArray($data, $this->data);
self::toArray($data, $this->data);
}
private function toArray(array &$data, Tag $tag){
private static function toArray(array &$data, Tag $tag){
/** @var Compound[]|Enum[]|IntArray[] $tag */
foreach($tag as $key => $value){
if($value instanceof Compound or $value instanceof Enum or $value instanceof IntArray){
$data[$key] = [];
$this->toArray($data[$key], $value);
self::toArray($data[$key], $value);
}else{
$data[$key] = $value->getValue();
}
}
}
private function fromArray(Tag $tag, array $data, $byteArray = false){
private static function fromArray(Tag $tag, array $data, $byteArray = false){
foreach($data as $key => $value){
if(is_array($value)){
$isNumeric = true;
@ -335,7 +338,7 @@ class NBT{
}
}
$tag{$key} = $isNumeric ? ($isIntArray ? new IntArray($key, []) : new Enum($key, [])) : new Compound($key, []);
$this->fromArray($tag->{$key}, $value);
self::fromArray($tag->{$key}, $value);
}elseif(is_int($value)){
$tag{$key} = new Int($key, $value);
}elseif(is_float($value)){
@ -354,7 +357,7 @@ class NBT{
public function setArray(array $data, $byteArray = false){
$this->data = new Compound("", []);
$this->fromArray($this->data, $data, $byteArray);
self::fromArray($this->data, $data, $byteArray);
}
/**

View File

@ -100,9 +100,15 @@ class CraftingDataPacket extends DataPacket{
}
}
private static function writeEnchant(){
private static function writeEnchant($slot, $enchantmentId, $enchantmentLevel, $cost, $name, BinaryStream $stream){
//TODO
$stream->putInt($slot);
$stream->putInt($enchantmentId);
$stream->putInt($enchantmentLevel);
$stream->putInt($cost);
$stream->putString($name);
return CraftingDataPacket::ENTRY_ENCHANT;
}

View File

@ -30,7 +30,7 @@ interface Info{
/**
* Actual Minecraft: PE protocol version
*/
const CURRENT_PROTOCOL = 32;
const CURRENT_PROTOCOL = 33;
const LOGIN_PACKET = 0x87;
const PLAY_STATUS_PACKET = 0x88;

View File

@ -41,10 +41,10 @@ class TextPacket extends DataPacket{
public function decode(){
$this->type = $this->getByte();
switch($this->type){
case self::TYPE_POPUP:
case self::TYPE_CHAT:
$this->source = $this->getString();
case self::TYPE_RAW:
case self::TYPE_POPUP:
case self::TYPE_TIP:
$this->message = $this->getString();
break;

View File

@ -35,7 +35,7 @@ use pocketmine\nbt\tag\Int;
use pocketmine\nbt\tag\Short;
use pocketmine\nbt\tag\String;
class Chest extends Spawnable implements InventoryHolder, Container{
class Chest extends Spawnable implements InventoryHolder, Container, Nameable{
/** @var ChestInventory */
protected $inventory;
@ -182,6 +182,23 @@ class Chest extends Spawnable implements InventoryHolder, Container{
}
}
public function getName(){
return isset($this->namedtag->CustomName) ? $this->namedtag->CustomName->getValue() : "Chest";
}
public function hasName(){
return isset($this->namedtag->CustomName);
}
public function setName($str){
if($str === ""){
unset($this->namedtag->CustomName);
return;
}
$this->namedtag->CustomName = new String("CustomName", $str);
}
public function isPaired(){
if(!isset($this->namedtag->pairx) or !isset($this->namedtag->pairz)){
return false;
@ -248,7 +265,7 @@ class Chest extends Spawnable implements InventoryHolder, Container{
public function getSpawnCompound(){
if($this->isPaired()){
return new Compound("", [
$c = new Compound("", [
new String("id", Tile::CHEST),
new Int("x", (int) $this->x),
new Int("y", (int) $this->y),
@ -257,12 +274,18 @@ class Chest extends Spawnable implements InventoryHolder, Container{
new Int("pairz", (int) $this->namedtag["pairz"])
]);
}else{
return new Compound("", [
$c = new Compound("", [
new String("id", Tile::CHEST),
new Int("x", (int) $this->x),
new Int("y", (int) $this->y),
new Int("z", (int) $this->z)
]);
}
if($this->hasName()){
$c->CustomName = $this->namedtag->CustomName;
}
return $c;
}
}

View File

@ -25,14 +25,38 @@ use pocketmine\nbt\tag\Compound;
use pocketmine\nbt\tag\Int;
use pocketmine\nbt\tag\String;
class EnchantTable extends Spawnable{
class EnchantTable extends Spawnable implements Nameable{
public function getName(){
return isset($this->namedtag->CustomName) ? $this->namedtag->CustomName->getValue() : "Chest";
}
public function hasName(){
return isset($this->namedtag->CustomName);
}
public function setName($str){
if($str === ""){
unset($this->namedtag->CustomName);
return;
}
$this->namedtag->CustomName = new String("CustomName", $str);
}
public function getSpawnCompound(){
return new Compound("", [
$c = new Compound("", [
new String("id", Tile::ENCHANT_TABLE),
new Int("x", (int) $this->x),
new Int("y", (int) $this->y),
new Int("z", (int) $this->z)
]);
if($this->hasName()){
$c->CustomName = $this->namedtag->CustomName;
}
return $c;
}
}

View File

@ -34,10 +34,11 @@ use pocketmine\nbt\tag\Byte;
use pocketmine\nbt\tag\Compound;
use pocketmine\nbt\tag\Enum;
use pocketmine\nbt\tag\Short;
use pocketmine\nbt\tag\String;
use pocketmine\network\Network;
use pocketmine\network\protocol\ContainerSetDataPacket;
class Furnace extends Tile implements InventoryHolder, Container{
class Furnace extends Tile implements InventoryHolder, Container, Nameable{
/** @var FurnaceInventory */
protected $inventory;
@ -69,6 +70,23 @@ class Furnace extends Tile implements InventoryHolder, Container{
}
}
public function getName(){
return isset($this->namedtag->CustomName) ? $this->namedtag->CustomName->getValue() : "Chest";
}
public function hasName(){
return isset($this->namedtag->CustomName);
}
public function setName($str){
if($str === ""){
unset($this->namedtag->CustomName);
return;
}
$this->namedtag->CustomName = new String("CustomName", $str);
}
public function close(){
if($this->closed === false){
foreach($this->getInventory()->getViewers() as $player){

View File

@ -0,0 +1,42 @@
<?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/
*
*
*/
namespace pocketmine\tile;
interface Nameable{
/**
* @return string
*/
public function getName();
/**
* @param void $str
*/
public function setName($str);
/**
* @return bool
*/
public function hasName();
}