Skip to content

Event System

Hytale has two separate event systems for different purposes:

SystemUse CaseRegistration
EventBusServer-wide events (player connect, chat, world events)getEventRegistry().register()
ECS EventsEntity-specific events (damage, block break, death)getEntityStoreRegistry().registerSystem()

EventBus (Server Events)

The EventBus handles global server events using simple lambda registration. This is the simpler approach for most common events.

Basic Registration

java
@Override
protected void setup() {
    // Register for player chat events
    getEventRegistry().register(PlayerChatEvent.class, event -> {
        PlayerRef sender = event.getSender();
        String message = event.getContent();
        System.out.println(sender.getUsername() + " said: " + message);
    });

    // Register for player connections
    getEventRegistry().register(PlayerConnectEvent.class, event -> {
        PlayerRef player = event.getPlayerRef();
        System.out.println(player.getUsername() + " connected!");
    });
}

Global vs Key-Based Registration

java
// Global - receives ALL events of this type
getEventRegistry().registerGlobal(PlayerChatEvent.class, event -> {
    // Handle all chat messages
});

// Key-based - receives events for a specific key
getEventRegistry().register(SomeKeyedEvent.class, myKey, event -> {
    // Handle events only for this key
});

// Unhandled - receives events that no key-based handler processed
getEventRegistry().registerUnhandled(SomeKeyedEvent.class, event -> {
    // Fallback handler
});

Event Priority

Control handler execution order with priorities:

java
import com.hypixel.hytale.event.EventPriority;

// Run before other handlers
getEventRegistry().register(EventPriority.EARLY, PlayerChatEvent.class, event -> {
    // Runs first - can modify event before others see it
});

// Run after other handlers
getEventRegistry().register(EventPriority.LATE, PlayerChatEvent.class, event -> {
    // Runs last - sees final state
});

Cancelling EventBus Events

Events implementing ICancellable can be cancelled:

java
getEventRegistry().register(EventPriority.EARLY, PlayerChatEvent.class, event -> {
    if (event.getContent().contains("spam")) {
        event.setCancelled(true);  // Message won't be sent
    }
});

Common EventBus Events

EventDescription
PlayerConnectEventPlayer connecting to server
PlayerDisconnectEventPlayer disconnecting
PlayerChatEventPlayer sends chat message (cancellable)
AddPlayerToWorldEventPlayer being added to a world
StartWorldEventWorld has started
AddWorldEventWorld being added to universe
RemoveWorldEventWorld being removed

Async Events

Some events are asynchronous and return CompletableFuture:

java
getEventRegistry().registerAsync(SomeAsyncEvent.class, event -> {
    return CompletableFuture.supplyAsync(() -> {
        // Do async work
        return null;
    });
});

ECS Events (Entity Events)

ECS events are for entity-specific interactions processed through the ECS architecture. They require extending system classes.

ECS Event Handlers

Extend EntityEventSystem for event-based handlers:

java
public class MyDamageHandler extends EntityEventSystem<Damage> {
    @Nonnull
    @Override
    public Query getQuery() {
        return Player.getComponentType();  // Only for players
    }

    @Nonnull
    @Override
    public Class<Damage> getEventType() {
        return Damage.class;
    }

    @Override
    public void handle(@Nonnull Ref<EntityStore> ref, @Nonnull Damage event,
                       @Nonnull Store store, @Nonnull CommandBuffer commandBuffer) {
        // Handle damage to the entity
        if (event.getAmount() > 50) {
            event.setCancelled(true);  // Block massive damage
        }
    }
}

Register in setup():

java
getEntityStoreRegistry().registerSystem(new MyDamageHandler());

Component Change Events

React to component additions/removals with RefChangeSystem:

java
public class MyDeathHandler extends DeathSystems.OnDeathSystem {
    @Override
    public void onComponentAdded(Ref ref, DeathComponent component,
                                  Store store, CommandBuffer buffer) {
        // Entity just died (DeathComponent was added)
    }

    @Override
    public void onComponentRemoved(Ref ref, DeathComponent component,
                                    Store store, CommandBuffer buffer) {
        // Entity respawned (DeathComponent was removed)
    }
}

Entity Lifecycle Events

React to entities being added/removed with RefSystem:

java
public class EntitySpawnListener extends RefSystem {
    @Override
    public void onEntityAdded(Ref ref, AddReason reason, Store store, CommandBuffer buffer) {
        if (reason == AddReason.SPAWN) {
            // New entity spawned
        }
    }

    @Override
    public void onEntityRemove(Ref ref, RemoveReason reason, Store store, CommandBuffer buffer) {
        // Entity being removed
    }
}

System Groups

ECS events run in defined system groups that control when your handler executes relative to others:

java
@Nonnull
@Override
public SystemGroup getGroup() {
    return DamageModule.get().getFilterDamageGroup();  // Run in filter phase
}

WARNING

Only cancel ECS events in the filter group. Cancelling in the inspect group has no effect since the action already happened.

When to Use Which System

ScenarioSystemExample
Player connects/disconnectsEventBusPlayerConnectEvent
Player chat messagesEventBusPlayerChatEvent
World lifecycleEventBusStartWorldEvent
Damage to entitiesECSDamage event
Block break/placeECSBreakBlockEvent
Entity spawn/despawnECSRefSystem
Death/respawnECSDeathComponent changes

See Also

Unofficial documentation · Any questions? Found a mistake? Have something you want documented? Join the Discord server at the top and let us know in #hytale!