Horizons
🔌 API

☕ API Java & Modules


📝 Introduction

Horizons expose une API Java complète via le package org.metaloul.horizons.api.
Pour utiliser l'API, ajoutez le jar de Horizons à votre projet (scope provided).

Point d'entrée

import org.metaloul.horizons.api.Horizons;

if (Horizons.isEnabled()) {
    // Accès statique aux managers
    TeamManagerAPI teams = Horizons.getTeamAPI();
    ShopAPI shops = Horizons.getShopAPI();
}

🧩 Système de Modules

Le système de modules permet de créer des extensions qui tournent à l'intérieur de Horizons. Contrairement aux plugins Bukkit classiques, les modules bénéficient de :

  • Partage de ressources : Connexion BDD partagée, système de configuration unifié.
  • Intégration profonde : Accès direct aux managers internes.
  • Isolation : ClassLoader dédié pour éviter les conflits de dépendances.
  • Hot-Reload : Possibilité de recharger la configuration des modules sans redémarrer.

Créer un module

Un module est un simple JAR contenant un fichier module.yml et une classe étendant HorizonsModule.

Le descriptor (module.yml)

À placer à la racine du JAR :

name: MonModule
version: 1.0.0
main: com.monpackage.MonModule
author: VotreNom
description: Un module exemple
dependencies: [] # Modules requis

La classe principale

import org.metaloul.horizons.api.module.HorizonsModule;

public class MonModule extends HorizonsModule {

    public MonModule() {
        super("MonModule", "1.0.0", "Auteur");
    }

    @Override
    public void onEnable() {
        getLogger().info("Mon module démarre !");
        
        // Enregistrement automatique (nettoyé au disable)
        registerCommand(new MaCommande());
        registerListener(new MonListener());
        
        // Configurable GUI item
        setConfigMetadata("options.welcome", Material.PAPER, "Welcome Msg", "Description");
    }

    @Override
    public void onDisable() {
        // Nettoyage automatique
    }
}

🎨 Personnalisation du GUI de Configuration (Optionnel)

Les modules peuvent personnaliser l'apparence de leurs options dans le menu de configuration admin (/horizons config). Ceci est purement optionnel ; par défaut, Horizons affichera des items génériques.

Utilisez setConfigMetadata dans onEnable :

// 1. Icône du module dans la liste principale
setConfigMetadata("", Material.DIAMOND_SWORD, "&bMon Module", "&7Description du module");

// 2. Icône pour une section de config spécifique
setConfigMetadata("database", Material.CHEST, "&eBase de données", "&7Configuration MySQL");

// 3. Icône pour une valeur spécifique
setConfigMetadata("database.host", Material.PAPER, "&fHôte Connexion", "&7IP du serveur");

Syntaxe : setConfigMetadata(String path, Material icon, String name, String description)

  • path : Chemin dans le config.yml (ex: category.setting). Chaine vide "" pour le module lui-même.
  • icon : Material Bukkit à afficher.
  • name & description : Supportent les codes couleurs (&a, &l, etc.).

😎Exemple de module

Le fichier historique ../.gitbook/assets/ModerationModule.zip ne se trouvait pas dans le dépôt source.

⚒️Custom Item Providers

Horizons offre deux façons d'ajouter des items custom :

  • Méthode Simplifiée (SimpleCustomItemProvider) : Pour ajouter rapidement vos propres items créés via code.
  • Méthode Avancée (CustomItemProvider) : Pour intégrer un plugin d'items externe (comme MMOItems, ExecutableItems, etc).

Option A : Créer vos propres items (Simple)

// 1. Initialiser le provider pour votre module
SimpleCustomItemProvider myProvider = new SimpleCustomItemProvider("mon_module");

// 2. Créer vos ItemStacks (Exemple avec ItemBuilder mais marche avec n'importe quel ItemStack)
ItemStack superEpée = new ItemStack(Material.DIAMOND_SWORD);
ItemMeta meta = superEpée.getItemMeta();
meta.setDisplayName("§cExcalibur");
superEpée.setItemMeta(meta);

// 3. Enregistrer les items dans votre provider
// Soit un par un :
myProvider.registerItem("excalibur", superEpée);
myProvider.registerItem("bouclier_magique", magicShield);

// Soit automatiquement depuis une classe (champs 'public static ItemStack') :
// L'ID sera le nom du champ en minuscule (ex: "EXCALIBUR" -> "excalibur")
myProvider.registerItemsFromClass(MyItems.class);

// 4. Enregistrer le provider dans Horizons
registerCustomItemProvider(myProvider);

Option B : Support d'un Plugin Externe (Avancé)

public class MonPluginProvider implements CustomItemProvider {
    @Override
    public String getProviderId() { return "mon_plugin_externe"; }
    
    @Override
    public Optional<ItemStack> getItemStack(String id, int amount) {
        // Logique pour récupérer l'item depuis l'API externe
        return ExternalApi.getItem(id);
    }
    
    // ... implémenter les autres méthodes (isCustomItem, etc)
}

// Enregistrement
registerCustomItemProvider(new MonPluginProvider());

Utilisation dans les configs (Shop, Kits, etc) : Une fois enregistrés, vos items sont accessibles partout dans Horizons via le format : provider_id:item_id.
Exemple : mon_module:excalibur ou oraxen:hyper_sword.

😎Exemple d'item custom simple

Le fichier historique ../.gitbook/assets/src.zip ne se trouvait pas dans le dépôt source.

🌍 Système de Traduction (I18n)

Horizons fournit un système de langue natif et automatisé pour vos modules.

1. Structure des Fichiers Dans votre projet (JAR), placez vos fichiers YAML de langue dans src/main/resources/languages/ :

  • fr_FR.yml (Français)
  • en_US.yml (Anglais - Fallback par défaut)

Exemple de contenu fr_FR.yml :

mon-module:
  welcome: "&aBienvenue sur mon module, {player} !"
  error: "&cUne erreur est survenue."

2. Utilisation dans le Code Votre classe principale (HorizonsModule) possède la méthode msg() pour récupérer les messages traduits.

// String msg(String key, String... placeholders)

// Simple
player.sendMessage(msg("mon-module.error"));

// Avec placeholders ({player} -> "Bob")
player.sendMessage(msg("mon-module.welcome", "{player}", player.getName()));

3. Automatisation

  • Installation : Au premier lancement, vos fichiers .yml sont extraits automatiquement dans plugins/Horizons/modules/<votre-module>/languages/.
  • Synchronisation : Votre module utilise automatiquement la langue définie dans la config globale de Horizons.
  • Reload : La commande /hz reload recharge aussi vos langues instantanément.

ModuleLanguageManager

En arrière-plan, chaque module se voit attribuer une instance de ModuleLanguageManager.

Fonctionnalités clés :

  1. Isolation : Charge les ressources depuis le ClassLoader du module (isolation du JAR).
  2. Synchronisation : La méthode reload() lit la configuration globale du serveur (language.default dans config.yml) pour s'assurer que tous les modules parlent la même langue que le coeur du plugin.
  3. Fallback : Si une clé de traduction manque dans la langue cible, le manager peut (selon implémentation) se replier sur la langue par défaut du module.

🛠 APIs Principales

Cette section présente les concepts. Pour la liste complète des méthodes, voir la section Référence Syntaxique Complète ci-dessous.

TeamManagerAPI

Gère les équipes, scores et joueurs.

TeamManagerAPI api = Horizons.getTeamAPI();
api.addTeamScore("Red", 100);

ShopAPI

Gère l'économie, les shops et le marché noir.

ShopAPI api = Horizons.getShopAPI();
double price = api.getItemPrice("minerals::miner", Material.DIAMOND);

WebAPIManager

Permet d'interroger les données du serveur via HTTP/JSON.


📚 Référence Syntaxique Complète

Voici la liste exhaustive des méthodes disponibles pour chaque API.

TeamManagerAPI Référence

Package : org.metaloul.horizons.api
Accès : Horizons.getTeamAPI()

Vérifications & Lecture

RetourMéthodeDescription
booleanteamExists(String teamName)Vérifie si une équipe existe.
booleanisPlayerInTeam(Player player, String teamName)Vérifie si le joueur est dans l'équipe donnée.
StringgetTeamPrefix(String teamName)Retourne le préfixe (couleur/tag).
StringgetTeamDisplayName(String teamName)Retourne le nom d'affichage.
intgetTeamScore(String teamName)Retourne le score actuel.
StringgetPlayerTeam(Player player)Retourne le nom de l'équipe du joueur.
List<String>getAllTeams()Retourne tous les noms d'équipes.
List<Player>getTeamPlayers(String teamName)Retourne les joueurs en ligne.
List<UUID>getTeamPlayerUUIDs(String teamName)Retourne tous les joueurs (offline inclus).
Map<String, Integer>getAllTeamScores()Retourne une map Equipe -> Score.
List<String>getTeamsSortedByScore()Retourne les équipes triées par score.

Modification (Écriture)

RetourMéthodeDescription
voidcreateTeam(String name, String prefix, String display)Crée une nouvelle équipe.
voidremoveTeam(String teamName)Supprime une équipe.
voidaddPlayerToTeam(Player player, String teamName)Ajoute un joueur.
booleanremovePlayerFromTeam(String playerName)Retire un joueur.
voidsetTeamPrefix(String teamName, String prefix)Change le préfixe.
voidsetTeamDisplayName(String teamName, String name)Change le nom d'affichage.
voidsetTeamScore(String teamName, int score)Définit le score.
voidaddTeamScore(String teamName, int points)Ajoute des points.
voidremoveTeamScore(String teamName, int points)Retire des points.

ShopAPI Référence

Package : org.metaloul.horizons.api
Accès : Horizons.getShopAPI()

Ouverture de Shop

RetourMéthodeDescription
booleanopenShop(Player player, String shopId)Ouvre un shop pour un joueur. Retourne true si succès.
Set<String>getAllShopIds()Retourne tous les IDs de shops disponibles.

Lecture des Prix & Items

RetourMéthodeDescription
booleanshopExists(String shopId)Vérifie l'existence d'un shop.
List<Material>getShopItems(String shopId)Liste des matériaux vendus.
doublegetItemPrice(String shopId, Material material)Prix global actuel.
doublegetItemPrice(String shopId, Material mat, String team)Prix pour une équipe spécifique.
doublegetCustomItemPrice(String shopId, String itemKey)Prix d'un item custom.
PriceTrendgetPriceTrend(String shopId, Material material)Tendance (UP, DOWN, STABLE).

Marché Noir

RetourMéthodeDescription
booleanblackMarketExists(String marketId)Vérifie l'existence.
List<Material>getBlackMarketItems(String marketId)Items disponibles.
intgetBlackMarketItemPrice(String id, Material mat)Prix actuel (entier).

Configuration des Scopes (Global vs Per-Team)

RetourMéthodeDescription
StringgetPriceScope(String shopId, String itemKey)Scope effectif (GLOBAL/PER_TEAM).
StringgetShopPriceScope(String shopId)Scope configuré pour le shop.
StringgetGlobalPriceScope()Scope par défaut du serveur.
voidsetItemPriceScope(String shopId, String key, String scope)Configure le scope d'un item.
voidsetShopPriceScope(String shopId, String scope)Configure le scope d'un shop.

Infos Économie Avancée

RetourMéthodeDescription
StringgetPricingType(shopId, itemKey)Type de pricing (STATIC, TIERED, etc).
longgetTotalSales(shopId, itemKey, team)Ventes totales (lifetime).
intgetPeriodSales(shopId, itemKey, team)Ventes sur la période actuelle.
longgetNextTierThreshold(shopId, itemKey, team)Seuil de ventes pour le prochain palier.
doublegetNextTierPrice(shopId, itemKey, team)Prix au prochain palier.
intgetCurrentTierIndex(shopId, itemKey, team)Index du palier actuel (base 1).
longgetTimeUntilNextPriceReset()Temps restant avant reset auto (secondes).
doublegetMinPrice(shopId, itemKey)Prix minimum configuré.
doublegetMaxPrice(shopId, itemKey)Prix maximum configuré.
doublegetBasePrice(shopId, itemKey)Prix de base configuré.
doublegetPreviousPrice(shopId, itemKey, team)Prix avant mise à jour.
intgetSupplyThreshold(shopId, itemKey)Seuil de ventes pour baisse de prix.

WebAPIManager (HTTP API)

Authentification : Toutes les requêtes HTTP nécessitent le paramètre ?secret=VOTRE_SECRET_API.
Port par défaut : 8080 (Configurable dans config.yml).
Format : Réponse JSON UTF-8.

Endpoints HTTP

  1. Liste des Équipes
    GET /api/teams?secret=...

Retourne la liste complète des équipes, scores et joueurs.

{
  "teams": [
    {
      "name": "red",
      "displayName": "&cRouge",
      "displayNameClean": "Rouge",
      "prefix": "&c[R]",
      "score": 150,
      "players": [
        { "uuid": "...", "name": "Player1", "online": true },
        { "uuid": "...", "name": "Player2", "online": false }
      ]
    }
  ]
}
  1. Liste des Joueurs
    GET /api/players?secret=...

Retourne tous les joueurs connus avec leur équipe et score personnel.

{
  "players": [
    {
      "uuid": "...",
      "name": "Player1",
      "score": 10,
      "team": "red",
      "online": true
    }
  ]
}
  1. Données des Shops
    GET /api/shops?secret=...

Retourne la configuration et les prix actuels de tous les shops.

{
  "shops": [
    {
      "id": "minerals::miner",
      "name": "Miner Shop",
      "items": [
        {
          "material": "DIAMOND",
          "currentPrice": 45.5,
          "pricingType": "DYNAMIC",
          "basePrice": 50.0
        }
      ]
    }
  ]
}

On this page