Upgrade Storage
This page covers the storage side of terminal upgrade cards in 1.21.1. The public item hook lives in Terminal Upgrade Cards, but the persistence and slot lifecycle are handled elsewhere.
Everything here is 1.21.1-only. The Forge 1.20.1 line does not have the card API or persistent upgrade storage, but it does already inject terminal-side UI scaffolding through MEStorageMenuMixin and MyoSlotSemantics.
Where the slots come from
Section titled “Where the slots come from”MEStorageMenuMixin injects into the AE2 terminal menu constructor and ensures the terminal side panel and custom slot groups exist:
- extra view-cell slots
- Myotus upgrade slots
When the upgrade slot semantic is missing, Myotus adds 5 slots backed by an internal inventory and uses Icon.BACKGROUND_UPGRADE for the slot background.
What can be inserted
Section titled “What can be inserted”Insertion is gated by TerminalUpgradeSlotFilter.
Only items whose Item implements ITerminalUpgradeCard are accepted:
return stack.getItem() instanceof ITerminalUpgradeCard;That keeps the slot contract simple for addon authors and automatically rejects unrelated items.
Persistence model
Section titled “Persistence model”On the server, the mixin creates:
new PlayerUpgradeContainer( serverPlayer, TerminalUpgradeStorageKey.of(host), TerminalUpgradeStorageKey.legacyKeysOf(host))PlayerUpgradeContainer stores contents in the player’s persistent NBT, not in the terminal GUI session itself.
Important details:
- slot count is fixed at
5 - writes happen through
saveChangedInventory() - contents persist after closing the GUI
- storage is scoped to a terminal-specific key, not one global upgrade inventory
Storage key strategy
Section titled “Storage key strategy”TerminalUpgradeStorageKey generates different stable keys depending on terminal host type.
Part-based terminals
Section titled “Part-based terminals”For AEBasePart hosts, the key includes:
- host class name
- dimension ID
- block position
- part side
That gives each placed terminal part its own upgrade inventory.
Item-based terminals
Section titled “Item-based terminals”For ItemMenuHost hosts, the key includes:
- host class name
- item ID
- a UUID stored on the
ItemStack
The UUID is written into custom item data under myotus_terminal_storage_uuid. This is what keeps portable/item terminals from sharing one storage bucket.
Legacy migration behavior
Section titled “Legacy migration behavior”PlayerUpgradeContainer migrates older storage layouts in this order:
- existing new-format terminal key
- legacy per-item keys returned by
legacyKeysOf(host) - old shared
terminal_upgradesdata
The last case means the historical shared payload is moved into the first terminal opened after the update and then removed from the legacy key.
Lifecycle dispatch
Section titled “Lifecycle dispatch”The same MEStorageMenuMixin also dispatches upgrade callbacks.
- when the terminal menu first opens
- when a new upgrade card is inserted into an upgrade slot
- every
broadcastChanges()cycle while the menu stays open
- when the menu is removed
- when an installed card is replaced or removed
This means card authors do not have to poll slot state themselves. The mixin tracks previous slot contents and translates those changes into onTerminalOpen(), onTerminalTick(), and onTerminalClose() calls.
Query helpers
Section titled “Query helpers”TerminalUpgradeHelper gives addon code a cleaner read API over the slot list.
It supports:
getInstalledUpgrades(menu)hasUpgrade(menu, Item)hasUpgrade(menu, ResourceLocation)countUpgrade(menu, Item)countUpgrade(menu, ResourceLocation)
The ResourceLocation overloads return safe fallback values when the target item is not present in the registry, which is useful for optional cross-mod behavior.
Practical implications for addon authors
Section titled “Practical implications for addon authors”- Upgrade cards are effectively per terminal instance, not global per player.
- Item-hosted terminals keep their own identity through stack UUIDs.
- Cards survive menu reopen because the server writes them into player persistent data.
- A dev-only sample item,
DiamondUpgradeCardItem, exists in non-production builds as a reference implementation.