Files
Documentation/content/world/entities/inventory/containers.fr.md
2026-01-20 20:33:59 +01:00

23 KiB

title, type, weight
title type weight
Conteneurs docs 2

Les conteneurs gèrent des collections d'ItemStacks dans Hytale. Le système d'inventaire utilise ItemContainer comme abstraction de base avec Inventory comme conteneur multi-sections spécialisé du joueur.

Structure de l'Inventaire

Les inventaires des joueurs sont composés de plusieurs sections ItemContainer :

Inventory inv = player.getInventory();

// Obtenir les sections individuelles
ItemContainer storage = inv.getStorage();     // Stockage principal (36 slots par défaut)
ItemContainer hotbar = inv.getHotbar();       // Hotbar (9 slots par défaut)
ItemContainer armor = inv.getArmor();         // Emplacements d'armure
ItemContainer utility = inv.getUtility();     // Objets utilitaires (4 slots par défaut)
ItemContainer backpack = inv.getBackpack();   // Sac à dos (extensible)

// Conteneurs combinés pour opérations multi-sections
CombinedItemContainer hotbarFirst = inv.getCombinedHotbarFirst();
CombinedItemContainer storageFirst = inv.getCombinedStorageFirst();

IDs de Section

Chaque section a un ID constant pour les opérations :

Section ID Constante
Hotbar -1 Inventory.HOTBAR_SECTION_ID
Stockage -2 Inventory.STORAGE_SECTION_ID
Armure -3 Inventory.ARMOR_SECTION_ID
Utilitaire -5 Inventory.UTILITY_SECTION_ID
Outils -8 Inventory.TOOLS_SECTION_ID (déprécié)
Sac à dos -9 Inventory.BACKPACK_SECTION_ID

Bases d'ItemContainer

Lire les Objets

ItemContainer container = inv.getStorage();

// Obtenir la capacité (PAS getSize!)
short capacity = container.getCapacity();

// Obtenir l'objet au slot (slot est de type SHORT)
ItemStack item = container.getItemStack((short) 0);

// Vérifier si vide
boolean empty = container.isEmpty();

// Accès sécurisé aux objets
ItemStack stack = container.getItemStack((short) slot);
if (!ItemStack.isEmpty(stack)) {
    String itemId = stack.getItemId();
    int quantity = stack.getQuantity();
}

Définir des Objets

ItemContainer container = inv.getHotbar();

// Définir l'objet au slot - retourne une Transaction
ItemStackSlotTransaction transaction = container.setItemStackForSlot(
    (short) 0,
    new ItemStack("iron_sword", 1)
);

// Vérifier si l'opération a réussi
if (transaction.succeeded()) {
    // L'objet a été défini avec succès
}

// Vider un slot
container.setItemStackForSlot((short) 0, null);

Ajouter des Objets

ItemContainer container = inv.getStorage();
ItemStack toAdd = new ItemStack("wood_plank", 64);

// Ajouter au premier slot disponible (empile avec les objets existants d'abord)
ItemStackTransaction transaction = container.addItemStack(toAdd);

// Vérifier les objets restants qui n'ont pas pu rentrer
ItemStack remainder = transaction.getRemainder();
if (!ItemStack.isEmpty(remainder)) {
    // Certains objets n'ont pas pu rentrer
    int leftover = remainder.getQuantity();
}

// Ajouter à un slot spécifique
ItemStackSlotTransaction slotTransaction = container.addItemStackToSlot(
    (short) 5,
    toAdd
);

// Vérifier si le conteneur peut accueillir les objets avant d'ajouter
if (container.canAddItemStack(toAdd)) {
    container.addItemStack(toAdd);
}

Retirer des Objets

// Retirer d'un slot spécifique
SlotTransaction transaction = container.removeItemStackFromSlot((short) 0);

// Retirer une quantité spécifique du slot
ItemStackSlotTransaction removeTransaction = container.removeItemStackFromSlot(
    (short) 0,
    10  // quantité à retirer
);

// Retirer un type d'objet spécifique de n'importe où dans le conteneur
ItemStack toRemove = new ItemStack("iron_ore", 5);
ItemStackTransaction itemTransaction = container.removeItemStack(toRemove);

// Vérifier si les objets peuvent être retirés avant de retirer
if (container.canRemoveItemStack(toRemove)) {
    container.removeItemStack(toRemove);
}

Slots Actifs

Les joueurs ont des slots actifs pour la hotbar et les objets utilitaires :

Inventory inv = player.getInventory();

// Obtenir le slot actif de la hotbar (0-8)
byte activeHotbar = inv.getActiveHotbarSlot();

// Définir le slot actif de la hotbar
inv.setActiveHotbarSlot((byte) 3);

// Obtenir l'objet actuellement en main
ItemStack handItem = inv.getItemInHand();

// Obtenir/définir le slot utilitaire actif
byte activeUtility = inv.getActiveUtilitySlot();
inv.setActiveUtilitySlot((byte) 1);

// Obtenir l'objet utilitaire
ItemStack utilityItem = inv.getUtilityItem();

Déplacer des Objets

Entre les Slots

Inventory inv = player.getInventory();
ItemContainer storage = inv.getStorage();
ItemContainer hotbar = inv.getHotbar();

// Déplacer un objet d'un slot à un autre dans le même conteneur
MoveTransaction<SlotTransaction> transaction = storage.moveItemStackFromSlotToSlot(
    (short) 0,      // depuis slot
    64,             // quantité
    storage,        // vers conteneur
    (short) 5       // vers slot
);

// Déplacer entre différents conteneurs
storage.moveItemStackFromSlotToSlot(
    (short) 0,
    32,
    hotbar,
    (short) 0
);

// Utiliser moveItem de l'Inventory pour les déplacements par section
inv.moveItem(
    Inventory.STORAGE_SECTION_ID,   // depuis section
    5,                               // depuis slot
    10,                              // quantité
    Inventory.HOTBAR_SECTION_ID,    // vers section
    0                                // vers slot
);

Déplacement Intelligent

// Le déplacement intelligent considère le type d'objet pour un placement optimal
inv.smartMoveItem(
    Inventory.STORAGE_SECTION_ID,
    0,                              // slot
    64,                             // quantité
    SmartMoveType.EquipOrMergeStack // tente d'équiper l'armure ou fusionner les piles
);

Itérer les Conteneurs

ItemContainer container = inv.getStorage();

// Itérer tous les slots non vides
container.forEach((slot, itemStack) -> {
    getLogger().at(Level.INFO).log("Slot " + slot + ": " +
        itemStack.getItemId() + " x" + itemStack.getQuantity());
});

// Compter les objets correspondant à une condition
int swordCount = container.countItemStacks(
    stack -> stack.getItemId().contains("sword")
);

// Vérifier si le conteneur a des objets empilables
ItemStack testStack = new ItemStack("stone", 1);
boolean hasStackable = container.containsItemStacksStackableWith(testStack);

Vérifier le Contenu

ItemContainer container = inv.getStorage();

// Vérifier si l'inventaire contient un type et quantité d'objet spécifiques
public boolean hasItems(ItemContainer container, String itemId, int amount) {
    int count = container.countItemStacks(
        stack -> stack.getItemId().equals(itemId)
    );
    return count >= amount;
}

// Trouver le premier slot avec un objet spécifique
public short findSlotWithItem(ItemContainer container, String itemId) {
    for (short i = 0; i < container.getCapacity(); i++) {
        ItemStack stack = container.getItemStack(i);
        if (!ItemStack.isEmpty(stack) && stack.getItemId().equals(itemId)) {
            return i;
        }
    }
    return -1;  // Non trouvé
}

// Compter les slots vides
public int countEmptySlots(ItemContainer container) {
    int empty = 0;
    for (short i = 0; i < container.getCapacity(); i++) {
        if (ItemStack.isEmpty(container.getItemStack(i))) {
            empty++;
        }
    }
    return empty;
}

Vider les Conteneurs

ItemContainer container = inv.getStorage();

// Vider tout le conteneur
ClearTransaction transaction = container.clear();

// Lâcher tous les objets (retourne la liste des objets lâchés)
List<ItemStack> droppedItems = container.dropAllItemStacks();

// Retirer tous les objets (retourne la liste)
List<ItemStack> removedItems = container.removeAllItemStacks();

// Vider tout l'inventaire du joueur
inv.clear();

// Lâcher tout de l'inventaire du joueur
List<ItemStack> allDropped = inv.dropAllItemStacks();

Tri

Valeurs SortType disponibles : NAME, TYPE, RARITY

ItemContainer container = inv.getStorage();

// Trier les objets
container.sortItems(SortType.NAME);

// Trier via Inventory (sauvegarde aussi la préférence de tri)
inv.sortStorage(SortType.NAME);
inv.setSortType(SortType.RARITY);  // Ou TYPE

Événements de Conteneur

// S'enregistrer pour les événements de changement de conteneur
container.registerChangeEvent(event -> {
    ItemContainer changedContainer = event.container();
    Transaction transaction = event.transaction();

    getLogger().at(Level.INFO).log("Conteneur modifié !");
});

// Avec priorité
container.registerChangeEvent(EventPriority.EARLY, event -> {
    // Gérer tôt
});

Système de Transactions

Toutes les opérations de modification retournent des objets Transaction :

// Les transactions suivent le succès et les changements
ItemStackTransaction transaction = container.addItemStack(itemStack);

if (transaction.succeeded()) {
    ItemStack remainder = transaction.getRemainder();
    // ...
}

// Les transactions de slot incluent les infos du slot
ItemStackSlotTransaction slotTransaction = container.setItemStackForSlot(
    (short) 0,
    itemStack
);

if (slotTransaction.succeeded()) {
    short slot = slotTransaction.getSlot();
    ItemStack before = slotTransaction.getSlotBefore();
    ItemStack after = slotTransaction.getSlotAfter();
}

Paramètres d'Opération

La plupart des opérations de conteneur supportent des paramètres optionnels :

// Valeurs par défaut
DEFAULT_ADD_ALL_OR_NOTHING = false;    // Ajouts partiels autorisés
DEFAULT_REMOVE_ALL_OR_NOTHING = true;  // Uniquement retraits complets
DEFAULT_FULL_STACKS = false;           // Peut diviser les piles
DEFAULT_EXACT_AMOUNT = true;           // Quantités exactes uniquement
DEFAULT_FILTER = true;                 // Applique les filtres de slot

// Ajouter avec paramètres
container.addItemStack(itemStack, allOrNothing, fullStacks, filter);

// allOrNothing: si true, échoue entièrement si tous les objets ne rentrent pas
// fullStacks: si true, remplit uniquement les slots vides (pas d'empilement)
// filter: si true, respecte les filtres de slot

Retrait par Matériau et Ressource

Les conteneurs supportent le retrait d'objets par type de matériau ou de ressource (utilisé pour le craft) :

{{< callout type="info" >}} Constructeur MaterialQuantity : MaterialQuantity(itemId, resourceTypeId, tag, quantity, metadata)

Au moins un parmi itemId, resourceTypeId, ou tag doit être non-null. {{< /callout >}}

// Retirer par matériau en utilisant itemId
MaterialQuantity materialByItem = new MaterialQuantity("iron_ingot", null, null, 5, null);
if (container.canRemoveMaterial(materialByItem)) {
    MaterialTransaction transaction = container.removeMaterial(materialByItem);
}

// Retirer par matériau en utilisant resourceTypeId
MaterialQuantity materialByResource = new MaterialQuantity(null, "iron", null, 5, null);
if (container.canRemoveMaterial(materialByResource)) {
    MaterialTransaction transaction = container.removeMaterial(materialByResource);
}

// Retirer par type de ressource (constructeur plus simple)
ResourceQuantity resource = new ResourceQuantity("wood", 10);
if (container.canRemoveResource(resource)) {
    ResourceTransaction transaction = container.removeResource(resource);
}

// Retirer par index de tag
if (container.canRemoveTag(tagIndex, quantity)) {
    TagTransaction transaction = container.removeTag(tagIndex, quantity);
}

// Retrait en masse
List<MaterialQuantity> materials = List.of(
    new MaterialQuantity("iron_ingot", null, null, 2, null),
    new MaterialQuantity(null, null, "Wood", 5, null)  // Avec tag
);
if (container.canRemoveMaterials(materials)) {
    container.removeMaterials(materials);
}

Opérations en Masse

Ajouter ou retirer plusieurs objets à la fois :

// Ajouter plusieurs objets
List<ItemStack> items = List.of(
    new ItemStack("iron_ore", 10),
    new ItemStack("gold_ore", 5)
);

if (container.canAddItemStacks(items)) {
    ListTransaction<ItemStackTransaction> transaction = container.addItemStacks(items);
}

// Retirer plusieurs objets
if (container.canRemoveItemStacks(items)) {
    container.removeItemStacks(items);
}

// Ajouter les objets dans l'ordre (préserve les positions de slot)
container.addItemStacksOrdered(items);
container.addItemStacksOrdered((short) 5, items);  // À partir du slot 5

Opérations de Déplacement Avancées

// Déplacer tous les objets vers un autre conteneur
ListTransaction<MoveTransaction<ItemStackTransaction>> result =
    storage.moveAllItemStacksTo(hotbar, backpack);

// Déplacer tous les objets correspondant à une condition
storage.moveAllItemStacksTo(
    item -> item.getItemId().contains("ore"),
    hotbar
);

// Quick stack : déplace uniquement les objets qui peuvent s'empiler avec des objets existants
storage.quickStackTo(hotbar);

// Combiner les petites piles dans un slot
container.combineItemStacksIntoSlot(targetContainer, (short) 0);

// Échanger des objets entre conteneurs
storage.swapItems(
    (short) 0,         // position source
    hotbar,            // conteneur cible
    (short) 0,         // position destination
    (short) 5          // nombre de slots à échanger
);

Opérations de Remplacement

// Remplacer l'objet dans le slot s'il correspond à l'attendu
ItemStackSlotTransaction transaction = container.replaceItemStackInSlot(
    (short) 0,
    expectedItem,  // doit correspondre à l'objet actuel pour continuer
    newItem
);

// Remplacer tous les objets avec une fonction
container.replaceAll((slot, existing) -> {
    if (existing.getItemId().equals("old_item")) {
        return new ItemStack("new_item", existing.getQuantity());
    }
    return existing;
});

Filtres de Slot

Contrôler quels objets peuvent aller dans quels slots :

// Définir un filtre global pour le conteneur
container.setGlobalFilter(FilterType.WHITELIST);

// Définir un filtre pour un slot spécifique
container.setSlotFilter(
    FilterActionType.ADD,     // Filtre sur les opérations d'ajout
    (short) 0,                // Slot
    slotFilter                // Implémentation du filtre
);

Bonnes Pratiques

{{< callout type="info" >}} Conseils pour les Conteneurs :

  • Les indices de slot sont short, pas int - castez correctement
  • Vérifiez toujours ItemStack.isEmpty(stack) - gère null et vide
  • Utilisez getQuantity() pas getCount()
  • Vérifiez le succès de la transaction avec succeeded()
  • Utilisez les conteneurs combinés pour les opérations multi-sections
  • Les changements d'inventaire du joueur déclenchent LivingEntityInventoryChangeEvent {{< /callout >}}
// Pattern sécurisé pour travailler avec les conteneurs
public void safeAddItem(ItemContainer container, ItemStack item) {
    if (ItemStack.isEmpty(item)) {
        return;
    }

    if (!container.canAddItemStack(item)) {
        // Gérer le conteneur plein
        return;
    }

    ItemStackTransaction transaction = container.addItemStack(item);
    if (!transaction.succeeded()) {
        // Gérer l'échec
    }
}

Référence API ItemContainer

Méthodes Principales

Méthode Retour Description
getCapacity() short Nombre total de slots
getItemStack(short) ItemStack? Obtenir l'objet au slot
isEmpty() boolean True si aucun objet
clone() ItemContainer Cloner le conteneur
clear() ClearTransaction Retirer tous les objets

Opérations d'Ajout

Méthode Retour Description
canAddItemStack(ItemStack) boolean Vérifier si peut ajouter
canAddItemStack(ItemStack, fullStacks, filter) boolean Vérifier avec options
addItemStack(ItemStack) ItemStackTransaction Ajouter au premier disponible
addItemStack(ItemStack, allOrNothing, fullStacks, filter) ItemStackTransaction Ajouter avec options
canAddItemStackToSlot(short, ItemStack, allOrNothing, filter) boolean Vérifier si peut ajouter au slot
addItemStackToSlot(short, ItemStack) ItemStackSlotTransaction Ajouter à un slot spécifique
addItemStackToSlot(short, ItemStack, allOrNothing, filter) ItemStackSlotTransaction Ajouter au slot avec options
canAddItemStacks(List<ItemStack>) boolean Vérifier si peut ajouter plusieurs
addItemStacks(List<ItemStack>) ListTransaction Ajouter plusieurs objets
addItemStacksOrdered(List<ItemStack>) ListTransaction Ajouter dans l'ordre
addItemStacksOrdered(short offset, List<ItemStack>) ListTransaction Ajouter dans l'ordre depuis offset

Opérations de Définition

Méthode Retour Description
setItemStackForSlot(short, ItemStack) ItemStackSlotTransaction Définir l'objet au slot
setItemStackForSlot(short, ItemStack, filter) ItemStackSlotTransaction Définir avec option filtre
replaceItemStackInSlot(short, ItemStack attendu, ItemStack nouveau) ItemStackSlotTransaction Remplacer si correspondance
replaceAll(SlotReplacementFunction) ListTransaction Remplacer tous les objets

Opérations de Retrait

Méthode Retour Description
removeItemStackFromSlot(short) SlotTransaction Retirer tout le slot
removeItemStackFromSlot(short, filter) SlotTransaction Retirer avec filtre
removeItemStackFromSlot(short, quantity) ItemStackSlotTransaction Retirer une quantité
removeItemStackFromSlot(short, ItemStack, quantity) ItemStackSlotTransaction Retirer objet correspondant
canRemoveItemStack(ItemStack) boolean Vérifier si peut retirer
removeItemStack(ItemStack) ItemStackTransaction Retirer type d'objet
canRemoveItemStacks(List<ItemStack>) boolean Vérifier si peut retirer plusieurs
removeItemStacks(List<ItemStack>) ListTransaction Retirer plusieurs objets
removeAllItemStacks() List<ItemStack> Retirer et retourner tous
dropAllItemStacks() List<ItemStack> Lâcher tous (respecte cantDrop)
dropAllItemStacks(filter) List<ItemStack> Lâcher avec option filtre

Retrait Matériau/Ressource/Tag

Méthode Retour Description
canRemoveMaterial(MaterialQuantity) boolean Vérifier retrait matériau
removeMaterial(MaterialQuantity) MaterialTransaction Retirer par matériau
removeMaterialFromSlot(short, MaterialQuantity) MaterialSlotTransaction Retirer matériau du slot
canRemoveMaterials(List<MaterialQuantity>) boolean Vérifier plusieurs matériaux
removeMaterials(List<MaterialQuantity>) ListTransaction Retirer plusieurs matériaux
canRemoveResource(ResourceQuantity) boolean Vérifier retrait ressource
removeResource(ResourceQuantity) ResourceTransaction Retirer par ressource
removeResourceFromSlot(short, ResourceQuantity) ResourceSlotTransaction Retirer ressource du slot
canRemoveResources(List<ResourceQuantity>) boolean Vérifier plusieurs ressources
removeResources(List<ResourceQuantity>) ListTransaction Retirer plusieurs ressources
canRemoveTag(tagIndex, quantity) boolean Vérifier retrait tag
removeTag(tagIndex, quantity) TagTransaction Retirer par tag
removeTagFromSlot(short, tagIndex, quantity) TagSlotTransaction Retirer tag du slot

Opérations de Déplacement

Méthode Retour Description
moveItemStackFromSlot(short, ItemContainer) MoveTransaction Déplacer slot vers conteneur
moveItemStackFromSlot(short, quantity, ItemContainer) MoveTransaction Déplacer quantité
moveItemStackFromSlot(short, ItemContainer...) ListTransaction Déplacer vers plusieurs conteneurs
moveItemStackFromSlotToSlot(short, quantity, ItemContainer, short) MoveTransaction Déplacer vers slot spécifique
moveAllItemStacksTo(ItemContainer...) ListTransaction Déplacer tous les objets
moveAllItemStacksTo(Predicate, ItemContainer...) ListTransaction Déplacer objets correspondants
quickStackTo(ItemContainer...) ListTransaction Déplacer uniquement empilables
combineItemStacksIntoSlot(ItemContainer, short) ListTransaction Combiner piles dans slot
swapItems(short srcPos, ItemContainer, short destPos, short length) ListTransaction Échanger plages d'objets

Méthodes Utilitaires

Méthode Retour Description
forEach(ShortObjectConsumer) void Itérer slots non vides
forEachWithMeta(consumer, meta) void Itérer avec métadonnées
countItemStacks(Predicate) int Compter objets correspondants (quantité totale)
containsItemStacksStackableWith(ItemStack) boolean Vérifier objets empilables
sortItems(SortType) ListTransaction Trier conteneur
registerChangeEvent(Consumer) EventRegistration Écouter les changements
registerChangeEvent(EventPriority, Consumer) EventRegistration Écouter avec priorité
setGlobalFilter(FilterType) void Définir filtre conteneur
setSlotFilter(FilterActionType, short, SlotFilter) void Définir filtre slot
containsContainer(ItemContainer) boolean Vérifier si contient conteneur

Méthodes Statiques

Méthode Retour Description
copy(from, to, remainder) T Copier objets entre conteneurs
ensureContainerCapacity(container, capacity, supplier, remainder) T S'assurer de la capacité
getNewContainer(capacity, supplier) ItemContainer Créer ou obtenir vide
getMatchingResourceType(Item, resourceId) ItemResourceType? Trouver type ressource pour objet
validateQuantity(int) void Lance exception si < 0
validateSlotIndex(short, capacity) void Lance exception si hors limites

Constantes Statiques

Champ Type Description
CODEC CodecMapCodec<ItemContainer> Codec de sérialisation
DEFAULT_ADD_ALL_OR_NOTHING boolean false
DEFAULT_REMOVE_ALL_OR_NOTHING boolean true
DEFAULT_FULL_STACKS boolean false
DEFAULT_EXACT_AMOUNT boolean true
DEFAULT_FILTER boolean true

Classes Imbriquées

Classe Description
ItemContainerChangeEvent Record événement avec container() et transaction()

Référence API Inventory

Méthode Retour Description
getStorage() ItemContainer Section de stockage principal
getHotbar() ItemContainer Section hotbar
getArmor() ItemContainer Section armure
getUtility() ItemContainer Section utilitaire
getBackpack() ItemContainer Section sac à dos
getSectionById(int) ItemContainer? Obtenir section par ID
getItemInHand() ItemStack? Objet actuellement tenu
getActiveHotbarSlot() byte Slot actif de la hotbar
setActiveHotbarSlot(byte) void Définir hotbar active
getCombinedHotbarFirst() CombinedItemContainer Hotbar+Stockage combinés
moveItem(...) void Déplacer entre sections
clear() void Vider toutes les sections