Class UISurface

java.lang.Object
com.hypixel.hytale.server.core.modules.ui.UISurface
Direct Known Subclasses:
UIHudWidget, UIPage

public abstract class UISurface extends Object
Shared base for UIPage and UIHudWidget. Manages command registration and the emitter callback injected by the owning manager.

Lifecycle: the owning manager calls bind(PlayerRef, Consumer) when the surface goes live and unbind() on teardown. A surface can be re-bound to a different player by calling bind(PlayerRef, Consumer) again; unbind() must always be called before the surface is discarded.

Threading. A surface and its owning manager are confined to the world thread that owns the player, the same thread that runs the ECS and dispatches client commands. Emitting commands, opening batches, and toggling visibility must all happen on that thread, so the surface needs no internal locking. To touch a surface from another thread (a timer, an async result) wrap the work in execute(Runnable), which hops onto the world thread.

  • Method Details

    • getId

      @Nonnull public String getId()
    • getXaml

      @Nonnull public String getXaml()
    • executeCommand

      public void executeCommand(@Nonnull String commandId, @Nullable Object parameter, @Nonnull Ref<EntityStore> ref, @Nonnull Store<EntityStore> store)
      Dispatches an incoming command from the client. Called by the owning manager.
    • createDataContext

      @Nullable public UIObjectDataValue createDataContext(@Nonnull Ref<EntityStore> ref, @Nonnull Store<EntityStore> store)
      Returns the initial data context for this surface, or null if this surface has no server-driven view model (e.g. a HUD widget that binds only client-side state).
    • beginBatch

      @Nonnull public UISurface.Batch beginBatch()
      Opens a batch on this surface. Commands emitted while the batch is open are collected and sent as one packet when the batch is closed, so use it with try-with-resources. Callers may UISurface.Batch.add(ServersideUICommand) their own protocol commands before or after running surface callbacks to control ordering within the packet.

      Batches nest: an inner batch merges its commands into the enclosing batch on close, so the whole nested sequence ships as one packet when the outermost batch closes. Use UISurface.Batch.flush() to force a packet boundary before then.

      A batch larger than the per-packet command cap is sent as several packets, in order.

    • onShow

      public void onShow(@Nonnull Ref<EntityStore> ref, @Nonnull Store<EntityStore> store)
      Called when this surface becomes active. Commands emitted here are batched with the init packet by the owning manager.
    • onHide

      public void onHide(@Nonnull Ref<EntityStore> ref, @Nonnull Store<EntityStore> store)
      Called when this surface is closed or removed. The emitter is still live when this is called; override to clean up timers or subscriptions.
    • getPlayerRef

      @Nullable public PlayerRef getPlayerRef()
    • bind

      public void bind(@Nonnull PlayerRef playerRef, @Nonnull Consumer<ServersideUICommand[]> commandEmitter)
      Attaches this surface to a player. Called by the owning manager when the surface goes live. Calling bind while already bound replaces both fields atomically; the caller is responsible for running any teardown on the previous owner before rebinding.
      Parameters:
      playerRef - the player this surface belongs to
      commandEmitter - receives non-empty command arrays to deliver to the client as one packet
    • unbind

      public void unbind()
      Detaches this surface from its player. Called by the owning manager on teardown. After this call emitCommand(ServersideUICommand) is a no-op and getPlayerRef() returns null.