webapp
Build / build (push) Has been cancelled

This commit is contained in:
gpatruno
2026-06-06 21:59:51 +02:00
parent 02d2af0993
commit 48a1b900c7
279 changed files with 7488 additions and 238 deletions
+178
View File
@@ -0,0 +1,178 @@
# Hytale — Serveur & plugin MMORPG
Serveur Hytale de développement et plugin **com.disklexar:MMORPG** : profils joueurs persistants, progression, classes, métiers, groupes et fondations pour l'économie, les quêtes et les guildes.
## Prérequis
- **JDK 25+** (Java 26 recommandé si JDK 25 indisponible)
- **Gradle** via le wrapper inclus (`./gradlew`)
- Serveur Hytale (binaire ou `./gradlew runServer` via [ScaffoldIt](https://scaffoldit.dev))
- Installation **Hytale** (launcher officiel) pour les assets du jeu
## Démarrage rapide
```bash
# Depuis ce dossier (Hytale/)
cp hytale.properties.example hytale.properties
# Éditer hytale.home_path (voir exemples dans le fichier)
./start-server.sh
```
Réinitialiser le monde de dev si le serveur a planté sans assets :
```bash
HYTALE_RESET_DEVSERVER=1 ./start-server.sh
```
Ou manuellement :
```bash
JAVA_HOME=/usr/lib/jvm/java-25-openjdk ./gradlew build
JAVA_HOME=/usr/lib/jvm/java-25-openjdk ./gradlew runServer
```
Le JAR produit se trouve dans `build/libs/hytale-mmorpg-0.1.0.jar` (nom selon version Gradle).
### Déploiement manuel
1. Copier le JAR dans le dossier `mods/` du serveur Hytale
2. Redémarrer le serveur
3. La configuration est générée dans le répertoire de données du plugin : `mods/com.disklexar_MMORPG/config.json`
## Systèmes MMORPG
| Système | Contenu | Effet |
|---------|---------|-------|
| **Classes** | Chevalier (`knight`) | Armes : Épée longue, Hache de bataille. 3 capacités (Charge/dash+étourdissement 3s, Toupie 3s, Cri de guerre : repousse + 20% résistance 20s, bonus si étourdi). |
| **Pouvoirs** (passifs, aucun par défaut) | Sprinteur (`sprinter`), Résilient (`resilient`) | +10% vitesse hors combat / +10% dégâts 5s après avoir été touché. |
| **Métiers** | Tueur de monstre (`monster_slayer`), Mineur (`miner`) | +1 money par monstre tué / +1 money par bloc cassé. |
| **Groupes** | Partage d'XP | Les membres reçoivent 40% de l'XP gagnée sur un kill. |
| **Races** | Humain (`human`, par défaut) | XP ×2. |
> **Effets de combat** : dash, étourdissement, toupie, knockback et le buff de vitesse sont
> implémentés via les APIs serveur (`Velocity`, `TransformComponent`, `MovementManager`,
> `TargetUtil`, `DamageSystems`). Les valeurs (distances, forces, dégâts) sont des constantes à
> ajuster en jeu.
## Commandes
| Commande | Description |
|----------|-------------|
| `/mmorpg help` | Affiche l'aide |
| `/mmorpg profile` | Résumé court (niveau, XP) |
| `/mmorpg info` | Toutes vos informations (chat) |
| `/mmorpg menu` | Menu joueur MMORPG — onglets Personnage, Inventaire, Compétences |
| `/mmorpg inventory` | Même menu, ouvert directement sur l'onglet Inventaire |
| `/mmorpg class <choisir\|quitter\|info> [classe]` | Gérer votre classe |
| `/mmorpg power <recevoir\|retirer\|info> [pouvoir]` | Gérer vos pouvoirs |
| `/mmorpg job <rejoindre\|quitter\|info> [metier]` | Gérer vos métiers |
| `/mmorpg group <inviter\|accepter\|quitter\|kick\|info> [joueur]` | Gérer votre groupe |
| `/mmorpg ability <1\|2\|3>` | Utiliser une capacité de classe |
| `/mmorpg password <mot_de_passe>` | Définir ou modifier le mot de passe web |
| Touches **Use Ability 1/2/3** | Même effet que la commande ci-dessus (si vous avez une classe) |
### Capacités de classe (touches Ability 1/2/3)
Les armes vanilla possèdent leurs propres compétences sur les slots Ability. Le plugin les **remplace**
dès qu'un joueur a choisi une classe MMORPG :
1. **Filtre de paquets** (`SyncInteractionChains`) — intercepte Ability 1/2/3 avant le moteur vanilla,
envoie `CancelInteractionChain` au client et lance la capacité de classe.
2. **Interaction native** (`mmorpg_cast_ability`) — enregistrée côté serveur ; les patches d'items dans
`plugins/mmorpg/src/main/resources/Server/Item/Items/` remplacent Ability1/2/3 sur les armes de test (sync client/serveur).
Prérequis en jeu : `/mmorpg class choisir <classe>` puis équiper une arme autorisée pour cette classe.
Sans classe, les compétences vanilla de l'arme s'appliquent normalement.
Pour ajouter d'autres armes, copiez un patch JSON existant (ex. `Weapon_Longsword_Mithril.json`) en
ne gardant que `"Id"` et `"Interactions"`.
`/mmorpg menu` ouvre une `CustomUIPage` listant toutes les infos du joueur (classe, race, pouvoirs,
métiers, groupe, money, temps de jeu, dates…). Un plugin **serveur seul** ne peut pas ajouter un
bouton dans l'écran d'inventaire natif ; les équivalents fournis sont la commande `/mmorpg menu` et
l'interaction `mmorpg_player_info` (voir `plugins/mmorpg/assetpack/README.md` pour brancher un asset `.ui`).
## Configuration
Fichier `config.json` (valeurs par défaut dans `plugins/mmorpg/src/main/resources/config.json`) :
| Clé | Description |
|-----|-------------|
| `Debug` | Logs détaillés |
| `DefaultLevel` | Niveau initial des nouveaux joueurs |
| `MaxPlayers` | Limite prévue (référence future) |
| `BaseXpPerLevel` | XP de base requise par niveau |
| `KillExperience` | XP de base accordée par monstre tué |
| `Database.FileName` | Nom du fichier SQLite (`mmorpg.db`) |
| `Database.UseMonorepoRoot` | Si `true`, place la base à la racine du dépôt (dossiers `Hytale/` + `Webapp/`) |
| `Database.Path` | Chemin absolu ou relatif au dossier de données du plugin (prioritaire) |
| `Features.Economy` | Active le module économie |
| `Features.Quests` | Active le module quêtes (M3) |
| `Features.Guilds` | Active le module guildes (M4) |
## Base de données
Le plugin persiste les données joueurs dans **SQLite**.
### Emplacement
| Contexte | Fichier |
|----------|---------|
| **Monorepo (dev)** | `../mmorpg.db` à la racine du dépôt (détection auto si `UseMonorepoRoot: true`) |
| **Production** | `{dataDirectory}/mmorpg.db` ou chemin explicite via `Database.Path` |
Inspecter en local :
```bash
sqlite3 ../mmorpg.db
SELECT uuid, display_name, level, experience FROM player_profiles;
```
Les fichiers `*.db` sont ignorés par Git.
### Schéma
`player_profiles` : `class_id`, `powers` (JSON), `jobs` (JSON), `guild_id`, `group_id`,
`is_connected`, `total_time_play`, `last_date_connected`, `date_creation`, `money`, `race_id`.
Tables de référence : `classes`, `powers`, `jobs`, `races`, `groups`, `group_members`.
Migrations versionnées via `schema_migrations` — voir `plugins/mmorpg/src/main/resources/db/migrations/`.
## Structure du plugin
```
plugins/mmorpg/src/main/java/com/disklexar/mmorpg/
├── MmorpgPlugin.java # Point d'entrée (commandes + systèmes ECS)
├── bootstrap/ # Initialisation et registre de services
├── core/ # Config et contrats
├── player/ # Sessions, profils, registre des joueurs en ligne
├── persistence/ # SQLite (migrations versionnées, repositories)
├── command/ # Commandes /mmorpg
├── events/ # Connexion / déconnexion, filtre paquets Ability
├── interaction/ # mmorpg_cast_ability (interaction native asset pack)
├── progression/ # XP et niveaux (multiplicateurs de race)
├── economy/ # Monnaie (money)
├── rpg/ # clazz · power · job · race · group
├── combat/ # Capacités, état de combat, effets passifs
│ └── system/ # Systèmes ECS : dégâts, morts/kills, casse de bloc
├── ui/ # AbilityBarHud, PlayerMenuPage, PlayerInfoPage
├── quest/ # Stub (M3)
└── social/ # Stub (M4)
```
## Documentation
- [Interface utilisateur MMORPG (UI/UX)](docs/README-UI.md)
- [Architecture](docs/ARCHITECTURE.md)
- [Feuille de route](docs/ROADMAP.md)
- [Guide de développement](docs/DEVELOPMENT.md)
- [Contribution](../CONTRIBUTING.md)
### Custom UI (Hytale)
- [Custom UI — vue d'ensemble](https://hytalemodding.dev/en/docs/official-documentation/custom-ui)
- [Layout](https://hytalemodding.dev/en/docs/official-documentation/custom-ui/layout)
- [Common Styling](https://hytalemodding.dev/en/docs/official-documentation/custom-ui/common-styling)
- [Guide plugin UI](https://hytalemodding.dev/en/docs/guides/plugin/ui)
+45
View File
@@ -0,0 +1,45 @@
import org.gradle.jvm.toolchain.JavaLanguageVersion
plugins {
id("com.gradleup.shadow") version "9.0.0-rc1"
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(25))
}
}
sourceSets {
main {
java.setSrcDirs(listOf("plugins/mmorpg/src/main/java"))
resources.setSrcDirs(listOf("plugins/mmorpg/src/main/resources"))
}
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.xerial:sqlite-jdbc:3.47.2.0")
implementation("com.google.code.gson:gson:2.11.0")
implementation("at.favre.lib:bcrypt:0.10.2")
}
tasks.shadowJar {
archiveClassifier.set("")
mergeServiceFiles()
}
tasks.jar {
enabled = false
}
tasks.assemble {
dependsOn(tasks.shadowJar)
}
tasks.build {
dependsOn(tasks.shadowJar)
}
+72
View File
@@ -0,0 +1,72 @@
# Architecture
## Vue d'ensemble
Le projet est un **plugin monolithique** Java déployé sur le serveur Hytale officiel. Le serveur gère le monde, le réseau et l'ECS ; le plugin ajoute la couche MMORPG (persistance, progression, systèmes futurs).
```mermaid
flowchart TB
subgraph server [Serveur Hytale]
ECS[ECS / Mondes]
Events[EventBus]
Cmds[CommandRegistry]
end
subgraph mmorpg [Plugin com.disklexar:MMORPG]
Plugin[MmorpgPlugin]
Boot[Bootstrap]
Registry[ServiceRegistry]
PlayerSvc[PlayerSessionService]
DB[(SQLite)]
end
Plugin --> Boot --> Registry
Registry --> PlayerSvc
PlayerSvc --> DB
Plugin --> Events
Plugin --> Cmds
```
## Cycle de vie du plugin
| Phase | Responsabilité |
|-------|----------------|
| `setup()` | Charge la config, initialise `Bootstrap`, enregistre commandes et événements |
| `start()` | Démarre les services (`DatabaseManager`, `PlayerSessionService`, …) |
| `shutdown()` | Sauvegarde les sessions, ferme SQLite |
Le singleton `MmorpgPlugin.get()` est rafraîchi à chaque chargement pour rester compatible avec le hot-reload Hytale.
## Modules et dépendances
| Package | Dépend de | Rôle |
|---------|-----------|------|
| `bootstrap` | `core`, `persistence`, `player` | Câblage des services |
| `core` | — | Config, interface `Service` |
| `persistence` | `core` | SQLite, repositories |
| `player` | `persistence`, `core` | Profils et sessions en ligne |
| `command` | `player`, `bootstrap` | Interface joueur |
| `events` | `player`, `bootstrap` | Connexion / déconnexion |
| `economy`, `quest`, `social` | — (stubs) | Extensions futures |
**Règle** : les packages `economy`, `quest` et `social` ne doivent pas être importés par `core` ou `persistence` tant qu'ils ne sont pas implémentés. L'activation se fait via `Features.*` dans `config.json`.
## Persistance
- Fichier : `{monorepoRoot}/mmorpg.db` en dev (monorepo) ou `{dataDirectory}/mmorpg.db` en production
- Migrations : `plugins/mmorpg/src/main/resources/db/migrations/*.sql`
- Table initiale : `player_profiles` (uuid, display_name, level, experience, timestamps)
Les dépendances JDBC (SQLite) et JSON (Gson) sont **embarquées dans le JAR** via Shadow, car absentes du classpath serveur.
## Événements joueur
- **Connexion prête** : `PlayerReadyEvent` → chargement ou création du profil
- **Déconnexion** : `PlayerDisconnectEvent` → sauvegarde et retrait de la session mémoire
## Conventions
- Identifiants joueur : `java.util.UUID`
- Noms affichés : `PlayerRef.getUsername()` en priorité
- Logs : `HytaleLogger` du plugin
- Permissions futures : préfixe `com.disklexar.mmorpg.*`
+69
View File
@@ -0,0 +1,69 @@
# Guide de développement
## Environnement
1. Installer **JDK 25** (`java-25-openjdk`). Le script `start-server.sh` force `/usr/lib/jvm/java-25-openjdk`.
2. Installer **Hytale** via le launcher et configurer `hytale.home_path` (copier `hytale.properties.example``hytale.properties` dans `Hytale/`).
3. Cloner le dépôt et ouvrir le projet Gradle dans `Hytale/` (IntelliJ : `./gradlew openIdea` via ScaffoldIt).
## Commandes Gradle
Exécuter depuis le dossier `Hytale/` :
| Tâche | Description |
|-------|-------------|
| `./gradlew build` | Compile et produit le JAR (Shadow) |
| `./gradlew runServer` | Serveur de dev local |
| `./gradlew generateManifest` | Régénère `manifest.json` depuis `settings.gradle.kts` |
| `./gradlew setupServer` | Prépare le répertoire `devserver/` |
## Workflow recommandé
1. Créer une branche depuis `main`
2. Implémenter dans le package approprié (voir [ARCHITECTURE.md](ARCHITECTURE.md))
3. Vérifier `./gradlew build`
4. Tester en jeu avec `./gradlew runServer`
5. Ouvrir une pull request
## Base de données locale
- **Monorepo** : `mmorpg.db` à la racine du dépôt (à côté de `Hytale/` et `Webapp/`), si `UseMonorepoRoot: true` dans `config.json`
- **Sinon** : `devserver/.../com.disklexar_MMORPG/mmorpg.db` (chemin exact selon ScaffoldIt)
- Inspecter avec `sqlite3 mmorpg.db`
- Requête utile : `SELECT * FROM player_profiles;`
Les fichiers `*.db` sont ignorés par Git.
## Logs
Le plugin utilise `getLogger()` (HytaleLogger). Activer `Debug: true` dans `config.json` pour plus de détails sur les sessions.
Logs serveur de dev : `Hytale/devserver/logs/`.
## Dépannage runServer
| Symptôme | Cause | Solution |
|----------|-------|----------|
| `--assets=null` dans les logs Gradle | `hytale.home_path` non configuré | `hytale.properties` ou `HYTALE_HOME` |
| `Missing default DamageCause assets` | Assets jeu absents | Installer Hytale + configurer le chemin |
| `Env_Zone1_Plains doesn't exist` | `devserver` créé sans assets | `HYTALE_RESET_DEVSERVER=1 ./start-server.sh` |
| `Task :runServer FAILED` exit 1 | Voir `devserver/logs/*.log` | Corriger la cause ci-dessus |
## API Hytale
La dépendance `com.hypixel.hytale:Server:+` est en **compileOnly** : ne pas l'inclure dans le JAR final. En cas d'erreur de compilation après mise à jour serveur :
- Vérifier les noms d'événements (`PlayerReadyEvent`, `PlayerDisconnectEvent`)
- Consulter [doctale.dev](https://doctale.dev) et le template [HytaleModding/plugin-template](https://github.com/HytaleModding/plugin-template)
## Ajouter une migration SQL
1. Créer `plugins/mmorpg/src/main/resources/db/migrations/00X_description.sql`
2. Étendre `SchemaInitializer` pour exécuter les nouveaux fichiers dans l'ordre
3. Documenter le changement dans le changelog / PR
## Style de code
- Packages en minuscules, classes en PascalCase
- Pas de logique métier dans `MmorpgPlugin` — déléguer aux services
- Fermer les ressources JDBC dans try-with-resources
+439
View File
@@ -0,0 +1,439 @@
# Interface utilisateur MMORPG — conception UI/UX
Document de référence pour l'interface joueur du plugin **com.disklexar:MMORPG** sur Hytale.
Objectif : une UI type MMORPG **moderne, ergonomique, immersive et intuitive**, compatible avec les
contraintes d'un plugin **serveur** (assets `.ui` embarqués, `CustomUIHud`, `CustomUIPage`).
---
## Principes directeurs
| Principe | Application |
|----------|-------------|
| **Lisibilité en combat** | Contrastes élevés, tailles minimales 12 px, icônes + texte court |
| **Hiérarchie visuelle** | HUD persistant discret ; menus modaux pour la gestion profonde |
| **Feedback immédiat** | Cooldowns, buffs et dégâts reflétés en < 1 s côté client |
| **Cohérence** | Palette sombre `#1a1c20` / accents `#c8a45c` (or MMORPG) sur tous les écrans |
| **Responsive** | Ancres relatives (`Left`, `Right`, `Bottom`) + grilles flex, pas de pixels fixes centraux |
| **Dégradation gracieuse** | Commandes chat (`/mmorpg info`, `/mmorpg profile`) si un asset `.ui` est invalide |
### Palette
```
Fond HUD #1a1c20 @ 85 % Barre pleine vie #3d8f5a
Fond slot #24262a Barre vide #2a2d32
Texte primaire #e8e8ec Mana / énergie #4a8fd4
Texte secondaire #878e9c XP / niveau #c8a45c
Buff positif #5cb85c Debuff négatif #c9302c
Bordure focus #c8a45c Overlay modal #1b1b1f @ 93 %
```
---
## Architecture globale
```mermaid
flowchart TB
subgraph hud [HUD persistant — en jeu]
Vitals[Barres vie / mana / XP]
Buffs[Buffs & debuffs]
Hotbar[Barre d'action]
AbilityBar[Barre capacités classe]
end
subgraph menus [Menus joueur — modaux]
Shell[Coquille MmorpgPlayerShell.ui]
Char[Onglet Personnage]
Inv[Onglet Inventaire]
Skills[Onglet Arbre de compétences]
end
subgraph server [Serveur Java]
ABS[AbilityBarService]
PIP[PlayerInfoPage]
Future[HudVitalsService — M1]
FutureMenu[PlayerMenuPage — M1]
end
ABS --> AbilityBar
Future --> Vitals
Future --> Buffs
Future --> Hotbar
FutureMenu --> Shell
Shell --> Char
Shell --> Inv
Shell --> Skills
PIP -.->|fallback actuel| Char
```
### Arborescence des assets (cible)
```
src/main/resources/Common/UI/Custom/
├── Huds/
│ ├── MmorpgVitalsHud.ui # Vie, mana, XP (bas-gauche)
│ ├── MmorpgBuffTrayHud.ui # Buffs / debuffs (sous les barres)
│ ├── MmorpgHotbarHud.ui # Slots objets + raccourcis
│ └── MmorpgAbilityBar.ui # ✅ Implémenté — 3 slots classe
├── Pages/
│ ├── MmorpgPlayerShell.ui # Fenêtre à onglets (coquille)
│ ├── MmorpgCharacterTab.ui # Onglet Personnage
│ ├── MmorpgInventoryPage.ui # 🟡 Début — inventaire MMORPG (coquille + grille)
│ ├── MmorpgInventoryTab.ui # Onglet Inventaire (futur, dans coquille à onglets)
│ └── MmorpgSkillTreeTab.ui # Onglet Arbre de compétences
└── Widgets/
├── MmorpgProgressBar.ui # Barre réutilisable (vie, mana, XP)
├── MmorpgBuffIcon.ui # Icône buff avec timer
└── MmorpgSkillNode.ui # Nœud d'arbre de compétences
```
### Mapping code serveur
| Composant UI | Classe Java | Statut |
|--------------|-------------|--------|
| Barre capacités | `AbilityBarHud` + `AbilityBarService` | ✅ Actif |
| Profil joueur (fallback) | `PlayerInfoPage` | ✅ Actif (`/mmorpg menucustom`) |
| Menu à onglets | `PlayerMenuPage` | ✅ Actif (`/mmorpg menu`) |
| Onglet Personnage | `MmorpgCharacterTab.ui` | ✅ Actif |
| Onglet Inventaire | `MmorpgInventoryTab.ui` + `PlayerInventoryReader` | ✅ Actif |
| Onglet Compétences | `MmorpgSkillsTab.ui` | ✅ Actif (capacités classe + branches M1) |
| Barres vitales HUD | `VitalsHud` + `VitalsHudService` | 🔲 M1 |
| Buff tray | `BuffTrayHud` | 🔲 M1 |
| Hotbar étendue | `HotbarHud` | 🔲 M2 |
---
## 1. Affichage principal (HUD)
Le HUD reste **toujours visible** en exploration et en combat. Les éléments natifs Hytale
(inventaire rapide, minimap) sont conservés ; le plugin ajoute des calques `CustomUIHud`
(`z-order` croissant : vitals → buffs → hotbar → capacités).
### 1.1 Disposition écran (desktop 16:9)
```
┌──────────────────────────────────────────────────────────────────────────┐
│ [Minimap native] [Quêtes]* │
│ │
│ MONDE / COMBAT │
│ │
│ │
│ ┌─ Vitals ─────────────────┐ │
│ │ ♥ ████████░░ 840/1000 │ ← Vie │
│ │ ◆ ██████░░░░ 120/200 │ ← Mana / énergie │
│ │ ★ Nv.42 ████░ 67 % │ ← Niveau + barre XP │
│ └──────────────────────────┘ │
│ [Buff][Buff][Debuff]... ← Buff tray (max 8 icônes visibles) │
│ │
│ [1][2][3][4][5][6][7][8][9][0] ← Hotbar objets │
│ [Cap1][Cap2][Cap3] ← Barre capacités classe │
└──────────────────────────────────────────────────────────────────────────┘
* futur module quêtes
```
### 1.2 Barres de vie, mana et XP
**Fichier cible :** `Huds/MmorpgVitalsHud.ui`
| Élément | ID serveur | Donnée source | Comportement |
|---------|------------|---------------|--------------|
| Barre de vie | `#HealthBar`, `#HealthText` | Composants entité joueur (vanilla) + bonus MMORPG futurs | Remplissage proportionnel ; flash rouge si < 25 % |
| Barre de mana | `#ManaBar`, `#ManaText` | Attribut MMORPG (M1) | Masquée si classe sans mana (ex. Chevalier) |
| Niveau | `#LevelLabel` | `PlayerProfile.level` | `Nv. {n}` |
| Barre XP | `#XpBar`, `#XpText` | `ProgressionService` | `{current}/{required}` + pourcentage |
**Rafraîchissement :** toutes les 500 ms via `VitalsHudService` ; push immédiat sur gain d'XP ou dégâts.
**Widget réutilisable `MmorpgProgressBar.ui` :**
```
Group #ProgressBar
Group #Fill — largeur dynamique (ui.set Width ou FlexWeight)
Label #ValueText — "840 / 1000"
```
### 1.3 Buffs et debuffs actifs
**Fichier cible :** `Huds/MmorpgBuffTrayHud.ui`
| Propriété | Valeur |
|-----------|--------|
| Position | Au-dessus des barres vitales, aligné à gauche |
| Capacité | 8 icônes visibles ; défilement horizontal si > 8 |
| Par icône | Image, nom court, timer circulaire ou compte à rebours |
| Sources serveur | `CombatBuffService`, `StunService`, effets de classe |
**IDs dynamiques :** `#BuffSlot0``#BuffSlot7` — le serveur injecte des instances de
`Widgets/MmorpgBuffIcon.ui` via `appendInline`.
**Code couleur :** bordure verte = buff allié ; rouge = debuff ; or = effet neutre / passif.
### 1.4 Barre d'action (hotbar)
**Fichier cible :** `Huds/MmorpgHotbarHud.ui`
La hotbar MMORPG **complète** la barre native sans la remplacer :
| Zone | Slots | Contenu |
|------|-------|---------|
| Objets consommables | 10 (10) | Potions, nourriture, gadgets MMORPG |
| Capacités classe | Ability 13 | Géré par `MmorpgAbilityBar.ui` (déjà séparé) |
| Slot utilitaire | `U` (optionnel) | Monture, outil de métier |
**Par slot :**
- Icône de l'objet / compétence
- Raccourci clavier (coin supérieur droit)
- Overlay cooldown (assombrissement + texte secondes)
- Bordure dorée si sélectionné
**Interaction :** les slots 13 déclenchent `mmorpg_cast_ability` ; les autres passent par
l'inventaire natif ou des interactions custom futures.
### 1.5 Barre de capacités de classe (implémentée)
**Fichier :** `Common/UI/Custom/MmorpgAbilityBar.ui`
**Service :** `AbilityBarService` — affichage automatique à la connexion si le joueur a une classe.
| Slot | ID | Touche | Mise à jour |
|------|-----|--------|-------------|
| 1 | `#Slot1Name`, `#Slot1Key` | Q (Use Ability 1) | Nom + cooldown (`Charge (3s)`) |
| 2 | `#Slot2Name`, `#Slot2Key` | E (Use Ability 2) | idem |
| 3 | `#Slot3Name`, `#Slot3Key` | R (Use Ability 3) | idem |
Les labels `#Slot*Key` / `#Ability*Key` sont remplis par `AbilitySlotKeys` avec les raccourcis
Hytale par défaut (`[Q]`, `[E]`, `[R]`). Le serveur ne connaît pas les rebinding client.
**Commande debug :** `/mmorpg hud` — force la synchronisation.
---
## 2. Menus joueur
Ouverture : **`/mmorpg menu`** → coquille à onglets (`PlayerMenuPage`).
Fallback chat : `/mmorpg info` si la page UI échoue.
### 2.1 Coquille — `MmorpgPlayerShell.ui`
```
Panel (centré, max 900×600, fond #1b1b1fEE)
├── Header
│ ├── Portrait / icône classe #ClassPortrait
│ ├── Nom joueur #PlayerName
│ └── Monnaie #MoneyLabel
├── TabBar (horizontal)
│ ├── Button #TabCharacter "Personnage"
│ ├── Button #TabInventory "Inventaire"
│ └── Button #TabSkills "Compétences"
├── ContentHost #TabContent (swap le document de l'onglet actif)
└── Footer
└── Button #CloseButton "Fermer"
```
**Navigation :** `UIEventBuilder` lie chaque onglet ; le serveur charge le `.ui` de l'onglet
dans `#TabContent` via `ui.clear` + `ui.append`.
### 2.2 Onglet Personnage
**Fichier cible :** `Pages/MmorpgCharacterTab.ui`
| Section | Champs | Source `PlayerProfile` |
|---------|--------|------------------------|
| Identité | Nom, race, classe | `displayName`, `raceId`, `classId` |
| Progression | Niveau, XP, barre XP | `level`, `experience` |
| Attributs* | Force, Agilité, Intelligence… | M1 — stats dérivées |
| Pouvoirs passifs | Liste à puces | `powers``PowerCatalog` |
| Métiers | Liste à puces | `jobs``JobCatalog` |
| Social | Groupe, guilde | `groupId`, `guildId` |
| Statistiques | Temps de jeu, argent, dates | `PlayerInfoView` (existant) |
\* Les attributs numériques sont un placeholder visuel jusqu'à l'implémentation M1.
**Layout :** deux colonnes sur grand écran — gauche : portrait + barres ; droite : listes
pouvoirs / métiers / social.
### 2.3 Onglet Inventaire
**Fichier inventaire :** `Pages/MmorpgInventoryPage.ui` — document **racine** pour l'onglet Inventaire (`/mmorpg inventory`)
**Fichier coquille :** `Pages/MmorpgPlayerShell.ui` — Personnage / Compétences uniquement
> Relié à l'inventaire **vanilla** via `ItemGrid.InventorySectionId` (sac, barre rapide, armure, utilitaire).
> **`InventorySectionId` ne fonctionne pas** dans une coquille imbriquée : l'inventaire doit être le document
> racine (`MmorpgInventoryPage.ui`). Changement d'onglet vers/depuis Inventaire → `rebuild()` complet.
> Ne pas appeler `#Grid.Slots` depuis le serveur (tableau ou `#Grid.Slots.N`) — le client rejette
> ces commandes et déconnecte. Les grilles utilisent `InventorySectionId` ; l'affichage passe par
> des overlays `ItemSlot` (`ItemId` / `Quantity`).
> Glisser-déposer synchronisé ; panneau détails au clic.
| Zone | ID | Section vanilla |
|------|-----|-----------------|
| Armure | `#ArmorGrid` | `ARMOR_SECTION_ID` (-3) |
| Utilitaire | `#UtilityGrid` | `UTILITY_SECTION_ID` (-5) |
| Sac | `#StorageGrid` | `STORAGE_SECTION_ID` (-2), 9×4 |
| Barre rapide | `#HotbarGrid` | `HOTBAR_SECTION_ID` (-1) |
| Détails | `#ItemDetails` | Clic / survol slot → `PlayerInventoryReader` |
**À venir :** filtres par catégorie, stats MMORPG sur items tagués, boutons Utiliser / Jeter.
**Ergonomie :**
- Clic gauche : sélection + détails
- Double-clic : utiliser (si consommable)
- Shift-clic : déplacer vers équipement (futur)
- Recherche texte `#SearchField` en haut de grille
### 2.4 Onglet Arbre de compétences
**Fichier cible :** `Pages/MmorpgSkillTreeTab.ui`
| Élément | Description |
|---------|-------------|
| `#TreeCanvas` | Zone scrollable / zoomable (pincer sur mobile) |
| `#SkillNode_*` | Nœuds : icône, rang actuel / max, prérequis |
| `#PointsAvailable` | Points de compétence non dépensés |
| `#NodeTooltip` | Survol : nom, effet, coût, prérequis |
| `#ResetButton` | Réinitialisation (coût en monnaie, futur) |
**États visuels d'un nœud (`Widgets/MmorpgSkillNode.ui`) :**
| État | Apparence |
|------|-----------|
| Verrouillé | Grisé, cadenas |
| Disponible | Bordure or clignotante légère |
| Appris (rang 1n) | Rempli, rang affiché |
| Max | Bordure brillante, étoile |
**Données :** JSON ou table SQLite `skill_nodes` (M1+) ; rendu initial basé sur la classe active
(`ClassCatalog` → 3 branches par classe en V1).
---
## 3. Responsive et multi-résolution
### Breakpoints (ratio largeur / hauteur viewport client)
| Profil | Condition | Adaptations |
|--------|-----------|-------------|
| **Desktop** | largeur ≥ 1280 px | Menus 900 px ; HUD complet ; 2 colonnes Personnage |
| **Compact** | 10241279 px | Menus 720 px ; buff tray 6 icônes ; texte réduit 1 px |
| **Small** | < 1024 px | Menus plein écran ; vitals empilés ; hotbar 6 slots visibles + scroll |
| **Ultrawide** | ratio > 2.1 | HUD ancré aux tiers gauche/droite, pas aux bords extrêmes |
### Règles d'ancrage (fichiers `.ui`)
```
# HUD bas
Anchor: (Bottom: 24, Left: 24) — vitals
Anchor: (Bottom: 28, Left: 0, Right: 0) — ability bar (centré)
# Menu modal
Anchor: Center
Style: (MaxWidth: 900, Width: 90%)
```
- Préférer `FlexWeight`, `Padding: (Full: n)` et `LayoutMode: Top/Right` aux positions absolues.
- Les groupes vides utilisent `Anchor: (Width: 6)` comme séparateurs (pattern `MmorpgAbilityBar.ui`).
- Tester en 1920×1080, 1366×768 et 1280×720.
### Accessibilité
- Contraste texte / fond ≥ 4.5:1 (WCAG AA)
- Taille police minimale 12 px (HUD) / 14 px (menus)
- Les cooldowns affichent **chiffres + assombrissement** (pas la couleur seule)
- Raccourcis clavier listés dans chaque infobulle de slot
---
## 4. Flux utilisateur
```mermaid
sequenceDiagram
participant J as Joueur
participant C as Client Hytale
participant S as Serveur MMORPG
J->>C: Connexion
C->>S: PlayerReadyEvent
S->>S: loadOrCreate(profile)
alt a une classe
S->>C: addCustomHud(MmorpgAbilityBar)
end
S->>C: Message bienvenue (niveau, race)
J->>C: /mmorpg menu ou touche C
C->>S: openCustomPage
S->>C: PlayerInfoPage (puis PlayerMenuPage)
J->>C: Ability 1
C->>S: SyncInteractionChains (filtré)
S->>C: CancelInteractionChain + cast
S->>C: update HUD cooldowns
```
---
## 5. Commandes et raccourcis
| Action | Commande / touche | Écran |
|--------|-------------------|-------|
| Ouvrir profil | `/mmorpg menu` | Menu (liste → coquille) |
| Profil chat | `/mmorpg info` | Fallback texte |
| Résumé court | `/mmorpg profile` | Chat |
| Forcer HUD capacités | `/mmorpg hud` | HUD |
| Capacité 13 | Touches Ability 1/2/3 | HUD + exécution |
| Fermer menu | Échap | — |
**Raccourcis cibles (M1) :** `C` → menu ; `K` → arbre de compétences ; `I` déjà natif inventaire.
---
## 6. Phases d'implémentation
| Phase | Livrables UI | Dépendances gameplay |
|-------|--------------|----------------------|
| **M0** ✅ | `MmorpgAbilityBar.ui`, `PlayerInfoPage`, `/mmorpg hud` | Classes, capacités |
| **M1** | `MmorpgVitalsHud`, `MmorpgBuffTray`, `MmorpgPlayerShell` + onglet Personnage | Stats vie/mana, buffs |
| **M2** | Onglet Inventaire MMORPG, `MmorpgHotbarHud` | Items tagués, équipement — **début** : `MmorpgInventoryPage.ui` |
| **M3** | Onglet Arbre de compétences | Points de compétence, déblocages |
| **M4** | Quêtes dans HUD, tooltips riches | Module quêtes |
---
## 7. Validation et tests
1. **Asset pack** : `IncludesAssetPack: true` dans `manifest.json` — chaque `.ui` doit être
validé en jeu (un fichier invalide **crash le client** à la connexion).
2. **Checklist par écran :**
- [ ] Connexion sans crash client
- [ ] HUD visible après choix de classe
- [ ] Cooldowns décrémentent chaque seconde
- [ ] Déconnexion retire le HUD (`AbilityBarService.dismiss`)
- [ ] Menu s'ouvre et se ferme (Échap)
- [ ] Responsive : pas de chevauchement à 1366×768
3. **Logs serveur :** rechercher `Ability bar HUD` dans `devserver/logs/`.
---
## 8. Références
### Documentation Custom UI (officielle / guides)
- [Custom UI — vue d'ensemble](https://hytalemodding.dev/en/docs/official-documentation/custom-ui) — HUD vs pages, `append` / `set`, sélecteurs
- [Layout](https://hytalemodding.dev/en/docs/official-documentation/custom-ui/layout) — `Anchor`, `LayoutMode`, `FlexWeight` (utilisé pour le panneau inventaire 3 colonnes)
- [Common Styling](https://hytalemodding.dev/en/docs/official-documentation/custom-ui/common-styling) — `Common.ui`, styles vanilla réutilisables
- [Guide plugin UI](https://hytalemodding.dev/en/docs/guides/plugin/ui) — chemin `Common/UI/Custom`, `IncludesAssetPack`, mode diagnostic client
**Rappels appris en production :**
- `CustomUIHud` : uniquement `append(document)` + `set()` — pas de `appendInline` / `clear` (crash client).
- Propriétés dynamiques : préférer `ProgressBar.Value` plutôt que `Group.Width` (rejeté par le client).
- Ancrage HUD : le groupe racine doit avoir `Anchor: (Left: …, Width: …)` sinon centrage écran.
### Fichiers projet
- Code UI : `src/main/java/com/disklexar/mmorpg/ui/`
- HUD vitals + capacités : `src/main/resources/Common/UI/Custom/MmorpgAbilityBar.ui`
- Inventaire (début) : `src/main/resources/Common/UI/Custom/Pages/MmorpgInventoryPage.ui`
- Profil (scaffold) : `src/main/resources/Common/UI/Custom/Pages/MmorpgPlayerInfo.ui`
- Guide asset pack : [assetpack/README.md](../assetpack/README.md)
- Architecture : [ARCHITECTURE.md](ARCHITECTURE.md)
+53
View File
@@ -0,0 +1,53 @@
# Feuille de route
## M0 — Fondation (actuel)
- [x] Projet Gradle + ScaffoldIt
- [x] Plugin `com.disklexar:MMORPG`
- [x] SQLite + table `player_profiles`
- [x] Sessions joueur (connexion / déconnexion)
- [x] Commandes `/mmorpg help` et `/mmorpg profile`
- [x] Packages stub : `economy`, `quest`, `social`
- [x] Documentation et CI
## M1 — Personnage et progression
- [ ] Système d'expérience et montée de niveau
- [ ] Statistiques de base (vie, mana, attributs)
- [ ] Sauvegarde position / monde (spawn MMORPG)
- [ ] Messages et UI côté client (si API disponible)
## M2 — Économie
- [ ] Monnaie serveur (wallets SQLite)
- [ ] Transactions atomiques
- [ ] Vendeurs NPC et tables de loot
- [ ] Activer `Features.Economy` dans la config
## M3 — Quêtes
- [ ] Définitions de quêtes (JSON ou DB)
- [ ] Objectifs : collecte, dialogue, zone
- [ ] Récompenses XP / items / monnaie
- [ ] Quêtes journalières
- [ ] Activer `Features.Quests`
## M4 — Social et instances
- [ ] Groupes / parties
- [ ] Guildes (création, rangs, banque)
- [ ] Instances / donjons dédiés
- [ ] Activer `Features.Guilds`
## M5 — Production
- [ ] Migration PostgreSQL optionnelle
- [ ] Cache Redis pour sessions multi-serveur
- [ ] Métriques et monitoring
- [ ] Anti-triche basique (rate limits, validation serveur)
## Hors périmètre connu
- Asset pack custom (modèles, textures)
- Interface web d'administration
- Client modifié (hors API serveur)
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored Executable
+248
View File
@@ -0,0 +1,248 @@
#!/bin/sh
#
# Copyright © 2015 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='-Dfile.encoding=UTF-8 "-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
+93
View File
@@ -0,0 +1,93 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=-Dfile.encoding=UTF-8 "-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
+10
View File
@@ -0,0 +1,10 @@
# Copier ce fichier vers hytale.properties et adapter le chemin.
# Dossier d'installation Hytale (doit contenir install/.../Assets.zip)
#
# Linux (Flatpak) :
# hytale.home_path=/home/VOTRE_USER/.var/app/com.hypixel.HytaleLauncher/data/Hytale
#
# Windows :
# hytale.home_path=C:/Users/VOTRE_USER/AppData/Roaming/Hytale
hytale.home_path=
+54
View File
@@ -0,0 +1,54 @@
# Asset pack (scaffold) — MMORPG
Server-only plugins **cannot inject a button into the native inventory screen** and cannot render
a custom-designed page without a client-side asset (`.ui`). This folder is the scaffold to add one.
## What already works without this asset pack
- `/mmorpg menu` opens a real `CustomUIPage` (`PlayerInfoPage`) built with **inline UI markup**, so
it renders without any bundled asset.
- `/mmorpg info` prints the same data in chat (reliable fallback).
- The `mmorpg_player_info` interaction is registered (`OpenCustomUIInteraction`) so the page can be
opened from an item/block interaction once you wire one.
## Class ability keys (Ability 1/2/3)
Weapon ability slots are overridden in **`src/main/resources/Server/Item/Items/`** (bundled with the
plugin JAR, not this scaffold folder). Each patch sets:
```json
"Ability1": {
"Interactions": [{ "Type": "mmorpg_cast_ability", "Slot": 1 }]
}
```
The Java interaction `mmorpg_cast_ability` is registered in `MmorpgPlugin`. Even without a patch
for a given weapon, the **packet filter** still routes Ability 1/2/3 to class abilities when the
player has a class.
To patch another weapon, add `Server/Item/Items/<ItemId>.json` with only `"Id"` and `"Interactions"`.
Shipped examples: longsword, battleaxe, staff, daggers, shortbow, crossbow (mithril/cobalt variants).
## Enabling the designed `.ui` template
1. Package this `assetpack/` content according to your Hytale/ScaffoldIt asset-pack layout and set
`"IncludesAssetPack": true` in `src/main/resources/manifest.json`.
2. Edit `com.disklexar.mmorpg.ui.PlayerInfoPage#build` to append the template and fill fields:
```java
ui.append("Pages/MmorpgPlayerInfo.ui");
ui.set("#Title.Text", "Profil MMORPG");
for (PlayerInfoView.Entry e : PlayerInfoView.entries(profile)) {
ui.append("#Content", "Label { Text: \"" + e.label() + " : " + e.value() + "\"; }");
}
events.addEventBinding(CustomUIEventBindingType.Click, "#CloseButton");
```
3. Validate the `.ui` grammar in-game and adjust `MmorpgPlayerInfo.ui`.
## Inventory button
A literal button inside the native inventory UI requires a client UI mod/asset overriding the
inventory screen, which is out of scope for a server-only plugin. The supported equivalents are the
`/mmorpg menu` command and the `mmorpg_player_info` interaction above.
@@ -0,0 +1,29 @@
// Sample custom UI page template for the MMORPG player-info screen.
//
// This is a SCAFFOLD: the exact .ui markup grammar is defined by the Hytale client and must be
// validated in-game. The plugin works today without this file because PlayerInfoPage builds its
// layout with inline markup. Use this template when you want a richer designed layout, then have
// PlayerInfoPage.build() append "Pages/MmorpgPlayerInfo.ui" and set the named fields below.
//
// Named fields the server can target via UICommandBuilder.set(...):
// #Title.Text - page title
// #Content - vertical container the server appends one Label per attribute into
// #CloseButton - close/dismiss button (bind via UIEventBuilder)
Panel {
Style: (Width: 420; Anchor: Center; Padding: 16; Background: (Color: #1b1b1fEE));
Label #Title {
Text: "Profil MMORPG";
Style: (Alignment: Center; FontSize: 20; MarginBottom: 12);
}
VerticalList #Content {
Style: (Spacing: 4);
}
Button #CloseButton {
Text: "Fermer";
Style: (Alignment: Center; MarginTop: 12);
}
}

Some files were not shown because too many files have changed in this diff Show More