Skip to content

ItemStacks

Gunnar edited this page May 22, 2025 · 34 revisions

Scafall distinguishes between ItemStack (mutable) and ItemStackSnapshot (immutable) that are both a ItemStackLike.
This is mostly done to make it easier to understand which references can be mutated to apply changes.

ItemStack

ItemStacks are mutable, so it can be assumed that changes to the stack are reflected where ever else the stack is used (like an inventory)

Creating an ItemStack

import com.wolfyscript.scafall.wrappers.world.items.ItemStack
import com.wolfyscript.scafall.identifier.Key

val stack = ItemStack.of(Key.key(Key.MINECRAFT_NAMESPACE, "stick"))

Tip

When modifying the unwrapped ItemStack value, changes to it are reflected in the wrapper, so rewrapping is not necessary.

Create an immutable copy

val immutableStack = stack.snapshot()

ItemStackSnapshot

ItemStackSnapshots are immutable, meaning changes to the stack are not applied.

Note

Keep in mind when unwrapping it, you are modifying a copy of the original stack!
Changes to the value will not be reflected in the wrapper.

Create a mutable copy

val mutableStack = snapshot.createStack()

Data Components

Caution

This part of the API is currently discontinued.
Instead unwrap the ItemStack/ItemStackSnapshot and work with the platform specific features!

The API is very similar to the vanilla Data Component system. In fact, it tries to mirror the vanilla structure of data components as best as possible.
Since it is cross-platform, the provided data is converted and applied to the ItemStacks on their native platform (or fallback to Minecraft itself).

[!note] When you get the data from a ItemStackLike (mutable/immutable) then changes to that data are not reflected on the ItemStackLike.
For changes to be applied, the data needs to be set to the ItemStack again.

Applying data

import com.wolfyscript.scafall.data.ItemStackDataKeys
import com.wolfyscript.scafall.deserialize

// Specify a custom name for the item using the MiniMessage extension function
stack.set(ItemStackDataKeys.CUSTOM_NAME, "<purple><b>Special Stick".deserialize())

Removing data

import com.wolfyscript.scafall.data.ItemStackDataKeys

stack.remove(ItemStackDataKeys.CUSTOM_NAME)

Getting data

[!note] The data returned is always Nullable. It's non-null when that data is present, otherwise null.
This is the same for all data components, including simple numbers, so no default values (e.g. Int? instead of Int).

import com.wolfyscript.scafall.data.ItemStackDataKeys
import net.kyori.adventure.text.Component

val data: Component? = stack.get(ItemStackDataKeys.CUSTOM_NAME)

State of platform implementations

Not all Data Components have a converter implemented on each platform, due to limitations, or simply because they are still WIP.

The following table lists the current implementation status of the Data Component Converters:

⚫ — Not implemented
🟢 — Implemented
🔵 — Partly implemented / WIP / Untested
🟠 — Implemented with limitations (e.g. loss of information)
🔴 — Implementation not possible / Requires modding using NMS

Data Component Spigot Paper Sponge Notes
attribute_modifiers 🔵 🔵 🔵 -----
banner_patterns 🟢 🟢 🟢 -----
base_color 🟢 🟢 🟢 -----
bees -----
block_entity_data -----
block_state -----
blocks_attacks 🟠 Papers API is still EXPERIMENTAL (missing damage reduction, item damage)
break_sound 🟠 Paper only supports existing Sound Events. Custom radius is ignored
bucket_entity_data -----
bundle_contents 🟢 🟢 -----
can_break 🟠 🟠 Block preconditions are missing
can_place_on 🟠 🟠 Block preconditions are missing
charged_projectiles 🟢 🟢 🟢 -----
consumable 🟢 -----
container 🟢 -----
container_loot 🟢 -----
custom_data -----
custom_model_data 🟠 🟢 🟠 Changed in upcoming 1.21.4
custom_name 🟢 🟢 🟢 -----
damage 🟢 🟢 🟢 -----
damage_resistant 🟢 -----
debug_stick_state -----
death_protection 🟢 -----
dyed_color 🟢 🟢 -----
enchantable 🟢 🟢 -----
enchantment_glint_override 🟢 🟢 🟢 -----
enchantments 🟢 🟢 🟢 -----
entity_data -----
equippable 🔵 -----
firework_explosion 🔵 -----
fireworks 🔵 -----
food 🟢 🟢 -----
glider 🟢 🟢 -----
instrument 🟢 🟢 🟢 -----
intangible_projectile 🟢 🟢 🟢 -----
item_model 🟢 🟢 🟢 -----
item_name 🟢 🟢 🟢 -----
jukebox_playable -----
lock -----
lodestone_tracker -----
lore 🟢 🟢 🟢 -----
map_color 🟢 -----
map_decorations -----
map_id 🟢 🟢 -----
max_damage 🟢 🟢 -----
max_stack_size 🟢 🟢 -----
note_block_sound 🟢 🟢 🟢 -----
ominous_bottle_amplifier 🟢 -----
pot_decorations 🔵 🟢 🟢 -----
potion_contents -----
profile 🔵 🔵 -----
provides_banner_patterns 🟢 -----
provides_trim_material -----
rarity 🟢 -----
recipes 🟢 🟢 🔴 Couldn't find API in Sponge to get recipes
repairable 🟢 -----
repair_cost 🟢 🟢 🟢 -----
stored_enchantments 🟢 🟢 🟢 -----
suspicious_stew_effects 🟢 -----
tool 🟢 🟢 -----
tooltip_display 🟢 -----
tooltip_style 🟢 🟢 -----
trim 🟢 -----
unbreakable 🟢 🟢 🟢 -----
use_cooldown 🟢 -----
use_remainder 🟢 -----
weapon 🟢 -----
writable_book_content -----
written_book_content -----

ItemStackConfig

ItemStackConfigs wrap an ItemStack and provide additional configuration options, such as overrides. These overrides are able to modify the data of the wrapped ItemStack. They are only applied when required and can take context into account, such as the player, world, scoreboard, etc.

When saved to a config, the ItemStack is saved as is with its full data (SNBT), and the overrides are saved in a separate list.
When loaded from config both are loaded separately, meaning overrides are not directly applied.

Clone this wiki locally