This commit is contained in:
2026-01-20 20:33:59 +01:00
commit b16a40e431
583 changed files with 87339 additions and 0 deletions

View File

@@ -0,0 +1,430 @@
---
title: Transactions
type: docs
weight: 3
---
Les transactions suivent les résultats des opérations d'inventaire dans Hytale. Chaque modification d'un `ItemContainer` retourne un objet Transaction qui décrit ce qui s'est passé.
## Interface Transaction
Toutes les transactions implémentent l'interface de base `Transaction` :
```java
public interface Transaction {
// L'opération a-t-elle réussi ?
boolean succeeded();
// Un slot spécifique a-t-il été modifié ?
boolean wasSlotModified(short slot);
}
```
## Types de Transactions
### SlotTransaction
Suit les changements d'un seul slot :
```java
SlotTransaction transaction = container.removeItemStackFromSlot((short) 0);
if (transaction.succeeded()) {
// Ce qui était dans le slot avant
ItemStack before = transaction.getSlotBefore();
// Ce qui est dans le slot maintenant
ItemStack after = transaction.getSlotAfter();
// L'objet qui a été retiré/sorti
ItemStack output = transaction.getOutput();
// Quel slot a été affecté
short slot = transaction.getSlot();
// Quel type d'action (ADD, REMOVE, REPLACE)
ActionType action = transaction.getAction();
}
```
### ItemStackSlotTransaction
Transaction de slot étendue avec des détails supplémentaires :
```java
ItemStackSlotTransaction transaction = container.setItemStackForSlot(
(short) 0,
new ItemStack("iron_sword", 1)
);
if (transaction.succeeded()) {
short slot = transaction.getSlot();
ItemStack before = transaction.getSlotBefore();
ItemStack after = transaction.getSlotAfter();
// Vérifier les options utilisées
boolean wasFiltered = transaction.isFilter();
boolean wasAllOrNothing = transaction.isAllOrNothing();
}
```
### ItemStackTransaction
Suit les opérations qui peuvent affecter plusieurs slots :
```java
ItemStack toAdd = new ItemStack("stone", 128);
ItemStackTransaction transaction = container.addItemStack(toAdd);
if (transaction.succeeded()) {
// Objets qui n'ont pas pu rentrer (null si tous ont rentré)
ItemStack remainder = transaction.getRemainder();
// Objet original qu'on a essayé d'ajouter
ItemStack query = transaction.getQuery();
// Liste de toutes les transactions de slot qui ont eu lieu
List<ItemStackSlotTransaction> slotTransactions = transaction.getSlotTransactions();
for (ItemStackSlotTransaction slotTx : slotTransactions) {
getLogger().at(Level.INFO).log("Slot modifié " + slotTx.getSlot());
}
}
```
### MoveTransaction
Suit le déplacement d'objets entre conteneurs :
```java
MoveTransaction<SlotTransaction> transaction = storage.moveItemStackFromSlotToSlot(
(short) 0,
32,
hotbar,
(short) 0
);
if (transaction.succeeded()) {
// Transaction pour le retrait de la source
SlotTransaction removeTransaction = transaction.getRemoveTransaction();
// Transaction pour l'ajout à la destination
SlotTransaction addTransaction = transaction.getAddTransaction();
// Le conteneur de destination
ItemContainer destination = transaction.getOtherContainer();
// Direction du déplacement
MoveType moveType = transaction.getMoveType();
}
```
### ListTransaction
Encapsule plusieurs transactions :
```java
List<ItemStack> items = List.of(
new ItemStack("stone", 64),
new ItemStack("wood", 64)
);
ListTransaction<ItemStackTransaction> transaction = container.addItemStacks(items);
if (transaction.succeeded()) {
List<ItemStackTransaction> results = transaction.getList();
for (ItemStackTransaction result : results) {
if (result.succeeded()) {
ItemStack remainder = result.getRemainder();
// ...
}
}
}
```
## ActionType
Les opérations sont catégorisées par type d'action :
```java
public enum ActionType {
SET, // Objets définis (add=true, remove=false, destroy=true)
ADD, // Objets ajoutés au slot (add=true, remove=false, destroy=false)
REMOVE, // Objets retirés du slot (add=false, remove=true, destroy=false)
REPLACE // Contenu du slot remplacé (add=true, remove=true, destroy=false)
}
// Vérifier les caractéristiques de l'action
if (action.isAdd()) { /* opération ajoute des objets */ }
if (action.isRemove()) { /* opération retire des objets */ }
if (action.isDestroy()) { /* opération détruit le contenu du slot */ }
```
## MoveType
Direction des opérations de déplacement :
```java
public enum MoveType {
MOVE_TO_SELF, // Objets déplacés VERS ce conteneur
MOVE_FROM_SELF // Objets déplacés DEPUIS ce conteneur
}
```
## Patterns Courants
### Vérifier Avant de Modifier
```java
// Pattern sûr : vérifier d'abord, puis exécuter
public boolean safeTransfer(ItemContainer from, ItemContainer to, String itemId, int amount) {
ItemStack toRemove = new ItemStack(itemId, amount);
// Vérifier que les deux opérations peuvent réussir
if (!from.canRemoveItemStack(toRemove)) {
return false; // Pas assez d'objets
}
if (!to.canAddItemStack(toRemove)) {
return false; // Pas de place
}
// Exécuter le retrait
ItemStackTransaction removeResult = from.removeItemStack(toRemove);
if (!removeResult.succeeded()) {
return false;
}
// Exécuter l'ajout
ItemStack removed = removeResult.getQuery();
ItemStackTransaction addResult = to.addItemStack(removed);
// Gérer les restes éventuels
ItemStack remainder = addResult.getRemainder();
if (!ItemStack.isEmpty(remainder)) {
// Remettre les restes
from.addItemStack(remainder);
}
return true;
}
```
### Gérer les Restes
```java
public void giveItemSafe(Player player, String itemId, int quantity) {
ItemContainer storage = player.getInventory().getStorage();
ItemStack item = new ItemStack(itemId, quantity);
ItemStackTransaction result = storage.addItemStack(item);
if (!result.succeeded()) {
player.sendMessage(Message.raw("Inventaire plein !"));
return;
}
ItemStack remainder = result.getRemainder();
if (!ItemStack.isEmpty(remainder)) {
player.sendMessage(Message.raw(
"Seulement reçu " + (quantity - remainder.getQuantity()) + " objets, " +
"inventaire plein !"
));
}
}
```
### Opérations Atomiques
```java
// allOrNothing=true garantit que les opérations partielles ne se produisent pas
public boolean buyItem(Player player, String itemId, int price, int quantity) {
Inventory inv = player.getInventory();
ItemContainer storage = inv.getStorage();
ItemStack currency = new ItemStack("gold_coin", price);
ItemStack item = new ItemStack(itemId, quantity);
// Vérifier que les deux opérations peuvent réussir complètement
if (!storage.canRemoveItemStack(currency)) {
player.sendMessage(Message.raw("Pas assez d'or !"));
return false;
}
if (!storage.canAddItemStack(item)) {
player.sendMessage(Message.raw("Inventaire plein !"));
return false;
}
// Retirer la monnaie avec allOrNothing=true
ItemStackTransaction removeResult = storage.removeItemStack(currency, true, true);
if (!removeResult.succeeded()) {
return false;
}
// Ajouter l'objet
ItemStackTransaction addResult = storage.addItemStack(item, true, false, true);
if (!addResult.succeeded()) {
// Annuler : rendre la monnaie
storage.addItemStack(currency);
return false;
}
return true;
}
```
### Suivre les Changements
```java
// Utiliser wasSlotModified pour vérifier des slots spécifiques
public void onContainerChange(ItemContainer.ItemContainerChangeEvent event) {
Transaction transaction = event.transaction();
// Vérifier si le slot 0 de la hotbar a été affecté
if (transaction.wasSlotModified((short) 0)) {
getLogger().at(Level.INFO).log("Premier slot modifié !");
}
// Vérifier tous les slots de la hotbar
for (short i = 0; i < 9; i++) {
if (transaction.wasSlotModified(i)) {
getLogger().at(Level.INFO).log("Slot hotbar " + i + " modifié");
}
}
}
```
## Options de Transaction
De nombreuses opérations acceptent des paramètres optionnels :
| Paramètre | Description | Par défaut |
|-----------|-------------|---------|
| `allOrNothing` | Si vrai, l'opération échoue si tous les objets ne peuvent pas être traités | `false` |
| `fullStacks` | Si vrai, ajoute seulement aux slots vides (pas aux piles partielles) | `false` |
| `exactAmount` | Si vrai, doit retirer exactement la quantité demandée | `true` |
| `filter` | Si vrai, respecte les filtres de slot | `true` |
```java
// Comportement par défaut
container.addItemStack(item);
// Avec options
container.addItemStack(item, true, false, true); // allOrNothing, fullStacks, filter
container.removeItemStack(item, true, true); // allOrNothing, filter
```
## Bonnes Pratiques
{{< callout type="info" >}}
**Conseils pour les Transactions :**
- Toujours vérifier `succeeded()` avant d'accéder aux résultats
- Gérer les restes lors de l'ajout d'objets
- Utiliser `canAddItemStack()`/`canRemoveItemStack()` pour la pré-validation
- Utiliser `allOrNothing=true` pour les opérations critiques
- Vérifier `wasSlotModified()` pour suivre les changements de slots spécifiques
{{< /callout >}}
```java
// Bon : Vérifier le succès et gérer les restes
ItemStackTransaction tx = container.addItemStack(item);
if (tx.succeeded()) {
ItemStack remainder = tx.getRemainder();
if (!ItemStack.isEmpty(remainder)) {
// Gérer les objets restants
}
}
// Mauvais : Supposer le succès
container.addItemStack(item); // Pourrait échouer silencieusement !
```
## Référence API Transaction
### Interface Transaction
| Méthode | Retour | Description |
|--------|---------|-------------|
| `succeeded()` | `boolean` | True si l'opération a réussi |
| `wasSlotModified(short)` | `boolean` | True si le slot spécifique a été modifié |
### SlotTransaction
| Méthode | Retour | Description |
|--------|---------|-------------|
| `getSlot()` | `short` | Index du slot affecté |
| `getAction()` | `ActionType` | Type d'action effectuée |
| `getSlotBefore()` | `ItemStack?` | Contenu avant l'opération |
| `getSlotAfter()` | `ItemStack?` | Contenu après l'opération |
| `getOutput()` | `ItemStack?` | Objets retirés/sortis |
| `isAllOrNothing()` | `boolean` | Paramètre allOrNothing utilisé |
| `isExactAmount()` | `boolean` | Paramètre exactAmount utilisé |
| `isFilter()` | `boolean` | Paramètre filter utilisé |
| Statique | Type | Description |
|----------|------|-------------|
| `FAILED_ADD` | `SlotTransaction` | Transaction d'ajout échouée pré-construite |
### ItemStackSlotTransaction (étend SlotTransaction)
| Méthode | Retour | Description |
|--------|---------|-------------|
| `isAddToExistingSlot()` | `boolean` | True si ajouté à une pile existante |
| `getQuery()` | `ItemStack?` | Objet original demandé |
| `getRemainder()` | `ItemStack?` | Objets qui n'ont pas pu rentrer |
### ItemStackTransaction
| Méthode | Retour | Description |
|--------|---------|-------------|
| `getAction()` | `ActionType?` | Type d'action effectuée |
| `getQuery()` | `ItemStack?` | Objet original demandé |
| `getRemainder()` | `ItemStack?` | Objets qui n'ont pas pu rentrer |
| `isAllOrNothing()` | `boolean` | Paramètre allOrNothing utilisé |
| `isFilter()` | `boolean` | Paramètre filter utilisé |
| `getSlotTransactions()` | `List<ItemStackSlotTransaction>` | Toutes les transactions de slot |
| Statique | Type | Description |
|----------|------|-------------|
| `FAILED_ADD` | `ItemStackTransaction` | Transaction d'ajout échouée pré-construite |
### MoveTransaction<T extends Transaction>
| Méthode | Retour | Description |
|--------|---------|-------------|
| `getRemoveTransaction()` | `SlotTransaction` | Transaction de retrait |
| `getMoveType()` | `MoveType` | Direction du déplacement |
| `getOtherContainer()` | `ItemContainer` | L'autre conteneur impliqué |
| `getAddTransaction()` | `T` | Transaction d'ajout |
| `toInverted(ItemContainer)` | `MoveTransaction<T>` | Créer vue inversée pour l'autre conteneur |
### ListTransaction<T extends Transaction>
| Méthode | Retour | Description |
|--------|---------|-------------|
| `getList()` | `List<T>` | Toutes les transactions de la liste |
| `size()` | `int` | Nombre de transactions |
| Statique | Type | Description |
|----------|------|-------------|
| `EMPTY_SUCCESSFUL_TRANSACTION` | `ListTransaction<?>` | Succès vide pré-construit |
| `EMPTY_FAILED_TRANSACTION` | `ListTransaction<?>` | Échec vide pré-construit |
| `getEmptyTransaction(boolean)` | `ListTransaction<T>` | Obtenir succès/échec vide |
### Enum ActionType
| Valeur | isAdd | isRemove | isDestroy | Description |
|--------|-------|----------|-----------|-------------|
| `SET` | true | false | true | Définir le contenu du slot |
| `ADD` | true | false | false | Ajouter des objets au slot |
| `REMOVE` | false | true | false | Retirer des objets du slot |
| `REPLACE` | true | true | false | Remplacer le contenu du slot |
### Enum MoveType
| Valeur | Description |
|--------|-------------|
| `MOVE_TO_SELF` | Objets déplacés vers ce conteneur |
| `MOVE_FROM_SELF` | Objets déplacés depuis ce conteneur |