Skip to main content
Events are a core communication mechanism in Hytale server plugins. HRTK lets you capture events fired during a test and assert on their occurrence, count, and contents using EventAssert and EventCapture.

Capturing Events

Use TestContext.captureEvent() to start recording events of a specific type. The returned EventCapture<E> accumulates all matching events until you call close() or the test ends.
import com.frotty27.hrtk.api.context.TestContext;
import com.frotty27.hrtk.api.mock.EventCapture;

@HytaleTest
void testEventCapture(TestContext ctx) {
    EventCapture<PlayerJoinEvent> capture = ctx.captureEvent(PlayerJoinEvent.class);

    // ... trigger the event somehow ...

    EventAssert.assertEventFired(capture);
    capture.close();
}

EventCapture Interface

MethodDescription
getEvents()Get all captured events in order
getCount()Number of captured events
wasFired()True if at least one event was captured
anyMatch(predicate)True if any event matches the predicate
getFirst()First captured event (or null)
getLast()Last captured event (or null)
clear()Clear all captured events
close()Stop capturing and unregister the listener

EventAssert Methods

MethodDescription
assertEventFired(capture)Assert at least one event was captured
assertEventFired(capture, count)Assert exactly N events were captured
assertEventNotFired(capture)Assert no events were captured
assertEventFiredWith(capture, predicate)Assert at least one event matches

Examples

@HytaleTest
void noEventOnIdleServer(TestContext ctx) {
    EventCapture<CustomEvent> capture = ctx.captureEvent(CustomEvent.class);

    // Don't trigger anything

    EventAssert.assertEventNotFired(capture);
    HytaleAssert.assertEquals(0, capture.getCount());
    capture.close();
}
@HytaleTest
void eventContainsCorrectData(TestContext ctx) {
    EventCapture<DamageEvent> capture = ctx.captureEvent(DamageEvent.class);

    // ... apply damage to an entity ...

    EventAssert.assertEventFiredWith(capture, event ->
        event.getDamage() > 0 && event.getSource() != null
    );
    capture.close();
}
@HytaleTest
void exactlyTwoEventsOnDoubleHit(TestContext ctx) {
    EventCapture<HitEvent> capture = ctx.captureEvent(HitEvent.class);

    // ... trigger two hits ...

    EventAssert.assertEventFired(capture, 2);
    capture.close();
}
@HytaleTest
void inspectCapturedEvents(TestContext ctx) {
    EventCapture<ChatEvent> capture = ctx.captureEvent(ChatEvent.class);

    // ... trigger multiple chat messages ...

    HytaleAssert.assertNotNull(capture.getFirst());
    HytaleAssert.assertNotNull(capture.getLast());

    ChatEvent first = capture.getFirst();
    HytaleAssert.assertContainsString("hello", first.getMessage());
    capture.close();
}

Event Priority and Cancellation

HRTK’s event capture system registers listeners at the server level. This means:
  • Captured events include both cancelled and non-cancelled events (depending on listener priority)
  • Your test can observe events that other plugins may cancel
  • The capture does not interfere with normal event processing
Always call capture.close() when you are done to unregister the listener. If you forget, HRTK will close all open captures automatically when the suite finishes, but it is best practice to close them explicitly.

Practical Pattern: Event-Driven Verification

Instead of checking state directly, you can verify behavior through events:
@HytaleTest
void craftingFiresCompletionEvent(TestContext ctx) {
    EventCapture<CraftCompleteEvent> capture = ctx.captureEvent(CraftCompleteEvent.class);

    // Trigger crafting
    executeCraftingRecipe("wooden_planks");

    EventAssert.assertEventFiredWith(capture, event ->
        "wooden_planks".equals(event.getRecipeId()) && event.getQuantity() == 4
    );
    capture.close();
}

Next Steps