mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-23 19:34:15 +00:00
Merge branch 'master' into mcpe-1.2.5
This commit is contained in:
commit
3ca9e6ae98
@ -297,6 +297,15 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
/** @var int|null */
|
||||
protected $lineHeight = null;
|
||||
|
||||
/** @var string */
|
||||
protected $locale = "en_US";
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* Last measurement of player's latency in milliseconds.
|
||||
*/
|
||||
protected $lastPingMeasure = 1;
|
||||
|
||||
/**
|
||||
* @return TranslationContainer|string
|
||||
*/
|
||||
@ -738,6 +747,14 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the player's locale, e.g. en_US.
|
||||
* @return string
|
||||
*/
|
||||
public function getLocale() : string{
|
||||
return $this->locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player changes their skin.
|
||||
* Plugin developers should not use this, use setSkin() and sendSkin() instead.
|
||||
@ -791,6 +808,27 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return $this->port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last measured latency for this player, in milliseconds. This is measured automatically and reported
|
||||
* back by the network interface.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getPing() : int{
|
||||
return $this->lastPingMeasure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the player's last ping measurement.
|
||||
*
|
||||
* @internal Plugins should not use this method.
|
||||
*
|
||||
* @param int $pingMS
|
||||
*/
|
||||
public function updatePing(int $pingMS){
|
||||
$this->lastPingMeasure = $pingMS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Position
|
||||
*/
|
||||
@ -1434,7 +1472,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$this->server->broadcastPacket($entity->getViewers(), $pk);
|
||||
|
||||
$this->inventory->addItem(clone $item);
|
||||
$entity->kill();
|
||||
$entity->flagForDespawn();
|
||||
}elseif($entity instanceof DroppedItem){
|
||||
if($entity->getPickupDelay() <= 0){
|
||||
$item = $entity->getItem();
|
||||
@ -1464,7 +1502,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$this->server->broadcastPacket($entity->getViewers(), $pk);
|
||||
|
||||
$this->inventory->addItem(clone $item);
|
||||
$entity->kill();
|
||||
$entity->flagForDespawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1992,6 +2030,10 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$this->displayName = $this->username;
|
||||
$this->iusername = strtolower($this->username);
|
||||
|
||||
if($packet->locale !== null){
|
||||
$this->locale = $packet->locale;
|
||||
}
|
||||
|
||||
if(count($this->server->getOnlinePlayers()) >= $this->server->getMaxPlayers() and $this->kick("disconnectionScreen.serverFull", false)){
|
||||
return true;
|
||||
}
|
||||
@ -2497,12 +2539,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return true;
|
||||
}
|
||||
|
||||
$pk = new EntityEventPacket();
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->event = EntityEventPacket::USE_ITEM;
|
||||
$this->dataPacket($pk);
|
||||
$this->server->broadcastPacket($this->getViewers(), $pk);
|
||||
|
||||
if($this->isSurvival()){
|
||||
$slot = $this->inventory->getItemInHand();
|
||||
--$slot->count;
|
||||
@ -2673,7 +2709,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev = new PlayerRespawnEvent($this, $this->getSpawn()));
|
||||
|
||||
$realSpawn = $ev->getRespawnPosition()->add(0.5, 0, 0.5);
|
||||
$realSpawn = Position::fromObject($ev->getRespawnPosition()->add(0.5, 0, 0.5), $ev->getRespawnPosition()->getLevel());
|
||||
|
||||
if($realSpawn->distanceSquared($this->getSpawn()->add(0.5, 0, 0.5)) > 0.01){
|
||||
$this->teleport($realSpawn); //If the destination was modified by plugins
|
||||
@ -3626,10 +3662,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
if($source->isCancelled()){
|
||||
return;
|
||||
}elseif($this->getLastDamageCause() === $source and $this->spawned){
|
||||
$pk = new EntityEventPacket();
|
||||
$pk->entityRuntimeId = $this->id;
|
||||
$pk->event = EntityEventPacket::HURT_ANIMATION;
|
||||
$this->dataPacket($pk);
|
||||
$this->broadcastEntityEvent(EntityEventPacket::HURT_ANIMATION);
|
||||
|
||||
if($this->isSurvival()){
|
||||
$this->exhaust(0.3, PlayerExhaustEvent::CAUSE_DAMAGE);
|
||||
|
@ -167,8 +167,8 @@ namespace pocketmine {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(version_compare(RakLib::VERSION, "0.8.1") < 0){
|
||||
echo "[CRITICAL] RakLib version 0.8.1 is required, while you have version " . RakLib::VERSION . "." . PHP_EOL;
|
||||
if(version_compare(RakLib::VERSION, "0.8.2") < 0){
|
||||
echo "[CRITICAL] RakLib version 0.8.2 is required, while you have version " . RakLib::VERSION . "." . PHP_EOL;
|
||||
echo "[CRITICAL] Please update your submodules or use provided builds." . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
@ -1407,6 +1407,9 @@ class Server{
|
||||
* @return Server
|
||||
*/
|
||||
public static function getInstance() : Server{
|
||||
if(self::$instance === null){
|
||||
throw new \RuntimeException("Attempt to retrieve Server instance outside server thread");
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,7 @@ use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\nbt\tag\ShortTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\network\mcpe\protocol\AddEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\EntityEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\MoveEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\RemoveEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\SetEntityDataPacket;
|
||||
@ -470,6 +471,8 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
|
||||
/** @var bool */
|
||||
protected $closed = false;
|
||||
/** @var bool */
|
||||
private $needsDespawn = false;
|
||||
|
||||
/** @var TimingsHandler */
|
||||
protected $timings;
|
||||
@ -1279,15 +1282,20 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
|
||||
$this->lastUpdate = $currentTick;
|
||||
|
||||
if($this->needsDespawn){
|
||||
$this->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!$this->isAlive()){
|
||||
$this->deadTicks += $tickDiff;
|
||||
if($this->deadTicks >= $this->maxDeadTicks){
|
||||
$this->despawnFromAll();
|
||||
if(!$this->isPlayer){
|
||||
$this->close();
|
||||
$this->flagForDespawn();
|
||||
}
|
||||
}
|
||||
return $this->deadTicks < $this->maxDeadTicks;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -1929,6 +1937,13 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flags the entity to be removed from the world on the next tick.
|
||||
*/
|
||||
public function flagForDespawn() : void{
|
||||
$this->needsDespawn = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the entity has been "closed".
|
||||
* @return bool
|
||||
@ -2077,6 +2092,15 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcastEntityEvent(int $eventId, ?int $eventData = null, ?array $players = null) : void{
|
||||
$pk = new EntityEventPacket();
|
||||
$pk->entityRuntimeId = $this->id;
|
||||
$pk->event = $eventId;
|
||||
$pk->data = $eventData ?? 0;
|
||||
|
||||
$this->server->broadcastPacket($players ?? $this->getViewers(), $pk);
|
||||
}
|
||||
|
||||
public function __destruct(){
|
||||
$this->close();
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ class FallingSand extends Entity{
|
||||
}
|
||||
|
||||
if($this->onGround or $blockTarget !== null){
|
||||
$this->kill();
|
||||
$this->flagForDespawn();
|
||||
|
||||
$block = $this->level->getBlock($pos);
|
||||
if($block->getId() > 0 and $block->isTransparent() and !$block->canBeReplaced()){
|
||||
|
@ -118,7 +118,7 @@ class Item extends Entity{
|
||||
if($ev->isCancelled()){
|
||||
$this->age = 0;
|
||||
}else{
|
||||
$this->kill();
|
||||
$this->flagForDespawn();
|
||||
$hasUpdate = true;
|
||||
}
|
||||
}
|
||||
|
@ -108,10 +108,7 @@ abstract class Living extends Entity implements Damageable{
|
||||
parent::setHealth($amount);
|
||||
$this->attributeMap->getAttribute(Attribute::HEALTH)->setValue(ceil($this->getHealth()), true);
|
||||
if($this->isAlive() and !$wasAlive){
|
||||
$pk = new EntityEventPacket();
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->event = EntityEventPacket::RESPAWN;
|
||||
$this->server->broadcastPacket($this->hasSpawned, $pk);
|
||||
$this->broadcastEntityEvent(EntityEventPacket::RESPAWN);
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,10 +373,7 @@ abstract class Living extends Entity implements Damageable{
|
||||
|
||||
$this->setAbsorption(max(0, $this->getAbsorption() + $source->getDamage(EntityDamageEvent::MODIFIER_ABSORPTION)));
|
||||
|
||||
$pk = new EntityEventPacket();
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->event = $this->getHealth() <= 0 ? EntityEventPacket::DEATH_ANIMATION : EntityEventPacket::HURT_ANIMATION; //Ouch!
|
||||
$this->server->broadcastPacket($this->hasSpawned, $pk);
|
||||
$this->broadcastEntityEvent($this->getHealth() <= 0 ? EntityEventPacket::DEATH_ANIMATION : EntityEventPacket::HURT_ANIMATION); //Ouch!
|
||||
|
||||
$this->attackTime = 10; //0.5 seconds cooldown
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ class PrimedTNT extends Entity implements Explosive{
|
||||
$this->fuse -= $tickDiff;
|
||||
|
||||
if($this->fuse <= 0){
|
||||
$this->kill();
|
||||
$this->flagForDespawn();
|
||||
$this->explode();
|
||||
}
|
||||
}
|
||||
|
@ -64,10 +64,7 @@ class Squid extends WaterAnimal{
|
||||
$this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize();
|
||||
}
|
||||
|
||||
$pk = new EntityEventPacket();
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->event = EntityEventPacket::SQUID_INK_CLOUD;
|
||||
$this->server->broadcastPacket($this->hasSpawned, $pk);
|
||||
$this->broadcastEntityEvent(EntityEventPacket::SQUID_INK_CLOUD);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ class Arrow extends Projectile{
|
||||
}
|
||||
|
||||
if($this->age > 1200){
|
||||
$this->close();
|
||||
$this->flagForDespawn();
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ abstract class Projectile extends Entity{
|
||||
}
|
||||
}
|
||||
|
||||
$this->close();
|
||||
$this->flagForDespawn();
|
||||
}
|
||||
|
||||
public function saveNBT(){
|
||||
|
@ -40,7 +40,7 @@ abstract class Throwable extends Projectile{
|
||||
|
||||
if($this->age > 1200 or $this->isCollided){
|
||||
//TODO: hit particles
|
||||
$this->kill();
|
||||
$this->flagForDespawn();
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ class Bow extends Tool{
|
||||
$entity = $ev->getProjectile(); //This might have been changed by plugins
|
||||
|
||||
if($ev->isCancelled()){
|
||||
$entity->kill();
|
||||
$entity->flagForDespawn();
|
||||
$player->getInventory()->sendContents($player);
|
||||
}else{
|
||||
$entity->setMotion($entity->getMotion()->multiply($ev->getForce()));
|
||||
@ -87,7 +87,7 @@ class Bow extends Tool{
|
||||
if($entity instanceof Projectile){
|
||||
$player->getServer()->getPluginManager()->callEvent($projectileEv = new ProjectileLaunchEvent($entity));
|
||||
if($projectileEv->isCancelled()){
|
||||
$ev->getProjectile()->kill();
|
||||
$ev->getProjectile()->flagForDespawn();
|
||||
}else{
|
||||
$ev->getProjectile()->spawnToAll();
|
||||
$player->level->addSound(new LaunchSound($player), $player->getViewers());
|
||||
|
@ -49,7 +49,7 @@ abstract class ProjectileItem extends Item{
|
||||
if($projectile instanceof Projectile){
|
||||
$player->getServer()->getPluginManager()->callEvent($projectileEv = new ProjectileLaunchEvent($projectile));
|
||||
if($projectileEv->isCancelled()){
|
||||
$projectile->kill();
|
||||
$projectile->flagForDespawn();
|
||||
}else{
|
||||
$projectile->spawnToAll();
|
||||
$player->getLevel()->addSound(new LaunchSound($player), $player->getViewers());
|
||||
|
@ -237,6 +237,12 @@ class RakLibInterface implements ServerInstance, AdvancedSourceInterface{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function updatePing(string $identifier, int $pingMS){
|
||||
if(isset($this->players[$identifier])){
|
||||
$this->players[$identifier]->updatePing($pingMS);
|
||||
}
|
||||
}
|
||||
|
||||
private function getPacket($buffer){
|
||||
$pid = ord($buffer{0});
|
||||
if(($data = PacketPool::getPacketById($pid)) === null){
|
||||
|
@ -33,6 +33,7 @@ class EntityEventPacket extends DataPacket{
|
||||
|
||||
const HURT_ANIMATION = 2;
|
||||
const DEATH_ANIMATION = 3;
|
||||
const ARM_SWING = 4;
|
||||
|
||||
const TAME_FAIL = 6;
|
||||
const TAME_SUCCESS = 7;
|
||||
@ -44,12 +45,41 @@ class EntityEventPacket extends DataPacket{
|
||||
const FISH_HOOK_HOOK = 13;
|
||||
const FISH_HOOK_TEASE = 14;
|
||||
const SQUID_INK_CLOUD = 15;
|
||||
const AMBIENT_SOUND = 16;
|
||||
const ZOMBIE_VILLAGER_CURE = 16;
|
||||
|
||||
const RESPAWN = 18;
|
||||
const IRON_GOLEM_OFFER_FLOWER = 19;
|
||||
const IRON_GOLEM_WITHDRAW_FLOWER = 20;
|
||||
const LOVE_PARTICLES = 21; //breeding
|
||||
|
||||
const WITCH_SPELL_PARTICLES = 24;
|
||||
const FIREWORK_PARTICLES = 25;
|
||||
|
||||
const SILVERFISH_SPAWN_ANIMATION = 27;
|
||||
|
||||
const WITCH_DRINK_POTION = 29;
|
||||
const WITCH_THROW_POTION = 30;
|
||||
const MINECART_TNT_PRIME_FUSE = 31;
|
||||
|
||||
const PLAYER_ADD_XP_LEVELS = 34;
|
||||
const ELDER_GUARDIAN_CURSE = 35;
|
||||
const AGENT_ARM_SWING = 36;
|
||||
const ENDER_DRAGON_DEATH = 37;
|
||||
const DUST_PARTICLES = 38; //not sure what this is
|
||||
|
||||
const EATING_ITEM = 57;
|
||||
|
||||
const BABY_ANIMAL_FEED = 60; //green particles, like bonemeal on crops
|
||||
const DEATH_SMOKE_CLOUD = 61;
|
||||
const COMPLETE_TRADE = 62;
|
||||
const REMOVE_LEASH = 63; //data 1 = cut leash
|
||||
|
||||
const CONSUME_TOTEM = 65;
|
||||
const PLAYER_CHECK_TREASURE_HUNTER_ACHIEVEMENT = 66; //mojang...
|
||||
const ENTITY_SPAWN = 67; //used for MinecraftEventing stuff, not needed
|
||||
const DRAGON_PUKE = 68; //they call this puke particles
|
||||
const ITEM_ENTITY_MERGE = 69;
|
||||
|
||||
//TODO: add more events
|
||||
|
||||
/** @var int */
|
||||
|
@ -50,6 +50,8 @@ class LoginPacket extends DataPacket{
|
||||
public $identityPublicKey;
|
||||
/** @var string */
|
||||
public $serverAddress;
|
||||
/** @var string */
|
||||
public $locale;
|
||||
|
||||
/** @var array (the "chain" index contains one or more JWTs) */
|
||||
public $chainData = [];
|
||||
@ -119,6 +121,8 @@ class LoginPacket extends DataPacket{
|
||||
|
||||
$this->clientId = $this->clientData["ClientRandomId"] ?? null;
|
||||
$this->serverAddress = $this->clientData["ServerAddress"] ?? null;
|
||||
|
||||
$this->locale = $this->clientData["LanguageCode"] ?? null;
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
|
@ -160,7 +160,7 @@ auto-report:
|
||||
|
||||
anonymous-statistics:
|
||||
#Sends anonymous statistics for data aggregation, plugin usage tracking
|
||||
enabled: true
|
||||
enabled: false #TODO: re-enable this when we have a new stats host
|
||||
host: stats.pocketmine.net
|
||||
|
||||
auto-updater:
|
||||
|
@ -39,7 +39,7 @@ class UUID{
|
||||
}
|
||||
|
||||
public function equals(UUID $uuid) : bool{
|
||||
return $uuid->parts[0] === $this->parts[0] and $uuid->parts[1] === $this->parts[1] and $uuid->parts[2] === $this->parts[2] and $uuid->parts[3] === $this->parts[3];
|
||||
return $uuid->parts === $this->parts;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit a10881b0078559f646b570a12304dba71658357c
|
||||
Subproject commit 268a93c575c3ffa699e8a66b854834989245bb05
|
2
src/spl
2
src/spl
@ -1 +1 @@
|
||||
Subproject commit c4d4841586a19d95f25cc02b23baa00dbbc0b0d7
|
||||
Subproject commit cf7738721e7342c018a91ad300108b2dd95c7224
|
Loading…
x
Reference in New Issue
Block a user