Player Events & Interactions
Player events are the core of interactive add-ons. Listen to player actions and react accordingly.
Understanding Player Events
Everything players do in the world triggers an event. When they join, die, chat, take damage - these are all events. Your add-on can listen to these events and react instantly. This is how you build interactive features.
The key is subscriptions - you tell the server "when X happens, run this code". The server handles notifying you when the event occurs.
Player Join & Leave
These are the most common events. Join fires when a player enters the world, Leave fires when they disconnect:
import { world } from "@minecraft/server";
// When a player joins
world.afterEvents.playerJoin.subscribe((event) => {
const player = event.player;
player.sendMessage("§6Welcome to the realm!");
// Track player data
const playerId = player.nameTag;
console.log(`Player joined: ${playerId}`);
});
// When a player leaves
world.afterEvents.playerLeave.subscribe((event) => {
const player = event.player;
console.log(`Player left: ${player.nameTag}`);
});
Player Death Event
When a player dies, this event fires. You can detect the cause, give them items, teleport them, or modify the normal death behavior:
world.afterEvents.playerDie.subscribe((event) => {
const player = event.deadPlayer;
const damageSource = event.damageSource;
player.sendMessage("§cYou died!");
console.log(`${player.nameTag} died from ${damageSource.cause}`);
// Give player items back on death (instead of losing them)
const item = new ItemStack("golden_apple", 1);
player.container.addItem(item);
});
Use case: Survival servers often use this to prevent players from losing items on death, or to give them resurrection items automatically.
Chat Events
Chat events fire every time a player types. This is how custom commands work - you intercept the message before it displays to everyone:
world.beforeEvents.chatSend.subscribe((event) => {
const player = event.sender;
const message = event.message;
// Block certain words
if (message.includes("forbidden")) {
event.cancel = true; // Prevent the message from showing
player.sendMessage("§cThat word is not allowed!");
return;
}
// Custom commands
if (message.startsWith("!help")) {
event.cancel = true; // Hide from chat (only sender sees our response)
player.sendMessage("§6=== Custom Commands ===");
player.sendMessage("§e!help §r- Show this message");
player.sendMessage("§e!home §r- Teleport home");
}
});
Why event.cancel = true? It prevents the message from appearing in global chat. If you don't cancel, everyone sees the raw command. Cancel it so only you send a formatted response.
Equipment Changes
world.afterEvents.playerSpawn.subscribe((event) => {
const player = event.player;
// Detect equipment changes
let lastEquipment = {};
const checkEquipment = () => {
const head = player.getComponent("equippable").getEquipment(EquipmentSlot.Head);
const chest = player.getComponent("equippable").getEquipment(EquipmentSlot.Chest);
if (head?.typeId !== lastEquipment.head) {
player.sendMessage(`§aHead equipment changed to ${head?.typeId}`);
lastEquipment.head = head?.typeId;
}
};
});
Player Damage
world.afterEvents.entityHurt.subscribe((event) => {
const entity = event.hurtEntity;
// Only care about players
if (entity.typeId !== "minecraft:player") return;
const player = entity;
const damage = event.damage;
const source = event.damageSource.cause;
player.sendMessage(`§cYou took ${damage} damage from ${source}`);
});
Health & Hunger
world.afterEvents.entityTick.subscribe((event) => {
if (event.entity.typeId !== "minecraft:player") return;
const player = event.entity;
const health = player.getComponent("health");
// Low health warning
if (health.currentValue <= 4) {
player.sendMessage("§c⚠ Low health!");
}
});