mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-13 09:19:42 +00:00
New implementation of sending/setting/getting entity data, added effect saving
This commit is contained in:
parent
85c5714cbf
commit
2ae80031f0
@ -193,7 +193,6 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
protected $chunksPerTick;
|
||||
/** @var null|Position */
|
||||
private $spawnPosition = null;
|
||||
private $inAction = false;
|
||||
|
||||
protected $inAirTicks = 0;
|
||||
protected $lastSpeedTick = 0;
|
||||
@ -251,10 +250,6 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
return $this->namedtag instanceof Compound;
|
||||
}
|
||||
|
||||
protected function initEntity(){
|
||||
parent::initEntity();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
*/
|
||||
@ -669,6 +664,8 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->teleport($ev->getRespawnPosition());
|
||||
|
||||
$this->sendSettings();
|
||||
$this->sendData($this);
|
||||
$this->sendPotionEffects($this);
|
||||
$this->inventory->sendContents($this);
|
||||
$this->inventory->sendArmorContents($this);
|
||||
|
||||
@ -829,8 +826,8 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->sleeping = clone $pos;
|
||||
$this->teleport(new Position($pos->x + 0.5, $pos->y + 1, $pos->z + 0.5, $this->level));
|
||||
|
||||
$this->sendMetadata($this->getViewers());
|
||||
$this->sendMetadata($this);
|
||||
$this->setDataProperty(self::DATA_PLAYER_BED_POSITION, self::DATA_TYPE_POS, [$pos->x, $pos->y, $pos->z]);
|
||||
$this->setDataFlag(self::DATA_PLAYER_FLAGS, self::DATA_PLAYER_FLAG_SLEEP, true);
|
||||
|
||||
$this->setSpawn($pos);
|
||||
$this->tasks[] = $this->server->getScheduler()->scheduleDelayedTask(new CallbackTask([$this, "checkSleep"]), 60);
|
||||
@ -863,9 +860,8 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->server->getPluginManager()->callEvent($ev = new PlayerBedLeaveEvent($this, $this->level->getBlock($this->sleeping)));
|
||||
|
||||
$this->sleeping = null;
|
||||
|
||||
$this->sendMetadata($this->getViewers());
|
||||
$this->sendMetadata($this);
|
||||
$this->setDataFlag(self::DATA_PLAYER_FLAGS, self::DATA_PLAYER_FLAG_SLEEP, false);
|
||||
$this->setDataProperty(self::DATA_PLAYER_BED_POSITION, self::DATA_TYPE_POS, [0, 0, 0]);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1680,10 +1676,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
$this->inventory->sendHeldItem($this->hasSpawned);
|
||||
|
||||
if($this->inAction === true){
|
||||
$this->inAction = false;
|
||||
$this->sendMetadata($this->getViewers());
|
||||
}
|
||||
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
|
||||
break;
|
||||
case ProtocolInfo::USE_ITEM_PACKET:
|
||||
if($this->spawned === false or $this->dead === true or $this->blocked){
|
||||
@ -1697,10 +1690,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$packet->eid = $this->id;
|
||||
|
||||
if($packet->face >= 0 and $packet->face <= 5){ //Use Block, place
|
||||
if($this->inAction === true){
|
||||
$this->inAction = false;
|
||||
$this->sendMetadata($this->getViewers());
|
||||
}
|
||||
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
|
||||
|
||||
if($blockVector->distance($this) > 10){
|
||||
|
||||
@ -1797,9 +1787,8 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$snowball->spawnToAll();
|
||||
}
|
||||
}
|
||||
$this->inAction = true;
|
||||
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, true);
|
||||
$this->startAction = microtime(true);
|
||||
$this->sendMetadata($this->getViewers());
|
||||
}
|
||||
break;
|
||||
case ProtocolInfo::PLAYER_ACTION_PACKET:
|
||||
@ -1875,8 +1864,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
|
||||
$this->startAction = false;
|
||||
$this->inAction = false;
|
||||
$this->sendMetadata($this->getViewers());
|
||||
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
|
||||
break;
|
||||
case 6: //get out of the bed
|
||||
$this->stopSleep();
|
||||
@ -2080,15 +2068,14 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->teleport($ev->getRespawnPosition());
|
||||
|
||||
$this->fireTicks = 0;
|
||||
$this->airTicks = 300;
|
||||
$this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, 300);
|
||||
$this->deadTicks = 0;
|
||||
$this->noDamageTicks = 60;
|
||||
|
||||
$this->setHealth(20);
|
||||
$this->dead = false;
|
||||
|
||||
$this->sendMetadata($this->getViewers());
|
||||
$this->sendMetadata($this);
|
||||
$this->sendData($this);
|
||||
|
||||
$this->sendSettings();
|
||||
$this->inventory->sendContents($this);
|
||||
@ -2107,10 +2094,8 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
$this->craftingType = 0;
|
||||
|
||||
if($this->inAction === true){
|
||||
$this->inAction = false;
|
||||
$this->sendMetadata($this->getViewers());
|
||||
}
|
||||
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false); //TODO: check if this should be true
|
||||
|
||||
switch($packet->event){
|
||||
case 9: //Eating
|
||||
$items = [
|
||||
@ -2182,10 +2167,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
$this->level->dropItem($this->add(0, 1.3, 0), $item, $motion, 40);
|
||||
|
||||
if($this->inAction === true){
|
||||
$this->inAction = false;
|
||||
$this->sendMetadata($this->getViewers());
|
||||
}
|
||||
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
|
||||
break;
|
||||
case ProtocolInfo::MESSAGE_PACKET:
|
||||
if($this->spawned === false or $this->dead === true){
|
||||
@ -2701,30 +2683,6 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
}
|
||||
|
||||
public function getData(){ //TODO
|
||||
$flags = 0;
|
||||
$flags |= $this->fireTicks > 0 ? 1 : 0;
|
||||
$flags |= $this->hasEffect(Effect::INVISIBILITY) ? 1 << 5 : 0;
|
||||
//$flags |= ($this->crouched === true ? 0b10:0) << 1;
|
||||
$flags |= ($this->inAction === true ? 0b10000 : 0);
|
||||
$d = [
|
||||
0 => ["type" => 0, "value" => $flags],
|
||||
1 => ["type" => 1, "value" => $this->airTicks],
|
||||
3 => ["type" => 0, "value" => $this->hasEffect(Effect::INVISIBILITY) ? 0 : 1],
|
||||
16 => ["type" => 0, "value" => 0],
|
||||
17 => ["type" => 6, "value" => [0, 0, 0]],
|
||||
];
|
||||
|
||||
|
||||
if($this->sleeping instanceof Vector3){
|
||||
$d[16]["value"] = 2;
|
||||
$d[17]["value"] = [$this->sleeping->x, $this->sleeping->y, $this->sleeping->z];
|
||||
}
|
||||
|
||||
|
||||
return $d;
|
||||
}
|
||||
|
||||
public function teleport(Vector3 $pos, $yaw = null, $pitch = null){
|
||||
if(parent::teleport($pos, $yaw, $pitch)){
|
||||
|
||||
@ -2735,7 +2693,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->removeWindow($window);
|
||||
}
|
||||
|
||||
$this->airTicks = 300;
|
||||
$this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, 300);
|
||||
$this->resetFallDistance();
|
||||
$this->orderChunks();
|
||||
$this->nextChunkOrderRun = 0;
|
||||
|
@ -23,6 +23,9 @@ namespace pocketmine\entity;
|
||||
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\event\entity\EntityRegainHealthEvent;
|
||||
use pocketmine\network\protocol\MobEffectPacket;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\Server;
|
||||
|
||||
class Effect{
|
||||
const SPEED = 1;
|
||||
@ -136,12 +139,20 @@ class Effect{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getAmplifier(){
|
||||
return $this->amplifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $amplifier
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setAmplifier($amplifier){
|
||||
$this->amplifier = $amplifier;
|
||||
$this->amplifier = (int) $amplifier;
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -188,4 +199,44 @@ class Effect{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function add(Entity $entity, $modify = false){
|
||||
$pk = new MobEffectPacket();
|
||||
$pk->eid = $entity->getId();
|
||||
$pk->effectId = $this->getId();
|
||||
$pk->amplifier = $this->getAmplifier();
|
||||
$pk->particles = $this->isVisible();
|
||||
$pk->duration = $this->getDuration();
|
||||
if($modify){
|
||||
$pk->eventId = MobEffectPacket::EVENT_MODIFY;
|
||||
}else{
|
||||
$pk->eventId = MobEffectPacket::EVENT_ADD;
|
||||
}
|
||||
|
||||
Server::broadcastPacket($entity->getViewers(), $pk);
|
||||
if($entity instanceof Player){
|
||||
$entity->dataPacket($pk);
|
||||
}
|
||||
|
||||
if($this->id === Effect::INVISIBILITY){
|
||||
$entity->setDataFlag(Entity::DATA_FLAGS, Entity::DATA_FLAG_INVISIBLE, true);
|
||||
$entity->setDataProperty(Entity::DATA_SHOW_NAMETAG, Entity::DATA_TYPE_BYTE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public function remove(Entity $entity){
|
||||
$pk = new MobEffectPacket();
|
||||
$pk->eid = $entity->getId();
|
||||
$pk->eventId = MobEffectPacket::EVENT_REMOVE;
|
||||
$pk->effectId = $this->getId();
|
||||
Server::broadcastPacket($entity->getViewers(), $pk);
|
||||
if($entity instanceof Player){
|
||||
$entity->dataPacket($pk);
|
||||
}
|
||||
|
||||
if($this->id === Effect::INVISIBILITY){
|
||||
$entity->setDataFlag(Entity::DATA_FLAGS, Entity::DATA_FLAG_INVISIBLE, false);
|
||||
$entity->setDataProperty(Entity::DATA_SHOW_NAMETAG, Entity::DATA_TYPE_BYTE, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ use pocketmine\nbt\tag\Compound;
|
||||
use pocketmine\nbt\tag\Double;
|
||||
use pocketmine\nbt\tag\Enum;
|
||||
use pocketmine\nbt\tag\Float;
|
||||
use pocketmine\nbt\tag\Int;
|
||||
use pocketmine\nbt\tag\Short;
|
||||
use pocketmine\nbt\tag\String;
|
||||
use pocketmine\Network;
|
||||
@ -66,6 +67,26 @@ abstract class Entity extends Location implements Metadatable{
|
||||
|
||||
const NETWORK_ID = -1;
|
||||
|
||||
|
||||
const DATA_TYPE_BYTE = 0;
|
||||
const DATA_TYPE_SHORT = 1;
|
||||
const DATA_TYPE_INT = 2;
|
||||
const DATA_TYPE_FLOAT = 3;
|
||||
const DATA_TYPE_STRING = 4;
|
||||
const DATA_TYPE_SLOT = 5;
|
||||
const DATA_TYPE_POS = 6;
|
||||
const DATA_TYPE_ROTATION = 7;
|
||||
|
||||
const DATA_FLAGS = 0;
|
||||
const DATA_AIR = 1;
|
||||
const DATA_SHOW_NAMETAG = 3;
|
||||
|
||||
|
||||
const DATA_FLAG_ONFIRE = 0;
|
||||
const DATA_FLAG_ACTION = 4;
|
||||
const DATA_FLAG_INVISIBLE = 5;
|
||||
|
||||
|
||||
public static $entityCount = 1;
|
||||
/** @var Entity[] */
|
||||
private static $knownEntities = [];
|
||||
@ -81,6 +102,13 @@ abstract class Entity extends Location implements Metadatable{
|
||||
|
||||
protected $id;
|
||||
|
||||
protected $dataFlags = 0;
|
||||
protected $dataProperties = [
|
||||
self::DATA_FLAGS => [self::DATA_TYPE_BYTE, 0],
|
||||
self::DATA_SHOW_NAMETAG => [self::DATA_TYPE_BYTE, 1],
|
||||
self::DATA_AIR => [self::DATA_TYPE_SHORT, 300]
|
||||
];
|
||||
|
||||
public $passenger = null;
|
||||
public $vehicle = null;
|
||||
|
||||
@ -138,7 +166,6 @@ abstract class Entity extends Location implements Metadatable{
|
||||
public $lastUpdate;
|
||||
public $maxFireTicks;
|
||||
public $fireTicks;
|
||||
public $airTicks;
|
||||
public $namedtag;
|
||||
public $canCollide = true;
|
||||
|
||||
@ -210,7 +237,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
if(!isset($this->namedtag->Air)){
|
||||
$this->namedtag->Air = new Short("Air", 300);
|
||||
}
|
||||
$this->airTicks = $this->namedtag["Air"];
|
||||
$this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, $this->namedtag["Air"]);
|
||||
|
||||
if(!isset($this->namedtag->OnGround)){
|
||||
$this->namedtag->OnGround = new Byte("OnGround", 0);
|
||||
@ -239,23 +266,17 @@ abstract class Entity extends Location implements Metadatable{
|
||||
return $this->effects;
|
||||
}
|
||||
|
||||
public function removeAllEffects(){
|
||||
foreach($this->effects as $effect){
|
||||
$this->removeEffect($effect->getId());
|
||||
}
|
||||
}
|
||||
|
||||
public function removeEffect($effectId){
|
||||
if(isset($this->effects[$effectId])){
|
||||
$pk = new MobEffectPacket();
|
||||
$pk->eid = $this->getId();
|
||||
$pk->eventId = MobEffectPacket::EVENT_REMOVE;
|
||||
$pk->effectId = $effectId;
|
||||
Server::broadcastPacket($this->getViewers(), $pk);
|
||||
if($this instanceof Player){
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
|
||||
$effect = $this->effects[$effectId];
|
||||
unset($this->effects[$effectId]);
|
||||
|
||||
$this->sendMetadata($this->hasSpawned);
|
||||
if($this instanceof Player){
|
||||
$this->sendMetadata($this);
|
||||
}
|
||||
$effect->remove($this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,29 +285,21 @@ abstract class Entity extends Location implements Metadatable{
|
||||
}
|
||||
|
||||
public function addEffect(Effect $effect){
|
||||
$pk = new MobEffectPacket();
|
||||
$pk->eid = $this->getId();
|
||||
$pk->effectId = $effect->getId();
|
||||
$pk->amplifier = $effect->getAmplifier();
|
||||
$pk->particles = $effect->isVisible();
|
||||
$pk->duration = $effect->getDuration();
|
||||
if(isset($this->effects[$effect->getId()])){
|
||||
$pk->eventId = MobEffectPacket::EVENT_MODIFY;
|
||||
$oldEffect = $this->effects[$effect->getId()];
|
||||
if(
|
||||
$effect->getAmplifier() <= $oldEffect->getAmplifier()
|
||||
or ($effect->getAmplifier() === $oldEffect->getAmplifier()
|
||||
and $effect->getDuration() < $oldEffect->getDuration())
|
||||
){
|
||||
return;
|
||||
}
|
||||
$effect->add($this, true);
|
||||
}else{
|
||||
$pk->eventId = MobEffectPacket::EVENT_ADD;
|
||||
}
|
||||
|
||||
Server::broadcastPacket($this->getViewers(), $pk);
|
||||
if($this instanceof Player){
|
||||
$this->dataPacket($pk);
|
||||
$effect->add($this, false);
|
||||
}
|
||||
|
||||
$this->effects[$effect->getId()] = $effect;
|
||||
|
||||
$this->sendMetadata($this->hasSpawned);
|
||||
if($this instanceof Player){
|
||||
$this->sendMetadata($this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -356,12 +369,42 @@ abstract class Entity extends Location implements Metadatable{
|
||||
|
||||
$this->namedtag->FallDistance = new Float("FallDistance", $this->fallDistance);
|
||||
$this->namedtag->Fire = new Short("Fire", $this->fireTicks);
|
||||
$this->namedtag->Air = new Short("Air", $this->airTicks);
|
||||
$this->namedtag->Air = new Short("Air", $this->getDataProperty(self::DATA_AIR));
|
||||
$this->namedtag->OnGround = new Byte("OnGround", $this->onGround == true ? 1 : 0);
|
||||
$this->namedtag->Invulnerable = new Byte("Invulnerable", $this->invulnerable == true ? 1 : 0);
|
||||
|
||||
if(count($this->effects) > 0){
|
||||
$effects = [];
|
||||
foreach($this->effects as $effect){
|
||||
$effects[$effect->getId()] = new Compound($effect->getId(), [
|
||||
"Id" => new Byte("Id", $effect->getId()),
|
||||
"Amplifier" => new Byte("Amplifier", $effect->getAmplifier()),
|
||||
"Duration" => new Int("Duration", $effect->getDuration()),
|
||||
"Ambient" => new Byte("Ambient", 0),
|
||||
"ShowParticles" => new Byte("ShowParticles", $effect->isVisible() ? 1 : 0)
|
||||
]);
|
||||
}
|
||||
|
||||
$this->namedtag->ActiveEffects = new Enum("ActiveEffects", $effects);
|
||||
}else{
|
||||
unset($this->namedtag->ActiveEffects);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract function initEntity();
|
||||
protected function initEntity(){
|
||||
if(isset($this->namedtag->ActiveEffects)){
|
||||
foreach($this->namedtag->ActiveEffects->getValue() as $e){
|
||||
$effect = Effect::getEffect($e["Id"]);
|
||||
if($effect === null){
|
||||
continue;
|
||||
}
|
||||
|
||||
$effect->setAmplifier($e["Amplifier"])->setDuration($e["Duration"])->setVisible($e["ShowParticles"] > 0);
|
||||
|
||||
$this->addEffect($effect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Player[]
|
||||
@ -376,31 +419,42 @@ abstract class Entity extends Location implements Metadatable{
|
||||
public function spawnTo(Player $player){
|
||||
if(!isset($this->hasSpawned[$player->getId()]) and isset($player->usedChunks[Level::chunkHash($this->chunk->getX(), $this->chunk->getZ())])){
|
||||
$this->hasSpawned[$player->getId()] = $player;
|
||||
foreach($this->effects as $effect){
|
||||
$pk = new MobEffectPacket();
|
||||
$pk->eid = $this->getId();
|
||||
$pk->effectId = $effect->getId();
|
||||
$pk->amplifier = $effect->getAmplifier();
|
||||
$pk->particles = $effect->isVisible();
|
||||
$pk->duration = $effect->getDuration();
|
||||
$pk->eventId = MobEffectPacket::EVENT_ADD;
|
||||
|
||||
$player->dataPacket($pk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function sendPotionEffects(Player $player){
|
||||
foreach($this->effects as $effect){
|
||||
$pk = new MobEffectPacket();
|
||||
$pk->eid = $this->getId();
|
||||
$pk->effectId = $effect->getId();
|
||||
$pk->amplifier = $effect->getAmplifier();
|
||||
$pk->particles = $effect->isVisible();
|
||||
$pk->duration = $effect->getDuration();
|
||||
$pk->eventId = MobEffectPacket::EVENT_ADD;
|
||||
|
||||
$player->dataPacket($pk);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player[]|Player $player
|
||||
* @deprecated
|
||||
*/
|
||||
public function sendMetadata($player){
|
||||
$this->sendData($player);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player[]|Player $player
|
||||
* @param array $data Properly formatted entity data, defaults to everything
|
||||
*/
|
||||
public function sendData($player, array $data = null){
|
||||
if($player instanceof Player){
|
||||
$player = [$player];
|
||||
}
|
||||
|
||||
$pk = new SetEntityDataPacket();
|
||||
$pk->eid = $this->id;
|
||||
$pk->metadata = $this->getData();
|
||||
$pk->metadata = $data === null ? $this->dataProperties : $data;
|
||||
Server::broadcastPacket($player, $pk);
|
||||
}
|
||||
|
||||
@ -588,7 +642,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
$isPlayer = $this instanceof Player;
|
||||
|
||||
if($this->dead === true){
|
||||
$this->effects = [];
|
||||
$this->removeAllEffects();
|
||||
$this->despawnFromAll();
|
||||
if(!$isPlayer){
|
||||
$this->close();
|
||||
@ -1380,7 +1434,67 @@ abstract class Entity extends Location implements Metadatable{
|
||||
}
|
||||
}
|
||||
|
||||
abstract public function getData();
|
||||
/**
|
||||
* @param int $id
|
||||
* @param int $type
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setDataProperty($id, $type, $value){
|
||||
$this->dataProperties[$id] = [$type, $value];
|
||||
|
||||
$targets = $this->hasSpawned;
|
||||
if($this instanceof Player){
|
||||
$targets[] = $this;
|
||||
}
|
||||
|
||||
$this->sendData($targets, [$id => $this->dataProperties[$id]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDataProperty($id){
|
||||
return isset($this->dataProperties[$id]) ? $this->dataProperties[$id][1] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getDataPropertyType($id){
|
||||
return isset($this->dataProperties[$id]) ? $this->dataProperties[$id][0] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $propertyId;
|
||||
* @param int $id
|
||||
* @param bool $value
|
||||
*/
|
||||
public function setDataFlag($propertyId, $id, $value = true, $type = self::DATA_TYPE_BYTE){
|
||||
if($this->getDataFlag($propertyId, $id) !== $value){
|
||||
$flags = (int) $this->getDataProperty($propertyId);
|
||||
$flags ^= 1 << $id;
|
||||
$this->setDataProperty($propertyId, $type, $flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $propertyId
|
||||
* @param int $id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getDataFlag($propertyId, $id){
|
||||
return (((int) $this->getDataProperty($propertyId)) & (1 << $id)) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function getData(){}
|
||||
|
||||
public function __destruct(){
|
||||
$this->close();
|
||||
|
@ -50,6 +50,7 @@ class FallingSand extends Entity{
|
||||
public $canCollide = false;
|
||||
|
||||
protected function initEntity(){
|
||||
parent::initEntity();
|
||||
if(isset($this->namedtag->TileID)){
|
||||
$this->blockId = $this->namedtag["TileID"];
|
||||
}elseif(isset($this->namedtag->Tile)){
|
||||
|
@ -24,6 +24,7 @@ namespace pocketmine\entity;
|
||||
use pocketmine\inventory\InventoryHolder;
|
||||
use pocketmine\inventory\PlayerInventory;
|
||||
use pocketmine\item\Item as ItemItem;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\Byte;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
@ -37,6 +38,11 @@ use pocketmine\utils\TextFormat;
|
||||
|
||||
class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
|
||||
const DATA_PLAYER_FLAG_SLEEP = 1;
|
||||
|
||||
const DATA_PLAYER_FLAGS = 16;
|
||||
const DATA_PLAYER_BED_POSITION = 17;
|
||||
|
||||
protected $nameTag = "TESTIFICATE";
|
||||
/** @var PlayerInventory */
|
||||
protected $inventory;
|
||||
@ -52,6 +58,9 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
|
||||
protected function initEntity(){
|
||||
|
||||
$this->setDataFlag(self::DATA_PLAYER_FLAGS, self::DATA_PLAYER_FLAG_SLEEP, false);
|
||||
$this->setDataProperty(self::DATA_PLAYER_BED_POSITION, self::DATA_TYPE_POS, [0, 0, 0]);
|
||||
|
||||
$this->inventory = new PlayerInventory($this);
|
||||
if($this instanceof Player){
|
||||
$this->addWindow($this->inventory, 0);
|
||||
@ -186,23 +195,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
}
|
||||
}
|
||||
|
||||
public function getData(){ //TODO
|
||||
$flags = 0;
|
||||
$flags |= $this->fireTicks > 0 ? 1 : 0;
|
||||
$flags |= $this->hasEffect(Effect::INVISIBILITY) ? 1 << 5 : 0;
|
||||
//$flags |= ($this->crouched === true ? 0b10:0) << 1;
|
||||
//$flags |= ($this->inAction === true ? 0b10000:0);
|
||||
$d = [
|
||||
0 => ["type" => 0, "value" => $flags],
|
||||
1 => ["type" => 1, "value" => $this->airTicks],
|
||||
3 => ["type" => 0, "value" => $this->hasEffect(Effect::INVISIBILITY) ? 0 : 1],
|
||||
16 => ["type" => 0, "value" => 0],
|
||||
17 => ["type" => 6, "value" => [0, 0, 0]],
|
||||
];
|
||||
|
||||
return $d;
|
||||
}
|
||||
|
||||
public function close(){
|
||||
if(!$this->closed){
|
||||
if(!($this instanceof Player) or $this->loggedIn){
|
||||
|
@ -52,6 +52,8 @@ class Item extends Entity{
|
||||
public $canCollide = false;
|
||||
|
||||
protected function initEntity(){
|
||||
parent::initEntity();
|
||||
|
||||
$this->setMaxHealth(5);
|
||||
$this->setHealth($this->namedtag["Health"]);
|
||||
if(isset($this->namedtag->Age)){
|
||||
|
@ -46,6 +46,8 @@ abstract class Living extends Entity implements Damageable{
|
||||
protected $invisible = false;
|
||||
|
||||
protected function initEntity(){
|
||||
parent::initEntity();
|
||||
|
||||
if(isset($this->namedtag->HealF)){
|
||||
$this->namedtag->Health = new Short("Health", (int) $this->namedtag["HealF"]);
|
||||
unset($this->namedtag->HealF);
|
||||
@ -180,15 +182,16 @@ abstract class Living extends Entity implements Damageable{
|
||||
|
||||
if($this->dead !== true and $this->isInsideOfWater()){
|
||||
$hasUpdate = true;
|
||||
$this->airTicks -= $tickDiff;
|
||||
if($this->airTicks <= -20){
|
||||
$this->airTicks = 0;
|
||||
$airTicks = $this->getDataProperty(self::DATA_AIR) - $tickDiff;
|
||||
if($airTicks <= -20){
|
||||
$airTicks = 0;
|
||||
|
||||
$ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_DROWNING, 2);
|
||||
$this->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
$this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, $airTicks);
|
||||
}else{
|
||||
$this->airTicks = 300;
|
||||
$this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, 300);
|
||||
}
|
||||
|
||||
if($this->attackTime > 0){
|
||||
|
@ -45,6 +45,8 @@ class PrimedTNT extends Entity implements Explosive{
|
||||
public $canCollide = false;
|
||||
|
||||
protected function initEntity(){
|
||||
parent::initEntity();
|
||||
|
||||
if(isset($this->namedtag->Fuse)){
|
||||
$this->fuse = $this->namedtag["Fuse"];
|
||||
}else{
|
||||
|
@ -40,6 +40,8 @@ abstract class Projectile extends Entity{
|
||||
private $hadCollision = false;
|
||||
|
||||
protected function initEntity(){
|
||||
parent::initEntity();
|
||||
|
||||
$this->setMaxHealth(1);
|
||||
$this->setHealth(1);
|
||||
if(isset($this->namedtag->Age)){
|
||||
@ -52,17 +54,6 @@ abstract class Projectile extends Entity{
|
||||
return $entity instanceof Living and !$this->onGround;
|
||||
}
|
||||
|
||||
public function getData(){
|
||||
$flags = 0;
|
||||
$flags |= $this->fireTicks > 0 ? 1 : 0;
|
||||
|
||||
return [
|
||||
0 => ["type" => 0, "value" => $flags],
|
||||
1 => ["type" => 1, "value" => $this->airTicks],
|
||||
16 => ["type" => 0, "value" => 0] //Is critical
|
||||
];
|
||||
}
|
||||
|
||||
public function saveNBT(){
|
||||
parent::saveNBT();
|
||||
$this->namedtag->Age = new Short("Age", $this->age);
|
||||
|
@ -68,21 +68,6 @@ class Villager extends Creature implements NPC, Ageable{
|
||||
parent::spawnTo($player);
|
||||
}
|
||||
|
||||
public function getData(){ //TODO
|
||||
$flags = 0;
|
||||
$flags |= $this->fireTicks > 0 ? 1 : 0;
|
||||
//$flags |= ($this->crouched === true ? 0b10:0) << 1;
|
||||
//$flags |= ($this->inAction === true ? 0b10000:0);
|
||||
$d = [
|
||||
0 => ["type" => 0, "value" => $flags],
|
||||
1 => ["type" => 1, "value" => $this->airTicks],
|
||||
16 => ["type" => 0, "value" => 0],
|
||||
17 => ["type" => 6, "value" => [0, 0, 0]],
|
||||
];
|
||||
|
||||
return $d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the villager profession
|
||||
*
|
||||
|
@ -56,21 +56,6 @@ class Zombie extends Monster{
|
||||
parent::spawnTo($player);
|
||||
}
|
||||
|
||||
public function getData(){ //TODO
|
||||
$flags = 0;
|
||||
$flags |= $this->fireTicks > 0 ? 1 : 0;
|
||||
//$flags |= ($this->crouched === true ? 0b10:0) << 1;
|
||||
//$flags |= ($this->inAction === true ? 0b10000:0);
|
||||
$d = [
|
||||
0 => ["type" => 0, "value" => $flags],
|
||||
1 => ["type" => 1, "value" => $this->airTicks],
|
||||
16 => ["type" => 0, "value" => 0],
|
||||
17 => ["type" => 6, "value" => [0, 0, 0]],
|
||||
];
|
||||
|
||||
return $d;
|
||||
}
|
||||
|
||||
public function getDrops(){
|
||||
$drops = [
|
||||
ItemItem::get(ItemItem::FEATHER, 0, 1)
|
||||
|
@ -23,6 +23,7 @@
|
||||
* Various Utilities used around the code
|
||||
*/
|
||||
namespace pocketmine\utils;
|
||||
use pocketmine\entity\Entity;
|
||||
|
||||
/**
|
||||
* WARNING: This class is available on the PocketMine-MP Zephir project.
|
||||
@ -88,32 +89,32 @@ class Binary{
|
||||
public static function writeMetadata(array $data){
|
||||
$m = "";
|
||||
foreach($data as $bottom => $d){
|
||||
$m .= chr(($d["type"] << 5) | ($bottom & 0x1F));
|
||||
switch($d["type"]){
|
||||
case 0:
|
||||
$m .= self::writeByte($d["value"]);
|
||||
$m .= chr(($d[0] << 5) | ($bottom & 0x1F));
|
||||
switch($d[0]){
|
||||
case Entity::DATA_TYPE_BYTE:
|
||||
$m .= self::writeByte($d[1]);
|
||||
break;
|
||||
case 1:
|
||||
$m .= self::writeLShort($d["value"]);
|
||||
case Entity::DATA_TYPE_SHORT:
|
||||
$m .= self::writeLShort($d[1]);
|
||||
break;
|
||||
case 2:
|
||||
$m .= self::writeLInt($d["value"]);
|
||||
case Entity::DATA_TYPE_INT:
|
||||
$m .= self::writeLInt($d[1]);
|
||||
break;
|
||||
case 3:
|
||||
$m .= self::writeLFloat($d["value"]);
|
||||
case Entity::DATA_TYPE_FLOAT:
|
||||
$m .= self::writeLFloat($d[1]);
|
||||
break;
|
||||
case 4:
|
||||
$m .= self::writeLShort(strlen($d["value"])) . $d["value"];
|
||||
case Entity::DATA_TYPE_STRING:
|
||||
$m .= self::writeLShort(strlen($d[1])) . $d[1];
|
||||
break;
|
||||
case 5:
|
||||
$m .= self::writeLShort($d["value"][0]);
|
||||
$m .= self::writeByte($d["value"][1]);
|
||||
$m .= self::writeLShort($d["value"][2]);
|
||||
case Entity::DATA_TYPE_SLOT:
|
||||
$m .= self::writeLShort($d[1][0]);
|
||||
$m .= self::writeByte($d[1][1]);
|
||||
$m .= self::writeLShort($d[1][2]);
|
||||
break;
|
||||
case 6:
|
||||
$m .= self::writeLInt($d["value"][0]);
|
||||
$m .= self::writeLInt($d["value"][1]);
|
||||
$m .= self::writeLInt($d["value"][2]);
|
||||
case Entity::DATA_TYPE_POS:
|
||||
$m .= self::writeLInt($d[1][0]);
|
||||
$m .= self::writeLInt($d[1][1]);
|
||||
$m .= self::writeLInt($d[1][2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -140,29 +141,29 @@ class Binary{
|
||||
$bottom = $b & 0x1F;
|
||||
$type = $b >> 5;
|
||||
switch($type){
|
||||
case 0:
|
||||
case Entity::DATA_TYPE_BYTE:
|
||||
$r = self::readByte($value{$offset});
|
||||
++$offset;
|
||||
break;
|
||||
case 1:
|
||||
case Entity::DATA_TYPE_SHORT:
|
||||
$r = self::readLShort(substr($value, $offset, 2));
|
||||
$offset += 2;
|
||||
break;
|
||||
case 2:
|
||||
case Entity::DATA_TYPE_INT:
|
||||
$r = self::readLInt(substr($value, $offset, 4));
|
||||
$offset += 4;
|
||||
break;
|
||||
case 3:
|
||||
case Entity::DATA_TYPE_FLOAT:
|
||||
$r = self::readLFloat(substr($value, $offset, 4));
|
||||
$offset += 4;
|
||||
break;
|
||||
case 4:
|
||||
case Entity::DATA_TYPE_STRING:
|
||||
$len = self::readLShort(substr($value, $offset, 2));
|
||||
$offset += 2;
|
||||
$r = substr($value, $offset, $len);
|
||||
$offset += $len;
|
||||
break;
|
||||
case 5:
|
||||
case Entity::DATA_TYPE_SLOT:
|
||||
$r = [];
|
||||
$r[] = self::readLShort(substr($value, $offset, 2));
|
||||
$offset += 2;
|
||||
@ -171,7 +172,7 @@ class Binary{
|
||||
$r[] = self::readLShort(substr($value, $offset, 2));
|
||||
$offset += 2;
|
||||
break;
|
||||
case 6:
|
||||
case Entity::DATA_TYPE_POS:
|
||||
$r = [];
|
||||
for($i = 0; $i < 3; ++$i){
|
||||
$r[] = self::readLInt(substr($value, $offset, 4));
|
||||
@ -183,7 +184,7 @@ class Binary{
|
||||
|
||||
}
|
||||
if($types === true){
|
||||
$m[$bottom] = ["value" => $r, "type" => $type];
|
||||
$m[$bottom] = [$r, $type];
|
||||
}else{
|
||||
$m[$bottom] = $r;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user