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

Visibility Layers #424

Merged
merged 53 commits into from
Aug 2, 2023
Merged

Visibility Layers #424

merged 53 commits into from
Aug 2, 2023

Conversation

rj00a
Copy link
Member

@rj00a rj00a commented Jul 26, 2023

Objective

The objective of this PR is to solve the following problems with a holistic redesign of instances.

Closes #342, #362, but deviates greatly from the solution described in the issue.

  • If an entity is within the view distance of a client, packets for that entity are sent to the client unconditionally. However, there is often a need to limit the visibility of entities to certain clients depending on the situation. Some examples:

    • You have a minigame with spectators and players. Spectators can see both players and spectators, but players can only see players and not spectators.
    • An entity or set of entities is used as a makeshift GUI, only visible to the client using the GUI.
    • The server has many separate "arenas" that have identical chunk data, and you wish to share the chunk data across arenas to save memory.
    • You want to make a player truly invisible and potentially have some other entity take its place.

    It is possible to work around the problem by using invisibility effects or sending packets manually. But these are hacky solutions that are incomplete, inefficient, and inconvenient.

  • Updating clients involves looking up every chunk in the client's view distance every tick for every client. This wastes CPU time and doesn't scale well with larger view distances1.

  • Sometimes we want to broadcast packets to all clients matching some condition. Conditions could include...

    • If a chunk position is within the client's view.
    • If the client is within a certain radius of some position.
    • If the client is not some specific client (self exclusion).

    It isn't really possible to add all of these conditions in an efficient way using the current design.

Solution

Split the existing Instance component into two new components: ChunkLayer and EntityLayer. Chunk layers contain all of the chunks in a world along with some global configuration, like the world's dimension. Entity layers contain Minecraft entities. A LayerBundle containing both is provided for convenience. Both ChunkLayer and EntityLayer implement the common Layer trait.

The key idea is this: Clients can only view one chunk layer2, but can view any number of entity layers. These are the VisibleChunkLayer and VisibleEntityLayers components respectively. The client will receive entity packets from only the layers it can see. Clients can add and remove entity layers at any time to spawn and despawn the entities in the layer.

Every layer contains a "message buffer" for broadcasting information to all viewers. Every message contains a "key" and a payload of bytes (its meaning depends on the message). Clients walk through the list of messages and use this to update themselves.

There are a few things done to make this faster:

  • Message processing is parallelized over all clients.
  • The messages are sorted by their "key" and then deduplicated by merging payloads together. For instance, messages sending packet data on the condition that a certain chunk position is in view will be merged together if the chunk position is the same. Now there's only one memcpy instead of two.
  • Messages are split into two categories: "global" and "local". Local messages are those that have some spatial condition to them. Local messages are put in a bounding volume hierarchy so that large swaths of messages do not need to be examined by clients.

TODOs

  • More unit tests and fix bugs.
  • Add missing docs.
  • Reimplement valence_anvil.
  • Reimplement weather module.
  • Reimplement valence_world_border.

Footnotes

  1. At least the work is completely parallelized ¯\_(ツ)_/¯.

  2. Viewing multiple chunk layers has some technical problems and I don't see it as a design worth pursuing.

@rj00a rj00a mentioned this pull request Jul 31, 2023
3 tasks
@rj00a
Copy link
Member Author

rj00a commented Aug 1, 2023

Alright, this should be ready to go.

@dyc3 If you'd like to merge the ctf example we can do that now.

@rj00a rj00a marked this pull request as ready for review August 1, 2023 11:53
@rj00a
Copy link
Member Author

rj00a commented Aug 1, 2023

Hmm mysterious CI failures.

# Objective

Created to test out the visibility layer API in #424

requires #424

# Solution

Added a `ctf` example, where only the players on your team are glowing.

Currently somewhat bugged.
Copy link
Collaborator

@dyc3 dyc3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

crates/valence_client/src/lib.rs Show resolved Hide resolved
crates/valence_layer/README.md Outdated Show resolved Hide resolved
crates/valence_layer/src/chunk/loaded.rs Outdated Show resolved Hide resolved
crates/valence_layer/src/message.rs Outdated Show resolved Hide resolved
crates/valence_world_border/src/lib.rs Show resolved Hide resolved
crates/valence_world_border/src/lib.rs Show resolved Hide resolved
src/tests/weather.rs Outdated Show resolved Hide resolved
src/tests/world_border.rs Outdated Show resolved Hide resolved
@dyc3
Copy link
Collaborator

dyc3 commented Aug 1, 2023

The CI failures might be related to Testing many_players. Maybe it's getting OOM killed?

@rj00a rj00a enabled auto-merge (squash) August 2, 2023 14:40
@rj00a rj00a merged commit b99ad81 into main Aug 2, 2023
13 checks passed
@rj00a rj00a deleted the layers branch August 2, 2023 15:11
@rj00a rj00a mentioned this pull request Aug 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Visibility Layers
3 participants