Merge pull request #42 from pmmp/0.16

Update to 0.16 (1.6.1dev, API 2.1.0)
This commit is contained in:
Dylan K. Taylor 2016-10-30 11:27:10 +00:00 committed by GitHub
commit dc07fc42b4
108 changed files with 5349 additions and 1465 deletions

View File

@ -23,6 +23,7 @@ namespace pocketmine;
use pocketmine\block\Air;
use pocketmine\block\Block;
use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\entity\Arrow;
use pocketmine\entity\Effect;
@ -60,6 +61,7 @@ use pocketmine\event\player\PlayerMoveEvent;
use pocketmine\event\player\PlayerPreLoginEvent;
use pocketmine\event\player\PlayerQuitEvent;
use pocketmine\event\player\PlayerRespawnEvent;
use pocketmine\event\player\PlayerToggleFlightEvent;
use pocketmine\event\player\PlayerToggleSneakEvent;
use pocketmine\event\player\PlayerToggleSprintEvent;
use pocketmine\event\server\DataPacketReceiveEvent;
@ -100,6 +102,7 @@ use pocketmine\nbt\tag\ShortTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\network\protocol\AdventureSettingsPacket;
use pocketmine\network\protocol\AnimatePacket;
use pocketmine\network\protocol\AvailableCommandsPacket;
use pocketmine\network\protocol\BatchPacket;
use pocketmine\network\protocol\ChunkRadiusUpdatedPacket;
use pocketmine\network\protocol\ContainerClosePacket;
@ -113,6 +116,7 @@ use pocketmine\network\protocol\InteractPacket;
use pocketmine\network\protocol\MovePlayerPacket;
use pocketmine\network\protocol\PlayerActionPacket;
use pocketmine\network\protocol\PlayStatusPacket;
use pocketmine\network\protocol\ResourcePacksInfoPacket;
use pocketmine\network\protocol\RespawnPacket;
use pocketmine\network\protocol\SetDifficultyPacket;
use pocketmine\network\protocol\SetEntityMotionPacket;
@ -132,9 +136,9 @@ use pocketmine\plugin\Plugin;
use pocketmine\tile\Sign;
use pocketmine\tile\Spawnable;
use pocketmine\tile\Tile;
use pocketmine\utils\Binary;
use pocketmine\utils\TextFormat;
use pocketmine\utils\UUID;
use raklib\Binary;
/**
@ -230,9 +234,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
protected $inAirTicks = 0;
protected $startAirTicks = 5;
//TODO: Abilities
protected $autoJump = true;
protected $allowFlight = false;
protected $flying = false;
private $needACK = [];
@ -309,10 +314,19 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->sendSettings();
}
public function getAllowFlight(){
public function getAllowFlight() : bool{
return $this->allowFlight;
}
public function setFlying(bool $value){
$this->flying = $value;
$this->sendSettings();
}
public function isFlying() : bool{
return $this->flying;
}
public function setAutoJump($value){
$this->autoJump = $value;
$this->sendSettings();
@ -426,6 +440,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
$this->recalculatePermissions();
$this->sendSettings();
$this->sendCommandData();
}
/**
@ -489,6 +505,25 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return $this->perm->getEffectivePermissions();
}
public function sendCommandData(){
$pk = new AvailableCommandsPacket();
$data = new \stdClass();
$count = 0;
foreach($this->server->getCommandMap()->getCommands() as $command){
if(!$command->testPermissionSilent($this)){
continue;
}
++$count;
$data->{$command->getName()}->versions[0] = $command->generateCustomCommandData($this);
}
if($count > 0){
//TODO: structure checking
$pk->commands = json_encode($data);
$this->dataPacket($pk);
}
}
/**
* @param SourceInterface $interface
* @param null $clientID
@ -982,7 +1017,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->sleeping = clone $pos;
$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->setDataFlag(self::DATA_PLAYER_FLAGS, self::DATA_PLAYER_FLAG_SLEEP, true, self::DATA_TYPE_BYTE);
$this->setSpawn($pos);
@ -1017,7 +1052,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->sleeping = null;
$this->setDataProperty(self::DATA_PLAYER_BED_POSITION, self::DATA_TYPE_POS, [0, 0, 0]);
$this->setDataFlag(self::DATA_PLAYER_FLAGS, self::DATA_PLAYER_FLAG_SLEEP, false);
$this->setDataFlag(self::DATA_PLAYER_FLAGS, self::DATA_PLAYER_FLAG_SLEEP, false, self::DATA_TYPE_BYTE);
$this->level->sleepTicks = 0;
@ -1064,36 +1099,56 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
/**
* Sets the gamemode, and if needed, kicks the Player.
*
* @param int $gm
* @param int $gm
* @param bool $client if the client made this change in their GUI
*
* @return bool
*/
public function setGamemode($gm){
public function setGamemode(int $gm, bool $client = false){
if($gm < 0 or $gm > 3 or $this->gamemode === $gm){
return false;
}
$this->server->getPluginManager()->callEvent($ev = new PlayerGameModeChangeEvent($this, (int) $gm));
if($ev->isCancelled()){
if($client){ //gamemode change by client in the GUI
$pk = new SetPlayerGameTypePacket();
$pk->gamemode = $this->gamemode & 0x01;
$this->dataPacket($pk);
$this->sendSettings();
}
return false;
}
$this->gamemode = $gm;
$this->allowFlight = $this->isCreative();
if($this->isSpectator()){
$this->flying = true;
$this->despawnFromAll();
// Client automatically turns off flight controls when on the ground.
// A combination of this hack and a new AdventureSettings flag FINALLY
// fixes spectator flight controls. Thank @robske110 for this hack.
$this->teleport($this->temporalVector->setComponents($this->x, $this->y + 0.1, $this->z));
}else{
if($this->isSurvival()){
$this->flying = false;
}
$this->spawnToAll();
}
$this->namedtag->playerGameType = new IntTag("playerGameType", $this->gamemode);
$this->resetFallDistance();
$pk = new SetPlayerGameTypePacket();
$pk->gamemode = $this->gamemode & 0x01;
$this->dataPacket($pk);
$this->sendSettings();
$this->namedtag->playerGameType = new IntTag("playerGameType", $this->gamemode);
if(!$client){ //Gamemode changed by server, do not send for client changes
$pk = new SetPlayerGameTypePacket();
$pk->gamemode = $this->gamemode & 0x01;
$this->dataPacket($pk);
$this->sendSettings();
}else{
Command::broadcastCommandMessage($this, new TranslationContainer("commands.gamemode.success.self", [Server::getGamemodeString($gm)]));
}
$this->inventory->sendContents($this);
$this->inventory->sendContents($this->getViewers());
@ -1109,66 +1164,14 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
* Sends all the option flags
*/
public function sendSettings(){
/*
bit mask | flag name
0x00000001 world_inmutable
0x00000002 no_pvp
0x00000004 no_pvm
0x00000008 no_mvp
0x00000010 static_time
0x00000020 nametags_visible
0x00000040 auto_jump
0x00000080 allow_fly
0x00000100 noclip
0x00000200 ?
0x00000400 ?
0x00000800 ?
0x00001000 ?
0x00002000 ?
0x00004000 ?
0x00008000 ?
0x00010000 ?
0x00020000 ?
0x00040000 ?
0x00080000 ?
0x00100000 ?
0x00200000 ?
0x00400000 ?
0x00800000 ?
0x01000000 ?
0x02000000 ?
0x04000000 ?
0x08000000 ?
0x10000000 ?
0x20000000 ?
0x40000000 ?
0x80000000 ?
*/
$flags = 0;
if($this->isAdventure()){
$flags |= 0x01; //Do not allow placing/breaking blocks, adventure mode
}
/*if($nametags !== false){
$flags |= 0x20; //Show Nametags
}*/
if($this->autoJump){
$flags |= 0x40;
}
if($this->allowFlight){
$flags |= 0x80;
}
if($this->isSpectator()){
$flags |= 0x100;
}
$pk = new AdventureSettingsPacket();
$pk->flags = $flags;
$pk->userPermission = 2;
$pk->globalPermission = 2;
$pk->flags = 0;
$pk->worldImmutable = $this->isAdventure();
$pk->autoJump = $this->autoJump;
$pk->allowFlight = $this->allowFlight;
$pk->noClip = $this->isSpectator();
$pk->isFlying = $this->flying;
$pk->userPermission = ($this->isOp() ? AdventureSettingsPacket::PERMISSION_OPERATOR : AdventureSettingsPacket::PERMISSION_NORMAL);
$this->dataPacket($pk);
}
@ -1205,31 +1208,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return [];
}
public function setDataProperty($id, $type, $value, $send = true){
if(parent::setDataProperty($id, $type, $value, $send)){
return true;
}
return false;
}
public function entityBaseTick($tickDiff = 1){
$hasUpdate = parent::entityBaseTick($tickDiff);
$entries = $this->attributeMap->needSend();
if(count($entries) > 0){
$pk = new UpdateAttributesPacket();
$pk->entityId = 0;
$pk->entries = $entries;
$this->dataPacket($pk);
foreach($entries as $entry){
$entry->markSynchronized();
}
}
return $hasUpdate;
}
protected function checkGroundState($movX, $movY, $movZ, $dx, $dy, $dz){
if(!$this->onGround or $movY != 0){
$bb = clone $this->boundingBox;
@ -1451,7 +1429,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
if($this->chunk !== null){
$this->level->addEntityMotion($this->chunk->getX(), $this->chunk->getZ(), $this->getId(), $this->motionX, $this->motionY, $this->motionZ);
$pk = new SetEntityMotionPacket();
$pk->entities[] = [0, $mot->x, $mot->y, $mot->z];
$pk->eid = 0;
$pk->motionX = $mot->x;
$pk->motionY = $mot->y;
$pk->motionZ = $mot->z;
$this->dataPacket($pk);
}
@ -1465,6 +1446,20 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
protected function updateMovement(){
}
public function sendAttributes(bool $sendAll = false){
$entries = $sendAll ? $this->attributeMap->getAll() : $this->attributeMap->needSend();
if(count($entries) > 0){
$pk = new UpdateAttributesPacket();
$pk->entityId = 0;
$pk->entries = $entries;
$this->dataPacket($pk);
foreach($entries as $entry){
$entry->markSynchronized();
}
}
}
public function onUpdate($currentTick){
@ -1482,6 +1477,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->lastUpdate = $currentTick;
$this->sendAttributes();
if(!$this->isAlive() and $this->spawned){
++$this->deadTicks;
if($this->deadTicks >= 10){
@ -1505,7 +1502,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
$this->inAirTicks = 0;
}else{
if(!$this->allowFlight and $this->inAirTicks > 10 and !$this->isSleeping() and $this->getDataProperty(self::DATA_NO_AI) !== 1){
if(!$this->allowFlight and $this->inAirTicks > 10 and !$this->isSleeping() and !$this->isImmobile()){
$expectedVelocity = (-$this->gravity) / $this->drag - ((-$this->gravity) / $this->drag) * exp(-$this->drag * ($this->inAirTicks - $this->startAirTicks));
$diff = ($this->speed->y - $expectedVelocity) ** 2;
@ -1678,9 +1675,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->inventory->setHeldItemSlot($this->inventory->getHotbarSlotIndex(0));
}
$pk = new PlayStatusPacket();
$pk->status = PlayStatusPacket::LOGIN_SUCCESS;
$this->dataPacket($pk);
$this->dataPacket(new ResourcePacksInfoPacket());
if($this->spawnPosition === null and isset($this->namedtag->SpawnLevel) and ($level = $this->server->getLevelByName($this->namedtag["SpawnLevel"])) instanceof Level){
$this->spawnPosition = new Position($this->namedtag["SpawnX"], $this->namedtag["SpawnY"], $this->namedtag["SpawnZ"], $level);
@ -1689,17 +1684,26 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$spawnPosition = $this->getSpawn();
$pk = new StartGamePacket();
$pk->seed = -1;
$pk->dimension = 0;
$pk->entityUniqueId = 0;
$pk->entityRuntimeId = 0;
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
$pk->spawnX = (int) $spawnPosition->x;
$pk->spawnY = (int) $spawnPosition->y;
$pk->spawnZ = (int) $spawnPosition->z;
$pk->generator = 1; //0 old, 1 infinite, 2 flat
$pk->seed = -1;
$pk->dimension = 0; //TODO: implement this properly
$pk->gamemode = $this->gamemode & 0x01;
$pk->eid = 0; //Always use EntityID as zero for the actual player
$pk->difficulty = $this->server->getDifficulty();
$pk->spawnX = $spawnPosition->getFloorX();
$pk->spawnY = $spawnPosition->getFloorY();
$pk->spawnZ = $spawnPosition->getFloorZ();
$pk->hasBeenLoadedInCreative = 1;
$pk->dayCycleStopTime = -1; //TODO: implement this properly
$pk->eduMode = 0;
$pk->rainLevel = 0; //TODO: implement these properly
$pk->lightningLevel = 0;
$pk->commandsEnabled = 1;
$pk->levelId = "";
$pk->worldName = $this->server->getMotd();
$this->dataPacket($pk);
$pk = new SetTimePacket();
@ -1707,19 +1711,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk->started = $this->level->stopTime == false;
$this->dataPacket($pk);
$pk = new SetSpawnPositionPacket();
$pk->x = (int) $spawnPosition->x;
$pk->y = (int) $spawnPosition->y;
$pk->z = (int) $spawnPosition->z;
$this->dataPacket($pk);
$pk = new SetHealthPacket();
$pk->health = $this->getHealth();
$this->dataPacket($pk);
$pk = new SetDifficultyPacket();
$pk->difficulty = $this->server->getDifficulty();
$this->dataPacket($pk);
$this->sendAttributes(true);
$this->setNameTagVisible(true);
$this->setNameTagAlwaysVisible(true);
$this->server->getLogger()->info($this->getServer()->getLanguage()->translateString("pocketmine.player.logIn", [
TextFormat::AQUA . $this->username . TextFormat::WHITE,
@ -1736,6 +1730,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->setRemoveFormat(false);
}
$this->sendCommandData();
if($this->isCreative()){
$this->inventory->sendCreativeContents();
}
@ -1880,6 +1876,21 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
$this->forceMovement = null;
break;
case ProtocolInfo::ADVENTURE_SETTINGS_PACKET:
//TODO: player abilities, check for other changes
if($packet->isFlying and !$this->allowFlight){
$this->kick("Flying is not enabled on this server");
break;
}else{
$this->server->getPluginManager()->callEvent($ev = new PlayerToggleFlightEvent($this, $packet->isFlying));
if($ev->isCancelled()){
$this->sendSettings();
}else{
$this->flying = $ev->isFlying();
}
break;
}
break;
case ProtocolInfo::MOB_EQUIPMENT_PACKET:
if($this->spawned === false or !$this->isAlive()){
@ -1989,8 +2000,12 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->level->sendBlocks([$this], [$target, $block], UpdateBlockPacket::FLAG_ALL_PRIORITY);
break;
}elseif($packet->face === 0xff){
$aimPos = (new Vector3($packet->x / 32768, $packet->y / 32768, $packet->z / 32768))->normalize();
}elseif($packet->face === -1){
$aimPos = new Vector3(
-sin($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI),
-sin($this->pitch / 180 * M_PI),
cos($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI)
);
if($this->isCreative()){
$item = $this->inventory->getItemInHand();
@ -2194,7 +2209,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->setSneaking(false);
$this->extinguish();
$this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, 300, false);
$this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, 400, false);
$this->deadTicks = 0;
$this->noDamageTicks = 60;
@ -2308,123 +2323,120 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$target = $this->level->getEntity($packet->target);
$cancelled = false;
if($packet->action === InteractPacket::ACTION_RIGHT_CLICK){
// TODO handle
break;
}
if(
$target instanceof Player and
$this->server->getConfigBoolean("pvp", true) === false
){
$cancelled = true;
}
if($target instanceof Entity and $this->getGamemode() !== Player::VIEW and $this->isAlive() and $target->isAlive()){
if($target instanceof DroppedItem or $target instanceof Arrow){
$this->kick("Attempting to attack an invalid entity");
$this->server->getLogger()->warning($this->getServer()->getLanguage()->translateString("pocketmine.player.invalidEntity", [$this->getName()]));
break;
}
$item = $this->inventory->getItemInHand();
$damageTable = [
Item::WOODEN_SWORD => 4,
Item::GOLD_SWORD => 4,
Item::STONE_SWORD => 5,
Item::IRON_SWORD => 6,
Item::DIAMOND_SWORD => 7,
Item::WOODEN_AXE => 3,
Item::GOLD_AXE => 3,
Item::STONE_AXE => 3,
Item::IRON_AXE => 5,
Item::DIAMOND_AXE => 6,
Item::WOODEN_PICKAXE => 2,
Item::GOLD_PICKAXE => 2,
Item::STONE_PICKAXE => 3,
Item::IRON_PICKAXE => 4,
Item::DIAMOND_PICKAXE => 5,
Item::WOODEN_SHOVEL => 1,
Item::GOLD_SHOVEL => 1,
Item::STONE_SHOVEL => 2,
Item::IRON_SHOVEL => 3,
Item::DIAMOND_SHOVEL => 4,
];
$damage = [
EntityDamageEvent::MODIFIER_BASE => isset($damageTable[$item->getId()]) ? $damageTable[$item->getId()] : 1,
];
if(!$this->canInteract($target, 8)){
$cancelled = true;
}elseif($target instanceof Player){
if(($target->getGamemode() & 0x01) > 0){
break;
}elseif($this->server->getConfigBoolean("pvp") !== true or $this->server->getDifficulty() === 0){
switch($packet->action){
case InteractPacket::ACTION_LEFT_CLICK: //Attack
if($target instanceof Player and $this->server->getConfigBoolean("pvp", true) === false){
$cancelled = true;
}
$armorValues = [
Item::LEATHER_CAP => 1,
Item::LEATHER_TUNIC => 3,
Item::LEATHER_PANTS => 2,
Item::LEATHER_BOOTS => 1,
Item::CHAIN_HELMET => 1,
Item::CHAIN_CHESTPLATE => 5,
Item::CHAIN_LEGGINGS => 4,
Item::CHAIN_BOOTS => 1,
Item::GOLD_HELMET => 1,
Item::GOLD_CHESTPLATE => 5,
Item::GOLD_LEGGINGS => 3,
Item::GOLD_BOOTS => 1,
Item::IRON_HELMET => 2,
Item::IRON_CHESTPLATE => 6,
Item::IRON_LEGGINGS => 5,
Item::IRON_BOOTS => 2,
Item::DIAMOND_HELMET => 3,
Item::DIAMOND_CHESTPLATE => 8,
Item::DIAMOND_LEGGINGS => 6,
Item::DIAMOND_BOOTS => 3,
];
$points = 0;
foreach($target->getInventory()->getArmorContents() as $index => $i){
if(isset($armorValues[$i->getId()])){
$points += $armorValues[$i->getId()];
if($target instanceof Entity and $this->getGamemode() !== Player::VIEW and $this->isAlive() and $target->isAlive()){
if($target instanceof DroppedItem or $target instanceof Arrow){
$this->kick("Attempting to attack an invalid entity");
$this->server->getLogger()->warning($this->getServer()->getLanguage()->translateString("pocketmine.player.invalidEntity", [$this->getName()]));
break;
}
}
$damage[EntityDamageEvent::MODIFIER_ARMOR] = -floor($damage[EntityDamageEvent::MODIFIER_BASE] * $points * 0.04);
}
$item = $this->inventory->getItemInHand();
$damageTable = [
Item::WOODEN_SWORD => 4,
Item::GOLD_SWORD => 4,
Item::STONE_SWORD => 5,
Item::IRON_SWORD => 6,
Item::DIAMOND_SWORD => 7,
$ev = new EntityDamageByEntityEvent($this, $target, EntityDamageEvent::CAUSE_ENTITY_ATTACK, $damage);
if($cancelled){
$ev->setCancelled();
}
Item::WOODEN_AXE => 3,
Item::GOLD_AXE => 3,
Item::STONE_AXE => 3,
Item::IRON_AXE => 5,
Item::DIAMOND_AXE => 6,
$target->attack($ev->getFinalDamage(), $ev);
Item::WOODEN_PICKAXE => 2,
Item::GOLD_PICKAXE => 2,
Item::STONE_PICKAXE => 3,
Item::IRON_PICKAXE => 4,
Item::DIAMOND_PICKAXE => 5,
if($ev->isCancelled()){
if($item->isTool() and $this->isSurvival()){
$this->inventory->sendContents($this);
Item::WOODEN_SHOVEL => 1,
Item::GOLD_SHOVEL => 1,
Item::STONE_SHOVEL => 2,
Item::IRON_SHOVEL => 3,
Item::DIAMOND_SHOVEL => 4,
];
$damage = [
EntityDamageEvent::MODIFIER_BASE => isset($damageTable[$item->getId()]) ? $damageTable[$item->getId()] : 1,
];
if(!$this->canInteract($target, 8)){
$cancelled = true;
}elseif($target instanceof Player){
if(($target->getGamemode() & 0x01) > 0){
break;
}elseif($this->server->getConfigBoolean("pvp") !== true or $this->server->getDifficulty() === 0){
$cancelled = true;
}
$armorValues = [
Item::LEATHER_CAP => 1,
Item::LEATHER_TUNIC => 3,
Item::LEATHER_PANTS => 2,
Item::LEATHER_BOOTS => 1,
Item::CHAIN_HELMET => 1,
Item::CHAIN_CHESTPLATE => 5,
Item::CHAIN_LEGGINGS => 4,
Item::CHAIN_BOOTS => 1,
Item::GOLD_HELMET => 1,
Item::GOLD_CHESTPLATE => 5,
Item::GOLD_LEGGINGS => 3,
Item::GOLD_BOOTS => 1,
Item::IRON_HELMET => 2,
Item::IRON_CHESTPLATE => 6,
Item::IRON_LEGGINGS => 5,
Item::IRON_BOOTS => 2,
Item::DIAMOND_HELMET => 3,
Item::DIAMOND_CHESTPLATE => 8,
Item::DIAMOND_LEGGINGS => 6,
Item::DIAMOND_BOOTS => 3,
];
$points = 0;
foreach($target->getInventory()->getArmorContents() as $index => $i){
if(isset($armorValues[$i->getId()])){
$points += $armorValues[$i->getId()];
}
}
$damage[EntityDamageEvent::MODIFIER_ARMOR] = -floor($damage[EntityDamageEvent::MODIFIER_BASE] * $points * 0.04);
}
$ev = new EntityDamageByEntityEvent($this, $target, EntityDamageEvent::CAUSE_ENTITY_ATTACK, $damage);
if($cancelled){
$ev->setCancelled();
}
$target->attack($ev->getFinalDamage(), $ev);
if($ev->isCancelled()){
if($item->isTool() and $this->isSurvival()){
$this->inventory->sendContents($this);
}
break;
}
if($this->isSurvival()){
if($item->isTool()){
if($item->useOn($target) and $item->getDamage() >= $item->getMaxDurability()){
$this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1));
}else{
$this->inventory->setItemInHand($item);
}
}
$this->exhaust(0.3, PlayerExhaustEvent::CAUSE_ATTACK);
}
}
break;
}
if($this->isSurvival()){
if($item->isTool()){
if($item->useOn($target) and $item->getDamage() >= $item->getMaxDurability()){
$this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1));
}else{
$this->inventory->setItemInHand($item);
}
}
$this->exhaust(0.3, PlayerExhaustEvent::CAUSE_ATTACK);
}
default:
break; //TODO: handle other actions
}
break;
@ -2491,6 +2503,26 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
break;
case ProtocolInfo::COMMAND_STEP_PACKET:
if($this->spawned === false or !$this->isAlive()){
break;
}
$this->craftingType = 0;
$commandText = $packet->command;
if($packet->args !== null){
foreach($packet->args as $arg){ //command ordering will be an issue
$commandText .= " " . $arg;
}
}
$this->server->getPluginManager()->callEvent($ev = new PlayerCommandPreprocessEvent($this, "/" . $commandText));
if($ev->isCancelled()){
break;
}
Timings::$playerCommandTimer->startTiming();
$this->server->dispatchCommand($ev->getPlayer(), substr($ev->getMessage(), 1));
Timings::$playerCommandTimer->stopTiming();
break;
case ProtocolInfo::TEXT_PACKET:
if($this->spawned === false or !$this->isAlive()){
break;
@ -2510,9 +2542,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
if($ev->isCancelled()){
break;
}
if(substr($ev->getMessage(), 0, 1) === "/"){ //Command
if(substr($ev->getMessage(), 0, 2) === "./"){ //Command (./ = fast hack for old plugins post 0.16)
Timings::$playerCommandTimer->startTiming();
$this->server->dispatchCommand($ev->getPlayer(), substr($ev->getMessage(), 1));
$this->server->dispatchCommand($ev->getPlayer(), substr($ev->getMessage(), 2));
Timings::$playerCommandTimer->stopTiming();
}else{
$this->server->getPluginManager()->callEvent($ev = new PlayerChatEvent($this, $ev->getMessage()));
@ -2808,7 +2840,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$t = $this->level->getTile($pos);
if($t instanceof Sign){
$nbt = new NBT(NBT::LITTLE_ENDIAN);
$nbt->read($packet->namedtag);
$nbt->read($packet->namedtag, false, true);
$nbt = $nbt->getData();
if($nbt["id"] !== Tile::SIGN){
$t->spawnTo($this);
@ -2839,6 +2871,18 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk->radius = $packet->radius;
$this->dataPacket($pk);
break;
case ProtocolInfo::SET_PLAYER_GAME_TYPE_PACKET:
if($packet->gamemode !== $this->gamemode){
if(!$this->hasPermission("pocketmine.command.gamemode")){
$pk = new SetPlayerGameTypePacket();
$pk->gamemode = $this->gamemode & 0x01;
$this->dataPacket($pk);
$this->sendSettings();
break;
}
$this->setGamemode($packet->gamemode, true);
}
break;
default:
break;
}
@ -3504,7 +3548,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk->encode();
$batch = new BatchPacket();
$batch->payload = zlib_encode(Binary::writeInt(strlen($pk->getBuffer())) . $pk->getBuffer(), ZLIB_ENCODING_DEFLATE, Server::getInstance()->networkCompressionLevel);
$batch->payload = zlib_encode(Binary::writeUnsignedVarInt(strlen($pk->getBuffer())) . $pk->getBuffer(), ZLIB_ENCODING_DEFLATE, Server::getInstance()->networkCompressionLevel);
$batch->encode();
$batch->isEncoded = true;

View File

@ -72,11 +72,11 @@ namespace pocketmine {
use pocketmine\utils\Utils;
use pocketmine\wizard\Installer;
const VERSION = "1.6dev";
const API_VERSION = "2.0.0";
const VERSION = "1.6.1dev";
const API_VERSION = "2.1.0";
const CODENAME = "Unleashed";
const MINECRAFT_VERSION = "v0.15.10.0 alpha";
const MINECRAFT_VERSION_NETWORK = "0.15.10.0";
const MINECRAFT_VERSION = "v0.16.0.5 alpha";
const MINECRAFT_VERSION_NETWORK = "0.16.0.5";
/*
* Startup code. Do not look at it, it may harm you.

View File

@ -1567,10 +1567,10 @@ class Server{
InventoryType::init();
Block::init();
Enchantment::init();
Item::init();
Biome::init();
Effect::init();
Enchantment::init();
Attribute::init();
$this->craftingManager = new CraftingManager();
@ -1798,9 +1798,9 @@ class Server{
if(!$p->isEncoded){
$p->encode();
}
$str .= Binary::writeInt(strlen($p->buffer)) . $p->buffer;
$str .= Binary::writeUnsignedVarInt(strlen($p->buffer)) . $p->buffer;
}else{
$str .= Binary::writeInt(strlen($p)) . $p;
$str .= Binary::writeUnsignedVarInt(strlen($p)) . $p;
}
}
@ -1889,7 +1889,7 @@ class Server{
}
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.notFound"));
$sender->sendMessage(new TranslationContainer(TextFormat::GOLD . "%commands.generic.notFound"));
return false;
}
@ -2219,6 +2219,9 @@ class Server{
$pk = new PlayerListPacket();
$pk->type = PlayerListPacket::TYPE_ADD;
foreach($this->playerList as $player){
if($p === $player){
continue; //fixes duplicates
}
$pk->entries[] = [$player->getUniqueId(), $player->getId(), $player->getDisplayName(), $player->getSkinId(), $player->getSkinData()];
}

View File

@ -27,12 +27,18 @@ namespace pocketmine\command;
use pocketmine\event\TextContainer;
use pocketmine\event\TimingsHandler;
use pocketmine\event\TranslationContainer;
use pocketmine\Player;
use pocketmine\Server;
use pocketmine\utils\TextFormat;
abstract class Command{
/** @var \stdClass */
private static $defaultDataTemplate = null;
/** @var string */
private $name;
/** @var \stdClass */
protected $commandData = null;
/** @var string */
private $nextLabel;
@ -75,16 +81,49 @@ abstract class Command{
* @param string[] $aliases
*/
public function __construct($name, $description = "", $usageMessage = null, array $aliases = []){
$this->name = $name;
$this->nextLabel = $name;
$this->label = $name;
$this->description = $description;
$this->commandData = self::generateDefaultData();
$this->name = $this->nextLabel = $this->label = $name;
$this->setDescription($description);
$this->usageMessage = $usageMessage === null ? "/" . $name : $usageMessage;
$this->aliases = $aliases;
$this->activeAliases = (array) $aliases;
$this->setAliases($aliases);
$this->timings = new TimingsHandler("** Command: " . $name);
}
/**
* Returns an \stdClass containing command data
*
* @return \stdClass
*/
public function getDefaultCommandData() : \stdClass{
return $this->commandData;
}
/**
* Generates modified command data for the specified player
* for AvailableCommandsPacket.
*
* @param Player $player
*
* @return \stdClass|null
*/
public function generateCustomCommandData(Player $player){
if(!$this->testPermission($player)){
return null;
}
$customData = clone $this->commandData;
$customData->aliases = $this->getAliases();
foreach($customData->overloads as &$overload){
if(($p = @$overload->pocketminePermission) !== null and !$player->hasPermission($p)){
unset($overload);
}
}
return $customData;
}
public function getOverloads(): \stdClass{
return $this->commandData->overloads;
}
/**
* @param CommandSender $sender
* @param string $commandLabel
@ -105,14 +144,19 @@ abstract class Command{
* @return string
*/
public function getPermission(){
return $this->permission;
return $this->commandData->pocketminePermission ?? null;
}
/**
* @param string|null $permission
*/
public function setPermission($permission){
$this->permission = $permission;
if($permission !== null){
$this->commandData->pocketminePermission = $permission;
}else{
unset($this->commandData->pocketminePermission);
}
}
/**
@ -128,7 +172,7 @@ abstract class Command{
if($this->permissionMessage === null){
$target->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.permission"));
}elseif($this->permissionMessage !== ""){
$target->sendMessage(str_replace("<permission>", $this->permission, $this->permissionMessage));
$target->sendMessage(str_replace("<permission>", $this->getPermission(), $this->permissionMessage));
}
return false;
@ -140,11 +184,11 @@ abstract class Command{
* @return bool
*/
public function testPermissionSilent(CommandSender $target){
if($this->permission === null or $this->permission === ""){
if(($perm = $this->getPermission()) === null or $perm === ""){
return true;
}
foreach(explode(";", $this->permission) as $permission){
foreach(explode(";", $perm) as $permission){
if($target->hasPermission($permission)){
return true;
}
@ -197,7 +241,7 @@ abstract class Command{
public function unregister(CommandMap $commandMap){
if($this->allowChangesFrom($commandMap)){
$this->commandMap = null;
$this->activeAliases = $this->aliases;
$this->activeAliases = $this->commandData->aliases;
$this->label = $this->nextLabel;
return true;
@ -240,7 +284,7 @@ abstract class Command{
* @return string
*/
public function getDescription(){
return $this->description;
return $this->commandData->description;
}
/**
@ -254,7 +298,7 @@ abstract class Command{
* @param string[] $aliases
*/
public function setAliases(array $aliases){
$this->aliases = $aliases;
$this->commandData->aliases = $aliases;
if(!$this->isRegistered()){
$this->activeAliases = (array) $aliases;
}
@ -264,7 +308,7 @@ abstract class Command{
* @param string $description
*/
public function setDescription($description){
$this->description = $description;
$this->commandData->description = $description;
}
/**
@ -281,6 +325,13 @@ abstract class Command{
$this->usageMessage = $usage;
}
public static final function generateDefaultData() : \stdClass{
if(self::$defaultDataTemplate === null){
self::$defaultDataTemplate = json_decode(file_get_contents(Server::getInstance()->getFilePath() . "src/pocketmine/resources/command_default.json"));
}
return clone self::$defaultDataTemplate;
}
/**
* @param CommandSender $source
* @param string $message

View File

@ -23,9 +23,5 @@ namespace pocketmine\entity;
interface Ageable{
const DATA_AGEABLE_FLAGS = 14;
const DATA_FLAG_BABY = 0;
public function isBaby();
}

View File

@ -24,14 +24,7 @@ namespace pocketmine\entity;
abstract class Animal extends Creature implements Ageable{
public function initEntity(){
parent::initEntity();
if($this->getDataProperty(self::DATA_AGEABLE_FLAGS) === null){
$this->setDataProperty(self::DATA_AGEABLE_FLAGS, self::DATA_TYPE_BYTE, 0);
}
}
public function isBaby(){
return $this->getDataFlag(self::DATA_AGEABLE_FLAGS, self::DATA_FLAG_BABY);
return $this->getDataFlag(self::DATA_FLAGS, self::DATA_FLAG_BABY);
}
}

View File

@ -50,17 +50,18 @@ class Attribute{
protected static $attributes = [];
public static function init(){
self::addAttribute(self::ABSORPTION, "generic.absorption", 0.00, 340282346638528859811704183484516925440.00, 0.00);
self::addAttribute(self::SATURATION, "player.saturation", 0.00, 20.00, 5.00);
self::addAttribute(self::EXHAUSTION, "player.exhaustion", 0.00, 5.00, 0.41);
self::addAttribute(self::KNOCKBACK_RESISTANCE, "generic.knockbackResistance", 0.00, 1.00, 0.00);
self::addAttribute(self::HEALTH, "generic.health", 0.00, 20.00, 20.00);
self::addAttribute(self::MOVEMENT_SPEED, "generic.movementSpeed", 0.00, 340282346638528859811704183484516925440.00, 0.10);
self::addAttribute(self::FOLLOW_RANGE, "generic.followRange", 0.00, 2048.00, 16.00, false);
self::addAttribute(self::HUNGER, "player.hunger", 0.00, 20.00, 20.00);
self::addAttribute(self::ATTACK_DAMAGE, "generic.attackDamage", 0.00, 340282346638528859811704183484516925440.00, 1.00, false);
self::addAttribute(self::EXPERIENCE_LEVEL, "player.level", 0.00, 24791.00, 0.00);
self::addAttribute(self::EXPERIENCE, "player.experience", 0.00, 1.00, 0.00);
self::addAttribute(self::ABSORPTION, "minecraft:absorption", 0.00, 340282346638528859811704183484516925440.00, 0.00);
self::addAttribute(self::SATURATION, "minecraft:player.saturation", 0.00, 20.00, 5.00);
self::addAttribute(self::EXHAUSTION, "minecraft:player.exhaustion", 0.00, 5.00, 0.41);
self::addAttribute(self::KNOCKBACK_RESISTANCE, "minecraft:knockback_resistance", 0.00, 1.00, 0.00);
self::addAttribute(self::HEALTH, "minecraft:health", 0.00, 20.00, 20.00);
self::addAttribute(self::MOVEMENT_SPEED, "minecraft:movement", 0.00, 340282346638528859811704183484516925440.00, 0.10);
self::addAttribute(self::FOLLOW_RANGE, "minecraft:follow_range", 0.00, 2048.00, 16.00, false);
self::addAttribute(self::HUNGER, "minecraft:player.hunger", 0.00, 20.00, 20.00);
self::addAttribute(self::ATTACK_DAMAGE, "minecraft:attack_damage", 0.00, 340282346638528859811704183484516925440.00, 1.00, false);
self::addAttribute(self::EXPERIENCE_LEVEL, "minecraft:player.level", 0.00, 24791.00, 0.00);
self::addAttribute(self::EXPERIENCE, "minecraft:player.experience", 0.00, 1.00, 0.00);
//TODO: minecraft:luck (for fishing?)
}
/**

View File

@ -38,6 +38,10 @@ class AttributeMap implements \ArrayAccess{
return $this->attributes[$id] ?? null;
}
public function getAll(): array{
return $this->attributes;
}
/**
* @return Attribute[]
*/

View File

@ -269,7 +269,7 @@ class Effect{
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);
$entity->setNameTagVisible(false);
}elseif($this->id === Effect::SPEED){
$attr = $entity->getAttributeMap()->getAttribute(Attribute::MOVEMENT_SPEED);
if($modify and $oldEffect !== null){
@ -303,7 +303,7 @@ class Effect{
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);
$entity->setNameTagVisible(true);
}elseif($this->id === Effect::SPEED){
$attr = $entity->getAttributeMap()->getAttribute(Attribute::MOVEMENT_SPEED);
$attr->setValue($attr->getValue() / (1 + 0.2 * $this->amplifier));

View File

@ -62,10 +62,8 @@ use pocketmine\Server;
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;
@ -74,16 +72,42 @@ abstract class Entity extends Location implements Metadatable{
const DATA_TYPE_SLOT = 5;
const DATA_TYPE_POS = 6;
const DATA_TYPE_LONG = 7;
const DATA_TYPE_VECTOR3F = 8;
const DATA_FLAGS = 0;
const DATA_AIR = 1;
const DATA_NAMETAG = 2;
const DATA_SHOW_NAMETAG = 3;
const DATA_SILENT = 4;
const DATA_POTION_COLOR = 7;
const DATA_POTION_AMBIENT = 8;
const DATA_NO_AI = 15;
const DATA_LINKED_EID = 23;
//1 (int)
const DATA_VARIANT = 2; //int
const DATA_COLOUR = 3; //byte
const DATA_NAMETAG = 4; //string
const DATA_OWNER_EID = 5; //long
const DATA_AIR = 7; //short
const DATA_POTION_COLOR = 8; //int (ARGB!)
const DATA_POTION_AMBIENT = 9; //byte
/* 27 (byte) player-specific flags
* 28 (int) player "index"?
* 29 (block coords) bed position */
const DATA_LEAD_HOLDER_EID = 38; //long
const DATA_SCALE = 39; //float
const DATA_INTERACTIVE_TAG = 40; //string (button text)
/* 41 (long) */
const DATA_URL_TAG = 43; //string
const DATA_MAX_AIR = 44; //short
const DATA_MARK_VARIANT = 45; //int
/* 46 (byte)
* 47 (int)
* 48 (int)
* 49 (long)
* 50 (long)
* 51 (long)
* 52 (short) */
const DATA_BOUNDING_BOX_WIDTH = 53; //float
const DATA_BOUNDING_BOX_HEIGHT = 54; //float
/* 56 (vector3f)
* 57 (byte)
* 58 (float)
* 59 (float) */
const DATA_FLAG_ONFIRE = 0;
@ -92,7 +116,33 @@ abstract class Entity extends Location implements Metadatable{
const DATA_FLAG_SPRINTING = 3;
const DATA_FLAG_ACTION = 4;
const DATA_FLAG_INVISIBLE = 5;
const DATA_FLAG_TEMPTED = 6; //???
const DATA_FLAG_INLOVE = 7;
const DATA_FLAG_SADDLED = 8;
const DATA_FLAG_POWERED = 9;
const DATA_FLAG_IGNITED = 10; //for creepers?
const DATA_FLAG_BABY = 11;
const DATA_FLAG_CONVERTING = 12; //???
const DATA_FLAG_CRITICAL = 13;
const DATA_FLAG_CAN_SHOW_NAMETAG = 14;
const DATA_FLAG_ALWAYS_SHOW_NAMETAG = 15;
const DATA_FLAG_IMMOBILE = 16, DATA_FLAG_NO_AI = 16;
const DATA_FLAG_SILENT = 17;
const DATA_FLAG_WALLCLIMBING = 18;
const DATA_FLAG_RESTING = 19; //for bats?
const DATA_FLAG_SITTING = 20;
const DATA_FLAG_ANGRY = 21;
const DATA_FLAG_INTERESTED = 22; //for mobs following players with food?
const DATA_FLAG_CHARGED = 23;
const DATA_FLAG_TAMED = 24;
const DATA_FLAG_LEASHED = 25;
const DATA_FLAG_SHEARED = 26; //for sheep
const DATA_FLAG_FALL_FLYING = 27; //???
const DATA_FLAG_ELDER = 28; //elder guardian
const DATA_FLAG_MOVING = 29;
const DATA_FLAG_BREATHING = 30; //hides bubbles if true
const DATA_FLAG_CHESTED = 31; //for mules?
const DATA_FLAG_STACKABLE = 32; //???
public static $entityCount = 1;
/** @var Entity[] */
@ -111,13 +161,12 @@ abstract class Entity extends Location implements Metadatable{
protected $dataFlags = 0;
protected $dataProperties = [
self::DATA_FLAGS => [self::DATA_TYPE_BYTE, 0],
self::DATA_AIR => [self::DATA_TYPE_SHORT, 300],
self::DATA_FLAGS => [self::DATA_TYPE_LONG, 0],
self::DATA_AIR => [self::DATA_TYPE_SHORT, 400],
self::DATA_MAX_AIR => [self::DATA_TYPE_SHORT, 400],
self::DATA_NAMETAG => [self::DATA_TYPE_STRING, ""],
self::DATA_SHOW_NAMETAG => [self::DATA_TYPE_BYTE, 1],
self::DATA_SILENT => [self::DATA_TYPE_BYTE, 0],
self::DATA_NO_AI => [self::DATA_TYPE_BYTE, 0],
self::DATA_LINKED_EID => [self::DATA_TYPE_LONG, -1],
self::DATA_LEAD_HOLDER_EID => [self::DATA_TYPE_LONG, -1],
self::DATA_SCALE => [self::DATA_TYPE_FLOAT, 1],
];
public $passenger = null;
@ -290,9 +339,17 @@ abstract class Entity extends Location implements Metadatable{
* @return bool
*/
public function isNameTagVisible(){
return $this->getDataProperty(self::DATA_SHOW_NAMETAG) > 0;
return $this->getDataFlag(self::DATA_FLAGS, self::DATA_FLAG_CAN_SHOW_NAMETAG);
}
/**
* @return bool
*/
public function isNameTagAlwaysVisible(){
return $this->getDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ALWAYS_SHOW_NAMETAG);
}
/**
* @param string $name
*/
@ -304,7 +361,14 @@ abstract class Entity extends Location implements Metadatable{
* @param bool $value
*/
public function setNameTagVisible($value = true){
$this->setDataProperty(self::DATA_SHOW_NAMETAG, self::DATA_TYPE_BYTE, $value ? 1 : 0);
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_CAN_SHOW_NAMETAG, $value);
}
/**
* @param bool $value
*/
public function setNameTagAlwaysVisible($value = true){
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ALWAYS_SHOW_NAMETAG, $value);
}
public function isSneaking(){
@ -327,6 +391,14 @@ abstract class Entity extends Location implements Metadatable{
}
}
public function isImmobile() : bool{
return $this->getDataFlag(self::DATA_FLAGS, self::DATA_FLAG_IMMOBILE);
}
public function setImmobile($value = true) : bool{
return $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_IMMOBILE, $value);
}
/**
* @return Effect[]
*/
@ -383,6 +455,7 @@ abstract class Entity extends Location implements Metadatable{
}
protected function recalculateEffectColor(){
//TODO: add transparency values
$color = [0, 0, 0]; //RGB
$count = 0;
$ambient = true;
@ -574,14 +647,23 @@ abstract class Entity extends Location implements Metadatable{
* @param array $data Properly formatted entity data, defaults to everything
*/
public function sendData($player, array $data = null){
if(!is_array($player)){
$player = [$player];
}
$pk = new SetEntityDataPacket();
$pk->eid = ($player === $this ? 0 : $this->getId());
$pk->eid = $this->getId();
$pk->metadata = $data === null ? $this->dataProperties : $data;
if(!is_array($player)){
$player->dataPacket($pk);
}else{
Server::broadcastPacket($player, $pk);
foreach($player as $p){
if($p === $this){
continue;
}
$p->dataPacket(clone $pk);
}
if($this instanceof Player){
$pk->eid = 0;
$this->dataPacket($pk);
}
}
@ -1567,7 +1649,7 @@ abstract class Entity extends Location implements Metadatable{
* @param bool $value
* @param int $type
*/
public function setDataFlag($propertyId, $id, $value = true, $type = self::DATA_TYPE_BYTE){
public function setDataFlag($propertyId, $id, $value = true, $type = self::DATA_TYPE_LONG){
if($this->getDataFlag($propertyId, $id) !== $value){
$flags = (int) $this->getDataProperty($propertyId);
$flags ^= 1 << $id;

View File

@ -41,12 +41,13 @@ use pocketmine\Player;
use pocketmine\utils\UUID;
class Human extends Creature implements ProjectileSource, InventoryHolder{
const DATA_PLAYER_FLAG_SLEEP = 1;
const DATA_PLAYER_FLAG_DEAD = 2;
const DATA_PLAYER_FLAG_DEAD = 2; //TODO: CHECK
const DATA_PLAYER_FLAGS = 16;
const DATA_PLAYER_BED_POSITION = 17;
const DATA_PLAYER_FLAGS = 27;
const DATA_PLAYER_BED_POSITION = 29;
/** @var PlayerInventory */
protected $inventory;
@ -253,7 +254,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
protected function initEntity(){
$this->setDataFlag(self::DATA_PLAYER_FLAGS, self::DATA_PLAYER_FLAG_SLEEP, false);
$this->setDataFlag(self::DATA_PLAYER_FLAGS, self::DATA_PLAYER_FLAG_SLEEP, false, self::DATA_TYPE_BYTE);
$this->setDataProperty(self::DATA_PLAYER_BED_POSITION, self::DATA_TYPE_POS, [0, 0, 0], false);
$this->inventory = new PlayerInventory($this);

View File

@ -178,6 +178,7 @@ abstract class Living extends Entity implements Damageable{
public function entityBaseTick($tickDiff = 1){
Timings::$timerLivingEntityBaseTick->startTiming();
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_BREATHING, !$this->isInsideOfWater());
$hasUpdate = parent::entityBaseTick($tickDiff);
@ -190,7 +191,7 @@ abstract class Living extends Entity implements Damageable{
if(!$this->hasEffect(Effect::WATER_BREATHING) and $this->isInsideOfWater()){
if($this instanceof WaterAnimal){
$this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, 300);
$this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, 400);
}else{
$hasUpdate = true;
$airTicks = $this->getDataProperty(self::DATA_AIR) - $tickDiff;
@ -214,7 +215,7 @@ abstract class Living extends Entity implements Damageable{
}
$this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, $airTicks);
}else{
$this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, 300);
$this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, 400);
}
}
}

View File

@ -82,6 +82,6 @@ class Villager extends Creature implements NPC, Ageable{
}
public function isBaby(){
return $this->getDataFlag(self::DATA_AGEABLE_FLAGS, self::DATA_FLAG_BABY);
return $this->getDataFlag(self::DATA_FLAGS, self::DATA_FLAG_BABY);
}
}

View File

@ -22,14 +22,8 @@
namespace pocketmine\entity;
abstract class WaterAnimal extends Creature implements Ageable{
public function initEntity(){
parent::initEntity();
if($this->getDataProperty(self::DATA_AGEABLE_FLAGS) === null){
$this->setDataProperty(self::DATA_AGEABLE_FLAGS, self::DATA_TYPE_BYTE, 0);
}
}
public function isBaby(){
return $this->getDataFlag(self::DATA_AGEABLE_FLAGS, self::DATA_FLAG_BABY);
return $this->getDataFlag(self::DATA_FLAGS, self::DATA_FLAG_BABY);
}
}

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\event\player;
use pocketmine\event\Cancellable;
use pocketmine\Player;
class PlayerToggleFlightEvent extends PlayerEvent implements Cancellable{
public static $handlerList = null;
/** @var bool */
protected $isFlying;
public function __construct(Player $player, $isFlying){
$this->player = $player;
$this->isFlying = (bool) $isFlying;
}
public function isFlying(){
return $this->isFlying;
}
}

View File

@ -77,7 +77,7 @@ class CraftingManager{
case 2:
$result = $recipe["Result"];
$resultItem = Item::get($result["ID"], $result["Damage"], $result["Count"]);
$this->registerRecipe(new FurnaceRecipe($resultItem, Item::get($recipe["Ingredients"], 0, 1)));
$this->registerRecipe(new FurnaceRecipe($resultItem, Item::get($recipe["Ingredients"], null, 1)));
break;
case 3:
$result = $recipe["Result"];

View File

@ -227,8 +227,15 @@ class Item implements ItemIds{
$creativeItems = new Config(Server::getInstance()->getFilePath() . "src/pocketmine/resources/creativeitems.json", Config::JSON, []);
foreach($creativeItems->getAll() as $item){
self::addCreativeItem(Item::get($item["ID"], $item["Damage"]));
foreach($creativeItems->getAll() as $data){
$item = Item::get($data["id"], $data["damage"]);
if($item->getName() === "Unknown"){
continue;
}
if(isset($data["nbt"])){
$item->setNamedTag(NBT::parseJson(json_encode($data["nbt"])));
}
self::addCreativeItem($item);
}
}
@ -241,7 +248,7 @@ class Item implements ItemIds{
}
public static function addCreativeItem(Item $item){
Item::$creative[] = Item::get($item->getId(), $item->getDamage());
Item::$creative[] = clone $item;
}
public static function removeCreativeItem(Item $item){

View File

@ -723,9 +723,14 @@ class Level implements ChunkManager, Metadatable{
foreach($this->motionToSend as $index => $entry){
Level::getXZ($index, $chunkX, $chunkZ);
$pk = new SetEntityMotionPacket();
$pk->entities = $entry;
$this->addChunkPacket($chunkX, $chunkZ, $pk);
foreach($entry as $entity){
$pk = new SetEntityMotionPacket();
$pk->eid = $entity[0];
$pk->motionX = $entity[1];
$pk->motionY = $entity[2];
$pk->motionZ = $entity[3];
$this->addChunkPacket($chunkX, $chunkZ, $pk);
}
}
$this->motionToSend = [];

View File

@ -86,7 +86,7 @@ class Anvil extends McRegion{
}
}
$nbt->setData($list);
$tiles = $nbt->write();
$tiles = $nbt->write(true);
}
$extraData = new BinaryStream();

View File

@ -49,7 +49,7 @@ class ChunkRequestTask extends AsyncTask{
foreach($chunk->getTiles() as $tile){
if($tile instanceof Spawnable){
$nbt->setData($tile->getSpawnCompound());
$tiles .= $nbt->write();
$tiles .= $nbt->write(true);
}
}

View File

@ -129,7 +129,7 @@ class McRegion extends BaseLevelProvider{
}
}
$nbt->setData($list);
$tiles = $nbt->write();
$tiles = $nbt->write(true);
}
$extraData = new BinaryStream();

View File

@ -89,11 +89,14 @@ class FloatingTextParticle extends Particle{
$pk->pitch = 0;
$pk->item = 0;
$pk->meta = 0;
$flags = 0;
$flags |= 1 << Entity::DATA_FLAG_INVISIBLE;
$flags |= 1 << Entity::DATA_FLAG_CAN_SHOW_NAMETAG;
$flags |= 1 << Entity::DATA_FLAG_ALWAYS_SHOW_NAMETAG;
$flags |= 1 << Entity::DATA_FLAG_IMMOBILE;
$pk->metadata = [
Entity::DATA_FLAGS => [Entity::DATA_TYPE_BYTE, 1 << Entity::DATA_FLAG_INVISIBLE],
Entity::DATA_FLAGS => [Entity::DATA_TYPE_LONG, $flags],
Entity::DATA_NAMETAG => [Entity::DATA_TYPE_STRING, $this->title . ($this->text !== "" ? "\n" . $this->text : "")],
Entity::DATA_SHOW_NAMETAG => [Entity::DATA_TYPE_BYTE, 1],
Entity::DATA_NO_AI => [Entity::DATA_TYPE_BYTE, 1]
];
$p[] = $pk;

View File

@ -463,14 +463,14 @@ class NBT{
$this->endianness = $endianness & 0x01;
}
public function read($buffer, $doMultiple = false){
public function read($buffer, $doMultiple = false, bool $network = false){
$this->offset = 0;
$this->buffer = $buffer;
$this->data = $this->readTag();
$this->data = $this->readTag($network);
if($doMultiple and $this->offset < strlen($this->buffer)){
$this->data = [$this->data];
do{
$this->data[] = $this->readTag();
$this->data[] = $this->readTag($network);
}while($this->offset < strlen($this->buffer));
}
$this->buffer = "";
@ -480,20 +480,25 @@ class NBT{
$this->read(zlib_decode($buffer));
}
public function readNetworkCompressed($buffer, $compression = ZLIB_ENCODING_GZIP){
$this->read(zlib_decode($buffer), false, true);
}
/**
* @return string|bool
*/
public function write(){
public function write(bool $network = false){
$this->offset = 0;
$this->buffer = "";
if($this->data instanceof CompoundTag){
$this->writeTag($this->data);
$this->writeTag($this->data, $network);
return $this->buffer;
}elseif(is_array($this->data)){
foreach($this->data as $tag){
$this->writeTag($tag);
$this->writeTag($tag, $network);
}
return $this->buffer;
}
@ -509,51 +514,64 @@ class NBT{
return false;
}
public function readTag(){
switch($this->getByte()){
public function writeNetworkCompressed($compression = ZLIB_ENCODING_GZIP, $level = 7){
if(($write = $this->write(true)) !== false){
return zlib_encode($write, $compression, $level);
}
return false;
}
public function readTag(bool $network = false){
if($this->feof()){
$tagType = -1; //prevent crashes for empty tags
}else{
$tagType = $this->getByte();
}
switch($tagType){
case NBT::TAG_Byte:
$tag = new ByteTag($this->getString());
$tag->read($this);
$tag = new ByteTag($this->getString($network));
$tag->read($this, $network);
break;
case NBT::TAG_Short:
$tag = new ShortTag($this->getString());
$tag->read($this);
$tag = new ShortTag($this->getString($network));
$tag->read($this, $network);
break;
case NBT::TAG_Int:
$tag = new IntTag($this->getString());
$tag->read($this);
$tag = new IntTag($this->getString($network));
$tag->read($this, $network);
break;
case NBT::TAG_Long:
$tag = new LongTag($this->getString());
$tag->read($this);
$tag = new LongTag($this->getString($network));
$tag->read($this, $network);
break;
case NBT::TAG_Float:
$tag = new FloatTag($this->getString());
$tag->read($this);
$tag = new FloatTag($this->getString($network));
$tag->read($this, $network);
break;
case NBT::TAG_Double:
$tag = new DoubleTag($this->getString());
$tag->read($this);
$tag = new DoubleTag($this->getString($network));
$tag->read($this, $network);
break;
case NBT::TAG_ByteArray:
$tag = new ByteArrayTag($this->getString());
$tag->read($this);
$tag = new ByteArrayTag($this->getString($network));
$tag->read($this, $network);
break;
case NBT::TAG_String:
$tag = new StringTag($this->getString());
$tag->read($this);
$tag = new StringTag($this->getString($network));
$tag->read($this, $network);
break;
case NBT::TAG_List:
$tag = new ListTag($this->getString());
$tag->read($this);
$tag = new ListTag($this->getString($network));
$tag->read($this, $network);
break;
case NBT::TAG_Compound:
$tag = new CompoundTag($this->getString());
$tag->read($this);
$tag = new CompoundTag($this->getString($network));
$tag->read($this, $network);
break;
case NBT::TAG_IntArray:
$tag = new IntArrayTag($this->getString());
$tag->read($this);
$tag = new IntArrayTag($this->getString($network));
$tag->read($this, $network);
break;
case NBT::TAG_End: //No named tag
@ -564,12 +582,12 @@ class NBT{
return $tag;
}
public function writeTag(Tag $tag){
public function writeTag(Tag $tag, bool $network = false){
$this->putByte($tag->getType());
if($tag instanceof NamedTAG){
$this->putString($tag->getName());
$this->putString($tag->getName(), $network);
}
$tag->write($this);
$tag->write($this, $network);
}
public function getByte(){
@ -588,12 +606,19 @@ class NBT{
$this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeShort($v) : Binary::writeLShort($v);
}
public function getInt(){
public function getInt(bool $network = false){
if($network === true){
return Binary::readVarInt($this);
}
return $this->endianness === self::BIG_ENDIAN ? Binary::readInt($this->get(4)) : Binary::readLInt($this->get(4));
}
public function putInt($v){
$this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeInt($v) : Binary::writeLInt($v);
public function putInt($v, bool $network = false){
if($network === true){
$this->buffer .= Binary::writeVarInt($v);
}else{
$this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeInt($v) : Binary::writeLInt($v);
}
}
public function getLong(){
@ -620,12 +645,17 @@ class NBT{
$this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeDouble($v) : Binary::writeLDouble($v);
}
public function getString(){
return $this->get($this->getShort());
public function getString(bool $network = false){
$len = $network ? $this->getByte() : $this->getShort();
return $this->get($len);
}
public function putString($v){
$this->putShort(strlen($v));
public function putString($v, bool $network = false){
if($network === true){
$this->putByte(strlen($v));
}else{
$this->putShort(strlen($v));
}
$this->buffer .= $v;
}

View File

@ -31,12 +31,12 @@ class ByteArrayTag extends NamedTag{
return NBT::TAG_ByteArray;
}
public function read(NBT $nbt){
$this->value = $nbt->get($nbt->getInt());
public function read(NBT $nbt, bool $network = false){
$this->value = $nbt->get($nbt->getInt($network));
}
public function write(NBT $nbt){
$nbt->putInt(strlen($this->value));
public function write(NBT $nbt, bool $network = false){
$nbt->putInt(strlen($this->value), $network);
$nbt->put($this->value);
}
}

View File

@ -31,11 +31,11 @@ class ByteTag extends NamedTag{
return NBT::TAG_Byte;
}
public function read(NBT $nbt){
public function read(NBT $nbt, bool $network = false){
$this->value = $nbt->getByte();
}
public function write(NBT $nbt){
public function write(NBT $nbt, bool $network = false){
$nbt->putByte($this->value);
}
}

View File

@ -83,23 +83,23 @@ class CompoundTag extends NamedTag implements \ArrayAccess{
return NBT::TAG_Compound;
}
public function read(NBT $nbt){
public function read(NBT $nbt, bool $network = false){
$this->value = [];
do{
$tag = $nbt->readTag();
$tag = $nbt->readTag($network);
if($tag instanceof NamedTag and $tag->getName() !== ""){
$this->{$tag->getName()} = $tag;
}
}while(!($tag instanceof EndTag) and !$nbt->feof());
}
public function write(NBT $nbt){
public function write(NBT $nbt, bool $network = false){
foreach($this as $tag){
if($tag instanceof Tag and !($tag instanceof EndTag)){
$nbt->writeTag($tag);
$nbt->writeTag($tag, $network);
}
}
$nbt->writeTag(new EndTag);
$nbt->writeTag(new EndTag, $network);
}
public function __toString(){

View File

@ -31,11 +31,11 @@ class DoubleTag extends NamedTag{
return NBT::TAG_Double;
}
public function read(NBT $nbt){
public function read(NBT $nbt, bool $network = false){
$this->value = $nbt->getDouble();
}
public function write(NBT $nbt){
public function write(NBT $nbt, bool $network = false){
$nbt->putDouble($this->value);
}
}

View File

@ -29,11 +29,11 @@ class EndTag extends Tag{
return NBT::TAG_End;
}
public function read(NBT $nbt){
public function read(NBT $nbt, bool $network = false){
}
public function write(NBT $nbt){
public function write(NBT $nbt, bool $network = false){
}
}

View File

@ -31,11 +31,11 @@ class FloatTag extends NamedTag{
return NBT::TAG_Float;
}
public function read(NBT $nbt){
public function read(NBT $nbt, bool $network = false){
$this->value = $nbt->getFloat();
}
public function write(NBT $nbt){
public function write(NBT $nbt, bool $network = false){
$nbt->putFloat($this->value);
}
}

View File

@ -31,13 +31,13 @@ class IntArrayTag extends NamedTag{
return NBT::TAG_IntArray;
}
public function read(NBT $nbt){
$size = $nbt->getInt();
public function read(NBT $nbt, bool $network = false){
$size = $nbt->getInt($network);
$this->value = array_values(unpack($nbt->endianness === NBT::LITTLE_ENDIAN ? "V*" : "N*", $nbt->get($size * 4)));
}
public function write(NBT $nbt){
$nbt->putInt(count($this->value));
public function write(NBT $nbt, bool $network = false){
$nbt->putInt(count($this->value), $network);
$nbt->put(pack($nbt->endianness === NBT::LITTLE_ENDIAN ? "V*" : "N*", ...$this->value));
}

View File

@ -31,11 +31,11 @@ class IntTag extends NamedTag{
return NBT::TAG_Int;
}
public function read(NBT $nbt){
$this->value = $nbt->getInt();
public function read(NBT $nbt, bool $network = false){
$this->value = $nbt->getInt($network);
}
public function write(NBT $nbt){
$nbt->putInt($this->value);
public function write(NBT $nbt, bool $network = false){
$nbt->putInt($this->value, $network);
}
}

View File

@ -114,72 +114,72 @@ class ListTag extends NamedTag implements \ArrayAccess, \Countable{
return $this->tagType;
}
public function read(NBT $nbt){
public function read(NBT $nbt, bool $network = false){
$this->value = [];
$this->tagType = $nbt->getByte();
$size = $nbt->getInt();
$size = $nbt->getInt($network);
for($i = 0; $i < $size and !$nbt->feof(); ++$i){
switch($this->tagType){
case NBT::TAG_Byte:
$tag = new ByteTag("");
$tag->read($nbt);
$tag->read($nbt, $network);
$this->{$i} = $tag;
break;
case NBT::TAG_Short:
$tag = new ShortTag("");
$tag->read($nbt);
$tag->read($nbt, $network);
$this->{$i} = $tag;
break;
case NBT::TAG_Int:
$tag = new IntTag("");
$tag->read($nbt);
$tag->read($nbt, $network);
$this->{$i} = $tag;
break;
case NBT::TAG_Long:
$tag = new LongTag("");
$tag->read($nbt);
$tag->read($nbt, $network);
$this->{$i} = $tag;
break;
case NBT::TAG_Float:
$tag = new FloatTag("");
$tag->read($nbt);
$tag->read($nbt, $network);
$this->{$i} = $tag;
break;
case NBT::TAG_Double:
$tag = new DoubleTag("");
$tag->read($nbt);
$tag->read($nbt, $network);
$this->{$i} = $tag;
break;
case NBT::TAG_ByteArray:
$tag = new ByteArrayTag("");
$tag->read($nbt);
$tag->read($nbt, $network);
$this->{$i} = $tag;
break;
case NBT::TAG_String:
$tag = new StringTag("");
$tag->read($nbt);
$tag->read($nbt, $network);
$this->{$i} = $tag;
break;
case NBT::TAG_List:
$tag = new TagEnum("");
$tag->read($nbt);
$tag->read($nbt, $network);
$this->{$i} = $tag;
break;
case NBT::TAG_Compound:
$tag = new CompoundTag("");
$tag->read($nbt);
$tag->read($nbt, $network);
$this->{$i} = $tag;
break;
case NBT::TAG_IntArray:
$tag = new IntArrayTag("");
$tag->read($nbt);
$tag->read($nbt, $network);
$this->{$i} = $tag;
break;
}
}
}
public function write(NBT $nbt){
public function write(NBT $nbt, bool $network = false){
if(!isset($this->tagType)){
$id = null;
foreach($this as $tag){
@ -205,7 +205,7 @@ class ListTag extends NamedTag implements \ArrayAccess, \Countable{
}
$nbt->putInt(count($tags));
foreach($tags as $tag){
$tag->write($nbt);
$tag->write($nbt, $network);
}
}

View File

@ -31,11 +31,13 @@ class LongTag extends NamedTag{
return NBT::TAG_Long;
}
public function read(NBT $nbt){
//TODO: check if this also changed to varint
public function read(NBT $nbt, bool $network = false){
$this->value = $nbt->getLong();
}
public function write(NBT $nbt){
public function write(NBT $nbt, bool $network = false){
$nbt->putLong($this->value);
}
}

View File

@ -31,11 +31,11 @@ class ShortTag extends NamedTag{
return NBT::TAG_Short;
}
public function read(NBT $nbt){
public function read(NBT $nbt, bool $network = false){
$this->value = $nbt->getShort();
}
public function write(NBT $nbt){
public function write(NBT $nbt, bool $network = false){
$nbt->putShort($this->value);
}
}

View File

@ -31,12 +31,11 @@ class StringTag extends NamedTag{
return NBT::TAG_String;
}
public function read(NBT $nbt){
$this->value = $nbt->get($nbt->getShort());
public function read(NBT $nbt, bool $network = false){
$this->value = $nbt->getString($network);
}
public function write(NBT $nbt){
$nbt->putShort(strlen($this->value));
$nbt->put($this->value);
public function write(NBT $nbt, bool $network = false){
$nbt->putString($this->value, $network);
}
}

View File

@ -40,9 +40,9 @@ abstract class Tag extends \stdClass{
$this->value = $value;
}
abstract public function write(NBT $nbt);
abstract public function write(NBT $nbt, bool $network = false);
abstract public function read(NBT $nbt);
abstract public function read(NBT $nbt, bool $network = false);
public function __toString(){
return (string) $this->value;

View File

@ -25,16 +25,20 @@
namespace pocketmine\network;
use pocketmine\network\protocol\AddEntityPacket;
use pocketmine\network\protocol\AddHangingEntityPacket;
use pocketmine\network\protocol\AddItemEntityPacket;
use pocketmine\network\protocol\AddItemPacket;
use pocketmine\network\protocol\AddPaintingPacket;
use pocketmine\network\protocol\AddPlayerPacket;
use pocketmine\network\protocol\AdventureSettingsPacket;
use pocketmine\network\protocol\AnimatePacket;
use pocketmine\network\protocol\AvailableCommandsPacket;
use pocketmine\network\protocol\BatchPacket;
use pocketmine\network\protocol\BlockEntityDataPacket;
use pocketmine\network\protocol\BlockEventPacket;
use pocketmine\network\protocol\ChangeDimensionPacket;
use pocketmine\network\protocol\ChunkRadiusUpdatedPacket;
use pocketmine\network\protocol\CommandStepPacket;
use pocketmine\network\protocol\ContainerClosePacket;
use pocketmine\network\protocol\ContainerOpenPacket;
use pocketmine\network\protocol\ContainerSetContentPacket;
@ -52,19 +56,27 @@ use pocketmine\network\protocol\HurtArmorPacket;
use pocketmine\network\protocol\Info as ProtocolInfo;
use pocketmine\network\protocol\Info;
use pocketmine\network\protocol\InteractPacket;
use pocketmine\network\protocol\InventoryActionPacket;
use pocketmine\network\protocol\ItemFrameDropItemPacket;
use pocketmine\network\protocol\LevelEventPacket;
use pocketmine\network\protocol\LevelSoundEventPacket;
use pocketmine\network\protocol\LoginPacket;
use pocketmine\network\protocol\MobArmorEquipmentPacket;
use pocketmine\network\protocol\MobEquipmentPacket;
use pocketmine\network\protocol\MoveEntityPacket;
use pocketmine\network\protocol\MovePlayerPacket;
use pocketmine\network\protocol\PlayerActionPacket;
use pocketmine\network\protocol\PlayerInputPacket;
use pocketmine\network\protocol\PlayerListPacket;
use pocketmine\network\protocol\PlayStatusPacket;
use pocketmine\network\protocol\RemoveBlockPacket;
use pocketmine\network\protocol\RemoveEntityPacket;
use pocketmine\network\protocol\ReplaceSelectedItemPacket;
use pocketmine\network\protocol\RequestChunkRadiusPacket;
use pocketmine\network\protocol\ResourcePackClientResponsePacket;
use pocketmine\network\protocol\ResourcePacksInfoPacket;
use pocketmine\network\protocol\RespawnPacket;
use pocketmine\network\protocol\SetCommandsEnabledPacket;
use pocketmine\network\protocol\SetDifficultyPacket;
use pocketmine\network\protocol\SetEntityDataPacket;
use pocketmine\network\protocol\SetEntityLinkPacket;
@ -73,6 +85,7 @@ use pocketmine\network\protocol\SetHealthPacket;
use pocketmine\network\protocol\SetPlayerGameTypePacket;
use pocketmine\network\protocol\SetSpawnPositionPacket;
use pocketmine\network\protocol\SetTimePacket;
use pocketmine\network\protocol\SpawnExperienceOrbPacket;
use pocketmine\network\protocol\StartGamePacket;
use pocketmine\network\protocol\TakeItemEntityPacket;
use pocketmine\network\protocol\TextPacket;
@ -81,6 +94,7 @@ use pocketmine\network\protocol\UseItemPacket;
use pocketmine\Player;
use pocketmine\Server;
use pocketmine\utils\Binary;
use pocketmine\utils\BinaryStream;
class Network{
@ -208,18 +222,25 @@ class Network{
}
public function processBatch(BatchPacket $packet, Player $p){
$str = zlib_decode($packet->payload, 1024 * 1024 * 64); //Max 64MB
$len = strlen($str);
$offset = 0;
try{
while($offset < $len){
$pkLen = Binary::readInt(substr($str, $offset, 4));
$offset += 4;
if(strlen($packet->payload) === 0){
//prevent zlib_decode errors for incorrectly-decoded packets
throw new \InvalidArgumentException("BatchPacket payload is empty or packet decode error");
}
$buf = substr($str, $offset, $pkLen);
$offset += $pkLen;
$str = zlib_decode($packet->payload, 1024 * 1024 * 64); //Max 64MB
$len = strlen($str);
if(($pk = $this->getPacket(ord($buf{0}))) !== null){ // #blameshoghi
if($len === 0){
throw new \InvalidStateException("Decoded BatchPacket payload is empty");
}
$stream = new BinaryStream($str);
while($stream->offset < $len){
$buf = $stream->getString();
if(($pk = $this->getPacket(ord($buf{0}))) !== null){
if($pk::NETWORK_ID === Info::BATCH_PACKET){
throw new \InvalidStateException("Invalid BatchPacket inside BatchPacket");
}
@ -227,11 +248,8 @@ class Network{
$pk->setBuffer($buf, 1);
$pk->decode();
assert($pk->feof(), "Still " . strlen(substr($pk->buffer, $pk->offset)) . " bytes unread in " . get_class($pk));
$p->handleDataPacket($pk);
if($pk->getOffset() <= 0){
return;
}
}
}
}catch(\Throwable $e){
@ -284,56 +302,69 @@ class Network{
private function registerPackets(){
$this->packetPool = new \SplFixedArray(256);
$this->registerPacket(ProtocolInfo::LOGIN_PACKET, LoginPacket::class);
$this->registerPacket(ProtocolInfo::PLAY_STATUS_PACKET, PlayStatusPacket::class);
$this->registerPacket(ProtocolInfo::DISCONNECT_PACKET, DisconnectPacket::class);
$this->registerPacket(ProtocolInfo::BATCH_PACKET, BatchPacket::class);
$this->registerPacket(ProtocolInfo::TEXT_PACKET, TextPacket::class);
$this->registerPacket(ProtocolInfo::SET_TIME_PACKET, SetTimePacket::class);
$this->registerPacket(ProtocolInfo::START_GAME_PACKET, StartGamePacket::class);
$this->registerPacket(ProtocolInfo::ADD_PLAYER_PACKET, AddPlayerPacket::class);
$this->registerPacket(ProtocolInfo::ADD_ENTITY_PACKET, AddEntityPacket::class);
$this->registerPacket(ProtocolInfo::REMOVE_ENTITY_PACKET, RemoveEntityPacket::class);
$this->registerPacket(ProtocolInfo::ADD_HANGING_ENTITY_PACKET, AddHangingEntityPacket::class);
$this->registerPacket(ProtocolInfo::ADD_ITEM_ENTITY_PACKET, AddItemEntityPacket::class);
$this->registerPacket(ProtocolInfo::TAKE_ITEM_ENTITY_PACKET, TakeItemEntityPacket::class);
$this->registerPacket(ProtocolInfo::MOVE_ENTITY_PACKET, MoveEntityPacket::class);
$this->registerPacket(ProtocolInfo::MOVE_PLAYER_PACKET, MovePlayerPacket::class);
$this->registerPacket(ProtocolInfo::REMOVE_BLOCK_PACKET, RemoveBlockPacket::class);
$this->registerPacket(ProtocolInfo::UPDATE_BLOCK_PACKET, UpdateBlockPacket::class);
$this->registerPacket(ProtocolInfo::ADD_ITEM_PACKET, AddItemPacket::class);
$this->registerPacket(ProtocolInfo::ADD_PAINTING_PACKET, AddPaintingPacket::class);
$this->registerPacket(ProtocolInfo::EXPLODE_PACKET, ExplodePacket::class);
$this->registerPacket(ProtocolInfo::LEVEL_EVENT_PACKET, LevelEventPacket::class);
$this->registerPacket(ProtocolInfo::BLOCK_EVENT_PACKET, BlockEventPacket::class);
$this->registerPacket(ProtocolInfo::ENTITY_EVENT_PACKET, EntityEventPacket::class);
$this->registerPacket(ProtocolInfo::MOB_EQUIPMENT_PACKET, MobEquipmentPacket::class);
$this->registerPacket(ProtocolInfo::MOB_ARMOR_EQUIPMENT_PACKET, MobArmorEquipmentPacket::class);
$this->registerPacket(ProtocolInfo::INTERACT_PACKET, InteractPacket::class);
$this->registerPacket(ProtocolInfo::USE_ITEM_PACKET, UseItemPacket::class);
$this->registerPacket(ProtocolInfo::PLAYER_ACTION_PACKET, PlayerActionPacket::class);
$this->registerPacket(ProtocolInfo::HURT_ARMOR_PACKET, HurtArmorPacket::class);
$this->registerPacket(ProtocolInfo::SET_ENTITY_DATA_PACKET, SetEntityDataPacket::class);
$this->registerPacket(ProtocolInfo::SET_ENTITY_MOTION_PACKET, SetEntityMotionPacket::class);
$this->registerPacket(ProtocolInfo::SET_ENTITY_LINK_PACKET, SetEntityLinkPacket::class);
$this->registerPacket(ProtocolInfo::SET_HEALTH_PACKET, SetHealthPacket::class);
$this->registerPacket(ProtocolInfo::SET_SPAWN_POSITION_PACKET, SetSpawnPositionPacket::class);
$this->registerPacket(ProtocolInfo::ADD_PLAYER_PACKET, AddPlayerPacket::class);
$this->registerPacket(ProtocolInfo::ADVENTURE_SETTINGS_PACKET, AdventureSettingsPacket::class);
$this->registerPacket(ProtocolInfo::ANIMATE_PACKET, AnimatePacket::class);
$this->registerPacket(ProtocolInfo::RESPAWN_PACKET, RespawnPacket::class);
$this->registerPacket(ProtocolInfo::DROP_ITEM_PACKET, DropItemPacket::class);
$this->registerPacket(ProtocolInfo::CONTAINER_OPEN_PACKET, ContainerOpenPacket::class);
$this->registerPacket(ProtocolInfo::AVAILABLE_COMMANDS_PACKET, AvailableCommandsPacket::class);
$this->registerPacket(ProtocolInfo::BATCH_PACKET, BatchPacket::class);
$this->registerPacket(ProtocolInfo::BLOCK_ENTITY_DATA_PACKET, BlockEntityDataPacket::class);
$this->registerPacket(ProtocolInfo::BLOCK_EVENT_PACKET, BlockEventPacket::class);
$this->registerPacket(ProtocolInfo::CHANGE_DIMENSION_PACKET, ChangeDimensionPacket::class);
$this->registerPacket(ProtocolInfo::CHUNK_RADIUS_UPDATED_PACKET, ChunkRadiusUpdatedPacket::class);
$this->registerPacket(ProtocolInfo::COMMAND_STEP_PACKET, CommandStepPacket::class);
$this->registerPacket(ProtocolInfo::CONTAINER_CLOSE_PACKET, ContainerClosePacket::class);
$this->registerPacket(ProtocolInfo::CONTAINER_SET_SLOT_PACKET, ContainerSetSlotPacket::class);
$this->registerPacket(ProtocolInfo::CONTAINER_SET_DATA_PACKET, ContainerSetDataPacket::class);
$this->registerPacket(ProtocolInfo::CONTAINER_OPEN_PACKET, ContainerOpenPacket::class);
$this->registerPacket(ProtocolInfo::CONTAINER_SET_CONTENT_PACKET, ContainerSetContentPacket::class);
$this->registerPacket(ProtocolInfo::CONTAINER_SET_DATA_PACKET, ContainerSetDataPacket::class);
$this->registerPacket(ProtocolInfo::CONTAINER_SET_SLOT_PACKET, ContainerSetSlotPacket::class);
$this->registerPacket(ProtocolInfo::CRAFTING_DATA_PACKET, CraftingDataPacket::class);
$this->registerPacket(ProtocolInfo::CRAFTING_EVENT_PACKET, CraftingEventPacket::class);
$this->registerPacket(ProtocolInfo::ADVENTURE_SETTINGS_PACKET, AdventureSettingsPacket::class);
$this->registerPacket(ProtocolInfo::BLOCK_ENTITY_DATA_PACKET, BlockEntityDataPacket::class);
$this->registerPacket(ProtocolInfo::DISCONNECT_PACKET, DisconnectPacket::class);
$this->registerPacket(ProtocolInfo::DROP_ITEM_PACKET, DropItemPacket::class);
$this->registerPacket(ProtocolInfo::ENTITY_EVENT_PACKET, EntityEventPacket::class);
$this->registerPacket(ProtocolInfo::EXPLODE_PACKET, ExplodePacket::class);
$this->registerPacket(ProtocolInfo::FULL_CHUNK_DATA_PACKET, FullChunkDataPacket::class);
$this->registerPacket(ProtocolInfo::SET_DIFFICULTY_PACKET, SetDifficultyPacket::class);
$this->registerPacket(ProtocolInfo::SET_PLAYER_GAMETYPE_PACKET, SetPlayerGameTypePacket::class);
$this->registerPacket(ProtocolInfo::CHANGE_DIMENSION_PACKET, ChangeDimensionPacket::class);
$this->registerPacket(ProtocolInfo::HURT_ARMOR_PACKET, HurtArmorPacket::class);
$this->registerPacket(ProtocolInfo::INTERACT_PACKET, InteractPacket::class);
$this->registerPacket(ProtocolInfo::INVENTORY_ACTION_PACKET, InventoryActionPacket::class);
$this->registerPacket(ProtocolInfo::ITEM_FRAME_DROP_ITEM_PACKET, ItemFrameDropItemPacket::class);
$this->registerPacket(ProtocolInfo::LEVEL_EVENT_PACKET, LevelEventPacket::class);
$this->registerPacket(ProtocolInfo::LEVEL_SOUND_EVENT_PACKET, LevelSoundEventPacket::class);
$this->registerPacket(ProtocolInfo::LOGIN_PACKET, LoginPacket::class);
$this->registerPacket(ProtocolInfo::MOB_ARMOR_EQUIPMENT_PACKET, MobArmorEquipmentPacket::class);
$this->registerPacket(ProtocolInfo::MOB_EQUIPMENT_PACKET, MobEquipmentPacket::class);
$this->registerPacket(ProtocolInfo::MOVE_ENTITY_PACKET, MoveEntityPacket::class);
$this->registerPacket(ProtocolInfo::MOVE_PLAYER_PACKET, MovePlayerPacket::class);
$this->registerPacket(ProtocolInfo::PLAYER_ACTION_PACKET, PlayerActionPacket::class);
$this->registerPacket(ProtocolInfo::PLAYER_INPUT_PACKET, PlayerInputPacket::class);
$this->registerPacket(ProtocolInfo::PLAYER_LIST_PACKET, PlayerListPacket::class);
$this->registerPacket(ProtocolInfo::PLAY_STATUS_PACKET, PlayStatusPacket::class);
$this->registerPacket(ProtocolInfo::REMOVE_BLOCK_PACKET, RemoveBlockPacket::class);
$this->registerPacket(ProtocolInfo::REMOVE_ENTITY_PACKET, RemoveEntityPacket::class);
$this->registerPacket(ProtocolInfo::REPLACE_SELECTED_ITEM_PACKET, ReplaceSelectedItemPacket::class);
$this->registerPacket(ProtocolInfo::REQUEST_CHUNK_RADIUS_PACKET, RequestChunkRadiusPacket::class);
$this->registerPacket(ProtocolInfo::CHUNK_RADIUS_UPDATED_PACKET, ChunkRadiusUpdatedPacket::class);
$this->registerPacket(ProtocolInfo::RESOURCE_PACK_CLIENT_RESPONSE_PACKET, ResourcePackClientResponsePacket::class);
$this->registerPacket(ProtocolInfo::RESOURCE_PACKS_INFO_PACKET, ResourcePacksInfoPacket::class);
$this->registerPacket(ProtocolInfo::RESPAWN_PACKET, RespawnPacket::class);
$this->registerPacket(ProtocolInfo::SET_COMMANDS_ENABLED_PACKET, SetCommandsEnabledPacket::class);
$this->registerPacket(ProtocolInfo::SET_DIFFICULTY_PACKET, SetDifficultyPacket::class);
$this->registerPacket(ProtocolInfo::SET_ENTITY_DATA_PACKET, SetEntityDataPacket::class);
$this->registerPacket(ProtocolInfo::SET_ENTITY_LINK_PACKET, SetEntityLinkPacket::class);
$this->registerPacket(ProtocolInfo::SET_ENTITY_MOTION_PACKET, SetEntityMotionPacket::class);
$this->registerPacket(ProtocolInfo::SET_HEALTH_PACKET, SetHealthPacket::class);
$this->registerPacket(ProtocolInfo::SET_PLAYER_GAME_TYPE_PACKET, SetPlayerGameTypePacket::class);
$this->registerPacket(ProtocolInfo::SET_SPAWN_POSITION_PACKET, SetSpawnPositionPacket::class);
$this->registerPacket(ProtocolInfo::SET_TIME_PACKET, SetTimePacket::class);
$this->registerPacket(ProtocolInfo::SPAWN_EXPERIENCE_ORB_PACKET, SpawnExperienceOrbPacket::class);
$this->registerPacket(ProtocolInfo::START_GAME_PACKET, StartGamePacket::class);
$this->registerPacket(ProtocolInfo::TAKE_ITEM_ENTITY_PACKET, TakeItemEntityPacket::class);
$this->registerPacket(ProtocolInfo::TEXT_PACKET, TextPacket::class);
$this->registerPacket(ProtocolInfo::UPDATE_BLOCK_PACKET, UpdateBlockPacket::class);
$this->registerPacket(ProtocolInfo::USE_ITEM_PACKET, UseItemPacket::class);
}
}

View File

@ -132,6 +132,7 @@ class RakLibInterface implements ServerInstance, AdvancedSourceInterface{
$pk = $this->getPacket($packet->buffer);
if($pk !== null){
$pk->decode();
assert($pk->feof(), "Still " . strlen(substr($pk->buffer, $pk->offset)) . " bytes unread!");
$this->players[$identifier]->handleDataPacket($pk);
}
}

View File

@ -42,7 +42,7 @@ class AddEntityPacket extends DataPacket{
public $yaw;
public $pitch;
public $modifiers;
public $metadata;
public $metadata = [];
public $links = [];
public function decode(){
@ -51,23 +51,20 @@ class AddEntityPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putLong($this->eid);
$this->putInt($this->type);
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putFloat($this->speedX);
$this->putFloat($this->speedY);
$this->putFloat($this->speedZ);
$this->putFloat($this->yaw * (256 / 360));
$this->putFloat($this->pitch * (256 / 360));
$this->putInt($this->modifiers);
$this->putEntityId($this->eid); //EntityUniqueID - TODO: verify this
$this->putEntityId($this->eid);
$this->putUnsignedVarInt($this->type);
$this->putVector3f($this->x, $this->y, $this->z);
$this->putVector3f($this->speedX, $this->speedY, $this->speedZ);
$this->putLFloat($this->yaw * (256 / 360));
$this->putLFloat($this->pitch * (256 / 360));
$this->putUnsignedVarInt($this->modifiers); //attributes?
$meta = Binary::writeMetadata($this->metadata);
$this->put($meta);
$this->putShort(count($this->links));
$this->putUnsignedVarInt(count($this->links));
foreach($this->links as $link){
$this->putLong($link[0]);
$this->putLong($link[1]);
$this->putEntityId($link[0]);
$this->putEntityId($link[1]);
$this->putByte($link[2]);
}
}

View File

@ -0,0 +1,48 @@
<?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\network\protocol;
#include <rules/DataPacket.h>
class AddHangingEntityPacket extends DataPacket{
const NETWORK_ID = Info::ADD_HANGING_ENTITY_PACKET;
public $entityUniqueId;
public $entityRuntimeId;
public $x;
public $y;
public $z;
public $unknown;
public function decode(){
}
public function encode(){
$this->reset();
$this->putEntityId($this->entityUniqueId);
$this->putEntityId($this->entityRuntimeId);
$this->putBlockCoords($this->x, $this->y, $this->z);
$this->putVarInt($this->unknown);
}
}

View File

@ -42,14 +42,11 @@ class AddItemEntityPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putLong($this->eid);
$this->putEntityId($this->eid); //EntityUniqueID
$this->putEntityId($this->eid); //EntityRuntimeID
$this->putSlot($this->item);
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putFloat($this->speedX);
$this->putFloat($this->speedY);
$this->putFloat($this->speedZ);
$this->putVector3f($this->x, $this->y, $this->z);
$this->putVector3f($this->speedX, $this->speedY, $this->speedZ);
}
}

View File

@ -0,0 +1,41 @@
<?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\network\protocol;
#include <rules/DataPacket.h>
class AddItemPacket extends DataPacket{
const NETWORK_ID = Info::ADD_ITEM_PACKET;
public $item;
public function decode(){
}
public function encode(){
$this->reset();
$this->putSlot($this->item);
}
}

View File

@ -40,11 +40,10 @@ class AddPaintingPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putLong($this->eid);
$this->putInt($this->x);
$this->putInt($this->y);
$this->putInt($this->z);
$this->putInt($this->direction);
$this->putEntityId($this->eid); //EntityUniqueID
$this->putEntityId($this->eid); //EntityRuntimeID
$this->putBlockCoords($this->x, $this->y, $this->z);
$this->putVarInt($this->direction);
$this->putString($this->title);
}

View File

@ -43,7 +43,7 @@ class AddPlayerPacket extends DataPacket{
public $pitch;
public $yaw;
public $item;
public $metadata;
public $metadata = [];
public function decode(){
@ -53,16 +53,14 @@ class AddPlayerPacket extends DataPacket{
$this->reset();
$this->putUUID($this->uuid);
$this->putString($this->username);
$this->putLong($this->eid);
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putFloat($this->speedX);
$this->putFloat($this->speedY);
$this->putFloat($this->speedZ);
$this->putFloat($this->yaw);
$this->putFloat($this->yaw); //TODO headrot
$this->putFloat($this->pitch);
$this->putEntityId($this->eid); //EntityUniqueID
$this->putEntityId($this->eid); //EntityRuntimeID
$this->putVector3f($this->x, $this->y, $this->z);
$this->putVector3f($this->speedX, $this->speedY, $this->speedZ);
//TODO: check these are in the right order
$this->putLFloat($this->yaw);
$this->putLFloat($this->yaw); //TODO headrot
$this->putLFloat($this->pitch);
$this->putSlot($this->item);
$meta = Binary::writeMetadata($this->metadata);

View File

@ -27,19 +27,71 @@ namespace pocketmine\network\protocol;
class AdventureSettingsPacket extends DataPacket{
const NETWORK_ID = Info::ADVENTURE_SETTINGS_PACKET;
public $flags;
const PERMISSION_NORMAL = 0;
const PERMISSION_OPERATOR = 1;
const PERMISSION_HOST = 2;
const PERMISSION_AUTOMATION = 3;
const PERMISSION_ADMIN = 4;
public $worldImmutable;
public $noPvp;
public $noPvm;
public $noMvp;
public $autoJump;
public $allowFlight;
public $noClip;
public $isFlying;
/*
bit mask | flag name
0x00000001 world_immutable
0x00000002 no_pvp
0x00000004 no_pvm
0x00000008 no_mvp
0x00000010 ?
0x00000020 auto_jump
0x00000040 allow_fly
0x00000080 noclip
0x00000100 ?
0x00000200 is_flying
*/
public $flags = 0;
public $userPermission;
public $globalPermission;
public function decode(){
$this->flags = $this->getUnsignedVarInt();
$this->userPermission = $this->getUnsignedVarInt();
$this->worldImmutable = (bool) ($this->flags & 1);
$this->noPvp = (bool) ($this->flags & (1 << 1));
$this->noPvm = (bool) ($this->flags & (1 << 2));
$this->noMvp = (bool) ($this->flags & (1 << 3));
$this->autoJump = (bool) ($this->flags & (1 << 5));
$this->allowFlight = (bool) ($this->flags & (1 << 6));
$this->noClip = (bool) ($this->flags & (1 << 7));
$this->isFlying = (bool) ($this->flags & (1 << 9));
}
public function encode(){
$this->reset();
$this->putInt($this->flags);
$this->putInt($this->userPermission);
$this->putInt($this->globalPermission);
$this->flags |= ((int) $this->worldImmutable);
$this->flags |= ((int) $this->noPvp) << 1;
$this->flags |= ((int) $this->noPvm) << 2;
$this->flags |= ((int) $this->noMvp) << 3;
$this->flags |= ((int) $this->autoJump) << 5;
$this->flags |= ((int) $this->allowFlight) << 6;
$this->flags |= ((int) $this->noClip) << 7;
$this->flags |= ((int) $this->isFlying) << 9;
$this->putUnsignedVarInt($this->flags);
$this->putUnsignedVarInt($this->userPermission);
}
}

View File

@ -31,14 +31,14 @@ class AnimatePacket extends DataPacket{
public $eid;
public function decode(){
$this->action = $this->getByte();
$this->eid = $this->getLong();
$this->action = $this->getVarInt();
$this->eid = $this->getEntityId();
}
public function encode(){
$this->reset();
$this->putByte($this->action);
$this->putLong($this->eid);
$this->putVarInt($this->action);
$this->putEntityId($this->eid);
}
}

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\network\protocol;
#include <rules/DataPacket.h>
class AvailableCommandsPacket extends DataPacket{
const NETWORK_ID = Info::AVAILABLE_COMMANDS_PACKET;
public $commands; //JSON-encoded command data
public $unknown;
public function decode(){
}
public function encode(){
$this->reset();
$this->putString($this->commands);
$this->putString($this->unknown);
}
}

View File

@ -30,14 +30,12 @@ class BatchPacket extends DataPacket{
public $payload;
public function decode(){
$size = $this->getInt();
$this->payload = $this->get($size);
$this->payload = $this->getString();
}
public function encode(){
$this->reset();
$this->putInt(strlen($this->payload));
$this->put($this->payload);
$this->putString($this->payload);
}
}

View File

@ -33,17 +33,13 @@ class BlockEntityDataPacket extends DataPacket{
public $namedtag;
public function decode(){
$this->x = $this->getInt();
$this->y = $this->getInt();
$this->z = $this->getInt();
$this->getBlockCoords($this->x, $this->y, $this->z);
$this->namedtag = $this->get(true);
}
public function encode(){
$this->reset();
$this->putInt($this->x);
$this->putInt($this->y);
$this->putInt($this->z);
$this->putBlockCoords($this->x, $this->y, $this->z);
$this->put($this->namedtag);
}

View File

@ -39,11 +39,9 @@ class BlockEventPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putInt($this->x);
$this->putInt($this->y);
$this->putInt($this->z);
$this->putInt($this->case1);
$this->putInt($this->case2);
$this->putBlockCoords($this->x, $this->y, $this->z);
$this->putVarInt($this->case1);
$this->putVarInt($this->case2);
}
}

View File

@ -34,7 +34,7 @@ class ChangeDimensionPacket extends DataPacket{
public $x;
public $y;
public $z;
public $unknown;
public $unknown; //bool
public function decode(){
@ -42,11 +42,9 @@ class ChangeDimensionPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putByte($this->dimension);
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putByte($this->unknown);
$this->putVarInt($this->dimension);
$this->putVector3f($this->x, $this->y, $this->z);
$this->putBool($this->unknown);
}
}

View File

@ -34,7 +34,7 @@ class ChunkRadiusUpdatedPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putInt($this->radius);
$this->putVarInt($this->radius);
}
}

View File

@ -0,0 +1,68 @@
<?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\network\protocol;
#include <rules/DataPacket.h>
class CommandStepPacket extends DataPacket{
const NETWORK_ID = Info::COMMAND_STEP_PACKET;
/**
* unknown (string)
* unknown (string)
* unknown (uvarint)
* unknown (uvarint)
* unknown (bool)
* unknown (uvarint64)
* unknown (string)
* unknown (string)
* https://gist.github.com/dktapps/8285b93af4ca38e0104bfeb9a6c87afd
*/
public $command;
public $overload;
public $uvarint1;
public $uvarint2;
public $bool;
public $uvarint64;
public $args; //JSON formatted command arguments
public $string4;
public function decode(){
$this->command = $this->getString();
$this->overload = $this->getString();
$this->uvarint1 = $this->getUnsignedVarInt();
$this->uvarint2 = $this->getUnsignedVarInt();
$this->bool = (bool) $this->getByte();
$this->uvarint64 = $this->getUnsignedVarInt(); //TODO: varint64
$this->args = json_decode($this->getString());
$this->string4 = $this->getString();
while(!$this->feof()){
$this->getByte(); //prevent assertion errors. TODO: find out why there are always 3 extra bytes at the end of this packet.
}
}
public function encode(){
}
}

View File

@ -33,6 +33,7 @@ class ContainerOpenPacket extends DataPacket{
public $x;
public $y;
public $z;
public $entityId = -1;
public function decode(){
@ -42,10 +43,9 @@ class ContainerOpenPacket extends DataPacket{
$this->reset();
$this->putByte($this->windowid);
$this->putByte($this->type);
$this->putShort($this->slots);
$this->putInt($this->x);
$this->putInt($this->y);
$this->putInt($this->z);
$this->putVarInt($this->slots);
$this->putBlockCoords($this->x, $this->y, $this->z);
$this->putEntityId($this->entityId);
}
}

View File

@ -30,6 +30,7 @@ class ContainerSetContentPacket extends DataPacket{
const SPECIAL_INVENTORY = 0;
const SPECIAL_ARMOR = 0x78;
const SPECIAL_CREATIVE = 0x79;
const SPECIAL_HOTBAR = 0x7a;
public $windowid;
public $slots = [];
@ -43,14 +44,14 @@ class ContainerSetContentPacket extends DataPacket{
public function decode(){
$this->windowid = $this->getByte();
$count = $this->getShort();
$count = $this->getUnsignedVarInt();
for($s = 0; $s < $count and !$this->feof(); ++$s){
$this->slots[$s] = $this->getSlot();
}
if($this->windowid === self::SPECIAL_INVENTORY){
$count = $this->getShort();
$count = $this->getUnsignedVarInt();
for($s = 0; $s < $count and !$this->feof(); ++$s){
$this->hotbar[$s] = $this->getInt();
$this->hotbar[$s] = $this->getVarInt();
}
}
}
@ -58,17 +59,17 @@ class ContainerSetContentPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putByte($this->windowid);
$this->putShort(count($this->slots));
$this->putUnsignedVarInt(count($this->slots));
foreach($this->slots as $slot){
$this->putSlot($slot);
}
if($this->windowid === self::SPECIAL_INVENTORY and count($this->hotbar) > 0){
$this->putShort(count($this->hotbar));
$this->putUnsignedVarInt(count($this->hotbar));
foreach($this->hotbar as $slot){
$this->putInt($slot);
$this->putVarInt($slot);
}
}else{
$this->putShort(0);
$this->putUnsignedVarInt(0);
}
}

View File

@ -38,8 +38,8 @@ class ContainerSetDataPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putByte($this->windowid);
$this->putShort($this->property);
$this->putShort($this->value);
$this->putVarInt($this->property);
$this->putVarInt($this->value);
}
}

View File

@ -36,16 +36,16 @@ class ContainerSetSlotPacket extends DataPacket{
public function decode(){
$this->windowid = $this->getByte();
$this->slot = $this->getShort();
$this->hotbarSlot = $this->getShort();
$this->slot = $this->getVarInt();
$this->hotbarSlot = $this->getVarInt();
$this->item = $this->getSlot();
}
public function encode(){
$this->reset();
$this->putByte($this->windowid);
$this->putShort($this->slot);
$this->putShort($this->hotbarSlot);
$this->putVarInt($this->slot);
$this->putVarInt($this->hotbarSlot);
$this->putSlot($this->item);
}

View File

@ -58,12 +58,12 @@ class CraftingDataPacket extends DataPacket{
}
private static function writeShapelessRecipe(ShapelessRecipe $recipe, BinaryStream $stream){
$stream->putInt($recipe->getIngredientCount());
$stream->putUnsignedVarInt($recipe->getIngredientCount());
foreach($recipe->getIngredientList() as $item){
$stream->putSlot($item);
}
$stream->putInt(1);
$stream->putUnsignedVarInt(1);
$stream->putSlot($recipe->getResult());
$stream->putUUID($recipe->getId());
@ -72,8 +72,8 @@ class CraftingDataPacket extends DataPacket{
}
private static function writeShapedRecipe(ShapedRecipe $recipe, BinaryStream $stream){
$stream->putInt($recipe->getWidth());
$stream->putInt($recipe->getHeight());
$stream->putVarInt($recipe->getWidth());
$stream->putVarInt($recipe->getHeight());
for($z = 0; $z < $recipe->getHeight(); ++$z){
for($x = 0; $x < $recipe->getWidth(); ++$x){
@ -81,7 +81,7 @@ class CraftingDataPacket extends DataPacket{
}
}
$stream->putInt(1);
$stream->putUnsignedVarInt(1);
$stream->putSlot($recipe->getResult());
$stream->putUUID($recipe->getId());
@ -90,13 +90,14 @@ class CraftingDataPacket extends DataPacket{
}
private static function writeFurnaceRecipe(FurnaceRecipe $recipe, BinaryStream $stream){
if($recipe->getInput()->getDamage() !== 0){ //Data recipe
$stream->putInt(($recipe->getInput()->getId() << 16) | ($recipe->getInput()->getDamage()));
if($recipe->getInput()->getDamage() !== null){ //Data recipe
$stream->putVarInt($recipe->getInput()->getId());
$stream->putVarInt($recipe->getInput()->getDamage());
$stream->putSlot($recipe->getResult());
return CraftingDataPacket::ENTRY_FURNACE_DATA;
}else{
$stream->putInt($recipe->getInput()->getId());
$stream->putVarInt($recipe->getInput()->getId());
$stream->putSlot($recipe->getResult());
return CraftingDataPacket::ENTRY_FURNACE;
@ -104,15 +105,15 @@ class CraftingDataPacket extends DataPacket{
}
private static function writeEnchantList(EnchantmentList $list, BinaryStream $stream){
//TODO: check this works on 0.16 (cannot currently test)
$stream->putByte($list->getSize());
for($i = 0; $i < $list->getSize(); ++$i){
$entry = $list->getSlot($i);
$stream->putInt($entry->getCost());
$stream->putByte(count($entry->getEnchantments()));
$stream->putUnsignedVarInt($entry->getCost());
$stream->putUnsignedVarInt(count($entry->getEnchantments()));
foreach($entry->getEnchantments() as $enchantment){
$stream->putInt($enchantment->getId());
$stream->putInt($enchantment->getLevel());
$stream->putUnsignedVarInt($enchantment->getId());
$stream->putUnsignedVarInt($enchantment->getLevel());
}
$stream->putString($entry->getRandomName());
}
@ -147,24 +148,22 @@ class CraftingDataPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putInt(count($this->entries));
$this->putUnsignedVarInt(count($this->entries));
$writer = new BinaryStream();
foreach($this->entries as $d){
$entryType = self::writeEntry($d, $writer);
if($entryType >= 0){
$this->putInt($entryType);
$this->putInt(strlen($writer->getBuffer()));
$this->putVarInt($entryType);
$this->put($writer->getBuffer());
}else{
$this->putInt(-1);
$this->putInt(0);
$this->putVarInt(-1);
}
$writer->reset();
}
$this->putByte($this->cleanRecipes ? 1 : 0);
$this->putBool($this->cleanRecipes);
}
}

View File

@ -41,15 +41,15 @@ class CraftingEventPacket extends DataPacket{
public function decode(){
$this->windowId = $this->getByte();
$this->type = $this->getInt();
$this->type = $this->getVarInt();
$this->id = $this->getUUID();
$size = $this->getInt();
$size = $this->getUnsignedVarInt();
for($i = 0; $i < $size and $i < 128; ++$i){
$this->input[] = $this->getSlot();
}
$size = $this->getInt();
$size = $this->getUnsignedVarInt();
for($i = 0; $i < $size and $i < 128; ++$i){
$this->output[] = $this->getSlot();
}

View File

@ -27,14 +27,17 @@ namespace pocketmine\network\protocol;
class DisconnectPacket extends DataPacket{
const NETWORK_ID = Info::DISCONNECT_PACKET;
public $hideDisconnectionScreen = false;
public $message;
public function decode(){
$this->hideDisconnectionScreen = $this->getBool();
$this->message = $this->getString();
}
public function encode(){
$this->reset();
$this->putBool($this->hideDisconnectionScreen);
$this->putString($this->message);
}

View File

@ -47,16 +47,19 @@ class EntityEventPacket extends DataPacket{
public $eid;
public $event;
public $unknown;
public function decode(){
$this->eid = $this->getLong();
$this->eid = $this->getEntityId();
$this->event = $this->getByte();
$this->unknown = $this->getVarInt();
}
public function encode(){
$this->reset();
$this->putLong($this->eid);
$this->putEntityId($this->eid);
$this->putByte($this->event);
$this->putVarInt($this->unknown);
}
}

View File

@ -44,16 +44,12 @@ class ExplodePacket extends DataPacket{
public function encode(){
$this->reset();
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putFloat($this->radius);
$this->putInt(count($this->records));
$this->putVector3f($this->x, $this->y, $this->z);
$this->putLFloat($this->radius);
$this->putUnsignedVarInt(count($this->records));
if(count($this->records) > 0){
foreach($this->records as $record){
$this->putByte($record->x);
$this->putByte($record->y);
$this->putByte($record->z);
$this->putBlockCoords($record->x, $record->y, $record->z);
}
}
}

View File

@ -41,11 +41,10 @@ class FullChunkDataPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putInt($this->chunkX);
$this->putInt($this->chunkZ);
$this->putVarInt($this->chunkX);
$this->putVarInt($this->chunkZ);
$this->putByte($this->order);
$this->putInt(strlen($this->data));
$this->put($this->data);
$this->putString($this->data);
}
}

View File

@ -35,7 +35,7 @@ class HurtArmorPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putByte($this->health);
$this->putVarInt($this->health);
}
}

View File

@ -30,7 +30,7 @@ interface Info{
/**
* Actual Minecraft: PE protocol version
*/
const CURRENT_PROTOCOL = 84;
const CURRENT_PROTOCOL = 91;
const LOGIN_PACKET = 0x01;
const PLAY_STATUS_PACKET = 0x02;
@ -38,64 +38,79 @@ interface Info{
const CLIENT_TO_SERVER_HANDSHAKE_PACKET = 0x04;
const DISCONNECT_PACKET = 0x05;
const BATCH_PACKET = 0x06;
const TEXT_PACKET = 0x07;
const SET_TIME_PACKET = 0x08;
const START_GAME_PACKET = 0x09;
const ADD_PLAYER_PACKET = 0x0a;
const ADD_ENTITY_PACKET = 0x0b;
const REMOVE_ENTITY_PACKET = 0x0c;
const ADD_ITEM_ENTITY_PACKET = 0x0d;
const TAKE_ITEM_ENTITY_PACKET = 0x0e;
const MOVE_ENTITY_PACKET = 0x0f;
const MOVE_PLAYER_PACKET = 0x10;
const RIDER_JUMP_PACKET = 0x11;
const REMOVE_BLOCK_PACKET = 0x12;
const UPDATE_BLOCK_PACKET = 0x13;
const ADD_PAINTING_PACKET = 0x14;
const EXPLODE_PACKET = 0x15;
const LEVEL_EVENT_PACKET = 0x16;
const BLOCK_EVENT_PACKET = 0x17;
const ENTITY_EVENT_PACKET = 0x18;
const MOB_EFFECT_PACKET = 0x19;
const UPDATE_ATTRIBUTES_PACKET = 0x1a;
const MOB_EQUIPMENT_PACKET = 0x1b;
const MOB_ARMOR_EQUIPMENT_PACKET = 0x1c;
const INTERACT_PACKET = 0x1e;
const USE_ITEM_PACKET = 0x1f;
const PLAYER_ACTION_PACKET = 0x20;
const HURT_ARMOR_PACKET = 0x21;
const SET_ENTITY_DATA_PACKET = 0x22;
const SET_ENTITY_MOTION_PACKET = 0x23;
const SET_ENTITY_LINK_PACKET = 0x24;
const SET_HEALTH_PACKET = 0x25;
const SET_SPAWN_POSITION_PACKET = 0x26;
const ANIMATE_PACKET = 0x27;
const RESPAWN_PACKET = 0x28;
const DROP_ITEM_PACKET = 0x29;
const CONTAINER_OPEN_PACKET = 0x2a;
const CONTAINER_CLOSE_PACKET = 0x2b;
const CONTAINER_SET_SLOT_PACKET = 0x2c;
const CONTAINER_SET_DATA_PACKET = 0x2d;
const CONTAINER_SET_CONTENT_PACKET = 0x2e;
const CRAFTING_DATA_PACKET = 0x2f;
const CRAFTING_EVENT_PACKET = 0x30;
const ADVENTURE_SETTINGS_PACKET = 0x31;
const BLOCK_ENTITY_DATA_PACKET = 0x32;
const PLAYER_INPUT_PACKET = 0x33;
const FULL_CHUNK_DATA_PACKET = 0x34;
const SET_DIFFICULTY_PACKET = 0x35;
const CHANGE_DIMENSION_PACKET = 0x36;
const SET_PLAYER_GAMETYPE_PACKET = 0x37;
const PLAYER_LIST_PACKET = 0x38;
const TELEMETRY_EVENT_PACKET = 0x39;
const SPAWN_EXPERIENCE_ORB_PACKET = 0x3a;
const CLIENTBOUND_MAP_ITEM_DATA_PACKET = 0x3b;
const MAP_INFO_REQUEST_PACKET = 0x3c;
const REQUEST_CHUNK_RADIUS_PACKET = 0x3d;
const CHUNK_RADIUS_UPDATED_PACKET = 0x3e;
const ITEM_FRAME_DROP_ITEM_PACKET = 0x3f;
const REPLACE_SELECTED_ITEM_PACKET = 0x40;
const ADD_ITEM_PACKET = 0x41;
const RESOURCE_PACKS_INFO_PACKET = 0x07;
const RESOURCE_PACK_STACK_PACKET = 0x08;
const RESOURCE_PACK_CLIENT_RESPONSE_PACKET = 0x09;
const TEXT_PACKET = 0x0a;
const SET_TIME_PACKET = 0x0b;
const START_GAME_PACKET = 0x0c;
const ADD_PLAYER_PACKET = 0x0d;
const ADD_ENTITY_PACKET = 0x0e;
const REMOVE_ENTITY_PACKET = 0x0f;
const ADD_ITEM_ENTITY_PACKET = 0x10;
const ADD_HANGING_ENTITY_PACKET = 0x11;
const TAKE_ITEM_ENTITY_PACKET = 0x12;
const MOVE_ENTITY_PACKET = 0x13;
const MOVE_PLAYER_PACKET = 0x14;
const RIDER_JUMP_PACKET = 0x15;
const REMOVE_BLOCK_PACKET = 0x16;
const UPDATE_BLOCK_PACKET = 0x17;
const ADD_PAINTING_PACKET = 0x18;
const EXPLODE_PACKET = 0x19;
const LEVEL_SOUND_EVENT_PACKET = 0x1a;
const LEVEL_EVENT_PACKET = 0x1b;
const BLOCK_EVENT_PACKET = 0x1c;
const ENTITY_EVENT_PACKET = 0x1d;
const MOB_EFFECT_PACKET = 0x1e;
const UPDATE_ATTRIBUTES_PACKET = 0x1f;
const MOB_EQUIPMENT_PACKET = 0x20;
const MOB_ARMOR_EQUIPMENT_PACKET = 0x21;
const INTERACT_PACKET = 0x22;
const USE_ITEM_PACKET = 0x23;
const PLAYER_ACTION_PACKET = 0x24;
const HURT_ARMOR_PACKET = 0x25;
const SET_ENTITY_DATA_PACKET = 0x26;
const SET_ENTITY_MOTION_PACKET = 0x27;
const SET_ENTITY_LINK_PACKET = 0x28;
const SET_HEALTH_PACKET = 0x29;
const SET_SPAWN_POSITION_PACKET = 0x2a;
const ANIMATE_PACKET = 0x2b;
const RESPAWN_PACKET = 0x2c;
const DROP_ITEM_PACKET = 0x2d;
const INVENTORY_ACTION_PACKET = 0x2e;
const CONTAINER_OPEN_PACKET = 0x2f;
const CONTAINER_CLOSE_PACKET = 0x30;
const CONTAINER_SET_SLOT_PACKET = 0x31;
const CONTAINER_SET_DATA_PACKET = 0x32;
const CONTAINER_SET_CONTENT_PACKET = 0x33;
const CRAFTING_DATA_PACKET = 0x34;
const CRAFTING_EVENT_PACKET = 0x35;
const ADVENTURE_SETTINGS_PACKET = 0x36;
const BLOCK_ENTITY_DATA_PACKET = 0x37;
const PLAYER_INPUT_PACKET = 0x38;
const FULL_CHUNK_DATA_PACKET = 0x39;
const SET_COMMANDS_ENABLED_PACKET = 0x3a;
const SET_DIFFICULTY_PACKET = 0x3b;
const CHANGE_DIMENSION_PACKET = 0x3c;
const SET_PLAYER_GAME_TYPE_PACKET = 0x3d;
const PLAYER_LIST_PACKET = 0x3e;
const EVENT_PACKET = 0x3f;
const SPAWN_EXPERIENCE_ORB_PACKET = 0x40;
const CLIENTBOUND_MAP_ITEM_DATA_PACKET = 0x41;
const MAP_INFO_REQUEST_PACKET = 0x42;
const REQUEST_CHUNK_RADIUS_PACKET = 0x43;
const CHUNK_RADIUS_UPDATED_PACKET = 0x44;
const ITEM_FRAME_DROP_ITEM_PACKET = 0x45;
const REPLACE_SELECTED_ITEM_PACKET = 0x46;
const GAME_RULES_CHANGED_PACKET = 0x47;
const CAMERA_PACKET = 0x48;
const ADD_ITEM_PACKET = 0x49;
const BOSS_EVENT_PACKET = 0x4a;
const AVAILABLE_COMMANDS_PACKET = 0x4b;
const COMMAND_STEP_PACKET = 0x4c;
const RESOURCE_PACK_DATA_INFO_PACKET = 0x4d;
const RESOURCE_PACK_CHUNK_DATA_PACKET = 0x4e;
const RESOURCE_PACK_CHUNK_REQUEST_PACKET = 0x4f;
}

View File

@ -30,22 +30,20 @@ class InteractPacket extends DataPacket{
const ACTION_RIGHT_CLICK = 1;
const ACTION_LEFT_CLICK = 2;
const ACTION_LEAVE_VEHICLE = 3;
/** @deprecated Do NOT use this. This constant is misleading and will be removed in the future */
const ACTION_JUMP = 3;
const ACTION_MOUSEOVER = 4;
public $action;
public $eid;
public $target;
public function decode(){
$this->action = $this->getByte();
$this->target = $this->getLong();
$this->target = $this->getEntityId();
}
public function encode(){
$this->reset();
$this->putByte($this->action);
$this->putLong($this->target);
$this->putEntityId($this->target);
}
}

View File

@ -0,0 +1,40 @@
<?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\network\protocol;
#include <rules/DataPacket.h>
class InventoryActionPacket extends DataPacket{
const NETWORK_ID = Info::INVENTORY_ACTION_PACKET;
public $unknown;
public $item;
public function decode(){
}
public function encode(){
$this->putUnsignedVarInt($this->unknown);
$this->putSlot($this->item);
}
}

View File

@ -0,0 +1,44 @@
<?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\network\protocol;
#include <rules/DataPacket.h>
class ItemFrameDropItemPacket extends DataPacket{
const NETWORK_ID = Info::ITEM_FRAME_DROP_ITEM_PACKET;
public $x;
public $y;
public $z;
public $item;
public function decode(){
$this->getBlockCoords($this->x, $this->y, $this->z);
$this->item = $this->getSlot();
}
public function encode(){
}
}

View File

@ -23,7 +23,6 @@ namespace pocketmine\network\protocol;
#include <rules/DataPacket.h>
class LevelEventPacket extends DataPacket{
const NETWORK_ID = Info::LEVEL_EVENT_PACKET;
@ -67,9 +66,9 @@ class LevelEventPacket extends DataPacket{
const EVENT_ADD_PARTICLE_MASK = 0x4000;
public $evid;
public $x;
public $y;
public $z;
public $x = 0; //Weather effects don't have coordinates
public $y = 0;
public $z = 0;
public $data;
public function decode(){
@ -78,11 +77,9 @@ class LevelEventPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putShort($this->evid);
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putInt($this->data);
$this->putVarInt($this->evid);
$this->putVector3f($this->x, $this->y, $this->z);
$this->putVarInt($this->data);
}
}

View File

@ -0,0 +1,56 @@
<?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\network\protocol;
#include <rules/DataPacket.h>
class LevelSoundEventPacket extends DataPacket{
const NETWORK_ID = Info::LEVEL_SOUND_EVENT_PACKET;
public $sound;
public $x;
public $y;
public $z;
public $volume;
public $pitch;
public $unknownBool;
public $unknownBool2;
public function decode(){
$this->sound = $this->getByte();
$this->getVector3f($this->x, $this->y, $this->z);
$this->volume = $this->getVarInt();
$this->pitch = $this->getVarInt();
$this->unknownBool = $this->getBool();
$this->unknownBool2 = $this->getBool();
}
public function encode(){
$this->reset();
$this->putByte($this->sound);
$this->putVector3f($this->x, $this->y, $this->z);
$this->putVarInt($this->volume);
$this->putVarInt($this->pitch);
$this->putBool($this->unknownBool);
$this->putBool($this->unknownBool2);
}
}

View File

@ -27,9 +27,11 @@ namespace pocketmine\network\protocol;
class LoginPacket extends DataPacket{
const NETWORK_ID = Info::LOGIN_PACKET;
const EDITION_POCKET = 0;
public $username;
public $protocol;
public $gameEdition;
public $clientUUID;
public $clientId;
public $identityPublicKey;
@ -44,7 +46,10 @@ class LoginPacket extends DataPacket{
if($this->protocol !== Info::CURRENT_PROTOCOL){
return; //Do not attempt to decode for non-accepted protocols
}
$str = zlib_decode($this->get($this->getInt()), 1024 * 1024 * 64);
$this->gameEdition = $this->getByte();
$str = zlib_decode($this->getString(), 1024 * 1024 * 64);
$this->setBuffer($str, 0);

View File

@ -31,7 +31,7 @@ class MobArmorEquipmentPacket extends DataPacket{
public $slots = [];
public function decode(){
$this->eid = $this->getLong();
$this->eid = $this->getEntityId();
$this->slots[0] = $this->getSlot();
$this->slots[1] = $this->getSlot();
$this->slots[2] = $this->getSlot();
@ -40,7 +40,7 @@ class MobArmorEquipmentPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putLong($this->eid);
$this->putEntityId($this->eid);
$this->putSlot($this->slots[0]);
$this->putSlot($this->slots[1]);
$this->putSlot($this->slots[2]);

View File

@ -44,12 +44,12 @@ class MobEffectPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putLong($this->eid);
$this->putEntityId($this->eid);
$this->putByte($this->eventId);
$this->putByte($this->effectId);
$this->putByte($this->amplifier);
$this->putByte($this->particles ? 1 : 0);
$this->putInt($this->duration);
$this->putVarInt($this->effectId);
$this->putVarInt($this->amplifier);
$this->putBool($this->particles);
$this->putVarInt($this->duration);
}
}

View File

@ -31,20 +31,23 @@ class MobEquipmentPacket extends DataPacket{
public $item;
public $slot;
public $selectedSlot;
public $unknownByte;
public function decode(){
$this->eid = $this->getLong();
$this->eid = $this->getEntityId(); //EntityRuntimeID
$this->item = $this->getSlot();
$this->slot = $this->getByte();
$this->selectedSlot = $this->getByte();
$this->unknownByte = $this->getByte();
}
public function encode(){
$this->reset();
$this->putLong($this->eid);
$this->putEntityId($this->eid); //EntityRuntimeID
$this->putSlot($this->item);
$this->putByte($this->slot);
$this->putByte($this->selectedSlot);
$this->putByte($this->unknownByte);
}
}

View File

@ -36,10 +36,8 @@ class MoveEntityPacket extends DataPacket{
public $pitch;
public function decode(){
$this->eid = $this->getLong();
$this->x = $this->getFloat();
$this->y = $this->getFloat();
$this->z = $this->getFloat();
$this->eid = $this->getEntityId();
$this->getVector3f($this->x, $this->y, $this->z);
$this->pitch = $this->getByte() * (360.0 / 256);
$this->yaw = $this->getByte() * (360.0 / 256);
$this->headYaw = $this->getByte() * (360.0 / 256);
@ -47,10 +45,8 @@ class MoveEntityPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putLong($this->eid);
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putEntityId($this->eid);
$this->putVector3f($this->x, $this->y, $this->z);
$this->putByte($this->pitch / (360.0 / 256));
$this->putByte($this->yaw / (360.0 / 256));
$this->putByte($this->headYaw / (360.0 / 256));

View File

@ -47,28 +47,24 @@ class MovePlayerPacket extends DataPacket{
}
public function decode(){
$this->eid = $this->getLong();
$this->x = $this->getFloat();
$this->y = $this->getFloat();
$this->z = $this->getFloat();
$this->yaw = $this->getFloat();
$this->bodyYaw = $this->getFloat();
$this->pitch = $this->getFloat();
$this->eid = $this->getEntityId(); //EntityRuntimeID
$this->getVector3f($this->x, $this->y, $this->z);
$this->pitch = $this->getLFloat();
$this->yaw = $this->getLFloat();
$this->bodyYaw = $this->getLFloat();
$this->mode = $this->getByte();
$this->onGround = $this->getByte() > 0;
$this->onGround = $this->getBool();
}
public function encode(){
$this->reset();
$this->putLong($this->eid);
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putFloat($this->yaw);
$this->putFloat($this->bodyYaw); //TODO
$this->putFloat($this->pitch);
$this->putEntityId($this->eid); //EntityRuntimeID
$this->putVector3f($this->x, $this->y, $this->z);
$this->putLFloat($this->pitch);
$this->putLFloat($this->yaw);
$this->putLFloat($this->bodyYaw); //TODO
$this->putByte($this->mode);
$this->putByte($this->onGround > 0);
$this->putBool($this->onGround);
}
}

View File

@ -40,7 +40,7 @@ class PlayerActionPacket extends DataPacket{
const ACTION_STOP_SPRINT = 10;
const ACTION_START_SNEAK = 11;
const ACTION_STOP_SNEAK = 12;
const ACTION_DIMENSION_CHANGE = 13;
const ACTION_DIMENSION_CHANGE = 13; //TODO: correct these
public $eid;
public $action;
@ -50,22 +50,18 @@ class PlayerActionPacket extends DataPacket{
public $face;
public function decode(){
$this->eid = $this->getLong();
$this->action = $this->getInt();
$this->x = $this->getInt();
$this->y = $this->getInt();
$this->z = $this->getInt();
$this->face = $this->getInt();
$this->eid = $this->getEntityId();
$this->action = $this->getVarInt();
$this->getBlockCoords($this->x, $this->y, $this->z);
$this->face = $this->getVarInt();
}
public function encode(){
$this->reset();
$this->putLong($this->eid);
$this->putInt($this->action);
$this->putInt($this->x);
$this->putInt($this->y);
$this->putInt($this->z);
$this->putInt($this->face);
$this->putEntityId($this->eid);
$this->putVarInt($this->action);
$this->putBlockCoords($this->x, $this->y, $this->z);
$this->putVarInt($this->face);
}
}

View File

@ -0,0 +1,46 @@
<?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\network\protocol;
#include <rules/DataPacket.h>
class PlayerInputPacket extends DataPacket{
const NETWORK_ID = Info::PLAYER_INPUT_PACKET;
public $motionX;
public $motionY;
public $unknownBool1;
public $unknownBool2;
public function decode(){
$this->motionX = $this->getLFloat();
$this->motionY = $this->getLFloat();
$this->unknownBool1 = $this->getBool();
$this->unknownBool2 = $this->getBool();
}
public function encode(){
}
}

View File

@ -30,7 +30,7 @@ class PlayerListPacket extends DataPacket{
const TYPE_ADD = 0;
const TYPE_REMOVE = 1;
//REMOVE: UUID, ADD: UUID, entity id, name, isSlim, skin
//REMOVE: UUID, ADD: UUID, entity id, name, skinId, skin
/** @var array[] */
public $entries = [];
public $type;
@ -47,11 +47,11 @@ class PlayerListPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putByte($this->type);
$this->putInt(count($this->entries));
$this->putUnsignedVarInt(count($this->entries));
foreach($this->entries as $d){
if($this->type === self::TYPE_ADD){
$this->putUUID($d[0]);
$this->putLong($d[1]);
$this->putEntityId($d[1]);
$this->putString($d[2]);
$this->putString($d[3]);
$this->putString($d[4]);

View File

@ -27,16 +27,12 @@ namespace pocketmine\network\protocol;
class RemoveBlockPacket extends DataPacket{
const NETWORK_ID = Info::REMOVE_BLOCK_PACKET;
public $eid;
public $x;
public $y;
public $z;
public function decode(){
$this->eid = $this->getLong();
$this->x = $this->getInt();
$this->z = $this->getInt();
$this->y = $this->getByte();
$this->getBlockCoords($this->x, $this->y, $this->z);
}
public function encode(){

View File

@ -35,7 +35,7 @@ class RemoveEntityPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putLong($this->eid);
$this->putEntityId($this->eid);
}
}

View File

@ -0,0 +1,41 @@
<?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\network\protocol;
#include <rules/DataPacket.h>
class ReplaceSelectedItemPacket extends DataPacket{
const NETWORK_ID = Info::REPLACE_SELECTED_ITEM_PACKET;
public $item;
public function decode(){
}
public function encode(){
$this->reset();
$this->putSlot($this->item);
}
}

View File

@ -30,7 +30,7 @@ class RequestChunkRadiusPacket extends DataPacket{
public $radius;
public function decode(){
$this->radius = $this->getInt();
$this->radius = $this->getVarInt();
}
public function encode(){

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\network\protocol;
#include <rules/DataPacket.h>
class ResourcePackClientResponsePacket extends DataPacket{
const NETWORK_ID = Info::RESOURCE_PACK_CLIENT_RESPONSE_PACKET;
public $unknownByte;
public $unknownShort;
public function decode(){
$this->unknownByte = $this->getByte();
$this->unknownShort = $this->getShort();
}
public function encode(){
}
}

View File

@ -0,0 +1,57 @@
<?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\network\protocol;
#include <rules/DataPacket.h>
class ResourcePacksInfoPacket extends DataPacket{
const NETWORK_ID = Info::RESOURCE_PACKS_INFO_PACKET;
public $mustAccept = false; //force client to use selected resource packs
/** @var ResourcePackInfoEntry */
public $behaviourPackEntries = [];
/** @var ResourcePackInfoEntry */
public $resourcePackEntries = [];
public function decode(){
}
public function encode(){
$this->reset();
$this->putBool($this->mustAccept);
$this->putShort(count($this->behaviourPackEntries));
foreach($this->behaviourPackEntries as $entry){
$this->putString($entry->getPackId());
$this->putString($entry->getVersion());
$this->putLong($entry->getUint64());
}
$this->putShort(count($this->resourcePackEntries));
foreach($this->resourcePackEntries as $entry){
$this->putString($entry->getPackId());
$this->putString($entry->getVersion());
$this->putLong($entry->getUint64());
}
}
}

View File

@ -32,16 +32,16 @@ class RespawnPacket extends DataPacket{
public $z;
public function decode(){
$this->x = $this->getFloat();
$this->y = $this->getFloat();
$this->z = $this->getFloat();
$this->x = $this->getLFloat();
$this->y = $this->getLFloat();
$this->z = $this->getLFloat();
}
public function encode(){
$this->reset();
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putLFloat($this->x);
$this->putLFloat($this->y);
$this->putLFloat($this->z);
}
}
}

View File

@ -0,0 +1,41 @@
<?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\network\protocol;
#include <rules/DataPacket.h>
class SetCommandsEnabledPacket extends DataPacket{
const NETWORK_ID = Info::SET_COMMANDS_ENABLED_PACKET;
public $enabled;
public function decode(){
}
public function encode(){
$this->reset();
$this->putBool($this->enabled);
}
}

View File

@ -30,12 +30,12 @@ class SetDifficultyPacket extends DataPacket{
public $difficulty;
public function decode(){
$this->difficulty = $this->getInt();
$this->difficulty = $this->getUnsignedVarInt();
}
public function encode(){
$this->reset();
$this->putInt($this->difficulty);
$this->putUnsignedVarInt($this->difficulty);
}
}

View File

@ -40,7 +40,7 @@ class SetEntityDataPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putLong($this->eid);
$this->putEntityId($this->eid);
$meta = Binary::writeMetadata($this->metadata);
$this->put($meta);
}

View File

@ -37,8 +37,8 @@ class SetEntityLinkPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putLong($this->from);
$this->putLong($this->to);
$this->putEntityId($this->from);
$this->putEntityId($this->to);
$this->putByte($this->type);
}

View File

@ -27,10 +27,10 @@ namespace pocketmine\network\protocol;
class SetEntityMotionPacket extends DataPacket{
const NETWORK_ID = Info::SET_ENTITY_MOTION_PACKET;
// eid, motX, motY, motZ
/** @var array[] */
public $entities = [];
public $eid;
public $motionX;
public $motionY;
public $motionZ;
public function clean(){
$this->entities = [];
@ -43,13 +43,8 @@ class SetEntityMotionPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putInt(count($this->entities));
foreach($this->entities as $d){
$this->putLong($d[0]); //eid
$this->putFloat($d[1]); //motX
$this->putFloat($d[2]); //motY
$this->putFloat($d[3]); //motZ
}
$this->putEntityId($this->eid);
$this->putVector3f($this->motionX, $this->motionY, $this->motionZ);
}
}

View File

@ -35,7 +35,7 @@ class SetHealthPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putInt($this->health);
$this->putVarInt($this->health);
}
}

View File

@ -25,17 +25,17 @@ namespace pocketmine\network\protocol;
class SetPlayerGameTypePacket extends DataPacket{
const NETWORK_ID = Info::SET_PLAYER_GAMETYPE_PACKET;
const NETWORK_ID = Info::SET_PLAYER_GAME_TYPE_PACKET;
public $gamemode;
public function decode(){
$this->gamemode = $this->getVarInt();
}
public function encode(){
$this->reset();
$this->putInt($this->gamemode);
$this->putVarInt($this->gamemode);
}
}

View File

@ -27,9 +27,11 @@ namespace pocketmine\network\protocol;
class SetSpawnPositionPacket extends DataPacket{
const NETWORK_ID = Info::SET_SPAWN_POSITION_PACKET;
public $unknown;
public $x;
public $y;
public $z;
public $unknownBool;
public function decode(){
@ -37,9 +39,9 @@ class SetSpawnPositionPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putInt($this->x);
$this->putInt($this->y);
$this->putInt($this->z);
$this->putVarInt($this->unknown);
$this->putBlockCoords($this->x, $this->y, $this->z);
$this->putBool($this->unknownBool);
}
}

View File

@ -35,8 +35,8 @@ class SetTimePacket extends DataPacket{
public function encode(){
$this->reset();
$this->putInt($this->time);
$this->putByte($this->started ? 1 : 0);
$this->putVarInt($this->time);
$this->putBool($this->started);
}
}

View File

@ -0,0 +1,44 @@
<?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\network\protocol;
#include <rules/DataPacket.h>
class SpawnExperienceOrbPacket extends DataPacket{
const NETWORK_ID = Info::SPAWN_EXPERIENCE_ORB_PACKET;
public $x;
public $y;
public $z;
public $amount;
public function decode(){
}
public function encode(){
$this->reset();
$this->putVector3f($this->x, $this->y, $this->z);
$this->putVarInt($this->amount);
}
}

View File

@ -27,18 +27,28 @@ namespace pocketmine\network\protocol;
class StartGamePacket extends DataPacket{
const NETWORK_ID = Info::START_GAME_PACKET;
public $seed;
public $dimension;
public $generator;
public $gamemode;
public $eid;
public $spawnX;
public $spawnY;
public $spawnZ;
public $entityUniqueId;
public $entityRuntimeId;
public $x;
public $y;
public $z;
public $unknown;
public $seed;
public $dimension;
public $generator = 1; //default infinite - 0 old, 1 infinite, 2 flat
public $gamemode;
public $difficulty;
public $spawnX;
public $spawnY;
public $spawnZ;
public $hasAchievementsDisabled = 1;
public $dayCycleStopTime = -1; //-1 = not stopped, any positive value = stopped at that time
public $eduMode = 0;
public $rainLevel;
public $lightningLevel;
public $commandsEnabled;
public $isTexturePacksRequired = 0;
public $levelId = ""; //base64 string, usually the same as world folder name in vanilla
public $worldName;
public function decode(){
@ -46,21 +56,26 @@ class StartGamePacket extends DataPacket{
public function encode(){
$this->reset();
$this->putInt($this->seed);
$this->putByte($this->dimension);
$this->putInt($this->generator);
$this->putInt($this->gamemode);
$this->putLong($this->eid);
$this->putInt($this->spawnX);
$this->putInt($this->spawnY);
$this->putInt($this->spawnZ);
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putByte(1);
$this->putByte(1);
$this->putByte(0);
$this->putString($this->unknown);
$this->putEntityId($this->entityUniqueId); //EntityUniqueID
$this->putEntityId($this->entityRuntimeId); //EntityRuntimeID
$this->putVector3f($this->x, $this->y, $this->z);
$this->putLFloat(0); //TODO: find out what these are (yaw/pitch?)
$this->putLFloat(0);
$this->putVarInt($this->seed);
$this->putVarInt($this->dimension);
$this->putVarInt($this->generator);
$this->putVarInt($this->gamemode);
$this->putVarInt($this->difficulty);
$this->putBlockCoords($this->spawnX, $this->spawnY, $this->spawnZ);
$this->putBool($this->hasAchievementsDisabled);
$this->putVarInt($this->dayCycleStopTime);
$this->putBool($this->eduMode);
$this->putLFloat($this->rainLevel);
$this->putLFloat($this->lightningLevel);
$this->putBool($this->commandsEnabled);
$this->putBool($this->isTexturePacksRequired);
$this->putString($this->levelId);
$this->putString($this->worldName);
}
}

View File

@ -36,8 +36,8 @@ class TakeItemEntityPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putLong($this->target);
$this->putLong($this->eid);
$this->putEntityId($this->target);
$this->putEntityId($this->eid);
}
}

View File

@ -33,6 +33,7 @@ class TextPacket extends DataPacket{
const TYPE_POPUP = 3;
const TYPE_TIP = 4;
const TYPE_SYSTEM = 5;
const TYPE_WHISPER = 6;
public $type;
public $source;

View File

@ -40,15 +40,13 @@ class UpdateAttributesPacket extends DataPacket{
public function encode(){
$this->reset();
$this->putLong($this->entityId);
$this->putShort(count($this->entries));
$this->putEntityId($this->entityId);
$this->putUnsignedVarInt(count($this->entries));
foreach($this->entries as $entry){
$this->putFloat($entry->getMinValue());
$this->putFloat($entry->getMaxValue());
$this->putFloat($entry->getValue());
$this->putLFloat($entry->getMinValue());
$this->putLFloat($entry->getMaxValue());
$this->putLFloat($entry->getValue());
$this->putLFloat($entry->getDefaultValue());
$this->putString($entry->getName());
}
}

Some files were not shown because too many files have changed in this diff Show More