Merge remote-tracking branch 'origin/stable' into minor-next

This commit is contained in:
Dylan K. Taylor 2023-04-19 23:57:26 +01:00
commit 71b78b02d3
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
6 changed files with 64 additions and 51 deletions

View File

@ -115,6 +115,8 @@ abstract class Entity{
/** @var Block[]|null */ /** @var Block[]|null */
protected $blocksAround; protected $blocksAround;
private bool $checkBlockIntersectionsNextTick = true;
/** @var Location */ /** @var Location */
protected $location; protected $location;
/** @var Location */ /** @var Location */
@ -649,7 +651,10 @@ abstract class Entity{
$hasUpdate = false; $hasUpdate = false;
$this->checkBlockIntersections(); if($this->checkBlockIntersectionsNextTick){
$this->checkBlockIntersections();
}
$this->checkBlockIntersectionsNextTick = true;
if($this->location->y <= World::Y_MIN - 16 && $this->isAlive()){ if($this->location->y <= World::Y_MIN - 16 && $this->isAlive()){
$ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_VOID, 10); $ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_VOID, 10);
@ -1308,6 +1313,7 @@ abstract class Entity{
} }
protected function checkBlockIntersections() : void{ protected function checkBlockIntersections() : void{
$this->checkBlockIntersectionsNextTick = false;
$vectors = []; $vectors = [];
foreach($this->getBlocksAroundWithEntityInsideActions() as $block){ foreach($this->getBlocksAroundWithEntityInsideActions() as $block){
@ -1319,10 +1325,12 @@ abstract class Entity{
} }
} }
$vector = Vector3::sum(...$vectors); if(count($vectors) > 0){
if($vector->lengthSquared() > 0){ $vector = Vector3::sum(...$vectors);
$d = 0.014; if($vector->lengthSquared() > 0){
$this->motion = $this->motion->addVector($vector->normalize()->multiply($d)); $d = 0.014;
$this->motion = $this->motion->addVector($vector->normalize()->multiply($d));
}
} }
} }

View File

@ -57,8 +57,11 @@ class RegisteredListener{
return; return;
} }
$this->timings->startTiming(); $this->timings->startTiming();
($this->handler)($event); try{
$this->timings->stopTiming(); ($this->handler)($event);
}finally{
$this->timings->stopTiming();
}
} }
public function isHandlingCancelled() : bool{ public function isHandlingCancelled() : bool{

View File

@ -353,30 +353,35 @@ class Item implements \JsonSerializable{
} }
protected function serializeCompoundTag(CompoundTag $tag) : void{ protected function serializeCompoundTag(CompoundTag $tag) : void{
$display = $tag->getCompoundTag(self::TAG_DISPLAY) ?? new CompoundTag(); $display = $tag->getCompoundTag(self::TAG_DISPLAY);
$this->hasCustomName() ? if($this->customName !== ""){
$display->setString(self::TAG_DISPLAY_NAME, $this->getCustomName()) : $display ??= new CompoundTag();
$display->removeTag(self::TAG_DISPLAY_NAME); $display->setString(self::TAG_DISPLAY_NAME, $this->customName);
}else{
$display?->removeTag(self::TAG_DISPLAY_NAME);
}
if(count($this->lore) > 0){ if(count($this->lore) > 0){
$loreTag = new ListTag(); $loreTag = new ListTag();
foreach($this->lore as $line){ foreach($this->lore as $line){
$loreTag->push(new StringTag($line)); $loreTag->push(new StringTag($line));
} }
$display ??= new CompoundTag();
$display->setTag(self::TAG_DISPLAY_LORE, $loreTag); $display->setTag(self::TAG_DISPLAY_LORE, $loreTag);
}else{ }else{
$display->removeTag(self::TAG_DISPLAY_LORE); $display?->removeTag(self::TAG_DISPLAY_LORE);
} }
$display->count() > 0 ? $display !== null && $display->count() > 0 ?
$tag->setTag(self::TAG_DISPLAY, $display) : $tag->setTag(self::TAG_DISPLAY, $display) :
$tag->removeTag(self::TAG_DISPLAY); $tag->removeTag(self::TAG_DISPLAY);
if($this->hasEnchantments()){ if(count($this->enchantments) > 0){
$ench = new ListTag(); $ench = new ListTag();
foreach($this->getEnchantments() as $enchantmentInstance){ $enchantmentIdMap = EnchantmentIdMap::getInstance();
foreach($this->enchantments as $enchantmentInstance){
$ench->push(CompoundTag::create() $ench->push(CompoundTag::create()
->setShort(self::TAG_ENCH_ID, EnchantmentIdMap::getInstance()->toId($enchantmentInstance->getType())) ->setShort(self::TAG_ENCH_ID, $enchantmentIdMap->toId($enchantmentInstance->getType()))
->setShort(self::TAG_ENCH_LVL, $enchantmentInstance->getLevel()) ->setShort(self::TAG_ENCH_LVL, $enchantmentInstance->getLevel())
); );
} }
@ -385,8 +390,8 @@ class Item implements \JsonSerializable{
$tag->removeTag(self::TAG_ENCH); $tag->removeTag(self::TAG_ENCH);
} }
($blockData = $this->getCustomBlockData()) !== null ? $this->blockEntityTag !== null ?
$tag->setTag(self::TAG_BLOCK_ENTITY_TAG, clone $blockData) : $tag->setTag(self::TAG_BLOCK_ENTITY_TAG, clone $this->blockEntityTag) :
$tag->removeTag(self::TAG_BLOCK_ENTITY_TAG); $tag->removeTag(self::TAG_BLOCK_ENTITY_TAG);
if(count($this->canPlaceOn) > 0){ if(count($this->canPlaceOn) > 0){

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\convert; namespace pocketmine\network\mcpe\convert;
use pocketmine\block\Block;
use pocketmine\block\BlockLegacyIds; use pocketmine\block\BlockLegacyIds;
use pocketmine\item\Durable; use pocketmine\item\Durable;
use pocketmine\item\Item; use pocketmine\item\Item;
@ -135,14 +136,16 @@ class TypeConverter{
if($itemStack->isNull()){ if($itemStack->isNull()){
return ItemStack::null(); return ItemStack::null();
} }
$nbt = null; $nbt = $itemStack->getNamedTag();
if($itemStack->hasNamedTag()){ if($nbt->count() === 0){
$nbt = clone $itemStack->getNamedTag(); $nbt = null;
}else{
$nbt = clone $nbt;
} }
$isBlockItem = $itemStack->getId() < 256; $internalId = $itemStack->getId();
$internalMeta = $itemStack->getMeta();
$idMeta = ItemTranslator::getInstance()->toNetworkIdQuiet($itemStack->getId(), $itemStack->getMeta()); $idMeta = ItemTranslator::getInstance()->toNetworkIdQuiet($internalId, $internalMeta);
if($idMeta === null){ if($idMeta === null){
//Display unmapped items as INFO_UPDATE, but stick something in their NBT to make sure they don't stack with //Display unmapped items as INFO_UPDATE, but stick something in their NBT to make sure they don't stack with
//other unmapped items. //other unmapped items.
@ -150,8 +153,8 @@ class TypeConverter{
if($nbt === null){ if($nbt === null){
$nbt = new CompoundTag(); $nbt = new CompoundTag();
} }
$nbt->setInt(self::PM_ID_TAG, $itemStack->getId()); $nbt->setInt(self::PM_ID_TAG, $internalId);
$nbt->setInt(self::PM_META_TAG, $itemStack->getMeta()); $nbt->setInt(self::PM_META_TAG, $internalMeta);
}else{ }else{
[$id, $meta] = $idMeta; [$id, $meta] = $idMeta;
@ -166,23 +169,15 @@ class TypeConverter{
} }
$nbt->setInt(self::DAMAGE_TAG, $itemStack->getDamage()); $nbt->setInt(self::DAMAGE_TAG, $itemStack->getDamage());
$meta = 0; $meta = 0;
}elseif($isBlockItem && $itemStack->getMeta() !== 0){
//TODO HACK: This foul-smelling code ensures that we can correctly deserialize an item when the
//client sends it back to us, because as of 1.16.220, blockitems quietly discard their metadata
//client-side. Aside from being very annoying, this also breaks various server-side behaviours.
if($nbt === null){
$nbt = new CompoundTag();
}
$nbt->setInt(self::PM_META_TAG, $itemStack->getMeta());
$meta = 0;
} }
} }
$blockRuntimeId = 0; $blockRuntimeId = 0;
if($isBlockItem){ if($internalId < 256){
$block = $itemStack->getBlock(); $block = $itemStack->getBlock();
if($block->getId() !== BlockLegacyIds::AIR){ if($block->getId() !== BlockLegacyIds::AIR){
$blockRuntimeId = RuntimeBlockMapping::getInstance()->toRuntimeId($block->getFullId()); $blockRuntimeId = RuntimeBlockMapping::getInstance()->toRuntimeId($block->getFullId());
$meta = 0;
} }
} }
@ -208,6 +203,11 @@ class TypeConverter{
$compound = $itemStack->getNbt(); $compound = $itemStack->getNbt();
[$id, $meta] = ItemTranslator::getInstance()->fromNetworkId($itemStack->getId(), $itemStack->getMeta()); [$id, $meta] = ItemTranslator::getInstance()->fromNetworkId($itemStack->getId(), $itemStack->getMeta());
if($itemStack->getBlockRuntimeId() !== 0){
//blockitem meta is zeroed out by the client, so we have to infer it from the block runtime ID
$blockFullId = RuntimeBlockMapping::getInstance()->fromRuntimeId($itemStack->getBlockRuntimeId());
$meta = $blockFullId & Block::INTERNAL_METADATA_MASK;
}
if($compound !== null){ if($compound !== null){
$compound = clone $compound; $compound = clone $compound;
@ -222,12 +222,6 @@ class TypeConverter{
$compound->removeTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION); $compound->removeTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION);
$compound->setTag(self::DAMAGE_TAG, $conflicted); $compound->setTag(self::DAMAGE_TAG, $conflicted);
} }
}elseif(($metaTag = $compound->getTag(self::PM_META_TAG)) instanceof IntTag){
//TODO HACK: This foul-smelling code ensures that we can correctly deserialize an item when the
//client sends it back to us, because as of 1.16.220, blockitems quietly discard their metadata
//client-side. Aside from being very annoying, this also breaks various server-side behaviours.
$meta = $metaTag->getValue();
$compound->removeTag(self::PM_META_TAG);
} }
if($compound->count() === 0){ if($compound->count() === 0){
$compound = null; $compound = null;

View File

@ -53,6 +53,7 @@ use function implode;
use function mt_rand; use function mt_rand;
use function random_bytes; use function random_bytes;
use function rtrim; use function rtrim;
use function str_split;
use function substr; use function substr;
use const PHP_INT_MAX; use const PHP_INT_MAX;
@ -196,7 +197,7 @@ class RakLibInterface implements ServerEventListener, AdvancedNetworkInterface{
try{ try{
$session->handleEncoded($buf); $session->handleEncoded($buf);
}catch(PacketHandlingException $e){ }catch(PacketHandlingException $e){
$errorId = bin2hex(random_bytes(6)); $errorId = implode("-", str_split(bin2hex(random_bytes(6)), 4));
$logger = $session->getLogger(); $logger = $session->getLogger();
$logger->error("Bad packet (error ID $errorId): " . $e->getMessage()); $logger->error("Bad packet (error ID $errorId): " . $e->getMessage());

View File

@ -24,12 +24,10 @@ declare(strict_types=1);
namespace pocketmine\tools\simulate_chunk_selector; namespace pocketmine\tools\simulate_chunk_selector;
use pocketmine\player\ChunkSelector; use pocketmine\player\ChunkSelector;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Utils; use pocketmine\utils\Utils;
use pocketmine\world\format\Chunk; use pocketmine\world\format\Chunk;
use pocketmine\world\World; use pocketmine\world\World;
use Symfony\Component\Filesystem\Path; use Symfony\Component\Filesystem\Path;
use function assert;
use function count; use function count;
use function dirname; use function dirname;
use function fwrite; use function fwrite;
@ -128,7 +126,12 @@ if(count(getopt("", ["help"])) !== 0){
exit(0); exit(0);
} }
foreach(Utils::stringifyKeys(getopt("", ["radius:", "baseX:", "baseZ:", "scale:", "chunksPerStep:"])) as $name => $value){ $opts = getopt("", ["radius:", "baseX:", "baseZ:", "scale:", "chunksPerStep:", "output:"]);
foreach(["radius", "baseX", "baseZ", "scale", "chunksPerStep"] as $name){
$value = $opts[$name] ?? null;
if($value === null){
continue;
}
if(!is_string($value) || (string) ((int) $value) !== $value){ if(!is_string($value) || (string) ((int) $value) !== $value){
fwrite(STDERR, "Value for --$name must be an integer\n"); fwrite(STDERR, "Value for --$name must be an integer\n");
exit(1); exit(1);
@ -139,8 +142,7 @@ foreach(Utils::stringifyKeys(getopt("", ["radius:", "baseX:", "baseZ:", "scale:"
"baseX" => ($baseX = $value), "baseX" => ($baseX = $value),
"baseZ" => ($baseZ = $value), "baseZ" => ($baseZ = $value),
"scale" => ($scale = $value), "scale" => ($scale = $value),
"chunksPerStep" => ($nChunksPerStep = $value), "chunksPerStep" => ($nChunksPerStep = $value)
default => throw new AssumptionFailedError("getopt() returned unknown option")
}; };
} }
if($radius === null){ if($radius === null){
@ -149,10 +151,10 @@ if($radius === null){
} }
$outputDirectory = null; $outputDirectory = null;
foreach(Utils::stringifyKeys(getopt("", ["output:"])) as $name => $value){ if(isset($opts["output"])){
assert($name === "output"); $value = $opts["output"];
if(!is_string($value)){ if(!is_string($value)){
fwrite(STDERR, "Value for --$name must be a string\n"); fwrite(STDERR, "Value for --output be a string\n");
exit(1); exit(1);
} }
if(!@mkdir($value) && !is_dir($value)){ if(!@mkdir($value) && !is_dir($value)){