## Description
Add the ping computation system and capability to send ping to
connecting clients.
Currently the player list will only update upon connection. Should
another ticket be made for updating this since it seems out of scope for
this issue?
## Test Plan
Printing ping per keepalive packet on a different computer on my
network. It seems to work fine but would need extra feedback.
#### Related
#207
<!-- Please make sure that your PR is aligned with the guidelines in
CONTRIBUTING.md to the best of your ability. -->
<!-- Good PRs have tests! Make sure you have sufficient test coverage.
-->
## Description
<!-- Describe the changes you've made. You may include any justification
you want here. -->
I've used the popular `owo-colors` library to colourise the output of
the `packet_inspector`.
This makes it a lot easier to see who's sending what for debugging
purposes.
In future, I'd like to be able to filter out common, low-information
packets like `SetPlayerPosition` and `KeepAlive` as well, but that's not
in this PR.
![image](https://user-images.githubusercontent.com/28905212/218880818-69c0461c-bd23-45c4-9fd4-7c5868be4b67.png)
## Test Plan
No tests - just eyeball 😄.
<!-- Please make sure that your PR is aligned with the guidelines in
CONTRIBUTING.md to the best of your ability. -->
<!-- Good PRs have tests! Make sure you have sufficient test coverage.
-->
## Description
<!-- Describe the changes you've made. You may include any justification
you want here. -->
Added a quick and dirty bounds check because we haven't created drop
item/itemstack event(s) yet.
## Test Plan
<!-- Explain how you tested your changes, and include any code that you
used to test this. -->
<!-- If there is an example that is sufficient to use in place of a
playground, replace the playground section with a note that indicates
this. -->
use the `building` example
<!-- You need to include steps regardless of whether or not you are
using a playground. -->
Steps:
1. `cargo run --example building`
2. open inventory
3. pick an item
4. drop the item outside of the inventory window
5. see that the server does not panic
#### Related
<!-- Link to any issues that have context for this or that this PR
fixes. -->
fixes#233
This PR redesigns Valence's architecture around the Bevy Entity
Component System framework (`bevy_ecs` and `bevy_app`). Along the way, a
large number of changes and improvements have been made.
- Valence is now a Bevy plugin. This allows Valence to integrate with
the wider Bevy ecosystem.
- The `Config` trait has been replaced with the plugin struct which is
much easier to configure. Async callbacks are grouped into their own
trait.
- `World` has been renamed to `Instance` to avoid confusion with
`bevy_ecs::world::World`.
- Entities, clients, player list, and inventories are all just ECS
components/resources. There is no need for us to have our own
generational arena/slotmap/etc for each one.
- Client events use Bevy's event system. Users can read events with the
`EventReader` system parameter. This also means that events are
dispatched at an earlier stage of the program where access to the full
server is available. There is a special "event loop" stage which is used
primarily to avoid the loss of ordering information between events.
- Chunks have been completely overhauled to be simpler and faster. The
distinction between loaded and unloaded chunks has been mostly
eliminated. The per-section bitset that tracked changes has been
removed, which should further reduce memory usage. More operations on
chunks are available such as removal and cloning.
- The full client's game profile is accessible rather than just the
textures.
- Replaced `vek` with `glam` for parity with Bevy.
- Basic inventory support has been added.
- Various small changes to `valence_protocol`.
- New Examples
- The terrain and anvil examples are now fully asynchronous and will not
block the main tick loop while chunks are loading.
# TODOs
- [x] Implement and dispatch client events.
- ~~[ ] Finish implementing the new entity/chunk update algorithm.~~ New
approach ended up being slower. And also broken.
- [x] [Update rust-mc-bot to
1.19.3](https://github.com/Eoghanmc22/rust-mc-bot/pull/3).
- [x] Use rust-mc-bot to test for and fix any performance regressions.
Revert to old entity/chunk update algorithm if the new one turns out to
be slower for some reason.
- [x] Make inventories an ECS component.
- [x] Make player lists an ECS ~~component~~ resource.
- [x] Expose all properties of the client's game profile.
- [x] Update the examples.
- [x] Update `valence_anvil`.
- ~~[ ] Update `valence_spatial_index` to use `glam` instead of `vek`.~~
Maybe later
- [x] Make entity events use a bitset.
- [x] Update docs.
Closes#69Closes#179Closes#53
---------
Co-authored-by: Carson McManus <dyc3@users.noreply.github.com>
Co-authored-by: AviiNL <me@avii.nl>
Co-authored-by: Danik Vitek <x3665107@gmail.com>
Co-authored-by: Snowiiii <71594357+Snowiiii@users.noreply.github.com>
- Extends `Text`'s `Deserialize` impl to allow for deserializing JSON
data types other than objects.
- Add additional `From` impls for `Text`.
- Better `Debug` impl for `Text`.
- Tweaked text unit tests.
Adds `tracing` to `valence_protocol` so we can log debug info about
partially decoded packets. `packet_inspector` has been set to print log
messages at the debug level.
Adds the `valence_anvil` crate for loading anvil worlds. It can only read blocks and biomes currently. Support for saving data is to be added later.
Co-authored-by: Ryan <ryanj00a@gmail.com>
- Fix performance issues related to writing individual bytes instead of
using `Write::write_all`.
- Make manual implementations of `Encode` and `Decode` easier:
- Remove `encoded_len` method from `Encode`
- Split `Packet` trait into `EncodePacket` and `DecodePacket`.
- Simplify derive macros.
- automatically handle CloseContainer packet so the client updates open_inventory
- Use `Option<InventoryId>` for `open_inventory` on client
Co-authored-by: Ryan Johnson <ryanj00a@gmail.com>
This PR also includes the Criterion benchmark.
## Before this commit
> Benchmarking BlockState::to_kind
> Benchmarking BlockState::to_kind: Warming up for 3.0000 s Benchmarking
BlockState::to_kind: Collecting 100 samples in estimated 20.045 s (273k
iterations) Benchmarking BlockState::to_kind: Analyzing
> BlockState::to_kind time: [68.925 µs 69.202 µs 69.477 µs]
>
> Found 5 outliers among 100 measurements (5.00%)
> 4 (4.00%) high mild
> 1 (1.00%) high severe
## After this commit
> Benchmarking BlockState::to_kind
> Benchmarking BlockState::to_kind: Warming up for 3.0000 s Benchmarking
BlockState::to_kind: Collecting 100 samples in estimated 20.010 s (3.8M
iterations) Benchmarking BlockState::to_kind: Analyzing
> BlockState::to_kind time: [1.5814 µs 1.5859 µs 1.5912 µs]
> change: [-97.692% -97.678% -97.666%] (p = 0.00 < 0.05)
> Performance has improved.
> Found 4 outliers among 100 measurements (4.00%)
> 4 (4.00%) high mild
Co-authored-by: Ryan Johnson <ryanj00a@gmail.com>
- Implement `encoded_len` for packet enums.
- Fix bug in `has_next_packet` causing a later `unwrap` to panic.
- Add robust `encoded_len` check in `PacketEncoder` for debug builds.
- Split packet inspector regex into separate "inclusive" and "exclusive"
arguments because the `regex` crate does not support negative lookahead.
- Better `Debug` impls for `Ident` and `Compound`.
- Remove read/write timeouts from packet inspector.
Previously, the chunk data cache was regenerated at the end of each tick
every time a block or biome was modified in a chunk. This causes
performance problems in situations where chunks are being modified every
tick, like the conway example or redstone machines.
This changes things so that the chunk data packet is regenerated only
when a client actually needs to load the chunk. This isn't perfect
because the regeneration cannot happen in parallel, but the benefits
outweigh the costs. (The chunk data packet _is_ generated in parallel
when the chunk is first created. There is also some parallelism when
clients are loading different chunks. The packet cache is guarded by a
`Mutex`.)
This has revealed that compression is surprisingly slow. This should be
investigated later.
Closes#84
# Changes
- Implemented new algorithm for tracking loaded entities and chunks.
- The client does not need to maintain a list of loaded chunks and
entities anymore, as this information can be inferred using carefully
maintained data from the previous tick.
- Chunks are used as a spatial partition for entities. Entity visibility
is now based on chunk visibility rather than the euclidean distance to
clients.
- The BVH is no longer strictly necessary, so it has been moved to the
new `valence_spatial_index` crate.
- The API has been generalized to support things other than entities.
The crate does not have a dependency on the main `valence` crate.
- Chunk, entity, and player list packets are now aggressively cached to
increase performance.
- Chunk packets now include some filler light data. This makes the
vanilla client lag a lot less.
- Entities and chunks must now be marked as deleted before they are
removed.
- Improved `ChunkPos` interface.
- Added function to get the duration per tick.
- Added `Index` and `IndexMut` impls to collection types.
As a result of the above changes, performance under heavy load has
increased significantly. With the rust-mc-bot test on my machine, I went
from a max of ~1000 players to ~4000 players.
# Noteworthy Changes
- Simplified the `client` module and update procedure. Sending packets
is not deferred unless necessary.
- Client events are no longer buffered in `Client` before reaching the
user.
- Expanded `ClientEvent` to account for most packets.
- Most types containing custom `state` now implement `Deref` and
`DerefMut`. This means you don't have to write `.state` all over the
place. `Server` was excluded from this because it does not play well
with the borrow checker.
- Fixed bugs related to entity visibility.
- Client now correctly holds the semaphore permit from the initial
connection.
- Other miscellaneous API changes throughout the project.
# Known Issues
- Inventory stuff is still incomplete. The inventory examples have been
temporarily disabled.
The `tracing` crate seems to be the go-to
logging/profiling/instrumentation solution nowadays. Perhaps in the
future we could use `tracing` for profiling instead of (or in addition
to) the `perf`-based `cargo flamegraph` command. This would sidestep the
issue of `rayon` polluting the output. I conducted an initial experiment
by adding some more spans but wasn't very happy with the result.
Log messages have also been improved. There is some additional context
and events are raised when clients are added/removed from the server.
With the introduction of `valence_protocol` and some future plans, I've decided it's unrealistic to try and hide all the protocol code. There are situations where direct access is necessary.