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{
|
protected function getBuilderInventoryAndSlot(ItemStackRequestSlotInfo $info) : array{
|
||||||
$windowId = ItemStackContainerIdTranslator::translate($info->getContainerId(), $this->inventoryManager->getCurrentWindowId());
|
$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){
|
if($windowAndSlot === null){
|
||||||
throw new ItemStackRequestProcessException("No open inventory matches container UI ID: " . $info->getContainerId() . ", slot ID: " . $info->getSlotId());
|
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}
|
* @phpstan-return array{Inventory, int}
|
||||||
*/
|
*/
|
||||||
private function getInventoryAndSlot(int $containerInterfaceId, int $slotId) : ?array{
|
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());
|
$windowId = ItemStackContainerIdTranslator::translate($containerInterfaceId, $this->inventoryManager->getCurrentWindowId());
|
||||||
$windowAndSlot = $this->inventoryManager->locateWindowAndSlot($windowId, $slotId);
|
$windowAndSlot = $this->inventoryManager->locateWindowAndSlot($windowId, $slotId);
|
||||||
if($windowAndSlot === null){
|
if($windowAndSlot === null){
|
||||||
|
@ -28,9 +28,9 @@ use pocketmine\entity\Entity;
|
|||||||
use pocketmine\event\Event;
|
use pocketmine\event\Event;
|
||||||
use pocketmine\network\mcpe\protocol\ClientboundPacket;
|
use pocketmine\network\mcpe\protocol\ClientboundPacket;
|
||||||
use pocketmine\network\mcpe\protocol\ServerboundPacket;
|
use pocketmine\network\mcpe\protocol\ServerboundPacket;
|
||||||
|
use pocketmine\player\Player;
|
||||||
use pocketmine\scheduler\TaskHandler;
|
use pocketmine\scheduler\TaskHandler;
|
||||||
use function get_class;
|
use function get_class;
|
||||||
use function str_starts_with;
|
|
||||||
|
|
||||||
abstract class Timings{
|
abstract class Timings{
|
||||||
public const INCLUDED_BY_OTHER_TIMINGS_PREFIX = "** ";
|
public const INCLUDED_BY_OTHER_TIMINGS_PREFIX = "** ";
|
||||||
@ -202,8 +202,14 @@ abstract class Timings{
|
|||||||
|
|
||||||
public static function getEntityTimings(Entity $entity) : TimingsHandler{
|
public static function getEntityTimings(Entity $entity) : TimingsHandler{
|
||||||
self::init();
|
self::init();
|
||||||
$entityType = (new \ReflectionClass($entity))->getShortName();
|
$reflect = new \ReflectionClass($entity);
|
||||||
|
$entityType = $reflect->getShortName();
|
||||||
if(!isset(self::$entityTypeTimingMap[$entityType])){
|
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);
|
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{
|
public static function getEventTimings(Event $event) : TimingsHandler{
|
||||||
$eventClass = get_class($event);
|
$eventClass = get_class($event);
|
||||||
if(!isset(self::$events[$eventClass])){
|
if(!isset(self::$events[$eventClass])){
|
||||||
if(str_starts_with($eventClass, "pocketmine\\event\\")){
|
self::$events[$eventClass] = new TimingsHandler($eventClass, group: "Events");
|
||||||
$name = (new \ReflectionClass($event))->getShortName();
|
|
||||||
}else{
|
|
||||||
$name = $eventClass;
|
|
||||||
}
|
|
||||||
self::$events[$eventClass] = new TimingsHandler($name, group: "Events");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$events[$eventClass];
|
return self::$events[$eventClass];
|
||||||
|
@ -28,6 +28,8 @@ use pocketmine\Server;
|
|||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
use function count;
|
use function count;
|
||||||
use function hrtime;
|
use function hrtime;
|
||||||
|
use function implode;
|
||||||
|
use function spl_object_id;
|
||||||
|
|
||||||
class TimingsHandler{
|
class TimingsHandler{
|
||||||
private static bool $enabled = false;
|
private static bool $enabled = false;
|
||||||
@ -48,7 +50,16 @@ class TimingsHandler{
|
|||||||
$avg = $time / $count;
|
$avg = $time / $count;
|
||||||
|
|
||||||
$group = $timings->getGroup();
|
$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 = [];
|
$result = [];
|
||||||
|
|
||||||
@ -107,9 +118,15 @@ class TimingsHandler{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ?TimingsRecord $record = null;
|
private ?TimingsRecord $rootRecord = null;
|
||||||
private int $timingDepth = 0;
|
private int $timingDepth = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var TimingsRecord[]
|
||||||
|
* @phpstan-var array<int, TimingsRecord>
|
||||||
|
*/
|
||||||
|
private array $recordsByParent = [];
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private string $name,
|
private string $name,
|
||||||
private ?TimingsHandler $parent = null,
|
private ?TimingsHandler $parent = null,
|
||||||
@ -128,13 +145,24 @@ class TimingsHandler{
|
|||||||
|
|
||||||
private function internalStartTiming(int $now) : void{
|
private function internalStartTiming(int $now) : void{
|
||||||
if(++$this->timingDepth === 1){
|
if(++$this->timingDepth === 1){
|
||||||
if($this->record === null){
|
|
||||||
$this->record = new TimingsRecord($this);
|
|
||||||
}
|
|
||||||
$this->record->startTiming($now);
|
|
||||||
if($this->parent !== null){
|
if($this->parent !== null){
|
||||||
$this->parent->internalStartTiming($now);
|
$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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->record !== null){
|
$record = TimingsRecord::getCurrentRecord();
|
||||||
//this might be null if a timings reset occurred while the timer was running
|
if($record !== null){
|
||||||
$this->record->stopTiming($now);
|
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){
|
if($this->parent !== null){
|
||||||
$this->parent->internalStopTiming($now);
|
$this->parent->internalStopTiming($now);
|
||||||
@ -184,6 +215,7 @@ class TimingsHandler{
|
|||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
public function destroyCycles() : void{
|
public function destroyCycles() : void{
|
||||||
$this->record = null;
|
$this->rootRecord = null;
|
||||||
|
$this->recordsByParent = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,8 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\timings;
|
namespace pocketmine\timings;
|
||||||
|
|
||||||
use pocketmine\Server;
|
use pocketmine\Server;
|
||||||
use function round;
|
use pocketmine\utils\AssumptionFailedError;
|
||||||
|
use function floor;
|
||||||
use function spl_object_id;
|
use function spl_object_id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,11 +40,14 @@ final class TimingsRecord{
|
|||||||
*/
|
*/
|
||||||
private static array $records = [];
|
private static array $records = [];
|
||||||
|
|
||||||
|
private static ?self $currentRecord = null;
|
||||||
|
|
||||||
public static function clearRecords() : void{
|
public static function clearRecords() : void{
|
||||||
foreach(self::$records as $record){
|
foreach(self::$records as $record){
|
||||||
$record->handler->destroyCycles();
|
$record->handler->destroyCycles();
|
||||||
}
|
}
|
||||||
self::$records = [];
|
self::$records = [];
|
||||||
|
self::$currentRecord = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,7 +60,7 @@ final class TimingsRecord{
|
|||||||
if($measure){
|
if($measure){
|
||||||
foreach(self::$records as $record){
|
foreach(self::$records as $record){
|
||||||
if($record->curTickTotal > Server::TARGET_NANOSECONDS_PER_TICK){
|
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->curTickTotal = 0;
|
||||||
$record->curCount = 0;
|
$record->curCount = 0;
|
||||||
@ -81,11 +85,18 @@ final class TimingsRecord{
|
|||||||
|
|
||||||
public function __construct(
|
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.
|
//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;
|
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 getName() : string{ return $this->handler->getName(); }
|
||||||
|
|
||||||
public function getGroup() : string{ return $this->handler->getGroup(); }
|
public function getGroup() : string{ return $this->handler->getGroup(); }
|
||||||
@ -104,12 +115,22 @@ final class TimingsRecord{
|
|||||||
|
|
||||||
public function startTiming(int $now) : void{
|
public function startTiming(int $now) : void{
|
||||||
$this->start = $now;
|
$this->start = $now;
|
||||||
|
self::$currentRecord = $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function stopTiming(int $now) : void{
|
public function stopTiming(int $now) : void{
|
||||||
if($this->start == 0){
|
if($this->start == 0){
|
||||||
return;
|
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;
|
$diff = $now - $this->start;
|
||||||
$this->totalTime += $diff;
|
$this->totalTime += $diff;
|
||||||
$this->curTickTotal += $diff;
|
$this->curTickTotal += $diff;
|
||||||
@ -117,4 +138,8 @@ final class TimingsRecord{
|
|||||||
++$this->count;
|
++$this->count;
|
||||||
$this->start = 0;
|
$this->start = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getCurrentRecord() : ?self{
|
||||||
|
return self::$currentRecord;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user