Skip to content

Dividing Clients and Entities into smaller components #199

@rj00a

Description

@rj00a

Brainstorming some ideas for how the monolithic Client and McEntity components could be split up into a set of smaller components. Here are some reasons you would want to do this:

  • Improve query performance by increasing parallelism and useful data in the CPU cache.
  • More modular design can split code into smaller understandable pieces.
  • Integrate with Bevy's change detection.
  • Share data between client and Minecraft entity when they share the same ECS entity. (Typically the client will have a player entity associated with it).
  • Save memory by spawning entities without unused components.

Some reasons you wouldn't want to do this:

  • Many corner cases and interactions that are not accounted for can lead to bugs.
  • Potentially confusing and unintuitive.
  • Invalid states are very much representable.

Component Name Description Effect When Added Effect When Removed Effect When Modified
Despawned Any ECS Entities with this component are despawned at the end of the tick. This gives Valence an opportunity to perform deinitialization of components that can't be removed explicitly. In particular, McEntity and its other components.
Client The main client component. Contains the TCP connection and packet buffers. Also contains immutable info such as username, UUID, and IP among other things. Joins the client (Should only be done by Valence). Maybe we want to allow attaching Client to existing entities somehow? No effect, but the client is disconnected when dropped. Removing only this component from an McEntity will allow you to take control.
Disconnected Marker component to indicate that a client is disconnected.
Location Contains the instance an Entity or Client is inside. Also contains the instance from the previous tick. Disallowed at least for entities because we need it to clean up the instance. Changes the instance a client or entity is in. Makes clients respawn even if old_instance == new_instance. Can be used to respawn the client after death.
Position The XYZ coordinates (old and new) of a client or entity. Automatically updated by Valence as a client moves around. Disallowed at least for entities because we need it to clean up the instance. Teleports clients and entities when modified
Direction Contains the pitch/yaw pair of an entity or client. Automatically updated by clients as they look around. Disallowed(?) Sets the pitch/yaw of entities and teleports clients to set their pitch/yaw. Can be combined with Position modifications to form a single teleport.
Velocity Contains the velocity vector for clients and entities. Causes clients to be launched. Unknown effect on entities. (Velocity is really weird in Minecraft).
OnGround The on ground boolean for clients and entities. Automatically updated by clients. Changes the on ground state for entities.
Vehicle The vehicle entity a client or entity is riding. TODO TODO TODO
DeathLocation Contains a (DimensionId, BlockPos) pair. Used by respawning clients to set their recovery compass position Can be modified, but won't have an effect until the client is respawned.
GameModeComponent (GameMode was taken) Contains the game mode of a client. Disallowed(?) Sets the gamemode of the client it's attached to.
McEntity The main component for Minecraft entities. Contains protocol entity ID and UUID. Spawns the entity. Must have Location and Position to do so. Sets the protocol ID to the next unique value. Was initialized to zero when the component was created. Definitely disallowed because we need the protocol ID to send despawn packets to clients. Also, we need the position+location to remove its ID from the instance it was in. Otherwise, there would be a memory leak.
EntityKindComponent (EntityKind was taken) Contains the type of Minecraft entity (Blaze, Chicken, Player, etc). Disallowed(?) Respawns the entity as the new type. All metadata is reset. Protocol ID is reused(?)
*Metadata, where * is every entity type. Component and system definitions would be generated. Contains the metadata (TrackedData) of a particular entity type. TrackedData is currently an enum, so this would save a lot of space. Not to mention easier because it's queryable and you wouldn't have to match on any enums. Initializes the metadata. Would be nice if we allowed spawning entities without metadata to save memory. Clears the metadata(?) Updates the entity's metadata. Has no effect if component does not match the entity's type as determined by EntityKindComponent. When PlayerMetadata is modified on a client, the changes are sent to the client's own player entity.
ExpOrbCount The amount of experience in an exp orb entity. Changes its visuals. Only used when spawning exp orb entities. Modifications have no effect afterwards.
FallingBlockState The BlockState of falling block entities Only used when spawning falling block entities. Modifications have no effect afterwards.
Statuses Bitset containing a bit for each entity status. Cleared at the end of the tick. Triggers any set statuses for an entity. Triggers any set statuses for an entity.
Animations Bitset containing a bit for each entity animation. Cleared at the end of the tick. Triggers any set animations for an entity. Triggers any set animations for an entity.
Hitbox Contains the AABB hitbox for an entity. Updated at the end of each tick. No effect, but likely to be overwritten at the end of the tick.

Questions

  • How granular should the components be? Should there be Location/OldLocation and Position/OldPosition, or is that kind of thing too cumbersome?
  • What about miscellaneous data in Client like is_hardcore, is_flat, etc?
  • Should UUID be shared between clients and entities as a component? Should it not be a component because it's immutable?
  • Should the protocol ID of entities be a component? This would be immutable too.
  • Should metadata components be broken up further to match Minecraft's class hierarchy? That seems very challenging.
  • Working with metadata internally when there are a million different component types might be challenging. Probably need to cache metadata initialization bytes in McEntity.
  • What about the inventory stuff for clients?
  • What about poses?
  • Does McEntity need to exist? It's kind of an ugly name.
  • What is the most effective way to disallow removing components? Log an error? Panic in debug mode?

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions