En esta guía aprenderás cómo mostrar UI personalizada a los jugadores en Hytale.
Información Importante
- Todos los
.uifiles deben estar en tu carpeta de recursos del plugin:resources/Common/UI/Custom - Asegúrate de que tu
manifest.jsoncontenga"IncludesAssetPack": true - Hytale Client tiene un Diagnostic Mode bajo General, que muestra errores más detallados.
Recursos Útiles
Video Tutorials:
Ejemplos de GitHub:
.ui Files
Hytale actualmente usa .ui files para renderizar UI.
⚠️ Están deprecated, se planea mover a NoesisGUI, pero aún son el método vigente.
Elementos UI
La UI se define usando una estructura tipo árbol, similar a HTML y CSS.
Group {
TextField #MyInput {
Style: $Common.@DefaultInputFieldStyle;
Background: $Common.@InputBoxBackground;
Anchor: (Top: 10, Width: 200, Height: 50);
}
}
TextField: campo de texto editable por el jugador.Group: contenedor de elementos, similar a un<div>.#MyInput: ID obligatorio para acceder al elemento desde Java.
Variables
@MyTex = PatchStyle(TexturePath: "MyBackground.png");
Texturas
PatchStyle(TexturePath: "MyBackground.png");
- Path relativo al
.uifile. - Las texturas se ajustan automáticamente al tamaño del elemento.
Incluir otros .ui files
$Common = "Common.ui";
Style: $Common.@DefaultInputFieldStyle;
HUDs
Un HUD permanece en pantalla siempre, como barra de vida o hotbar.
No permite interacción con el juego.
CustomUIHud
Crea una clase que extienda CustomUIHud y sobrescribe build:
uiCommandBuilder.append("MyUI.ui");
// El archivo debe estar en resources/Common/UI/Custom/MyUI.ui
Mostrar y ocultar HUD:
player.getHudManager().setCustomHud(hud); // Mostrar
player.getHudManager().hideHudComponent(hud); // Ocultar
UI Pages
Las UI Pages bloquean la interacción con el juego y permiten usar el cursor del mouse.
Ejemplos: Crafting, pausa.
CustomUIPage
Extiende esta clase si no necesitas recibir input de usuario. Similar a CustomUIHud.
InteractiveCustomUIPage
Usa esta clase si necesitas recibir eventos e input del jugador.
$Common = "Common.ui";
@MyTex = PatchStyle(TexturePath: "MyBackground.png");
Group {
LayoutMode: Center;
Group #MyPanel {
Background: @MyTex;
Anchor: (Width: 800, Height: 1000);
LayoutMode: Top;
Label #MyLabel {
Style: (FontSize: 32, Alignment: Center);
Anchor: (Top: 50);
Text: "MyText";
Padding: (Full: 10);
}
TextField #MyInput {
Style: $Common.@DefaultInputFieldStyle;
Background: $Common.@InputBoxBackground;
Anchor: (Top: 10, Width: 200, Height: 50);
Padding: (Full: 10);
}
}
}
InteractiveCustomUIPage – Clase de Datos
public static class Data {
public static final BuilderCodec<Data> CODEC = BuilderCodec.builder(Data.class, Data::new)
.append(new KeyedCodec<>("@MyInput", Codec.STRING), (data, value) -> data.value = value, data -> data.value)
.add()
.build();
private String value; // Valor del TextField
}
PlayerRef: jugador que verá la UICustomPageLifetime: controla si puede cerrar la UIBuilderCodec<Data>: serializa/deserializa datos del cliente al servidor
Construyendo la UI
@Override
public void build(@Nonnull Ref<EntityStore> ref, @Nonnull UICommandBuilder uiCommandBuilder,
@Nonnull UIEventBuilder uiEventBuilder, @Nonnull Store<EntityStore> store) {
uiCommandBuilder.append("MyUI.ui");
uiEventBuilder.addEventBinding(
CustomUIEventBindingType.ValueChanged,
"#MyInput",
EventData.of("@MyInput", "#MyInput.Value"),
false
);
}
- Escucha cambios en el valor de
#MyInputy lo mapea a@MyInput.
Manejar Eventos de Datos
@Override
public void handleDataEvent(@Nonnull Ref<EntityStore> ref, @Nonnull Store<EntityStore> store, Data data) {
super.handleDataEvent(ref, store, data);
System.out.println("EVENT: " + data.value);
sendUpdate(); // Actualiza la UI para el cliente
}
⚠️ Siempre llamar
sendUpdate()después de un cambio, de lo contrario la UI se queda cargando.
Abrir UI Pages
player.getPageManager().openCustomPage(ref, store, new MyUI(playerRef));
Actualizar UI Dinámicamente
Ejemplo: cambiar el texto de un Label en tiempo real:
public void updateText(String newText) {
UICommandBuilder uiCommandBuilder = new UICommandBuilder();
uiCommandBuilder.set("#MyLabel.TextSpans", Message.raw(newText));
update(false, uiCommandBuilder); // false = mantener UI existente
}
Problemas Comunes
Failed to apply custom ui hud commands
→ Tu.uifile tiene errores de sintaxis o path incorrecto.Could not find document XXXXX for Custom UI Append command
→ La ruta del.uifile no coincide con la especificada en tu código.
