355 lines
11 KiB
Markdown
355 lines
11 KiB
Markdown
---
|
|
title: ItemStacks
|
|
type: docs
|
|
weight: 1
|
|
---
|
|
|
|
ItemStack représente une pile d'objets dans Hytale avec quantité, durabilité et métadonnées.
|
|
|
|
## Créer des ItemStacks
|
|
|
|
Les ItemStacks sont créés en utilisant des constructeurs avec un ID d'objet :
|
|
|
|
```java
|
|
// Créer par ID d'objet
|
|
ItemStack sword = new ItemStack("iron_sword");
|
|
|
|
// Créer avec quantité
|
|
ItemStack materials = new ItemStack("wood_plank", 64);
|
|
|
|
// Créer avec quantité et métadonnées
|
|
BsonDocument metadata = new BsonDocument();
|
|
ItemStack customItem = new ItemStack("iron_sword", 1, metadata);
|
|
|
|
// Créer avec tous les paramètres (durabilité)
|
|
ItemStack damagedSword = new ItemStack("iron_sword", 1, 50.0, 100.0, null);
|
|
// Paramètres: itemId, quantity, durability, maxDurability, metadata
|
|
```
|
|
|
|
## Propriétés d'ItemStack
|
|
|
|
```java
|
|
ItemStack stack = new ItemStack("iron_sword", 1);
|
|
|
|
// Obtenir l'ID de l'objet
|
|
String itemId = stack.getItemId(); // "iron_sword"
|
|
|
|
// Obtenir l'asset Item
|
|
Item item = stack.getItem();
|
|
|
|
// Obtenir la quantité (PAS getCount!)
|
|
int quantity = stack.getQuantity();
|
|
|
|
// Vérifier si vide
|
|
boolean empty = stack.isEmpty();
|
|
|
|
// Vérifier la validité
|
|
boolean valid = stack.isValid();
|
|
|
|
// Durabilité
|
|
double durability = stack.getDurability();
|
|
double maxDurability = stack.getMaxDurability();
|
|
boolean unbreakable = stack.isUnbreakable(); // true si maxDurability <= 0
|
|
boolean broken = stack.isBroken(); // true si durability == 0
|
|
```
|
|
|
|
## Modifier les ItemStacks
|
|
|
|
ItemStack utilise un pattern `with*` qui retourne de NOUVELLES instances :
|
|
|
|
```java
|
|
ItemStack stack = new ItemStack("iron_sword", 1);
|
|
|
|
// Changer la quantité - retourne un NOUVEL ItemStack ou null si quantité est 0
|
|
ItemStack moreItems = stack.withQuantity(32);
|
|
|
|
// Changer la durabilité
|
|
ItemStack damaged = stack.withDurability(50.0);
|
|
|
|
// Augmenter la durabilité
|
|
ItemStack repaired = stack.withIncreasedDurability(25.0);
|
|
|
|
// Restaurer la durabilité complète
|
|
ItemStack fullyRepaired = stack.withRestoredDurability(100.0);
|
|
|
|
// Changer la durabilité max
|
|
ItemStack stronger = stack.withMaxDurability(200.0);
|
|
|
|
// Changer l'état (pour les objets avec états)
|
|
ItemStack newState = stack.withState("activated");
|
|
|
|
// Ajouter/modifier les métadonnées
|
|
ItemStack withMeta = stack.withMetadata(metadataDocument);
|
|
|
|
// Ajouter une valeur de métadonnée spécifique
|
|
ItemStack tagged = stack.withMetadata("CustomKey", Codec.STRING, "CustomValue");
|
|
```
|
|
|
|
{{< callout type="warning" >}}
|
|
**Important :** `withQuantity(0)` retourne `null`, pas un ItemStack vide. Vérifiez toujours null quand vous diminuez la quantité !
|
|
{{< /callout >}}
|
|
|
|
## La Constante EMPTY
|
|
|
|
Utilisez `ItemStack.EMPTY` pour les piles vides :
|
|
|
|
```java
|
|
// Instance vide statique (singleton)
|
|
ItemStack empty = ItemStack.EMPTY;
|
|
|
|
// Vérifier si vide
|
|
if (stack.isEmpty()) {
|
|
// La pile est vide
|
|
}
|
|
|
|
// Méthode helper statique
|
|
if (ItemStack.isEmpty(stack)) {
|
|
// Gère les piles null et vides
|
|
}
|
|
```
|
|
|
|
## Comparer les ItemStacks
|
|
|
|
```java
|
|
ItemStack a = new ItemStack("iron_sword", 1);
|
|
ItemStack b = new ItemStack("iron_sword", 5);
|
|
ItemStack c = new ItemStack("diamond_sword", 1);
|
|
|
|
// Vérifier si empilables (même itemId, durability, maxDurability ET metadata)
|
|
// Note: Des quantités différentes peuvent s'empiler, mais les durabilités doivent correspondre exactement
|
|
boolean canStack = a.isStackableWith(b);
|
|
|
|
// Vérifier type équivalent (même itemId et metadata, ignore les durabilités)
|
|
boolean sameType = a.isEquivalentType(b);
|
|
|
|
// Vérifier même type d'objet seulement (juste itemId)
|
|
boolean sameItem = ItemStack.isSameItemType(a, c); // false
|
|
|
|
// Helpers statiques (gèrent les nulls en sécurité)
|
|
ItemStack.isStackableWith(a, b);
|
|
ItemStack.isEquivalentType(a, b);
|
|
```
|
|
|
|
## Travailler avec les Métadonnées
|
|
|
|
ItemStack supporte les métadonnées BSON pour les données personnalisées :
|
|
|
|
```java
|
|
// Créer un codec de métadonnée
|
|
KeyedCodec<String> OWNER_KEY = new KeyedCodec<>("Owner", Codec.STRING);
|
|
|
|
// Ajouter des métadonnées
|
|
ItemStack withOwner = stack.withMetadata(OWNER_KEY, "PlayerName");
|
|
|
|
// Lire les métadonnées
|
|
String owner = stack.getFromMetadataOrNull(OWNER_KEY);
|
|
|
|
// Lire avec clé et codec
|
|
Integer level = stack.getFromMetadataOrNull("Level", Codec.INTEGER);
|
|
|
|
// Lire avec défaut depuis BuilderCodec
|
|
MyData data = stack.getFromMetadataOrDefault("Data", MyData.CODEC);
|
|
```
|
|
|
|
## Objets de Bloc
|
|
|
|
Vérifier si un objet peut être placé comme bloc :
|
|
|
|
```java
|
|
ItemStack stack = new ItemStack("stone", 1);
|
|
|
|
// Obtenir la clé de bloc associée (null si pas un objet de bloc)
|
|
String blockKey = stack.getBlockKey();
|
|
if (blockKey != null) {
|
|
// Cet objet peut être placé comme bloc
|
|
}
|
|
|
|
// Vérifier via l'asset Item
|
|
Item item = stack.getItem();
|
|
if (item.hasBlockType()) {
|
|
String blockId = item.getBlockId();
|
|
}
|
|
```
|
|
|
|
## Patterns Courants
|
|
|
|
### Consommer des Objets
|
|
|
|
```java
|
|
public ItemStack consumeOne(ItemStack stack) {
|
|
if (stack == null || stack.isEmpty()) {
|
|
return null;
|
|
}
|
|
|
|
int newQuantity = stack.getQuantity() - 1;
|
|
|
|
// withQuantity retourne null si quantité est 0
|
|
return stack.withQuantity(newQuantity);
|
|
}
|
|
|
|
// Utilisation avec conteneur
|
|
public void useItem(ItemContainer container, short slot) {
|
|
ItemStack current = container.getItemStack(slot);
|
|
ItemStack remaining = consumeOne(current);
|
|
|
|
// remaining peut être null si la pile est épuisée
|
|
container.setItemStackForSlot(slot, remaining);
|
|
}
|
|
```
|
|
|
|
### Vérifier le Type d'Objet
|
|
|
|
```java
|
|
public boolean isHoldingSword(ItemStack hand) {
|
|
if (hand == null || hand.isEmpty()) {
|
|
return false;
|
|
}
|
|
|
|
// Vérifier le type d'objet par ID
|
|
return hand.getItemId().contains("sword");
|
|
|
|
// Ou vérifier via l'asset Item
|
|
// return hand.getItem().getCategory().equals("weapon");
|
|
}
|
|
```
|
|
|
|
### Diviser des Piles
|
|
|
|
```java
|
|
public ItemStack[] splitStack(ItemStack stack, int splitAmount) {
|
|
if (stack == null || stack.isEmpty()) {
|
|
return null;
|
|
}
|
|
|
|
int currentQuantity = stack.getQuantity();
|
|
if (splitAmount >= currentQuantity) {
|
|
return new ItemStack[] { stack, null };
|
|
}
|
|
|
|
// Créer deux piles
|
|
ItemStack remaining = stack.withQuantity(currentQuantity - splitAmount);
|
|
ItemStack split = stack.withQuantity(splitAmount);
|
|
|
|
return new ItemStack[] { remaining, split };
|
|
}
|
|
```
|
|
|
|
### Fusionner des Piles
|
|
|
|
```java
|
|
public ItemStack[] mergeStacks(ItemStack target, ItemStack source) {
|
|
if (!target.isStackableWith(source)) {
|
|
return new ItemStack[] { target, source }; // Ne peut pas fusionner
|
|
}
|
|
|
|
int maxStack = target.getItem().getMaxStack();
|
|
int totalQuantity = target.getQuantity() + source.getQuantity();
|
|
|
|
if (totalQuantity <= maxStack) {
|
|
// Fusion complète
|
|
return new ItemStack[] {
|
|
target.withQuantity(totalQuantity),
|
|
null
|
|
};
|
|
}
|
|
|
|
// Fusion partielle
|
|
return new ItemStack[] {
|
|
target.withQuantity(maxStack),
|
|
source.withQuantity(totalQuantity - maxStack)
|
|
};
|
|
}
|
|
```
|
|
|
|
## Bonnes Pratiques
|
|
|
|
{{< callout type="info" >}}
|
|
**Rappelez-vous :**
|
|
- Utilisez `getQuantity()` pas `getCount()` - Hytale utilise "quantity"
|
|
- `withQuantity(0)` retourne `null` - vérifiez cela !
|
|
- Utilisez `ItemStack.isEmpty(stack)` pour gérer null et vide
|
|
- Les ItemStacks sont principalement immuables - les méthodes `with*` retournent de nouvelles instances
|
|
- Utilisez `isStackableWith()` avant de tenter de fusionner des piles
|
|
- `ResourceType.Id` ne doit pas être null lors de la création d'objets via codecs
|
|
{{< /callout >}}
|
|
|
|
```java
|
|
// Bon : Gérer null de withQuantity
|
|
ItemStack result = stack.withQuantity(newQuantity);
|
|
if (result == null) {
|
|
// Pile épuisée, gérer appropriément
|
|
}
|
|
|
|
// Bon : Vérification vide sécurisée
|
|
if (ItemStack.isEmpty(stack)) {
|
|
// Gère à la fois null et ItemStack.EMPTY vide
|
|
}
|
|
|
|
// Mauvais : Ignorer la valeur retournée
|
|
stack.withQuantity(10); // Retourne nouvelle pile, original inchangé !
|
|
```
|
|
|
|
## Référence API ItemStack
|
|
|
|
### Méthodes d'Instance
|
|
|
|
| Méthode | Retour | Description |
|
|
|--------|---------|-------------|
|
|
| `getItemId()` | `String` | L'identifiant du type d'objet |
|
|
| `getItem()` | `Item` | L'asset Item (retourne `Item.UNKNOWN` si non trouvé) |
|
|
| `getQuantity()` | `int` | Taille de la pile |
|
|
| `getDurability()` | `double` | Durabilité actuelle |
|
|
| `getMaxDurability()` | `double` | Durabilité maximum |
|
|
| `isEmpty()` | `boolean` | True si itemId égale "Empty" |
|
|
| `isUnbreakable()` | `boolean` | True si maxDurability <= 0 |
|
|
| `isBroken()` | `boolean` | True si PAS incassable ET durability == 0 |
|
|
| `isValid()` | `boolean` | True si vide OU l'asset existe |
|
|
| `isStackableWith(ItemStack)` | `boolean` | Même itemId, durability, maxDurability, metadata |
|
|
| `isEquivalentType(ItemStack)` | `boolean` | Même itemId et metadata (ignore durabilité) |
|
|
| `getBlockKey()` | `String?` | ID bloc si plaçable, null sinon |
|
|
| `getOverrideDroppedItemAnimation()` | `boolean` | Flag d'override animation |
|
|
| `getMetadata()` | `BsonDocument?` | **Déprécié** - Retourne metadata clonée |
|
|
| `getFromMetadataOrNull(KeyedCodec)` | `T?` | Obtenir valeur metadata typée |
|
|
| `getFromMetadataOrNull(String, Codec)` | `T?` | Obtenir metadata par clé |
|
|
| `getFromMetadataOrDefault(String, BuilderCodec)` | `T` | Obtenir metadata avec défaut |
|
|
|
|
### Méthodes de Modification (retournent nouveau ItemStack)
|
|
|
|
| Méthode | Retour | Description |
|
|
|--------|---------|-------------|
|
|
| `withQuantity(int)` | `ItemStack?` | **Retourne null si quantité est 0** |
|
|
| `withDurability(double)` | `ItemStack` | Borné à [0, maxDurability] |
|
|
| `withMaxDurability(double)` | `ItemStack` | Borne aussi la durabilité actuelle |
|
|
| `withIncreasedDurability(double)` | `ItemStack` | Ajoute à la durabilité |
|
|
| `withRestoredDurability(double)` | `ItemStack` | Définit durabilité et max |
|
|
| `withState(String)` | `ItemStack` | Change l'état de l'objet |
|
|
| `withMetadata(BsonDocument)` | `ItemStack` | Remplace toutes les metadata |
|
|
| `withMetadata(KeyedCodec, T)` | `ItemStack` | Définit metadata typée |
|
|
| `withMetadata(String, Codec, T)` | `ItemStack` | Définit metadata par clé |
|
|
| `withMetadata(String, BsonValue)` | `ItemStack` | Définit valeur BSON brute |
|
|
| `setOverrideDroppedItemAnimation(boolean)` | `void` | **Mute en place** |
|
|
|
|
### Champs Statiques
|
|
|
|
| Champ | Type | Description |
|
|
|-------|------|-------------|
|
|
| `EMPTY` | `ItemStack` | Pile vide singleton (itemId = "Empty") |
|
|
| `EMPTY_ARRAY` | `ItemStack[]` | Constante tableau vide |
|
|
| `CODEC` | `BuilderCodec<ItemStack>` | Codec de sérialisation |
|
|
|
|
### Méthodes Statiques
|
|
|
|
| Méthode | Retour | Description |
|
|
|--------|---------|-------------|
|
|
| `isEmpty(ItemStack)` | `boolean` | Vérification vide null-safe |
|
|
| `isStackableWith(ItemStack, ItemStack)` | `boolean` | Vérification empilable null-safe |
|
|
| `isEquivalentType(ItemStack, ItemStack)` | `boolean` | Vérification type null-safe |
|
|
| `isSameItemType(ItemStack, ItemStack)` | `boolean` | Compare itemId seulement |
|
|
| `fromPacket(ItemQuantity)` | `ItemStack?` | Créer depuis paquet réseau |
|
|
|
|
### Classes Imbriquées
|
|
|
|
| Classe | Description |
|
|
|-------|-------------|
|
|
| `ItemStack.Metadata` | Contient constante `BLOCK_STATE` pour clé metadata état bloc |
|