Entity: Fire EntitySpawnEvent/ItemSpawnEvent on the first entity tick, instead of in the constructor (#5314)

This allows plugins to modify the entity via setters in EntitySpawnEvent without their changes getting overwritten by setter calls directly after the 'new YourEntity' statement.

As well as benefiting plugins, this also clears a path for a BC-breaking change in PM5 (to have the programmer use addEntity() to spawn entities, instead of the constructor doing it, which will improve on a number of data handling aspects).

fixes #4973

This targets next-minor because it has some side effects on plugins that depended on the old behaviour, such as VanillaHopper, so it's not suitable for a patch release.
This commit is contained in:
Dylan T 2022-09-29 22:30:12 +01:00 committed by GitHub
parent 0c7f8470b9
commit 41970feb57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 3 deletions

View File

@ -249,10 +249,8 @@ abstract class Entity{
$this->getWorld()->addEntity($this);
$this->lastUpdate = $this->server->getTick();
(new EntitySpawnEvent($this))->call();
$this->scheduleUpdate();
}
abstract protected function getInitialSizeInfo() : EntitySizeInfo;
@ -937,6 +935,14 @@ abstract class Entity{
return (new Vector2(-cos(deg2rad($this->location->yaw) - M_PI_2), -sin(deg2rad($this->location->yaw) - M_PI_2)))->normalize();
}
/**
* Called from onUpdate() on the first tick of a new entity. This is called before any movement processing or
* main ticking logic. Use this to fire any events related to spawning the entity.
*/
protected function onFirstUpdate(int $currentTick) : void{
(new EntitySpawnEvent($this))->call();
}
public function onUpdate(int $currentTick) : bool{
if($this->closed){
return false;
@ -953,6 +959,10 @@ abstract class Entity{
$this->lastUpdate = $currentTick;
if($this->justCreated){
$this->onFirstUpdate($currentTick);
}
if(!$this->isAlive()){
if($this->onDeathUpdate($tickDiff)){
$this->flagForDespawn();

View File

@ -92,8 +92,11 @@ class ItemEntity extends Entity{
$this->pickupDelay = $nbt->getShort("PickupDelay", $this->pickupDelay);
$this->owner = $nbt->getString("Owner", $this->owner);
$this->thrower = $nbt->getString("Thrower", $this->thrower);
}
(new ItemSpawnEvent($this))->call();
protected function onFirstUpdate(int $currentTick) : void{
(new ItemSpawnEvent($this))->call(); //this must be called before EntitySpawnEvent, to maintain backwards compatibility
parent::onFirstUpdate($currentTick);
}
protected function entityBaseTick(int $tickDiff = 1) : bool{

View File

@ -1343,6 +1343,10 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$this->lastUpdate = $currentTick;
if($this->justCreated){
$this->onFirstUpdate($currentTick);
}
if(!$this->isAlive() && $this->spawned){
$this->onDeathUpdate($tickDiff);
return true;