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!