Skip to content
MyoWiki Myotus · 1.20.1

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.

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.

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.

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

TerminalUpgradeStorageKey generates different stable keys depending on terminal host type.

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.

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.

PlayerUpgradeContainer migrates older storage layouts in this order:

  1. existing new-format terminal key
  2. legacy per-item keys returned by legacyKeysOf(host)
  3. old shared terminal_upgrades data

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.

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.

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.

  • 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.