Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an inventory system #397

Open
patowen opened this issue May 11, 2024 · 3 comments
Open

Add an inventory system #397

patowen opened this issue May 11, 2024 · 3 comments
Assignees
Labels
enhancement New feature or request

Comments

@patowen
Copy link
Collaborator

patowen commented May 11, 2024

As a first step to adding actual gameplay, the player should be able to obtain, organize, and use resources, so to allow that, we will need to give the player an inventory. Implementing this is somewhat involved, as it has several moving parts:

  • Some way to track the items a player is holding
  • A GUI for the inventory that allows a player to move items around
  • A way to select materials to place
  • A server-authoritative inventory (at least for what items are in there, but likely for how they're organized as well to be able to know if the inventory is full)
  • Serialization of the player inventory for saving
  • Atomic modifications to the save file for placing and breaking blocks (to avoid item loss or duplication)

To avoid needing to implement "item entities" or an equivalent feature, breaking blocks should immediately put them in the player's inventory. This might also be a good quality-of-life feature in general to keep long-term. However, for now, if the player's inventory is full, the fallback should be the simplest to implement: The block should be erased from existence.

It shouldn't matter exactly what the inventory controls are or how certain selections are made, as long as the code is written in such a way that tweaks are feasible. Just having this feature exist at all should be the priority.

@patowen patowen added the enhancement New feature or request label May 11, 2024
@Ralith
Copy link
Owner

Ralith commented May 11, 2024

To start with, we must define a data model. A simple and flexible in-memory data model is a plain Vec<Entity> sitting in a discrete component. This interacts with the described goals as follows:

A GUI for the inventory that allows a player to move items around

Left to future work. Future work could annotate the Vec with positions in a grid. Alternatively, many games have done just fine with plain lists of items.

A way to select materials to place

We already have a material selection scheme, albeit a primitive one. It could be easily extended to scan the inventory to find an Entity that represents a block of the selected material and consume it. This might seem inefficient, but it's implausible that inventories will ever become large enough for this to matter, and we can always add an index later if needed. A more usable GUI can be developed in follow-up work, either as an extension of the main inventory GUI or a dedicated interface.

A server-authoritative inventory

common::proto can be extended with an event for use by the server to communicate the addition or removal of an entity to/from another entity's inventory, to be included in Spawns as with all other discrete events. For the client's part, it is sufficient to extend BlockUpdate to specify the EntityId to be consumed when placing a block.

Serialization of the player inventory for saving

As a component, inventory should be encoded into a column of the bytes field representing the entity that owns it (for now, always a character) in its EntityNode. A plain [EntityId] encoding will suffice.

The stored block entities themselves are a bit of a funny case, since they don't necessarily have a location in world space. For serialization purposes, we might as well deem them part of the same EntityNode as the entity that owns the inventory, which ensures they are loaded when relevant.

Atomic modifications to the save file for placing and breaking blocks (to avoid item loss or duplication)

Thanks to redb, all save file updates are transactional, so this requires no effort beyond choosing not to gratuitously split the transaction.

@Ralith
Copy link
Owner

Ralith commented May 11, 2024

The choice to represent resources as first-class entities may seem strange, but is deliberate. It is certain that we'll want to store things other than raw materials, and those will have additional state (i.e. components) attached. By embracing this model from the start, we can reduce the number of special cases, without any real drawbacks.

@patowen
Copy link
Collaborator Author

patowen commented May 11, 2024

The choice to represent resources as first-class entities may seem strange, but is deliberate. It is certain that we'll want to store things other than raw materials, and those will have additional state (i.e. components) attached. By embracing this model from the start, we can reduce the number of special cases, without any real drawbacks.

That makes sense to me. The only potential downside I can think of is efficiency, but to fix that, for simple materials, if we needed to in the future, we could always if we needed to add the optimization of the ItemStack component that could just have a material ID and a number. Use of entities here will give us the flexibility we need, so I'm optimistic about this as the foundational design for inventory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants