Horizons
⚙️ Configuration

🛍️ Shops

🛠️ Outil en ligne : Un générateur de configuration de shops est disponible pour vous aider à créer et configurer vos shops facilement.

📌 Note: Pour utiliser les shops, assurez-vous que le plugin FancyNPCs soit installé sur le serveur. 🛠️

🛒 Configuration des Shops

Cette section concerne les paramètres de configuration dans config.yml.

⚙️ Paramètres de Configuration

🕐 Fréquence de mise à jour

Cette option configure l'intervalle à laquelle les prix des articles dans les shops sont automatiquement mis à jour. La valeur par défaut est "15m" (15 minutes).

Le format accepte différentes unités de temps:

  • s pour secondes
  • m pour minutes
  • h pour heures

💡 Exemple d'utilisation

shops:
  # Intervalle de mise à jour des prix (format: 15m, 1h, etc.)
  # Contrôle la fréquence à laquelle les prix de tous les shops sont mis à jour
  price_update_interval: "15m"

À chaque intervalle, le système exécute la méthode pour tous les shops configurés, recalculant les prix selon les paramètres de prix dynamiques définis pour chaque article.

🔊 Sons de l'Interface

Les sons peuvent être configurés à deux niveaux :

  1. Globalement dans config.yml → s'applique à tous les shops
  2. Par shop/NPC dans le fichier de shop → surcharge les sons globaux

Hiérarchie de priorité : Configuration NPC > Configuration globale

Configuration globale (config.yml)

shops:
  sounds:
    open: BLOCK_CHEST_OPEN          # Son d'ouverture
    close: BLOCK_CHEST_CLOSE        # Son de fermeture
    purchase_success: ENTITY_PLAYER_LEVELUP  # Vente réussie
    purchase_fail: ENTITY_VILLAGER_NO        # Vente échouée
    page_change: UI_BUTTON_CLICK    # Changement de page
    volume: 1.0                     # Volume (0.0 - 1.0)
    pitch: 1.0                      # Tonalité (0.5 - 2.0)

Configuration par shop (fichier de shop)

Vous pouvez surcharger les sons pour un shop spécifique :

shop:
  Miner_Market:
    display_name: "&7Miner Market"
    # ... autres options ...
    gui:
      sounds:
        open: BLOCK_BARREL_OPEN
        close: BLOCK_BARREL_CLOSE
        purchase_success: ENTITY_VILLAGER_YES
        purchase_fail: ENTITY_VILLAGER_NO
        page_change: UI_BUTTON_CLICK
        volume: 0.8
        pitch: 1.2

💡 Astuce : Les sons par shop sont optionnels. Si non spécifiés, les sons globaux seront utilisés.

💬 Messages d'Interaction

messages:
  # Message lors d'une vente réussie (supporte {points} pour le montant)
  purchase_success: "&aVous avez gagné {points} points pour votre équipe!"
  # Message lors d'une vente échouée
  purchase_fail: "&cVous n'avez pas l'item requis!"

💡 Exemple complet

shops:
  price_update_interval: "15m"  # Intervalle de mise à jour des prix (s: secondes, m: minutes, h: heures)
  # Configuration des sons
  sounds:
    open: BLOCK_CHEST_OPEN        # Son d'ouverture du shop
    close: BLOCK_CHEST_CLOSE      # Son de fermeture du shop
    page_change: UI_BUTTON_CLICK  # Son lors du changement de page
    purchase_success: ENTITY_PLAYER_LEVELUP  # Son lors d'une vente réussie
    purchase_fail: ENTITY_VILLAGER_NO       # Son lors d'une vente échouée
    volume: 1.0                   # Volume des sons (entre 0.0 et 1.0)
    pitch: 1.0                    # Tonalité des sons (entre 0.5 et 2.0)
  # Messages personnalisables
  messages:
    purchase_success: "&aVous avez gagné {points} points pour votre équipe!"
    purchase_fail: "&cVous n'avez pas l'item requis!"
  # Mode de stockage des prix
  storage:
    type: "JSON"                  # Type de stockage: "JSON" ou "MYSQL"
    # Configuration MySQL (uniquement si type est "MYSQL")
    mysql:
      host: "localhost"
      port: 3306
      database: "horizons"
      username: "user"
      password: "password"
      table_prefix: "hz_"

💾 Système de Sauvegarde des Prix des shops

Le plugin Horizons propose deux méthodes de stockage pour les prix des shops permettant une persistance des prix après rechargement du plugin.

📄 Stockage JSON

  • Les prix sont sauvegardés dans des fichiers JSON dans le dossier plugins/Horizons/data/shop_prices/
  • Chaque shop a son propre fichier (ex: example_shop::Forgeron.json)
  • Avantages: simple, pas de dépendance externe
  • Configuration par défaut, ne nécessite aucune configuration supplémentaire

🗃️ Stockage MySQL (optionnel)

  • Les prix sont sauvegardés dans une base de données MySQL
  • Idéal pour les serveurs multi-instances ou avec beaucoup de shops
  • Nécessite une configuration dans la section shops.storage.mysql
  • Les tables sont créées automatiquement lors du premier démarrage
  • Permet une synchronisation des prix en temps réel entre plusieurs serveurs

⏱️ Les prix sont automatiquement sauvegardés:

  • À intervalles réguliers (configurable via price_update_interval)
  • Lors de la désactivation du plugin
  • Lors du rechargement des configurations

Pour changer le mode de stockage, modifiez simplement shops.storage.type dans la configuration principale.

🎮 Interactions avec les Shops

Les shop gèrent les interactions suivantes :

  • 🖱️ Clic gauche sur un item : Vend une unité de cet item au prix actuel.
  • 🖱️ Clic droit sur un item : Vend tous les items du même type dans l'inventaire du joueur.
  • 🔄 Clic sur une flèche : Permet de naviguer entre les pages du shop.
    • ⬅️ Flèche gauche (emplacement 45) : Page précédente.
    • ➡️ Flèche droite (emplacement 53) : Page suivante.

💰 Format d'Affichage des Prix

Les prix sont affichés dans l'interface avec une tendance indiquant leur évolution :

  • 📈 Augmentation : ↑
  • 📉 Diminution : ↓
  • ➡️ Stable : →

🏪 Association avec les NPCs

Les shops sont automatiquement associés à des NPCs FancyNPCs par leur ID. Lorsqu'un joueur fait un clic droit sur un NPC :

  1. 🎵 Le son configuré est joué.
  2. 🛍️ Le shop correspondant s'ouvre automatiquement.
  3. 📦 L'interface s'affiche avec les items disponibles.

🎯 Modes de Trigger

Le plugin propose deux modes pour ouvrir un shop : via NPC ou via commande.

Mode NPC (par défaut)

C'est le comportement classique : un NPC FancyNpcs est créé aux coordonnées spécifiées et le shop s'ouvre au clic.

shop:
  Shop_Keeper:
    # trigger.type: "npc"  # optionnel, c'est la valeur par défaut
    display_name: "&6&lShop Keeper"
    entity_type: VILLAGER
    Position:
      world: world
      x: 0
      y: 64
      z: 0
    gui_title: "&6General Store"
    items:
      # ...

Mode Command

Ce mode permet d'ouvrir un shop sans créer de NPC. Idéal pour l'intégration avec d'autres plugins de NPC ou autres plugins (menus customs, blocs interactifs, etc.)

shop:
  Remote_Shop:
    trigger:
      type: "command"  # Pas de NPC créé
    display_name: "&d&lRemote Shop"
    gui_title: "§d§lRemote Shop"
    gui:
      rows: 3
    # Note: Position non requise en mode "command"
    # entity_type non requis non plus
    items:
      DIAMOND:
        pricing:
          type: STATIC
          base_price: 100

Ouverture via Commande

La commande pour ouvrir un shop est réservée à la console ou aux administrateurs (permission horizons.admin).

/horizons shop open <joueur> <shopId>

Exemple :

/horizons shop open Notch example_shop::Remote_Shop

⚠️ Sécurité : Les joueurs normaux ne peuvent PAS utiliser cette commande, même avec des permissions shop. Cela permet aux autres plugins d'exécuter la commande via console sans risque.

Intégration avec d'autres plugins :

💡 Pour l'API Java complète, voir la documentation API.

📝 Structure des Shops

Les shops sont configurés dans des fichiers YAML situés dans le dossier plugins/Horizons/shops/. Chaque fichier représente une ou plusieurs boutiques avec un ou plusieurs NPCs.

🏪 Configuration des NPCs

shop:
  ID_DU_VENDEUR: #Peut être un nombre ou du texte
    display_name: '&6&lNom du vendeur'
    entity_type: VILLAGER
    profession: ARMORER
    villager_type: PLAINS
    Position:
      world: world
      x: 0
      y: 64
      z: 0
    gui_title: '&6Nom du GUI'
    items:
      DIAMOND_SWORD:
        pricing:
          type: STATIC
          base_price: 500
      NETHERITE_CHESTPLATE:
        pricing:
          type: STATIC
          base_price: 2000
      DIAMOND_PICKAXE:
        pricing:
          type: DYNAMIC
          base_price: 300
          min_price: 150
          max_price: 600
          adjustment:
            type: SUPPLY_DEMAND
            demand_multiplier: 0.15
            supply_threshold: 50
            cooldown_rate: 0.03
      GOLDEN_APPLE:
        quantity: 8
        pricing:
          type: DYNAMIC
          base_price: 120
          min_price: 80
          max_price: 250
          adjustment:
            type: FIXED_PERCENTAGE
            change_rate: 0.05
            supply_threshold: 30
      ENCHANTED_GOLDEN_APPLE:
        pricing:
          type: DYNAMIC
          base_price: 1500
          min_price: 1000
          max_price: 3000
          adjustment:
            type: SUPPLY_DEMAND
            demand_multiplier: 0.2
            supply_threshold: 10
            cooldown_rate: 0.02
      IRON_INGOT:
        pricing:
          type: TIERED
          base_price: 50
          tiers:
            tier2:
              threshold: 100
              price: 45
            tier3:
              threshold: 500
              price: 40
            tier4:
              threshold: 1000
              price: 35

⚙ Configuration des NPCs

Options Disponibles

ParamètreDescriptionObligatoire
display_nameNom affiché du NPC (supporte les codes couleur)Oui
entity_typeType d'entité (VILLAGER, PLAYER, etc.)Oui
PositionSection contenant les coordonnéesOui
gui_titleTitre de l'interface du shopOui

Types d'Entités Spécifiques

Villageois

shop:
  Forgeron:
    display_name: "&c&lForgeron"
    entity_type: "VILLAGER"
    profession: "WEAPONSMITH"  # Type de métier
    villager_type: "PLAINS"    # Type de biome

Professions disponibles : ARMORER, BUTCHER, CARTOGRAPHER, CLERIC, FARMER, FISHERMAN, FLETCHER, LEATHERWORKER, LIBRARIAN, MASON, NITWIT, NONE, SHEPHERD, TOOLSMITH, WEAPONSMITH.

Types de villageois : DESERT, JUNGLE, PLAINS, SAVANNA, SNOW, SWAMP, TAIGA.

Joueur avec Skin

shop:
  Trader:
    display_name: "&6&lTrader Elite"
    entity_type: "PLAYER"
    skin_name: "Notch"  # Nom du skin à utiliser

🎨 Configuration de l'Interface (GUI)

Les shops peuvent avoir une interface entièrement personnalisable. Si non spécifié, une configuration par défaut est utilisée.

📊 Hiérarchie de Priorité

La configuration GUI suit une hiérarchie de 3 niveaux. Le système cherche chaque paramètre dans cet ordre :

PrioritéSourceChemin
1 (Plus haute)Configuration NPCshop.NPC_ID.gui.*
2Defaults du fichiershop.gui_default.*
3Defaults globauxconfig.yml → shops.gui_defaults.*
4 (Fallback)Valeurs codées en durVoir tableau ci-dessous

💡 Astuce : Vous pouvez définir des defaults dans config.yml pour tous les shops, puis les surcharger au niveau fichier ou NPC.

📦 Valeurs par Défaut (Fallback)

Si aucune configuration n'est trouvée, ces valeurs sont utilisées :

ParamètreValeur par défaut
rows6
layout.items.slotsSlots 10-16, 19-25, 28-34, 37-43 (7 colonnes × 4 lignes au centre)
layout.pagination.previous.slot45
layout.pagination.next.slot53
layout.border.item.materialBLACK_STAINED_GLASS_PANE
layout.border.item.name(espace)

🔧 Structure Complète

shop:
  # ════════════════════════════════════════════════════
  # DEFAULTS DU FICHIER (Optionnel)
  # S'applique à tous les NPCs de ce fichier
  # ════════════════════════════════════════════════════
  gui_default:
    rows: 4
    layout:
      border:
        item:
          material: BLUE_STAINED_GLASS_PANE
      items:
        slots: [10, 11, 12, 13, 14, 15, 16]
      pagination:
        previous:
          slot: 27
        next:
          slot: 35

  # ════════════════════════════════════════════════════
  # CONFIGURATION SPÉCIFIQUE AU NPC
  # Surcharge les defaults du fichier et globaux
  # ════════════════════════════════════════════════════
  Shop_Keeper:
    display_name: "&6&lShop Keeper"
    entity_type: VILLAGER
    # ... autres options ...
    
    gui:
      # Nombre de lignes de l'inventaire (1-6)
      rows: 6
      
      layout:
        # ─────────────────────────────────────────────
        # BORDURE
        # ─────────────────────────────────────────────
        border:
          # Option 1: Remplissage intelligent (2 slots = début et fin)
          # Remplit automatiquement tous les slots sauf items et pagination
          slots: [0, 53]
          
          # Option 2: Liste explicite de slots
          # slots: [0, 1, 2, 3, 4, 5, 6, 7, 8, 45, 46, 47, 48, 49, 50, 51, 52, 53]
          
          item:
            material: BLACK_STAINED_GLASS_PANE
            name: " "
            # lore: [] # Optionnel
            
        # ─────────────────────────────────────────────
        # SLOTS D'ITEMS À VENDRE
        # ─────────────────────────────────────────────
        items:
          slots:
            - 10
            - 11
            - 12
            - 13
            - 14
            - 15
            - 16
            # ... etc
          # Ou en ligne: slots: [10, 11, 12, 13, 14, 15, 16]
          
        # ─────────────────────────────────────────────
        # PAGINATION
        # ─────────────────────────────────────────────
        pagination:
          previous:
            # Un seul slot
            slot: 45
            # OU plusieurs slots (tous cliquables)
            # slots: [45, 46]
            item:
              material: ARROW
              name: "&6<< Page précédente"
              
          next:
            slot: 53
            # slots: [52, 53]
            item:
              material: ARROW
              name: "&6Page suivante >>"

📐 Cas de Figures et Exemples

Cas 1: Shop Minimal (utilise tous les defaults)

shop:
  Simple_Vendor:
    display_name: "&aVendeur"
    entity_type: VILLAGER
    Position:
      world: world
      x: 100
      y: 64
      z: 200
    gui_title: "&aShop"
    items:
      DIAMOND:
        pricing:
          type: STATIC
          base_price: 100

Résultat : GUI de 6 lignes, bordure noire, items au centre, pagination en bas.


Cas 2: Petit Shop (3 lignes)

shop:
  Mini_Shop:
    display_name: "&eMini Shop"
    entity_type: VILLAGER
    Position:
      world: world
      x: 100
      y: 64
      z: 200
    gui_title: "&ePetit Shop"
    gui:
      rows: 3
      layout:
        items:
          slots: [10, 11, 12, 13, 14, 15, 16]  # Ligne du milieu uniquement
        pagination:
          previous:
            slot: 18  # En bas à gauche
          next:
            slot: 26  # En bas à droite
    items:
      DIAMOND:
        pricing:
          type: STATIC
          base_price: 100

Cas 3: Shop avec Layout Custom (style grille espacée)

shop:
  Miner_Market:
    display_name: "&8&lMiner Market"
    entity_type: PLAYER
    skin_name: "Notch"
    Position:
      world: world
      x: 100
      y: 64
      z: 200
    gui_title: "&8Miner Market"
    gui:
      rows: 5
      layout:
        border:
          slots: [0, 44]  # Remplissage auto
          item:
            material: GRAY_STAINED_GLASS_PANE
        items:
          # Grille espacée 3x3 au centre
          slots: [11, 13, 15, 20, 22, 24, 29, 31, 33]
        pagination:
          previous:
            slot: 36
          next:
            slot: 44
    items:
      COAL:
        quantity: 64
        pricing:
          type: STATIC
          base_price: 5

Cas 4: Defaults au niveau fichier

shop:
  # Tous les NPCs de ce fichier héritent de cette config
  gui_default:
    rows: 4
    layout:
      border:
        item:
          material: PURPLE_STAINED_GLASS_PANE
      items:
        slots: [10, 11, 12, 13, 14, 15, 16]

  # Ce NPC utilise les defaults du fichier
  Vendor_1:
    display_name: "&5Vendeur 1"
    # ... pas de section gui: → utilise gui_default

  # Ce NPC surcharge certains paramètres
  Vendor_2:
    display_name: "&5Vendeur 2"
    gui:
      rows: 6  # Surcharge seulement rows
      # layout hérite de gui_default

Cas 5: Configuration globale dans config.yml

# Dans config.yml
shops:
  gui_defaults:
    rows: 6
    layout:
      items:
        slots: [10, 11, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24, 25]
      border:
        item:
          material: BLACK_STAINED_GLASS_PANE
      pagination:
        previous:
          slot: 45
        next:
          slot: 53

Note : Cette configuration s'applique à TOUS les shops du serveur, sauf s'ils ont leur propre configuration.

⚠️ Points Importants

  1. Les slots d'items sont exclusifs : Un slot ne peut pas être à la fois un slot d'item ET un slot de pagination.
  2. Le remplissage de bordure est intelligent : Avec slots: [0, 53], le système remplit tous les slots SAUF ceux définis pour les items et la pagination.
  3. La pagination est optionnelle : Si vous avez peu d'items (tous tiennent sur une page), les flèches n'apparaîtront pas.

🖼️ Format d'Affichage des Items

Vous pouvez personnaliser comment les items sont affichés dans le shop (nom et description).

shop:
  Shop_Keeper:
    # ...
    display:
      name_format: "&6%name%" # Format du nom de l'item
      
      lore_formats:
        # Format par défaut
        default:
          - "&7Prix actuel: &2%price% %currency% %trend%"
          - "&7Quantité requise: &c%amount%"
          - "&7Clique gauche: &7&l>> &6Vendre %amount_click_left% item(s)"
          - "&7Clique droit: &7&l>> &6Vendre le maximum possible"
        
        # Format spécifique pour les items TIERED (optionnel)
        tiered:
          - "&7Prix actuel: &2%price% %currency% %trend%"
          - "&7Palier actuel: &6Tier %tier%"
          - "&7Quantité: &c%amount%"

Placeholders Disponibles :

  • %name% : Nom de l'item
  • %price% : Prix actuel
  • %currency% : Nom de la monnaie (ex: Emeralds)
  • %trend% : Flèche de tendance (↑, ↓, →)
  • %tier% : Numéro du palier actuel (pour les items TIERED)
  • %amount% : Quantité vendue par transaction
  • %amount_click_left% : Quantité vendue au clic gauche

⚙ Configuration des Items

Chaque item du shop est configuré dans la section items avec l'identifiant Minecraft de l'item comme clé.

Système de Prix

Le plugin supporte plusieurs modes de tarification définis par le paramètre type dans la section pricing.

1. Prix Statique (STATIC)

Le prix ne change jamais. Il reste fixé au base_price défini.

items:
  DIAMOND:
    pricing:
      type: "STATIC"
      base_price: 100          # Prix fixe

2. Prix Dynamique (SUPPLY_DEMAND / FIXED_PERCENTAGE)

Utilise le type DYNAMIC et une stratégie d'ajustement.

items:
  BREAD:
    pricing:
      type: "DYNAMIC"
      base_price: 50           # Prix de base
      min_price: 25            # Prix minimum
      max_price: 100           # Prix maximum
      adjustment:
        type: "SUPPLY_DEMAND"
        demand_multiplier: 0.15  # Multiplicateur de demande
        supply_threshold: 50     # Seuil de fourniture
        cooldown_rate: 0.05      # Taux de récupération

3. Prix par Paliers (TIERED)

Ce mode permet de définir des prix fixes qui évoluent selon le volume total cumulé des ventes de l'objet.

  • Le prix est déterminé par des paliers (tiers) de ventes cumulées.
  • Le base_price est utilisé tant que le premier palier n'est pas atteint (équivalent à un seuil de 0).
  • Les prix changent immédiatement au franchissement d'un palier (ce mode ignore l'intervalle de rafraîchissement global).

Paramètres spécifiques :

  • tiers: Section contenant la liste des paliers.
    • threshold: Nombre de ventes total requis pour atteindre ce palier.
    • price: Prix appliqué à partir de ce seuil.
items:
  GOLD_INGOT:
    pricing:
      type: "TIERED"
      base_price: 200.0 # Prix initial (pour 0 à 99 ventes)
      tiers:
        tier1:
          threshold: 100 # À partir de 100 ventes cumulées
          price: 150.0
        tier2:
          threshold: 500 # À partir de 500 ventes cumulées
          price: 100.0

Fonctionnement des Prix Dynamiques

Mode SUPPLY_DEMAND (Offre et Demande)

  • Les prix diminuent à mesure que les joueurs vendent des items (demande élevée)
  • Le calcul des prix est basé sur la formule : priceChange = -demandMultiplier * (salesCount/supplyThreshold)^1.5
  • Plus le nombre de ventes (salesCount) s'approche ou dépasse le seuil (supplyThreshold), plus la baisse est importante
  • Le taux de baisse dépend du demand_multiplier et du nombre d'achats par rapport au supply_threshold
  • Quand aucun achat n'est effectué, les prix remontent lentement selon le cooldown_rate

Mode FIXED_PERCENTAGE (Pourcentage Fixe)

  • Les prix augmentent régulièrement selon le change_rate si peu de ventes sont effectués
  • Quand les ventes dépassent le supply_threshold, les prix diminuent proportionnellement selon la formule : priceChange = -changeRate * (salesCount/supplyThreshold)^1.2
  • La diminution s'intensifie de manière exponentielle lorsque le nombre de ventes dépasse largement le seuil

🔢 Système de quantités

⚙ Configuration des quantités

Chaque item dans un shop peut avoir une quantité configurée qui détermine combien d'items sont vendus par transaction.

items:
  NETHERITE_INGOT:
    quantity: 5
    pricing:
      type: "STATIC"
      base_price: 1000          

🤖 Fonctionnement des quantités

🖱️ Clic gauche (Vente de quantité configurée)

  • Vend exactement la quantité configurée d'items
  • Le prix affiché est pour la quantité complète
  • Exemple : avec quantity: 5 et un prix de vente à 1000, un clic gauche vend 5 items pour 1000 points

🖱️ Clic droit (Vente maximale)

  • Vend le maximum possible en multiples de la quantité configurée
  • Le prix est multiplié par le nombre de sets vendus
  • Exemple : avec 12 items, quantity: 4, et un prix de vente à 1000 → vend 3 sets (12 items) pour 3000 points

🎯 Scope des Prix (GLOBAL / PER_TEAM)

Le plugin permet de configurer si les prix sont partagés globalement ou calculés séparément par équipe.

Modes disponibles

ModeDescription
GLOBALTous les joueurs voient le même prix. Les ventes de tous les joueurs affectent le même pool de prix. (Par défaut)
PER_TEAMChaque équipe a son propre marché indépendant. Les ventes d'une équipe n'affectent pas les prix des autres équipes.

Hiérarchie de priorité

Le scope est déterminé selon cette priorité (du plus prioritaire au moins prioritaire) :

  1. Niveau Item → Défini dans la section pricing de l'item
  2. Niveau Shop → Défini dans la configuration du NPC/shop
  3. Niveau Global → Défini dans config.yml sous shops.price_scope

Configuration

Niveau Global (config.yml)

shops:
  price_scope: "GLOBAL"  # ou "PER_TEAM"

Niveau Shop

shop:
  Forgeron:
    display_name: "&6&lForgeron"
    price_scope: "PER_TEAM"  # Tous les items de ce shop utilisent PER_TEAM
    items:
      DIAMOND:
        pricing:
          type: DYNAMIC
          base_price: 100

Niveau Item

shop:
  Marchand:
    display_name: "&2&lMarchand"
    price_scope: "GLOBAL"  # Par défaut pour ce shop
    items:
      DIAMOND:
        pricing:
          type: DYNAMIC
          base_price: 100
          price_scope: "PER_TEAM"  # Override: cet item est PER_TEAM
      IRON_INGOT:
        pricing:
          type: STATIC
          base_price: 50
          # Hérite du shop = GLOBAL

Exemple d'utilisation

Scénario : Compétition entre équipes

Avec price_scope: "PER_TEAM", chaque équipe gère son propre marché :

  • L'équipe Rouge vend beaucoup de diamants → Le prix baisse uniquement pour l'équipe Rouge
  • L'équipe Bleue n'a pas vendu de diamants → Le prix reste élevé pour l'équipe Bleue

Cela permet de créer des stratégies économiques où chaque équipe doit gérer son propre marché !

🔄 Système de Rotation

Le système de rotation permet de modifier automatiquement les items disponibles dans un shop selon un emploi du temps précis.

🎯 Fonctionnalités Clés

  • Planification Horaire : Définissez des plages horaires précises (ex: 14h00 à 18h00).
  • Récurrence Quotidienne : Créez des événements qui se répètent tous les jours.
  • Dates Spécifiques : Programmez des événements uniques pour des dates précises (ex: Nouvel An).
  • Filtres de Jours : Limitez les événements récurrents à certains jours (ex: Week-end uniquement).

⚙️ Configuration

shop:
  Daily_Deals:
    display_name: "&6&lOffres du Jour"
    # ... config standard ...
    
    rotation:
      enabled: true
      notify_players: true
      notification_message: "&e[Shop] &7Les offres ont changé!"
      
      sets:
        # EXEMPLE 1: Récurrence Quotidienne
        morning_coffee:
          start_time: "06:00"  # Format HH:mm
          end_time: "10:00"
          items:
            MILK_BUCKET:
              pricing:
                type: STATIC
                base_price: 5
                
        # EXEMPLE 2: Jours Spécifiques (Week-end)
        weekend_special:
          start_time: "00:00"
          end_time: "23:59"
          days: [SATURDAY, SUNDAY]
          items:
            DIAMOND_SWORD:
              pricing:
                type: STATIC
                base_price: 500
                
        # EXEMPLE 3: Date Absolue (Prioritaire)
        special_event:
          start_time: "2026-05-01 10:00" # Format yyyy-MM-dd HH:mm
          end_time: "2026-05-01 22:00"
          items:
            ENCHANTED_GOLDEN_APPLE:
              quantity: 2
              pricing:
                type: STATIC
                base_price: 50

📋 Options de Configuration

Vous pouvez personnaliser le comportement global de la rotation pour chaque shop :

OptionDescriptionValeur par défaut
enabledActive ou désactive le système de rotation pour ce shop.false
notify_playersSi true, envoie un message à tous les joueurs lors d'un changement d'items.false
notification_messageLe message à envoyer. Supporte les couleurs &."&e[Shop] &7New items available!"

📋 Règles de Fonctionnement

  1. Logique "Est-ce l'heure ?" : Le plugin vérifie chaque minute si l'un des sets correspond à l'heure actuelle.
  2. Priorité : Si plusieurs sets peuvent être actifs en même temps (ex: un set "Tous les jours" et un set "Lundi"), le premier défini dans le fichier prend la priorité.
  3. Inactivité : Si aucun set ne correspond à l'heure actuelle, le shop n'affichera aucun item de rotation.

📅 Formats de Temps

TypeFormatExempleDescription
RécurrentHH:mm14:30S'active tous les jours à cette heure.
Absoluyyyy-MM-dd HH:mm2026-12-25 08:00S'active une seule fois à cette date précise.

📅 Filtre de Jours (days)

Vous pouvez ajouter une liste days pour restreindre un horaire récurrent à des jours spécifiques.

Valeurs acceptées (Anglais) : MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY.

happy_hour_tuesdays:
  start_time: "18:00"
  end_time: "19:00"
  days: [TUESDAY]

💾 Persistance

Le système est conçu pour être robuste :

  • Il vérifie l'heure système réelle (pas de décalage si le serveur lag).
  • Il se recalibre automatiquement après un redémarrage.
  • Si vous changez la config et faites /horizons reload, la mise à jour est immédiate.

On this page

🛒 Configuration des Shops⚙️ Paramètres de Configuration🕐 Fréquence de mise à jour💡 Exemple d'utilisation🔊 Sons de l'Interface💬 Messages d'Interaction💡 Exemple complet💾 Système de Sauvegarde des Prix des shops🎮 Interactions avec les Shops💰 Format d'Affichage des Prix🏪 Association avec les NPCs🎯 Modes de TriggerMode NPC (par défaut)Mode CommandOuverture via Commande📝 Structure des Shops🏪 Configuration des NPCs⚙ Configuration des NPCs🎨 Configuration de l'Interface (GUI)📊 Hiérarchie de Priorité📦 Valeurs par Défaut (Fallback)🔧 Structure Complète📐 Cas de Figures et ExemplesCas 1: Shop Minimal (utilise tous les defaults)Cas 2: Petit Shop (3 lignes)Cas 3: Shop avec Layout Custom (style grille espacée)Cas 4: Defaults au niveau fichierCas 5: Configuration globale dans config.yml⚠️ Points Importants🖼️ Format d'Affichage des Items⚙ Configuration des ItemsSystème de Prix1. Prix Statique (STATIC)2. Prix Dynamique (SUPPLY_DEMAND / FIXED_PERCENTAGE)3. Prix par Paliers (TIERED)Fonctionnement des Prix DynamiquesMode SUPPLY_DEMAND (Offre et Demande)Mode FIXED_PERCENTAGE (Pourcentage Fixe)🔢 Système de quantités⚙ Configuration des quantités🤖 Fonctionnement des quantités🎯 Scope des Prix (GLOBAL / PER_TEAM)Modes disponiblesHiérarchie de prioritéConfigurationNiveau Global (config.yml)Niveau ShopNiveau ItemExemple d'utilisation🔄 Système de Rotation🎯 Fonctionnalités Clés⚙️ Configuration📋 Options de Configuration📋 Règles de Fonctionnement📅 Formats de Temps📅 Filtre de Jours (days)💾 Persistance