12 KiB
12 KiB
title, type, weight
| title | type | weight |
|---|---|---|
| Transactions | docs | 3 |
Transactions track the results of inventory operations in Hytale. Every modification to an ItemContainer returns a Transaction object that describes what happened.
Transaction Interface
All transactions implement the base Transaction interface:
public interface Transaction {
// Did the operation succeed?
boolean succeeded();
// Was a specific slot modified?
boolean wasSlotModified(short slot);
}
Transaction Types
SlotTransaction
Tracks changes to a single slot:
SlotTransaction transaction = container.removeItemStackFromSlot((short) 0);
if (transaction.succeeded()) {
// What was in the slot before
ItemStack before = transaction.getSlotBefore();
// What is in the slot now
ItemStack after = transaction.getSlotAfter();
// The item that was removed/output
ItemStack output = transaction.getOutput();
// Which slot was affected
short slot = transaction.getSlot();
// What type of action (ADD, REMOVE, REPLACE)
ActionType action = transaction.getAction();
}
ItemStackSlotTransaction
Extended slot transaction with additional details:
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();
// Check options used
boolean wasFiltered = transaction.isFilter();
boolean wasAllOrNothing = transaction.isAllOrNothing();
}
ItemStackTransaction
Tracks operations that may affect multiple slots:
ItemStack toAdd = new ItemStack("stone", 128);
ItemStackTransaction transaction = container.addItemStack(toAdd);
if (transaction.succeeded()) {
// Items that couldn't fit (null if all fit)
ItemStack remainder = transaction.getRemainder();
// Original item we tried to add
ItemStack query = transaction.getQuery();
// List of all slot transactions that occurred
List<ItemStackSlotTransaction> slotTransactions = transaction.getSlotTransactions();
for (ItemStackSlotTransaction slotTx : slotTransactions) {
getLogger().at(Level.INFO).log("Modified slot " + slotTx.getSlot());
}
}
MoveTransaction
Tracks moving items between containers:
MoveTransaction<SlotTransaction> transaction = storage.moveItemStackFromSlotToSlot(
(short) 0,
32,
hotbar,
(short) 0
);
if (transaction.succeeded()) {
// Transaction for removing from source
SlotTransaction removeTransaction = transaction.getRemoveTransaction();
// Transaction for adding to destination
SlotTransaction addTransaction = transaction.getAddTransaction();
// The destination container
ItemContainer destination = transaction.getOtherContainer();
// Direction of the move
MoveType moveType = transaction.getMoveType();
}
ListTransaction
Wraps multiple transactions:
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
Operations are categorized by action type:
public enum ActionType {
SET, // Items set (add=true, remove=false, destroy=true)
ADD, // Items added to slot (add=true, remove=false, destroy=false)
REMOVE, // Items removed from slot (add=false, remove=true, destroy=false)
REPLACE // Slot contents replaced (add=true, remove=true, destroy=false)
}
// Check action characteristics
if (action.isAdd()) { /* operation adds items */ }
if (action.isRemove()) { /* operation removes items */ }
if (action.isDestroy()) { /* operation destroys slot contents */ }
MoveType
Direction of move operations:
public enum MoveType {
MOVE_TO_SELF, // Items being moved TO this container
MOVE_FROM_SELF // Items being moved FROM this container
}
Common Patterns
Check Before Modify
// Safe pattern: verify first, then execute
public boolean safeTransfer(ItemContainer from, ItemContainer to, String itemId, int amount) {
ItemStack toRemove = new ItemStack(itemId, amount);
// Check both operations can succeed
if (!from.canRemoveItemStack(toRemove)) {
return false; // Not enough items
}
if (!to.canAddItemStack(toRemove)) {
return false; // No space
}
// Execute removal
ItemStackTransaction removeResult = from.removeItemStack(toRemove);
if (!removeResult.succeeded()) {
return false;
}
// Execute addition
ItemStack removed = removeResult.getQuery();
ItemStackTransaction addResult = to.addItemStack(removed);
// Handle any remainder
ItemStack remainder = addResult.getRemainder();
if (!ItemStack.isEmpty(remainder)) {
// Put remainder back
from.addItemStack(remainder);
}
return true;
}
Handling Remainders
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("Inventory full!"));
return;
}
ItemStack remainder = result.getRemainder();
if (!ItemStack.isEmpty(remainder)) {
player.sendMessage(Message.raw(
"Only received " + (quantity - remainder.getQuantity()) + " items, " +
"inventory full!"
));
}
}
Atomic Operations
// allOrNothing=true ensures partial operations don't happen
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);
// Check both operations can succeed fully
if (!storage.canRemoveItemStack(currency)) {
player.sendMessage(Message.raw("Not enough gold!"));
return false;
}
if (!storage.canAddItemStack(item)) {
player.sendMessage(Message.raw("Inventory full!"));
return false;
}
// Remove currency with allOrNothing=true
ItemStackTransaction removeResult = storage.removeItemStack(currency, true, true);
if (!removeResult.succeeded()) {
return false;
}
// Add item
ItemStackTransaction addResult = storage.addItemStack(item, true, false, true);
if (!addResult.succeeded()) {
// Rollback: return the currency
storage.addItemStack(currency);
return false;
}
return true;
}
Tracking Changes
// Use wasSlotModified to check specific slots
public void onContainerChange(ItemContainer.ItemContainerChangeEvent event) {
Transaction transaction = event.transaction();
// Check if hotbar slot 0 was affected
if (transaction.wasSlotModified((short) 0)) {
getLogger().at(Level.INFO).log("First slot was modified!");
}
// Check all hotbar slots
for (short i = 0; i < 9; i++) {
if (transaction.wasSlotModified(i)) {
getLogger().at(Level.INFO).log("Hotbar slot " + i + " modified");
}
}
}
Transaction Options
Many operations accept optional parameters:
| Parameter | Description | Default |
|---|---|---|
allOrNothing |
If true, operation fails if not all items can be processed | false |
fullStacks |
If true, only add to empty slots (not partial stacks) | false |
exactAmount |
If true, must remove exact quantity requested | true |
filter |
If true, respect slot filters | true |
// Default behavior
container.addItemStack(item);
// With options
container.addItemStack(item, true, false, true); // allOrNothing, fullStacks, filter
container.removeItemStack(item, true, true); // allOrNothing, filter
Best Practices
{{< callout type="info" >}} Transaction Tips:
- Always check
succeeded()before accessing results - Handle remainders when adding items
- Use
canAddItemStack()/canRemoveItemStack()for pre-validation - Use
allOrNothing=truefor critical operations - Check
wasSlotModified()to track specific slot changes {{< /callout >}}
// Good: Check success and handle remainder
ItemStackTransaction tx = container.addItemStack(item);
if (tx.succeeded()) {
ItemStack remainder = tx.getRemainder();
if (!ItemStack.isEmpty(remainder)) {
// Handle leftover items
}
}
// Bad: Assume success
container.addItemStack(item); // Might fail silently!
Transaction API Reference
Transaction Interface
| Method | Returns | Description |
|---|---|---|
succeeded() |
boolean |
True if operation succeeded |
wasSlotModified(short) |
boolean |
True if specific slot was modified |
SlotTransaction
| Method | Returns | Description |
|---|---|---|
getSlot() |
short |
The affected slot index |
getAction() |
ActionType |
Type of action performed |
getSlotBefore() |
ItemStack? |
Contents before operation |
getSlotAfter() |
ItemStack? |
Contents after operation |
getOutput() |
ItemStack? |
Items removed/output |
isAllOrNothing() |
boolean |
allOrNothing parameter used |
isExactAmount() |
boolean |
exactAmount parameter used |
isFilter() |
boolean |
filter parameter used |
| Static | Type | Description |
|---|---|---|
FAILED_ADD |
SlotTransaction |
Pre-built failed add transaction |
ItemStackSlotTransaction (extends SlotTransaction)
| Method | Returns | Description |
|---|---|---|
isAddToExistingSlot() |
boolean |
True if added to existing stack |
getQuery() |
ItemStack? |
Original item requested |
getRemainder() |
ItemStack? |
Items that couldn't fit |
ItemStackTransaction
| Method | Returns | Description |
|---|---|---|
getAction() |
ActionType? |
Type of action performed |
getQuery() |
ItemStack? |
Original item requested |
getRemainder() |
ItemStack? |
Items that couldn't fit |
isAllOrNothing() |
boolean |
allOrNothing parameter used |
isFilter() |
boolean |
filter parameter used |
getSlotTransactions() |
List<ItemStackSlotTransaction> |
All slot transactions |
| Static | Type | Description |
|---|---|---|
FAILED_ADD |
ItemStackTransaction |
Pre-built failed add transaction |
MoveTransaction
| Method | Returns | Description |
|---|---|---|
getRemoveTransaction() |
SlotTransaction |
Transaction for removal |
getMoveType() |
MoveType |
Direction of move |
getOtherContainer() |
ItemContainer |
The other container involved |
getAddTransaction() |
T |
Transaction for addition |
toInverted(ItemContainer) |
MoveTransaction<T> |
Create inverted view for other container |
ListTransaction
| Method | Returns | Description |
|---|---|---|
getList() |
List<T> |
All transactions in list |
size() |
int |
Number of transactions |
| Static | Type | Description |
|---|---|---|
EMPTY_SUCCESSFUL_TRANSACTION |
ListTransaction<?> |
Pre-built empty success |
EMPTY_FAILED_TRANSACTION |
ListTransaction<?> |
Pre-built empty failure |
getEmptyTransaction(boolean) |
ListTransaction<T> |
Get empty success/failure |
ActionType Enum
| Value | isAdd | isRemove | isDestroy | Description |
|---|---|---|---|---|
SET |
true | false | true | Set slot contents |
ADD |
true | false | false | Add items to slot |
REMOVE |
false | true | false | Remove items from slot |
REPLACE |
true | true | false | Replace slot contents |
MoveType Enum
| Value | Description |
|---|---|
MOVE_TO_SELF |
Items moving to this container |
MOVE_FROM_SELF |
Items moving from this container |