This commit is contained in:
2026-01-20 20:33:59 +01:00
commit b16a40e431
583 changed files with 87339 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
---
title: UI Systems
type: docs
weight: 5
---
The UI Systems section covers user interface, permissions, and custom pages.
## Overview
{{< cards cols="2" >}}
{{< card link="hud-manager" title="HUD Manager" subtitle="Control visibility of HUD components" icon="eye" >}}
{{< card link="custom-pages" title="Custom Pages" subtitle="Create custom UI overlays" icon="document-text" >}}
{{< card link="windows" title="Windows" subtitle="Inventory and crafting windows" icon="collection" >}}
{{< card link="ui-files" title="UI Files" subtitle="The .ui markup language" icon="code" >}}
{{< card link="ui-syntax" title="UI Syntax" subtitle="Variables, imports, templates" icon="document" >}}
{{< card link="ui-widgets" title="UI Widgets" subtitle="Available widget types" icon="cube" >}}
{{< card link="ui-properties" title="UI Properties" subtitle="Anchor, layout, padding" icon="adjustments" >}}
{{< card link="ui-styles" title="UI Styles" subtitle="Styling system" icon="color-swatch" >}}
{{< card link="permissions" title="Permissions" subtitle="Player permissions and access control" icon="shield-check" >}}
{{< /cards >}}
## Key Concepts
### HUD Components
The HUD consists of built-in components that can be shown or hidden:
- **Hotbar** - Item slots at the bottom of the screen
- **Health/Mana/Stamina** - Vital stat bars
- **Chat** - Text communication
- **Compass** - Direction indicator
- **Notifications** - Alert messages
- And many more...
### Custom Pages
Custom pages allow you to create overlay UIs using the `UICommandBuilder`:
```java
public class MyPage extends CustomUIPage {
public MyPage(PlayerRef ref) {
super(ref, CustomPageLifetime.CanDismiss);
}
@Override
public void build(Ref<EntityStore> ref, UICommandBuilder builder,
UIEventBuilder events, Store<EntityStore> store) {
// Build UI using builder.set(), builder.append(), etc.
builder.append("Pages/MyTemplate.ui");
builder.set("#title", "Welcome!");
}
}
```
### Page Manager
Each player has a `PageManager` that handles custom pages:
```java
Player player = ...;
PageManager pageManager = player.getPageManager();
// Open a custom page
pageManager.openCustomPage(ref, store, new MyPage(player.getPlayerRef()));
// Close to normal view
pageManager.setPage(ref, store, Page.None);
```
## Accessing the HUD Manager
```java
Player player = ...;
HudManager hudManager = player.getHudManager();
// Hide all HUD components
hudManager.setVisibleHudComponents(player.getPlayerRef());
// Show specific components
hudManager.showHudComponents(player.getPlayerRef(),
HudComponent.Hotbar,
HudComponent.Health
);
```
## Architecture
```
Player
├── HudManager → Controls HUD visibility
├── PageManager → Manages custom pages
│ └── CustomUIPage → Your custom UI
└── WindowManager → Manages windows (inventory, crafting)
```
{{< callout type="info" >}}
UI operations are typically performed through the `PlayerRef` or `Player` component. Access these through events or the command context.
{{< /callout >}}

View File

@@ -0,0 +1,97 @@
---
title: Systèmes UI
type: docs
weight: 5
---
La section Systèmes UI couvre l'interface utilisateur, les permissions et les pages personnalisées.
## Vue d'Ensemble
{{< cards cols="2" >}}
{{< card link="hud-manager" title="Gestionnaire HUD" subtitle="Contrôler la visibilité des éléments HUD" icon="eye" >}}
{{< card link="custom-pages" title="Pages Personnalisées" subtitle="Créer des interfaces interactives" icon="document" >}}
{{< card link="windows" title="Fenêtres" subtitle="Conteneurs d'inventaire et crafting" icon="collection" >}}
{{< card link="ui-files" title="Fichiers UI" subtitle="Le langage de balisage .ui" icon="code" >}}
{{< card link="ui-syntax" title="Syntaxe UI" subtitle="Variables, imports, templates" icon="document" >}}
{{< card link="ui-widgets" title="Widgets UI" subtitle="Types de widgets disponibles" icon="cube" >}}
{{< card link="ui-properties" title="Propriétés UI" subtitle="Anchor, layout, padding" icon="adjustments" >}}
{{< card link="ui-styles" title="Styles UI" subtitle="Système de styles" icon="color-swatch" >}}
{{< card link="permissions" title="Permissions" subtitle="Permissions joueur et contrôle d'accès" icon="shield-check" >}}
{{< /cards >}}
### Architecture UI
Le système UI se compose de trois couches principales :
1. **HUD** - Éléments persistants à l'écran (barre de vie, hotbar, etc.)
2. **Pages** - Overlays plein écran (menus, interfaces personnalisées)
3. **Fenêtres** - Interfaces de conteneur (coffres, crafting)
### Accéder au Système UI
```java
Player player = ...;
// Gestionnaire HUD - contrôle la visibilité des composants HUD
HudManager hudManager = player.getHudManager();
// Gestionnaire de Pages - gère les overlays et pages personnalisées
PageManager pageManager = player.getPageManager();
// Gestionnaire de Fenêtres - gère les interfaces de conteneur
WindowManager windowManager = player.getWindowManager();
```
## Utilisation Rapide
### Afficher/Masquer les Éléments HUD
```java
// Masquer le compas et le speedomètre
hudManager.hideHudComponents(player.getPlayerRef(),
HudComponent.Compass,
HudComponent.Speedometer
);
// N'afficher que les éléments essentiels
hudManager.setVisibleHudComponents(player.getPlayerRef(),
HudComponent.Hotbar,
HudComponent.Health,
HudComponent.Reticle
);
```
### Ouvrir une Page Personnalisée
```java
// Créer et ouvrir une page personnalisée
MyCustomPage page = new MyCustomPage(player.getPlayerRef());
pageManager.openCustomPage(
player.getReference(),
player.getReference().getStore(),
page
);
```
### Ouvrir une Fenêtre de Conteneur
```java
// Ouvrir un conteneur de coffre
ContainerWindow window = new ContainerWindow(
1, // ID de fenêtre
WindowType.Container,
chestContainer
);
pageManager.setPageWithWindows(ref, store, Page.None, true, window);
```
## Bonnes Pratiques
{{< callout type="info" >}}
**Directives UI :**
- Utilisez toujours `PlayerRef` lors de l'appel des méthodes HUD
- Nettoyez les pages et fenêtres lors de la déconnexion du joueur
- Utilisez `sendUpdate()` pour les petits changements, `rebuild()` pour les changements majeurs
- Testez les interactions UI dans différents modes de jeu
{{< /callout >}}

View File

@@ -0,0 +1,341 @@
---
title: Custom Pages
type: docs
weight: 2
---
Custom pages allow plugins to create interactive UI overlays that can receive user input and display dynamic content.
**Package:** `com.hypixel.hytale.server.core.entity.entities.player.pages`
## Page Lifetimes
Control how pages can be closed:
| Lifetime | Description |
|----------|-------------|
| `CustomPageLifetime.CantClose` | Page cannot be dismissed by the player |
| `CustomPageLifetime.CanDismiss` | Player can close with Escape key |
| `CustomPageLifetime.CanDismissOrCloseThroughInteraction` | Can close via Escape or interaction |
## Creating a Custom Page
Extend `CustomUIPage`:
```java
public class WelcomePage extends CustomUIPage {
public WelcomePage(PlayerRef playerRef) {
super(playerRef, CustomPageLifetime.CanDismiss);
}
@Override
public void build(Ref<EntityStore> ref, UICommandBuilder builder,
UIEventBuilder events, Store<EntityStore> store) {
// Load a UI template from assets (extension .ui is REQUIRED)
builder.append("Pages/WelcomeScreen.ui");
// Set dynamic values
builder.set("#player_name", playerRef.getUsername());
builder.set("#server_name", "My Server");
}
}
```
## UICommandBuilder
Build UI content dynamically:
### Append Content
```java
// Append a UI template (extension .ui is REQUIRED)
builder.append("Pages/TemplatePath.ui");
// Append to a specific selector
builder.append("#container", "Pages/ChildTemplate.ui");
// Append inline YAML/JSON
builder.appendInline("#list", "{ type: text, content: 'Hello' }");
```
### Set Values
```java
// Set text
builder.set("#title", "Welcome!");
builder.set("#description", Message.translation("my.key"));
// Set numbers
builder.set("#score", 1500);
builder.set("#progress", 0.75f);
// Set boolean
builder.set("#visible", true);
// Set to null
builder.setNull("#optional_field");
```
### Set Objects
```java
// Set ItemStack
ItemStack item = ...;
builder.setObject("#item_display", item);
// Set UI Area
Area area = new Area(0, 0, 100, 50);
builder.setObject("#bounds", area);
// Set arrays/lists
builder.set("#items", itemStackArray);
builder.set("#options", stringList);
```
### Remove Content
```java
// Clear children of an element
builder.clear("#container");
// Remove an element entirely
builder.remove("#element_id");
// Insert before an element
builder.insertBefore("#existing", "Pages/NewElement.ui");
```
## UIEventBuilder
Bind events to UI elements using `addEventBinding`:
```java
import com.hypixel.hytale.protocol.packets.interface_.CustomUIEventBindingType;
import com.hypixel.hytale.server.core.ui.builder.EventData;
@Override
public void build(Ref<EntityStore> ref, UICommandBuilder builder,
UIEventBuilder events, Store<EntityStore> store) {
builder.append("Pages/Menu.ui");
// Bind click events using addEventBinding
events.addEventBinding(CustomUIEventBindingType.Activating, "#button_start",
EventData.of("Action", "start_game"));
events.addEventBinding(CustomUIEventBindingType.Activating, "#button_settings",
EventData.of("Action", "open_settings"));
}
```
### Event Binding Types
| Type | Description |
|------|-------------|
| `Activating` | Button click/activation |
| `RightClicking` | Right-click action |
| `DoubleClicking` | Double-click action |
| `MouseEntered` | Mouse hover enter |
| `MouseExited` | Mouse hover exit |
| `ValueChanged` | Input value changed |
| `FocusGained` | Element focused |
| `FocusLost` | Element lost focus |
## Handling Events
Override `handleDataEvent` to process user interactions. The `rawData` parameter contains JSON with the event data:
```java
public class MenuPage extends CustomUIPage {
public MenuPage(PlayerRef ref) {
super(ref, CustomPageLifetime.CanDismiss);
}
@Override
public void build(Ref<EntityStore> ref, UICommandBuilder builder,
UIEventBuilder events, Store<EntityStore> store) {
builder.append("Pages/MainMenu.ui");
events.addEventBinding(CustomUIEventBindingType.Activating, "#play_button",
EventData.of("Action", "play"));
events.addEventBinding(CustomUIEventBindingType.Activating, "#quit_button",
EventData.of("Action", "quit"));
}
@Override
public void handleDataEvent(Ref<EntityStore> ref, Store<EntityStore> store, String rawData) {
// rawData contains JSON like: {"Action":"play"}
if (rawData.contains("\"Action\":\"play\"")) {
startGame();
} else if (rawData.contains("\"Action\":\"quit\"")) {
close();
}
}
private void startGame() {
// Game logic...
close(); // Close the page
}
}
```
{{< callout type="info" >}}
**Tip:** For more complex event handling, consider using a JSON parser library or extending `InteractiveCustomUIPage<T>` with a typed data class.
{{< /callout >}}
## Opening Pages
Use `PageManager` to open pages:
```java
Player player = ...;
PageManager pageManager = player.getPageManager();
// Open custom page
pageManager.openCustomPage(
player.getReference(),
player.getReference().getStore(),
new MenuPage(player.getPlayerRef())
);
```
## Closing Pages
```java
// From within the page
protected void close() {
// Inherited method - closes this page
}
// From outside
pageManager.setPage(ref, store, Page.None);
```
## Updating Pages
Update content without rebuilding:
```java
// Send update with new commands
UICommandBuilder update = new UICommandBuilder();
update.set("#score", newScore);
sendUpdate(update);
// Full rebuild
rebuild();
// Clear and update
sendUpdate(update, true); // clear=true
```
## Page with Windows
Open pages alongside inventory windows:
```java
// Open page with windows
pageManager.openCustomPageWithWindows(
ref, store,
new CraftingPage(playerRef),
craftingWindow,
playerInventoryWindow
);
```
## Interactive Page Example
```java
public class ShopPage extends CustomUIPage {
private int selectedItem = -1;
private final List<ShopItem> items;
public ShopPage(PlayerRef ref, List<ShopItem> items) {
super(ref, CustomPageLifetime.CanDismiss);
this.items = items;
}
@Override
public void build(Ref<EntityStore> ref, UICommandBuilder builder,
UIEventBuilder events, Store<EntityStore> store) {
builder.append("Pages/Shop.ui");
// Populate items
for (int i = 0; i < items.size(); i++) {
ShopItem item = items.get(i);
builder.set("#item_" + i + "_name", item.getName());
builder.set("#item_" + i + "_price", item.getPrice());
events.addEventBinding(CustomUIEventBindingType.Activating, "#item_" + i,
EventData.of("Action", "select").append("Index", String.valueOf(i)));
}
events.addEventBinding(CustomUIEventBindingType.Activating, "#buy_button",
EventData.of("Action", "buy"));
events.addEventBinding(CustomUIEventBindingType.Activating, "#close_button",
EventData.of("Action", "close"));
}
@Override
public void handleDataEvent(Ref<EntityStore> ref, Store<EntityStore> store, String rawData) {
// Parse JSON event data
if (rawData.contains("\"Action\":\"select\"")) {
// Extract index from JSON
int indexStart = rawData.indexOf("\"Index\":\"") + 9;
int indexEnd = rawData.indexOf("\"", indexStart);
selectedItem = Integer.parseInt(rawData.substring(indexStart, indexEnd));
updateSelection();
} else if (rawData.contains("\"Action\":\"buy\"") && selectedItem >= 0) {
purchaseItem(selectedItem);
} else if (rawData.contains("\"Action\":\"close\"")) {
close();
}
}
private void updateSelection() {
UICommandBuilder update = new UICommandBuilder();
update.set("#selected_index", selectedItem);
update.set("#selected_name", items.get(selectedItem).getName());
sendUpdate(update);
}
private void purchaseItem(int index) {
// Purchase logic...
rebuild(); // Refresh UI
}
}
```
## Built-in Pages
Available page types:
| Page | Description |
|------|-------------|
| `Page.None` | No page open (close current page) |
| `Page.Bench` | Crafting/workbench interface |
| `Page.Inventory` | Player inventory |
| `Page.ToolsSettings` | Tools settings |
| `Page.Map` | World map |
| `Page.MachinimaEditor` | Machinima editor |
| `Page.ContentCreation` | Content creation tools |
| `Page.Custom` | Custom UI page |
```java
// Open built-in page
pageManager.setPage(ref, store, Page.Inventory);
```
## Best Practices
{{< callout type="info" >}}
**Custom Page Guidelines:**
- Use `CanDismiss` unless the page must be modal
- Handle the `onDismiss` callback for cleanup
- Use `sendUpdate()` for small changes, `rebuild()` for major changes
- Store page state in instance fields
- Close pages properly using `close()` or `setPage(Page.None)`
{{< /callout >}}
{{< callout type="warning" >}}
**Important:** Always check if `playerRef.getReference()` is null before accessing the store, as the player may have disconnected.
{{< /callout >}}

View File

@@ -0,0 +1,341 @@
---
title: Pages Personnalisées
type: docs
weight: 2
---
Les pages personnalisées permettent aux plugins de créer des overlays UI interactifs qui peuvent recevoir des entrées utilisateur et afficher du contenu dynamique.
**Package:** `com.hypixel.hytale.server.core.entity.entities.player.pages`
## Durées de Vie des Pages
Contrôle comment les pages peuvent être fermées :
| Durée de Vie | Description |
|--------------|-------------|
| `CustomPageLifetime.CantClose` | La page ne peut pas être fermée par le joueur |
| `CustomPageLifetime.CanDismiss` | Le joueur peut fermer avec Échap |
| `CustomPageLifetime.CanDismissOrCloseThroughInteraction` | Peut fermer via Échap ou interaction |
## Créer une Page Personnalisée
Étendez `CustomUIPage` :
```java
public class WelcomePage extends CustomUIPage {
public WelcomePage(PlayerRef playerRef) {
super(playerRef, CustomPageLifetime.CanDismiss);
}
@Override
public void build(Ref<EntityStore> ref, UICommandBuilder builder,
UIEventBuilder events, Store<EntityStore> store) {
// Charger un template UI depuis les assets (extension .ui OBLIGATOIRE)
builder.append("Pages/WelcomeScreen.ui");
// Définir des valeurs dynamiques
builder.set("#player_name", playerRef.getUsername());
builder.set("#server_name", "Mon Serveur");
}
}
```
## UICommandBuilder
Construire du contenu UI dynamiquement :
### Ajouter du Contenu
```java
// Ajouter un template UI (extension .ui OBLIGATOIRE)
builder.append("Pages/TemplatePath.ui");
// Ajouter à un sélecteur spécifique
builder.append("#container", "Pages/ChildTemplate.ui");
// Ajouter du YAML/JSON inline
builder.appendInline("#list", "{ type: text, content: 'Bonjour' }");
```
### Définir des Valeurs
```java
// Définir du texte
builder.set("#title", "Bienvenue !");
builder.set("#description", Message.translation("my.key"));
// Définir des nombres
builder.set("#score", 1500);
builder.set("#progress", 0.75f);
// Définir un booléen
builder.set("#visible", true);
// Mettre à null
builder.setNull("#optional_field");
```
### Définir des Objets
```java
// Définir un ItemStack
ItemStack item = ...;
builder.setObject("#item_display", item);
// Définir une Zone UI
Area area = new Area(0, 0, 100, 50);
builder.setObject("#bounds", area);
// Définir des tableaux/listes
builder.set("#items", itemStackArray);
builder.set("#options", stringList);
```
### Supprimer du Contenu
```java
// Vider les enfants d'un élément
builder.clear("#container");
// Supprimer un élément entièrement
builder.remove("#element_id");
// Insérer avant un élément
builder.insertBefore("#existing", "Pages/NewElement.ui");
```
## UIEventBuilder
Lier des événements aux éléments UI avec `addEventBinding` :
```java
import com.hypixel.hytale.protocol.packets.interface_.CustomUIEventBindingType;
import com.hypixel.hytale.server.core.ui.builder.EventData;
@Override
public void build(Ref<EntityStore> ref, UICommandBuilder builder,
UIEventBuilder events, Store<EntityStore> store) {
builder.append("Pages/Menu.ui");
// Lier des événements de clic avec addEventBinding
events.addEventBinding(CustomUIEventBindingType.Activating, "#button_start",
EventData.of("Action", "start_game"));
events.addEventBinding(CustomUIEventBindingType.Activating, "#button_settings",
EventData.of("Action", "open_settings"));
}
```
### Types de Liaison d'Événements
| Type | Description |
|------|-------------|
| `Activating` | Clic/activation de bouton |
| `RightClicking` | Action clic droit |
| `DoubleClicking` | Action double-clic |
| `MouseEntered` | Entrée du survol souris |
| `MouseExited` | Sortie du survol souris |
| `ValueChanged` | Valeur d'entrée changée |
| `FocusGained` | Élément focus |
| `FocusLost` | Élément perd le focus |
## Gérer les Événements
Surchargez `handleDataEvent` pour traiter les interactions utilisateur. Le paramètre `rawData` contient du JSON avec les données de l'événement :
```java
public class MenuPage extends CustomUIPage {
public MenuPage(PlayerRef ref) {
super(ref, CustomPageLifetime.CanDismiss);
}
@Override
public void build(Ref<EntityStore> ref, UICommandBuilder builder,
UIEventBuilder events, Store<EntityStore> store) {
builder.append("Pages/MainMenu.ui");
events.addEventBinding(CustomUIEventBindingType.Activating, "#play_button",
EventData.of("Action", "play"));
events.addEventBinding(CustomUIEventBindingType.Activating, "#quit_button",
EventData.of("Action", "quit"));
}
@Override
public void handleDataEvent(Ref<EntityStore> ref, Store<EntityStore> store, String rawData) {
// rawData contient du JSON comme : {"Action":"play"}
if (rawData.contains("\"Action\":\"play\"")) {
startGame();
} else if (rawData.contains("\"Action\":\"quit\"")) {
close();
}
}
private void startGame() {
// Logique de jeu...
close(); // Fermer la page
}
}
```
{{< callout type="info" >}}
**Conseil :** Pour une gestion d'événements plus complexe, envisagez d'utiliser une bibliothèque de parsing JSON ou d'étendre `InteractiveCustomUIPage<T>` avec une classe de données typée.
{{< /callout >}}
## Ouvrir des Pages
Utilisez `PageManager` pour ouvrir des pages :
```java
Player player = ...;
PageManager pageManager = player.getPageManager();
// Ouvrir une page personnalisée
pageManager.openCustomPage(
player.getReference(),
player.getReference().getStore(),
new MenuPage(player.getPlayerRef())
);
```
## Fermer des Pages
```java
// Depuis l'intérieur de la page
protected void close() {
// Méthode héritée - ferme cette page
}
// Depuis l'extérieur
pageManager.setPage(ref, store, Page.None);
```
## Mettre à Jour des Pages
Mettre à jour le contenu sans reconstruire :
```java
// Envoyer une mise à jour avec de nouvelles commandes
UICommandBuilder update = new UICommandBuilder();
update.set("#score", newScore);
sendUpdate(update);
// Reconstruction complète
rebuild();
// Vider et mettre à jour
sendUpdate(update, true); // clear=true
```
## Page avec Fenêtres
Ouvrir des pages avec des fenêtres d'inventaire :
```java
// Ouvrir une page avec des fenêtres
pageManager.openCustomPageWithWindows(
ref, store,
new CraftingPage(playerRef),
craftingWindow,
playerInventoryWindow
);
```
## Exemple de Page Interactive
```java
public class ShopPage extends CustomUIPage {
private int selectedItem = -1;
private final List<ShopItem> items;
public ShopPage(PlayerRef ref, List<ShopItem> items) {
super(ref, CustomPageLifetime.CanDismiss);
this.items = items;
}
@Override
public void build(Ref<EntityStore> ref, UICommandBuilder builder,
UIEventBuilder events, Store<EntityStore> store) {
builder.append("Pages/Shop.ui");
// Peupler les items
for (int i = 0; i < items.size(); i++) {
ShopItem item = items.get(i);
builder.set("#item_" + i + "_name", item.getName());
builder.set("#item_" + i + "_price", item.getPrice());
events.addEventBinding(CustomUIEventBindingType.Activating, "#item_" + i,
EventData.of("Action", "select").append("Index", String.valueOf(i)));
}
events.addEventBinding(CustomUIEventBindingType.Activating, "#buy_button",
EventData.of("Action", "buy"));
events.addEventBinding(CustomUIEventBindingType.Activating, "#close_button",
EventData.of("Action", "close"));
}
@Override
public void handleDataEvent(Ref<EntityStore> ref, Store<EntityStore> store, String rawData) {
// Parser les données JSON de l'événement
if (rawData.contains("\"Action\":\"select\"")) {
// Extraire l'index du JSON
int indexStart = rawData.indexOf("\"Index\":\"") + 9;
int indexEnd = rawData.indexOf("\"", indexStart);
selectedItem = Integer.parseInt(rawData.substring(indexStart, indexEnd));
updateSelection();
} else if (rawData.contains("\"Action\":\"buy\"") && selectedItem >= 0) {
purchaseItem(selectedItem);
} else if (rawData.contains("\"Action\":\"close\"")) {
close();
}
}
private void updateSelection() {
UICommandBuilder update = new UICommandBuilder();
update.set("#selected_index", selectedItem);
update.set("#selected_name", items.get(selectedItem).getName());
sendUpdate(update);
}
private void purchaseItem(int index) {
// Logique d'achat...
rebuild(); // Rafraîchir l'UI
}
}
```
## Pages Intégrées
Types de pages disponibles :
| Page | Description |
|------|-------------|
| `Page.None` | Pas de page ouverte (fermer la page courante) |
| `Page.Bench` | Interface d'établi/crafting |
| `Page.Inventory` | Inventaire du joueur |
| `Page.ToolsSettings` | Paramètres des outils |
| `Page.Map` | Carte du monde |
| `Page.MachinimaEditor` | Éditeur de machinima |
| `Page.ContentCreation` | Outils de création de contenu |
| `Page.Custom` | Page UI personnalisée |
```java
// Ouvrir une page intégrée
pageManager.setPage(ref, store, Page.Inventory);
```
## Bonnes Pratiques
{{< callout type="info" >}}
**Directives des Pages Personnalisées :**
- Utilisez `CanDismiss` sauf si la page doit être modale
- Gérez le callback `onDismiss` pour le nettoyage
- Utilisez `sendUpdate()` pour les petits changements, `rebuild()` pour les changements majeurs
- Stockez l'état de la page dans des champs d'instance
- Fermez correctement les pages en utilisant `close()` ou `setPage(Page.None)`
{{< /callout >}}
{{< callout type="warning" >}}
**Important :** Vérifiez toujours si `playerRef.getReference()` est null avant d'accéder au store, car le joueur peut s'être déconnecté.
{{< /callout >}}

View File

@@ -0,0 +1,232 @@
---
title: HUD Manager
type: docs
weight: 1
---
The `HudManager` controls which HUD components are visible to the player.
**Package:** `com.hypixel.hytale.server.core.entity.entities.player.hud`
## HUD Components
All available HUD components:
| Component | Description |
|-----------|-------------|
| `HudComponent.Hotbar` | Player's item hotbar |
| `HudComponent.StatusIcons` | Status effect icons |
| `HudComponent.Reticle` | Crosshair/targeting reticle |
| `HudComponent.Chat` | Chat window |
| `HudComponent.Requests` | Pending requests UI |
| `HudComponent.Notifications` | Alert notifications |
| `HudComponent.KillFeed` | Kill/death messages |
| `HudComponent.InputBindings` | Control hints |
| `HudComponent.PlayerList` | Tab player list |
| `HudComponent.EventTitle` | Large event titles |
| `HudComponent.Compass` | Direction compass |
| `HudComponent.ObjectivePanel` | Quest/objective tracker |
| `HudComponent.PortalPanel` | Portal interface |
| `HudComponent.BuilderToolsLegend` | Builder tool hints |
| `HudComponent.Speedometer` | Speed indicator |
| `HudComponent.UtilitySlotSelector` | Utility slot UI |
| `HudComponent.BlockVariantSelector` | Block variant picker |
| `HudComponent.BuilderToolsMaterialSlotSelector` | Builder material slots |
| `HudComponent.Stamina` | Stamina bar |
| `HudComponent.AmmoIndicator` | Ammunition counter |
| `HudComponent.Health` | Health bar |
| `HudComponent.Mana` | Mana bar |
| `HudComponent.Oxygen` | Oxygen/breath bar |
| `HudComponent.Sleep` | Sleep indicator |
## Default Components
These components are visible by default:
```java
Set<HudComponent> DEFAULT = Set.of(
HudComponent.UtilitySlotSelector,
HudComponent.BlockVariantSelector,
HudComponent.StatusIcons,
HudComponent.Hotbar,
HudComponent.Chat,
HudComponent.Notifications,
HudComponent.KillFeed,
HudComponent.InputBindings,
HudComponent.Reticle,
HudComponent.Compass,
HudComponent.Speedometer,
HudComponent.ObjectivePanel,
HudComponent.PortalPanel,
HudComponent.EventTitle,
HudComponent.Stamina,
HudComponent.AmmoIndicator,
HudComponent.Health,
HudComponent.Mana,
HudComponent.Oxygen,
HudComponent.BuilderToolsLegend,
HudComponent.Sleep
);
```
## Accessing the HUD Manager
```java
Player player = ...;
HudManager hudManager = player.getHudManager();
```
## Showing Components
```java
// Show specific components (additive)
hudManager.showHudComponents(player.getPlayerRef(),
HudComponent.Health,
HudComponent.Stamina,
HudComponent.Hotbar
);
// Show from a Set
Set<HudComponent> components = Set.of(
HudComponent.Chat,
HudComponent.Notifications
);
hudManager.showHudComponents(player.getPlayerRef(), components);
```
## Hiding Components
```java
// Hide specific components
hudManager.hideHudComponents(player.getPlayerRef(),
HudComponent.Compass,
HudComponent.Speedometer
);
```
## Setting Components
Replace all visible components:
```java
// Set exact visible components (replaces all)
hudManager.setVisibleHudComponents(player.getPlayerRef(),
HudComponent.Hotbar,
HudComponent.Health
);
// Clear all HUD components (empty)
hudManager.setVisibleHudComponents(player.getPlayerRef());
```
## Querying Visible Components
```java
Set<HudComponent> visible = hudManager.getVisibleHudComponents();
if (visible.contains(HudComponent.Health)) {
// Health bar is visible
}
```
## Resetting the HUD
```java
// Reset to default components and clear custom HUD
hudManager.resetHud(player.getPlayerRef());
// Reset entire UI state
hudManager.resetUserInterface(player.getPlayerRef());
```
## Custom HUD Overlay
For persistent overlays:
```java
public class ScoreboardHud extends CustomUIHud {
public ScoreboardHud(PlayerRef ref) {
super(ref);
}
@Override
protected void build(UICommandBuilder builder) {
// Extension .ui is REQUIRED
builder.append("Hud/Scoreboard.ui");
builder.set("#score", 1500);
builder.set("#rank", "Gold");
}
}
// Set custom HUD
hudManager.setCustomHud(player.getPlayerRef(), new ScoreboardHud(player.getPlayerRef()));
// Remove custom HUD
hudManager.setCustomHud(player.getPlayerRef(), null);
```
## Practical Examples
### Cinematic Mode
Hide all UI for cutscenes:
```java
public void enterCinematicMode(Player player) {
HudManager hud = player.getHudManager();
// Store current state if needed for restoration
Set<HudComponent> previous = new HashSet<>(hud.getVisibleHudComponents());
// Clear all HUD
hud.setVisibleHudComponents(player.getPlayerRef());
}
public void exitCinematicMode(Player player, Set<HudComponent> restore) {
player.getHudManager().setVisibleHudComponents(player.getPlayerRef(), restore);
}
```
### Minimal HUD Mode
Show only essential components:
```java
public void setMinimalHud(Player player) {
player.getHudManager().setVisibleHudComponents(player.getPlayerRef(),
HudComponent.Hotbar,
HudComponent.Health,
HudComponent.Reticle
);
}
```
### Builder Mode HUD
Show builder-specific components:
```java
public void enableBuilderHud(Player player) {
HudManager hud = player.getHudManager();
hud.showHudComponents(player.getPlayerRef(),
HudComponent.BuilderToolsLegend,
HudComponent.BuilderToolsMaterialSlotSelector,
HudComponent.BlockVariantSelector
);
}
```
## Best Practices
{{< callout type="info" >}}
**HUD Guidelines:**
- Always use `PlayerRef` when calling HUD methods
- Store previous state before clearing if you need to restore later
- Consider game mode when deciding which components to show
- Use `resetHud()` to return to default state
{{< /callout >}}
{{< callout type="warning" >}}
**Performance Note:** Avoid rapid toggling of HUD components as each change sends packets to the client.
{{< /callout >}}

View File

@@ -0,0 +1,232 @@
---
title: Gestionnaire HUD
type: docs
weight: 1
---
Le `HudManager` contrôle quels composants HUD sont visibles pour le joueur.
**Package:** `com.hypixel.hytale.server.core.entity.entities.player.hud`
## Composants HUD
Tous les composants HUD disponibles :
| Composant | Description |
|-----------|-------------|
| `HudComponent.Hotbar` | Barre d'objets du joueur |
| `HudComponent.StatusIcons` | Icônes d'effets de statut |
| `HudComponent.Reticle` | Réticule/viseur |
| `HudComponent.Chat` | Fenêtre de chat |
| `HudComponent.Requests` | UI des demandes en attente |
| `HudComponent.Notifications` | Notifications d'alerte |
| `HudComponent.KillFeed` | Messages de kill/mort |
| `HudComponent.InputBindings` | Indications de contrôle |
| `HudComponent.PlayerList` | Liste des joueurs (Tab) |
| `HudComponent.EventTitle` | Grands titres d'événements |
| `HudComponent.Compass` | Boussole de direction |
| `HudComponent.ObjectivePanel` | Suivi de quêtes/objectifs |
| `HudComponent.PortalPanel` | Interface de portail |
| `HudComponent.BuilderToolsLegend` | Indications d'outils de construction |
| `HudComponent.Speedometer` | Indicateur de vitesse |
| `HudComponent.UtilitySlotSelector` | UI des slots d'utilitaires |
| `HudComponent.BlockVariantSelector` | Sélecteur de variantes de blocs |
| `HudComponent.BuilderToolsMaterialSlotSelector` | Slots de matériaux du builder |
| `HudComponent.Stamina` | Barre d'endurance |
| `HudComponent.AmmoIndicator` | Compteur de munitions |
| `HudComponent.Health` | Barre de vie |
| `HudComponent.Mana` | Barre de mana |
| `HudComponent.Oxygen` | Barre d'oxygène/respiration |
| `HudComponent.Sleep` | Indicateur de sommeil |
## Composants par Défaut
Ces composants sont visibles par défaut :
```java
Set<HudComponent> DEFAULT = Set.of(
HudComponent.UtilitySlotSelector,
HudComponent.BlockVariantSelector,
HudComponent.StatusIcons,
HudComponent.Hotbar,
HudComponent.Chat,
HudComponent.Notifications,
HudComponent.KillFeed,
HudComponent.InputBindings,
HudComponent.Reticle,
HudComponent.Compass,
HudComponent.Speedometer,
HudComponent.ObjectivePanel,
HudComponent.PortalPanel,
HudComponent.EventTitle,
HudComponent.Stamina,
HudComponent.AmmoIndicator,
HudComponent.Health,
HudComponent.Mana,
HudComponent.Oxygen,
HudComponent.BuilderToolsLegend,
HudComponent.Sleep
);
```
## Accéder au Gestionnaire HUD
```java
Player player = ...;
HudManager hudManager = player.getHudManager();
```
## Afficher des Composants
```java
// Afficher des composants spécifiques (additif)
hudManager.showHudComponents(player.getPlayerRef(),
HudComponent.Health,
HudComponent.Stamina,
HudComponent.Hotbar
);
// Afficher depuis un Set
Set<HudComponent> components = Set.of(
HudComponent.Chat,
HudComponent.Notifications
);
hudManager.showHudComponents(player.getPlayerRef(), components);
```
## Masquer des Composants
```java
// Masquer des composants spécifiques
hudManager.hideHudComponents(player.getPlayerRef(),
HudComponent.Compass,
HudComponent.Speedometer
);
```
## Définir les Composants
Remplacer tous les composants visibles :
```java
// Définir exactement les composants visibles (remplace tout)
hudManager.setVisibleHudComponents(player.getPlayerRef(),
HudComponent.Hotbar,
HudComponent.Health
);
// Vider tous les composants HUD
hudManager.setVisibleHudComponents(player.getPlayerRef());
```
## Requêter les Composants Visibles
```java
Set<HudComponent> visible = hudManager.getVisibleHudComponents();
if (visible.contains(HudComponent.Health)) {
// La barre de vie est visible
}
```
## Réinitialiser le HUD
```java
// Réinitialiser aux composants par défaut et vider le HUD personnalisé
hudManager.resetHud(player.getPlayerRef());
// Réinitialiser l'état UI complet
hudManager.resetUserInterface(player.getPlayerRef());
```
## HUD Personnalisé
Pour les overlays persistants :
```java
public class ScoreboardHud extends CustomUIHud {
public ScoreboardHud(PlayerRef ref) {
super(ref);
}
@Override
protected void build(UICommandBuilder builder) {
// L'extension .ui est OBLIGATOIRE
builder.append("Hud/Scoreboard.ui");
builder.set("#score", 1500);
builder.set("#rank", "Or");
}
}
// Définir le HUD personnalisé
hudManager.setCustomHud(player.getPlayerRef(), new ScoreboardHud(player.getPlayerRef()));
// Supprimer le HUD personnalisé
hudManager.setCustomHud(player.getPlayerRef(), null);
```
## Exemples Pratiques
### Mode Cinématique
Masquer toute l'UI pour les cinématiques :
```java
public void enterCinematicMode(Player player) {
HudManager hud = player.getHudManager();
// Stocker l'état actuel si nécessaire pour restauration
Set<HudComponent> previous = new HashSet<>(hud.getVisibleHudComponents());
// Vider tout le HUD
hud.setVisibleHudComponents(player.getPlayerRef());
}
public void exitCinematicMode(Player player, Set<HudComponent> restore) {
player.getHudManager().setVisibleHudComponents(player.getPlayerRef(), restore);
}
```
### Mode HUD Minimal
N'afficher que les composants essentiels :
```java
public void setMinimalHud(Player player) {
player.getHudManager().setVisibleHudComponents(player.getPlayerRef(),
HudComponent.Hotbar,
HudComponent.Health,
HudComponent.Reticle
);
}
```
### HUD Mode Construction
Afficher les composants spécifiques au builder :
```java
public void enableBuilderHud(Player player) {
HudManager hud = player.getHudManager();
hud.showHudComponents(player.getPlayerRef(),
HudComponent.BuilderToolsLegend,
HudComponent.BuilderToolsMaterialSlotSelector,
HudComponent.BlockVariantSelector
);
}
```
## Bonnes Pratiques
{{< callout type="info" >}}
**Directives HUD :**
- Utilisez toujours `PlayerRef` lors de l'appel des méthodes HUD
- Stockez l'état précédent avant de vider si vous devez restaurer plus tard
- Considérez le mode de jeu lors du choix des composants à afficher
- Utilisez `resetHud()` pour revenir à l'état par défaut
{{< /callout >}}
{{< callout type="warning" >}}
**Note de Performance :** Évitez le basculement rapide des composants HUD car chaque changement envoie des paquets au client.
{{< /callout >}}

View File

@@ -0,0 +1,349 @@
---
title: Permissions System
type: docs
weight: 12
---
The Permissions system provides fine-grained access control for commands, editor features, and custom plugin functionality.
**Package:** `com.hypixel.hytale.server.core.permissions`
## Overview
Hytale uses a permission system with:
- **User permissions** - Directly assigned to individual players
- **Group permissions** - Inherited by all members of a group
- **Permission providers** - Custom logic for dynamic permissions
## Accessing the Permissions Module
```java
import com.hypixel.hytale.server.core.permissions.PermissionsModule;
// Use static get() method - NOT HytaleServer.get().getPermissionsModule()
PermissionsModule permissions = PermissionsModule.get();
```
## Checking Permissions
```java
UUID playerUuid = player.getPlayerRef().getUuid();
// Check if player has permission
boolean canEdit = permissions.hasPermission(playerUuid, "hytale.editor.asset");
// Check in command context
if (permissions.hasPermission(ctx.sender().getUuid(), "myplugin.admin")) {
// Admin-only logic
}
```
## User Permissions
Manage permissions for individual players:
```java
UUID playerUuid = player.getPlayerRef().getUuid();
// Add permissions
permissions.addUserPermission(playerUuid, Set.of(
"myplugin.feature.create",
"myplugin.feature.delete"
));
// Remove permissions
permissions.removeUserPermission(playerUuid, Set.of(
"myplugin.feature.delete"
));
```
## Group Permissions
Groups allow shared permissions across multiple players:
### Managing Groups
```java
// Add player to a group
permissions.addUserToGroup(playerUuid, "moderators");
// Remove player from a group
permissions.removeUserFromGroup(playerUuid, "moderators");
// Get all groups for a player
Set<String> groups = permissions.getGroupsForUser(playerUuid);
```
### Group Permission Events
Listen for group changes using specific event subclasses:
```java
import com.hypixel.hytale.server.core.event.events.permissions.*;
// Player ADDED to group
getEventRegistry().register(PlayerGroupEvent.Added.class, event -> {
UUID playerUuid = event.getPlayerUuid();
String group = event.getGroupName(); // Note: getGroupName(), NOT getGroup()
log("Player joined group: " + group);
});
// Player REMOVED from group
getEventRegistry().register(PlayerGroupEvent.Removed.class, event -> {
UUID playerUuid = event.getPlayerUuid();
String group = event.getGroupName();
log("Player left group: " + group);
});
// Group permissions ADDED
getEventRegistry().register(GroupPermissionChangeEvent.Added.class, event -> {
String group = event.getGroupName();
Set<String> added = event.getAddedPermissions();
log("Group " + group + " got permissions: " + added);
});
// Group permissions REMOVED
getEventRegistry().register(GroupPermissionChangeEvent.Removed.class, event -> {
String group = event.getGroupName();
Set<String> removed = event.getRemovedPermissions();
log("Group " + group + " lost permissions: " + removed);
});
// Player permissions ADDED
getEventRegistry().register(PlayerPermissionChangeEvent.PermissionsAdded.class, event -> {
UUID playerUuid = event.getPlayerUuid();
Set<String> added = event.getAddedPermissions();
});
// Player permissions REMOVED
getEventRegistry().register(PlayerPermissionChangeEvent.PermissionsRemoved.class, event -> {
UUID playerUuid = event.getPlayerUuid();
Set<String> removed = event.getRemovedPermissions();
});
```
## Built-in Permissions
Hytale includes many built-in permissions:
### Command Permissions
| Permission | Description |
|------------|-------------|
| `hytale.command.*` | All command access |
| `hytale.command.gamemode` | Change game mode |
| `hytale.command.tp` | Teleportation |
| `hytale.command.give` | Give items |
| `hytale.command.time` | Time control |
### Editor Permissions
| Permission | Description |
|------------|-------------|
| `hytale.editor.asset` | Asset editing |
| `hytale.editor.packs.*` | Pack management |
| `hytale.editor.builderTools` | Builder tools access |
| `hytale.editor.brush.*` | Brush tools |
| `hytale.editor.prefab.*` | Prefab editing |
| `hytale.editor.selection.*` | Selection tools |
| `hytale.editor.history` | Undo/redo history |
### Camera Permissions
| Permission | Description |
|------------|-------------|
| `hytale.camera.flycam` | Free camera mode |
## Custom Permission Provider
Implement `PermissionProvider` for dynamic permission logic:
{{< callout type="info" >}}
**Note:** `PermissionProvider` is an interface that provides sets of permissions, not a simple hasPermission check. The `PermissionsModule` checks these sets.
{{< /callout >}}
```java
import com.hypixel.hytale.server.core.permissions.provider.PermissionProvider;
public class VIPPermissionProvider implements PermissionProvider {
private final Map<UUID, Set<String>> vipPermissions = new ConcurrentHashMap<>();
private final Map<UUID, Set<String>> vipGroups = new ConcurrentHashMap<>();
@Override
@Nonnull
public String getName() {
return "VIPPermissionProvider";
}
@Override
public Set<String> getUserPermissions(@Nonnull UUID uuid) {
// Return the permissions for this user
// VIP users get extra permissions automatically
if (isVIP(uuid)) {
Set<String> perms = new HashSet<>(vipPermissions.getOrDefault(uuid, Collections.emptySet()));
perms.add("vip.lounge");
perms.add("vip.cosmetics");
return perms;
}
return vipPermissions.getOrDefault(uuid, Collections.emptySet());
}
@Override
public void addUserPermissions(@Nonnull UUID uuid, @Nonnull Set<String> permissions) {
vipPermissions.computeIfAbsent(uuid, k -> new HashSet<>()).addAll(permissions);
}
@Override
public void removeUserPermissions(@Nonnull UUID uuid, @Nonnull Set<String> permissions) {
Set<String> userPerms = vipPermissions.get(uuid);
if (userPerms != null) {
userPerms.removeAll(permissions);
}
}
@Override
public Set<String> getGroupPermissions(@Nonnull String group) {
return Collections.emptySet();
}
@Override
public void addGroupPermissions(@Nonnull String group, @Nonnull Set<String> permissions) {}
@Override
public void removeGroupPermissions(@Nonnull String group, @Nonnull Set<String> permissions) {}
@Override
public Set<String> getGroupsForUser(@Nonnull UUID uuid) {
return vipGroups.getOrDefault(uuid, Collections.emptySet());
}
@Override
public void addUserToGroup(@Nonnull UUID uuid, @Nonnull String group) {
vipGroups.computeIfAbsent(uuid, k -> new HashSet<>()).add(group);
}
@Override
public void removeUserFromGroup(@Nonnull UUID uuid, @Nonnull String group) {
Set<String> groups = vipGroups.get(uuid);
if (groups != null) {
groups.remove(group);
}
}
private boolean isVIP(UUID uuid) {
// Your VIP checking logic
return vipDatabase.contains(uuid);
}
}
```
### Registering Custom Providers
```java
@Override
public void start() {
PermissionsModule permissions = PermissionsModule.get();
permissions.addProvider(new VIPPermissionProvider());
}
```
## Permission Wildcards
Permissions support wildcard matching:
```java
// Grant all permissions under a namespace
permissions.addUserPermission(playerUuid, Set.of("myplugin.*"));
// This now passes:
permissions.hasPermission(playerUuid, "myplugin.anything");
permissions.hasPermission(playerUuid, "myplugin.feature.nested");
```
## Command Permission Integration
Commands automatically check permissions based on their ID:
```java
public class AdminCommand extends AbstractCommand {
public AdminCommand() {
super("admin", "myplugin.commands.admin.description");
// Permission check is automatic based on command registration
}
@Override
protected CompletableFuture<Void> execute(CommandContext ctx) {
// Only players with appropriate permission reach here
return null;
}
}
```
## Practical Examples
### Role-Based Access
```java
public class RoleManager {
private final PermissionsModule permissions;
public RoleManager() {
this.permissions = PermissionsModule.get();
}
public void promoteToModerator(UUID playerUuid) {
permissions.addUserToGroup(playerUuid, "moderators");
permissions.addUserPermission(playerUuid, Set.of(
"server.kick",
"server.mute",
"server.warn"
));
}
public void demoteFromModerator(UUID playerUuid) {
permissions.removeUserFromGroup(playerUuid, "moderators");
permissions.removeUserPermission(playerUuid, Set.of(
"server.kick",
"server.mute",
"server.warn"
));
}
public boolean canModerate(UUID playerUuid) {
return permissions.getGroupsForUser(playerUuid).contains("moderators");
}
}
```
### Feature Gating
```java
public void useFeature(Player player, String featureName) {
UUID uuid = player.getPlayerRef().getUuid();
PermissionsModule perms = PermissionsModule.get();
String permission = "myplugin.feature." + featureName;
if (!perms.hasPermission(uuid, permission)) {
player.sendMessage(Message.translation("error.no_permission"));
return;
}
// Execute feature
executeFeature(player, featureName);
}
```
## Best Practices
{{< callout type="info" >}}
**Permission Guidelines:**
- Use namespaced permissions (e.g., `myplugin.feature.name`)
- Prefer groups for role-based access over individual permissions
- Check permissions at entry points, not deep in logic
- Use wildcards sparingly and intentionally
{{< /callout >}}
{{< callout type="warning" >}}
**Security Note:** Always validate permissions server-side. Never trust client-reported permission states.
{{< /callout >}}

View File

@@ -0,0 +1,349 @@
---
title: Système de Permissions
type: docs
weight: 12
---
Le système de Permissions fournit un contrôle d'accès granulaire pour les commandes, les fonctionnalités de l'éditeur et les fonctionnalités personnalisées des plugins.
**Package:** `com.hypixel.hytale.server.core.permissions`
## Vue d'Ensemble
Hytale utilise un système de permissions avec :
- **Permissions utilisateur** - Directement assignées aux joueurs individuels
- **Permissions de groupe** - Héritées par tous les membres d'un groupe
- **Fournisseurs de permissions** - Logique personnalisée pour les permissions dynamiques
## Accéder au Module de Permissions
```java
import com.hypixel.hytale.server.core.permissions.PermissionsModule;
// Utiliser la méthode statique get() - PAS HytaleServer.get().getPermissionsModule()
PermissionsModule permissions = PermissionsModule.get();
```
## Vérifier les Permissions
```java
UUID playerUuid = player.getPlayerRef().getUuid();
// Vérifier si le joueur a la permission
boolean canEdit = permissions.hasPermission(playerUuid, "hytale.editor.asset");
// Vérifier dans le contexte de commande
if (permissions.hasPermission(ctx.sender().getUuid(), "myplugin.admin")) {
// Logique réservée aux admins
}
```
## Permissions Utilisateur
Gérer les permissions pour les joueurs individuels :
```java
UUID playerUuid = player.getPlayerRef().getUuid();
// Ajouter des permissions
permissions.addUserPermission(playerUuid, Set.of(
"myplugin.feature.create",
"myplugin.feature.delete"
));
// Supprimer des permissions
permissions.removeUserPermission(playerUuid, Set.of(
"myplugin.feature.delete"
));
```
## Permissions de Groupe
Les groupes permettent de partager des permissions entre plusieurs joueurs :
### Gérer les Groupes
```java
// Ajouter un joueur à un groupe
permissions.addUserToGroup(playerUuid, "moderators");
// Retirer un joueur d'un groupe
permissions.removeUserFromGroup(playerUuid, "moderators");
// Obtenir tous les groupes d'un joueur
Set<String> groups = permissions.getGroupsForUser(playerUuid);
```
### Événements de Permissions de Groupe
Écouter les changements de groupes en utilisant des sous-classes spécifiques :
```java
import com.hypixel.hytale.server.core.event.events.permissions.*;
// Joueur AJOUTÉ à un groupe
getEventRegistry().register(PlayerGroupEvent.Added.class, event -> {
UUID playerUuid = event.getPlayerUuid();
String group = event.getGroupName(); // Note: getGroupName(), PAS getGroup()
log("Joueur a rejoint le groupe : " + group);
});
// Joueur RETIRÉ d'un groupe
getEventRegistry().register(PlayerGroupEvent.Removed.class, event -> {
UUID playerUuid = event.getPlayerUuid();
String group = event.getGroupName();
log("Joueur a quitté le groupe : " + group);
});
// Permissions du groupe AJOUTÉES
getEventRegistry().register(GroupPermissionChangeEvent.Added.class, event -> {
String group = event.getGroupName();
Set<String> added = event.getAddedPermissions();
log("Groupe " + group + " a reçu les permissions : " + added);
});
// Permissions du groupe RETIRÉES
getEventRegistry().register(GroupPermissionChangeEvent.Removed.class, event -> {
String group = event.getGroupName();
Set<String> removed = event.getRemovedPermissions();
log("Groupe " + group + " a perdu les permissions : " + removed);
});
// Permissions du joueur AJOUTÉES
getEventRegistry().register(PlayerPermissionChangeEvent.PermissionsAdded.class, event -> {
UUID playerUuid = event.getPlayerUuid();
Set<String> added = event.getAddedPermissions();
});
// Permissions du joueur RETIRÉES
getEventRegistry().register(PlayerPermissionChangeEvent.PermissionsRemoved.class, event -> {
UUID playerUuid = event.getPlayerUuid();
Set<String> removed = event.getRemovedPermissions();
});
```
## Permissions Intégrées
Hytale inclut de nombreuses permissions intégrées :
### Permissions de Commandes
| Permission | Description |
|------------|-------------|
| `hytale.command.*` | Accès à toutes les commandes |
| `hytale.command.gamemode` | Changer de mode de jeu |
| `hytale.command.tp` | Téléportation |
| `hytale.command.give` | Donner des objets |
| `hytale.command.time` | Contrôle du temps |
### Permissions de l'Éditeur
| Permission | Description |
|------------|-------------|
| `hytale.editor.asset` | Édition des assets |
| `hytale.editor.packs.*` | Gestion des packs |
| `hytale.editor.builderTools` | Accès aux outils de construction |
| `hytale.editor.brush.*` | Outils de pinceau |
| `hytale.editor.prefab.*` | Édition des prefabs |
| `hytale.editor.selection.*` | Outils de sélection |
| `hytale.editor.history` | Historique annuler/rétablir |
### Permissions de Caméra
| Permission | Description |
|------------|-------------|
| `hytale.camera.flycam` | Mode caméra libre |
## Fournisseur de Permission Personnalisé
Implémentez `PermissionProvider` pour une logique de permission dynamique :
{{< callout type="info" >}}
**Note :** `PermissionProvider` est une interface qui fournit des ensembles de permissions, pas une simple vérification hasPermission. Le `PermissionsModule` vérifie ces ensembles.
{{< /callout >}}
```java
import com.hypixel.hytale.server.core.permissions.provider.PermissionProvider;
public class VIPPermissionProvider implements PermissionProvider {
private final Map<UUID, Set<String>> vipPermissions = new ConcurrentHashMap<>();
private final Map<UUID, Set<String>> vipGroups = new ConcurrentHashMap<>();
@Override
@Nonnull
public String getName() {
return "VIPPermissionProvider";
}
@Override
public Set<String> getUserPermissions(@Nonnull UUID uuid) {
// Retourner les permissions pour cet utilisateur
// Les utilisateurs VIP reçoivent des permissions supplémentaires automatiquement
if (isVIP(uuid)) {
Set<String> perms = new HashSet<>(vipPermissions.getOrDefault(uuid, Collections.emptySet()));
perms.add("vip.lounge");
perms.add("vip.cosmetics");
return perms;
}
return vipPermissions.getOrDefault(uuid, Collections.emptySet());
}
@Override
public void addUserPermissions(@Nonnull UUID uuid, @Nonnull Set<String> permissions) {
vipPermissions.computeIfAbsent(uuid, k -> new HashSet<>()).addAll(permissions);
}
@Override
public void removeUserPermissions(@Nonnull UUID uuid, @Nonnull Set<String> permissions) {
Set<String> userPerms = vipPermissions.get(uuid);
if (userPerms != null) {
userPerms.removeAll(permissions);
}
}
@Override
public Set<String> getGroupPermissions(@Nonnull String group) {
return Collections.emptySet();
}
@Override
public void addGroupPermissions(@Nonnull String group, @Nonnull Set<String> permissions) {}
@Override
public void removeGroupPermissions(@Nonnull String group, @Nonnull Set<String> permissions) {}
@Override
public Set<String> getGroupsForUser(@Nonnull UUID uuid) {
return vipGroups.getOrDefault(uuid, Collections.emptySet());
}
@Override
public void addUserToGroup(@Nonnull UUID uuid, @Nonnull String group) {
vipGroups.computeIfAbsent(uuid, k -> new HashSet<>()).add(group);
}
@Override
public void removeUserFromGroup(@Nonnull UUID uuid, @Nonnull String group) {
Set<String> groups = vipGroups.get(uuid);
if (groups != null) {
groups.remove(group);
}
}
private boolean isVIP(UUID uuid) {
// Votre logique de vérification VIP
return vipDatabase.contains(uuid);
}
}
```
### Enregistrer des Fournisseurs Personnalisés
```java
@Override
public void start() {
PermissionsModule permissions = PermissionsModule.get();
permissions.addProvider(new VIPPermissionProvider());
}
```
## Wildcards de Permission
Les permissions supportent les correspondances avec wildcard :
```java
// Accorder toutes les permissions sous un namespace
permissions.addUserPermission(playerUuid, Set.of("myplugin.*"));
// Ceci passe maintenant :
permissions.hasPermission(playerUuid, "myplugin.anything");
permissions.hasPermission(playerUuid, "myplugin.feature.nested");
```
## Intégration des Permissions de Commandes
Les commandes vérifient automatiquement les permissions basées sur leur ID :
```java
public class AdminCommand extends AbstractCommand {
public AdminCommand() {
super("admin", "myplugin.commands.admin.description");
// La vérification de permission est automatique basée sur l'enregistrement de la commande
}
@Override
protected CompletableFuture<Void> execute(CommandContext ctx) {
// Seuls les joueurs avec la permission appropriée arrivent ici
return null;
}
}
```
## Exemples Pratiques
### Accès Basé sur les Rôles
```java
public class RoleManager {
private final PermissionsModule permissions;
public RoleManager() {
this.permissions = PermissionsModule.get();
}
public void promoteToModerator(UUID playerUuid) {
permissions.addUserToGroup(playerUuid, "moderators");
permissions.addUserPermission(playerUuid, Set.of(
"server.kick",
"server.mute",
"server.warn"
));
}
public void demoteFromModerator(UUID playerUuid) {
permissions.removeUserFromGroup(playerUuid, "moderators");
permissions.removeUserPermission(playerUuid, Set.of(
"server.kick",
"server.mute",
"server.warn"
));
}
public boolean canModerate(UUID playerUuid) {
return permissions.getGroupsForUser(playerUuid).contains("moderators");
}
}
```
### Verrouillage de Fonctionnalités
```java
public void useFeature(Player player, String featureName) {
UUID uuid = player.getPlayerRef().getUuid();
PermissionsModule perms = PermissionsModule.get();
String permission = "myplugin.feature." + featureName;
if (!perms.hasPermission(uuid, permission)) {
player.sendMessage(Message.translation("error.no_permission"));
return;
}
// Exécuter la fonctionnalité
executeFeature(player, featureName);
}
```
## Bonnes Pratiques
{{< callout type="info" >}}
**Directives des Permissions :**
- Utilisez des permissions avec namespace (ex: `myplugin.feature.name`)
- Préférez les groupes pour l'accès basé sur les rôles plutôt que les permissions individuelles
- Vérifiez les permissions aux points d'entrée, pas profondément dans la logique
- Utilisez les wildcards avec parcimonie et intentionnellement
{{< /callout >}}
{{< callout type="warning" >}}
**Note de Sécurité :** Validez toujours les permissions côté serveur. Ne faites jamais confiance aux états de permission rapportés par le client.
{{< /callout >}}

View File

@@ -0,0 +1,161 @@
---
title: UI Files
type: docs
weight: 10
---
UI files (`.ui`) are Hytale's declarative markup language for defining user interfaces. They describe the structure, layout, and styling of UI elements that can be loaded by plugins via `UICommandBuilder.append()`.
## File Location
UI files are typically stored in the Assets directory:
```
Assets/
Common/UI/Custom/ # Server-side custom UI
Pages/ # Custom page templates
Hud/ # Custom HUD elements
Common.ui # Shared definitions
Sounds.ui # Sound definitions
Client/Interface/ # Client-side UI
InGame/Hud/ # HUD components
Common/ # Common components
Common.ui # Client shared definitions
```
## Basic Structure
A `.ui` file consists of variable definitions and widget declarations:
```
// Import external definitions
$Common = "../Common.ui";
// Define local variables
@ButtonHeight = 44;
@TextColor = #96a9be;
// Define a widget tree
Group #Container {
Anchor: (Width: 400, Height: 300);
Background: (Color: #000000(0.8));
Label #Title {
Text: "Hello World";
Style: (FontSize: 24, TextColor: @TextColor);
}
}
```
## Loading UI Files from Plugins
Use `UICommandBuilder.append()` to load a UI file:
```java
@Override
public void build(Ref<EntityStore> ref, UICommandBuilder builder,
UIEventBuilder events, Store<EntityStore> store) {
// Load the UI template (extension .ui is REQUIRED)
builder.append("Pages/MyPage.ui");
// Append to a specific element
builder.append("#ContentList", "Pages/ListItem.ui");
// Set dynamic values using selectors
builder.set("#Title", "Welcome, " + playerRef.getUsername());
}
```
### Path Resolution
The path is relative to `Common/UI/Custom/`. The `.ui` extension is **required**.
| Path in `append()` | Resolved Location |
|-------------------|-------------------|
| `Pages/MyPage.ui` | `Common/UI/Custom/Pages/MyPage.ui` |
| `Common.ui` | `Common/UI/Custom/Common.ui` |
### For Java Plugins (Mods)
When creating a Java plugin with custom UI, place your `.ui` files in the resources folder:
```
your-plugin/
src/main/
java/ # Java source code
resources/
Common/UI/Custom/ # UI files go here
Pages/
MyPage.ui
MyButton.ui
Common.ui # Your shared definitions
plugin.json # Plugin manifest
```
Set `"IncludesAssetPack": true` in your `plugin.json` to enable asset loading:
```json
{
"Group": "MyGroup",
"Name": "MyPlugin",
"Version": "1.0.0",
"Main": "com.example.MyPlugin",
"IncludesAssetPack": true
}
```
{{< callout type="info" >}}
The server automatically looks for UI files in `Common/UI/Custom/` within your plugin's asset pack. This is why paths like `Pages/MyPage.ui` work without specifying the full path.
{{< /callout >}}
## Key Concepts
### Variables
Variables store reusable values:
```
@Height = 50; // Number
@Color = #ff5500; // Color
@Style = (FontSize: 16, RenderBold: true); // Object
```
### Imports
Import definitions from other files:
```
$Common = "Common.ui"; // Import file
$Common.@DefaultButtonStyle // Reference imported variable
```
### Widget IDs
Use `#` to assign IDs that can be targeted from Java:
```
Label #PlayerName {
Text: "Unknown";
}
```
```java
builder.set("#PlayerName", player.getUsername());
```
### Localization
Use `%` prefix for translation keys:
```
Label {
Text: %server.ui.welcome.title;
}
```
## Next Steps
- [UI Syntax](ui-syntax) - Detailed syntax reference
- [UI Widgets](ui-widgets) - Available widget types
- [UI Properties](ui-properties) - Common properties
- [UI Styles](ui-styles) - Styling system

View File

@@ -0,0 +1,161 @@
---
title: Fichiers UI
type: docs
weight: 10
---
Les fichiers UI (`.ui`) sont le langage de balisage déclaratif de Hytale pour définir les interfaces utilisateur. Ils décrivent la structure, la disposition et le style des éléments UI qui peuvent être chargés par les plugins via `UICommandBuilder.append()`.
## Emplacement des Fichiers
Les fichiers UI sont généralement stockés dans le répertoire Assets :
```
Assets/
Common/UI/Custom/ # UI personnalisée côté serveur
Pages/ # Templates de pages personnalisées
Hud/ # Éléments HUD personnalisés
Common.ui # Définitions partagées
Sounds.ui # Définitions de sons
Client/Interface/ # UI côté client
InGame/Hud/ # Composants HUD
Common/ # Composants communs
Common.ui # Définitions partagées client
```
## Structure de Base
Un fichier `.ui` se compose de définitions de variables et de déclarations de widgets :
```
// Importer des définitions externes
$Common = "../Common.ui";
// Définir des variables locales
@ButtonHeight = 44;
@TextColor = #96a9be;
// Définir un arbre de widgets
Group #Container {
Anchor: (Width: 400, Height: 300);
Background: (Color: #000000(0.8));
Label #Title {
Text: "Bonjour le monde";
Style: (FontSize: 24, TextColor: @TextColor);
}
}
```
## Charger des Fichiers UI depuis les Plugins
Utilisez `UICommandBuilder.append()` pour charger un fichier UI :
```java
@Override
public void build(Ref<EntityStore> ref, UICommandBuilder builder,
UIEventBuilder events, Store<EntityStore> store) {
// Charger le template UI (extension .ui OBLIGATOIRE)
builder.append("Pages/MyPage.ui");
// Ajouter à un élément spécifique
builder.append("#ContentList", "Pages/ListItem.ui");
// Définir des valeurs dynamiques avec des sélecteurs
builder.set("#Title", "Bienvenue, " + playerRef.getUsername());
}
```
### Résolution des Chemins
Le chemin est relatif à `Common/UI/Custom/`. L'extension `.ui` est **obligatoire**.
| Chemin dans `append()` | Emplacement Résolu |
|------------------------|-------------------|
| `Pages/MyPage.ui` | `Common/UI/Custom/Pages/MyPage.ui` |
| `Common.ui` | `Common/UI/Custom/Common.ui` |
### Pour les Plugins Java (Mods)
Lors de la création d'un plugin Java avec une UI personnalisée, placez vos fichiers `.ui` dans le dossier resources :
```
your-plugin/
src/main/
java/ # Code source Java
resources/
Common/UI/Custom/ # Les fichiers UI vont ici
Pages/
MyPage.ui
MyButton.ui
Common.ui # Vos définitions partagées
plugin.json # Manifeste du plugin
```
Définissez `"IncludesAssetPack": true` dans votre `plugin.json` pour activer le chargement des assets :
```json
{
"Group": "MyGroup",
"Name": "MyPlugin",
"Version": "1.0.0",
"Main": "com.example.MyPlugin",
"IncludesAssetPack": true
}
```
{{< callout type="info" >}}
Le serveur cherche automatiquement les fichiers UI dans `Common/UI/Custom/` au sein de l'asset pack de votre plugin. C'est pourquoi des chemins comme `Pages/MyPage.ui` fonctionnent sans spécifier le chemin complet.
{{< /callout >}}
## Concepts Clés
### Variables
Les variables stockent des valeurs réutilisables :
```
@Height = 50; // Nombre
@Color = #ff5500; // Couleur
@Style = (FontSize: 16, RenderBold: true); // Objet
```
### Imports
Importer des définitions depuis d'autres fichiers :
```
$Common = "Common.ui"; // Importer un fichier
$Common.@DefaultButtonStyle // Référencer une variable importée
```
### IDs de Widget
Utilisez `#` pour assigner des IDs ciblables depuis Java :
```
Label #PlayerName {
Text: "Inconnu";
}
```
```java
builder.set("#PlayerName", player.getUsername());
```
### Localisation
Utilisez le préfixe `%` pour les clés de traduction :
```
Label {
Text: %server.ui.welcome.title;
}
```
## Étapes Suivantes
- [Syntaxe UI](ui-syntax) - Référence de syntaxe détaillée
- [Widgets UI](ui-widgets) - Types de widgets disponibles
- [Propriétés UI](ui-properties) - Propriétés communes
- [Styles UI](ui-styles) - Système de styles

View File

@@ -0,0 +1,384 @@
---
title: UI Properties
type: docs
weight: 13
---
This page documents common properties available on UI widgets.
## Anchor (Positioning)
The `Anchor` property controls widget position and size.
### Position Properties
```
Anchor: (
Left: 10, // Distance from left edge
Right: 10, // Distance from right edge
Top: 10, // Distance from top edge
Bottom: 10 // Distance from bottom edge
);
```
### Size Properties
```
Anchor: (
Width: 200, // Fixed width
Height: 100 // Fixed height
);
```
### Shorthand Properties
```
Anchor: (Full: 10); // All sides = 10
Anchor: (Horizontal: 20); // Left and Right = 20
Anchor: (Vertical: 15); // Top and Bottom = 15
```
### Combined Example
```
// Fixed size, positioned from top-left
Anchor: (Left: 50, Top: 100, Width: 300, Height: 200);
// Fill parent with margins
Anchor: (Full: 16);
// Anchored to bottom-right corner
Anchor: (Right: 20, Bottom: 20, Width: 100, Height: 40);
// Full width, fixed height at bottom
Anchor: (Horizontal: 0, Bottom: 0, Height: 50);
```
## Background
The `Background` property sets widget background appearance.
### Solid Color
```
Background: (Color: #ff5500);
Background: (Color: #000000(0.5)); // With opacity
```
### Simple Texture
```
Background: "MyTexture.png";
Background: (TexturePath: "MyTexture.png");
```
### 9-Patch (Stretchable) Texture
```
// Uniform border
Background: (TexturePath: "Panel.png", Border: 20);
// Separate horizontal/vertical borders
Background: (
TexturePath: "Button.png",
HorizontalBorder: 80,
VerticalBorder: 12
);
```
### Using PatchStyle
```
@MyBackground = PatchStyle(
TexturePath: "Panel.png",
Border: 16
);
Group {
Background: @MyBackground;
}
```
## Padding
The `Padding` property sets inner spacing.
```
Padding: (Full: 16); // All sides
Padding: (Horizontal: 20); // Left and Right
Padding: (Vertical: 10); // Top and Bottom
Padding: (Left: 10, Right: 20); // Individual sides
Padding: (Top: 5, Bottom: 15, Horizontal: 10);
```
### Using Padding Constructor
```
@ContentPadding = Padding(Full: 16, Top: 8);
Group {
Padding: @ContentPadding;
}
```
## LayoutMode
The `LayoutMode` property controls how children are arranged.
### Stacking Modes
| Mode | Description |
|------|-------------|
| `Top` | Stack children from top to bottom |
| `Bottom` | Stack children from bottom to top |
| `Left` | Stack children from left to right |
| `Right` | Stack children from right to left |
```
Group {
LayoutMode: Top; // Vertical list, top-aligned
Label { Text: "First"; Anchor: (Height: 30); }
Label { Text: "Second"; Anchor: (Height: 30); }
Label { Text: "Third"; Anchor: (Height: 30); }
}
```
### Centering Modes
| Mode | Description |
|------|-------------|
| `Middle` | Center children vertically |
| `CenterMiddle` | Center children both horizontally and vertically |
```
Group {
LayoutMode: CenterMiddle;
Label { Text: "Centered!"; }
}
```
### Scrolling Modes
| Mode | Description |
|------|-------------|
| `TopScrolling` | Vertical scroll, content from top |
| `BottomScrolling` | Vertical scroll, content from bottom (chat-style) |
```
Group #ChatLog {
LayoutMode: BottomScrolling;
ScrollbarStyle: @DefaultScrollbarStyle;
AutoScrollDown: true;
}
```
### Wrapping Mode
| Mode | Description |
|------|-------------|
| `LeftCenterWrap` | Flow left-to-right, wrap to next row |
```
Group #ItemGrid {
LayoutMode: LeftCenterWrap;
// Items will wrap to new rows
}
```
## FlexWeight
The `FlexWeight` property controls flexible sizing in layout.
```
Group {
LayoutMode: Left;
Group {
Anchor: (Width: 100); // Fixed width
}
Group {
FlexWeight: 1; // Takes remaining space
}
Group {
FlexWeight: 2; // Takes 2x the space of FlexWeight: 1
}
}
```
## Visible
Controls widget visibility.
```
Group #Panel {
Visible: true; // or false, or @Variable
}
Button #CloseButton {
Visible: @CloseButton; // Controlled by template parameter
}
```
## Text
Sets text content for Label and TextButton widgets.
```
Label {
Text: "Static text";
}
Label {
Text: %server.ui.title; // Translation key
}
Label #DynamicText {
Text: ""; // Set from Java
}
```
## ScrollbarStyle
Configures scrollbar appearance for scrolling containers.
```
Group {
LayoutMode: TopScrolling;
ScrollbarStyle: (
Spacing: 6,
Size: 6,
Background: (TexturePath: "Scrollbar.png", Border: 3),
Handle: (TexturePath: "ScrollbarHandle.png", Border: 3),
HoveredHandle: (TexturePath: "ScrollbarHandleHovered.png", Border: 3),
DraggedHandle: (TexturePath: "ScrollbarHandleDragged.png", Border: 3)
);
}
```
### ScrollbarStyle Options
| Property | Description |
|----------|-------------|
| `Spacing` | Gap between scrollbar and content |
| `Size` | Scrollbar width/height |
| `Background` | Track background |
| `Handle` | Normal handle appearance |
| `HoveredHandle` | Handle when hovered |
| `DraggedHandle` | Handle when dragging |
| `OnlyVisibleWhenHovered` | Hide when not interacting |
## AutoScrollDown
For BottomScrolling containers, automatically scroll to new content.
```
Group #ChatLog {
LayoutMode: BottomScrolling;
AutoScrollDown: true;
}
```
## Disabled
Disables interaction with a widget.
```
Button #SubmitButton {
Disabled: false;
}
ActionButton #Binding {
Disabled: true;
}
```
## TooltipText
Displays tooltip on hover.
```
Button #InfoButton {
TooltipText: %ui.tooltip.help;
}
```
## TextTooltipStyle
Configures tooltip appearance.
```
Button {
TooltipText: "Help text";
TextTooltipStyle: (
Background: (TexturePath: "TooltipBg.png", Border: 24),
MaxWidth: 400,
LabelStyle: (Wrap: true, FontSize: 16),
Padding: 24
);
}
```
## Common Property Combinations
### Panel with Title and Content
```
Group #Panel {
Anchor: (Width: 400, Height: 300);
Background: (TexturePath: "Panel.png", Border: 20);
LayoutMode: Top;
Padding: (Full: 16);
Label #Title {
Anchor: (Height: 40);
// ...
}
Group #Content {
FlexWeight: 1;
LayoutMode: TopScrolling;
ScrollbarStyle: @DefaultScrollbarStyle;
Padding: (Top: 8);
}
}
```
### Horizontal Button Row
```
Group #ButtonRow {
Anchor: (Height: 50);
LayoutMode: Right;
Padding: (Horizontal: 10);
TextButton #Cancel {
Anchor: (Width: 100);
}
Group { Anchor: (Width: 10); } // Spacer
TextButton #Confirm {
Anchor: (Width: 100);
}
}
```
### Full-Screen Overlay
```
Group #Overlay {
Anchor: (Full: 0);
Background: (Color: #000000(0.7));
LayoutMode: CenterMiddle;
Group #Dialog {
Anchor: (Width: 500, Height: 300);
Background: (TexturePath: "Dialog.png", Border: 20);
}
}
```

View File

@@ -0,0 +1,384 @@
---
title: Propriétés UI
type: docs
weight: 13
---
Cette page documente les propriétés communes disponibles sur les widgets UI.
## Anchor (Positionnement)
La propriété `Anchor` contrôle la position et la taille du widget.
### Propriétés de Position
```
Anchor: (
Left: 10, // Distance depuis le bord gauche
Right: 10, // Distance depuis le bord droit
Top: 10, // Distance depuis le bord supérieur
Bottom: 10 // Distance depuis le bord inférieur
);
```
### Propriétés de Taille
```
Anchor: (
Width: 200, // Largeur fixe
Height: 100 // Hauteur fixe
);
```
### Propriétés Raccourcies
```
Anchor: (Full: 10); // Tous les côtés = 10
Anchor: (Horizontal: 20); // Gauche et Droite = 20
Anchor: (Vertical: 15); // Haut et Bas = 15
```
### Exemple Combiné
```
// Taille fixe, positionné depuis le coin supérieur gauche
Anchor: (Left: 50, Top: 100, Width: 300, Height: 200);
// Remplit le parent avec des marges
Anchor: (Full: 16);
// Ancré au coin inférieur droit
Anchor: (Right: 20, Bottom: 20, Width: 100, Height: 40);
// Pleine largeur, hauteur fixe en bas
Anchor: (Horizontal: 0, Bottom: 0, Height: 50);
```
## Background
La propriété `Background` définit l'apparence du fond du widget.
### Couleur Unie
```
Background: (Color: #ff5500);
Background: (Color: #000000(0.5)); // Avec opacité
```
### Texture Simple
```
Background: "MyTexture.png";
Background: (TexturePath: "MyTexture.png");
```
### Texture 9-Patch (Étirable)
```
// Bordure uniforme
Background: (TexturePath: "Panel.png", Border: 20);
// Bordures horizontales/verticales séparées
Background: (
TexturePath: "Button.png",
HorizontalBorder: 80,
VerticalBorder: 12
);
```
### Utiliser PatchStyle
```
@MyBackground = PatchStyle(
TexturePath: "Panel.png",
Border: 16
);
Group {
Background: @MyBackground;
}
```
## Padding
La propriété `Padding` définit l'espacement intérieur.
```
Padding: (Full: 16); // Tous les côtés
Padding: (Horizontal: 20); // Gauche et Droite
Padding: (Vertical: 10); // Haut et Bas
Padding: (Left: 10, Right: 20); // Côtés individuels
Padding: (Top: 5, Bottom: 15, Horizontal: 10);
```
### Utiliser le Constructeur Padding
```
@ContentPadding = Padding(Full: 16, Top: 8);
Group {
Padding: @ContentPadding;
}
```
## LayoutMode
La propriété `LayoutMode` contrôle l'arrangement des enfants.
### Modes d'Empilement
| Mode | Description |
|------|-------------|
| `Top` | Empile les enfants de haut en bas |
| `Bottom` | Empile les enfants de bas en haut |
| `Left` | Empile les enfants de gauche à droite |
| `Right` | Empile les enfants de droite à gauche |
```
Group {
LayoutMode: Top; // Liste verticale, alignée en haut
Label { Text: "Premier"; Anchor: (Height: 30); }
Label { Text: "Deuxième"; Anchor: (Height: 30); }
Label { Text: "Troisième"; Anchor: (Height: 30); }
}
```
### Modes de Centrage
| Mode | Description |
|------|-------------|
| `Middle` | Centre les enfants verticalement |
| `CenterMiddle` | Centre les enfants horizontalement et verticalement |
```
Group {
LayoutMode: CenterMiddle;
Label { Text: "Centré !"; }
}
```
### Modes avec Défilement
| Mode | Description |
|------|-------------|
| `TopScrolling` | Défilement vertical, contenu depuis le haut |
| `BottomScrolling` | Défilement vertical, contenu depuis le bas (style chat) |
```
Group #ChatLog {
LayoutMode: BottomScrolling;
ScrollbarStyle: @DefaultScrollbarStyle;
AutoScrollDown: true;
}
```
### Mode Retour à la Ligne
| Mode | Description |
|------|-------------|
| `LeftCenterWrap` | Flux gauche-droite, retour à la ligne suivante |
```
Group #ItemGrid {
LayoutMode: LeftCenterWrap;
// Les items passeront à la ligne suivante
}
```
## FlexWeight
La propriété `FlexWeight` contrôle le dimensionnement flexible dans la mise en page.
```
Group {
LayoutMode: Left;
Group {
Anchor: (Width: 100); // Largeur fixe
}
Group {
FlexWeight: 1; // Prend l'espace restant
}
Group {
FlexWeight: 2; // Prend 2x l'espace de FlexWeight: 1
}
}
```
## Visible
Contrôle la visibilité du widget.
```
Group #Panel {
Visible: true; // ou false, ou @Variable
}
Button #CloseButton {
Visible: @CloseButton; // Contrôlé par paramètre de template
}
```
## Text
Définit le contenu texte pour les widgets Label et TextButton.
```
Label {
Text: "Texte statique";
}
Label {
Text: %server.ui.title; // Clé de traduction
}
Label #DynamicText {
Text: ""; // Défini depuis Java
}
```
## ScrollbarStyle
Configure l'apparence de la scrollbar pour les conteneurs défilants.
```
Group {
LayoutMode: TopScrolling;
ScrollbarStyle: (
Spacing: 6,
Size: 6,
Background: (TexturePath: "Scrollbar.png", Border: 3),
Handle: (TexturePath: "ScrollbarHandle.png", Border: 3),
HoveredHandle: (TexturePath: "ScrollbarHandleHovered.png", Border: 3),
DraggedHandle: (TexturePath: "ScrollbarHandleDragged.png", Border: 3)
);
}
```
### Options ScrollbarStyle
| Propriété | Description |
|-----------|-------------|
| `Spacing` | Écart entre la scrollbar et le contenu |
| `Size` | Largeur/hauteur de la scrollbar |
| `Background` | Fond de la piste |
| `Handle` | Apparence normale de la poignée |
| `HoveredHandle` | Poignée au survol |
| `DraggedHandle` | Poignée pendant le glissement |
| `OnlyVisibleWhenHovered` | Masquer quand pas d'interaction |
## AutoScrollDown
Pour les conteneurs BottomScrolling, défile automatiquement vers le nouveau contenu.
```
Group #ChatLog {
LayoutMode: BottomScrolling;
AutoScrollDown: true;
}
```
## Disabled
Désactive l'interaction avec un widget.
```
Button #SubmitButton {
Disabled: false;
}
ActionButton #Binding {
Disabled: true;
}
```
## TooltipText
Affiche une infobulle au survol.
```
Button #InfoButton {
TooltipText: %ui.tooltip.help;
}
```
## TextTooltipStyle
Configure l'apparence de l'infobulle.
```
Button {
TooltipText: "Texte d'aide";
TextTooltipStyle: (
Background: (TexturePath: "TooltipBg.png", Border: 24),
MaxWidth: 400,
LabelStyle: (Wrap: true, FontSize: 16),
Padding: 24
);
}
```
## Combinaisons de Propriétés Courantes
### Panneau avec Titre et Contenu
```
Group #Panel {
Anchor: (Width: 400, Height: 300);
Background: (TexturePath: "Panel.png", Border: 20);
LayoutMode: Top;
Padding: (Full: 16);
Label #Title {
Anchor: (Height: 40);
// ...
}
Group #Content {
FlexWeight: 1;
LayoutMode: TopScrolling;
ScrollbarStyle: @DefaultScrollbarStyle;
Padding: (Top: 8);
}
}
```
### Rangée de Boutons Horizontale
```
Group #ButtonRow {
Anchor: (Height: 50);
LayoutMode: Right;
Padding: (Horizontal: 10);
TextButton #Cancel {
Anchor: (Width: 100);
}
Group { Anchor: (Width: 10); } // Espaceur
TextButton #Confirm {
Anchor: (Width: 100);
}
}
```
### Overlay Plein Écran
```
Group #Overlay {
Anchor: (Full: 0);
Background: (Color: #000000(0.7));
LayoutMode: CenterMiddle;
Group #Dialog {
Anchor: (Width: 500, Height: 300);
Background: (TexturePath: "Dialog.png", Border: 20);
}
}
```

View File

@@ -0,0 +1,367 @@
---
title: UI Styles
type: docs
weight: 14
---
This page documents the styling system for Hytale UI widgets.
## Style States
Interactive widgets support multiple states:
| State | When Applied |
|-------|--------------|
| `Default` | Normal state |
| `Hovered` | Mouse over widget |
| `Pressed` | Mouse button held |
| `Disabled` | Widget is disabled |
```
Style: (
Default: (Background: "Button.png"),
Hovered: (Background: "ButtonHovered.png"),
Pressed: (Background: "ButtonPressed.png"),
Disabled: (Background: "ButtonDisabled.png")
);
```
## LabelStyle
Text styling for Label widgets.
```
@MyLabelStyle = LabelStyle(
FontSize: 16,
FontName: "Default", // or "Secondary"
TextColor: #ffffff,
RenderBold: true,
RenderUppercase: false,
LetterSpacing: 0,
Wrap: false,
HorizontalAlignment: Center, // Start, Center, End
VerticalAlignment: Center, // Top, Center, Bottom
OutlineColor: #000000(0.5)
);
Label {
Style: @MyLabelStyle;
}
```
### LabelStyle Properties
| Property | Type | Description |
|----------|------|-------------|
| `FontSize` | number | Text size |
| `FontName` | string | Font family ("Default", "Secondary") |
| `TextColor` | color | Text color |
| `RenderBold` | bool | Bold text |
| `RenderUppercase` | bool | Force uppercase |
| `LetterSpacing` | number | Space between characters |
| `Wrap` | bool | Enable text wrapping |
| `HorizontalAlignment` | enum | Start, Center, End |
| `VerticalAlignment` | enum | Top, Center, Bottom |
| `OutlineColor` | color | Text outline color |
| `Alignment` | enum | Shorthand for both alignments (Center) |
## ButtonStyle
Styling for Button widgets (without text).
```
@MyButtonStyle = ButtonStyle(
Default: (Background: (TexturePath: "Button.png", Border: 12)),
Hovered: (Background: (TexturePath: "ButtonHovered.png", Border: 12)),
Pressed: (Background: (TexturePath: "ButtonPressed.png", Border: 12)),
Disabled: (Background: (TexturePath: "ButtonDisabled.png", Border: 12)),
Sounds: @ButtonSounds
);
Button {
Style: @MyButtonStyle;
}
```
### Button State Properties
| Property | Type | Description |
|----------|------|-------------|
| `Background` | PatchStyle | Background appearance |
## TextButtonStyle
Styling for TextButton widgets.
```
@MyTextButtonStyle = TextButtonStyle(
Default: (
Background: (TexturePath: "Button.png", Border: 12),
LabelStyle: (FontSize: 17, TextColor: #bfcdd5, RenderBold: true)
),
Hovered: (
Background: (TexturePath: "ButtonHovered.png", Border: 12),
LabelStyle: (FontSize: 17, TextColor: #ffffff, RenderBold: true)
),
Pressed: (
Background: (TexturePath: "ButtonPressed.png", Border: 12),
LabelStyle: (FontSize: 17, TextColor: #aaaaaa, RenderBold: true)
),
Disabled: (
Background: (TexturePath: "ButtonDisabled.png", Border: 12),
LabelStyle: (FontSize: 17, TextColor: #797b7c, RenderBold: true)
),
Sounds: @ButtonSounds
);
```
### TextButton State Properties
| Property | Type | Description |
|----------|------|-------------|
| `Background` | PatchStyle | Background appearance |
| `LabelStyle` | LabelStyle | Text styling |
## PatchStyle
9-patch texture configuration for stretchable backgrounds.
```
@MyPatchStyle = PatchStyle(
TexturePath: "Panel.png",
Border: 16 // Uniform border
);
@MyPatchStyle2 = PatchStyle(
TexturePath: "Button.png",
HorizontalBorder: 80, // Left/right border
VerticalBorder: 12 // Top/bottom border
);
// With color tint
@ColoredPatch = PatchStyle(
Color: #ff0000(0.5) // Semi-transparent red
);
```
### PatchStyle Properties
| Property | Type | Description |
|----------|------|-------------|
| `TexturePath` | string | Path to texture file |
| `Border` | number | Uniform 9-patch border |
| `HorizontalBorder` | number | Left/right 9-patch border |
| `VerticalBorder` | number | Top/bottom 9-patch border |
| `Color` | color | Solid color (instead of texture) |
## InputFieldStyle
Styling for text input fields.
```
@MyInputStyle = InputFieldStyle(
TextColor: #ffffff,
FontSize: 16
);
@MyPlaceholderStyle = InputFieldStyle(
TextColor: #6e7da1
);
TextField {
Style: @MyInputStyle;
PlaceholderStyle: @MyPlaceholderStyle;
}
```
## SliderStyle
Styling for slider controls.
```
@MySliderStyle = SliderStyle(
Background: (TexturePath: "SliderBackground.png", Border: 2),
Handle: "SliderHandle.png",
HandleWidth: 16,
HandleHeight: 16,
Sounds: (
Activate: (SoundPath: "SliderTick.ogg", Volume: 10),
MouseHover: (SoundPath: "Hover.ogg", Volume: 6)
)
);
```
### SliderStyle Properties
| Property | Type | Description |
|----------|------|-------------|
| `Background` | PatchStyle | Track background |
| `Handle` | string | Handle texture path |
| `HandleWidth` | number | Handle width |
| `HandleHeight` | number | Handle height |
| `Sounds` | object | Sound effects |
## CheckBoxStyle
Styling for checkbox controls.
```
@MyCheckBoxStyle = CheckBoxStyle(
Unchecked: (
DefaultBackground: (Color: #00000000),
HoveredBackground: (Color: #ffffff20),
PressedBackground: (Color: #ffffff10),
DisabledBackground: (Color: #424242),
ChangedSound: (SoundPath: "Untick.ogg", Volume: 6)
),
Checked: (
DefaultBackground: (TexturePath: "Checkmark.png"),
HoveredBackground: (TexturePath: "Checkmark.png"),
PressedBackground: (TexturePath: "Checkmark.png"),
ChangedSound: (SoundPath: "Tick.ogg", Volume: 6)
)
);
```
## DropdownBoxStyle
Styling for dropdown menus.
```
@MyDropdownStyle = DropdownBoxStyle(
DefaultBackground: (TexturePath: "Dropdown.png", Border: 16),
HoveredBackground: (TexturePath: "DropdownHovered.png", Border: 16),
PressedBackground: (TexturePath: "DropdownPressed.png", Border: 16),
DefaultArrowTexturePath: "DropdownCaret.png",
HoveredArrowTexturePath: "DropdownCaret.png",
PressedArrowTexturePath: "DropdownCaretPressed.png",
ArrowWidth: 13,
ArrowHeight: 18,
LabelStyle: (TextColor: #96a9be, FontSize: 13),
EntryLabelStyle: (TextColor: #b7cedd),
SelectedEntryLabelStyle: (TextColor: #b7cedd, RenderBold: true),
HorizontalPadding: 8,
PanelBackground: (TexturePath: "DropdownBox.png", Border: 16),
PanelPadding: 6,
PanelAlign: Right, // or Bottom
PanelOffset: 7,
EntryHeight: 31,
EntriesInViewport: 10,
HoveredEntryBackground: (Color: #0a0f17),
PressedEntryBackground: (Color: #0f1621),
Sounds: @DropdownBoxSounds,
EntrySounds: @ButtonSounds
);
```
## ScrollbarStyle
Styling for scrollbars.
```
@MyScrollbarStyle = ScrollbarStyle(
Spacing: 6,
Size: 6,
Background: (TexturePath: "Scrollbar.png", Border: 3),
Handle: (TexturePath: "ScrollbarHandle.png", Border: 3),
HoveredHandle: (TexturePath: "ScrollbarHandleHovered.png", Border: 3),
DraggedHandle: (TexturePath: "ScrollbarHandleDragged.png", Border: 3),
OnlyVisibleWhenHovered: false
);
```
## TabNavigationStyle
Styling for tab navigation.
```
@TabStyle = TabStyleState(
Background: "Tab.png",
Overlay: "TabOverlay.png",
IconAnchor: (Width: 44, Height: 44),
Anchor: (Width: 82, Height: 62)
);
@MyTabsStyle = TabNavigationStyle(
TabStyle: (
Default: @TabStyle,
Hovered: (...@TabStyle, Background: "TabHovered.png"),
Pressed: (...@TabStyle, Background: "TabPressed.png")
),
SelectedTabStyle: (
Default: (
...@TabStyle,
Overlay: "TabSelectedOverlay.png"
)
),
TabSounds: @TabSounds,
SeparatorAnchor: (Width: 5, Height: 34),
SeparatorBackground: "TabSeparator.png"
);
```
## TextTooltipStyle
Styling for text tooltips.
```
@MyTooltipStyle = TextTooltipStyle(
Background: (TexturePath: "TooltipBackground.png", Border: 24),
MaxWidth: 400,
LabelStyle: (Wrap: true, FontSize: 16),
Padding: 24
);
```
## Sound Definitions
Sounds are defined as objects with audio properties.
```
@ButtonSounds = (
Activate: (
SoundPath: "Sounds/ButtonActivate.ogg",
Volume: 6,
MinPitch: -0.2,
MaxPitch: 0.2
),
MouseHover: (
SoundPath: "Sounds/ButtonHover.ogg",
Volume: 6
)
);
@DropdownBoxSounds = DropdownBoxSounds(
Activate: (SoundPath: "Tick.ogg", Volume: 6),
MouseHover: (SoundPath: "Hover.ogg", Volume: 6),
Close: (SoundPath: "Untick.ogg", Volume: 6)
);
```
### Sound Properties
| Property | Type | Description |
|----------|------|-------------|
| `SoundPath` | string | Path to audio file |
| `Volume` | number | Volume level (can be negative) |
| `MinPitch` | number | Minimum pitch variation |
| `MaxPitch` | number | Maximum pitch variation |
## Style Inheritance
Use the spread operator to extend styles:
```
@BaseButtonStyle = TextButtonStyle(
Default: (Background: @DefaultBg, LabelStyle: @DefaultLabel),
Hovered: (Background: @HoveredBg, LabelStyle: @DefaultLabel),
Pressed: (Background: @PressedBg, LabelStyle: @DefaultLabel),
Sounds: @ButtonSounds
);
@DestructiveButtonStyle = TextButtonStyle(
...@BaseButtonStyle,
Default: (...@BaseButtonStyle.Default, Background: @DestructiveBg),
Sounds: @DestructiveSounds
);
```

View File

@@ -0,0 +1,367 @@
---
title: Styles UI
type: docs
weight: 14
---
Cette page documente le système de styles pour les widgets UI de Hytale.
## États de Style
Les widgets interactifs supportent plusieurs états :
| État | Quand Appliqué |
|------|----------------|
| `Default` | État normal |
| `Hovered` | Souris sur le widget |
| `Pressed` | Bouton de souris maintenu |
| `Disabled` | Widget désactivé |
```
Style: (
Default: (Background: "Button.png"),
Hovered: (Background: "ButtonHovered.png"),
Pressed: (Background: "ButtonPressed.png"),
Disabled: (Background: "ButtonDisabled.png")
);
```
## LabelStyle
Style de texte pour les widgets Label.
```
@MyLabelStyle = LabelStyle(
FontSize: 16,
FontName: "Default", // ou "Secondary"
TextColor: #ffffff,
RenderBold: true,
RenderUppercase: false,
LetterSpacing: 0,
Wrap: false,
HorizontalAlignment: Center, // Start, Center, End
VerticalAlignment: Center, // Top, Center, Bottom
OutlineColor: #000000(0.5)
);
Label {
Style: @MyLabelStyle;
}
```
### Propriétés LabelStyle
| Propriété | Type | Description |
|-----------|------|-------------|
| `FontSize` | nombre | Taille du texte |
| `FontName` | chaîne | Famille de police ("Default", "Secondary") |
| `TextColor` | couleur | Couleur du texte |
| `RenderBold` | bool | Texte en gras |
| `RenderUppercase` | bool | Forcer les majuscules |
| `LetterSpacing` | nombre | Espace entre les caractères |
| `Wrap` | bool | Activer le retour à la ligne |
| `HorizontalAlignment` | enum | Start, Center, End |
| `VerticalAlignment` | enum | Top, Center, Bottom |
| `OutlineColor` | couleur | Couleur du contour du texte |
| `Alignment` | enum | Raccourci pour les deux alignements (Center) |
## ButtonStyle
Style pour les widgets Button (sans texte).
```
@MyButtonStyle = ButtonStyle(
Default: (Background: (TexturePath: "Button.png", Border: 12)),
Hovered: (Background: (TexturePath: "ButtonHovered.png", Border: 12)),
Pressed: (Background: (TexturePath: "ButtonPressed.png", Border: 12)),
Disabled: (Background: (TexturePath: "ButtonDisabled.png", Border: 12)),
Sounds: @ButtonSounds
);
Button {
Style: @MyButtonStyle;
}
```
### Propriétés d'État Button
| Propriété | Type | Description |
|-----------|------|-------------|
| `Background` | PatchStyle | Apparence du fond |
## TextButtonStyle
Style pour les widgets TextButton.
```
@MyTextButtonStyle = TextButtonStyle(
Default: (
Background: (TexturePath: "Button.png", Border: 12),
LabelStyle: (FontSize: 17, TextColor: #bfcdd5, RenderBold: true)
),
Hovered: (
Background: (TexturePath: "ButtonHovered.png", Border: 12),
LabelStyle: (FontSize: 17, TextColor: #ffffff, RenderBold: true)
),
Pressed: (
Background: (TexturePath: "ButtonPressed.png", Border: 12),
LabelStyle: (FontSize: 17, TextColor: #aaaaaa, RenderBold: true)
),
Disabled: (
Background: (TexturePath: "ButtonDisabled.png", Border: 12),
LabelStyle: (FontSize: 17, TextColor: #797b7c, RenderBold: true)
),
Sounds: @ButtonSounds
);
```
### Propriétés d'État TextButton
| Propriété | Type | Description |
|-----------|------|-------------|
| `Background` | PatchStyle | Apparence du fond |
| `LabelStyle` | LabelStyle | Style du texte |
## PatchStyle
Configuration de texture 9-patch pour les fonds étirables.
```
@MyPatchStyle = PatchStyle(
TexturePath: "Panel.png",
Border: 16 // Bordure uniforme
);
@MyPatchStyle2 = PatchStyle(
TexturePath: "Button.png",
HorizontalBorder: 80, // Bordure gauche/droite
VerticalBorder: 12 // Bordure haut/bas
);
// Avec teinte de couleur
@ColoredPatch = PatchStyle(
Color: #ff0000(0.5) // Rouge semi-transparent
);
```
### Propriétés PatchStyle
| Propriété | Type | Description |
|-----------|------|-------------|
| `TexturePath` | chaîne | Chemin vers le fichier texture |
| `Border` | nombre | Bordure 9-patch uniforme |
| `HorizontalBorder` | nombre | Bordure 9-patch gauche/droite |
| `VerticalBorder` | nombre | Bordure 9-patch haut/bas |
| `Color` | couleur | Couleur unie (au lieu de texture) |
## InputFieldStyle
Style pour les champs de saisie texte.
```
@MyInputStyle = InputFieldStyle(
TextColor: #ffffff,
FontSize: 16
);
@MyPlaceholderStyle = InputFieldStyle(
TextColor: #6e7da1
);
TextField {
Style: @MyInputStyle;
PlaceholderStyle: @MyPlaceholderStyle;
}
```
## SliderStyle
Style pour les contrôles curseur.
```
@MySliderStyle = SliderStyle(
Background: (TexturePath: "SliderBackground.png", Border: 2),
Handle: "SliderHandle.png",
HandleWidth: 16,
HandleHeight: 16,
Sounds: (
Activate: (SoundPath: "SliderTick.ogg", Volume: 10),
MouseHover: (SoundPath: "Hover.ogg", Volume: 6)
)
);
```
### Propriétés SliderStyle
| Propriété | Type | Description |
|-----------|------|-------------|
| `Background` | PatchStyle | Fond de la piste |
| `Handle` | chaîne | Chemin texture de la poignée |
| `HandleWidth` | nombre | Largeur de la poignée |
| `HandleHeight` | nombre | Hauteur de la poignée |
| `Sounds` | objet | Effets sonores |
## CheckBoxStyle
Style pour les cases à cocher.
```
@MyCheckBoxStyle = CheckBoxStyle(
Unchecked: (
DefaultBackground: (Color: #00000000),
HoveredBackground: (Color: #ffffff20),
PressedBackground: (Color: #ffffff10),
DisabledBackground: (Color: #424242),
ChangedSound: (SoundPath: "Untick.ogg", Volume: 6)
),
Checked: (
DefaultBackground: (TexturePath: "Checkmark.png"),
HoveredBackground: (TexturePath: "Checkmark.png"),
PressedBackground: (TexturePath: "Checkmark.png"),
ChangedSound: (SoundPath: "Tick.ogg", Volume: 6)
)
);
```
## DropdownBoxStyle
Style pour les menus déroulants.
```
@MyDropdownStyle = DropdownBoxStyle(
DefaultBackground: (TexturePath: "Dropdown.png", Border: 16),
HoveredBackground: (TexturePath: "DropdownHovered.png", Border: 16),
PressedBackground: (TexturePath: "DropdownPressed.png", Border: 16),
DefaultArrowTexturePath: "DropdownCaret.png",
HoveredArrowTexturePath: "DropdownCaret.png",
PressedArrowTexturePath: "DropdownCaretPressed.png",
ArrowWidth: 13,
ArrowHeight: 18,
LabelStyle: (TextColor: #96a9be, FontSize: 13),
EntryLabelStyle: (TextColor: #b7cedd),
SelectedEntryLabelStyle: (TextColor: #b7cedd, RenderBold: true),
HorizontalPadding: 8,
PanelBackground: (TexturePath: "DropdownBox.png", Border: 16),
PanelPadding: 6,
PanelAlign: Right, // ou Bottom
PanelOffset: 7,
EntryHeight: 31,
EntriesInViewport: 10,
HoveredEntryBackground: (Color: #0a0f17),
PressedEntryBackground: (Color: #0f1621),
Sounds: @DropdownBoxSounds,
EntrySounds: @ButtonSounds
);
```
## ScrollbarStyle
Style pour les barres de défilement.
```
@MyScrollbarStyle = ScrollbarStyle(
Spacing: 6,
Size: 6,
Background: (TexturePath: "Scrollbar.png", Border: 3),
Handle: (TexturePath: "ScrollbarHandle.png", Border: 3),
HoveredHandle: (TexturePath: "ScrollbarHandleHovered.png", Border: 3),
DraggedHandle: (TexturePath: "ScrollbarHandleDragged.png", Border: 3),
OnlyVisibleWhenHovered: false
);
```
## TabNavigationStyle
Style pour la navigation par onglets.
```
@TabStyle = TabStyleState(
Background: "Tab.png",
Overlay: "TabOverlay.png",
IconAnchor: (Width: 44, Height: 44),
Anchor: (Width: 82, Height: 62)
);
@MyTabsStyle = TabNavigationStyle(
TabStyle: (
Default: @TabStyle,
Hovered: (...@TabStyle, Background: "TabHovered.png"),
Pressed: (...@TabStyle, Background: "TabPressed.png")
),
SelectedTabStyle: (
Default: (
...@TabStyle,
Overlay: "TabSelectedOverlay.png"
)
),
TabSounds: @TabSounds,
SeparatorAnchor: (Width: 5, Height: 34),
SeparatorBackground: "TabSeparator.png"
);
```
## TextTooltipStyle
Style pour les infobulles texte.
```
@MyTooltipStyle = TextTooltipStyle(
Background: (TexturePath: "TooltipBackground.png", Border: 24),
MaxWidth: 400,
LabelStyle: (Wrap: true, FontSize: 16),
Padding: 24
);
```
## Définitions de Sons
Les sons sont définis comme des objets avec des propriétés audio.
```
@ButtonSounds = (
Activate: (
SoundPath: "Sounds/ButtonActivate.ogg",
Volume: 6,
MinPitch: -0.2,
MaxPitch: 0.2
),
MouseHover: (
SoundPath: "Sounds/ButtonHover.ogg",
Volume: 6
)
);
@DropdownBoxSounds = DropdownBoxSounds(
Activate: (SoundPath: "Tick.ogg", Volume: 6),
MouseHover: (SoundPath: "Hover.ogg", Volume: 6),
Close: (SoundPath: "Untick.ogg", Volume: 6)
);
```
### Propriétés de Son
| Propriété | Type | Description |
|-----------|------|-------------|
| `SoundPath` | chaîne | Chemin vers le fichier audio |
| `Volume` | nombre | Niveau de volume (peut être négatif) |
| `MinPitch` | nombre | Variation de hauteur minimale |
| `MaxPitch` | nombre | Variation de hauteur maximale |
## Héritage de Styles
Utilisez l'opérateur spread pour étendre les styles :
```
@BaseButtonStyle = TextButtonStyle(
Default: (Background: @DefaultBg, LabelStyle: @DefaultLabel),
Hovered: (Background: @HoveredBg, LabelStyle: @DefaultLabel),
Pressed: (Background: @PressedBg, LabelStyle: @DefaultLabel),
Sounds: @ButtonSounds
);
@DestructiveButtonStyle = TextButtonStyle(
...@BaseButtonStyle,
Default: (...@BaseButtonStyle.Default, Background: @DestructiveBg),
Sounds: @DestructiveSounds
);
```

View File

@@ -0,0 +1,331 @@
---
title: UI Syntax
type: docs
weight: 11
---
This page covers the complete syntax of Hytale's UI markup language.
## Comments
```
// Single line comment
/* Multi-line
comment */
```
## Variables
### Local Variables
Define variables with `@` prefix:
```
@MyNumber = 50;
@MyString = "Hello";
@MyColor = #ff5500;
@MyObject = (Key: value, Other: 123);
```
### Variable Types
| Type | Example |
|------|---------|
| Number | `@Size = 50;` |
| String | `@Text = "Hello";` |
| Color | `@Color = #ff5500;` |
| Object | `@Obj = (Width: 100, Height: 50);` |
| Array | `@List = [item1, item2, item3];` |
| Boolean | `@Visible = true;` |
### Using Variables
Reference variables with `@`:
```
Group {
Anchor: (Height: @MyNumber);
Background: (Color: @MyColor);
}
```
## Imports
### Import Files
Use `$` prefix to import external files:
```
$Common = "Common.ui";
$Sounds = "../Sounds.ui";
$ClientCommon = "../../Common.ui";
```
### Reference Imported Variables
Access imported variables with dot notation:
```
$Common.@DefaultButtonStyle
$Sounds.@ButtonsLight
```
### Use Imported Templates
Instantiate templates from imports:
```
$Common.@TextButton {
@Text = "Click Me";
}
```
## Colors
### Hexadecimal
```
@Color1 = #ff5500; // RGB
@Color2 = #ff5500ff; // RGBA
```
### With Opacity
```
@Color3 = #ff5500(0.5); // 50% opacity
@Color4 = #000000(0.8); // 80% opacity
```
## Objects
### Basic Object
```
@Style = (
FontSize: 16,
TextColor: #ffffff,
RenderBold: true
);
```
### Nested Objects
```
@ButtonStyle = (
Default: (
Background: (TexturePath: "Button.png", Border: 12)
),
Hovered: (
Background: (TexturePath: "ButtonHovered.png", Border: 12)
)
);
```
## Spread Operator
Use `...` to extend/merge objects:
```
@BaseStyle = (
FontSize: 16,
TextColor: #ffffff
);
@ExtendedStyle = (
...@BaseStyle, // Inherit all properties from @BaseStyle
RenderBold: true // Add/override properties
);
```
Spread works in any object context:
```
Style: (
...$Common.@DefaultButtonStyle,
Sounds: (
...$Sounds.@ButtonsLight,
Activate: (Volume: 10)
)
);
```
## Templates (Macros)
### Define a Template
Templates are reusable widget definitions with parameters:
```
@MyButton = TextButton {
@Text = ""; // Parameter with default
@Anchor = Anchor(); // Parameter with default
@Sounds = (); // Empty default
Style: @DefaultTextButtonStyle;
Anchor: (...@Anchor, Height: 44);
Text: @Text;
};
```
### Instantiate a Template
```
// Use with defaults
@MyButton {}
// Override parameters
@MyButton {
@Text = "Submit";
@Anchor = (Width: 200);
}
// From import
$Common.@TextButton {
@Text = %ui.button.confirm;
}
```
## Widget Declarations
### Basic Widget
```
WidgetType {
Property: value;
}
```
### Widget with ID
IDs start with `#` and allow targeting from Java. IDs must be in **UpperCamelCase** format (no hyphens or underscores):
```
Label #PlayerName {
Text: "Unknown";
}
// Valid IDs
#MainPanel
#ConfirmButton
#PlayerHealthBar
// Invalid IDs (will cause errors)
#main-panel // No hyphens allowed
#confirm_button // No underscores allowed
#playerhealthbar // Should be UpperCamelCase
```
### Nested Widgets
```
Group #Container {
Label #Title {
Text: "Header";
}
Group #Content {
Label {
Text: "Body text";
}
}
}
```
### Anonymous Widgets
Widgets without ID are anonymous:
```
Group {
Label { Text: "No ID"; }
}
```
## Selectors
Selectors are strings starting with `#` used to target elements:
```java
// In Java code
builder.set("#PlayerName", "Steve");
builder.append("#Container", "ui/child_template");
builder.clear("#Content");
```
## Translation Keys
Use `%` prefix for localized strings:
```
Label {
Text: %server.ui.shop.title;
}
TextButton {
Text: %client.button.confirm;
}
```
## Typed Constructors
Some complex types use function-style constructors:
```
// Style constructors
@Style = LabelStyle(FontSize: 16, TextColor: #fff);
@BtnStyle = ButtonStyle(Default: (...), Hovered: (...));
// Layout constructors
@Pad = Padding(Full: 10);
@Anch = Anchor(Width: 100, Height: 50);
// Visual constructors
@Bg = PatchStyle(TexturePath: "bg.png", Border: 12);
@Scroll = ScrollbarStyle(Size: 6, Spacing: 8);
```
## Complete Example
```
$Common = "Common.ui";
$Sounds = "Sounds.ui";
@PanelWidth = 400;
@PanelHeight = 300;
@TitleColor = #b4c8c9;
@PanelTitle = Label {
@Text = "";
Style: (
FontSize: 20,
TextColor: @TitleColor,
RenderBold: true,
HorizontalAlignment: Center
);
Text: @Text;
};
Group #MainPanel {
Anchor: (Width: @PanelWidth, Height: @PanelHeight);
Background: (TexturePath: "Panel.png", Border: 20);
LayoutMode: Top;
Padding: (Full: 16);
@PanelTitle {
@Text = %ui.panel.title;
}
Group #Content {
FlexWeight: 1;
LayoutMode: TopScrolling;
ScrollbarStyle: $Common.@DefaultScrollbarStyle;
}
$Common.@TextButton #ConfirmButton {
@Text = %ui.button.confirm;
@Sounds = $Sounds.@ButtonsLight;
}
}
```

View File

@@ -0,0 +1,331 @@
---
title: Syntaxe UI
type: docs
weight: 11
---
Cette page couvre la syntaxe complète du langage de balisage UI de Hytale.
## Commentaires
```
// Commentaire sur une ligne
/* Commentaire
multi-lignes */
```
## Variables
### Variables Locales
Définissez les variables avec le préfixe `@` :
```
@MyNumber = 50;
@MyString = "Bonjour";
@MyColor = #ff5500;
@MyObject = (Key: value, Other: 123);
```
### Types de Variables
| Type | Exemple |
|------|---------|
| Nombre | `@Size = 50;` |
| Chaîne | `@Text = "Bonjour";` |
| Couleur | `@Color = #ff5500;` |
| Objet | `@Obj = (Width: 100, Height: 50);` |
| Tableau | `@List = [item1, item2, item3];` |
| Booléen | `@Visible = true;` |
### Utiliser les Variables
Référencez les variables avec `@` :
```
Group {
Anchor: (Height: @MyNumber);
Background: (Color: @MyColor);
}
```
## Imports
### Importer des Fichiers
Utilisez le préfixe `$` pour importer des fichiers externes :
```
$Common = "Common.ui";
$Sounds = "../Sounds.ui";
$ClientCommon = "../../Common.ui";
```
### Référencer les Variables Importées
Accédez aux variables importées avec la notation pointée :
```
$Common.@DefaultButtonStyle
$Sounds.@ButtonsLight
```
### Utiliser les Templates Importés
Instanciez les templates depuis les imports :
```
$Common.@TextButton {
@Text = "Cliquez-moi";
}
```
## Couleurs
### Hexadécimal
```
@Color1 = #ff5500; // RGB
@Color2 = #ff5500ff; // RGBA
```
### Avec Opacité
```
@Color3 = #ff5500(0.5); // 50% d'opacité
@Color4 = #000000(0.8); // 80% d'opacité
```
## Objets
### Objet Simple
```
@Style = (
FontSize: 16,
TextColor: #ffffff,
RenderBold: true
);
```
### Objets Imbriqués
```
@ButtonStyle = (
Default: (
Background: (TexturePath: "Button.png", Border: 12)
),
Hovered: (
Background: (TexturePath: "ButtonHovered.png", Border: 12)
)
);
```
## Opérateur Spread
Utilisez `...` pour étendre/fusionner des objets :
```
@BaseStyle = (
FontSize: 16,
TextColor: #ffffff
);
@ExtendedStyle = (
...@BaseStyle, // Hérite de toutes les propriétés de @BaseStyle
RenderBold: true // Ajoute/remplace des propriétés
);
```
Le spread fonctionne dans tout contexte d'objet :
```
Style: (
...$Common.@DefaultButtonStyle,
Sounds: (
...$Sounds.@ButtonsLight,
Activate: (Volume: 10)
)
);
```
## Templates (Macros)
### Définir un Template
Les templates sont des définitions de widgets réutilisables avec paramètres :
```
@MyButton = TextButton {
@Text = ""; // Paramètre avec défaut
@Anchor = Anchor(); // Paramètre avec défaut
@Sounds = (); // Défaut vide
Style: @DefaultTextButtonStyle;
Anchor: (...@Anchor, Height: 44);
Text: @Text;
};
```
### Instancier un Template
```
// Utiliser avec les défauts
@MyButton {}
// Remplacer les paramètres
@MyButton {
@Text = "Valider";
@Anchor = (Width: 200);
}
// Depuis un import
$Common.@TextButton {
@Text = %ui.button.confirm;
}
```
## Déclarations de Widgets
### Widget Simple
```
WidgetType {
Property: value;
}
```
### Widget avec ID
Les IDs commencent par `#` et permettent le ciblage depuis Java. Les IDs doivent être en format **UpperCamelCase** (pas de tirets ni underscores) :
```
Label #PlayerName {
Text: "Inconnu";
}
// IDs valides
#MainPanel
#ConfirmButton
#PlayerHealthBar
// IDs invalides (causeront des erreurs)
#main-panel // Pas de tirets
#confirm_button // Pas d'underscores
#playerhealthbar // Doit être en UpperCamelCase
```
### Widgets Imbriqués
```
Group #Container {
Label #Title {
Text: "En-tête";
}
Group #Content {
Label {
Text: "Corps du texte";
}
}
}
```
### Widgets Anonymes
Les widgets sans ID sont anonymes :
```
Group {
Label { Text: "Pas d'ID"; }
}
```
## Sélecteurs
Les sélecteurs sont des chaînes commençant par `#` utilisées pour cibler des éléments :
```java
// Dans le code Java
builder.set("#PlayerName", "Steve");
builder.append("#Container", "ui/child_template");
builder.clear("#Content");
```
## Clés de Traduction
Utilisez le préfixe `%` pour les chaînes localisées :
```
Label {
Text: %server.ui.shop.title;
}
TextButton {
Text: %client.button.confirm;
}
```
## Constructeurs Typés
Certains types complexes utilisent des constructeurs de style fonction :
```
// Constructeurs de styles
@Style = LabelStyle(FontSize: 16, TextColor: #fff);
@BtnStyle = ButtonStyle(Default: (...), Hovered: (...));
// Constructeurs de layout
@Pad = Padding(Full: 10);
@Anch = Anchor(Width: 100, Height: 50);
// Constructeurs visuels
@Bg = PatchStyle(TexturePath: "bg.png", Border: 12);
@Scroll = ScrollbarStyle(Size: 6, Spacing: 8);
```
## Exemple Complet
```
$Common = "Common.ui";
$Sounds = "Sounds.ui";
@PanelWidth = 400;
@PanelHeight = 300;
@TitleColor = #b4c8c9;
@PanelTitle = Label {
@Text = "";
Style: (
FontSize: 20,
TextColor: @TitleColor,
RenderBold: true,
HorizontalAlignment: Center
);
Text: @Text;
};
Group #MainPanel {
Anchor: (Width: @PanelWidth, Height: @PanelHeight);
Background: (TexturePath: "Panel.png", Border: 20);
LayoutMode: Top;
Padding: (Full: 16);
@PanelTitle {
@Text = %ui.panel.title;
}
Group #Content {
FlexWeight: 1;
LayoutMode: TopScrolling;
ScrollbarStyle: $Common.@DefaultScrollbarStyle;
}
$Common.@TextButton #ConfirmButton {
@Text = %ui.button.confirm;
@Sounds = $Sounds.@ButtonsLight;
}
}
```

View File

@@ -0,0 +1,393 @@
---
title: UI Widgets
type: docs
weight: 12
---
This page documents all available widget types in Hytale's UI system.
## Container Widgets
### Group
Basic container for organizing other widgets.
```
Group #Container {
Anchor: (Width: 400, Height: 300);
Background: (Color: #000000(0.5));
LayoutMode: Top;
Padding: (Full: 16);
// Child widgets...
}
```
**Key Properties:**
- `Anchor` - Position and size
- `Background` - Background color or texture
- `LayoutMode` - Child arrangement mode
- `Padding` - Inner spacing
- `Visible` - Show/hide
- `FlexWeight` - Flexible sizing weight
## Text Widgets
### Label
Displays static or dynamic text.
```
Label #Title {
Text: "Hello World";
Style: (
FontSize: 24,
TextColor: #ffffff,
RenderBold: true,
HorizontalAlignment: Center,
VerticalAlignment: Center
);
Anchor: (Height: 40);
}
```
**Key Properties:**
- `Text` - Text content (string or `%translation.key`)
- `Style` - LabelStyle object
- `Anchor` - Position and size
- `Padding` - Text padding
## Button Widgets
### Button
Clickable button without text label.
```
Button #CloseButton {
Anchor: (Width: 32, Height: 32);
Style: (
Default: (Background: "CloseButton.png"),
Hovered: (Background: "CloseButtonHovered.png"),
Pressed: (Background: "CloseButtonPressed.png"),
Disabled: (Background: "CloseButtonDisabled.png"),
Sounds: @ButtonSounds
);
}
```
### TextButton
Button with text label.
```
TextButton #SubmitButton {
Text: %ui.button.submit;
Style: (
Default: (
Background: (TexturePath: "Button.png", Border: 12),
LabelStyle: (FontSize: 16, TextColor: #ffffff)
),
Hovered: (
Background: (TexturePath: "ButtonHovered.png", Border: 12),
LabelStyle: (FontSize: 16, TextColor: #ffffff)
),
Pressed: (
Background: (TexturePath: "ButtonPressed.png", Border: 12),
LabelStyle: (FontSize: 16, TextColor: #cccccc)
),
Sounds: @ButtonSounds
);
Anchor: (Height: 44);
Padding: (Horizontal: 24);
}
```
### BackButton
Pre-styled back/dismiss button.
```
BackButton {}
```
### ActionButton
Button that displays an action name with input binding.
```
ActionButton #BindingInventory {
Disabled: true;
LayoutMode: Right;
Alignment: Right;
ActionName: %client.hud.inputBindings.inventory;
Anchor: (Top: 15);
}
```
## Input Widgets
### TextField
Single-line text input.
```
TextField #NameInput {
Anchor: (Height: 38);
Style: @DefaultInputFieldStyle;
PlaceholderStyle: @DefaultInputFieldPlaceholderStyle;
Background: (TexturePath: "InputBox.png", Border: 16);
Padding: (Horizontal: 10);
PlaceholderText: %ui.placeholder.enterName;
}
```
### NumberField
Numeric input field.
```
NumberField #QuantityInput {
Anchor: (Width: 100, Height: 38);
Style: @DefaultInputFieldStyle;
Background: (TexturePath: "InputBox.png", Border: 16);
Padding: (Horizontal: 10);
Min: 1;
Max: 100;
}
```
### CompactTextField
Expandable search-style text field.
```
CompactTextField #SearchInput {
Anchor: (Height: 30);
CollapsedWidth: 34;
ExpandedWidth: 200;
PlaceholderText: %ui.search.placeholder;
Style: (FontSize: 16);
PlaceholderStyle: (TextColor: #3d5a85, RenderUppercase: true, FontSize: 14);
Padding: (Horizontal: 12, Left: 34);
Decoration: (
Default: (
Icon: (Texture: "SearchIcon.png", Width: 16, Height: 16, Offset: 9),
ClearButtonStyle: @ClearButtonStyle
)
);
ExpandSound: (SoundPath: "Sounds/Expand.ogg", Volume: 6);
CollapseSound: (SoundPath: "Sounds/Collapse.ogg", Volume: 5);
}
```
### Slider
Horizontal slider control.
```
Slider #VolumeSlider {
Anchor: (Width: 200, Height: 16);
Style: (
Background: (TexturePath: "SliderBackground.png", Border: 2),
Handle: "SliderHandle.png",
HandleWidth: 16,
HandleHeight: 16,
Sounds: (
Activate: (SoundPath: "Tick.ogg", Volume: 10),
MouseHover: (SoundPath: "Hover.ogg", Volume: 6)
)
);
Min: 0;
Max: 100;
Value: 50;
}
```
### SliderNumberField
Combined slider with numeric display.
```
SliderNumberField #BrightnessSlider {
Anchor: (Width: 270, Height: 5);
SliderStyle: @DefaultSliderStyle;
NumberFieldStyle: @DefaultInputFieldStyle;
}
```
### CheckBox
Toggle checkbox.
```
CheckBox #EnableOption {
Anchor: (Width: 22, Height: 22);
Background: (TexturePath: "CheckBoxFrame.png", Border: 7);
Padding: (Full: 4);
Style: (
Unchecked: (
DefaultBackground: (Color: #00000000),
HoveredBackground: (Color: #00000000),
ChangedSound: (SoundPath: "Untick.ogg", Volume: 6)
),
Checked: (
DefaultBackground: (TexturePath: "Checkmark.png"),
HoveredBackground: (TexturePath: "Checkmark.png"),
ChangedSound: (SoundPath: "Tick.ogg", Volume: 6)
)
);
Value: false;
}
```
### DropdownBox
Dropdown selection menu.
```
DropdownBox #LanguageSelector {
Anchor: (Width: 330, Height: 32);
Style: (
DefaultBackground: (TexturePath: "Dropdown.png", Border: 16),
HoveredBackground: (TexturePath: "DropdownHovered.png", Border: 16),
PressedBackground: (TexturePath: "DropdownPressed.png", Border: 16),
DefaultArrowTexturePath: "DropdownCaret.png",
ArrowWidth: 13,
ArrowHeight: 18,
LabelStyle: (TextColor: #96a9be, FontSize: 13),
PanelBackground: (TexturePath: "DropdownBox.png", Border: 16),
EntryHeight: 31,
EntriesInViewport: 10,
Sounds: @DropdownBoxSounds
);
}
```
## Display Widgets
### Sprite
Animated or static image.
```
Sprite #LoadingSpinner {
Anchor: (Width: 32, Height: 32);
TexturePath: "Spinner.png";
Frame: (Width: 32, Height: 32, PerRow: 8, Count: 72);
FramesPerSecond: 30;
}
```
### AssetImage
Display an asset image (item icon, etc.).
```
AssetImage #ItemIcon {
Anchor: (Width: 64, Height: 64);
}
```
### ProgressBar
Progress indicator bar.
```
ProgressBar #HealthBar {
Anchor: (Width: 200, Height: 20);
BarTexturePath: "HealthBarFill.png";
Alignment: Horizontal;
Direction: Start;
Value: 0.75;
}
```
**Properties:**
- `Alignment` - `Horizontal` or `Vertical`
- `Direction` - `Start` or `End`
- `Value` - 0.0 to 1.0
## Inventory Widgets
### ItemGrid
Grid display for inventory items.
```
ItemGrid #HotbarGrid {
SlotsPerRow: 9;
Style: (
SlotBackground: "ItemSlot.png",
SlotSize: 64,
SlotSpacing: 4,
HoveredSlotBackground: "ItemSlotHovered.png",
SelectedSlotBackground: "ItemSlotSelected.png"
);
Background: (TexturePath: "HotbarBackground.png", Border: 10);
Padding: 4;
RenderItemQualityBackground: true;
AreItemsDraggable: true;
}
```
## Navigation Widgets
### TabNavigation
Tab-based navigation.
```
TabNavigation #CategoryTabs {
Style: (
TabStyle: (
Default: (Background: "Tab.png", IconAnchor: (Width: 44, Height: 44)),
Hovered: (Background: "TabHovered.png"),
Pressed: (Background: "TabPressed.png")
),
SelectedTabStyle: (
Default: (Background: "TabSelected.png", Overlay: "TabSelectedOverlay.png")
),
TabSounds: @TabSounds
);
}
```
## Tooltip Properties
Many widgets support tooltips:
```
TextButton #InfoButton {
TooltipText: %ui.tooltip.info;
TextTooltipStyle: (
Background: (TexturePath: "TooltipBackground.png", Border: 24),
MaxWidth: 400,
LabelStyle: (Wrap: true, FontSize: 16),
Padding: 24
);
}
```
## Widget Summary Table
| Widget | Purpose |
|--------|---------|
| `Group` | Container for layout |
| `Label` | Text display |
| `Button` | Clickable button |
| `TextButton` | Button with text |
| `BackButton` | Pre-styled back button |
| `ActionButton` | Action with keybind display |
| `TextField` | Text input |
| `NumberField` | Numeric input |
| `CompactTextField` | Expandable search field |
| `Slider` | Slider control |
| `SliderNumberField` | Slider with number display |
| `CheckBox` | Toggle checkbox |
| `DropdownBox` | Selection dropdown |
| `Sprite` | Image/animation |
| `AssetImage` | Asset icon display |
| `ProgressBar` | Progress indicator |
| `ItemGrid` | Inventory grid |
| `TabNavigation` | Tab navigation |

View File

@@ -0,0 +1,393 @@
---
title: Widgets UI
type: docs
weight: 12
---
Cette page documente tous les types de widgets disponibles dans le système UI de Hytale.
## Widgets Conteneurs
### Group
Conteneur de base pour organiser d'autres widgets.
```
Group #Container {
Anchor: (Width: 400, Height: 300);
Background: (Color: #000000(0.5));
LayoutMode: Top;
Padding: (Full: 16);
// Widgets enfants...
}
```
**Propriétés Clés :**
- `Anchor` - Position et taille
- `Background` - Couleur ou texture de fond
- `LayoutMode` - Mode d'arrangement des enfants
- `Padding` - Espacement intérieur
- `Visible` - Afficher/masquer
- `FlexWeight` - Poids de dimensionnement flexible
## Widgets Texte
### Label
Affiche du texte statique ou dynamique.
```
Label #Title {
Text: "Bonjour le monde";
Style: (
FontSize: 24,
TextColor: #ffffff,
RenderBold: true,
HorizontalAlignment: Center,
VerticalAlignment: Center
);
Anchor: (Height: 40);
}
```
**Propriétés Clés :**
- `Text` - Contenu texte (chaîne ou `%translation.key`)
- `Style` - Objet LabelStyle
- `Anchor` - Position et taille
- `Padding` - Marge du texte
## Widgets Boutons
### Button
Bouton cliquable sans label texte.
```
Button #CloseButton {
Anchor: (Width: 32, Height: 32);
Style: (
Default: (Background: "CloseButton.png"),
Hovered: (Background: "CloseButtonHovered.png"),
Pressed: (Background: "CloseButtonPressed.png"),
Disabled: (Background: "CloseButtonDisabled.png"),
Sounds: @ButtonSounds
);
}
```
### TextButton
Bouton avec label texte.
```
TextButton #SubmitButton {
Text: %ui.button.submit;
Style: (
Default: (
Background: (TexturePath: "Button.png", Border: 12),
LabelStyle: (FontSize: 16, TextColor: #ffffff)
),
Hovered: (
Background: (TexturePath: "ButtonHovered.png", Border: 12),
LabelStyle: (FontSize: 16, TextColor: #ffffff)
),
Pressed: (
Background: (TexturePath: "ButtonPressed.png", Border: 12),
LabelStyle: (FontSize: 16, TextColor: #cccccc)
),
Sounds: @ButtonSounds
);
Anchor: (Height: 44);
Padding: (Horizontal: 24);
}
```
### BackButton
Bouton retour/fermer pré-stylisé.
```
BackButton {}
```
### ActionButton
Bouton qui affiche un nom d'action avec sa touche associée.
```
ActionButton #BindingInventory {
Disabled: true;
LayoutMode: Right;
Alignment: Right;
ActionName: %client.hud.inputBindings.inventory;
Anchor: (Top: 15);
}
```
## Widgets de Saisie
### TextField
Champ de saisie texte mono-ligne.
```
TextField #NameInput {
Anchor: (Height: 38);
Style: @DefaultInputFieldStyle;
PlaceholderStyle: @DefaultInputFieldPlaceholderStyle;
Background: (TexturePath: "InputBox.png", Border: 16);
Padding: (Horizontal: 10);
PlaceholderText: %ui.placeholder.enterName;
}
```
### NumberField
Champ de saisie numérique.
```
NumberField #QuantityInput {
Anchor: (Width: 100, Height: 38);
Style: @DefaultInputFieldStyle;
Background: (TexturePath: "InputBox.png", Border: 16);
Padding: (Horizontal: 10);
Min: 1;
Max: 100;
}
```
### CompactTextField
Champ de texte extensible style recherche.
```
CompactTextField #SearchInput {
Anchor: (Height: 30);
CollapsedWidth: 34;
ExpandedWidth: 200;
PlaceholderText: %ui.search.placeholder;
Style: (FontSize: 16);
PlaceholderStyle: (TextColor: #3d5a85, RenderUppercase: true, FontSize: 14);
Padding: (Horizontal: 12, Left: 34);
Decoration: (
Default: (
Icon: (Texture: "SearchIcon.png", Width: 16, Height: 16, Offset: 9),
ClearButtonStyle: @ClearButtonStyle
)
);
ExpandSound: (SoundPath: "Sounds/Expand.ogg", Volume: 6);
CollapseSound: (SoundPath: "Sounds/Collapse.ogg", Volume: 5);
}
```
### Slider
Contrôle curseur horizontal.
```
Slider #VolumeSlider {
Anchor: (Width: 200, Height: 16);
Style: (
Background: (TexturePath: "SliderBackground.png", Border: 2),
Handle: "SliderHandle.png",
HandleWidth: 16,
HandleHeight: 16,
Sounds: (
Activate: (SoundPath: "Tick.ogg", Volume: 10),
MouseHover: (SoundPath: "Hover.ogg", Volume: 6)
)
);
Min: 0;
Max: 100;
Value: 50;
}
```
### SliderNumberField
Curseur combiné avec affichage numérique.
```
SliderNumberField #BrightnessSlider {
Anchor: (Width: 270, Height: 5);
SliderStyle: @DefaultSliderStyle;
NumberFieldStyle: @DefaultInputFieldStyle;
}
```
### CheckBox
Case à cocher.
```
CheckBox #EnableOption {
Anchor: (Width: 22, Height: 22);
Background: (TexturePath: "CheckBoxFrame.png", Border: 7);
Padding: (Full: 4);
Style: (
Unchecked: (
DefaultBackground: (Color: #00000000),
HoveredBackground: (Color: #00000000),
ChangedSound: (SoundPath: "Untick.ogg", Volume: 6)
),
Checked: (
DefaultBackground: (TexturePath: "Checkmark.png"),
HoveredBackground: (TexturePath: "Checkmark.png"),
ChangedSound: (SoundPath: "Tick.ogg", Volume: 6)
)
);
Value: false;
}
```
### DropdownBox
Menu de sélection déroulant.
```
DropdownBox #LanguageSelector {
Anchor: (Width: 330, Height: 32);
Style: (
DefaultBackground: (TexturePath: "Dropdown.png", Border: 16),
HoveredBackground: (TexturePath: "DropdownHovered.png", Border: 16),
PressedBackground: (TexturePath: "DropdownPressed.png", Border: 16),
DefaultArrowTexturePath: "DropdownCaret.png",
ArrowWidth: 13,
ArrowHeight: 18,
LabelStyle: (TextColor: #96a9be, FontSize: 13),
PanelBackground: (TexturePath: "DropdownBox.png", Border: 16),
EntryHeight: 31,
EntriesInViewport: 10,
Sounds: @DropdownBoxSounds
);
}
```
## Widgets d'Affichage
### Sprite
Image animée ou statique.
```
Sprite #LoadingSpinner {
Anchor: (Width: 32, Height: 32);
TexturePath: "Spinner.png";
Frame: (Width: 32, Height: 32, PerRow: 8, Count: 72);
FramesPerSecond: 30;
}
```
### AssetImage
Affiche une image d'asset (icône d'item, etc.).
```
AssetImage #ItemIcon {
Anchor: (Width: 64, Height: 64);
}
```
### ProgressBar
Barre de progression.
```
ProgressBar #HealthBar {
Anchor: (Width: 200, Height: 20);
BarTexturePath: "HealthBarFill.png";
Alignment: Horizontal;
Direction: Start;
Value: 0.75;
}
```
**Propriétés :**
- `Alignment` - `Horizontal` ou `Vertical`
- `Direction` - `Start` ou `End`
- `Value` - 0.0 à 1.0
## Widgets d'Inventaire
### ItemGrid
Grille d'affichage pour les items d'inventaire.
```
ItemGrid #HotbarGrid {
SlotsPerRow: 9;
Style: (
SlotBackground: "ItemSlot.png",
SlotSize: 64,
SlotSpacing: 4,
HoveredSlotBackground: "ItemSlotHovered.png",
SelectedSlotBackground: "ItemSlotSelected.png"
);
Background: (TexturePath: "HotbarBackground.png", Border: 10);
Padding: 4;
RenderItemQualityBackground: true;
AreItemsDraggable: true;
}
```
## Widgets de Navigation
### TabNavigation
Navigation par onglets.
```
TabNavigation #CategoryTabs {
Style: (
TabStyle: (
Default: (Background: "Tab.png", IconAnchor: (Width: 44, Height: 44)),
Hovered: (Background: "TabHovered.png"),
Pressed: (Background: "TabPressed.png")
),
SelectedTabStyle: (
Default: (Background: "TabSelected.png", Overlay: "TabSelectedOverlay.png")
),
TabSounds: @TabSounds
);
}
```
## Propriétés de Tooltip
De nombreux widgets supportent les tooltips :
```
TextButton #InfoButton {
TooltipText: %ui.tooltip.info;
TextTooltipStyle: (
Background: (TexturePath: "TooltipBackground.png", Border: 24),
MaxWidth: 400,
LabelStyle: (Wrap: true, FontSize: 16),
Padding: 24
);
}
```
## Tableau Récapitulatif des Widgets
| Widget | Usage |
|--------|-------|
| `Group` | Conteneur pour la mise en page |
| `Label` | Affichage de texte |
| `Button` | Bouton cliquable |
| `TextButton` | Bouton avec texte |
| `BackButton` | Bouton retour pré-stylisé |
| `ActionButton` | Action avec affichage de touche |
| `TextField` | Saisie de texte |
| `NumberField` | Saisie numérique |
| `CompactTextField` | Champ de recherche extensible |
| `Slider` | Contrôle curseur |
| `SliderNumberField` | Curseur avec affichage numérique |
| `CheckBox` | Case à cocher |
| `DropdownBox` | Menu déroulant de sélection |
| `Sprite` | Image/animation |
| `AssetImage` | Affichage d'icône d'asset |
| `ProgressBar` | Indicateur de progression |
| `ItemGrid` | Grille d'inventaire |
| `TabNavigation` | Navigation par onglets |

View File

@@ -0,0 +1,174 @@
---
title: Windows
type: docs
weight: 3
---
Windows are UI panels for displaying and managing inventory containers, crafting interfaces, and other item-based interactions.
**Package:** `com.hypixel.hytale.server.core.entity.entities.player.windows`
## Window Types
| Type | Description |
|------|-------------|
| `WindowType.Container` | Standard inventory/container view |
| `WindowType.PocketCrafting` | Small crafting grid (2x2) |
| `WindowType.BasicCrafting` | Basic crafting table (3x3) |
| `WindowType.DiagramCrafting` | Diagram-based crafting |
| `WindowType.StructuralCrafting` | Structural/building crafting |
| `WindowType.Processing` | Processing/smelting interface |
| `WindowType.Memories` | Memories storage interface |
## Window Manager
Each player has a `WindowManager` that handles open windows:
```java
Player player = ...;
WindowManager windowManager = player.getWindowManager();
```
## Window Classes
### ContainerWindow
For standard container interfaces:
```java
import com.hypixel.hytale.server.core.entity.entities.player.windows.ContainerWindow;
import com.hypixel.hytale.server.core.inventory.container.ItemContainer;
// Open a container window - takes just the ItemContainer
ContainerWindow window = new ContainerWindow(itemContainer);
```
{{< callout type="info" >}}
`ContainerWindow` automatically uses `WindowType.Container`. The window ID is assigned internally.
{{< /callout >}}
### BlockWindow
`BlockWindow` is an abstract class for block-based containers. It's typically used through built-in interactions rather than instantiated directly.
```java
// BlockWindow is abstract - used internally by block interactions
// Constructor: BlockWindow(WindowType, x, y, z, rotationIndex, BlockType)
```
### ItemStackContainerWindow
For ItemStack-based containers:
```java
import com.hypixel.hytale.server.core.entity.entities.player.windows.ItemStackContainerWindow;
import com.hypixel.hytale.server.core.inventory.container.ItemStackItemContainer;
// Takes an ItemStackItemContainer
ItemStackContainerWindow window = new ItemStackContainerWindow(itemStackItemContainer);
```
## Opening Windows
Use `PageManager.setPageWithWindows()` or `openCustomPageWithWindows()`:
```java
Player player = ...;
PageManager pageManager = player.getPageManager();
Ref<EntityStore> ref = player.getReference();
Store<EntityStore> store = ref.getStore();
// Open page with inventory windows
ContainerWindow chestWindow = new ContainerWindow(chestContainer);
boolean success = pageManager.setPageWithWindows(
ref, store,
Page.None, // or Page.Bench, Page.Inventory, etc.
true, // canCloseThroughInteraction
chestWindow
);
```
## With Custom Pages
Combine windows with custom UI pages:
```java
// Custom crafting UI with windows
CraftingPage craftingPage = new CraftingPage(player.getPlayerRef());
ContainerWindow inputWindow = new ContainerWindow(1, WindowType.BasicCrafting, inputContainer);
ContainerWindow outputWindow = new ContainerWindow(2, WindowType.Container, outputContainer);
pageManager.openCustomPageWithWindows(
ref, store,
craftingPage,
inputWindow,
outputWindow
);
```
## Window Events
Windows interact with the inventory system. Handle inventory changes through the appropriate events and handlers.
## Practical Example
### Chest Container UI
```java
public void openChest(Player player, ItemContainer chestContainer) {
PageManager pageManager = player.getPageManager();
Ref<EntityStore> ref = player.getReference();
Store<EntityStore> store = ref.getStore();
ContainerWindow window = new ContainerWindow(chestContainer);
pageManager.setPageWithWindows(
ref, store,
Page.Bench, // Use Bench page for container UI
true, // Allow closing via interaction
window
);
}
```
### Opening Multiple Windows
```java
public void openCraftingUI(Player player, ItemContainer inputContainer,
ItemContainer outputContainer) {
PageManager pageManager = player.getPageManager();
Ref<EntityStore> ref = player.getReference();
Store<EntityStore> store = ref.getStore();
// Create multiple windows
ContainerWindow inputWindow = new ContainerWindow(inputContainer);
ContainerWindow outputWindow = new ContainerWindow(outputContainer);
pageManager.setPageWithWindows(
ref, store,
Page.Bench,
true,
inputWindow,
outputWindow
);
}
```
{{< callout type="info" >}}
**Note:** `BlockWindow` is abstract and used internally by block interactions. For custom crafting UIs, use `ContainerWindow` with your own containers.
{{< /callout >}}
## Best Practices
{{< callout type="info" >}}
**Window Guidelines:**
- Use unique window IDs for each open window
- Match `WindowType` to the intended interface
- Clean up containers when windows are closed
- Use `canCloseThroughInteraction` appropriately
{{< /callout >}}
{{< callout type="warning" >}}
**Important:** Windows are tied to container state. Ensure containers persist for the duration the window is open.
{{< /callout >}}

View File

@@ -0,0 +1,174 @@
---
title: Fenêtres
type: docs
weight: 3
---
Les fenêtres sont des panneaux UI pour afficher et gérer les conteneurs d'inventaire, les interfaces de crafting et autres interactions basées sur les objets.
**Package:** `com.hypixel.hytale.server.core.entity.entities.player.windows`
## Types de Fenêtres
| Type | Description |
|------|-------------|
| `WindowType.Container` | Vue standard inventaire/conteneur |
| `WindowType.PocketCrafting` | Petite grille de crafting (2x2) |
| `WindowType.BasicCrafting` | Table de crafting basique (3x3) |
| `WindowType.DiagramCrafting` | Crafting basé sur des diagrammes |
| `WindowType.StructuralCrafting` | Crafting structurel/construction |
| `WindowType.Processing` | Interface de traitement/fonte |
| `WindowType.Memories` | Interface de stockage des Mémoires |
## Gestionnaire de Fenêtres
Chaque joueur a un `WindowManager` qui gère les fenêtres ouvertes :
```java
Player player = ...;
WindowManager windowManager = player.getWindowManager();
```
## Classes de Fenêtres
### ContainerWindow
Pour les interfaces de conteneur standard :
```java
import com.hypixel.hytale.server.core.entity.entities.player.windows.ContainerWindow;
import com.hypixel.hytale.server.core.inventory.container.ItemContainer;
// Ouvrir une fenêtre de conteneur - prend juste l'ItemContainer
ContainerWindow window = new ContainerWindow(itemContainer);
```
{{< callout type="info" >}}
`ContainerWindow` utilise automatiquement `WindowType.Container`. L'ID de fenêtre est assigné en interne.
{{< /callout >}}
### BlockWindow
`BlockWindow` est une classe abstraite pour les conteneurs liés aux blocs. Elle est typiquement utilisée via les interactions intégrées plutôt qu'instanciée directement.
```java
// BlockWindow est abstraite - utilisée en interne par les interactions de blocs
// Constructeur: BlockWindow(WindowType, x, y, z, rotationIndex, BlockType)
```
### ItemStackContainerWindow
Pour les conteneurs basés sur ItemStack :
```java
import com.hypixel.hytale.server.core.entity.entities.player.windows.ItemStackContainerWindow;
import com.hypixel.hytale.server.core.inventory.container.ItemStackItemContainer;
// Prend un ItemStackItemContainer
ItemStackContainerWindow window = new ItemStackContainerWindow(itemStackItemContainer);
```
## Ouvrir des Fenêtres
Utilisez `PageManager.setPageWithWindows()` ou `openCustomPageWithWindows()` :
```java
Player player = ...;
PageManager pageManager = player.getPageManager();
Ref<EntityStore> ref = player.getReference();
Store<EntityStore> store = ref.getStore();
// Ouvrir une page avec des fenêtres d'inventaire
ContainerWindow chestWindow = new ContainerWindow(chestContainer);
boolean success = pageManager.setPageWithWindows(
ref, store,
Page.None, // ou Page.Bench, Page.Inventory, etc.
true, // canCloseThroughInteraction
chestWindow
);
```
## Avec des Pages Personnalisées
Combiner les fenêtres avec des pages UI personnalisées :
```java
// UI de crafting personnalisée avec fenêtres
CraftingPage craftingPage = new CraftingPage(player.getPlayerRef());
ContainerWindow inputWindow = new ContainerWindow(inputContainer);
ContainerWindow outputWindow = new ContainerWindow(outputContainer);
pageManager.openCustomPageWithWindows(
ref, store,
craftingPage,
inputWindow,
outputWindow
);
```
## Événements de Fenêtre
Les fenêtres interagissent avec le système d'inventaire. Gérez les changements d'inventaire via les événements et handlers appropriés.
## Exemple Pratique
### UI de Conteneur Coffre
```java
public void openChest(Player player, ItemContainer chestContainer) {
PageManager pageManager = player.getPageManager();
Ref<EntityStore> ref = player.getReference();
Store<EntityStore> store = ref.getStore();
ContainerWindow window = new ContainerWindow(chestContainer);
pageManager.setPageWithWindows(
ref, store,
Page.Bench, // Utiliser Page.Bench pour l'UI de conteneur
true, // Permettre la fermeture via interaction
window
);
}
```
### Ouvrir Plusieurs Fenêtres
```java
public void openCraftingUI(Player player, ItemContainer inputContainer,
ItemContainer outputContainer) {
PageManager pageManager = player.getPageManager();
Ref<EntityStore> ref = player.getReference();
Store<EntityStore> store = ref.getStore();
// Créer plusieurs fenêtres
ContainerWindow inputWindow = new ContainerWindow(inputContainer);
ContainerWindow outputWindow = new ContainerWindow(outputContainer);
pageManager.setPageWithWindows(
ref, store,
Page.Bench,
true,
inputWindow,
outputWindow
);
}
```
{{< callout type="info" >}}
**Note :** `BlockWindow` est abstraite et utilisée en interne par les interactions de blocs. Pour des UI de crafting personnalisées, utilisez `ContainerWindow` avec vos propres conteneurs.
{{< /callout >}}
## Bonnes Pratiques
{{< callout type="info" >}}
**Directives des Fenêtres :**
- Utilisez des IDs de fenêtre uniques pour chaque fenêtre ouverte
- Faites correspondre `WindowType` à l'interface prévue
- Nettoyez les conteneurs quand les fenêtres sont fermées
- Utilisez `canCloseThroughInteraction` de manière appropriée
{{< /callout >}}
{{< callout type="warning" >}}
**Important :** Les fenêtres sont liées à l'état du conteneur. Assurez-vous que les conteneurs persistent pendant toute la durée d'ouverture de la fenêtre.
{{< /callout >}}