Skip to main content
World events are fired when worlds change state or chunks are loaded/unloaded. All world events extend the WorldEvent base class.

WorldEvent Base Class

All world events inherit from this class:
getWorld()
World
Returns the world involved in the event

World Lifecycle Events

Cancellable: NoCalled when a world is initialized (first loaded).
public function onWorldInit(WorldInitEvent $event) : void {
    $world = $event->getWorld();
    
    // Set up world-specific configuration
    $world->setTime(World::TIME_DAY);
    $world->stopTime();
    
    $this->getLogger()->info("World initialized: " . $world->getDisplayName());
}
Cancellable: NoCalled when a world is loaded.
public function onWorldLoad(WorldLoadEvent $event) : void {
    $world = $event->getWorld();
    
    // Apply world settings
    $world->setDifficulty(World::DIFFICULTY_HARD);
    
    $this->getLogger()->info("World loaded: " . $world->getFolderName());
}
Cancellable: YesCalled when a world is about to be unloaded.
public function onWorldUnload(WorldUnloadEvent $event) : void {
    $world = $event->getWorld();
    
    // Prevent unloading spawn world
    if ($world->getFolderName() === "world") {
        $event->cancel();
        return;
    }
    
    // Save custom world data before unload
    $this->saveWorldData($world);
}
Cancellable: NoCalled when a world is saved to disk.
public function onWorldSave(WorldSaveEvent $event) : void {
    $world = $event->getWorld();
    
    // Perform custom save operations
    $this->saveCustomWorldData($world);
    
    $this->getLogger()->info("World saved: " . $world->getFolderName());
}

Chunk Events

Chunk events extend ChunkEvent which extends WorldEvent:
getChunkX()
int
Returns the chunk X coordinate
getChunkZ()
int
Returns the chunk Z coordinate
getChunk()
Chunk
Returns the chunk object
Cancellable: NoCalled when a chunk is loaded or newly generated.
public function onChunkLoad(ChunkLoadEvent $event) : void {
    $world = $event->getWorld();
    $chunkX = $event->getChunkX();
    $chunkZ = $event->getChunkZ();
    $chunk = $event->getChunk();
    
    if ($event->isNewChunk()) {
        // Chunk was just generated
        $this->populateCustomStructures($chunk, $world);
    } else {
        // Chunk was loaded from disk
        $this->loadChunkData($chunkX, $chunkZ);
    }
}
Methods:
  • isNewChunk() - Returns true if chunk was newly generated, false if loaded from storage
Cancellable: YesCalled when a chunk is about to be unloaded.
public function onChunkUnload(ChunkUnloadEvent $event) : void {
    $world = $event->getWorld();
    $chunkX = $event->getChunkX();
    $chunkZ = $event->getChunkZ();
    
    // Prevent spawn chunk from unloading
    if ($this->isSpawnChunk($world, $chunkX, $chunkZ)) {
        $event->cancel();
        return;
    }
    
    // Save chunk-specific data
    $this->saveChunkData($chunkX, $chunkZ);
}
Cancellable: NoCalled when a chunk is populated with decorations (trees, ores, etc.).
public function onChunkPopulate(ChunkPopulateEvent $event) : void {
    $world = $event->getWorld();
    $chunkX = $event->getChunkX();
    $chunkZ = $event->getChunkZ();
    $chunk = $event->getChunk();
    
    // Add custom structures during population
    $this->addCustomOres($chunk, $world, $chunkX, $chunkZ);
    $this->spawnCustomMobs($world, $chunkX, $chunkZ);
}

World Property Events

Cancellable: NoCalled when a world’s spawn position changes.
public function onSpawnChange(SpawnChangeEvent $event) : void {
    $world = $event->getWorld();
    $previousSpawn = $event->getPreviousSpawn();
    $newSpawn = $world->getSpawnLocation();
    
    $this->getLogger()->info(
        "Spawn changed in {$world->getFolderName()}: " .
        "({$previousSpawn->x}, {$previousSpawn->y}, {$previousSpawn->z}) -> " .
        "({$newSpawn->x}, {$newSpawn->y}, {$newSpawn->z})"
    );
}
Methods:
  • getPreviousSpawn() - Returns the previous spawn position
Cancellable: NoCalled when a world’s difficulty changes.
public function onDifficultyChange(WorldDifficultyChangeEvent $event) : void {
    $world = $event->getWorld();
    $oldDifficulty = $event->getOldDifficulty();
    $newDifficulty = $event->getNewDifficulty();
    
    $difficultyNames = [
        World::DIFFICULTY_PEACEFUL => "Peaceful",
        World::DIFFICULTY_EASY => "Easy",
        World::DIFFICULTY_NORMAL => "Normal",
        World::DIFFICULTY_HARD => "Hard"
    ];
    
    $this->getLogger()->info(
        "Difficulty changed in {$world->getFolderName()}: " .
        "{$difficultyNames[$oldDifficulty]} -> {$difficultyNames[$newDifficulty]}"
    );
}
Methods:
  • getOldDifficulty() - Returns the previous difficulty
  • getNewDifficulty() - Returns the new difficulty
Cancellable: NoCalled when a world’s display name changes.
public function onDisplayNameChange(WorldDisplayNameChangeEvent $event) : void {
    $world = $event->getWorld();
    $oldName = $event->getOldName();
    $newName = $event->getNewName();
    
    $this->getLogger()->info(
        "World display name changed: {$oldName} -> {$newName}"
    );
}
Methods:
  • getOldName() - Returns the previous display name
  • getNewName() - Returns the new display name

Audio-Visual Events

Cancellable: YesCalled when a sound is played in a world.
public function onWorldSound(WorldSoundEvent $event) : void {
    $sound = $event->getSound();
    $position = $event->getPosition();
    $recipients = $event->getRecipients();
    
    // Filter recipients
    $filteredRecipients = array_filter($recipients, function($player) {
        return $player->hasPermission("myplugin.hear_sounds");
    });
    
    $event->setRecipients($filteredRecipients);
    
    // Cancel specific sounds
    if ($sound instanceof ExplodeSoundclass) {
        $event->cancel();
    }
}
Methods:
  • getSound() - Returns the Sound object
  • getPosition() - Returns the Vector3 position where sound plays
  • getRecipients() - Returns array of Players who will hear the sound
  • setRecipients(array $recipients) - Sets who will hear the sound
Cancellable: YesCalled when particles are spawned in a world.
public function onWorldParticle(WorldParticleEvent $event) : void {
    $particle = $event->getParticle();
    $position = $event->getPosition();
    $recipients = $event->getRecipients();
    
    // Cancel particle for specific players
    $filteredRecipients = array_filter($recipients, function($player) {
        return !$player->hasTag("no_particles");
    });
    
    $event->setRecipients($filteredRecipients);
}
Methods:
  • getParticle() - Returns the Particle object
  • getPosition() - Returns the Vector3 position where particles spawn
  • getRecipients() - Returns array of Players who will see particles
  • setRecipients(array $recipients) - Sets who will see particles

Usage Examples

Keeping Spawn Chunks Loaded

use pocketmine\event\Listener;
use pocketmine\event\world\ChunkUnloadEvent;

class SpawnProtector implements Listener {
    
    public function onChunkUnload(ChunkUnloadEvent $event) : void {
        $world = $event->getWorld();
        $chunkX = $event->getChunkX();
        $chunkZ = $event->getChunkZ();
        
        // Calculate spawn chunk coordinates
        $spawn = $world->getSpawnLocation();
        $spawnChunkX = $spawn->x >> 4;
        $spawnChunkZ = $spawn->z >> 4;
        
        // Prevent unloading chunks within 2 chunks of spawn
        if (abs($chunkX - $spawnChunkX) <= 2 && abs($chunkZ - $spawnChunkZ) <= 2) {
            $event->cancel();
        }
    }
}

Custom Chunk Population

use pocketmine\event\world\ChunkPopulateEvent;
use pocketmine\block\VanillaBlocks;

public function onChunkPopulate(ChunkPopulateEvent $event) : void {
    $world = $event->getWorld();
    $chunkX = $event->getChunkX();
    $chunkZ = $event->getChunkZ();
    $chunk = $event->getChunk();
    
    // Add custom ore generation
    $random = new Random($world->getSeed() + ($chunkX * 31) + $chunkZ);
    
    // Generate 5 diamond ore veins per chunk
    for ($i = 0; $i < 5; $i++) {
        $x = $random->nextBoundedInt(16);
        $y = $random->nextBoundedInt(16) + 5; // Y 5-20
        $z = $random->nextBoundedInt(16);
        
        $world->setBlockAt(
            ($chunkX << 4) + $x,
            $y,
            ($chunkZ << 4) + $z,
            VanillaBlocks::DIAMOND_ORE()
        );
    }
}

World Time Control

use pocketmine\event\world\WorldLoadEvent;
use pocketmine\world\World;

public function onWorldLoad(WorldLoadEvent $event) : void {
    $world = $event->getWorld();
    
    // Set specific world to always be daytime
    if ($world->getFolderName() === "lobby") {
        $world->setTime(World::TIME_DAY);
        $world->stopTime();
    }
    
    // Set PvP world to always be night
    if ($world->getFolderName() === "pvp") {
        $world->setTime(World::TIME_NIGHT);
        $world->stopTime();
    }
}

Sound Filtering

use pocketmine\event\world\WorldSoundEvent;
use pocketmine\world\sound\XpCollectSound;

public function onWorldSound(WorldSoundEvent $event) : void {
    $sound = $event->getSound();
    $recipients = $event->getRecipients();
    
    // Only let nearby players hear XP sounds
    if ($sound instanceof XpCollectSound) {
        $position = $event->getPosition();
        
        $nearbyRecipients = array_filter($recipients, function($player) use ($position) {
            return $player->getPosition()->distance($position) <= 10;
        });
        
        $event->setRecipients($nearbyRecipients);
    }
}

Complete World Event List

All world-related events:
  • ChunkEvent - Base class for chunk events
  • ChunkLoadEvent - Chunk is loaded or generated
  • ChunkPopulateEvent - Chunk is populated with decorations
  • ChunkUnloadEvent - Chunk is being unloaded
  • SpawnChangeEvent - World spawn position changes
  • WorldDifficultyChangeEvent - World difficulty changes
  • WorldDisplayNameChangeEvent - World display name changes
  • WorldEvent - Base class for world events
  • WorldInitEvent - World is initialized
  • WorldLoadEvent - World is loaded
  • WorldParticleEvent - Particles are spawned
  • WorldSaveEvent - World is saved
  • WorldSoundEvent - Sound is played
  • WorldUnloadEvent - World is being unloaded

Build docs developers (and LLMs) love