mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-07 12:18:46 +00:00
Merge branch 'minor-next' into major-next
This commit is contained in:
commit
d731f5485a
@ -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());
|
||||
}
|
||||
|
@ -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){
|
||||
|
@ -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];
|
||||
|
@ -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 = [];
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user