diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8c846fd..60eaa7a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,6 +9,9 @@ on: jobs: build: runs-on: ubuntu-latest + defaults: + run: + working-directory: Hytale steps: - uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index 729d4ea..5aa4b2a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,15 @@ ### Build ### -build/ +Hytale/build/ +Hytale/.gradle/ +Hytale/.kotlin/ +Hytale/devserver/ .gradle/ -.kotlin/ -devserver/ ### Hytale local config (chemin d'installation personnel) ### -hytale.properties +Hytale/hytale.properties +Hytale/gradle.properties -### Database ### +### Database (racine du monorepo + emplacements locaux) ### *.db *.db-journal diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8d3e2c6..e63e712 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,10 +1,10 @@ # Contribution -Merci de contribuer au serveur MMORPG Hytale. +Merci de contribuer au serveur MMORPG Hytale Disklexar. ## Avant de commencer -1. Lire [ARCHITECTURE.md](docs/ARCHITECTURE.md) et [ROADMAP.md](docs/ROADMAP.md) +1. Lire [ARCHITECTURE.md](Hytale/docs/ARCHITECTURE.md) et [ROADMAP.md](Hytale/docs/ROADMAP.md) 2. Vérifier qu'aucune issue existante ne couvre déjà votre sujet ## Branches @@ -16,7 +16,7 @@ Merci de contribuer au serveur MMORPG Hytale. ## Pull requests - Une PR = un sujet cohérent -- `./gradlew build` doit passer +- `cd Hytale && ./gradlew build` doit passer - Description en français ou anglais : **quoi** + **pourquoi** - Référencer la phase roadmap (M0, M1, …) si applicable diff --git a/Hytale/README.md b/Hytale/README.md new file mode 100644 index 0000000..fea5338 --- /dev/null +++ b/Hytale/README.md @@ -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 [classe]` | Gérer votre classe | +| `/mmorpg power [pouvoir]` | Gérer vos pouvoirs | +| `/mmorpg job [metier]` | Gérer vos métiers | +| `/mmorpg group [joueur]` | Gérer votre groupe | +| `/mmorpg ability <1\|2\|3>` | Utiliser une capacité de classe | +| `/mmorpg password ` | 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 ` 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) diff --git a/build.gradle.kts b/Hytale/build.gradle.kts similarity index 72% rename from build.gradle.kts rename to Hytale/build.gradle.kts index a165b2a..54766e0 100644 --- a/build.gradle.kts +++ b/Hytale/build.gradle.kts @@ -10,6 +10,13 @@ java { } } +sourceSets { + main { + java.setSrcDirs(listOf("plugins/mmorpg/src/main/java")) + resources.setSrcDirs(listOf("plugins/mmorpg/src/main/resources")) + } +} + repositories { mavenCentral() } @@ -17,6 +24,7 @@ repositories { 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 { diff --git a/docs/ARCHITECTURE.md b/Hytale/docs/ARCHITECTURE.md similarity index 93% rename from docs/ARCHITECTURE.md rename to Hytale/docs/ARCHITECTURE.md index 20a9944..9930800 100644 --- a/docs/ARCHITECTURE.md +++ b/Hytale/docs/ARCHITECTURE.md @@ -53,8 +53,8 @@ Le singleton `MmorpgPlugin.get()` est rafraîchi à chaque chargement pour reste ## Persistance -- Fichier : `{dataDirectory}/mmorpg.db` -- Migrations : `src/main/resources/db/migrations/*.sql` +- 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. diff --git a/docs/DEVELOPMENT.md b/Hytale/docs/DEVELOPMENT.md similarity index 82% rename from docs/DEVELOPMENT.md rename to Hytale/docs/DEVELOPMENT.md index 73bd1cd..701a6f2 100644 --- a/docs/DEVELOPMENT.md +++ b/Hytale/docs/DEVELOPMENT.md @@ -3,11 +3,13 @@ ## 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`). -3. Cloner le dépôt et ouvrir le projet dans IntelliJ IDEA : `./gradlew openIdea` (ScaffoldIt). +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) | @@ -25,7 +27,8 @@ ## Base de données locale -- Fichier : `devserver/.../com.disklexar_MMORPG/mmorpg.db` (chemin exact selon ScaffoldIt) +- **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;` @@ -35,7 +38,7 @@ Les fichiers `*.db` sont ignorés par Git. Le plugin utilise `getLogger()` (HytaleLogger). Activer `Debug: true` dans `config.json` pour plus de détails sur les sessions. -Logs serveur de dev : `devserver/logs/`. +Logs serveur de dev : `Hytale/devserver/logs/`. ## Dépannage runServer @@ -55,7 +58,7 @@ La dépendance `com.hypixel.hytale:Server:+` est en **compileOnly** : ne pas l'i ## Ajouter une migration SQL -1. Créer `src/main/resources/db/migrations/00X_description.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 diff --git a/docs/README-UI.md b/Hytale/docs/README-UI.md similarity index 98% rename from docs/README-UI.md rename to Hytale/docs/README-UI.md index fdea3a9..b2651fc 100644 --- a/docs/README-UI.md +++ b/Hytale/docs/README-UI.md @@ -260,7 +260,9 @@ pouvoirs / métiers / social. > 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 — le client rejette cette commande et déconnecte. +> 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 | diff --git a/docs/ROADMAP.md b/Hytale/docs/ROADMAP.md similarity index 100% rename from docs/ROADMAP.md rename to Hytale/docs/ROADMAP.md diff --git a/gradle/wrapper/gradle-wrapper.jar b/Hytale/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from gradle/wrapper/gradle-wrapper.jar rename to Hytale/gradle/wrapper/gradle-wrapper.jar diff --git a/gradle/wrapper/gradle-wrapper.properties b/Hytale/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from gradle/wrapper/gradle-wrapper.properties rename to Hytale/gradle/wrapper/gradle-wrapper.properties diff --git a/gradlew b/Hytale/gradlew similarity index 100% rename from gradlew rename to Hytale/gradlew diff --git a/gradlew.bat b/Hytale/gradlew.bat similarity index 100% rename from gradlew.bat rename to Hytale/gradlew.bat diff --git a/hytale.properties.example b/Hytale/hytale.properties.example similarity index 100% rename from hytale.properties.example rename to Hytale/hytale.properties.example diff --git a/assetpack/README.md b/Hytale/plugins/mmorpg/assetpack/README.md similarity index 100% rename from assetpack/README.md rename to Hytale/plugins/mmorpg/assetpack/README.md diff --git a/assetpack/ui/Pages/MmorpgPlayerInfo.ui b/Hytale/plugins/mmorpg/assetpack/ui/Pages/MmorpgPlayerInfo.ui similarity index 100% rename from assetpack/ui/Pages/MmorpgPlayerInfo.ui rename to Hytale/plugins/mmorpg/assetpack/ui/Pages/MmorpgPlayerInfo.ui diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/MmorpgPlugin.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/MmorpgPlugin.class new file mode 100644 index 0000000..8e2d86d Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/MmorpgPlugin.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/bootstrap/Bootstrap.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/bootstrap/Bootstrap.class new file mode 100644 index 0000000..2220198 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/bootstrap/Bootstrap.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/bootstrap/ServiceRegistry.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/bootstrap/ServiceRegistry.class new file mode 100644 index 0000000..00e9ec9 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/bootstrap/ServiceRegistry.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/AbilityService$CastResult.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/AbilityService$CastResult.class new file mode 100644 index 0000000..6727aae Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/AbilityService$CastResult.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/AbilityService.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/AbilityService.class new file mode 100644 index 0000000..e1d014c Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/AbilityService.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/ClassAbilityController$1.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/ClassAbilityController$1.class new file mode 100644 index 0000000..edec1ce Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/ClassAbilityController$1.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/ClassAbilityController$ResolveFailure.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/ClassAbilityController$ResolveFailure.class new file mode 100644 index 0000000..a6cfa1b Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/ClassAbilityController$ResolveFailure.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/ClassAbilityController$ResolveOutcome.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/ClassAbilityController$ResolveOutcome.class new file mode 100644 index 0000000..f29880f Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/ClassAbilityController$ResolveOutcome.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/ClassAbilityController$ResolvedAbility.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/ClassAbilityController$ResolvedAbility.class new file mode 100644 index 0000000..57d103f Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/ClassAbilityController$ResolvedAbility.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/ClassAbilityController.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/ClassAbilityController.class new file mode 100644 index 0000000..2b7d70d Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/ClassAbilityController.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/CombatBuffService.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/CombatBuffService.class new file mode 100644 index 0000000..fc1271d Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/CombatBuffService.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/CombatFx.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/CombatFx.class new file mode 100644 index 0000000..942f603 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/CombatFx.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/CombatStateService.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/CombatStateService.class new file mode 100644 index 0000000..11839ac Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/CombatStateService.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/MmorpgScheduler.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/MmorpgScheduler.class new file mode 100644 index 0000000..382d082 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/MmorpgScheduler.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/PassiveEffectService.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/PassiveEffectService.class new file mode 100644 index 0000000..ee9650b Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/PassiveEffectService.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/PoisonService.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/PoisonService.class new file mode 100644 index 0000000..c86f229 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/PoisonService.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/StunService.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/StunService.class new file mode 100644 index 0000000..8593844 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/StunService.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/system/MinerBlockBreakSystem.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/system/MinerBlockBreakSystem.class new file mode 100644 index 0000000..e48d52c Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/system/MinerBlockBreakSystem.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/system/MmorpgDamageSystem.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/system/MmorpgDamageSystem.class new file mode 100644 index 0000000..5fcb751 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/system/MmorpgDamageSystem.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/system/MmorpgDeathSystem.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/system/MmorpgDeathSystem.class new file mode 100644 index 0000000..d92cff1 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/combat/system/MmorpgDeathSystem.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/AbilityCommand.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/AbilityCommand.class new file mode 100644 index 0000000..e3e6c0d Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/AbilityCommand.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/ClassCommand$Choose.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/ClassCommand$Choose.class new file mode 100644 index 0000000..7417f45 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/ClassCommand$Choose.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/ClassCommand$Info.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/ClassCommand$Info.class new file mode 100644 index 0000000..cc264a4 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/ClassCommand$Info.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/ClassCommand$Leave.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/ClassCommand$Leave.class new file mode 100644 index 0000000..e2d066d Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/ClassCommand$Leave.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/ClassCommand.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/ClassCommand.class new file mode 100644 index 0000000..45526c5 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/ClassCommand.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/CommandSupport.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/CommandSupport.class new file mode 100644 index 0000000..9419349 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/CommandSupport.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$1.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$1.class new file mode 100644 index 0000000..53ed729 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$1.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$Accept.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$Accept.class new file mode 100644 index 0000000..24144b1 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$Accept.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$Info.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$Info.class new file mode 100644 index 0000000..7eb9359 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$Info.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$Invite.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$Invite.class new file mode 100644 index 0000000..13f22e9 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$Invite.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$Kick.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$Kick.class new file mode 100644 index 0000000..ab5c352 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$Kick.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$Leave.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$Leave.class new file mode 100644 index 0000000..fcb5c62 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand$Leave.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand.class new file mode 100644 index 0000000..eeda4ea Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/GroupCommand.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/HudCommand.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/HudCommand.class new file mode 100644 index 0000000..727f48c Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/HudCommand.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/InfoCommand.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/InfoCommand.class new file mode 100644 index 0000000..68c585a Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/InfoCommand.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/InventoryCommand.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/InventoryCommand.class new file mode 100644 index 0000000..88fb9bd Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/InventoryCommand.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/JobCommand$Info.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/JobCommand$Info.class new file mode 100644 index 0000000..3583af2 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/JobCommand$Info.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/JobCommand$Join.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/JobCommand$Join.class new file mode 100644 index 0000000..fc356b7 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/JobCommand$Join.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/JobCommand$Leave.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/JobCommand$Leave.class new file mode 100644 index 0000000..31c05c6 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/JobCommand$Leave.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/JobCommand.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/JobCommand.class new file mode 100644 index 0000000..ee6af6e Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/JobCommand.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/MenuCommand.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/MenuCommand.class new file mode 100644 index 0000000..1f76a73 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/MenuCommand.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/MenuCustomCommand.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/MenuCustomCommand.class new file mode 100644 index 0000000..1f5e6ab Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/MenuCustomCommand.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/MmorpgCommand.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/MmorpgCommand.class new file mode 100644 index 0000000..7ad5d31 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/MmorpgCommand.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/MmorpgHelpCommand.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/MmorpgHelpCommand.class new file mode 100644 index 0000000..b34fc81 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/MmorpgHelpCommand.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/MmorpgProfileCommand.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/MmorpgProfileCommand.class new file mode 100644 index 0000000..549e7d2 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/MmorpgProfileCommand.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/PowerCommand$Grant.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/PowerCommand$Grant.class new file mode 100644 index 0000000..9d7050f Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/PowerCommand$Grant.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/PowerCommand$Info.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/PowerCommand$Info.class new file mode 100644 index 0000000..3d383fd Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/PowerCommand$Info.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/PowerCommand$Revoke.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/PowerCommand$Revoke.class new file mode 100644 index 0000000..6cdafb4 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/PowerCommand$Revoke.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/PowerCommand.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/PowerCommand.class new file mode 100644 index 0000000..c1aaee7 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/command/PowerCommand.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/core/config/MmorpgConfig$DatabaseConfig.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/core/config/MmorpgConfig$DatabaseConfig.class new file mode 100644 index 0000000..0b4afc4 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/core/config/MmorpgConfig$DatabaseConfig.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/core/config/MmorpgConfig$FeaturesConfig.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/core/config/MmorpgConfig$FeaturesConfig.class new file mode 100644 index 0000000..209f046 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/core/config/MmorpgConfig$FeaturesConfig.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/core/config/MmorpgConfig.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/core/config/MmorpgConfig.class new file mode 100644 index 0000000..887f028 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/core/config/MmorpgConfig.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/core/service/Service.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/core/service/Service.class new file mode 100644 index 0000000..45f2290 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/core/service/Service.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/economy/EconomyService.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/economy/EconomyService.class new file mode 100644 index 0000000..951383c Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/economy/EconomyService.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/events/AbilityPacketFilter.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/events/AbilityPacketFilter.class new file mode 100644 index 0000000..6422666 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/events/AbilityPacketFilter.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/events/PlayerConnectionHandler.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/events/PlayerConnectionHandler.class new file mode 100644 index 0000000..6ecaffc Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/events/PlayerConnectionHandler.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/interaction/MmorpgCastAbilityInteraction.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/interaction/MmorpgCastAbilityInteraction.class new file mode 100644 index 0000000..fff7a5b Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/interaction/MmorpgCastAbilityInteraction.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/persistence/DatabaseManager.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/persistence/DatabaseManager.class new file mode 100644 index 0000000..6af4b57 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/persistence/DatabaseManager.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/persistence/repository/GroupRepository.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/persistence/repository/GroupRepository.class new file mode 100644 index 0000000..9d66893 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/persistence/repository/GroupRepository.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/persistence/repository/PlayerProfileRepository$1.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/persistence/repository/PlayerProfileRepository$1.class new file mode 100644 index 0000000..638c828 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/persistence/repository/PlayerProfileRepository$1.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/persistence/repository/PlayerProfileRepository.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/persistence/repository/PlayerProfileRepository.class new file mode 100644 index 0000000..87cf7db Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/persistence/repository/PlayerProfileRepository.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/persistence/schema/SchemaInitializer.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/persistence/schema/SchemaInitializer.class new file mode 100644 index 0000000..1cd0ab8 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/persistence/schema/SchemaInitializer.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/OnlinePlayer.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/OnlinePlayer.class new file mode 100644 index 0000000..e2cde52 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/OnlinePlayer.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/OnlinePlayerRegistry.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/OnlinePlayerRegistry.class new file mode 100644 index 0000000..98a49e0 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/OnlinePlayerRegistry.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/PlayerInfoView$Entry.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/PlayerInfoView$Entry.class new file mode 100644 index 0000000..9c933e5 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/PlayerInfoView$Entry.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/PlayerInfoView.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/PlayerInfoView.class new file mode 100644 index 0000000..970a19b Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/PlayerInfoView.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/PlayerSessionService.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/PlayerSessionService.class new file mode 100644 index 0000000..5be7a26 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/PlayerSessionService.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/model/PlayerProfile.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/model/PlayerProfile.class new file mode 100644 index 0000000..32b2f25 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/player/model/PlayerProfile.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/progression/ProgressionService.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/progression/ProgressionService.class new file mode 100644 index 0000000..8fde373 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/progression/ProgressionService.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/clazz/AbilityDefinition.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/clazz/AbilityDefinition.class new file mode 100644 index 0000000..8f62efd Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/clazz/AbilityDefinition.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/clazz/ClassCatalog.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/clazz/ClassCatalog.class new file mode 100644 index 0000000..7fd81a6 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/clazz/ClassCatalog.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/clazz/ClassService.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/clazz/ClassService.class new file mode 100644 index 0000000..d78a62f Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/clazz/ClassService.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/clazz/PlayerClass.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/clazz/PlayerClass.class new file mode 100644 index 0000000..76abd94 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/clazz/PlayerClass.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/group/Group.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/group/Group.class new file mode 100644 index 0000000..f3f05ad Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/group/Group.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/group/GroupService$AcceptResult.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/group/GroupService$AcceptResult.class new file mode 100644 index 0000000..ddc7aa7 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/group/GroupService$AcceptResult.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/group/GroupService$InviteResult.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/group/GroupService$InviteResult.class new file mode 100644 index 0000000..90a4bbe Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/group/GroupService$InviteResult.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/group/GroupService$KickResult.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/group/GroupService$KickResult.class new file mode 100644 index 0000000..d384877 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/group/GroupService$KickResult.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/group/GroupService.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/group/GroupService.class new file mode 100644 index 0000000..22e218b Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/group/GroupService.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/job/JobCatalog.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/job/JobCatalog.class new file mode 100644 index 0000000..772da1b Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/job/JobCatalog.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/job/JobDefinition.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/job/JobDefinition.class new file mode 100644 index 0000000..5a511cc Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/job/JobDefinition.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/job/JobService.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/job/JobService.class new file mode 100644 index 0000000..7db3c52 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/job/JobService.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/power/PowerCatalog.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/power/PowerCatalog.class new file mode 100644 index 0000000..8ae45c0 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/power/PowerCatalog.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/power/PowerDefinition.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/power/PowerDefinition.class new file mode 100644 index 0000000..ab84bfa Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/power/PowerDefinition.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/power/PowerService.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/power/PowerService.class new file mode 100644 index 0000000..44a877a Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/power/PowerService.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/race/RaceCatalog.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/race/RaceCatalog.class new file mode 100644 index 0000000..9e2a7d8 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/race/RaceCatalog.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/race/RaceDefinition.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/race/RaceDefinition.class new file mode 100644 index 0000000..98fc751 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/race/RaceDefinition.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/race/RaceService.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/race/RaceService.class new file mode 100644 index 0000000..dbd9c60 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/rpg/race/RaceService.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/AbilityBarHud.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/AbilityBarHud.class new file mode 100644 index 0000000..19c4297 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/AbilityBarHud.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/AbilityBarService.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/AbilityBarService.class new file mode 100644 index 0000000..f98b50e Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/AbilityBarService.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/AbilitySlotKeys.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/AbilitySlotKeys.class new file mode 100644 index 0000000..8a79997 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/AbilitySlotKeys.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInfoPage.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInfoPage.class new file mode 100644 index 0000000..1ffc136 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInfoPage.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryDrag.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryDrag.class new file mode 100644 index 0000000..82ffe74 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryDrag.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryPage$SlotSelection.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryPage$SlotSelection.class new file mode 100644 index 0000000..2fb8d07 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryPage$SlotSelection.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryPage$UiEvent.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryPage$UiEvent.class new file mode 100644 index 0000000..e7db8e9 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryPage$UiEvent.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryPage.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryPage.class new file mode 100644 index 0000000..b23f911 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryPage.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryReader$ItemView.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryReader$ItemView.class new file mode 100644 index 0000000..074d010 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryReader$ItemView.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryReader$SectionCounts.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryReader$SectionCounts.class new file mode 100644 index 0000000..5716636 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryReader$SectionCounts.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryReader$Snapshot.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryReader$Snapshot.class new file mode 100644 index 0000000..bd13b7a Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryReader$Snapshot.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryReader.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryReader.class new file mode 100644 index 0000000..bab3ada Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventoryReader.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventorySlotView$SlotRef.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventorySlotView$SlotRef.class new file mode 100644 index 0000000..d50f80e Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventorySlotView$SlotRef.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventorySlotView.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventorySlotView.class new file mode 100644 index 0000000..fe39452 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerInventorySlotView.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerMenuPage$Tab.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerMenuPage$Tab.class new file mode 100644 index 0000000..0220787 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerMenuPage$Tab.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerMenuPage$UiEvent.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerMenuPage$UiEvent.class new file mode 100644 index 0000000..13a090c Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerMenuPage$UiEvent.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerMenuPage.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerMenuPage.class new file mode 100644 index 0000000..a3be905 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerMenuPage.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerVitalsReader$Vitals.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerVitalsReader$Vitals.class new file mode 100644 index 0000000..e8f5115 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerVitalsReader$Vitals.class differ diff --git a/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerVitalsReader.class b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerVitalsReader.class new file mode 100644 index 0000000..ccae868 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/classes/java/main/com/disklexar/mmorpg/ui/PlayerVitalsReader.class differ diff --git a/Hytale/plugins/mmorpg/build/libs/hytale-mmorpg-sources.jar b/Hytale/plugins/mmorpg/build/libs/hytale-mmorpg-sources.jar new file mode 100644 index 0000000..bb897a7 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/libs/hytale-mmorpg-sources.jar differ diff --git a/Hytale/plugins/mmorpg/build/libs/hytale-mmorpg.jar b/Hytale/plugins/mmorpg/build/libs/hytale-mmorpg.jar new file mode 100644 index 0000000..b1ec5c9 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/libs/hytale-mmorpg.jar differ diff --git a/Hytale/plugins/mmorpg/build/reports/problems/problems-report.html b/Hytale/plugins/mmorpg/build/reports/problems/problems-report.html new file mode 100644 index 0000000..f0e9719 --- /dev/null +++ b/Hytale/plugins/mmorpg/build/reports/problems/problems-report.html @@ -0,0 +1,659 @@ + + + + + + + + + + + + + Gradle Configuration Cache + + + +
+ +
+ Loading... +
+ + + + + + diff --git a/src/main/resources/Common/UI/Custom/MmorpgAbilityBar.ui b/Hytale/plugins/mmorpg/build/resources/main/Common/UI/Custom/Huds/MmorpgAbilityBar.ui similarity index 100% rename from src/main/resources/Common/UI/Custom/MmorpgAbilityBar.ui rename to Hytale/plugins/mmorpg/build/resources/main/Common/UI/Custom/Huds/MmorpgAbilityBar.ui diff --git a/src/main/resources/Common/UI/Custom/Pages/MmorpgCharacterTab.ui b/Hytale/plugins/mmorpg/build/resources/main/Common/UI/Custom/Pages/MmorpgCharacterTab.ui similarity index 100% rename from src/main/resources/Common/UI/Custom/Pages/MmorpgCharacterTab.ui rename to Hytale/plugins/mmorpg/build/resources/main/Common/UI/Custom/Pages/MmorpgCharacterTab.ui diff --git a/src/main/resources/Common/UI/Custom/Pages/MmorpgInventoryPage.ui b/Hytale/plugins/mmorpg/build/resources/main/Common/UI/Custom/Pages/MmorpgInventoryPage.ui similarity index 81% rename from src/main/resources/Common/UI/Custom/Pages/MmorpgInventoryPage.ui rename to Hytale/plugins/mmorpg/build/resources/main/Common/UI/Custom/Pages/MmorpgInventoryPage.ui index 01dc255..29673ef 100644 --- a/src/main/resources/Common/UI/Custom/Pages/MmorpgInventoryPage.ui +++ b/Hytale/plugins/mmorpg/build/resources/main/Common/UI/Custom/Pages/MmorpgInventoryPage.ui @@ -5,15 +5,18 @@ @MmorpgMuted = #878e9c; @MmorpgBorder = #3a3f4a; +@SlotSize = 52; +@SlotGap = 4; +@SlotColWidth = @SlotSize + @SlotGap; +@SlotRowHeight = @SlotSize + @SlotGap; +@StorageGridWidth = (@SlotColWidth * 9) - @SlotGap; +@StorageGridHeight = (@SlotRowHeight * 4) - @SlotGap; +@HotbarWidth = (@SlotColWidth * 9) - @SlotGap; +@ColumnHeight = (@SlotRowHeight * 4) - @SlotGap; + @ShellWidth = 920; @ShellHeight = 660; -@GridStyle = ItemGridStyle( - SlotSpacing: 4, - SlotSize: 52, - SlotIconSize: 44 -); - Group { LayoutMode: Center; @@ -139,14 +142,9 @@ Group { Anchor: (Bottom: 6); } - ItemGrid #ArmorGrid { - Anchor: (Width: 56, Height: 232, Bottom: 10); - SlotsPerRow: 1; - InventorySectionId: -3; - AreItemsDraggable: true; - DisplayItemQuantity: true; - RenderItemQualityBackground: true; - Style: @GridStyle; + Group #ArmorSlots { + LayoutMode: Top; + Anchor: (Width: @SlotSize, Height: @ColumnHeight, Bottom: 10); } Label { @@ -161,14 +159,9 @@ Group { Anchor: (Bottom: 6); } - ItemGrid #UtilityGrid { - Anchor: (Width: 56, Height: 232); - SlotsPerRow: 1; - InventorySectionId: -5; - AreItemsDraggable: true; - DisplayItemQuantity: true; - RenderItemQualityBackground: true; - Style: @GridStyle; + Group #UtilitySlots { + LayoutMode: Top; + Anchor: (Width: @SlotSize, Height: @ColumnHeight); } } @@ -184,14 +177,9 @@ Group { Anchor: (Bottom: 6); } - ItemGrid #StorageGrid { - Anchor: (Width: 500, Height: 232, Bottom: 10); - SlotsPerRow: 9; - InventorySectionId: -2; - AreItemsDraggable: true; - DisplayItemQuantity: true; - RenderItemQualityBackground: true; - Style: @GridStyle; + Group #StorageSlots { + LayoutMode: Top; + Anchor: (Width: @StorageGridWidth, Height: @StorageGridHeight, Bottom: 10); } Label #HotbarSummary { @@ -200,14 +188,9 @@ Group { Anchor: (Bottom: 6); } - ItemGrid #HotbarGrid { - Anchor: (Width: 500, Height: 60); - SlotsPerRow: 9; - InventorySectionId: -1; - AreItemsDraggable: true; - DisplayItemQuantity: true; - RenderItemQualityBackground: true; - Style: @GridStyle; + Group #HotbarSlots { + LayoutMode: Top; + Anchor: (Width: @HotbarWidth, Height: @SlotSize); } } @@ -270,7 +253,7 @@ Group { Label #FooterHint { Style: (FontSize: 11, TextColor: @MmorpgMuted); - Text: "Échap pour fermer — glisser-déposer actif (inventaire vanilla synchronisé)"; + Text: "Échap pour fermer — clic source puis destination pour déplacer, survol pour les détails"; Anchor: (Top: 10); } } diff --git a/src/main/resources/Common/UI/Custom/Pages/MmorpgInventoryTab.ui b/Hytale/plugins/mmorpg/build/resources/main/Common/UI/Custom/Pages/MmorpgInventoryTab.ui similarity index 100% rename from src/main/resources/Common/UI/Custom/Pages/MmorpgInventoryTab.ui rename to Hytale/plugins/mmorpg/build/resources/main/Common/UI/Custom/Pages/MmorpgInventoryTab.ui diff --git a/src/main/resources/Common/UI/Custom/Pages/MmorpgPlayerInfo.ui b/Hytale/plugins/mmorpg/build/resources/main/Common/UI/Custom/Pages/MmorpgPlayerInfo.ui similarity index 100% rename from src/main/resources/Common/UI/Custom/Pages/MmorpgPlayerInfo.ui rename to Hytale/plugins/mmorpg/build/resources/main/Common/UI/Custom/Pages/MmorpgPlayerInfo.ui diff --git a/src/main/resources/Common/UI/Custom/Pages/MmorpgPlayerShell.ui b/Hytale/plugins/mmorpg/build/resources/main/Common/UI/Custom/Pages/MmorpgPlayerShell.ui similarity index 100% rename from src/main/resources/Common/UI/Custom/Pages/MmorpgPlayerShell.ui rename to Hytale/plugins/mmorpg/build/resources/main/Common/UI/Custom/Pages/MmorpgPlayerShell.ui diff --git a/src/main/resources/Common/UI/Custom/Pages/MmorpgSkillsTab.ui b/Hytale/plugins/mmorpg/build/resources/main/Common/UI/Custom/Pages/MmorpgSkillsTab.ui similarity index 100% rename from src/main/resources/Common/UI/Custom/Pages/MmorpgSkillsTab.ui rename to Hytale/plugins/mmorpg/build/resources/main/Common/UI/Custom/Pages/MmorpgSkillsTab.ui diff --git a/src/main/resources/Server/Item/Items/Weapon_Battleaxe_Mithril.json b/Hytale/plugins/mmorpg/build/resources/main/Server/Item/Items/Weapon_Battleaxe_Mithril.json similarity index 100% rename from src/main/resources/Server/Item/Items/Weapon_Battleaxe_Mithril.json rename to Hytale/plugins/mmorpg/build/resources/main/Server/Item/Items/Weapon_Battleaxe_Mithril.json diff --git a/src/main/resources/Server/Item/Items/Weapon_Crossbow_Ancient_Steel.json b/Hytale/plugins/mmorpg/build/resources/main/Server/Item/Items/Weapon_Crossbow_Ancient_Steel.json similarity index 100% rename from src/main/resources/Server/Item/Items/Weapon_Crossbow_Ancient_Steel.json rename to Hytale/plugins/mmorpg/build/resources/main/Server/Item/Items/Weapon_Crossbow_Ancient_Steel.json diff --git a/src/main/resources/Server/Item/Items/Weapon_Daggers_Mithril.json b/Hytale/plugins/mmorpg/build/resources/main/Server/Item/Items/Weapon_Daggers_Mithril.json similarity index 100% rename from src/main/resources/Server/Item/Items/Weapon_Daggers_Mithril.json rename to Hytale/plugins/mmorpg/build/resources/main/Server/Item/Items/Weapon_Daggers_Mithril.json diff --git a/src/main/resources/Server/Item/Items/Weapon_Longsword_Mithril.json b/Hytale/plugins/mmorpg/build/resources/main/Server/Item/Items/Weapon_Longsword_Mithril.json similarity index 100% rename from src/main/resources/Server/Item/Items/Weapon_Longsword_Mithril.json rename to Hytale/plugins/mmorpg/build/resources/main/Server/Item/Items/Weapon_Longsword_Mithril.json diff --git a/src/main/resources/Server/Item/Items/Weapon_Shortbow_Cobalt.json b/Hytale/plugins/mmorpg/build/resources/main/Server/Item/Items/Weapon_Shortbow_Cobalt.json similarity index 100% rename from src/main/resources/Server/Item/Items/Weapon_Shortbow_Cobalt.json rename to Hytale/plugins/mmorpg/build/resources/main/Server/Item/Items/Weapon_Shortbow_Cobalt.json diff --git a/src/main/resources/Server/Item/Items/Weapon_Staff_Mithril.json b/Hytale/plugins/mmorpg/build/resources/main/Server/Item/Items/Weapon_Staff_Mithril.json similarity index 100% rename from src/main/resources/Server/Item/Items/Weapon_Staff_Mithril.json rename to Hytale/plugins/mmorpg/build/resources/main/Server/Item/Items/Weapon_Staff_Mithril.json diff --git a/src/main/resources/config.json b/Hytale/plugins/mmorpg/build/resources/main/config.json similarity index 100% rename from src/main/resources/config.json rename to Hytale/plugins/mmorpg/build/resources/main/config.json diff --git a/src/main/resources/db/migrations/001_init.sql b/Hytale/plugins/mmorpg/build/resources/main/db/migrations/001_init.sql similarity index 100% rename from src/main/resources/db/migrations/001_init.sql rename to Hytale/plugins/mmorpg/build/resources/main/db/migrations/001_init.sql diff --git a/src/main/resources/db/migrations/002_rpg.sql b/Hytale/plugins/mmorpg/build/resources/main/db/migrations/002_rpg.sql similarity index 100% rename from src/main/resources/db/migrations/002_rpg.sql rename to Hytale/plugins/mmorpg/build/resources/main/db/migrations/002_rpg.sql diff --git a/src/main/resources/manifest.json b/Hytale/plugins/mmorpg/build/resources/main/manifest.json similarity index 95% rename from src/main/resources/manifest.json rename to Hytale/plugins/mmorpg/build/resources/main/manifest.json index d096676..275f1e8 100644 --- a/src/main/resources/manifest.json +++ b/Hytale/plugins/mmorpg/build/resources/main/manifest.json @@ -1,7 +1,7 @@ { "Group": "com.disklexar", "Name": "MMORPG", - "Version": "0.3.5", + "Version": "0.4.7", "Description": "Serveur MMORPG Hytale — progression, persistance et systèmes sociaux", "Authors": [ { diff --git a/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_d64546e794cf1792ce64f27ce1af0686/META-INF/services/java.sql.Driver b/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_d64546e794cf1792ce64f27ce1af0686/META-INF/services/java.sql.Driver new file mode 100644 index 0000000..1359f6f --- /dev/null +++ b/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_d64546e794cf1792ce64f27ce1af0686/META-INF/services/java.sql.Driver @@ -0,0 +1 @@ +org.sqlite.JDBC \ No newline at end of file diff --git a/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/java.security.Provider b/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/java.security.Provider new file mode 100644 index 0000000..689a9db --- /dev/null +++ b/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/java.security.Provider @@ -0,0 +1,2 @@ +org.bouncycastle.jce.provider.BouncyCastleProvider +org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider diff --git a/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/org/jline/terminal/provider/exec b/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/org/jline/terminal/provider/exec new file mode 100644 index 0000000..c9e6ead --- /dev/null +++ b/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/org/jline/terminal/provider/exec @@ -0,0 +1,16 @@ +# +# Copyright (C) 2022 the original author(s). +# +# 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 +# +# http://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. +# +class = org.jline.terminal.impl.exec.ExecTerminalProvider diff --git a/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/org/jline/terminal/provider/ffm b/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/org/jline/terminal/provider/ffm new file mode 100644 index 0000000..0932a41 --- /dev/null +++ b/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/org/jline/terminal/provider/ffm @@ -0,0 +1,16 @@ +# +# Copyright (C) 2022 the original author(s). +# +# 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 +# +# http://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. +# +class = org.jline.terminal.impl.ffm.FfmTerminalProvider diff --git a/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/org/jline/terminal/provider/jansi b/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/org/jline/terminal/provider/jansi new file mode 100644 index 0000000..a02d2df --- /dev/null +++ b/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/org/jline/terminal/provider/jansi @@ -0,0 +1,16 @@ +# +# Copyright (C) 2022 the original author(s). +# +# 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 +# +# http://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. +# +class = org.jline.terminal.impl.jansi.JansiTerminalProvider diff --git a/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/org/jline/terminal/provider/jna b/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/org/jline/terminal/provider/jna new file mode 100644 index 0000000..ec5372c --- /dev/null +++ b/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/org/jline/terminal/provider/jna @@ -0,0 +1,16 @@ +# +# Copyright (C) 2022 the original author(s). +# +# 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 +# +# http://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. +# +class = org.jline.terminal.impl.jna.JnaTerminalProvider diff --git a/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/org/jline/terminal/provider/jni b/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/org/jline/terminal/provider/jni new file mode 100644 index 0000000..10de0e8 --- /dev/null +++ b/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/org/jline/terminal/provider/jni @@ -0,0 +1,16 @@ +# +# Copyright (C) 2022 the original author(s). +# +# 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 +# +# http://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. +# +class = org.jline.terminal.impl.jni.JniTerminalProvider diff --git a/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/reactor.blockhound.integration.BlockHoundIntegration b/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/reactor.blockhound.integration.BlockHoundIntegration new file mode 100644 index 0000000..e33bea7 --- /dev/null +++ b/Hytale/plugins/mmorpg/build/tmp/.cache/expanded/zip_e4ee076448d568964de65de6661e0636/META-INF/services/reactor.blockhound.integration.BlockHoundIntegration @@ -0,0 +1,14 @@ +# Copyright 2019 The Netty Project +# +# The Netty Project licenses this file to you 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. +io.netty.util.internal.Hidden$NettyBlockHoundIntegration \ No newline at end of file diff --git a/Hytale/plugins/mmorpg/build/tmp/compileJava/previous-compilation-data.bin b/Hytale/plugins/mmorpg/build/tmp/compileJava/previous-compilation-data.bin new file mode 100644 index 0000000..6a72629 Binary files /dev/null and b/Hytale/plugins/mmorpg/build/tmp/compileJava/previous-compilation-data.bin differ diff --git a/Hytale/plugins/mmorpg/build/tmp/shadowJar/MANIFEST.MF b/Hytale/plugins/mmorpg/build/tmp/shadowJar/MANIFEST.MF new file mode 100644 index 0000000..adf70a3 --- /dev/null +++ b/Hytale/plugins/mmorpg/build/tmp/shadowJar/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Multi-Release: true + diff --git a/Hytale/plugins/mmorpg/build/tmp/sourcesJar/MANIFEST.MF b/Hytale/plugins/mmorpg/build/tmp/sourcesJar/MANIFEST.MF new file mode 100644 index 0000000..58630c0 --- /dev/null +++ b/Hytale/plugins/mmorpg/build/tmp/sourcesJar/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/gradle.properties b/Hytale/plugins/mmorpg/gradle.properties similarity index 100% rename from gradle.properties rename to Hytale/plugins/mmorpg/gradle.properties diff --git a/Hytale/plugins/mmorpg/gradle/wrapper/gradle-wrapper.jar b/Hytale/plugins/mmorpg/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..f8e1ee3 Binary files /dev/null and b/Hytale/plugins/mmorpg/gradle/wrapper/gradle-wrapper.jar differ diff --git a/Hytale/plugins/mmorpg/gradle/wrapper/gradle-wrapper.properties b/Hytale/plugins/mmorpg/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..bad7c24 --- /dev/null +++ b/Hytale/plugins/mmorpg/gradle/wrapper/gradle-wrapper.properties @@ -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 diff --git a/Hytale/plugins/mmorpg/gradlew b/Hytale/plugins/mmorpg/gradlew new file mode 100755 index 0000000..61b77d7 --- /dev/null +++ b/Hytale/plugins/mmorpg/gradlew @@ -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" "$@" diff --git a/Hytale/plugins/mmorpg/gradlew.bat b/Hytale/plugins/mmorpg/gradlew.bat new file mode 100644 index 0000000..bd8a8c0 --- /dev/null +++ b/Hytale/plugins/mmorpg/gradlew.bat @@ -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 diff --git a/src/main/java/com/disklexar/mmorpg/MmorpgPlugin.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/MmorpgPlugin.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/MmorpgPlugin.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/MmorpgPlugin.java diff --git a/src/main/java/com/disklexar/mmorpg/api/package-info.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/api/package-info.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/api/package-info.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/api/package-info.java diff --git a/src/main/java/com/disklexar/mmorpg/bootstrap/Bootstrap.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/bootstrap/Bootstrap.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/bootstrap/Bootstrap.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/bootstrap/Bootstrap.java diff --git a/src/main/java/com/disklexar/mmorpg/bootstrap/ServiceRegistry.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/bootstrap/ServiceRegistry.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/bootstrap/ServiceRegistry.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/bootstrap/ServiceRegistry.java diff --git a/src/main/java/com/disklexar/mmorpg/combat/AbilityService.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/AbilityService.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/combat/AbilityService.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/AbilityService.java diff --git a/src/main/java/com/disklexar/mmorpg/combat/ClassAbilityController.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/ClassAbilityController.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/combat/ClassAbilityController.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/ClassAbilityController.java diff --git a/src/main/java/com/disklexar/mmorpg/combat/CombatBuffService.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/CombatBuffService.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/combat/CombatBuffService.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/CombatBuffService.java diff --git a/src/main/java/com/disklexar/mmorpg/combat/CombatFx.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/CombatFx.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/combat/CombatFx.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/CombatFx.java diff --git a/src/main/java/com/disklexar/mmorpg/combat/CombatStateService.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/CombatStateService.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/combat/CombatStateService.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/CombatStateService.java diff --git a/src/main/java/com/disklexar/mmorpg/combat/MmorpgScheduler.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/MmorpgScheduler.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/combat/MmorpgScheduler.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/MmorpgScheduler.java diff --git a/src/main/java/com/disklexar/mmorpg/combat/PassiveEffectService.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/PassiveEffectService.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/combat/PassiveEffectService.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/PassiveEffectService.java diff --git a/src/main/java/com/disklexar/mmorpg/combat/PoisonService.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/PoisonService.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/combat/PoisonService.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/PoisonService.java diff --git a/src/main/java/com/disklexar/mmorpg/combat/StunService.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/StunService.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/combat/StunService.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/StunService.java diff --git a/src/main/java/com/disklexar/mmorpg/combat/system/MinerBlockBreakSystem.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/system/MinerBlockBreakSystem.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/combat/system/MinerBlockBreakSystem.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/system/MinerBlockBreakSystem.java diff --git a/src/main/java/com/disklexar/mmorpg/combat/system/MmorpgDamageSystem.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/system/MmorpgDamageSystem.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/combat/system/MmorpgDamageSystem.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/system/MmorpgDamageSystem.java diff --git a/src/main/java/com/disklexar/mmorpg/combat/system/MmorpgDeathSystem.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/system/MmorpgDeathSystem.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/combat/system/MmorpgDeathSystem.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/combat/system/MmorpgDeathSystem.java diff --git a/src/main/java/com/disklexar/mmorpg/command/AbilityCommand.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/AbilityCommand.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/command/AbilityCommand.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/AbilityCommand.java diff --git a/src/main/java/com/disklexar/mmorpg/command/ClassCommand.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/ClassCommand.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/command/ClassCommand.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/ClassCommand.java diff --git a/src/main/java/com/disklexar/mmorpg/command/CommandSupport.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/CommandSupport.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/command/CommandSupport.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/CommandSupport.java diff --git a/src/main/java/com/disklexar/mmorpg/command/GroupCommand.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/GroupCommand.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/command/GroupCommand.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/GroupCommand.java diff --git a/src/main/java/com/disklexar/mmorpg/command/HudCommand.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/HudCommand.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/command/HudCommand.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/HudCommand.java diff --git a/src/main/java/com/disklexar/mmorpg/command/InfoCommand.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/InfoCommand.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/command/InfoCommand.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/InfoCommand.java diff --git a/src/main/java/com/disklexar/mmorpg/command/InventoryCommand.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/InventoryCommand.java similarity index 95% rename from src/main/java/com/disklexar/mmorpg/command/InventoryCommand.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/InventoryCommand.java index b5adb80..74402b9 100644 --- a/src/main/java/com/disklexar/mmorpg/command/InventoryCommand.java +++ b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/InventoryCommand.java @@ -6,7 +6,6 @@ import com.disklexar.mmorpg.player.model.PlayerProfile; import com.disklexar.mmorpg.combat.AbilityService; import com.disklexar.mmorpg.progression.ProgressionService; import com.disklexar.mmorpg.ui.PlayerInventoryPage; -import com.disklexar.mmorpg.ui.PlayerMenuPage; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.server.core.Message; @@ -21,7 +20,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import javax.annotation.Nonnull; /** - * {@code /mmorpg inventory} — opens the MMORPG inventory shell (custom UI). + * {@code /mmorpg inventory} — opens {@code MmorpgInventoryPage.ui} with live {@code ItemSlot} icons. */ public final class InventoryCommand extends AbstractPlayerCommand { diff --git a/src/main/java/com/disklexar/mmorpg/command/JobCommand.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/JobCommand.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/command/JobCommand.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/JobCommand.java diff --git a/src/main/java/com/disklexar/mmorpg/command/MenuCommand.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/MenuCommand.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/command/MenuCommand.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/MenuCommand.java diff --git a/src/main/java/com/disklexar/mmorpg/command/MenuCustomCommand.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/MenuCustomCommand.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/command/MenuCustomCommand.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/MenuCustomCommand.java diff --git a/src/main/java/com/disklexar/mmorpg/command/MmorpgCommand.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/MmorpgCommand.java similarity index 94% rename from src/main/java/com/disklexar/mmorpg/command/MmorpgCommand.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/MmorpgCommand.java index 7565519..87c14ac 100644 --- a/src/main/java/com/disklexar/mmorpg/command/MmorpgCommand.java +++ b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/MmorpgCommand.java @@ -23,5 +23,6 @@ public final class MmorpgCommand extends AbstractCommandCollection { addSubCommand(new JobCommand(plugin)); addSubCommand(new GroupCommand(plugin)); addSubCommand(new AbilityCommand(plugin)); + addSubCommand(new PasswordCommand(plugin)); } } diff --git a/src/main/java/com/disklexar/mmorpg/command/MmorpgHelpCommand.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/MmorpgHelpCommand.java similarity index 95% rename from src/main/java/com/disklexar/mmorpg/command/MmorpgHelpCommand.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/MmorpgHelpCommand.java index e0df676..c674ae1 100644 --- a/src/main/java/com/disklexar/mmorpg/command/MmorpgHelpCommand.java +++ b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/MmorpgHelpCommand.java @@ -33,6 +33,7 @@ public final class MmorpgHelpCommand extends AbstractAsyncCommand { /mmorpg job [metier] /mmorpg group [joueur] /mmorpg ability <1|2|3> — utiliser une capacité de classe + /mmorpg password — mot de passe pour le site web Orion.ovh (ou utilisez directement les touches « Use ability 1/2/3 » en jeu) Classes : Chevalier, Archer, Mage, Assassin (voir /mmorpg class info) """)); diff --git a/src/main/java/com/disklexar/mmorpg/command/MmorpgProfileCommand.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/MmorpgProfileCommand.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/command/MmorpgProfileCommand.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/MmorpgProfileCommand.java diff --git a/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/PasswordCommand.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/PasswordCommand.java new file mode 100644 index 0000000..804a93b --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/PasswordCommand.java @@ -0,0 +1,71 @@ +package com.disklexar.mmorpg.command; + +import com.disklexar.mmorpg.MmorpgPlugin; +import com.disklexar.mmorpg.persistence.PasswordHasher; +import com.disklexar.mmorpg.persistence.repository.PlayerProfileRepository; +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.server.core.Message; +import com.hypixel.hytale.server.core.command.system.CommandContext; +import com.hypixel.hytale.server.core.command.system.arguments.system.RequiredArg; +import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes; +import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand; +import com.hypixel.hytale.server.core.universe.PlayerRef; +import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; + +import javax.annotation.Nonnull; +import java.sql.SQLException; +import java.util.UUID; +import java.util.logging.Level; + +/** + * {@code /mmorpg password } — sets or updates the web login password. + */ +public final class PasswordCommand extends AbstractPlayerCommand { + + private final MmorpgPlugin plugin; + private final RequiredArg passwordArg; + + public PasswordCommand(@Nonnull MmorpgPlugin plugin) { + super("password", "Définir ou modifier votre mot de passe web"); + this.plugin = plugin; + this.passwordArg = withRequiredArg( + "mot_de_passe", + "Mot de passe pour le site Orion.ovh", + ArgTypes.STRING); + } + + @Override + protected void execute( + @Nonnull CommandContext context, + @Nonnull Store store, + @Nonnull Ref ref, + @Nonnull PlayerRef playerRef, + @Nonnull World world) { + UUID uuid = CommandSupport.uuid(store, ref); + PlayerProfileRepository profiles = CommandSupport.service(plugin, PlayerProfileRepository.class); + if (uuid == null || profiles == null) { + context.sendMessage(Message.raw("Profil indisponible.")); + return; + } + + String password = context.get(passwordArg); + if (!PasswordHasher.isValidLength(password)) { + context.sendMessage(Message.raw(String.format( + "Mot de passe invalide (%d–%d caractères requis).", + PasswordHasher.MIN_LENGTH, + PasswordHasher.MAX_LENGTH))); + return; + } + + try { + profiles.setPasswordHash(uuid, PasswordHasher.hash(password)); + context.sendMessage(Message.raw( + "Mot de passe web enregistré. Connectez-vous sur Orion.ovh avec votre pseudo et ce mot de passe.")); + } catch (SQLException e) { + plugin.getLogger().at(Level.WARNING).log("Failed to save web password: %s", e.getMessage()); + context.sendMessage(Message.raw("Erreur lors de l'enregistrement du mot de passe.")); + } + } +} diff --git a/src/main/java/com/disklexar/mmorpg/command/PowerCommand.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/PowerCommand.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/command/PowerCommand.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/command/PowerCommand.java diff --git a/src/main/java/com/disklexar/mmorpg/core/config/MmorpgConfig.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/core/config/MmorpgConfig.java similarity index 85% rename from src/main/java/com/disklexar/mmorpg/core/config/MmorpgConfig.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/core/config/MmorpgConfig.java index 9f2cc5e..422ff8d 100644 --- a/src/main/java/com/disklexar/mmorpg/core/config/MmorpgConfig.java +++ b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/core/config/MmorpgConfig.java @@ -86,10 +86,24 @@ public final class MmorpgConfig { public static final class DatabaseConfig { @SerializedName("FileName") private String fileName = "mmorpg.db"; + /** Optional path override (absolute, or relative to the plugin data directory). */ + @SerializedName("Path") + private String path; + /** When true, store the database at the monorepo root ({@code Hytale/} + {@code Webapp/}). */ + @SerializedName("UseMonorepoRoot") + private boolean useMonorepoRoot = true; public String getFileName() { return fileName; } + + public String getPath() { + return path; + } + + public boolean isUseMonorepoRoot() { + return useMonorepoRoot; + } } public static final class FeaturesConfig { diff --git a/src/main/java/com/disklexar/mmorpg/core/service/Service.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/core/service/Service.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/core/service/Service.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/core/service/Service.java diff --git a/src/main/java/com/disklexar/mmorpg/economy/EconomyService.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/economy/EconomyService.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/economy/EconomyService.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/economy/EconomyService.java diff --git a/src/main/java/com/disklexar/mmorpg/economy/package-info.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/economy/package-info.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/economy/package-info.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/economy/package-info.java diff --git a/src/main/java/com/disklexar/mmorpg/events/AbilityPacketFilter.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/events/AbilityPacketFilter.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/events/AbilityPacketFilter.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/events/AbilityPacketFilter.java diff --git a/src/main/java/com/disklexar/mmorpg/events/PlayerConnectionHandler.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/events/PlayerConnectionHandler.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/events/PlayerConnectionHandler.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/events/PlayerConnectionHandler.java diff --git a/src/main/java/com/disklexar/mmorpg/interaction/MmorpgCastAbilityInteraction.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/interaction/MmorpgCastAbilityInteraction.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/interaction/MmorpgCastAbilityInteraction.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/interaction/MmorpgCastAbilityInteraction.java diff --git a/src/main/java/com/disklexar/mmorpg/persistence/DatabaseManager.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/persistence/DatabaseManager.java similarity index 58% rename from src/main/java/com/disklexar/mmorpg/persistence/DatabaseManager.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/persistence/DatabaseManager.java index a34ee06..6b9c088 100644 --- a/src/main/java/com/disklexar/mmorpg/persistence/DatabaseManager.java +++ b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/persistence/DatabaseManager.java @@ -7,6 +7,9 @@ import com.disklexar.mmorpg.persistence.schema.SchemaInitializer; import com.hypixel.hytale.logger.HytaleLogger; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.sql.Connection; import java.sql.DriverManager; @@ -34,7 +37,11 @@ public final class DatabaseManager implements Service { @Override public void start() { try { - Path dbPath = plugin.getDataDirectory().resolve(config.getDatabase().getFileName()); + Path dbPath = resolveDatabasePath(); + Path parent = dbPath.getParent(); + if (parent != null) { + Files.createDirectories(parent); + } String jdbcUrl = "jdbc:sqlite:" + dbPath.toAbsolutePath(); connection = DriverManager.getConnection(jdbcUrl); @@ -43,7 +50,7 @@ public final class DatabaseManager implements Service { SchemaInitializer.apply(connection); logger.at(Level.INFO).log("SQLite database ready at %s", dbPath); - } catch (SQLException e) { + } catch (SQLException | IOException e) { throw new IllegalStateException("Failed to initialize SQLite database", e); } } @@ -62,6 +69,38 @@ public final class DatabaseManager implements Service { } } + @Nonnull + private Path resolveDatabasePath() { + MmorpgConfig.DatabaseConfig database = config.getDatabase(); + String configuredPath = database.getPath(); + if (configuredPath != null && !configuredPath.isBlank()) { + Path path = Path.of(configuredPath); + return path.isAbsolute() + ? path + : plugin.getDataDirectory().resolve(path); + } + if (database.isUseMonorepoRoot()) { + Path monorepoRoot = findMonorepoRoot(plugin.getDataDirectory()); + if (monorepoRoot != null) { + return monorepoRoot.resolve(database.getFileName()); + } + } + return plugin.getDataDirectory().resolve(database.getFileName()); + } + + @Nullable + private static Path findMonorepoRoot(@Nonnull Path start) { + Path dir = start.toAbsolutePath().normalize(); + while (dir != null) { + if (Files.isDirectory(dir.resolve("Hytale")) + && Files.isDirectory(dir.resolve("Webapp"))) { + return dir; + } + dir = dir.getParent(); + } + return null; + } + @Nonnull public Connection getConnection() { if (connection == null) { diff --git a/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/persistence/PasswordHasher.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/persistence/PasswordHasher.java new file mode 100644 index 0000000..c3bd522 --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/persistence/PasswordHasher.java @@ -0,0 +1,28 @@ +package com.disklexar.mmorpg.persistence; + +import at.favre.lib.crypto.bcrypt.BCrypt; + +import javax.annotation.Nonnull; + +/** + * BCrypt hashing for web login passwords (compatible with the Node.js webapp). + */ +public final class PasswordHasher { + + private static final int COST = 10; + public static final int MIN_LENGTH = 6; + public static final int MAX_LENGTH = 72; + + private PasswordHasher() { + } + + @Nonnull + public static String hash(@Nonnull String plainPassword) { + return BCrypt.withDefaults().hashToString(COST, plainPassword.toCharArray()); + } + + public static boolean isValidLength(@Nonnull String plainPassword) { + int length = plainPassword.length(); + return length >= MIN_LENGTH && length <= MAX_LENGTH; + } +} diff --git a/src/main/java/com/disklexar/mmorpg/persistence/repository/GroupRepository.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/persistence/repository/GroupRepository.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/persistence/repository/GroupRepository.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/persistence/repository/GroupRepository.java diff --git a/src/main/java/com/disklexar/mmorpg/persistence/repository/PlayerProfileRepository.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/persistence/repository/PlayerProfileRepository.java similarity index 77% rename from src/main/java/com/disklexar/mmorpg/persistence/repository/PlayerProfileRepository.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/persistence/repository/PlayerProfileRepository.java index 95736d8..9bc9c85 100644 --- a/src/main/java/com/disklexar/mmorpg/persistence/repository/PlayerProfileRepository.java +++ b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/persistence/repository/PlayerProfileRepository.java @@ -6,6 +6,7 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.lang.reflect.Type; import java.sql.Connection; import java.sql.PreparedStatement; @@ -109,6 +110,50 @@ public final class PlayerProfileRepository { } } + public void setPasswordHash(@Nonnull UUID uuid, @Nonnull String passwordHash) throws SQLException { + String sql = """ + UPDATE player_profiles + SET password_hash = ?, updated_at = ? + WHERE uuid = ? + """; + try (PreparedStatement statement = connection().prepareStatement(sql)) { + statement.setString(1, passwordHash); + statement.setLong(2, System.currentTimeMillis()); + statement.setString(3, uuid.toString()); + if (statement.executeUpdate() == 0) { + throw new SQLException("Player profile not found: " + uuid); + } + } + } + + @Nonnull + public Optional findAuthByDisplayName(@Nonnull String displayName) throws SQLException { + String sql = """ + SELECT uuid, display_name, password_hash + FROM player_profiles + WHERE display_name = ? COLLATE NOCASE + LIMIT 1 + """; + try (PreparedStatement statement = connection().prepareStatement(sql)) { + statement.setString(1, displayName.trim()); + try (ResultSet resultSet = statement.executeQuery()) { + if (!resultSet.next()) { + return Optional.empty(); + } + return Optional.of(new PlayerAuthRecord( + UUID.fromString(resultSet.getString("uuid")), + resultSet.getString("display_name"), + resultSet.getString("password_hash"))); + } + } + } + + public record PlayerAuthRecord( + @Nonnull UUID uuid, + @Nonnull String displayName, + @Nullable String passwordHash) { + } + @Nonnull private PlayerProfile mapRow(@Nonnull ResultSet resultSet) throws SQLException { PlayerProfile profile = new PlayerProfile( diff --git a/src/main/java/com/disklexar/mmorpg/persistence/schema/SchemaInitializer.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/persistence/schema/SchemaInitializer.java similarity index 98% rename from src/main/java/com/disklexar/mmorpg/persistence/schema/SchemaInitializer.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/persistence/schema/SchemaInitializer.java index c52beb5..56ef2ab 100644 --- a/src/main/java/com/disklexar/mmorpg/persistence/schema/SchemaInitializer.java +++ b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/persistence/schema/SchemaInitializer.java @@ -25,7 +25,8 @@ public final class SchemaInitializer { private static final List MIGRATIONS = List.of( "001_init.sql", - "002_rpg.sql"); + "002_rpg.sql", + "003_web_password.sql"); private SchemaInitializer() { } diff --git a/src/main/java/com/disklexar/mmorpg/player/OnlinePlayer.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/player/OnlinePlayer.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/player/OnlinePlayer.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/player/OnlinePlayer.java diff --git a/src/main/java/com/disklexar/mmorpg/player/OnlinePlayerRegistry.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/player/OnlinePlayerRegistry.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/player/OnlinePlayerRegistry.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/player/OnlinePlayerRegistry.java diff --git a/src/main/java/com/disklexar/mmorpg/player/PlayerInfoView.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/player/PlayerInfoView.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/player/PlayerInfoView.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/player/PlayerInfoView.java diff --git a/src/main/java/com/disklexar/mmorpg/player/PlayerSessionService.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/player/PlayerSessionService.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/player/PlayerSessionService.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/player/PlayerSessionService.java diff --git a/src/main/java/com/disklexar/mmorpg/player/model/PlayerProfile.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/player/model/PlayerProfile.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/player/model/PlayerProfile.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/player/model/PlayerProfile.java diff --git a/src/main/java/com/disklexar/mmorpg/progression/ProgressionService.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/progression/ProgressionService.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/progression/ProgressionService.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/progression/ProgressionService.java diff --git a/src/main/java/com/disklexar/mmorpg/quest/package-info.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/quest/package-info.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/quest/package-info.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/quest/package-info.java diff --git a/src/main/java/com/disklexar/mmorpg/rpg/clazz/AbilityDefinition.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/clazz/AbilityDefinition.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/rpg/clazz/AbilityDefinition.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/clazz/AbilityDefinition.java diff --git a/src/main/java/com/disklexar/mmorpg/rpg/clazz/ClassCatalog.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/clazz/ClassCatalog.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/rpg/clazz/ClassCatalog.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/clazz/ClassCatalog.java diff --git a/src/main/java/com/disklexar/mmorpg/rpg/clazz/ClassService.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/clazz/ClassService.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/rpg/clazz/ClassService.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/clazz/ClassService.java diff --git a/src/main/java/com/disklexar/mmorpg/rpg/clazz/PlayerClass.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/clazz/PlayerClass.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/rpg/clazz/PlayerClass.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/clazz/PlayerClass.java diff --git a/src/main/java/com/disklexar/mmorpg/rpg/group/Group.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/group/Group.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/rpg/group/Group.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/group/Group.java diff --git a/src/main/java/com/disklexar/mmorpg/rpg/group/GroupService.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/group/GroupService.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/rpg/group/GroupService.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/group/GroupService.java diff --git a/src/main/java/com/disklexar/mmorpg/rpg/job/JobCatalog.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/job/JobCatalog.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/rpg/job/JobCatalog.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/job/JobCatalog.java diff --git a/src/main/java/com/disklexar/mmorpg/rpg/job/JobDefinition.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/job/JobDefinition.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/rpg/job/JobDefinition.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/job/JobDefinition.java diff --git a/src/main/java/com/disklexar/mmorpg/rpg/job/JobService.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/job/JobService.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/rpg/job/JobService.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/job/JobService.java diff --git a/src/main/java/com/disklexar/mmorpg/rpg/power/PowerCatalog.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/power/PowerCatalog.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/rpg/power/PowerCatalog.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/power/PowerCatalog.java diff --git a/src/main/java/com/disklexar/mmorpg/rpg/power/PowerDefinition.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/power/PowerDefinition.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/rpg/power/PowerDefinition.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/power/PowerDefinition.java diff --git a/src/main/java/com/disklexar/mmorpg/rpg/power/PowerService.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/power/PowerService.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/rpg/power/PowerService.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/power/PowerService.java diff --git a/src/main/java/com/disklexar/mmorpg/rpg/race/RaceCatalog.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/race/RaceCatalog.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/rpg/race/RaceCatalog.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/race/RaceCatalog.java diff --git a/src/main/java/com/disklexar/mmorpg/rpg/race/RaceDefinition.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/race/RaceDefinition.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/rpg/race/RaceDefinition.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/race/RaceDefinition.java diff --git a/src/main/java/com/disklexar/mmorpg/rpg/race/RaceService.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/race/RaceService.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/rpg/race/RaceService.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/rpg/race/RaceService.java diff --git a/src/main/java/com/disklexar/mmorpg/social/package-info.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/social/package-info.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/social/package-info.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/social/package-info.java diff --git a/src/main/java/com/disklexar/mmorpg/ui/AbilityBarHud.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/AbilityBarHud.java similarity index 97% rename from src/main/java/com/disklexar/mmorpg/ui/AbilityBarHud.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/AbilityBarHud.java index 7955b10..db4202d 100644 --- a/src/main/java/com/disklexar/mmorpg/ui/AbilityBarHud.java +++ b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/AbilityBarHud.java @@ -19,7 +19,7 @@ import java.util.UUID; public final class AbilityBarHud extends CustomUIHud { public static final String KEY = "mmorpg_ability_bar"; - private static final String DOCUMENT = "MmorpgAbilityBar.ui"; + private static final String DOCUMENT = "Huds/MmorpgAbilityBar.ui"; public AbilityBarHud(@Nonnull PlayerRef playerRef) { super(playerRef, KEY); } diff --git a/src/main/java/com/disklexar/mmorpg/ui/AbilityBarService.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/AbilityBarService.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/ui/AbilityBarService.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/AbilityBarService.java diff --git a/src/main/java/com/disklexar/mmorpg/ui/AbilitySlotKeys.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/AbilitySlotKeys.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/ui/AbilitySlotKeys.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/AbilitySlotKeys.java diff --git a/src/main/java/com/disklexar/mmorpg/ui/PlayerInfoPage.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/PlayerInfoPage.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/ui/PlayerInfoPage.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/PlayerInfoPage.java diff --git a/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/PlayerInventoryDrag.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/PlayerInventoryDrag.java new file mode 100644 index 0000000..1d322dc --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/PlayerInventoryDrag.java @@ -0,0 +1,48 @@ +package com.disklexar.mmorpg.ui; + +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.server.core.inventory.InventoryUtils; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; + +import javax.annotation.Nonnull; + +final class PlayerInventoryDrag { + + private PlayerInventoryDrag() { + } + + static boolean moveBetween( + @Nonnull Ref ref, + @Nonnull Store store, + int sourceSectionId, + int sourceSlotIndex, + int targetSectionId, + int targetSlotIndex) { + if (sourceSectionId == targetSectionId && sourceSlotIndex == targetSlotIndex) { + return false; + } + int quantity = sourceQuantity(store, ref, sourceSectionId, sourceSlotIndex); + if (quantity <= 0) { + return false; + } + InventoryUtils.moveItem( + ref, + sourceSectionId, + sourceSlotIndex, + quantity, + targetSectionId, + targetSlotIndex, + store); + return true; + } + + private static int sourceQuantity( + @Nonnull Store store, + @Nonnull Ref ref, + int sectionId, + int slotIndex) { + PlayerInventoryReader.ItemView item = PlayerInventoryReader.itemAt(store, ref, sectionId, slotIndex); + return item == null ? 0 : item.quantity(); + } +} diff --git a/src/main/java/com/disklexar/mmorpg/ui/PlayerInventoryPage.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/PlayerInventoryPage.java similarity index 73% rename from src/main/java/com/disklexar/mmorpg/ui/PlayerInventoryPage.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/PlayerInventoryPage.java index d4fa040..0f9a064 100644 --- a/src/main/java/com/disklexar/mmorpg/ui/PlayerInventoryPage.java +++ b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/PlayerInventoryPage.java @@ -15,7 +15,6 @@ import com.hypixel.hytale.protocol.packets.interface_.CustomPageLifetime; import com.hypixel.hytale.protocol.packets.interface_.CustomUIEventBindingType; import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.entity.entities.player.pages.InteractiveCustomUIPage; -import com.hypixel.hytale.server.core.inventory.InventoryComponent; import com.hypixel.hytale.server.core.ui.builder.EventData; import com.hypixel.hytale.server.core.ui.builder.UICommandBuilder; import com.hypixel.hytale.server.core.ui.builder.UIEventBuilder; @@ -27,7 +26,7 @@ import javax.annotation.Nullable; /** * Standalone inventory page ({@code MmorpgInventoryPage.ui} root document). - * Does not reference {@code MmorpgPlayerShell.ui}. + * Items are rendered via {@code ItemSlot}; move with click-source then click-destination. */ public final class PlayerInventoryPage extends InteractiveCustomUIPage { @@ -38,6 +37,9 @@ public final class PlayerInventoryPage extends InteractiveCustomUIPage store) { ui.append(DOCUMENT); applyHeader(ui); + PlayerInventorySlotView.mount(ui, events); + PlayerInventorySlotView.applyContents(ui, store, ref); + PlayerInventorySlotView.applyPickHighlight(ui, pendingPick); applyInventorySummary(ui, PlayerInventoryReader.snapshot(store, ref)); applyEmptyItemDetails(ui); applyTabHighlight(ui); bindTabButtons(events); - bindInventoryGridEvents(events); } @Override @@ -84,21 +88,72 @@ public final class PlayerInventoryPage extends InteractiveCustomUIPage ref, + @Nonnull Store store, + @Nonnull SlotSelection target) { + if (pendingPick == null) { + PlayerInventoryReader.ItemView item = PlayerInventoryReader.itemAt( + store, ref, target.sectionId(), target.slotIndex()); + if (item != null) { + pendingPick = new PlayerInventorySlotView.SlotRef(target.sectionId(), target.slotIndex()); + } + return; + } + + if (pendingPick.sectionId() == target.sectionId() && pendingPick.slotIndex() == target.slotIndex()) { + pendingPick = null; + return; + } + + PlayerInventoryDrag.moveBetween( + ref, + store, + pendingPick.sectionId(), + pendingPick.slotIndex(), + target.sectionId(), + target.slotIndex()); + pendingPick = null; + } + + private void applyDetailsForSlot( + @Nonnull UICommandBuilder ui, + @Nonnull Store store, + @Nonnull Ref ref, + @Nonnull SlotSelection selection) { PlayerInventoryReader.ItemView item = PlayerInventoryReader.itemAt( store, ref, selection.sectionId(), selection.slotIndex()); if (item != null) { applyItemDetails(ui, item); - } else { - applyEmptyItemDetails(ui); + return; } - applyInventorySummary(ui, PlayerInventoryReader.snapshot(store, ref)); - sendUpdate(ui, false); + applyEmptySlotDetails(ui); } private void applyHeader(@Nonnull UICommandBuilder ui) { @@ -138,15 +193,28 @@ public final class PlayerInventoryPage extends InteractiveCustomUIPage= container.getCapacity()) { return null; } @@ -71,7 +79,7 @@ public final class PlayerInventoryReader { if (ItemStack.isEmpty(stack)) { return null; } - return toView(stack, sectionId, slotIndex); + return toView(stack, sectionLabelId, slotIndex); } @Nullable diff --git a/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/PlayerInventorySlotView.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/PlayerInventorySlotView.java new file mode 100644 index 0000000..3094eae --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/PlayerInventorySlotView.java @@ -0,0 +1,260 @@ +package com.disklexar.mmorpg.ui; + +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.protocol.packets.interface_.CustomUIEventBindingType; +import com.hypixel.hytale.server.core.inventory.InventoryComponent; +import com.hypixel.hytale.server.core.inventory.ItemStack; +import com.hypixel.hytale.server.core.inventory.container.ItemContainer; +import com.hypixel.hytale.server.core.ui.builder.EventData; +import com.hypixel.hytale.server.core.ui.builder.UICommandBuilder; +import com.hypixel.hytale.server.core.ui.builder.UIEventBuilder; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * Renders player inventory sections with {@code ItemSlot} elements ({@code ItemId} + {@code Quantity}). + * Clicks and hover drive the details panel; click-source then click-destination moves items. + */ +public final class PlayerInventorySlotView { + + private static final int STORAGE_ROWS = 4; + private static final int STORAGE_COLS = 9; + private static final int ARMOR_SLOTS = 4; + private static final int UTILITY_SLOTS = 4; + private static final int HOTBAR_SLOTS = 9; + + private static final int SLOT_SIZE = 52; + private static final int SLOT_GAP = 4; + private static final int ROW_HEIGHT = SLOT_SIZE + SLOT_GAP; + private static final int COL_WIDTH = SLOT_SIZE + SLOT_GAP; + + private static final String CLEAR_HIGHLIGHT = "#00000000"; + private static final String PICK_CELL_BG = "#f5c842cc"; + + private PlayerInventorySlotView() { + } + + public static void mount( + @Nonnull UICommandBuilder ui, + @Nonnull UIEventBuilder events) { + mountColumn(ui, events, "#ArmorSlots", "Armor", InventoryComponent.ARMOR_SECTION_ID, ARMOR_SLOTS); + mountColumn(ui, events, "#UtilitySlots", "Utility", InventoryComponent.UTILITY_SECTION_ID, UTILITY_SLOTS); + mountGrid(ui, events, "#StorageSlots", "Storage", InventoryComponent.STORAGE_SECTION_ID, STORAGE_ROWS, STORAGE_COLS); + mountRow(ui, events, "#HotbarSlots", "Hotbar", InventoryComponent.HOTBAR_SECTION_ID, HOTBAR_SLOTS); + } + + public static void applyContents( + @Nonnull UICommandBuilder ui, + @Nonnull Store store, + @Nonnull Ref ref) { + applySection(ui, store, ref, InventoryComponent.ARMOR_SECTION_ID, "Armor", ARMOR_SLOTS); + applySection(ui, store, ref, InventoryComponent.UTILITY_SECTION_ID, "Utility", UTILITY_SLOTS); + applySection(ui, store, ref, InventoryComponent.STORAGE_SECTION_ID, "Storage", STORAGE_ROWS * STORAGE_COLS); + applySection(ui, store, ref, InventoryComponent.HOTBAR_SECTION_ID, "Hotbar", HOTBAR_SLOTS); + } + + public static void applyPickHighlight( + @Nonnull UICommandBuilder ui, + @Nullable SlotRef pick) { + clearHighlights(ui); + if (pick == null) { + return; + } + String prefix = prefixForSection(pick.sectionId()); + if (prefix != null) { + ui.set("#" + prefix + "Cell" + pick.slotIndex() + ".Background", PICK_CELL_BG); + } + } + + private static void mountColumn( + @Nonnull UICommandBuilder ui, + @Nonnull UIEventBuilder events, + @Nonnull String hostSelector, + @Nonnull String prefix, + int sectionId, + int slotCount) { + for (int slot = 0; slot < slotCount; slot++) { + mountSlotInCell(ui, hostSelector, prefix, slot, SLOT_SIZE, ROW_HEIGHT); + bindSlot(events, prefix, sectionId, slot); + } + } + + private static void mountRow( + @Nonnull UICommandBuilder ui, + @Nonnull UIEventBuilder events, + @Nonnull String hostSelector, + @Nonnull String prefix, + int sectionId, + int slotCount) { + ui.appendInline(hostSelector, "Group #" + prefix + "Row { LayoutMode: Left; }"); + for (int slot = 0; slot < slotCount; slot++) { + mountSlotInCell(ui, "#" + prefix + "Row", prefix, slot, COL_WIDTH, SLOT_SIZE); + bindSlot(events, prefix, sectionId, slot); + } + } + + private static void mountGrid( + @Nonnull UICommandBuilder ui, + @Nonnull UIEventBuilder events, + @Nonnull String hostSelector, + @Nonnull String prefix, + int sectionId, + int rows, + int cols) { + for (int row = 0; row < rows; row++) { + String rowId = prefix + "Row" + row; + String rowAnchor = row < rows - 1 + ? "LayoutMode: Left; Anchor: (Bottom: " + SLOT_GAP + ");" + : "LayoutMode: Left;"; + ui.appendInline(hostSelector, "Group #" + rowId + " { " + rowAnchor + " }"); + for (int col = 0; col < cols; col++) { + int slot = row * cols + col; + mountSlotInCell(ui, "#" + rowId, prefix, slot, COL_WIDTH, SLOT_SIZE); + bindSlot(events, prefix, sectionId, slot); + } + } + } + + /** + * {@code appendInline} accepts one element per call — mount the cell, then the slot inside it. + */ + private static void mountSlotInCell( + @Nonnull UICommandBuilder ui, + @Nonnull String hostSelector, + @Nonnull String prefix, + int slot, + int cellWidth, + int cellHeight) { + String cellId = prefix + "Cell" + slot; + ui.appendInline( + hostSelector, + "Group #" + cellId + " { Anchor: (Width: " + + cellWidth + ", Height: " + cellHeight + "); LayoutMode: Center; }"); + ui.appendInline("#" + cellId, slotButtonMarkup(prefix, slot)); + } + + @Nonnull + private static String slotButtonMarkup(@Nonnull String prefix, int slot) { + String slotId = prefix + "Slot" + slot; + return """ + ItemSlotButton #%sBtn { + Anchor: (Width: %d, Height: %d); + ItemSlot #%s { + Anchor: (Width: %d, Height: %d); + ShowQuantity: true; + ShowQualityBackground: true; + } + } + """.formatted( + slotId, + SLOT_SIZE, + SLOT_SIZE, + slotId, + SLOT_SIZE, + SLOT_SIZE); + } + + private static void bindSlot( + @Nonnull UIEventBuilder events, + @Nonnull String prefix, + int sectionId, + int slot) { + String buttonSelector = "#" + prefix + "Slot" + slot + "Btn"; + EventData hover = EventData.of("Action", "hover") + .append("Section", String.valueOf(sectionId)) + .append("Slot", String.valueOf(slot)); + EventData click = EventData.of("Action", "click") + .append("Section", String.valueOf(sectionId)) + .append("Slot", String.valueOf(slot)); + events.addEventBinding(CustomUIEventBindingType.MouseEntered, buttonSelector, hover, false); + events.addEventBinding(CustomUIEventBindingType.Activating, buttonSelector, click, false); + } + + private static void clearHighlights(@Nonnull UICommandBuilder ui) { + clearSectionHighlights(ui, "Armor", ARMOR_SLOTS); + clearSectionHighlights(ui, "Utility", UTILITY_SLOTS); + clearSectionHighlights(ui, "Storage", STORAGE_ROWS * STORAGE_COLS); + clearSectionHighlights(ui, "Hotbar", HOTBAR_SLOTS); + } + + private static void clearSectionHighlights( + @Nonnull UICommandBuilder ui, + @Nonnull String prefix, + int slotCount) { + for (int slot = 0; slot < slotCount; slot++) { + ui.set("#" + prefix + "Cell" + slot + ".Background", CLEAR_HIGHLIGHT); + } + } + + @Nullable + private static String prefixForSection(int sectionId) { + if (sectionId == InventoryComponent.ARMOR_SECTION_ID) { + return "Armor"; + } + if (sectionId == InventoryComponent.UTILITY_SECTION_ID) { + return "Utility"; + } + if (sectionId == InventoryComponent.STORAGE_SECTION_ID) { + return "Storage"; + } + if (sectionId == InventoryComponent.HOTBAR_SECTION_ID) { + return "Hotbar"; + } + return null; + } + + private static void applySection( + @Nonnull UICommandBuilder ui, + @Nonnull Store store, + @Nonnull Ref ref, + int sectionId, + @Nonnull String prefix, + int slotCount) { + ItemContainer container = container(store, ref, sectionId); + if (container == null) { + return; + } + int capacity = Math.min(slotCount, container.getCapacity()); + for (short slot = 0; slot < capacity; slot++) { + applySlot(ui, prefix, slot, container.getItemStack(slot)); + } + for (int slot = capacity; slot < slotCount; slot++) { + applySlot(ui, prefix, (short) slot, null); + } + } + + private static void applySlot( + @Nonnull UICommandBuilder ui, + @Nonnull String prefix, + short slot, + @Nullable ItemStack stack) { + String selector = "#" + prefix + "Slot" + slot; + if (stack == null || ItemStack.isEmpty(stack)) { + ui.setNull(selector + ".ItemId"); + ui.set(selector + ".Quantity", 0); + return; + } + String itemId = stack.getItemId(); + ui.set(selector + ".ItemId", itemId == null ? "" : itemId); + ui.set(selector + ".Quantity", stack.getQuantity()); + } + + @Nonnull + private static ItemContainer container( + @Nonnull Store store, + @Nonnull Ref ref, + int sectionId) { + var type = InventoryComponent.getComponentTypeById(sectionId); + if (type == null) { + return null; + } + InventoryComponent component = store.getComponent(ref, type); + return component == null ? null : component.getInventory(); + } + + public record SlotRef(int sectionId, int slotIndex) { + } +} diff --git a/src/main/java/com/disklexar/mmorpg/ui/PlayerMenuPage.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/PlayerMenuPage.java similarity index 99% rename from src/main/java/com/disklexar/mmorpg/ui/PlayerMenuPage.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/PlayerMenuPage.java index 7485205..9a74dd1 100644 --- a/src/main/java/com/disklexar/mmorpg/ui/PlayerMenuPage.java +++ b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/PlayerMenuPage.java @@ -38,8 +38,8 @@ import java.util.UUID; /** * MMORPG player menu with tabs: Personnage, Inventaire, Compétences. *

- * Inventaire uses {@code MmorpgInventoryPage.ui} as the root document so {@code ItemGrid.InventorySectionId} - * binds correctly. Personnage / Compétences use {@code MmorpgPlayerShell.ui}. + * Inventaire uses {@code MmorpgInventoryPage.ui} as the root document with {@code ItemSlot} icons. + * Personnage / Compétences use {@code MmorpgPlayerShell.ui}. */ public final class PlayerMenuPage extends InteractiveCustomUIPage { diff --git a/src/main/java/com/disklexar/mmorpg/ui/PlayerVitalsReader.java b/Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/PlayerVitalsReader.java similarity index 100% rename from src/main/java/com/disklexar/mmorpg/ui/PlayerVitalsReader.java rename to Hytale/plugins/mmorpg/src/main/java/com/disklexar/mmorpg/ui/PlayerVitalsReader.java diff --git a/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Huds/MmorpgAbilityBar.ui b/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Huds/MmorpgAbilityBar.ui new file mode 100644 index 0000000..83bb470 --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Huds/MmorpgAbilityBar.ui @@ -0,0 +1,198 @@ +@HealthBarFill = PatchStyle(Color: #e74c3c); +@HealthBarBg = PatchStyle(Color: #2a1515); +@StaminaBarFill = PatchStyle(Color: #2ecc71); +@StaminaBarBg = PatchStyle(Color: #152a1c); +@XpBarFill = PatchStyle(Color: #4a9eff); +@XpBarBg = PatchStyle(Color: #152030); +@VitalsPanelWidth = 260; +@VitalsBarWidth = 244; +@VitalsBarHeight = 16; +@AbilitySlotSize = 68; +@AbilityPanelPad = 3; +@AbilityPanelWidth = @AbilitySlotSize + (@AbilityPanelPad * 2); + +Group { + LayoutMode: Top; + Anchor: (Left: 16, Top: 16, Width: @VitalsPanelWidth); + + Label #HeaderLabel { + Style: (FontSize: 14, RenderBold: true, TextColor: #f5c842); + Text: "Nv.1 — Classe"; + Anchor: (Left: 0, Bottom: 8); + } + + Group #VitalsPanel { + LayoutMode: Top; + Padding: (Full: 8); + Background: #0d0f14(0.92); + Anchor: (Left: 0, Width: @VitalsPanelWidth, Bottom: 8); + + Group #HealthRow { + LayoutMode: Top; + Anchor: (Bottom: 6); + + Label #HealthTitle { + Style: (FontSize: 10, RenderBold: true, TextColor: #ff7b7b); + Text: "Vie"; + Anchor: (Bottom: 2); + } + + Group #HealthBarTrack { + LayoutMode: Full; + Anchor: (Width: @VitalsBarWidth, Height: @VitalsBarHeight); + + ProgressBar #HealthBar { + Anchor: (Width: @VitalsBarWidth, Height: @VitalsBarHeight); + Bar: @HealthBarFill; + Background: @HealthBarBg; + Value: 1.0; + Direction: End; + } + + Group { + LayoutMode: CenterMiddle; + Anchor: (Width: @VitalsBarWidth, Height: @VitalsBarHeight); + + Label #HealthValue { + Style: (FontSize: 9, RenderBold: true, TextColor: #ffffff); + Text: "0 / 0"; + } + } + } + } + + Group #StaminaRow { + LayoutMode: Top; + Anchor: (Bottom: 6); + + Label #StaminaTitle { + Style: (FontSize: 10, RenderBold: true, TextColor: #7bdc9a); + Text: "Endurance"; + Anchor: (Bottom: 2); + } + + Group #StaminaBarTrack { + LayoutMode: Full; + Anchor: (Width: @VitalsBarWidth, Height: @VitalsBarHeight); + + ProgressBar #StaminaBar { + Anchor: (Width: @VitalsBarWidth, Height: @VitalsBarHeight); + Bar: @StaminaBarFill; + Background: @StaminaBarBg; + Value: 1.0; + Direction: End; + } + + Group { + LayoutMode: CenterMiddle; + Anchor: (Width: @VitalsBarWidth, Height: @VitalsBarHeight); + + Label #StaminaValue { + Style: (FontSize: 9, RenderBold: true, TextColor: #ffffff); + Text: "0 / 0"; + } + } + } + } + + Group #XpRow { + LayoutMode: Top; + + Label #XpTitle { + Style: (FontSize: 10, RenderBold: true, TextColor: #8eb6ff); + Text: "Expérience"; + Anchor: (Bottom: 2); + } + + Group #XpBarTrack { + LayoutMode: Full; + Anchor: (Width: @VitalsBarWidth, Height: @VitalsBarHeight); + + ProgressBar #XpBar { + Anchor: (Width: @VitalsBarWidth, Height: @VitalsBarHeight); + Bar: @XpBarFill; + Background: @XpBarBg; + Value: 0.0; + Direction: End; + } + + Group { + LayoutMode: CenterMiddle; + Anchor: (Width: @VitalsBarWidth, Height: @VitalsBarHeight); + + Label #XpValue { + Style: (FontSize: 9, RenderBold: true, TextColor: #ffffff); + Text: "0 / 0"; + } + } + } + } + } + + Label #BarTitle { + Style: (FontSize: 12, RenderBold: true, TextColor: #f5c842); + Text: "CAPACITÉS"; + Anchor: (Left: 0, Bottom: 4); + } + + Group #AbilityBarPanel { + LayoutMode: Top; + Padding: (Full: @AbilityPanelPad); + Background: #0d0f14(0.92); + Anchor: (Left: 0, Width: @AbilityPanelWidth); + + Group #AbilitySlot1 { + Anchor: (Width: @AbilitySlotSize, Height: @AbilitySlotSize, Bottom: 5); + Background: #2a3140; + LayoutMode: Top; + Padding: (Full: 4); + + Label #Slot1Key { + Style: (FontSize: 12, RenderBold: true, TextColor: #f5c842); + Text: "[Q]"; + Anchor: (Bottom: 2); + } + + Label #Slot1Name { + Style: (FontSize: 10, TextColor: #ffffff, Wrap: true); + Text: "Capacité 1"; + } + } + + Group #AbilitySlot2 { + Anchor: (Width: @AbilitySlotSize, Height: @AbilitySlotSize, Bottom: 5); + Background: #2a3140; + LayoutMode: Top; + Padding: (Full: 4); + + Label #Slot2Key { + Style: (FontSize: 12, RenderBold: true, TextColor: #f5c842); + Text: "[E]"; + Anchor: (Bottom: 2); + } + + Label #Slot2Name { + Style: (FontSize: 10, TextColor: #ffffff, Wrap: true); + Text: "Capacité 2"; + } + } + + Group #AbilitySlot3 { + Anchor: (Width: @AbilitySlotSize, Height: @AbilitySlotSize); + Background: #2a3140; + LayoutMode: Top; + Padding: (Full: 4); + + Label #Slot3Key { + Style: (FontSize: 12, RenderBold: true, TextColor: #f5c842); + Text: "[R]"; + Anchor: (Bottom: 2); + } + + Label #Slot3Name { + Style: (FontSize: 10, TextColor: #ffffff, Wrap: true); + Text: "Capacité 3"; + } + } + } +} diff --git a/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgCharacterTab.ui b/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgCharacterTab.ui new file mode 100644 index 0000000..312ec55 --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgCharacterTab.ui @@ -0,0 +1,206 @@ +@MmorpgAccent = #f5c842; +@MmorpgText = #e8e8ec; +@MmorpgMuted = #878e9c; +@MmorpgBorder = #3a3f4a; +@HealthFill = PatchStyle(Color: #e74c3c); +@HealthBg = PatchStyle(Color: #2a1515); +@StaminaFill = PatchStyle(Color: #2ecc71); +@StaminaBg = PatchStyle(Color: #152a1c); +@XpFill = PatchStyle(Color: #4a9eff); +@XpBg = PatchStyle(Color: #152030); + +Group { + LayoutMode: Left; + + Group #LeftColumn { + LayoutMode: Top; + Anchor: (Width: 400, Right: 16); + + Label { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgMuted); + Text: "IDENTITÉ"; + Anchor: (Bottom: 6); + } + + Label #IdentityName { + Style: (FontSize: 18, RenderBold: true, TextColor: @MmorpgAccent); + Text: "Joueur"; + Anchor: (Bottom: 4); + } + + Label #RaceLabel { + Style: (FontSize: 13, TextColor: @MmorpgText); + Text: "Race : Humain"; + Anchor: (Bottom: 2); + } + + Label #ClassLabel { + Style: (FontSize: 13, TextColor: @MmorpgText); + Text: "Classe : —"; + Anchor: (Bottom: 10); + } + + Label { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgMuted); + Text: "PROGRESSION"; + Anchor: (Bottom: 6); + } + + Label #XpValue { + Style: (FontSize: 11, TextColor: @MmorpgText); + Text: "0 / 100 XP"; + Anchor: (Bottom: 4); + } + + ProgressBar #XpBar { + Anchor: (Width: 360, Height: 14, Bottom: 10); + Bar: @XpFill; + Background: @XpBg; + Value: 0.0; + Direction: End; + } + + Label { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgMuted); + Text: "VITALITÉ"; + Anchor: (Bottom: 6); + } + + Label #HealthValue { + Style: (FontSize: 10, TextColor: @MmorpgText); + Text: "Vie : —"; + Anchor: (Bottom: 2); + } + + ProgressBar #HealthBar { + Anchor: (Width: 360, Height: 12, Bottom: 6); + Bar: @HealthFill; + Background: @HealthBg; + Value: 1.0; + Direction: End; + } + + Label #StaminaValue { + Style: (FontSize: 10, TextColor: @MmorpgText); + Text: "Endurance : —"; + Anchor: (Bottom: 2); + } + + ProgressBar #StaminaBar { + Anchor: (Width: 360, Height: 12, Bottom: 10); + Bar: @StaminaFill; + Background: @StaminaBg; + Value: 1.0; + Direction: End; + } + + Label { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgMuted); + Text: "ATTRIBUTS"; + Anchor: (Bottom: 6); + } + + Group { + LayoutMode: Left; + Anchor: (Bottom: 4); + + Label #StatStr { + Style: (FontSize: 12, TextColor: @MmorpgText); + Text: "FOR 10"; + Padding: (Horizontal: 10, Vertical: 4); + Background: #2a3140; + Anchor: (Right: 6); + } + + Label #StatAgi { + Style: (FontSize: 12, TextColor: @MmorpgText); + Text: "AGI 10"; + Padding: (Horizontal: 10, Vertical: 4); + Background: #2a3140; + Anchor: (Right: 6); + } + + Label #StatInt { + Style: (FontSize: 12, TextColor: @MmorpgText); + Text: "INT 10"; + Padding: (Horizontal: 10, Vertical: 4); + Background: #2a3140; + } + } + + Label #StatsHint { + Style: (FontSize: 9, TextColor: @MmorpgMuted); + Text: "Attributs dérivés du niveau (système M1 à venir)"; + } + } + + Group #RightColumn { + LayoutMode: Top; + FlexWeight: 1; + + Label { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgMuted); + Text: "POUVOIRS PASSIFS"; + Anchor: (Bottom: 4); + } + + Label #PowersList { + Style: (FontSize: 12, TextColor: @MmorpgText, Wrap: true); + Text: "Aucun"; + Anchor: (Bottom: 10); + } + + Label { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgMuted); + Text: "MÉTIERS"; + Anchor: (Bottom: 4); + } + + Label #JobsList { + Style: (FontSize: 12, TextColor: @MmorpgText, Wrap: true); + Text: "Aucun"; + Anchor: (Bottom: 10); + } + + Label { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgMuted); + Text: "SOCIAL"; + Anchor: (Bottom: 4); + } + + Label #GroupLabel { + Style: (FontSize: 12, TextColor: @MmorpgText); + Text: "Groupe : Aucun"; + Anchor: (Bottom: 2); + } + + Label #GuildLabel { + Style: (FontSize: 12, TextColor: @MmorpgText); + Text: "Guilde : Aucune"; + Anchor: (Bottom: 10); + } + + Label { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgMuted); + Text: "STATISTIQUES"; + Anchor: (Bottom: 4); + } + + Label #PlayTimeLabel { + Style: (FontSize: 12, TextColor: @MmorpgText); + Text: "Temps de jeu : 0 min"; + Anchor: (Bottom: 2); + } + + Label #LastLoginLabel { + Style: (FontSize: 12, TextColor: @MmorpgText); + Text: "Dernière connexion : —"; + Anchor: (Bottom: 2); + } + + Label #CreatedLabel { + Style: (FontSize: 12, TextColor: @MmorpgText); + Text: "Création : —"; + } + } +} diff --git a/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgInventoryPage.ui b/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgInventoryPage.ui new file mode 100644 index 0000000..29673ef --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgInventoryPage.ui @@ -0,0 +1,260 @@ +@MmorpgBg = #0d0f14(0.96); +@MmorpgPanel = #1a1c20; +@MmorpgAccent = #f5c842; +@MmorpgText = #e8e8ec; +@MmorpgMuted = #878e9c; +@MmorpgBorder = #3a3f4a; + +@SlotSize = 52; +@SlotGap = 4; +@SlotColWidth = @SlotSize + @SlotGap; +@SlotRowHeight = @SlotSize + @SlotGap; +@StorageGridWidth = (@SlotColWidth * 9) - @SlotGap; +@StorageGridHeight = (@SlotRowHeight * 4) - @SlotGap; +@HotbarWidth = (@SlotColWidth * 9) - @SlotGap; +@ColumnHeight = (@SlotRowHeight * 4) - @SlotGap; + +@ShellWidth = 920; +@ShellHeight = 660; + +Group { + LayoutMode: Center; + + Group #MmorpgShell { + LayoutMode: Top; + Anchor: (Width: @ShellWidth, Height: @ShellHeight); + Background: @MmorpgBg; + Padding: (Full: 16); + + Group #Header { + LayoutMode: Left; + Anchor: (Bottom: 12); + + Group { + LayoutMode: Top; + FlexWeight: 1; + + Label #PlayerName { + Style: (FontSize: 20, RenderBold: true, TextColor: @MmorpgAccent); + Text: "Joueur"; + Anchor: (Bottom: 2); + } + + Label #ClassLabel { + Style: (FontSize: 13, TextColor: @MmorpgText); + Text: "Classe"; + } + } + + Group { + LayoutMode: Top; + Anchor: (Right: 24); + + Label #LevelLabel { + Style: (FontSize: 14, RenderBold: true, TextColor: @MmorpgText); + Text: "Nv. 1"; + Anchor: (Bottom: 2); + } + + Label #MoneyLabel { + Style: (FontSize: 13, TextColor: @MmorpgAccent); + Text: "0 pièces"; + } + } + } + + Group #TabBar { + LayoutMode: Left; + Padding: (Bottom: 10); + Anchor: (Bottom: 8); + + Group #TabCharacterWrap { + LayoutMode: Top; + Padding: (Horizontal: 12, Vertical: 4); + Anchor: (Right: 6); + Background: PatchStyle(Color: #00000000); + + TextButton #TabCharacter { + Text: "Personnage"; + } + + Group #TabCharacterIndicator { + Anchor: (Height: 2, Top: 4); + Background: PatchStyle(Color: @MmorpgAccent); + Visible: false; + } + } + + Group #TabInventoryWrap { + LayoutMode: Top; + Padding: (Horizontal: 12, Vertical: 4); + Anchor: (Right: 6); + Background: PatchStyle(Color: #00000000); + + TextButton #TabInventory { + Text: "Inventaire"; + } + + Group #TabInventoryIndicator { + Anchor: (Height: 2, Top: 4); + Background: PatchStyle(Color: @MmorpgAccent); + Visible: false; + } + } + + Group #TabSkillsWrap { + LayoutMode: Top; + Padding: (Horizontal: 12, Vertical: 4); + Anchor: (Right: 6); + Background: PatchStyle(Color: #00000000); + + TextButton #TabSkills { + Text: "Compétences"; + } + + Group #TabSkillsIndicator { + Anchor: (Height: 2, Top: 4); + Background: PatchStyle(Color: @MmorpgAccent); + Visible: false; + } + } + } + + Group #TabContent { + LayoutMode: Left; + FlexWeight: 1; + + Group #EquipmentPanel { + LayoutMode: Top; + Anchor: (Width: 88, Right: 12); + Padding: (Full: 8); + Background: @MmorpgPanel; + + Label { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgMuted); + Text: "ARMURE"; + Anchor: (Bottom: 4); + } + + Label #ArmorSummary { + Style: (FontSize: 9, TextColor: @MmorpgMuted); + Text: "Armure : 0 / 4"; + Anchor: (Bottom: 6); + } + + Group #ArmorSlots { + LayoutMode: Top; + Anchor: (Width: @SlotSize, Height: @ColumnHeight, Bottom: 10); + } + + Label { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgMuted); + Text: "UTILITAIRE"; + Anchor: (Bottom: 4); + } + + Label #UtilitySummary { + Style: (FontSize: 9, TextColor: @MmorpgMuted); + Text: "Utilitaire : 0 / 4"; + Anchor: (Bottom: 6); + } + + Group #UtilitySlots { + LayoutMode: Top; + Anchor: (Width: @SlotSize, Height: @ColumnHeight); + } + } + + Group #InventoryCenter { + LayoutMode: Top; + FlexWeight: 1; + Padding: (Full: 8); + Background: @MmorpgPanel; + + Label #StorageSummary { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgAccent); + Text: "Sac : 0 / 36"; + Anchor: (Bottom: 6); + } + + Group #StorageSlots { + LayoutMode: Top; + Anchor: (Width: @StorageGridWidth, Height: @StorageGridHeight, Bottom: 10); + } + + Label #HotbarSummary { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgAccent); + Text: "Barre rapide : 0 / 9"; + Anchor: (Bottom: 6); + } + + Group #HotbarSlots { + LayoutMode: Top; + Anchor: (Width: @HotbarWidth, Height: @SlotSize); + } + } + + Group #ItemDetails { + LayoutMode: Top; + Anchor: (Width: 260, Left: 12); + Padding: (Full: 10); + Background: @MmorpgPanel; + + Label { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgMuted); + Text: "DÉTAILS"; + Anchor: (Bottom: 8); + } + + Label #ItemName { + Style: (FontSize: 15, RenderBold: true, TextColor: @MmorpgAccent); + Text: "Aucun objet"; + Anchor: (Bottom: 6); + } + + Label #ItemRarity { + Style: (FontSize: 11, TextColor: @MmorpgMuted); + Text: "Sélectionnez un emplacement"; + Anchor: (Bottom: 8); + } + + Label #ItemDescription { + Style: (FontSize: 12, TextColor: @MmorpgText, Wrap: true); + Text: "Cliquez un objet pour afficher ses informations."; + Anchor: (Bottom: 12); + } + + Group #WeightTrack { + LayoutMode: Top; + Anchor: (Bottom: 4); + + Label { + Style: (FontSize: 10, TextColor: @MmorpgMuted); + Text: "Remplissage du sac"; + Anchor: (Bottom: 4); + } + + ProgressBar #WeightBar { + Anchor: (Width: 220, Height: 10); + Bar: PatchStyle(Color: @MmorpgAccent); + Background: PatchStyle(Color: @MmorpgBorder); + Value: 0.0; + Direction: End; + } + + Label #WeightValue { + Style: (FontSize: 9, TextColor: @MmorpgMuted); + Text: "0 piles"; + Anchor: (Top: 4); + } + } + } + } + + Label #FooterHint { + Style: (FontSize: 11, TextColor: @MmorpgMuted); + Text: "Échap pour fermer — clic source puis destination pour déplacer, survol pour les détails"; + Anchor: (Top: 10); + } + } +} diff --git a/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgInventoryTab.ui b/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgInventoryTab.ui new file mode 100644 index 0000000..79fcdf9 --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgInventoryTab.ui @@ -0,0 +1,161 @@ +@MmorpgPanel = #1a1c20; +@MmorpgAccent = #f5c842; +@MmorpgText = #e8e8ec; +@MmorpgMuted = #878e9c; +@MmorpgBorder = #3a3f4a; + +@GridStyle = ItemGridStyle( + SlotSpacing: 4, + SlotSize: 52, + SlotIconSize: 44 +); + +Group { + LayoutMode: Left; + + Group #EquipmentPanel { + LayoutMode: Top; + Anchor: (Width: 88, Right: 12); + Padding: (Full: 8); + Background: @MmorpgPanel; + + Label { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgMuted); + Text: "ARMURE"; + Anchor: (Bottom: 4); + } + + Label #ArmorSummary { + Style: (FontSize: 9, TextColor: @MmorpgMuted); + Text: "Armure : 0 / 4"; + Anchor: (Bottom: 6); + } + + ItemGrid #ArmorGrid { + Anchor: (Width: 56, Height: 232, Bottom: 10); + SlotsPerRow: 1; + InventorySectionId: -3; + AreItemsDraggable: true; + DisplayItemQuantity: true; + RenderItemQualityBackground: true; + Style: @GridStyle; + } + + Label { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgMuted); + Text: "UTILITAIRE"; + Anchor: (Bottom: 4); + } + + Label #UtilitySummary { + Style: (FontSize: 9, TextColor: @MmorpgMuted); + Text: "Utilitaire : 0 / 4"; + Anchor: (Bottom: 6); + } + + ItemGrid #UtilityGrid { + Anchor: (Width: 56, Height: 232); + SlotsPerRow: 1; + InventorySectionId: -5; + AreItemsDraggable: true; + DisplayItemQuantity: true; + RenderItemQualityBackground: true; + Style: @GridStyle; + } + } + + Group #InventoryCenter { + LayoutMode: Top; + FlexWeight: 1; + Padding: (Full: 8); + Background: @MmorpgPanel; + + Label #StorageSummary { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgAccent); + Text: "Sac : 0 / 36"; + Anchor: (Bottom: 6); + } + + ItemGrid #StorageGrid { + Anchor: (Width: 500, Height: 232, Bottom: 10); + SlotsPerRow: 9; + InventorySectionId: -2; + AreItemsDraggable: true; + DisplayItemQuantity: true; + RenderItemQualityBackground: true; + Style: @GridStyle; + } + + Label #HotbarSummary { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgAccent); + Text: "Barre rapide : 0 / 9"; + Anchor: (Bottom: 6); + } + + ItemGrid #HotbarGrid { + Anchor: (Width: 500, Height: 60); + SlotsPerRow: 9; + InventorySectionId: -1; + AreItemsDraggable: true; + DisplayItemQuantity: true; + RenderItemQualityBackground: true; + Style: @GridStyle; + } + } + + Group #ItemDetails { + LayoutMode: Top; + Anchor: (Width: 260, Left: 12); + Padding: (Full: 10); + Background: @MmorpgPanel; + + Label { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgMuted); + Text: "DÉTAILS"; + Anchor: (Bottom: 8); + } + + Label #ItemName { + Style: (FontSize: 15, RenderBold: true, TextColor: @MmorpgAccent); + Text: "Aucun objet"; + Anchor: (Bottom: 6); + } + + Label #ItemRarity { + Style: (FontSize: 11, TextColor: @MmorpgMuted); + Text: "Sélectionnez un emplacement"; + Anchor: (Bottom: 8); + } + + Label #ItemDescription { + Style: (FontSize: 12, TextColor: @MmorpgText, Wrap: true); + Text: "Cliquez un objet pour afficher ses informations."; + Anchor: (Bottom: 12); + } + + Group #WeightTrack { + LayoutMode: Top; + Anchor: (Bottom: 4); + + Label { + Style: (FontSize: 10, TextColor: @MmorpgMuted); + Text: "Remplissage du sac"; + Anchor: (Bottom: 4); + } + + ProgressBar #WeightBar { + Anchor: (Width: 220, Height: 10); + Bar: PatchStyle(Color: @MmorpgAccent); + Background: PatchStyle(Color: @MmorpgBorder); + Value: 0.0; + Direction: End; + } + + Label #WeightValue { + Style: (FontSize: 9, TextColor: @MmorpgMuted); + Text: "0 piles"; + Anchor: (Top: 4); + } + } + } +} diff --git a/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgPlayerInfo.ui b/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgPlayerInfo.ui new file mode 100644 index 0000000..8e60447 --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgPlayerInfo.ui @@ -0,0 +1,29 @@ +$C = "../Common.ui"; + +$C.@PageOverlay {} + +$C.@Container { + Anchor: (Width: 600, Height: 700); + + #Title { + Group { + $C.@Title { + @Text = %server.customUI.warpListPage.warps; + } + + $C.@HeaderSearch {} + } + } + + #Content { + LayoutMode: Left; + + Group #ProfileList { + FlexWeight: 1; + LayoutMode: TopScrolling; + ScrollbarStyle: $C.@DefaultScrollbarStyle; + } + } +} + +$C.@BackButton {} diff --git a/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgPlayerShell.ui b/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgPlayerShell.ui new file mode 100644 index 0000000..60a21e0 --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgPlayerShell.ui @@ -0,0 +1,131 @@ +@MmorpgBg = #0d0f14(0.96); +@MmorpgPanel = #1a1c20; +@MmorpgAccent = #f5c842; +@MmorpgText = #e8e8ec; +@MmorpgMuted = #878e9c; + +@ShellWidth = 920; +@ShellHeight = 660; + +Group { + LayoutMode: Center; + + Group #MmorpgShell { + LayoutMode: Top; + Anchor: (Width: @ShellWidth, Height: @ShellHeight); + Background: @MmorpgBg; + Padding: (Full: 16); + + Group #Header { + LayoutMode: Left; + Anchor: (Bottom: 12); + + Group { + LayoutMode: Top; + FlexWeight: 1; + + Label #PlayerName { + Style: (FontSize: 20, RenderBold: true, TextColor: @MmorpgAccent); + Text: "Joueur"; + Anchor: (Bottom: 2); + } + + Label #HeaderSubtitle { + Style: (FontSize: 13, TextColor: @MmorpgText); + Text: "Profil MMORPG"; + } + } + + Group { + LayoutMode: Top; + Anchor: (Right: 24); + + Label #LevelLabel { + Style: (FontSize: 14, RenderBold: true, TextColor: @MmorpgText); + Text: "Nv. 1"; + Anchor: (Bottom: 2); + } + + Label #MoneyLabel { + Style: (FontSize: 13, TextColor: @MmorpgAccent); + Text: "0 pièces"; + } + } + } + + Group #TabBar { + LayoutMode: Left; + Padding: (Bottom: 10); + Anchor: (Bottom: 8); + + Group #TabCharacterWrap { + LayoutMode: Top; + Padding: (Horizontal: 12, Vertical: 4); + Anchor: (Right: 6); + Background: PatchStyle(Color: #00000000); + + TextButton #TabCharacter { + Text: "Personnage"; + } + + Group #TabCharacterIndicator { + Anchor: (Height: 2, Top: 4); + Background: PatchStyle(Color: @MmorpgAccent); + Visible: false; + } + } + + Group #TabInventoryWrap { + LayoutMode: Top; + Padding: (Horizontal: 12, Vertical: 4); + Anchor: (Right: 6); + Background: PatchStyle(Color: #00000000); + + TextButton #TabInventory { + Text: "Inventaire"; + } + + Group #TabInventoryIndicator { + Anchor: (Height: 2, Top: 4); + Background: PatchStyle(Color: @MmorpgAccent); + Visible: false; + } + } + + Group #TabSkillsWrap { + LayoutMode: Top; + Padding: (Horizontal: 12, Vertical: 4); + Anchor: (Right: 6); + Background: PatchStyle(Color: #00000000); + + TextButton #TabSkills { + Text: "Compétences"; + } + + Group #TabSkillsIndicator { + Anchor: (Height: 2, Top: 4); + Background: PatchStyle(Color: @MmorpgAccent); + Visible: false; + } + } + } + + Group #TabContent { + LayoutMode: Top; + FlexWeight: 1; + + Group #DynamicTabHost { + LayoutMode: Top; + FlexWeight: 1; + Background: @MmorpgPanel; + Padding: (Full: 10); + } + } + + Label #FooterHint { + Style: (FontSize: 11, TextColor: @MmorpgMuted); + Text: "Échap pour fermer"; + Anchor: (Top: 10); + } + } +} diff --git a/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgSkillsTab.ui b/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgSkillsTab.ui new file mode 100644 index 0000000..c374f8e --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/Common/UI/Custom/Pages/MmorpgSkillsTab.ui @@ -0,0 +1,198 @@ +@MmorpgAccent = #f5c842; +@MmorpgText = #e8e8ec; +@MmorpgMuted = #878e9c; +@MmorpgSlot = #2a3140; +@MmorpgLocked = #1e2228; + +Group { + LayoutMode: Top; + + Label #ClassTitle { + Style: (FontSize: 16, RenderBold: true, TextColor: @MmorpgAccent); + Text: "Classe"; + Anchor: (Bottom: 2); + } + + Label #WeaponsLabel { + Style: (FontSize: 11, TextColor: @MmorpgMuted); + Text: "Armes : —"; + Anchor: (Bottom: 6); + } + + Label #PointsLabel { + Style: (FontSize: 12, TextColor: @MmorpgText); + Text: "Points de compétence : 0"; + Anchor: (Bottom: 10); + } + + Label { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgMuted); + Text: "CAPACITÉS DE CLASSE"; + Anchor: (Bottom: 6); + } + + Group { + LayoutMode: Left; + Anchor: (Bottom: 14); + + Group #AbilityPanel1 { + LayoutMode: Top; + Padding: (Full: 8); + Background: @MmorpgSlot; + Anchor: (Width: 250, Right: 10); + + Label #Ability1Key { + Style: (FontSize: 12, RenderBold: true, TextColor: @MmorpgAccent); + Text: "[Q]"; + Anchor: (Bottom: 4); + } + + Label #Ability1Name { + Style: (FontSize: 14, RenderBold: true, TextColor: @MmorpgText); + Text: "Capacité 1"; + Anchor: (Bottom: 4); + } + + Label #Ability1Cooldown { + Style: (FontSize: 10, TextColor: @MmorpgMuted); + Text: "Prêt"; + Anchor: (Bottom: 6); + } + + Label #Ability1Desc { + Style: (FontSize: 11, TextColor: @MmorpgMuted, Wrap: true); + Text: "—"; + } + } + + Group #AbilityPanel2 { + LayoutMode: Top; + Padding: (Full: 8); + Background: @MmorpgSlot; + Anchor: (Width: 250, Right: 10); + + Label #Ability2Key { + Style: (FontSize: 12, RenderBold: true, TextColor: @MmorpgAccent); + Text: "[E]"; + Anchor: (Bottom: 4); + } + + Label #Ability2Name { + Style: (FontSize: 14, RenderBold: true, TextColor: @MmorpgText); + Text: "Capacité 2"; + Anchor: (Bottom: 4); + } + + Label #Ability2Cooldown { + Style: (FontSize: 10, TextColor: @MmorpgMuted); + Text: "Prêt"; + Anchor: (Bottom: 6); + } + + Label #Ability2Desc { + Style: (FontSize: 11, TextColor: @MmorpgMuted, Wrap: true); + Text: "—"; + } + } + + Group #AbilityPanel3 { + LayoutMode: Top; + Padding: (Full: 8); + Background: @MmorpgSlot; + Anchor: (Width: 250); + + Label #Ability3Key { + Style: (FontSize: 12, RenderBold: true, TextColor: @MmorpgAccent); + Text: "[R]"; + Anchor: (Bottom: 4); + } + + Label #Ability3Name { + Style: (FontSize: 14, RenderBold: true, TextColor: @MmorpgText); + Text: "Capacité 3"; + Anchor: (Bottom: 4); + } + + Label #Ability3Cooldown { + Style: (FontSize: 10, TextColor: @MmorpgMuted); + Text: "Prêt"; + Anchor: (Bottom: 6); + } + + Label #Ability3Desc { + Style: (FontSize: 11, TextColor: @MmorpgMuted, Wrap: true); + Text: "—"; + } + } + } + + Label { + Style: (FontSize: 11, RenderBold: true, TextColor: @MmorpgMuted); + Text: "BRANCHES DE COMPÉTENCES"; + Anchor: (Bottom: 6); + } + + Group { + LayoutMode: Left; + Anchor: (Bottom: 8); + + Group #Branch1 { + LayoutMode: Top; + Padding: (Full: 8); + Background: @MmorpgLocked; + Anchor: (Width: 180, Right: 10); + + Label #Branch1Title { + Style: (FontSize: 12, RenderBold: true, TextColor: @MmorpgMuted); + Text: "Offensive"; + Anchor: (Bottom: 4); + } + + Label #Branch1Status { + Style: (FontSize: 10, TextColor: @MmorpgMuted); + Text: "Verrouillé — M1"; + } + } + + Group #Branch2 { + LayoutMode: Top; + Padding: (Full: 8); + Background: @MmorpgLocked; + Anchor: (Width: 180, Right: 10); + + Label #Branch2Title { + Style: (FontSize: 12, RenderBold: true, TextColor: @MmorpgMuted); + Text: "Défensive"; + Anchor: (Bottom: 4); + } + + Label #Branch2Status { + Style: (FontSize: 10, TextColor: @MmorpgMuted); + Text: "Verrouillé — M1"; + } + } + + Group #Branch3 { + LayoutMode: Top; + Padding: (Full: 8); + Background: @MmorpgLocked; + Anchor: (Width: 180); + + Label #Branch3Title { + Style: (FontSize: 12, RenderBold: true, TextColor: @MmorpgMuted); + Text: "Utilitaire"; + Anchor: (Bottom: 4); + } + + Label #Branch3Status { + Style: (FontSize: 10, TextColor: @MmorpgMuted); + Text: "Verrouillé — M1"; + } + } + } + + Label #SkillsHint { + Style: (FontSize: 10, TextColor: @MmorpgMuted, Wrap: true); + Text: "Utilisez [Q] [E] [R] (Use Ability 1/2/3) en jeu. L'arbre de talents complet arrive en M1."; + } +} diff --git a/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Battleaxe_Mithril.json b/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Battleaxe_Mithril.json new file mode 100644 index 0000000..65887d5 --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Battleaxe_Mithril.json @@ -0,0 +1,167 @@ +{ + "Parent": "Template_Weapon_Battleaxe", + "TranslationProperties": { + "Name": "server.items.Weapon_Battleaxe_Mithril.name" + }, + "Model": "Items/Weapons/Battleaxe/Mithril.blockymodel", + "Texture": "Items/Weapons/Battleaxe/Mithril_Texture.png", + "Icon": "Icons/ItemsGenerated/Weapon_Battleaxe_Mithril.png", + "Recipe": { + "TimeSeconds": 5, + "KnowledgeRequired": false, + "Input": [ + { + "ItemId": "Ingredient_Bar_Mithril", + "Quantity": 10 + }, + { + "ItemId": "Ingredient_Leather_Storm", + "Quantity": 4 + }, + { + "ItemId": "Ingredient_Voidheart", + "Quantity": 1 + } + ], + "BenchRequirement": [ + { + "Type": "Crafting", + "Categories": [ + "Weapon_Battleaxe" + ], + "Id": "Weapon_Bench", + "RequiredTierLevel": 3 + } + ] + }, + "Quality": "Epic", + "ItemLevel": 50, + "InteractionVars": { + "Swing_Down_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Battleaxe_Primary_Swing_Down_Damage", + "DamageCalculator": { + "BaseDamage": { + "Physical": 73 + } + }, + "DamageEffects": { + "WorldSoundEventId": "SFX_Battleaxe_T2_Impact", + "LocalSoundEventId": "SFX_Battleaxe_T2_Impact" + } + } + ] + }, + "Swing_Down_Left_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Battleaxe_Primary_Swing_Down_Left_Damage", + "DamageCalculator": { + "BaseDamage": { + "Physical": 36 + } + }, + "DamageEffects": { + "WorldSoundEventId": "SFX_Battleaxe_T2_Impact", + "LocalSoundEventId": "SFX_Battleaxe_T2_Impact" + } + } + ] + }, + "Swing_Down_Right_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Battleaxe_Primary_Swing_Down_Right_Damage", + "DamageCalculator": { + "BaseDamage": { + "Physical": 44 + } + }, + "DamageEffects": { + "WorldSoundEventId": "SFX_Battleaxe_T2_Impact", + "LocalSoundEventId": "SFX_Battleaxe_T2_Impact" + } + } + ] + }, + "Downstrike_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Battleaxe_Primary_Downstrike_Damage", + "DamageCalculator": { + "BaseDamage": { + "Physical": 57 + } + }, + "EntityStatsOnHit": [ + { + "EntityStatId": "SignatureEnergy", + "Amount": 2 + } + ], + "DamageEffects": { + "WorldSoundEventId": "SFX_Battleaxe_T2_Impact", + "LocalSoundEventId": "SFX_Battleaxe_T2_Impact" + } + } + ] + }, + "Signature_Whirlwind_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Battleaxe_Signature_Whirlwind_Damage", + "DamageCalculator": { + "BaseDamage": { + "Physical": 29 + } + }, + "EntityStatsOnHit": [], + "DamageEffects": { + "WorldSoundEventId": "SFX_Battleaxe_T2_Impact", + "LocalSoundEventId": "SFX_Battleaxe_T2_Impact" + } + } + ] + }, + "Guard_Wield": { + "Interactions": [ + { + "Parent": "Weapon_Battleaxe_Secondary_Guard_Wield", + "StaminaCost": { + "Value": 20, + "CostType": "Damage" + } + } + ] + } + }, + "MaxDurability": 220, + "DurabilityLossOnHit": 0.45, + "Interactions": { + "Ability1": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 1 + } + ] + }, + "Ability2": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 2 + } + ] + }, + "Ability3": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 3 + } + ] + } + } +} diff --git a/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Crossbow_Ancient_Steel.json b/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Crossbow_Ancient_Steel.json new file mode 100644 index 0000000..ab3a34e --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Crossbow_Ancient_Steel.json @@ -0,0 +1,88 @@ +{ + "Parent": "Template_Weapon_Crossbow", + "TranslationProperties": { + "Name": "server.items.Weapon_Crossbow_Ancient_Steel.name" + }, + "Model": "Items/Weapons/Crossbow/Iron.blockymodel", + "Texture": "Items/Weapons/Crossbow/Iron_Rusty_Texture.png", + "Icon": "Icons/ItemsGenerated/Weapon_Crossbow_Iron_Rusty.png", + "Quality": "Rare", + "ItemLevel": 30, + "InteractionVars": { + "Standard_Projectile_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Crossbow_Damage_Standard_Projectile", + "DamageCalculator": { + "BaseDamage": { + "Projectile": 16 + } + } + } + ] + }, + "Combo_Projectile_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Crossbow_Damage_Combo_Projectile", + "DamageCalculator": { + "BaseDamage": { + "Projectile": 42 + } + } + } + ] + }, + "Signature_BigArrow_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Crossbow_Damage_Signature_Projectile", + "DamageCalculator": { + "BaseDamage": { + "Projectile": 123 + } + } + } + ] + }, + "Guard_Wield": { + "Interactions": [ + { + "Parent": "Weapon_Crossbow_Secondary_Guard_Wield", + "StaminaCost": { + "Value": 15.56, + "CostType": "Damage" + } + } + ] + } + }, + "MaxDurability": 180, + "DurabilityLossOnHit": 0.28, + "Interactions": { + "Ability1": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 1 + } + ] + }, + "Ability2": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 2 + } + ] + }, + "Ability3": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 3 + } + ] + } + } +} diff --git a/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Daggers_Mithril.json b/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Daggers_Mithril.json new file mode 100644 index 0000000..a1ebb75 --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Daggers_Mithril.json @@ -0,0 +1,463 @@ +{ + "Parent": "Template_Weapon_Daggers", + "TranslationProperties": { + "Name": "server.items.Weapon_Daggers_Mithril.name" + }, + "Model": "Items/Weapons/Dagger/Mithril.blockymodel", + "Texture": "Items/Weapons/Dagger/Mithril_Texture.png", + "Icon": "Icons/ItemsGenerated/Weapon_Daggers_Mithril.png", + "Recipe": { + "TimeSeconds": 5, + "KnowledgeRequired": false, + "Input": [ + { + "ItemId": "Ingredient_Bar_Mithril", + "Quantity": 10 + }, + { + "ItemId": "Ingredient_Leather_Storm", + "Quantity": 3 + }, + { + "ItemId": "Ingredient_Voidheart", + "Quantity": 1 + } + ], + "BenchRequirement": [ + { + "Type": "Crafting", + "Categories": [ + "Weapon_Daggers" + ], + "Id": "Weapon_Bench", + "RequiredTierLevel": 3 + } + ] + }, + "Quality": "Epic", + "ItemLevel": 50, + "InteractionVars": { + "Swing_Left_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Daggers_Primary_Swing_Left_Damage", + "DamageCalculator": { + "BaseDamage": { + "Physical": 8 + } + }, + "DamageEffects": { + "WorldSoundEventId": "SFX_Daggers_T2_Slash_Impact", + "LocalSoundEventId": "SFX_Daggers_T2_Slash_Impact" + }, + "AngledDamage": [] + } + ] + }, + "Swing_Right_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Daggers_Primary_Swing_Right_Damage", + "DamageCalculator": { + "BaseDamage": { + "Physical": 8 + } + }, + "DamageEffects": { + "WorldSoundEventId": "SFX_Daggers_T2_Slash_Impact", + "LocalSoundEventId": "SFX_Daggers_T2_Slash_Impact" + }, + "AngledDamage": [] + } + ] + }, + "Stab_Left_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Daggers_Primary_Stab_Left_Damage", + "DamageCalculator": { + "BaseDamage": { + "Physical": 15 + } + }, + "DamageEffects": { + "WorldSoundEventId": "SFX_Daggers_T2_Stab_Impact", + "LocalSoundEventId": "SFX_Daggers_T2_Stab_Impact" + }, + "AngledDamage": [] + } + ] + }, + "Stab_Right_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Daggers_Primary_Stab_Right_Damage", + "DamageCalculator": { + "BaseDamage": { + "Physical": 25 + } + }, + "DamageEffects": { + "WorldSoundEventId": "SFX_Daggers_T2_Stab_Impact", + "LocalSoundEventId": "SFX_Daggers_T2_Stab_Impact" + }, + "AngledDamage": [] + } + ] + }, + "Pounce_Sweep_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Daggers_Primary_Pounce_Sweep_Damage", + "DamageCalculator": { + "BaseDamage": { + "Physical": 61 + } + }, + "EntityStatsOnHit": [ + { + "EntityStatId": "SignatureEnergy", + "Amount": 1 + } + ], + "DamageEffects": { + "WorldSoundEventId": "SFX_Daggers_T2_Slash_Impact", + "LocalSoundEventId": "SFX_Daggers_T2_Slash_Impact" + }, + "AngledDamage": [ + { + "Angle": 180, + "AngleDistance": 80, + "DamageEffects": { + "Knockback": { + "Direction": { + "X": 0, + "Y": 2, + "Z": -3 + }, + "Type": "Force", + "Force": 6, + "VelocityType": "Set", + "VelocityConfig": { + "AirResistance": 0.99, + "AirResistanceMax": 0.98, + "GroundResistance": 0.94, + "GroundResistanceMax": 0.3, + "Threshold": 3.0, + "Style": "Linear" + } + }, + "WorldParticles": [ + { + "SystemId": "Impact_Critical", + "Scale": 1, + "RotationOffset": { + "Yaw": 180, + "Pitch": 0, + "Roll": 0 + } + } + ], + "LocalSoundEventId": "SFX_Daggers_T2_Slash_Impact", + "WorldSoundEventId": "SFX_Daggers_T2_Slash_Impact" + }, + "DamageCalculator": { + "BaseDamage": { + "Physical": 92 + } + } + } + ] + } + ] + }, + "Pounce_Stab_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Daggers_Primary_Pounce_Stab_Damage", + "DamageCalculator": { + "BaseDamage": { + "Physical": 76 + } + }, + "EntityStatsOnHit": [ + { + "EntityStatId": "SignatureEnergy", + "Amount": 6 + } + ], + "DamageEffects": { + "WorldSoundEventId": "SFX_Daggers_T2_Stab_Impact", + "LocalSoundEventId": "SFX_Daggers_T2_Stab_Impact" + }, + "AngledDamage": [ + { + "Angle": 180, + "AngleDistance": 80, + "DamageEffects": { + "Knockback": { + "Direction": { + "X": 0, + "Y": 1, + "Z": -2 + }, + "Type": "Force", + "Force": 5, + "VelocityType": "Set", + "VelocityConfig": { + "AirResistance": 0.99, + "AirResistanceMax": 0.98, + "GroundResistance": 0.94, + "GroundResistanceMax": 0.3, + "Threshold": 3.0, + "Style": "Linear" + } + }, + "WorldParticles": [ + { + "SystemId": "Impact_Critical", + "Scale": 1, + "RotationOffset": { + "Yaw": 180, + "Pitch": 0, + "Roll": 0 + } + } + ], + "LocalSoundEventId": "SFX_Daggers_T2_Stab_Impact", + "WorldSoundEventId": "SFX_Daggers_T2_Stab_Impact" + }, + "DamageCalculator": { + "BaseDamage": { + "Physical": 114 + } + } + } + ] + } + ] + }, + "Razorstrike_Slash_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Daggers_Signature_Razorstrike_Slash_Damage", + "DamageCalculator": { + "BaseDamage": { + "Physical": 49 + } + }, + "EntityStatsOnHit": [], + "DamageEffects": { + "WorldSoundEventId": "SFX_Daggers_T2_Slash_Impact", + "LocalSoundEventId": "SFX_Daggers_T2_Slash_Impact" + }, + "AngledDamage": [ + { + "Angle": 180, + "AngleDistance": 80, + "DamageEffects": { + "Knockback": { + "Direction": { + "X": 0, + "Y": 1, + "Z": -2 + }, + "Type": "Force", + "Force": 7, + "VelocityType": "Add", + "VelocityConfig": { + "AirResistance": 0.99, + "AirResistanceMax": 0.98, + "GroundResistance": 0.94, + "GroundResistanceMax": 0.3, + "Threshold": 3.0, + "Style": "Linear" + } + }, + "WorldParticles": [ + { + "SystemId": "Impact_Critical", + "Scale": 1, + "RotationOffset": { + "Yaw": 180, + "Pitch": 0, + "Roll": 0 + } + } + ], + "LocalSoundEventId": "SFX_Daggers_T2_Slash_Impact", + "WorldSoundEventId": "SFX_Daggers_T2_Slash_Impact" + }, + "DamageCalculator": { + "BaseDamage": { + "Physical": 74 + } + } + } + ] + } + ] + }, + "Razorstrike_Sweep_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Daggers_Signature_Razorstrike_Sweep_Damage", + "DamageCalculator": { + "BaseDamage": { + "Physical": 61 + } + }, + "EntityStatsOnHit": [], + "DamageEffects": { + "WorldSoundEventId": "SFX_Daggers_T2_Slash_Impact", + "LocalSoundEventId": "SFX_Daggers_T2_Slash_Impact" + }, + "AngledDamage": [ + { + "Angle": 180, + "AngleDistance": 80, + "DamageEffects": { + "Knockback": { + "Direction": { + "X": 0, + "Y": 1, + "Z": -1 + }, + "Type": "Force", + "Force": 7, + "VelocityType": "Add", + "VelocityConfig": { + "AirResistance": 0.99, + "AirResistanceMax": 0.98, + "GroundResistance": 0.94, + "GroundResistanceMax": 0.3, + "Threshold": 3.0, + "Style": "Linear" + } + }, + "WorldParticles": [ + { + "SystemId": "Impact_Critical", + "Scale": 1, + "RotationOffset": { + "Yaw": 180, + "Pitch": 0, + "Roll": 0 + } + } + ], + "LocalSoundEventId": "SFX_Daggers_T2_Slash_Impact", + "WorldSoundEventId": "SFX_Daggers_T2_Slash_Impact" + }, + "DamageCalculator": { + "BaseDamage": { + "Physical": 92 + } + } + } + ] + } + ] + }, + "Razorstrike_Lunge_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Daggers_Signature_Razorstrike_Lunge_Damage", + "DamageCalculator": { + "BaseDamage": { + "Physical": 73 + } + }, + "EntityStatsOnHit": [], + "DamageEffects": { + "WorldSoundEventId": "SFX_Daggers_T2_Slash_Impact", + "LocalSoundEventId": "SFX_Daggers_T2_Slash_Impact" + }, + "AngledDamage": [ + { + "Angle": 180, + "AngleDistance": 80, + "DamageEffects": { + "Knockback": { + "Direction": { + "X": 0, + "Y": 2, + "Z": -3 + }, + "Type": "Force", + "Force": 12, + "VelocityType": "Set", + "VelocityConfig": { + "AirResistance": 0.99, + "AirResistanceMax": 0.98, + "GroundResistance": 0.94, + "GroundResistanceMax": 0.3, + "Threshold": 3.0, + "Style": "Linear" + } + }, + "WorldParticles": [ + { + "SystemId": "Impact_Critical", + "Scale": 1, + "RotationOffset": { + "Yaw": 180, + "Pitch": 0, + "Roll": 0 + } + } + ], + "LocalSoundEventId": "SFX_Daggers_T2_Slash_Impact", + "WorldSoundEventId": "SFX_Daggers_T2_Slash_Impact" + }, + "DamageCalculator": { + "BaseDamage": { + "Physical": 110 + } + } + } + ] + } + ] + }, + "Guard_Wield": { + "Interactions": [ + { + "Parent": "Weapon_Daggers_Secondary_Guard_Wield", + "StaminaCost": { + "Value": 20, + "CostType": "Damage" + } + } + ] + } + }, + "MaxDurability": 220, + "DurabilityLossOnHit": 0.1, + "Interactions": { + "Ability1": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 1 + } + ] + }, + "Ability2": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 2 + } + ] + }, + "Ability3": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 3 + } + ] + } + } +} diff --git a/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Longsword_Mithril.json b/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Longsword_Mithril.json new file mode 100644 index 0000000..255dcec --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Longsword_Mithril.json @@ -0,0 +1,167 @@ +{ + "TranslationProperties": { + "Name": "server.items.Weapon_Longsword_Mithril.name" + }, + "Categories": [ + "Items.Weapons" + ], + "Quality": "Epic", + "ItemLevel": 50, + "Model": "Items/Weapons/Longsword/Mithril.blockymodel", + "Texture": "Items/Weapons/Longsword/Mithril_Texture.png", + "PlayerAnimationsId": "Longsword", + "Interactions": { + "Primary": "Longsword_Attack", + "Ability1": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 1 + } + ] + }, + "Ability2": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 2 + } + ] + }, + "Ability3": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 3 + } + ] + } + }, + "InteractionVars": { + "Longsword_Swing_Left_Effect": { + "Interactions": [ + { + "Parent": "Longsword_Swing_Left_Effect", + "Effects": { + "WorldSoundEventId": "SFX_Longsword_Special_Swing" + } + } + ] + }, + "Longsword_Swing_Left_Damage": { + "Interactions": [ + { + "Parent": "Longsword_Swing_Left_Damage", + "DamageCalculator": { + "Type": "Absolute", + "BaseDamage": { + "Physical": 70 + }, + "RandomPercentageModifier": 0.15 + }, + "DamageEffects": { + "WorldSoundEventId": "SFX_Longsword_Special_Impact" + } + } + ] + }, + "Longsword_Swing_Right_Effect": { + "Interactions": [ + { + "Parent": "Longsword_Swing_Left_Effect", + "Effects": { + "WorldSoundEventId": "SFX_Longsword_Special_Swing" + } + } + ] + }, + "Longsword_Swing_Right_Damage": { + "Interactions": [ + { + "Parent": "Longsword_Swing_Right_Damage", + "DamageCalculator": { + "Type": "Absolute", + "BaseDamage": { + "Physical": 70 + }, + "RandomPercentageModifier": 0.15 + }, + "DamageEffects": { + "WorldSoundEventId": "SFX_Longsword_Special_Impact" + } + } + ] + }, + "Longsword_Swing_Up_Left_Effect": { + "Interactions": [ + { + "Parent": "Longsword_Swing_Left_Effect", + "Effects": { + "WorldSoundEventId": "SFX_Longsword_Special_Swing" + } + } + ] + }, + "Longsword_Swing_Up_Left_Damage": { + "Interactions": [ + { + "Parent": "Longsword_Swing_Up_Left_Damage", + "DamageCalculator": { + "Type": "Absolute", + "BaseDamage": { + "Physical": 70 + }, + "RandomPercentageModifier": 0.15 + }, + "DamageEffects": { + "WorldSoundEventId": "SFX_Longsword_Special_Impact" + } + } + ] + }, + "Longsword_Stab_Charged_Effect": "Longsword_Stab_Charged_Effect", + "Longsword_Stab_Charged_Damage": { + "Interactions": [ + { + "Parent": "Longsword_Stab_Charged_Damage", + "DamageCalculator": { + "BaseDamage": { + "Physical": 210 + }, + "Type": "Absolute", + "RandomPercentageModifier": 0.15 + }, + "DamageEffects": { + "WorldSoundEventId": "SFX_Longsword_Special_Impact" + } + } + ] + } + }, + "DroppedItemAnimation": "Items/Animations/Dropped/Dropped_Diagonal_Left.blockyanim", + "IconProperties": { + "Scale": 0.31, + "Translation": [ + -47, + -47 + ], + "Rotation": [ + 45, + 90, + 0 + ] + }, + "Icon": "Icons/ItemsGenerated/Weapon_Longsword_Mithril.png", + "Tags": { + "Type": [ + "Weapon" + ], + "Family": [ + "Longsword" + ] + }, + "MaxDurability": 160, + "DurabilityLossOnHit": 0.52, + "Weapon": {}, + "ItemSoundSetId": "ISS_Weapons_Blade_Large" +} diff --git a/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Shortbow_Cobalt.json b/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Shortbow_Cobalt.json new file mode 100644 index 0000000..c16e48d --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Shortbow_Cobalt.json @@ -0,0 +1,314 @@ +{ + "TranslationProperties": { + "Name": "server.items.Weapon_Shortbow_Cobalt.name" + }, + "Parent": "Template_Weapon_Shortbow", + "Quality": "Rare", + "Model": "Items/Weapons/Bow/Cobalt.blockymodel", + "Texture": "Items/Weapons/Bow/Cobalt_Texture.png", + "Icon": "Icons/ItemsGenerated/Weapon_Bow_Cobalt.png", + "ItemLevel": 35, + "Recipe": { + "TimeSeconds": 4, + "KnowledgeRequired": false, + "Input": [ + { + "ItemId": "Ingredient_Bar_Cobalt", + "Quantity": 10 + }, + { + "ItemId": "Ingredient_Leather_Heavy", + "Quantity": 2 + }, + { + "ItemId": "Ingredient_Fabric_Scrap_Shadoweave", + "Quantity": 3 + } + ], + "BenchRequirement": [ + { + "Type": "Crafting", + "Categories": [ + "Weapon_Bow" + ], + "Id": "Weapon_Bench", + "RequiredTierLevel": 2 + }, + { + "Type": "DiagramCrafting", + "Categories": [ + "Weapons.Bow" + ], + "Id": "Armory" + } + ] + }, + "InteractionVars": { + "Primary_Shoot_Damage_Strength_0": { + "Interactions": [ + { + "Parent": "Weapon_Shortbow_Primary_Shoot_Damage_Strength_0", + "DamageCalculator": { + "BaseDamage": { + "Projectile": 7 + } + } + } + ] + }, + "Primary_Shoot_Damage_Strength_1": { + "Interactions": [ + { + "Parent": "Weapon_Shortbow_Primary_Shoot_Damage_Strength_1", + "DamageCalculator": { + "BaseDamage": { + "Projectile": 11 + } + } + } + ] + }, + "Primary_Shoot_Damage_Strength_2": { + "Interactions": [ + { + "Parent": "Weapon_Shortbow_Primary_Shoot_Damage_Strength_2", + "DamageCalculator": { + "BaseDamage": { + "Projectile": 15 + } + } + } + ] + }, + "Primary_Shoot_Damage_Strength_3": { + "Interactions": [ + { + "Parent": "Weapon_Shortbow_Primary_Shoot_Damage_Strength_3", + "DamageCalculator": { + "BaseDamage": { + "Projectile": 20 + } + } + } + ] + }, + "Primary_Shoot_Damage_Strength_4": { + "Interactions": [ + { + "Parent": "Weapon_Shortbow_Primary_Shoot_Damage_Strength_4", + "DamageCalculator": { + "BaseDamage": { + "Projectile": 23 + } + }, + "TargetedDamage": { + "Head": { + "DamageCalculator": { + "BaseDamage": { + "Projectile": 30 + } + }, + "DamageEffects": { + "Knockback": { + "Type": "Force", + "VelocityConfig": { + "AirResistance": 0.99, + "AirResistanceMax": 0.98, + "GroundResistance": 0.94, + "GroundResistanceMax": 0.3, + "Threshold": 3.0, + "Style": "Linear" + }, + "Direction": { + "X": 0.0, + "Y": 0.5, + "Z": -1 + }, + "Force": 8, + "VelocityType": "Set" + }, + "WorldParticles": [ + { + "SystemId": "Impact_Critical", + "Scale": 1, + "RotationOffset": { + "Yaw": 180, + "Pitch": 0, + "Roll": 0 + } + } + ] + } + } + } + } + ] + }, + "Signature_Volley_Damage": { + "Interactions": [ + { + "Parent": "Weapon_Shortbow_Signature_Volley_Damage", + "DamageCalculator": { + "BaseDamage": { + "Projectile": 17 + } + } + } + ] + }, + "Guard_Wield": { + "Interactions": [ + { + "Parent": "Weapon_Shortbow_Secondary_Guard_Wield", + "StaminaCost": { + "Value": 12.22, + "CostType": "Damage" + } + } + ] + } + }, + "ItemAppearanceConditions": { + "SignatureCharges": [ + { + "Condition": [ + 1, + 100 + ], + "ConditionValueType": "Percent", + "Model": "Items/Weapons/Bow/Cobalt_Triple.blockymodel", + "Texture": "Items/Weapons/Bow/Cobalt_Texture.png", + "LocalSoundEventId": "SFX_Bow_T2_Signature_Loop_Local", + "WorldSoundEventId": "SFX_Bow_T2_Signature_Loop", + "Particles": [ + { + "SystemId": "Bow_Signature_Charge", + "TargetNodeName": "ARROW-PLACEHOLDER", + "PositionOffset": { + "X": 0.5, + "Y": 0.25, + "Z": 0 + }, + "Scale": 0.5, + "TargetEntityPart": "PrimaryItem" + }, + { + "SystemId": "Bow_Signature_Charge", + "TargetNodeName": "ARROW-PLACEHOLDER", + "PositionOffset": { + "X": 0.5, + "Y": 0, + "Z": 0 + }, + "Scale": 0.5, + "TargetEntityPart": "PrimaryItem" + }, + { + "SystemId": "Bow_Signature_Charge", + "TargetNodeName": "ARROW-PLACEHOLDER", + "PositionOffset": { + "X": 0.5, + "Y": -0.25, + "Z": 0 + }, + "Scale": 0.5, + "TargetEntityPart": "PrimaryItem" + } + ], + "ModelVFXId": "Bow_Signature_Status" + } + ], + "SignatureEnergy": [ + { + "Condition": [ + 100, + 100 + ], + "ConditionValueType": "Percent", + "Particles": [ + { + "SystemId": "Sword_Signature_Ready", + "TargetNodeName": "Handle", + "PositionOffset": { + "X": 0.8 + }, + "TargetEntityPart": "PrimaryItem" + }, + { + "SystemId": "Sword_Signature_Status_Spawn", + "TargetEntityPart": "PrimaryItem" + }, + { + "SystemId": "Bow_Signature_Status", + "TargetNodeName": "Bow-Top", + "PositionOffset": { + "X": 0.55 + }, + "TargetEntityPart": "PrimaryItem", + "Scale": 1.3 + }, + { + "SystemId": "Bow_Signature_Status", + "TargetNodeName": "Bow-Bot", + "TargetEntityPart": "PrimaryItem", + "Scale": 1.3 + } + ], + "FirstPersonParticles": [ + { + "SystemId": "Sword_Signature_Ready", + "TargetNodeName": "Handle", + "PositionOffset": { + "X": 0.8 + }, + "TargetEntityPart": "PrimaryItem" + }, + { + "SystemId": "Sword_Signature_Status_Spawn", + "TargetNodeName": "Handle", + "TargetEntityPart": "PrimaryItem", + "PositionOffset": { + "Y": 0 + } + }, + { + "SystemId": "Bow_Signature_Status_FP", + "TargetNodeName": "Bow-Top", + "PositionOffset": { + "X": 0.5 + }, + "TargetEntityPart": "PrimaryItem" + } + ] + } + ] + }, + "MaxDurability": 150, + "DurabilityLossOnHit": 0.58, + "Interactions": { + "Ability1": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 1 + } + ] + }, + "Ability2": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 2 + } + ] + }, + "Ability3": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 3 + } + ] + } + } +} diff --git a/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Staff_Mithril.json b/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Staff_Mithril.json new file mode 100644 index 0000000..f185406 --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/Server/Item/Items/Weapon_Staff_Mithril.json @@ -0,0 +1,94 @@ +{ + "TranslationProperties": { + "Name": "server.items.Weapon_Staff_Mithril.name" + }, + "Categories": [ + "Items.Weapons" + ], + "Quality": "Epic", + "ItemLevel": 50, + "Model": "Items/Weapons/Staff/Mithril.blockymodel", + "Texture": "Items/Weapons/Staff/Mithril_Texture.png", + "PlayerAnimationsId": "Staff", + "Interactions": { + "Primary": "Staff_Primary", + "Secondary": "Staff_Primary", + "Ability1": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 1 + } + ] + }, + "Ability2": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 2 + } + ] + }, + "Ability3": { + "Interactions": [ + { + "Type": "mmorpg_cast_ability", + "Slot": 3 + } + ] + } + }, + "InteractionVars": { + "Staff_Cast_Summon_Charged": { + "Interactions": [ + { + "Parent": "Staff_Cast_Summon_Charged", + "Costs": { + "Mana": 50 + } + } + ] + }, + "Staff_Cast_Summon_Cost": { + "Interactions": [ + { + "Parent": "Staff_Cast_Cost", + "StatModifiers": { + "Mana": -50 + } + } + ] + }, + "Staff_Cast_Summon_Launch": "Staff_Cast_Launch", + "Staff_Cast_Summon_Effect": "Staff_Cast_Effect", + "Staff_Cast_Summon_Fail": "Staff_Cast_Fail", + "Spear_Swing_Left_Damage": "Spear_Swing_Left_Damage", + "Spear_Swing_Right_Damage": "Spear_Swing_Right_Damage", + "Spear_Swing_Left_Effect": "Spear_Swing_Left_Effect", + "Spear_Swing_Right_Effect": "Spear_Swing_Right_Effect" + }, + "IconProperties": { + "Scale": 0.28, + "Translation": [ + -52, + -52 + ], + "Rotation": [ + 22.5, + 45, + 315 + ] + }, + "DroppedItemAnimation": "Items/Animations/Dropped/Dropped_Diagonal_Left.blockyanim", + "Icon": "Icons/ItemsGenerated/Weapon_Staff_Mithril.png", + "Tags": { + "Type": [ + "Weapon" + ], + "Family": [ + "Staff" + ] + }, + "Weapon": {}, + "ItemSoundSetId": "ISS_Weapons_Wood" +} diff --git a/Hytale/plugins/mmorpg/src/main/resources/config.json b/Hytale/plugins/mmorpg/src/main/resources/config.json new file mode 100644 index 0000000..1640ec2 --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/config.json @@ -0,0 +1,16 @@ +{ + "Debug": false, + "DefaultLevel": 1, + "MaxPlayers": 500, + "BaseXpPerLevel": 100, + "KillExperience": 10, + "Database": { + "FileName": "mmorpg.db", + "UseMonorepoRoot": true + }, + "Features": { + "Economy": true, + "Quests": false, + "Guilds": false + } +} diff --git a/Hytale/plugins/mmorpg/src/main/resources/db/migrations/001_init.sql b/Hytale/plugins/mmorpg/src/main/resources/db/migrations/001_init.sql new file mode 100644 index 0000000..39b6d8d --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/db/migrations/001_init.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS player_profiles ( + uuid TEXT PRIMARY KEY, + display_name TEXT NOT NULL, + level INTEGER NOT NULL DEFAULT 1, + experience INTEGER NOT NULL DEFAULT 0, + created_at INTEGER NOT NULL, + updated_at INTEGER NOT NULL +); diff --git a/Hytale/plugins/mmorpg/src/main/resources/db/migrations/002_rpg.sql b/Hytale/plugins/mmorpg/src/main/resources/db/migrations/002_rpg.sql new file mode 100644 index 0000000..fe00274 --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/db/migrations/002_rpg.sql @@ -0,0 +1,63 @@ +-- MMORPG progression schema: classes, powers, jobs, races, groups. +-- New columns on player_profiles. SQLite ignores duplicate ADD COLUMN guarded by +-- the migration runner (each migration is applied at most once via schema_migrations). + +ALTER TABLE player_profiles ADD COLUMN class_id TEXT; +ALTER TABLE player_profiles ADD COLUMN powers TEXT NOT NULL DEFAULT '[]'; +ALTER TABLE player_profiles ADD COLUMN jobs TEXT NOT NULL DEFAULT '[]'; +ALTER TABLE player_profiles ADD COLUMN guild_id TEXT; +ALTER TABLE player_profiles ADD COLUMN group_id TEXT; +ALTER TABLE player_profiles ADD COLUMN is_connected INTEGER NOT NULL DEFAULT 0; +ALTER TABLE player_profiles ADD COLUMN total_time_play INTEGER NOT NULL DEFAULT 0; +ALTER TABLE player_profiles ADD COLUMN last_date_connected INTEGER NOT NULL DEFAULT 0; +ALTER TABLE player_profiles ADD COLUMN date_creation INTEGER NOT NULL DEFAULT 0; +ALTER TABLE player_profiles ADD COLUMN money INTEGER NOT NULL DEFAULT 0; +ALTER TABLE player_profiles ADD COLUMN race_id TEXT NOT NULL DEFAULT 'human'; + +-- Backfill creation date for profiles that predate this migration. +UPDATE player_profiles SET date_creation = created_at WHERE date_creation = 0; + +-- Reference tables (definitions persisted for inspection / future editing). +CREATE TABLE IF NOT EXISTS classes ( + id TEXT PRIMARY KEY, + display_name TEXT NOT NULL, + description TEXT NOT NULL DEFAULT '', + weapons TEXT NOT NULL DEFAULT '[]' +); + +CREATE TABLE IF NOT EXISTS powers ( + id TEXT PRIMARY KEY, + display_name TEXT NOT NULL, + description TEXT NOT NULL DEFAULT '', + passive INTEGER NOT NULL DEFAULT 1 +); + +CREATE TABLE IF NOT EXISTS jobs ( + id TEXT PRIMARY KEY, + display_name TEXT NOT NULL, + description TEXT NOT NULL DEFAULT '' +); + +CREATE TABLE IF NOT EXISTS races ( + id TEXT PRIMARY KEY, + display_name TEXT NOT NULL, + description TEXT NOT NULL DEFAULT '', + xp_multiplier REAL NOT NULL DEFAULT 1.0 +); + +-- Groups (parties): shared XP between members. +CREATE TABLE IF NOT EXISTS groups ( + id TEXT PRIMARY KEY, + owner_uuid TEXT NOT NULL, + created_at INTEGER NOT NULL +); + +CREATE TABLE IF NOT EXISTS group_members ( + group_id TEXT NOT NULL, + player_uuid TEXT NOT NULL, + joined_at INTEGER NOT NULL, + PRIMARY KEY (group_id, player_uuid), + FOREIGN KEY (group_id) REFERENCES groups(id) ON DELETE CASCADE +); + +CREATE INDEX IF NOT EXISTS idx_group_members_player ON group_members(player_uuid); diff --git a/Hytale/plugins/mmorpg/src/main/resources/db/migrations/003_web_password.sql b/Hytale/plugins/mmorpg/src/main/resources/db/migrations/003_web_password.sql new file mode 100644 index 0000000..4460180 --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/db/migrations/003_web_password.sql @@ -0,0 +1,2 @@ +-- Web login: password set in-game via /mmorpg password +ALTER TABLE player_profiles ADD COLUMN password_hash TEXT; diff --git a/Hytale/plugins/mmorpg/src/main/resources/manifest.json b/Hytale/plugins/mmorpg/src/main/resources/manifest.json new file mode 100644 index 0000000..275f1e8 --- /dev/null +++ b/Hytale/plugins/mmorpg/src/main/resources/manifest.json @@ -0,0 +1,18 @@ +{ + "Group": "com.disklexar", + "Name": "MMORPG", + "Version": "0.4.7", + "Description": "Serveur MMORPG Hytale — progression, persistance et systèmes sociaux", + "Authors": [ + { + "Name": "Disklexar" + } + ], + "Website": "https://github.com/disklexar/hytale-mmorpg", + "DisabledByDefault": false, + "IncludesAssetPack": true, + "Dependencies": {}, + "OptionalDependencies": {}, + "ServerVersion": "*", + "Main": "com.disklexar.mmorpg.MmorpgPlugin" +} \ No newline at end of file diff --git a/settings.gradle.kts b/Hytale/settings.gradle.kts similarity index 100% rename from settings.gradle.kts rename to Hytale/settings.gradle.kts diff --git a/Hytale/src/main/resources/manifest.json b/Hytale/src/main/resources/manifest.json new file mode 100644 index 0000000..00d98a8 --- /dev/null +++ b/Hytale/src/main/resources/manifest.json @@ -0,0 +1,9 @@ +{ + "Group": "ScaffoldIt", + "Name": "Hytalemmorpg", + "Version": "0.0.0", + "Authors": [], + "DisabledByDefault": false, + "IncludesAssetPack": false, + "Main": "scaffoldit.hytalemmorpg.Hytalemmorpg" +} \ No newline at end of file diff --git a/start-server.sh b/Hytale/start-server.sh similarity index 100% rename from start-server.sh rename to Hytale/start-server.sh diff --git a/README.md b/README.md index 706434b..0c0dfbe 100644 --- a/README.md +++ b/README.md @@ -1,163 +1,60 @@ -# Hytale MMORPG +# Disklexar Hytale Server -Plugin serveur Hytale pour un MMORPG persistant : profils joueurs, progression et fondations modulaires pour l'économie, les quêtes et les guildes. +Monorepo du serveur MMORPG Hytale **Disklexar** : serveur de jeu, plugin persistant et futur site web. -## Prérequis +## Structure du dépôt -- **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)) +``` +hytaleServer/ +├── Hytale/ # Serveur Hytale + plugin MMORPG (Gradle, devserver, scripts) +│ ├── plugins/mmorpg/ # Code source du plugin +│ ├── start-server.sh +│ └── docs/ # Documentation technique du plugin +├── Webapp/ # Dashboard Node.js (stats, joueurs, profils) +├── mmorpg.db # Base SQLite partagée (créée au runtime, ignorée par Git) +├── LICENSE +└── CONTRIBUTING.md +``` + +## Composants + +| Dossier | Rôle | +|---------|------| +| **[Hytale/](Hytale/)** | Serveur de développement ScaffoldIt, plugin MMORPG (profils, classes, progression, UI). Voir [Hytale/README.md](Hytale/README.md). | +| **[Webapp/](Webapp/)** | Dashboard Node.js : stats serveur, liste joueurs, profils (lit `mmorpg.db`). | +| **`mmorpg.db`** | Base SQLite à la racine du dépôt, utilisée par le plugin MMORPG en dev (détection automatique du monorepo). | ## Démarrage rapide ```bash -# 1. Indiquer où Hytale est installé (launcher officiel) +cd Hytale cp hytale.properties.example hytale.properties -# Éditer hytale.home_path (voir exemples dans le fichier) +# Éditer hytale.home_path (installation Hytale via le launcher) -# 2. Compiler puis lancer le serveur de dev (Java 25 forcé) ./start-server.sh ``` -Si le serveur a déjà planté sans assets, réinitialisez le monde de dev : +Prérequis : **JDK 25+**, installation **Hytale** (assets via le launcher). + +### Webapp ```bash -HYTALE_RESET_DEVSERVER=1 ./start-server.sh +cd Webapp +npm install +npm start ``` -Ou manuellement : - -```bash -# Compiler le plugin (JAR avec SQLite + Gson embarqués) -JAVA_HOME=/usr/lib/jvm/java-25-openjdk ./gradlew build - -# Lancer le serveur de développement -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 [classe]` | Gérer votre classe | -| `/mmorpg power [pouvoir]` | Gérer vos pouvoirs | -| `/mmorpg job [metier]` | Gérer vos métiers | -| `/mmorpg group [joueur]` | Gérer votre groupe | -| `/mmorpg ability <1\|2\|3>` | Utiliser une capacité de classe | -| 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 - `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 ` 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 `assetpack/README.md` pour brancher un asset `.ui`). - -## Configuration - -Fichier `config.json` (valeurs par défaut dans `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` | Fichier SQLite (`mmorpg.db`) | -| `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 - -`player_profiles` ajoute : `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 dépendance : `classes`, `powers`, `jobs`, `races`, `groups`, `group_members`. -Les migrations sont versionnées via `schema_migrations` (voir `db/migrations/`). - -## Structure du projet - -``` -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, vue d'infos -├── persistence/ # SQLite (migrations versionnées, repositories) -├── command/ # Commandes /mmorpg (class, power, job, group, ability, info, menu) -├── events/ # Connexion / déconnexion, filtre paquets Ability 1/2/3 -├── interaction/ # mmorpg_cast_ability (interaction native asset pack) -├── progression/ # XP et niveaux (multiplicateurs de race) -├── economy/ # Monnaie (money) -├── rpg/ # clazz (classes) · power · job · race · group -├── combat/ # Capacités, état de combat, effets passifs, planificateur -│ └── system/ # Systèmes ECS : dégâts, morts/kills, casse de bloc -├── ui/ # AbilityBarHud, PlayerMenuPage, PlayerInfoPage -├── quest/ # Stub (M3) -└── social/ # Stub (M4) -``` +Dashboard sur [http://localhost:3000](http://localhost:3000) — nécessite `mmorpg.db` à la racine du dépôt. ## 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) +- [Plugin MMORPG — guide complet](Hytale/README.md) +- [Architecture](Hytale/docs/ARCHITECTURE.md) +- [Développement](Hytale/docs/DEVELOPMENT.md) +- [Feuille de route](Hytale/docs/ROADMAP.md) +- [Interface utilisateur](Hytale/docs/README-UI.md) - [Contribution](CONTRIBUTING.md) -### Custom UI (Hytale) - -Documentation officielle et guides communautaires utiles pour les assets `.ui` et les pages serveur : - -- [Custom UI — vue d'ensemble](https://hytalemodding.dev/en/docs/official-documentation/custom-ui) (architecture `UICommandBuilder`, HUD vs pages, sélecteurs `#Id.Propriété`) -- [Layout](https://hytalemodding.dev/en/docs/official-documentation/custom-ui/layout) (`Anchor`, `Padding`, `LayoutMode`, `FlexWeight`) -- [Common Styling](https://hytalemodding.dev/en/docs/official-documentation/custom-ui/common-styling) (`Common.ui`, styles partagés) -- [Guide plugin UI](https://hytalemodding.dev/en/docs/guides/plugin/ui) (emplacement des fichiers, `IncludesAssetPack`, diagnostic client) - ## Licence MIT — voir [LICENSE](LICENSE). diff --git a/Webapp/.env.example b/Webapp/.env.example new file mode 100644 index 0000000..bcab940 --- /dev/null +++ b/Webapp/.env.example @@ -0,0 +1,5 @@ +PORT=3000 +# Chemin vers la base SQLite du plugin MMORPG (relatif à Webapp/ ou absolu) +DB_PATH=../mmorpg.db +# Secret pour les sessions de connexion (changez en production) +SESSION_SECRET=change-me-in-production diff --git a/Webapp/.gitignore b/Webapp/.gitignore new file mode 100644 index 0000000..03c5ccf --- /dev/null +++ b/Webapp/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +.env +npm-debug.log* diff --git a/Webapp/README.md b/Webapp/README.md new file mode 100644 index 0000000..36f90bb --- /dev/null +++ b/Webapp/README.md @@ -0,0 +1,59 @@ +# Webapp Disklexar + +Tableau de bord Node.js pour consulter les données du serveur MMORPG Hytale (base SQLite `mmorpg.db`). + +## Pages + +| Route | Description | +|-------|-------------| +| `/` | Dashboard — joueurs connectés, statistiques globales | +| `/players` | Liste de tous les joueurs (clic → profil) | +| `/players/:uuid` | Profil joueur (données actuelles + extensions à venir) | +| `/market` | Marché — à implémenter | +| `/profile` | **Mon profil** — connexion pseudo / mot de passe, stats personnelles | + +## Prérequis + +- **Node.js 20+** +- Base **`mmorpg.db`** à la racine du monorepo (générée par le plugin Hytale) + +## Installation + +```bash +cd Webapp +npm install +cp .env.example .env +``` + +## Lancement + +```bash +npm start +# ou en mode watch : +npm run dev +``` + +Site accessible sur [http://localhost:3000](http://localhost:3000). + +## Configuration + +| Variable | Défaut | Description | +|----------|--------|-------------| +| `PORT` | `3000` | Port HTTP | +| `DB_PATH` | `../mmorpg.db` | Chemin vers la base SQLite (relatif à `Webapp/` ou absolu) | + +| `SESSION_SECRET` | `change-me-in-production` | Secret des cookies de session | + +## Connexion joueur + +1. Rejoindre le serveur Hytale (création automatique du profil) +2. En jeu : `/mmorpg password MonMotDePasse` (6–72 caractères) +3. Sur le site : **Mon profil** → pseudo + mot de passe + +Pour modifier le mot de passe, réutilisez la commande en jeu. + +## Stack + +- [Express](https://expressjs.com/) — serveur HTTP +- [EJS](https://ejs.co/) — templates +- [better-sqlite3](https://github.com/WiseLibs/better-sqlite3) — lecture SQLite en lecture seule diff --git a/Webapp/package-lock.json b/Webapp/package-lock.json new file mode 100644 index 0000000..5f7c9b5 --- /dev/null +++ b/Webapp/package-lock.json @@ -0,0 +1,1348 @@ +{ + "name": "disklexar-web", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "disklexar-web", + "version": "0.1.0", + "dependencies": { + "better-sqlite3": "^11.8.1", + "dotenv": "^16.4.7", + "ejs": "^3.1.10", + "express": "^4.21.2" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/better-sqlite3": { + "version": "11.10.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.10.0.tgz", + "integrity": "sha512-EwhOpyXiOEL/lKzHz9AW1msWFNzGc/z+LzeB3/jnFJpxu+th2yqvzsSWas1v9jgs9+xiXJcD5A8CJxAG2TaghQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.1" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/express": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.5", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.15.1", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" + }, + "node_modules/filelist": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-abi": { + "version": "3.92.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.92.0.tgz", + "integrity": "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/qs": { + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", + "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + } + } +} diff --git a/Webapp/package.json b/Webapp/package.json new file mode 100644 index 0000000..2e6f9f6 --- /dev/null +++ b/Webapp/package.json @@ -0,0 +1,21 @@ +{ + "name": "disklexar-web", + "version": "0.1.0", + "description": "Tableau de bord web du serveur MMORPG Hytale Disklexar", + "main": "server.js", + "scripts": { + "start": "node server.js", + "dev": "node --watch server.js" + }, + "engines": { + "node": ">=20" + }, + "dependencies": { + "bcrypt": "^5.1.1", + "better-sqlite3": "^11.8.1", + "dotenv": "^16.4.7", + "ejs": "^3.1.10", + "express": "^4.21.2", + "express-session": "^1.18.1" + } +} diff --git a/Webapp/public/css/style.css b/Webapp/public/css/style.css new file mode 100644 index 0000000..41c94c7 --- /dev/null +++ b/Webapp/public/css/style.css @@ -0,0 +1,520 @@ +:root { + --bg: #0f1419; + --bg-elevated: #171d25; + --bg-panel: #1c2430; + --border: #2a3544; + --text: #e8edf4; + --text-muted: #8b9cb0; + --accent: #5eb3ff; + --accent-soft: rgba(94, 179, 255, 0.12); + --success: #4ade80; + --warning: #fbbf24; + --danger: #f87171; + --radius: 12px; + --shadow: 0 8px 32px rgba(0, 0, 0, 0.35); + --font: "Segoe UI", system-ui, -apple-system, sans-serif; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + font-family: var(--font); + background: linear-gradient(135deg, #0b1015 0%, #121820 50%, #0f1419 100%); + color: var(--text); + min-height: 100vh; +} + +code { + font-family: ui-monospace, monospace; + font-size: 0.9em; + background: rgba(255, 255, 255, 0.06); + padding: 0.15em 0.4em; + border-radius: 4px; +} + +.layout { + display: grid; + grid-template-columns: 240px 1fr; + min-height: 100vh; +} + +.sidebar { + background: var(--bg-elevated); + border-right: 1px solid var(--border); + padding: 1.5rem 1rem; + display: flex; + flex-direction: column; + gap: 2rem; +} + +.brand { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0 0.5rem; +} + +.brand-mark { + width: 42px; + height: 42px; + border-radius: 10px; + background: linear-gradient(135deg, var(--accent), #3d7fd6); + display: grid; + place-items: center; + font-weight: 700; + font-size: 1.2rem; +} + +.brand small { + display: block; + color: var(--text-muted); + font-size: 0.75rem; +} + +.nav { + display: flex; + flex-direction: column; + gap: 0.35rem; +} + +.nav-link { + color: var(--text-muted); + text-decoration: none; + padding: 0.65rem 0.85rem; + border-radius: 8px; + transition: background 0.15s, color 0.15s; +} + +.nav-link:hover, +.nav-link.active { + background: var(--accent-soft); + color: var(--text); +} + +.sidebar-footer { + margin-top: auto; + font-size: 0.85rem; + color: var(--text-muted); + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0 0.5rem; +} + +.main { + padding: 2rem; + max-width: 1200px; +} + +.page-header { + margin-bottom: 1.75rem; +} + +.page-header h1 { + margin: 0 0 0.35rem; + font-size: 1.85rem; +} + +.subtitle { + margin: 0; + color: var(--text-muted); +} + +.alert { + padding: 0.85rem 1rem; + border-radius: var(--radius); + margin-bottom: 1.5rem; + border: 1px solid transparent; +} + +.alert-warning { + background: rgba(251, 191, 36, 0.1); + border-color: rgba(251, 191, 36, 0.25); + color: #fde68a; +} + +.stats-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + gap: 1rem; + margin-bottom: 1.5rem; +} + +.stat-card { + background: var(--bg-panel); + border: 1px solid var(--border); + border-radius: var(--radius); + padding: 1.1rem 1.25rem; + box-shadow: var(--shadow); +} + +.stat-label { + display: block; + color: var(--text-muted); + font-size: 0.85rem; + margin-bottom: 0.35rem; +} + +.stat-value { + font-size: 1.75rem; + line-height: 1.1; +} + +.stat-value.accent { + color: var(--success); +} + +.panel { + background: var(--bg-panel); + border: 1px solid var(--border); + border-radius: var(--radius); + padding: 1.25rem; + margin-bottom: 1.5rem; + box-shadow: var(--shadow); +} + +.panel-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 1rem; +} + +.panel-header h2 { + margin: 0; + font-size: 1.1rem; +} + +.badge { + background: var(--accent-soft); + color: var(--accent); + padding: 0.2rem 0.55rem; + border-radius: 999px; + font-size: 0.85rem; +} + +.table { + width: 100%; + border-collapse: collapse; +} + +.table th, +.table td { + text-align: left; + padding: 0.75rem 0.65rem; + border-bottom: 1px solid var(--border); +} + +.table th { + color: var(--text-muted); + font-size: 0.8rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.04em; +} + +.table tbody tr:last-child td { + border-bottom: none; +} + +.table-clickable tbody tr { + cursor: pointer; + transition: background 0.12s; +} + +.table-clickable tbody tr:hover { + background: rgba(255, 255, 255, 0.03); +} + +.player-name { + display: flex; + align-items: center; + gap: 0.45rem; + font-weight: 600; +} + +.muted { + color: var(--text-muted); + font-size: 0.82rem; +} + +.status-dot { + width: 8px; + height: 8px; + border-radius: 50%; + display: inline-block; + flex-shrink: 0; +} + +.status-dot.online { + background: var(--success); + box-shadow: 0 0 8px rgba(74, 222, 128, 0.6); +} + +.status-dot.offline { + background: #64748b; +} + +.status-dot.inline { + width: 7px; + height: 7px; +} + +.tag { + display: inline-block; + padding: 0.2rem 0.55rem; + border-radius: 999px; + font-size: 0.78rem; + font-weight: 600; +} + +.tag-online { + background: rgba(74, 222, 128, 0.15); + color: var(--success); +} + +.tag-offline { + background: rgba(100, 116, 139, 0.2); + color: #94a3b8; +} + +.link { + color: var(--accent); + text-decoration: none; +} + +.link:hover { + text-decoration: underline; +} + +.empty { + color: var(--text-muted); + margin: 0; +} + +.profile-layout { + display: grid; + gap: 1.5rem; +} + +.profile-head { + display: flex; + gap: 1rem; + align-items: center; + margin-bottom: 1.5rem; +} + +.avatar { + width: 64px; + height: 64px; + border-radius: 16px; + background: linear-gradient(135deg, #334155, #1e293b); + display: grid; + place-items: center; + font-size: 1.5rem; + font-weight: 700; +} + +.detail-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + gap: 1rem; + margin: 0; +} + +.detail-grid div { + background: rgba(0, 0, 0, 0.15); + border-radius: 8px; + padding: 0.85rem; +} + +.detail-grid dt { + margin: 0 0 0.25rem; + font-size: 0.78rem; + text-transform: uppercase; + letter-spacing: 0.04em; + color: var(--text-muted); +} + +.detail-grid dd { + margin: 0; + font-size: 1.05rem; + font-weight: 600; +} + +.chip-list { + margin-top: 1rem; + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + align-items: center; +} + +.chip-label { + color: var(--text-muted); + font-size: 0.85rem; + margin-right: 0.25rem; +} + +.chip { + background: var(--accent-soft); + color: var(--accent); + padding: 0.25rem 0.65rem; + border-radius: 999px; + font-size: 0.85rem; +} + +.coming-soon { + border-style: dashed; +} + +.coming-soon-page, +.error-page { + text-align: center; + padding: 3rem 2rem; +} + +.coming-soon-icon { + font-size: 2.5rem; + margin-bottom: 1rem; +} + +.btn { + display: inline-block; + margin-top: 1.25rem; + background: var(--accent); + color: #0b1015; + text-decoration: none; + padding: 0.65rem 1.1rem; + border-radius: 8px; + font-weight: 600; +} + +.btn:hover { + filter: brightness(1.08); +} + +.back-link { + margin-top: -0.5rem; +} + +.group-info { + margin-top: 1rem; + color: var(--text-muted); +} + +.auth-panel { + max-width: 480px; +} + +.auth-form { + display: flex; + flex-direction: column; + gap: 1rem; + margin-bottom: 1.5rem; +} + +.auth-form label { + display: flex; + flex-direction: column; + gap: 0.4rem; + font-size: 0.9rem; + color: var(--text-muted); +} + +.auth-form input { + background: var(--bg); + border: 1px solid var(--border); + border-radius: 8px; + color: var(--text); + padding: 0.7rem 0.85rem; + font-size: 1rem; +} + +.auth-form input:focus { + outline: none; + border-color: var(--accent); + box-shadow: 0 0 0 3px var(--accent-soft); +} + +.btn-block { + width: 100%; + margin-top: 0.25rem; + border: none; + cursor: pointer; + font-size: 1rem; +} + +.btn-secondary { + background: transparent; + color: var(--text); + border: 1px solid var(--border); + text-decoration: none; + padding: 0.65rem 1.1rem; + border-radius: 8px; + font-weight: 600; + cursor: pointer; +} + +.btn-secondary:hover { + background: rgba(255, 255, 255, 0.04); +} + +.profile-actions { + display: flex; + align-items: center; + gap: 1rem; + margin-bottom: 1.25rem; +} + +.auth-help h2 { + margin: 0 0 0.5rem; + font-size: 1rem; +} + +.auth-help p { + margin: 0 0 0.75rem; + color: var(--text-muted); +} + +.auth-help pre { + margin: 0 0 0.75rem; + padding: 0.85rem 1rem; + background: rgba(0, 0, 0, 0.25); + border-radius: 8px; + overflow-x: auto; +} + +.alert-error { + background: rgba(248, 113, 113, 0.1); + border-color: rgba(248, 113, 113, 0.25); + color: #fecaca; +} + +@media (max-width: 768px) { + .layout { + grid-template-columns: 1fr; + } + + .sidebar { + border-right: none; + border-bottom: 1px solid var(--border); + } + + .nav { + flex-direction: row; + flex-wrap: wrap; + } + + .main { + padding: 1rem; + } + + .table { + display: block; + overflow-x: auto; + } +} diff --git a/Webapp/server.js b/Webapp/server.js new file mode 100644 index 0000000..c96b2e0 --- /dev/null +++ b/Webapp/server.js @@ -0,0 +1,259 @@ +require("dotenv").config(); + +const express = require("express"); +const session = require("express-session"); +const path = require("path"); +const db = require("./src/db"); +const auth = require("./src/auth"); +const labels = require("./src/labels"); +const fmt = require("./src/format"); + +const app = express(); +const PORT = process.env.PORT || 3000; + +app.set("view engine", "ejs"); +app.set("views", path.join(__dirname, "views")); +app.use(express.static(path.join(__dirname, "public"))); +app.use(express.urlencoded({ extended: false })); + +app.use( + session({ + secret: process.env.SESSION_SECRET || "change-me-in-production", + resave: false, + saveUninitialized: false, + cookie: { + httpOnly: true, + maxAge: 7 * 24 * 60 * 60 * 1000, + sameSite: "lax", + }, + }), +); + +app.use((req, res, next) => { + res.locals.nav = [ + { href: "/", label: "Dashboard", key: "dashboard" }, + { href: "/players", label: "Joueurs", key: "players" }, + { href: "/market", label: "Marché", key: "market" }, + { href: "/profile", label: "Mon profil", key: "profile" }, + ]; + res.locals.fmt = fmt; + res.locals.auth = auth; + res.locals.dbStatus = db.getDbStatus(); + res.locals.sessionUser = req.session.playerUuid + ? { + uuid: req.session.playerUuid, + displayName: req.session.displayName, + } + : null; + next(); +}); + +function enrichPlayer(player) { + if (!player) return null; + + const classLabel = labels.labelClass( + player.class_id, + db.getReferenceLabel("classes", player.class_id), + ); + const raceLabel = labels.labelRace( + player.race_id, + db.getReferenceLabel("races", player.race_id), + ); + const jobs = labels.parseJsonArray(player.jobs).map(labels.labelJob); + const powers = labels.parseJsonArray(player.powers).map(labels.labelPower); + + return { + ...player, + classLabel, + raceLabel, + jobs, + powers, + isOnline: player.is_connected === 1, + }; +} + +function requireLogin(req, res, next) { + if (!req.session.playerUuid) { + return res.redirect("/profile"); + } + next(); +} + +app.get("/", (req, res) => { + const stats = db.getDashboardStats(); + const onlinePlayers = db.getOnlinePlayers().map(enrichPlayer); + const recentPlayers = db.getRecentPlayers().map(enrichPlayer); + + res.render("index", { + page: "dashboard", + title: "Dashboard", + stats, + onlinePlayers, + recentPlayers, + }); +}); + +app.get("/players", (req, res) => { + const players = db.getAllPlayers().map(enrichPlayer); + + res.render("players/list", { + page: "players", + title: "Joueurs", + players, + }); +}); + +app.get("/players/:uuid", (req, res) => { + const player = enrichPlayer(db.getPlayerByUuid(req.params.uuid)); + if (!player) { + return res.status(404).render("error", { + page: "players", + title: "Joueur introuvable", + message: "Ce joueur n'existe pas dans la base de données.", + }); + } + + const group = db.getGroupForPlayer(player.uuid); + + res.render("players/profile", { + page: "players", + title: player.display_name, + player, + group, + comingSoon: true, + isOwner: req.session.playerUuid === player.uuid, + }); +}); + +app.get("/market", (req, res) => { + res.render("coming-soon", { + page: "market", + title: "Marché", + heading: "Marché du serveur", + description: + "La place de marché permettra bientôt d'échanger des objets et consulter les annonces entre joueurs.", + }); +}); + +app.get("/profile", (req, res) => { + if (req.session.playerUuid) { + const player = enrichPlayer(db.getPlayerByUuid(req.session.playerUuid)); + if (!player) { + req.session.destroy(() => { + res.redirect("/profile"); + }); + return; + } + + const group = db.getGroupForPlayer(player.uuid); + + return res.render("profile/account", { + page: "profile", + title: "Mon profil", + player, + group, + }); + } + + res.render("profile/login", { + page: "profile", + title: "Connexion", + error: null, + pseudo: "", + needsMigration: db.getDbStatus().exists && !db.hasPasswordColumn(), + }); +}); + +app.post("/profile/login", async (req, res) => { + const pseudo = (req.body.pseudo || "").trim(); + const password = req.body.password || ""; + + if (!pseudo || !password) { + return res.status(400).render("profile/login", { + page: "profile", + title: "Connexion", + error: "Pseudo et mot de passe requis.", + pseudo, + needsMigration: db.getDbStatus().exists && !db.hasPasswordColumn(), + }); + } + + if (!db.getDbStatus().exists) { + return res.status(503).render("profile/login", { + page: "profile", + title: "Connexion", + error: "Base de données indisponible.", + pseudo, + needsMigration: false, + }); + } + + if (!db.hasPasswordColumn()) { + return res.status(503).render("profile/login", { + page: "profile", + title: "Connexion", + error: "Migration web manquante. Redémarrez le serveur Hytale pour mettre à jour la base.", + pseudo, + needsMigration: true, + }); + } + + const record = db.getPlayerAuthByDisplayName(pseudo); + if (!record) { + return res.status(401).render("profile/login", { + page: "profile", + title: "Connexion", + error: "Pseudo introuvable. Connectez-vous d'abord au serveur Hytale pour créer votre profil.", + pseudo, + needsMigration: false, + }); + } + + if (!record.password_hash) { + return res.status(401).render("profile/login", { + page: "profile", + title: "Connexion", + error: "Aucun mot de passe défini. Utilisez /mmorpg password en jeu.", + pseudo, + needsMigration: false, + }); + } + + const valid = await auth.verifyPassword(password, record.password_hash); + if (!valid) { + return res.status(401).render("profile/login", { + page: "profile", + title: "Connexion", + error: "Mot de passe incorrect.", + pseudo, + needsMigration: false, + }); + } + + req.session.playerUuid = record.uuid; + req.session.displayName = record.display_name; + res.redirect("/profile"); +}); + +app.post("/profile/logout", requireLogin, (req, res) => { + req.session.destroy(() => { + res.redirect("/profile"); + }); +}); + +app.use((req, res) => { + res.status(404).render("error", { + page: "", + title: "Page introuvable", + message: "La page demandée n'existe pas.", + }); +}); + +app.listen(PORT, () => { + const status = db.getDbStatus(); + console.log(`Orion.ovh Web → http://localhost:${PORT}`); + if (!status.exists) { + console.warn(`Base SQLite introuvable : ${status.path}`); + console.warn("Lancez le serveur Hytale pour créer mmorpg.db à la racine du monorepo."); + } +}); diff --git a/Webapp/src/auth.js b/Webapp/src/auth.js new file mode 100644 index 0000000..0286f63 --- /dev/null +++ b/Webapp/src/auth.js @@ -0,0 +1,26 @@ +const bcrypt = require("bcrypt"); + +const MIN_PASSWORD_LENGTH = 6; +const MAX_PASSWORD_LENGTH = 72; + +async function verifyPassword(plainPassword, passwordHash) { + if (!passwordHash) { + return false; + } + return bcrypt.compare(plainPassword, passwordHash); +} + +function validatePasswordLength(password) { + if (!password || typeof password !== "string") { + return false; + } + const length = password.length; + return length >= MIN_PASSWORD_LENGTH && length <= MAX_PASSWORD_LENGTH; +} + +module.exports = { + verifyPassword, + validatePasswordLength, + MIN_PASSWORD_LENGTH, + MAX_PASSWORD_LENGTH, +}; diff --git a/Webapp/src/db.js b/Webapp/src/db.js new file mode 100644 index 0000000..7f70d09 --- /dev/null +++ b/Webapp/src/db.js @@ -0,0 +1,189 @@ +const Database = require("better-sqlite3"); +const path = require("path"); +const fs = require("fs"); + +const dbPath = path.resolve( + __dirname, + "..", + process.env.DB_PATH || "../mmorpg.db", +); + +let db = null; + +function getDb() { + if (!fs.existsSync(dbPath)) { + return null; + } + if (!db) { + db = new Database(dbPath, { readonly: true, fileMustExist: true }); + } + return db; +} + +function getDbStatus() { + return { + path: dbPath, + exists: fs.existsSync(dbPath), + }; +} + +function queryAll(sql, params = []) { + const connection = getDb(); + if (!connection) { + return []; + } + return connection.prepare(sql).all(...params); +} + +function queryOne(sql, params = []) { + const connection = getDb(); + if (!connection) { + return null; + } + return connection.prepare(sql).get(...params) ?? null; +} + +function getDashboardStats() { + const connection = getDb(); + if (!connection) { + return { + totalPlayers: 0, + onlinePlayers: 0, + totalMoney: 0, + averageLevel: 0, + totalGroups: 0, + }; + } + + const row = queryOne(` + SELECT + COUNT(*) AS totalPlayers, + COALESCE(SUM(CASE WHEN is_connected = 1 THEN 1 ELSE 0 END), 0) AS onlinePlayers, + COALESCE(SUM(money), 0) AS totalMoney, + COALESCE(AVG(level), 0) AS averageLevel + FROM player_profiles + `); + + const groups = queryOne(`SELECT COUNT(*) AS count FROM groups`); + + return { + totalPlayers: row.totalPlayers, + onlinePlayers: row.onlinePlayers, + totalMoney: row.totalMoney, + averageLevel: Math.round(row.averageLevel * 10) / 10, + totalGroups: groups?.count ?? 0, + }; +} + +function getOnlinePlayers() { + return queryAll(` + SELECT uuid, display_name, level, class_id, race_id, money, last_date_connected + FROM player_profiles + WHERE is_connected = 1 + ORDER BY display_name COLLATE NOCASE ASC + `); +} + +function getRecentPlayers(limit = 8) { + return queryAll( + ` + SELECT uuid, display_name, level, is_connected, last_date_connected + FROM player_profiles + ORDER BY last_date_connected DESC + LIMIT ? + `, + [limit], + ); +} + +function getAllPlayers() { + return queryAll(` + SELECT + uuid, + display_name, + level, + experience, + class_id, + race_id, + money, + is_connected, + total_time_play, + last_date_connected, + date_creation + FROM player_profiles + ORDER BY display_name COLLATE NOCASE ASC + `); +} + +function getPlayerByUuid(uuid) { + return queryOne( + ` + SELECT + uuid, display_name, level, experience, class_id, powers, jobs, + guild_id, group_id, is_connected, total_time_play, last_date_connected, + date_creation, money, race_id, created_at, updated_at + FROM player_profiles + WHERE uuid = ? + `, + [uuid], + ); +} + +function getPlayerAuthByDisplayName(displayName) { + return queryOne( + ` + SELECT uuid, display_name, password_hash + FROM player_profiles + WHERE display_name = ? COLLATE NOCASE + LIMIT 1 + `, + [displayName.trim()], + ); +} + +function hasPasswordColumn() { + const connection = getDb(); + if (!connection) { + return false; + } + const columns = connection + .prepare("PRAGMA table_info(player_profiles)") + .all(); + return columns.some((column) => column.name === "password_hash"); +} + +function getGroupForPlayer(uuid) { + return queryOne( + ` + SELECT g.id, g.owner_uuid, g.created_at + FROM group_members gm + JOIN groups g ON g.id = gm.group_id + WHERE gm.player_uuid = ? + `, + [uuid], + ); +} + +function getReferenceLabel(table, id) { + if (!id) { + return null; + } + const row = queryOne( + `SELECT display_name FROM ${table} WHERE id = ?`, + [id], + ); + return row?.display_name ?? null; +} + +module.exports = { + getDbStatus, + getDashboardStats, + getOnlinePlayers, + getRecentPlayers, + getAllPlayers, + getPlayerByUuid, + getPlayerAuthByDisplayName, + hasPasswordColumn, + getGroupForPlayer, + getReferenceLabel, +}; diff --git a/Webapp/src/format.js b/Webapp/src/format.js new file mode 100644 index 0000000..9153fd8 --- /dev/null +++ b/Webapp/src/format.js @@ -0,0 +1,36 @@ +function formatTimestamp(ms) { + if (!ms || ms <= 0) { + return "—"; + } + return new Intl.DateTimeFormat("fr-FR", { + dateStyle: "medium", + timeStyle: "short", + }).format(new Date(ms)); +} + +function formatDuration(seconds) { + if (!seconds || seconds <= 0) { + return "0 min"; + } + const hours = Math.floor(seconds / 3600); + const minutes = Math.floor((seconds % 3600) / 60); + if (hours === 0) { + return `${minutes} min`; + } + return `${hours} h ${minutes} min`; +} + +function formatMoney(value) { + return new Intl.NumberFormat("fr-FR").format(value ?? 0); +} + +function formatNumber(value) { + return new Intl.NumberFormat("fr-FR").format(value ?? 0); +} + +module.exports = { + formatTimestamp, + formatDuration, + formatMoney, + formatNumber, +}; diff --git a/Webapp/src/labels.js b/Webapp/src/labels.js new file mode 100644 index 0000000..8231d88 --- /dev/null +++ b/Webapp/src/labels.js @@ -0,0 +1,58 @@ +const CLASS_LABELS = { + knight: "Chevalier", + archer: "Archer", + mage: "Mage", + assassin: "Assassin", +}; + +const RACE_LABELS = { + human: "Humain", +}; + +const JOB_LABELS = { + monster_slayer: "Tueur de monstres", + miner: "Mineur", +}; + +const POWER_LABELS = { + sprinter: "Sprinteur", + resilient: "Résilient", +}; + +function labelClass(id, dbLabel) { + if (dbLabel) return dbLabel; + if (!id) return "Aucune"; + return CLASS_LABELS[id] ?? id; +} + +function labelRace(id, dbLabel) { + if (dbLabel) return dbLabel; + if (!id) return "Inconnue"; + return RACE_LABELS[id] ?? id; +} + +function labelJob(id) { + return JOB_LABELS[id] ?? id; +} + +function labelPower(id) { + return POWER_LABELS[id] ?? id; +} + +function parseJsonArray(value) { + if (!value) return []; + try { + const parsed = JSON.parse(value); + return Array.isArray(parsed) ? parsed : []; + } catch { + return []; + } +} + +module.exports = { + labelClass, + labelRace, + labelJob, + labelPower, + parseJsonArray, +}; diff --git a/Webapp/views/coming-soon.ejs b/Webapp/views/coming-soon.ejs new file mode 100644 index 0000000..04235fd --- /dev/null +++ b/Webapp/views/coming-soon.ejs @@ -0,0 +1,10 @@ +<%- include('partials/page-start') %> + +

+
+

<%= heading %>

+

<%= description %>

+ Retour au dashboard +
+ +<%- include('partials/page-end') %> diff --git a/Webapp/views/error.ejs b/Webapp/views/error.ejs new file mode 100644 index 0000000..c8c768a --- /dev/null +++ b/Webapp/views/error.ejs @@ -0,0 +1,9 @@ +<%- include('partials/page-start') %> + +
+

<%= title %>

+

<%= message %>

+ Retour au dashboard +
+ +<%- include('partials/page-end') %> diff --git a/Webapp/views/index.ejs b/Webapp/views/index.ejs new file mode 100644 index 0000000..56290f5 --- /dev/null +++ b/Webapp/views/index.ejs @@ -0,0 +1,106 @@ +<%- include('partials/page-start') %> + +<%- include('partials/page-header', { title, subtitle: 'Vue d\'ensemble du serveur en temps réel' }) %> + +
+
+ Joueurs en ligne + <%= fmt.formatNumber(stats.onlinePlayers) %> +
+
+ Joueurs inscrits + <%= fmt.formatNumber(stats.totalPlayers) %> +
+
+ Niveau moyen + <%= stats.averageLevel %> +
+
+ Money en circulation + <%= fmt.formatMoney(stats.totalMoney) %> +
+
+ Groupes actifs + <%= fmt.formatNumber(stats.totalGroups) %> +
+
+ +
+
+

Joueurs connectés

+ <%= onlinePlayers.length %> +
+ <% if (onlinePlayers.length === 0) { %> +

Aucun joueur connecté pour le moment.

+ <% } else { %> + + + + + + + + + + + + + <% onlinePlayers.forEach(function(p) { %> + + + + + + + + + <% }); %> + +
JoueurNiveauClasseRaceMoney
+ + + <%= p.display_name %> + + <%= p.level %><%= p.classLabel %><%= p.raceLabel %><%= fmt.formatMoney(p.money) %>Profil
+ <% } %> +
+ +
+
+

Dernières connexions

+
+ <% if (recentPlayers.length === 0) { %> +

Aucun joueur enregistré.

+ <% } else { %> + + + + + + + + + + + + <% recentPlayers.forEach(function(p) { %> + + + + + + + + <% }); %> + +
JoueurNiveauStatutDernière connexion
<%= p.display_name %><%= p.level %> + <% if (p.isOnline) { %> + En ligne + <% } else { %> + Hors ligne + <% } %> + <%= fmt.formatTimestamp(p.last_date_connected) %>Profil
+ <% } %> +
+ +<%- include('partials/page-end') %> diff --git a/Webapp/views/partials/page-end.ejs b/Webapp/views/partials/page-end.ejs new file mode 100644 index 0000000..c22debf --- /dev/null +++ b/Webapp/views/partials/page-end.ejs @@ -0,0 +1,4 @@ + + + + diff --git a/Webapp/views/partials/page-header.ejs b/Webapp/views/partials/page-header.ejs new file mode 100644 index 0000000..ed238f8 --- /dev/null +++ b/Webapp/views/partials/page-header.ejs @@ -0,0 +1,8 @@ + diff --git a/Webapp/views/partials/page-start.ejs b/Webapp/views/partials/page-start.ejs new file mode 100644 index 0000000..73d8a08 --- /dev/null +++ b/Webapp/views/partials/page-start.ejs @@ -0,0 +1,42 @@ + + + + + + <%= title %> · Orion.ovh + + + +
+ +
+ <% if (!dbStatus.exists) { %> +
+ Fichier mmorpg.db introuvable. Démarrez le serveur Hytale pour initialiser la base à la racine du monorepo. +
+ <% } %> diff --git a/Webapp/views/partials/player-card.ejs b/Webapp/views/partials/player-card.ejs new file mode 100644 index 0000000..1a5ec21 --- /dev/null +++ b/Webapp/views/partials/player-card.ejs @@ -0,0 +1,80 @@ +
+
+
+
<%= player.display_name.charAt(0).toUpperCase() %>
+
+

<%= player.display_name %>

+

<%= player.uuid %>

+ <% if (player.isOnline) { %> + En ligne + <% } else { %> + Hors ligne + <% } %> +
+
+ +
+
+
Niveau
+
<%= player.level %>
+
+
+
Expérience
+
<%= fmt.formatNumber(player.experience) %>
+
+
+
Classe
+
<%= player.classLabel %>
+
+
+
Race
+
<%= player.raceLabel %>
+
+
+
Money
+
<%= fmt.formatMoney(player.money) %>
+
+
+
Temps de jeu
+
<%= fmt.formatDuration(player.total_time_play) %>
+
+
+
Création du compte
+
<%= fmt.formatTimestamp(player.date_creation || player.created_at) %>
+
+
+
Dernière connexion
+
<%= fmt.formatTimestamp(player.last_date_connected) %>
+
+
+ + <% if (player.jobs.length > 0) { %> +
+ Métiers + <% player.jobs.forEach(function(job) { %> + <%= job %> + <% }); %> +
+ <% } %> + + <% if (player.powers.length > 0) { %> +
+ Pouvoirs + <% player.powers.forEach(function(power) { %> + <%= power %> + <% }); %> +
+ <% } %> + + <% if (group) { %> +

Membre du groupe <%= group.id %>

+ <% } %> +
+ + <% if (typeof comingSoon !== 'undefined' && comingSoon) { %> +
+

Fonctionnalités à venir

+

Inventaire, compétences détaillées, historique de combat et statistiques avancées seront disponibles prochainement sur cette page.

+
+ <% } %> +
diff --git a/Webapp/views/players/list.ejs b/Webapp/views/players/list.ejs new file mode 100644 index 0000000..83f532d --- /dev/null +++ b/Webapp/views/players/list.ejs @@ -0,0 +1,49 @@ +<%- include('../partials/page-start') %> + +<%- include('../partials/page-header', { title, subtitle: players.length + ' joueur(s) enregistré(s)' }) %> + +
+ <% if (players.length === 0) { %> +

Aucun joueur trouvé dans la base de données.

+ <% } else { %> + + + + + + + + + + + + + + + <% players.forEach(function(p) { %> + + + + + + + + + + + <% }); %> + +
JoueurNiveauXPClasseRaceMoneyStatutTemps de jeu
+ <% } %> +
+ +<%- include('../partials/page-end') %> diff --git a/Webapp/views/players/profile.ejs b/Webapp/views/players/profile.ejs new file mode 100644 index 0000000..a586323 --- /dev/null +++ b/Webapp/views/players/profile.ejs @@ -0,0 +1,9 @@ +<%- include('../partials/page-start') %> + +<%- include('../partials/page-header', { title: player.display_name, subtitle: 'Profil joueur' }) %> + +<%- include('../partials/player-card', { player, group, comingSoon }) %> + + + +<%- include('../partials/page-end') %> diff --git a/Webapp/views/profile/account.ejs b/Webapp/views/profile/account.ejs new file mode 100644 index 0000000..704fc8b --- /dev/null +++ b/Webapp/views/profile/account.ejs @@ -0,0 +1,19 @@ +<%- include('../partials/page-start') %> + +<%- include('../partials/page-header', { title: 'Mon profil', subtitle: 'Connecté en tant que ' + player.display_name }) %> + +
+
+ +
+ Voir le profil public +
+ +<%- include('../partials/player-card', { player, group, comingSoon: false }) %> + +
+

À venir

+

Inventaire, historique de combat et gestion avancée du compte seront ajoutés prochainement.

+
+ +<%- include('../partials/page-end') %> diff --git a/Webapp/views/profile/login.ejs b/Webapp/views/profile/login.ejs new file mode 100644 index 0000000..e422f20 --- /dev/null +++ b/Webapp/views/profile/login.ejs @@ -0,0 +1,38 @@ +<%- include('../partials/page-start') %> + +<%- include('../partials/page-header', { title: 'Mon profil', subtitle: 'Connexion à Orion.ovh' }) %> + +
+ <% if (needsMigration) { %> +
+ La colonne password_hash est absente. Redémarrez le serveur Hytale pour appliquer la migration. +
+ <% } %> + + <% if (error) { %> +
<%= error %>
+ <% } %> + +
+ + + +
+ +
+

Première connexion ?

+

+ Rejoignez le serveur Hytale, puis définissez votre mot de passe web en jeu : +

+
/mmorpg password MonMotDePasse
+

Minimum <%= auth.MIN_PASSWORD_LENGTH %> caractères. Vous pourrez le modifier à tout moment avec la même commande.

+
+
+ +<%- include('../partials/page-end') %> diff --git a/gradle.properties.bak b/gradle.properties.bak deleted file mode 100644 index 96d799e..0000000 --- a/gradle.properties.bak +++ /dev/null @@ -1,3 +0,0 @@ -org.gradle.daemon=true -org.gradle.parallel=true -org.gradle.java.home=/usr/lib/jvm/java-25-openjdk