askill
hytale-events

hytale-eventsSafety --Repository

Documents Hytale's event system for handling game events in plugins. Covers IEvent (global events), IAsyncEvent (async events), and EcsEvent (ECS entity/block events). Use when listening to player join/disconnect, chat, crafting, damage, block break/place, entity death, or any server event. Triggers - event, IEvent, IAsyncEvent, EcsEvent, CancellableEcsEvent, EntityEventSystem, EventRegistry, registerGlobal, registerAsync, PlayerReadyEvent, PlayerDisconnectEvent, PlayerChatEvent, BreakBlockEvent, PlaceBlockEvent, Damage, CraftRecipeEvent, DropItemEvent, DeathSystems, OnDeathSystem, event handler, event listener.

8 stars
1.2k downloads
Updated 3/8/2026

Package Files

Loading files...
SKILL.md

Hytale Events Skill

Use this skill when working with events in Hytale plugins. This covers the three event categories: IEvent (global synchronous events), IAsyncEvent (asynchronous events), and EcsEvent (ECS-based entity/block events).

Related skills: For chat-specific event handling, see hytale-chat-formatting. For ECS system fundamentals, see hytale-ecs. For entity effects triggered by events, see hytale-entity-effects.


Quick Reference

TaskApproach
Listen to player joinregisterGlobal(PlayerReadyEvent.class, handler) in setup()
Listen to player disconnectregisterGlobal(PlayerDisconnectEvent.class, handler) in setup()
Listen to chat messagesregisterAsync(PlayerChatEvent.class, handler) in setup()
Cancel block breakExtend EntityEventSystem<EntityStore, BreakBlockEvent>, call setCancelled(true)
Cancel craftingExtend EntityEventSystem<EntityStore, CraftRecipeEvent.Pre>
Handle entity damageExtend EntityEventSystem<EntityStore, Damage>
Handle player deathExtend DeathSystems.OnDeathSystem
Handle block placementExtend EntityEventSystem<EntityStore, PlaceBlockEvent>
Register global eventthis.getEventRegistry().registerGlobal(EventClass.class, Handler::method)
Register async eventthis.getEventRegistry().registerAsync(EventClass.class, Handler::method)
Register ECS event systemthis.getEntityStoreRegistry().registerSystem(new MyEventSystem()) in start()

Event Categories

Hytale has three distinct event types, each with different registration patterns:

CategoryInterfaceRegistrationCancellableUse Case
IEventIEventregisterGlobal()NoPlayer join, disconnect, world events, plugin lifecycle
IAsyncEventIAsyncEventregisterAsync()Yes (some)Chat messages, asset loading
EcsEventEcsEvent / CancellableEcsEventregisterSystem()Yes (Cancellable)Block break/place, damage, crafting, item drops

IEvent — Global Events

Global events are fired for server-wide occurrences. Register them in your plugin's setup() method.

Registration Pattern

@Override
protected void setup() {
    this.getEventRegistry().registerGlobal(PlayerReadyEvent.class, MyEventHandler::onPlayerReady);
    this.getEventRegistry().registerGlobal(PlayerDisconnectEvent.class, MyEventHandler::onPlayerDisconnect);
    this.getEventRegistry().registerGlobal(ShutdownEvent.class, MyEventHandler::onShutdown);
}

Handler Class

public class MyEventHandler {
    public static void onPlayerReady(PlayerReadyEvent event) {
        Player player = event.getPlayer();
        player.sendMessage(Message.raw("Welcome " + player.getDisplayName()));
    }

    public static void onPlayerDisconnect(PlayerDisconnectEvent event) {
        // event.getRef() returns a Ref<EntityStore> for the disconnecting player
    }

    public static void onShutdown(ShutdownEvent event) {
        // Clean up resources on server shutdown
    }
}

Required Imports (IEvent)

import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.event.player.PlayerReadyEvent;
import com.hypixel.hytale.server.event.player.PlayerDisconnectEvent;
import com.hypixel.hytale.server.event.ShutdownEvent;

Available IEvent Types

Player Events

EventDescriptionKey Methods
PlayerReadyEventPlayer finished joining (fully loaded)getPlayer()
PlayerDisconnectEventPlayer disconnectinggetRef()Ref<EntityStore>
PlayerConnectEventPlayer beginning connection-
PlayerSetupConnectEventPlayer setup phase start-
PlayerSetupDisconnectEventPlayer setup phase disconnect-
PlayerMouseButtonEventPlayer mouse button input-
PlayerMouseMotionEventPlayer mouse motion-

World Events

EventDescription
AddWorldEventA world is being added
RemoveWorldEventA world is being removed
StartWorldEventA world is starting
AddPlayerToWorldEventPlayer added to a world
DrainPlayerFromWorldEventPlayer removed from a world
AllWorldsLoadedEventAll worlds finished loading

Lifecycle Events

EventDescription
BootEventServer boot
ShutdownEventServer shutting down
PluginSetupEventPlugin setup phase
AllNPCsLoadedEventAll NPCs finished loading
LoadedNPCEventIndividual NPC loaded

Asset Events

EventDescription
AssetPackRegisterEventAsset pack registered
AssetPackUnregisterEventAsset pack unregistered
RegisterAssetStoreEventAsset store registered
RemoveAssetStoreEventAsset store removed
GenerateAssetsEventAssets being generated
LoadedAssetsEventAssets finished loading
RemovedAssetsEventAssets removed
LoadAssetEventIndividual asset loading

Other Events

EventDescription
EntityRemoveEventEntity removed from world
LivingEntityInventoryChangeEventEntity inventory changed
ItemContainerChangeEventItem container changed
GenerateDefaultLanguageEventDefault language generation
GenerateSchemaEventSchema generation
GenerateServerStateEventServer state generation
ChunkPreLoadProcessEventChunk pre-load processing
TreasureChestOpeningEventTreasure chest opened
WindowCloseEventWindow closed
WorldPathChangedEventWorld path changed
MessagesUpdatedMessages updated

IAsyncEvent — Asynchronous Events

Async events run off the main tick thread. Register in setup() using registerAsync().

Registration Pattern

@Override
protected void setup() {
    this.getEventRegistry().registerAsync(PlayerChatEvent.class, MyEventHandler::onPlayerChat);
}

Handler Example

public static void onPlayerChat(PlayerChatEvent event) {
    PlayerRef sender = event.getSender();
    String content = event.getContent();

    // Cancel the message
    if (content.contains("badword")) {
        event.setCancelled(true);
        sender.sendMessage(Message.raw("That word is not allowed!"));
        return;
    }

    // Modify content
    event.setContent(content.toUpperCase());

    // Set custom formatter
    event.setFormatter((playerRef, message) ->
        Message.join(
            Message.raw("[Server] ").color(Color.GOLD),
            Message.raw(sender.getUsername()).color(Color.WHITE),
            Message.raw(": " + message).color(Color.GRAY)
        ));
}

Available IAsyncEvent Types

EventDescriptionCancellable
PlayerChatEventPlayer sends a chat messageYes
SendCommonAssetsEventCommon assets being sentNo
AssetEditorFetchAutoCompleteDataEventEditor autocomplete dataNo
AssetEditorRequestDataSetEventEditor data set requestNo

EcsEvent — ECS Entity/Block Events

ECS events are fired within the ECS tick loop and operate on entities matching a query. They use EntityEventSystem and are registered as systems.

Key Difference from IEvent

  • IEvent: Simple handler function, registered in setup()
  • EcsEvent: Full ECS system class extending EntityEventSystem, registered in start() via registerSystem()
  • EcsEvent receives Store, CommandBuffer, and ArchetypeChunk — giving full ECS access

EntityEventSystem Pattern

import com.hypixel.hytale.component.ArchetypeChunk;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.query.Archetype;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.ecs.system.EntityEventSystem;
import javax.annotation.Nonnull;

class MyCraftHandler extends EntityEventSystem<EntityStore, CraftRecipeEvent.Pre> {

    public MyCraftHandler() {
        super(CraftRecipeEvent.Pre.class);
    }

    @Override
    public void handle(int index,
                       @Nonnull ArchetypeChunk<EntityStore> archetypeChunk,
                       @Nonnull Store<EntityStore> store,
                       @Nonnull CommandBuffer<EntityStore> commandBuffer,
                       @Nonnull CraftRecipeEvent.Pre event) {
        // Access entity ref
        var ref = archetypeChunk.getReferenceTo(index);

        // Access event data
        CraftingRecipe recipe = event.getCraftedRecipe();

        // Cancel if needed (CancellableEcsEvent only)
        event.setCancelled(true);
    }

    @Override
    public Query<EntityStore> getQuery() {
        // Return which entities this system processes
        // Archetype.empty() = all entities that receive this event
        return Archetype.empty();
    }
}

Registration

@Override
protected void start() {
    this.getEntityStoreRegistry().registerSystem(new MyCraftHandler());
}

Required Imports (EcsEvent)

import com.hypixel.hytale.component.ArchetypeChunk;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.query.Archetype;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.ecs.system.EntityEventSystem;
import javax.annotation.Nonnull;

CancellableEcsEvent Types

These events extend CancellableEcsEvent and support setCancelled(true):

EventSub-EventsDescription
BreakBlockEventPlayer breaking a block
PlaceBlockEventPlayer placing a block
ChangeGameModeEventGame mode change
ChunkSaveEventChunk saving
ChunkUnloadEventChunk unloading
CraftRecipeEvent.Pre, .PostRecipe crafted (Pre = before, Post = after)
DamageEntity taking damage
DamageBlockEventBlock being damaged
DropItemEvent.Drop, .PlayerRequestItem dropped
InteractivelyPickupItemEventPlayer picking up an item
PrefabPasteEventPrefab being pasted
SwitchActiveSlotEventActive hotbar slot switch

Non-Cancellable EcsEvent Types

EventSub-EventsDescription
DiscoverInstanceEvent.DisplayInstance discovered
DiscoverZoneEvent.DisplayZone discovered
MoonPhaseChangeEventMoon phase changed
UseBlockEvent.Pre, .PostBlock used (Pre = before, Post = after)

Special Pattern: Death Events

Player/entity death uses a specialized system extending DeathSystems.OnDeathSystem (a RefChangeSystem under the hood).

Death System Example

import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.modules.entity.damage.Damage;
import com.hypixel.hytale.server.core.modules.entity.damage.DeathComponent;
import com.hypixel.hytale.server.core.modules.entity.damage.DeathSystems;
import com.hypixel.hytale.server.core.universe.Universe;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import javax.annotation.Nonnull;

public class PlayerDeathHandler extends DeathSystems.OnDeathSystem {

    @Nonnull
    @Override
    public Query<EntityStore> getQuery() {
        // Only process player deaths
        return Query.and(Player.getComponentType());
    }

    @Override
    public void onComponentAdded(
            @Nonnull Ref ref,
            @Nonnull DeathComponent component,
            @Nonnull Store store,
            @Nonnull CommandBuffer commandBuffer) {

        Player playerComponent = (Player) store.getComponent(ref, Player.getComponentType());
        assert playerComponent != null;

        Universe.get().sendMessage(
            Message.raw("Player died: " + playerComponent.getDisplayName()));

        // Access death damage info
        Damage deathInfo = component.getDeathInfo();
        if (deathInfo != null) {
            Universe.get().sendMessage(
                Message.raw("Damage amount: " + deathInfo.getAmount()));
        }
    }
}

Death System Registration

@Override
protected void start() {
    this.getEntityStoreRegistry().registerSystem(new PlayerDeathHandler());
}

Complete Plugin Example

A full plugin demonstrating all three event categories:

import com.hypixel.hytale.server.plugin.JavaPlugin;
import com.hypixel.hytale.server.plugin.JavaPluginInit;
import com.hypixel.hytale.server.event.player.PlayerReadyEvent;
import com.hypixel.hytale.server.event.player.PlayerDisconnectEvent;
import com.hypixel.hytale.server.event.PlayerChatEvent;
import javax.annotation.Nonnull;

public class MyPlugin extends JavaPlugin {

    public MyPlugin(@Nonnull JavaPluginInit init) {
        super(init);
    }

    @Override
    protected void setup() {
        // IEvent — global events
        this.getEventRegistry().registerGlobal(PlayerReadyEvent.class,
            EventHandlers::onPlayerReady);
        this.getEventRegistry().registerGlobal(PlayerDisconnectEvent.class,
            EventHandlers::onPlayerDisconnect);

        // IAsyncEvent — async events
        this.getEventRegistry().registerAsync(PlayerChatEvent.class,
            EventHandlers::onPlayerChat);
    }

    @Override
    protected void start() {
        // EcsEvent — ECS event systems
        this.getEntityStoreRegistry().registerSystem(new CraftBlocker());
        this.getEntityStoreRegistry().registerSystem(new PlayerDeathHandler());
    }
}

Common Patterns

Cancel an Event Conditionally

// CancellableEcsEvent pattern
@Override
public void handle(int index,
                   @Nonnull ArchetypeChunk<EntityStore> archetypeChunk,
                   @Nonnull Store<EntityStore> store,
                   @Nonnull CommandBuffer<EntityStore> commandBuffer,
                   @Nonnull BreakBlockEvent event) {
    // Check condition, then cancel
    if (shouldPreventBreak(event)) {
        event.setCancelled(true);
    }
}

Block Crafting by Ingredient

class BlockFibreCrafting extends EntityEventSystem<EntityStore, CraftRecipeEvent.Pre> {

    public BlockFibreCrafting() {
        super(CraftRecipeEvent.Pre.class);
    }

    @Override
    public void handle(int index,
                       @Nonnull ArchetypeChunk<EntityStore> archetypeChunk,
                       @Nonnull Store<EntityStore> store,
                       @Nonnull CommandBuffer<EntityStore> commandBuffer,
                       @Nonnull CraftRecipeEvent.Pre event) {
        CraftingRecipe recipe = event.getCraftedRecipe();
        if (recipe.getInput() != null) {
            for (MaterialQuantity mq : recipe.getInput()) {
                if (Objects.equals(mq.getItemId(), "Ingredient_Fibre")) {
                    event.setCancelled(true);
                    break;
                }
            }
        }
    }

    @Override
    public Query<EntityStore> getQuery() {
        return Archetype.empty();
    }
}

Filter Events by Entity Type

@Override
public Query<EntityStore> getQuery() {
    // Only process for entities with the Player component
    return Query.and(Player.getComponentType());
}

Access Entity Ref from EcsEvent

@Override
public void handle(int index,
                   @Nonnull ArchetypeChunk<EntityStore> archetypeChunk,
                   @Nonnull Store<EntityStore> store,
                   @Nonnull CommandBuffer<EntityStore> commandBuffer,
                   @Nonnull Damage damageEvent) {
    Ref<EntityStore> ref = archetypeChunk.getReferenceTo(index);
    // Use ref with store to access components
    Player player = (Player) store.getComponent(ref, Player.getComponentType());
}

Choosing the Right Event Type

NeedEvent CategoryRegistration
Player joins / leavesIEventregisterGlobal() in setup()
Chat messagesIAsyncEventregisterAsync() in setup()
Block break / placeEcsEventregisterSystem() in start()
Damage / combatEcsEventregisterSystem() in start()
CraftingEcsEventregisterSystem() in start()
Item drops / pickupsEcsEventregisterSystem() in start()
Entity deathSpecial (DeathSystems)registerSystem() in start()
Server shutdownIEventregisterGlobal() in setup()
World lifecycleIEventregisterGlobal() in setup()

Best Practices

  1. Register IEvent/IAsyncEvent in setup() and EcsEvent systems in start()
  2. Use method references for cleaner registration: EventHandler::onPlayerReady
  3. Keep event handler classes separate from the main plugin class for organization
  4. Use Archetype.empty() for the query when you want to process all entities receiving the event
  5. Use Query.and() to filter which entities your EcsEvent system processes
  6. Check setCancelled() only on CancellableEcsEvent subclasses — non-cancellable events will not have this method
  7. Use Pre/Post sub-events when available (e.g., CraftRecipeEvent.Pre vs .Post) to choose timing
  8. Access entity data via Store and Ref in EcsEvent handlers — never cache entity references
  9. Use CommandBuffer for mutations inside EcsEvent handlers (add/remove components)
  10. Death handling uses DeathSystems.OnDeathSystem (a RefChangeSystem), not EntityEventSystem

Resources

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

AI review pending.

Metadata

Licenseunknown
Version-
Updated3/8/2026
PublisherJBurlison

Tags

linting