Skip to content

Instantly share code, notes, and snippets.

@Floweynt
Created October 7, 2024 22:20
Show Gist options
  • Save Floweynt/00843144adfa1aca9c8b83f193be0484 to your computer and use it in GitHub Desktop.
Save Floweynt/00843144adfa1aca9c8b83f193be0484 to your computer and use it in GitHub Desktop.
Monumenta Item API

Item API Draft

Item API provides a way to manipulate item properties on the client side without maintaining server-side state.

Layers

Like an onion, the item api has layers

Datapack layer

Items can be described via json. I am too lazy to describe this format for now.

API Layer

The API provides a way to register items. A custom item simply needs to implement an interface, which provides callbacks that allows you to render specific items. This allows you to:

  • Render item names
  • Render item lore
  • Render other item properties
  • Load/store custom persistent data with NBT API

A proper implementation of equals and hashCode is enough to enable caching. To disable caching, override isCachable to return false.

NMS Layer

Mixin Injection into ItemStack the ResourceLocation that corresponds to the custom item's identifier. On NBT load, we figure out the custom item id (by reading a tag). If no tag is present, we look at the default custom item registry. If that is not present, return and do nothing. We then pass additional nbt data to the interface specified above.

Caching

TODO: figure this out

Networking

When sending stuff to the client, we replace the item being sent with the rendered version. This is very similar to Polymer's (a fabric mod) behavior, which means we can borrow logic.

Notes on optimization

Purely from the architecture of this mod, we get a few free optimizations:

  • Free compression of nbt data (both at runtime/memory and when persisted to disk) - the server doesn't store any "unnecessary" properties such as lore.
    • This should also solve issues with nbt comparison taking a long time
  • Fast-path virtual items (without hooking into protocollib)

Things to think about:

  • Caching "rendered" items
    • Perhaps we should cache serialized nbts instead, since that gives us fast packet serialization (maybe better than vanilla)

Relation with plugin-side item updates

By minimizing the amount of data stored server-side, we naturally cover most applications of item updates (modifying attributes, lore, etc). In our current implementation:

ItemStack@1 -> ("Foo", lore_data, attribute_data, ...) 
ItemStack@2 -> ("Foo", lore_data, attribute_data, ...) 
ItemStack@3 -> ("Bar", lore_data, attribute_data, ...) 
ItemStack@4 -> ("Bar", lore_data, attribute_data, ...) 

However, with item index:

"monumenta:foo" -> ("Foo", lore_data, attribute_data, ...)
"monumenta:bar" -> ("Bar", lore_data, attribute_data, ...)

ItemStack@1 -> (id = "monumenta:foo") 
ItemStack@2 -> (id = "monumenta:foo") 
ItemStack@3 -> (id = "monumenta:bar") 
ItemStack@4 -> (id = "monumenta:bar") 

Since the source of truth is the item index, server-side item upgrade is free.

1.20.5 and beyond

TODO

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment