Merge branch 'minor-next' into major-next

This commit is contained in:
Dylan K. Taylor 2023-03-31 21:29:42 +01:00
commit d731f5485a
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
5 changed files with 89 additions and 22 deletions

View File

@ -113,7 +113,12 @@ class ItemStackRequestExecutor{
*/
protected function getBuilderInventoryAndSlot(ItemStackRequestSlotInfo $info) : array{
$windowId = ItemStackContainerIdTranslator::translate($info->getContainerId(), $this->inventoryManager->getCurrentWindowId());
$windowAndSlot = $this->inventoryManager->locateWindowAndSlot($windowId, $info->getSlotId());
$slotId = $info->getSlotId();
if($info->getContainerId() === ContainerUIIds::OFFHAND && $slotId === 1){
//TODO: HACK! The client sends an incorrect slot ID for the offhand as of 1.19.70
$slotId = 0;
}
$windowAndSlot = $this->inventoryManager->locateWindowAndSlot($windowId, $slotId);
if($windowAndSlot === null){
throw new ItemStackRequestProcessException("No open inventory matches container UI ID: " . $info->getContainerId() . ", slot ID: " . $info->getSlotId());
}

View File

@ -53,6 +53,10 @@ final class ItemStackResponseBuilder{
* @phpstan-return array{Inventory, int}
*/
private function getInventoryAndSlot(int $containerInterfaceId, int $slotId) : ?array{
if($containerInterfaceId === ContainerUIIds::OFFHAND && $slotId === 1){
//TODO: HACK! The client sends an incorrect slot ID for the offhand as of 1.19.70
$slotId = 0;
}
$windowId = ItemStackContainerIdTranslator::translate($containerInterfaceId, $this->inventoryManager->getCurrentWindowId());
$windowAndSlot = $this->inventoryManager->locateWindowAndSlot($windowId, $slotId);
if($windowAndSlot === null){

View File

@ -28,9 +28,9 @@ use pocketmine\entity\Entity;
use pocketmine\event\Event;
use pocketmine\network\mcpe\protocol\ClientboundPacket;
use pocketmine\network\mcpe\protocol\ServerboundPacket;
use pocketmine\player\Player;
use pocketmine\scheduler\TaskHandler;
use function get_class;
use function str_starts_with;
abstract class Timings{
public const INCLUDED_BY_OTHER_TIMINGS_PREFIX = "** ";
@ -202,8 +202,14 @@ abstract class Timings{
public static function getEntityTimings(Entity $entity) : TimingsHandler{
self::init();
$entityType = (new \ReflectionClass($entity))->getShortName();
$reflect = new \ReflectionClass($entity);
$entityType = $reflect->getShortName();
if(!isset(self::$entityTypeTimingMap[$entityType])){
//the timings viewer calculates average player count by looking at this timer, so we need to ensure it has
//a name it can identify. However, we also want to make it obvious if this is a custom Player class.
if($entity instanceof Player && $reflect->getName() !== Player::class){
$entityType = "Player (" . $reflect->getName() . ")";
}
self::$entityTypeTimingMap[$entityType] = new TimingsHandler(self::INCLUDED_BY_OTHER_TIMINGS_PREFIX . "Entity Tick - " . $entityType, self::$tickEntity);
}
@ -273,12 +279,7 @@ abstract class Timings{
public static function getEventTimings(Event $event) : TimingsHandler{
$eventClass = get_class($event);
if(!isset(self::$events[$eventClass])){
if(str_starts_with($eventClass, "pocketmine\\event\\")){
$name = (new \ReflectionClass($event))->getShortName();
}else{
$name = $eventClass;
}
self::$events[$eventClass] = new TimingsHandler($name, group: "Events");
self::$events[$eventClass] = new TimingsHandler($eventClass, group: "Events");
}
return self::$events[$eventClass];

View File

@ -28,6 +28,8 @@ use pocketmine\Server;
use pocketmine\utils\Utils;
use function count;
use function hrtime;
use function implode;
use function spl_object_id;
class TimingsHandler{
private static bool $enabled = false;
@ -48,7 +50,16 @@ class TimingsHandler{
$avg = $time / $count;
$group = $timings->getGroup();
$groups[$group][] = $timings->getName() . " Time: $time Count: " . $count . " Avg: $avg Violations: " . $timings->getViolations();
$groups[$group][] = implode(" ", [
$timings->getName(),
"Time: $time",
"Count: $count",
"Avg: $avg",
"Violations: " . $timings->getViolations(),
"RecordId: " . $timings->getId(),
"ParentRecordId: " . ($timings->getParentId() ?? "none"),
"TimerId: " . $timings->getTimerId()
]);
}
$result = [];
@ -107,9 +118,15 @@ class TimingsHandler{
}
}
private ?TimingsRecord $record = null;
private ?TimingsRecord $rootRecord = null;
private int $timingDepth = 0;
/**
* @var TimingsRecord[]
* @phpstan-var array<int, TimingsRecord>
*/
private array $recordsByParent = [];
public function __construct(
private string $name,
private ?TimingsHandler $parent = null,
@ -128,13 +145,24 @@ class TimingsHandler{
private function internalStartTiming(int $now) : void{
if(++$this->timingDepth === 1){
if($this->record === null){
$this->record = new TimingsRecord($this);
}
$this->record->startTiming($now);
if($this->parent !== null){
$this->parent->internalStartTiming($now);
}
$current = TimingsRecord::getCurrentRecord();
if($current !== null){
$record = $this->recordsByParent[spl_object_id($current)] ?? null;
if($record === null){
$record = new TimingsRecord($this, $current);
$this->recordsByParent[spl_object_id($current)] = $record;
}
}else{
if($this->rootRecord === null){
$this->rootRecord = new TimingsRecord($this, null);
}
$record = $this->rootRecord;
}
$record->startTiming($now);
}
}
@ -155,9 +183,12 @@ class TimingsHandler{
return;
}
if($this->record !== null){
//this might be null if a timings reset occurred while the timer was running
$this->record->stopTiming($now);
$record = TimingsRecord::getCurrentRecord();
if($record !== null){
if($record->getTimerId() !== spl_object_id($this)){
throw new \LogicException("Timer \"" . $record->getName() . "\" should have been stopped before stopping timer \"" . $this->name . "\"");
}
$record->stopTiming($now);
}
if($this->parent !== null){
$this->parent->internalStopTiming($now);
@ -184,6 +215,7 @@ class TimingsHandler{
* @internal
*/
public function destroyCycles() : void{
$this->record = null;
$this->rootRecord = null;
$this->recordsByParent = [];
}
}

View File

@ -24,7 +24,8 @@ declare(strict_types=1);
namespace pocketmine\timings;
use pocketmine\Server;
use function round;
use pocketmine\utils\AssumptionFailedError;
use function floor;
use function spl_object_id;
/**
@ -39,11 +40,14 @@ final class TimingsRecord{
*/
private static array $records = [];
private static ?self $currentRecord = null;
public static function clearRecords() : void{
foreach(self::$records as $record){
$record->handler->destroyCycles();
}
self::$records = [];
self::$currentRecord = null;
}
/**
@ -56,7 +60,7 @@ final class TimingsRecord{
if($measure){
foreach(self::$records as $record){
if($record->curTickTotal > Server::TARGET_NANOSECONDS_PER_TICK){
$record->violations += (int) round($record->curTickTotal / Server::TARGET_NANOSECONDS_PER_TICK);
$record->violations += (int) floor($record->curTickTotal / Server::TARGET_NANOSECONDS_PER_TICK);
}
$record->curTickTotal = 0;
$record->curCount = 0;
@ -81,11 +85,18 @@ final class TimingsRecord{
public function __construct(
//I'm not the biggest fan of this cycle, but it seems to be the most effective way to avoid leaking anything.
private TimingsHandler $handler
private TimingsHandler $handler,
private ?TimingsRecord $parentRecord
){
self::$records[spl_object_id($this)] = $this;
}
public function getId() : int{ return spl_object_id($this); }
public function getParentId() : ?int{ return $this->parentRecord?->getId(); }
public function getTimerId() : int{ return spl_object_id($this->handler); }
public function getName() : string{ return $this->handler->getName(); }
public function getGroup() : string{ return $this->handler->getGroup(); }
@ -104,12 +115,22 @@ final class TimingsRecord{
public function startTiming(int $now) : void{
$this->start = $now;
self::$currentRecord = $this;
}
public function stopTiming(int $now) : void{
if($this->start == 0){
return;
}
if(self::$currentRecord !== $this){
if(self::$currentRecord === null){
//timings may have been stopped while this timer was running
return;
}
throw new AssumptionFailedError("stopTiming() called on a non-current timer");
}
self::$currentRecord = $this->parentRecord;
$diff = $now - $this->start;
$this->totalTime += $diff;
$this->curTickTotal += $diff;
@ -117,4 +138,8 @@ final class TimingsRecord{
++$this->count;
$this->start = 0;
}
public static function getCurrentRecord() : ?self{
return self::$currentRecord;
}
}