Reorganize Project (#321)
## Description
- `valence` and `valence_protocol` have been divided into smaller crates
in order to parallelize the build and improve IDE responsiveness. In the
process, code architecture has been made clearer by removing circular
dependencies between modules. `valence` is now just a shell around the
other crates.
- `workspace.packages` and `workspace.dependencies` are now used. This
makes dependency managements and crate configuration much easier.
- `valence_protocol` is no more. Most things from `valence_protocol`
ended up in `valence_core`. We won't advertise `valence_core` as a
general-purpose protocol library since it contains too much
valence-specific stuff. Closes #308.
- Networking code (login, initial TCP connection handling, etc.) has
been extracted into the `valence_network` crate. The API has been
expanded and improved with better defaults. Player counts and initial
connections to the server are now tracked separately. Player counts
function by default without any user configuration.
- Some crates like `valence_anvil`, `valence_network`,
`valence_player_list`, `valence_inventory`, etc. are now optional. They
can be enabled/disabled with feature flags and `DefaultPlugins` just
like bevy.
- Whole-server unit tests have been moved to `valence/src/tests` in
order to avoid [cyclic
dev-dependencies](https://github.com/rust-lang/cargo/issues/4242).
- Tools like `valence_stresser` and `packet_inspector` have been moved
to a new `tools` directory. Renamed `valence_stresser` to `stresser`.
Closes #241.
- Moved all benches to `valence/benches/` to make them easier to run and
organize.
Ignoring transitive dependencies and `valence_core`, here's what the
dependency graph looks like now:
```mermaid
graph TD
network --> client
client --> instance
biome --> registry
dimension --> registry
instance --> biome
instance --> dimension
instance --> entity
player_list --> client
inventory --> client
anvil --> instance
entity --> block
```
### Issues
- Inventory tests inspect many private implementation details of the
inventory module, forcing us to mark things as `pub` and
`#[doc(hidden)]`. It would be ideal if the tests only looked at
observable behavior.
- Consider moving packets in `valence_core` elsewhere. `Particle` wants
to use `BlockState`, but that's defined in `valence_block`, so we can't
use it without causing cycles.
- Unsure what exactly should go in `valence::prelude`.
- This could use some more tests of course, but I'm holding off on that
until I'm confident this is the direction we want to take things.
## TODOs
- [x] Update examples.
- [x] Update benches.
- [x] Update main README.
- [x] Add short READMEs to crates.
- [x] Test new schedule to ensure behavior is the same.
- [x] Update tools.
- [x] Copy lints to all crates.
- [x] Fix docs, clippy, etc.
2023-04-22 07:43:59 +10:00
|
|
|
#![doc = include_str!("../README.md")]
|
|
|
|
#![deny(
|
|
|
|
rustdoc::broken_intra_doc_links,
|
|
|
|
rustdoc::private_intra_doc_links,
|
|
|
|
rustdoc::missing_crate_level_docs,
|
|
|
|
rustdoc::invalid_codeblock_attributes,
|
|
|
|
rustdoc::invalid_rust_codeblocks,
|
|
|
|
rustdoc::bare_urls,
|
|
|
|
rustdoc::invalid_html_tags
|
|
|
|
)]
|
|
|
|
#![warn(
|
|
|
|
trivial_casts,
|
|
|
|
trivial_numeric_casts,
|
|
|
|
unused_lifetimes,
|
|
|
|
unused_import_braces,
|
|
|
|
unreachable_pub,
|
|
|
|
clippy::dbg_macro
|
|
|
|
)]
|
|
|
|
|
2023-05-09 10:34:33 +10:00
|
|
|
pub mod hitbox;
|
2023-05-29 18:36:11 +10:00
|
|
|
pub mod packet;
|
2023-05-09 10:34:33 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
use std::num::Wrapping;
|
2023-02-12 04:51:53 +11:00
|
|
|
use std::ops::Range;
|
2022-04-15 07:55:45 +10:00
|
|
|
|
2023-03-16 10:12:59 +11:00
|
|
|
use bevy_app::{App, CoreSet, Plugin};
|
2023-02-12 04:51:53 +11:00
|
|
|
use bevy_ecs::prelude::*;
|
Reorganize Project (#321)
## Description
- `valence` and `valence_protocol` have been divided into smaller crates
in order to parallelize the build and improve IDE responsiveness. In the
process, code architecture has been made clearer by removing circular
dependencies between modules. `valence` is now just a shell around the
other crates.
- `workspace.packages` and `workspace.dependencies` are now used. This
makes dependency managements and crate configuration much easier.
- `valence_protocol` is no more. Most things from `valence_protocol`
ended up in `valence_core`. We won't advertise `valence_core` as a
general-purpose protocol library since it contains too much
valence-specific stuff. Closes #308.
- Networking code (login, initial TCP connection handling, etc.) has
been extracted into the `valence_network` crate. The API has been
expanded and improved with better defaults. Player counts and initial
connections to the server are now tracked separately. Player counts
function by default without any user configuration.
- Some crates like `valence_anvil`, `valence_network`,
`valence_player_list`, `valence_inventory`, etc. are now optional. They
can be enabled/disabled with feature flags and `DefaultPlugins` just
like bevy.
- Whole-server unit tests have been moved to `valence/src/tests` in
order to avoid [cyclic
dev-dependencies](https://github.com/rust-lang/cargo/issues/4242).
- Tools like `valence_stresser` and `packet_inspector` have been moved
to a new `tools` directory. Renamed `valence_stresser` to `stresser`.
Closes #241.
- Moved all benches to `valence/benches/` to make them easier to run and
organize.
Ignoring transitive dependencies and `valence_core`, here's what the
dependency graph looks like now:
```mermaid
graph TD
network --> client
client --> instance
biome --> registry
dimension --> registry
instance --> biome
instance --> dimension
instance --> entity
player_list --> client
inventory --> client
anvil --> instance
entity --> block
```
### Issues
- Inventory tests inspect many private implementation details of the
inventory module, forcing us to mark things as `pub` and
`#[doc(hidden)]`. It would be ideal if the tests only looked at
observable behavior.
- Consider moving packets in `valence_core` elsewhere. `Particle` wants
to use `BlockState`, but that's defined in `valence_block`, so we can't
use it without causing cycles.
- Unsure what exactly should go in `valence::prelude`.
- This could use some more tests of course, but I'm holding off on that
until I'm confident this is the direction we want to take things.
## TODOs
- [x] Update examples.
- [x] Update benches.
- [x] Update main README.
- [x] Add short READMEs to crates.
- [x] Test new schedule to ensure behavior is the same.
- [x] Update tools.
- [x] Copy lints to all crates.
- [x] Fix docs, clippy, etc.
2023-04-22 07:43:59 +10:00
|
|
|
use glam::{DVec3, Vec3};
|
2023-03-22 17:29:38 +11:00
|
|
|
use paste::paste;
|
2023-02-12 04:51:53 +11:00
|
|
|
use rustc_hash::FxHashMap;
|
|
|
|
use tracing::warn;
|
2022-04-15 07:55:45 +10:00
|
|
|
use uuid::Uuid;
|
Reorganize Project (#321)
## Description
- `valence` and `valence_protocol` have been divided into smaller crates
in order to parallelize the build and improve IDE responsiveness. In the
process, code architecture has been made clearer by removing circular
dependencies between modules. `valence` is now just a shell around the
other crates.
- `workspace.packages` and `workspace.dependencies` are now used. This
makes dependency managements and crate configuration much easier.
- `valence_protocol` is no more. Most things from `valence_protocol`
ended up in `valence_core`. We won't advertise `valence_core` as a
general-purpose protocol library since it contains too much
valence-specific stuff. Closes #308.
- Networking code (login, initial TCP connection handling, etc.) has
been extracted into the `valence_network` crate. The API has been
expanded and improved with better defaults. Player counts and initial
connections to the server are now tracked separately. Player counts
function by default without any user configuration.
- Some crates like `valence_anvil`, `valence_network`,
`valence_player_list`, `valence_inventory`, etc. are now optional. They
can be enabled/disabled with feature flags and `DefaultPlugins` just
like bevy.
- Whole-server unit tests have been moved to `valence/src/tests` in
order to avoid [cyclic
dev-dependencies](https://github.com/rust-lang/cargo/issues/4242).
- Tools like `valence_stresser` and `packet_inspector` have been moved
to a new `tools` directory. Renamed `valence_stresser` to `stresser`.
Closes #241.
- Moved all benches to `valence/benches/` to make them easier to run and
organize.
Ignoring transitive dependencies and `valence_core`, here's what the
dependency graph looks like now:
```mermaid
graph TD
network --> client
client --> instance
biome --> registry
dimension --> registry
instance --> biome
instance --> dimension
instance --> entity
player_list --> client
inventory --> client
anvil --> instance
entity --> block
```
### Issues
- Inventory tests inspect many private implementation details of the
inventory module, forcing us to mark things as `pub` and
`#[doc(hidden)]`. It would be ideal if the tests only looked at
observable behavior.
- Consider moving packets in `valence_core` elsewhere. `Particle` wants
to use `BlockState`, but that's defined in `valence_block`, so we can't
use it without causing cycles.
- Unsure what exactly should go in `valence::prelude`.
- This could use some more tests of course, but I'm holding off on that
until I'm confident this is the direction we want to take things.
## TODOs
- [x] Update examples.
- [x] Update benches.
- [x] Update main README.
- [x] Add short READMEs to crates.
- [x] Test new schedule to ensure behavior is the same.
- [x] Update tools.
- [x] Copy lints to all crates.
- [x] Fix docs, clippy, etc.
2023-04-22 07:43:59 +10:00
|
|
|
use valence_core::chunk_pos::ChunkPos;
|
|
|
|
use valence_core::despawn::Despawned;
|
2023-05-29 18:36:11 +10:00
|
|
|
use valence_core::protocol::var_int::VarInt;
|
|
|
|
use valence_core::protocol::{Decode, Encode};
|
Reorganize Project (#321)
## Description
- `valence` and `valence_protocol` have been divided into smaller crates
in order to parallelize the build and improve IDE responsiveness. In the
process, code architecture has been made clearer by removing circular
dependencies between modules. `valence` is now just a shell around the
other crates.
- `workspace.packages` and `workspace.dependencies` are now used. This
makes dependency managements and crate configuration much easier.
- `valence_protocol` is no more. Most things from `valence_protocol`
ended up in `valence_core`. We won't advertise `valence_core` as a
general-purpose protocol library since it contains too much
valence-specific stuff. Closes #308.
- Networking code (login, initial TCP connection handling, etc.) has
been extracted into the `valence_network` crate. The API has been
expanded and improved with better defaults. Player counts and initial
connections to the server are now tracked separately. Player counts
function by default without any user configuration.
- Some crates like `valence_anvil`, `valence_network`,
`valence_player_list`, `valence_inventory`, etc. are now optional. They
can be enabled/disabled with feature flags and `DefaultPlugins` just
like bevy.
- Whole-server unit tests have been moved to `valence/src/tests` in
order to avoid [cyclic
dev-dependencies](https://github.com/rust-lang/cargo/issues/4242).
- Tools like `valence_stresser` and `packet_inspector` have been moved
to a new `tools` directory. Renamed `valence_stresser` to `stresser`.
Closes #241.
- Moved all benches to `valence/benches/` to make them easier to run and
organize.
Ignoring transitive dependencies and `valence_core`, here's what the
dependency graph looks like now:
```mermaid
graph TD
network --> client
client --> instance
biome --> registry
dimension --> registry
instance --> biome
instance --> dimension
instance --> entity
player_list --> client
inventory --> client
anvil --> instance
entity --> block
```
### Issues
- Inventory tests inspect many private implementation details of the
inventory module, forcing us to mark things as `pub` and
`#[doc(hidden)]`. It would be ideal if the tests only looked at
observable behavior.
- Consider moving packets in `valence_core` elsewhere. `Particle` wants
to use `BlockState`, but that's defined in `valence_block`, so we can't
use it without causing cycles.
- Unsure what exactly should go in `valence::prelude`.
- This could use some more tests of course, but I'm holding off on that
until I'm confident this is the direction we want to take things.
## TODOs
- [x] Update examples.
- [x] Update benches.
- [x] Update main README.
- [x] Add short READMEs to crates.
- [x] Test new schedule to ensure behavior is the same.
- [x] Update tools.
- [x] Copy lints to all crates.
- [x] Fix docs, clippy, etc.
2023-04-22 07:43:59 +10:00
|
|
|
use valence_core::uuid::UniqueId;
|
|
|
|
use valence_core::DEFAULT_TPS;
|
2022-07-28 00:10:35 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
include!(concat!(env!("OUT_DIR"), "/entity.rs"));
|
Reorganize Project (#321)
## Description
- `valence` and `valence_protocol` have been divided into smaller crates
in order to parallelize the build and improve IDE responsiveness. In the
process, code architecture has been made clearer by removing circular
dependencies between modules. `valence` is now just a shell around the
other crates.
- `workspace.packages` and `workspace.dependencies` are now used. This
makes dependency managements and crate configuration much easier.
- `valence_protocol` is no more. Most things from `valence_protocol`
ended up in `valence_core`. We won't advertise `valence_core` as a
general-purpose protocol library since it contains too much
valence-specific stuff. Closes #308.
- Networking code (login, initial TCP connection handling, etc.) has
been extracted into the `valence_network` crate. The API has been
expanded and improved with better defaults. Player counts and initial
connections to the server are now tracked separately. Player counts
function by default without any user configuration.
- Some crates like `valence_anvil`, `valence_network`,
`valence_player_list`, `valence_inventory`, etc. are now optional. They
can be enabled/disabled with feature flags and `DefaultPlugins` just
like bevy.
- Whole-server unit tests have been moved to `valence/src/tests` in
order to avoid [cyclic
dev-dependencies](https://github.com/rust-lang/cargo/issues/4242).
- Tools like `valence_stresser` and `packet_inspector` have been moved
to a new `tools` directory. Renamed `valence_stresser` to `stresser`.
Closes #241.
- Moved all benches to `valence/benches/` to make them easier to run and
organize.
Ignoring transitive dependencies and `valence_core`, here's what the
dependency graph looks like now:
```mermaid
graph TD
network --> client
client --> instance
biome --> registry
dimension --> registry
instance --> biome
instance --> dimension
instance --> entity
player_list --> client
inventory --> client
anvil --> instance
entity --> block
```
### Issues
- Inventory tests inspect many private implementation details of the
inventory module, forcing us to mark things as `pub` and
`#[doc(hidden)]`. It would be ideal if the tests only looked at
observable behavior.
- Consider moving packets in `valence_core` elsewhere. `Particle` wants
to use `BlockState`, but that's defined in `valence_block`, so we can't
use it without causing cycles.
- Unsure what exactly should go in `valence::prelude`.
- This could use some more tests of course, but I'm holding off on that
until I'm confident this is the direction we want to take things.
## TODOs
- [x] Update examples.
- [x] Update benches.
- [x] Update main README.
- [x] Add short READMEs to crates.
- [x] Test new schedule to ensure behavior is the same.
- [x] Update tools.
- [x] Copy lints to all crates.
- [x] Fix docs, clippy, etc.
2023-04-22 07:43:59 +10:00
|
|
|
pub struct EntityPlugin;
|
|
|
|
|
|
|
|
/// When new Minecraft entities are initialized and added to
|
|
|
|
/// [`EntityManager`].
|
|
|
|
///
|
|
|
|
/// Systems that need Minecraft entities to be in a valid state should run
|
|
|
|
/// _after_ this set.
|
|
|
|
#[derive(SystemSet, Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
|
|
|
pub struct InitEntitiesSet;
|
|
|
|
|
|
|
|
/// When tracked data is written to the entity's [`TrackedData`] component.
|
|
|
|
/// Systems that modify tracked data should run _before_ this.
|
|
|
|
#[derive(SystemSet, Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
|
|
|
pub struct UpdateTrackedDataSet;
|
|
|
|
|
|
|
|
/// When entities are updated and changes from the current tick are cleared.
|
|
|
|
/// Systems that need to observe changes to entities (Such as the difference
|
|
|
|
/// between [`Position`] and [`OldPosition`]) should run _before_ this set (and
|
|
|
|
/// probably after [`InitEntitiesSet`]).
|
|
|
|
#[derive(SystemSet, Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
|
|
|
pub struct ClearEntityChangesSet;
|
|
|
|
|
|
|
|
impl Plugin for EntityPlugin {
|
|
|
|
fn build(&self, app: &mut App) {
|
|
|
|
app.insert_resource(EntityManager::new())
|
|
|
|
.configure_sets((
|
|
|
|
InitEntitiesSet.in_base_set(CoreSet::PostUpdate),
|
|
|
|
UpdateTrackedDataSet.in_base_set(CoreSet::PostUpdate),
|
|
|
|
ClearEntityChangesSet
|
|
|
|
.after(InitEntitiesSet)
|
|
|
|
.after(UpdateTrackedDataSet)
|
|
|
|
.in_base_set(CoreSet::PostUpdate),
|
|
|
|
))
|
|
|
|
.add_systems(
|
|
|
|
(init_entities, remove_despawned_from_manager)
|
|
|
|
.chain()
|
|
|
|
.in_set(InitEntitiesSet),
|
|
|
|
)
|
|
|
|
.add_systems(
|
|
|
|
(
|
|
|
|
clear_status_changes,
|
|
|
|
clear_animation_changes,
|
|
|
|
clear_tracked_data_changes,
|
|
|
|
update_old_position,
|
|
|
|
update_old_location,
|
|
|
|
)
|
|
|
|
.in_set(ClearEntityChangesSet),
|
|
|
|
);
|
|
|
|
|
|
|
|
add_tracked_data_systems(app);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn update_old_position(mut query: Query<(&Position, &mut OldPosition)>) {
|
|
|
|
for (pos, mut old_pos) in &mut query {
|
|
|
|
old_pos.0 = pos.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn update_old_location(mut query: Query<(&Location, &mut OldLocation)>) {
|
|
|
|
for (loc, mut old_loc) in &mut query {
|
|
|
|
old_loc.0 = loc.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn init_entities(
|
|
|
|
mut entities: Query<
|
|
|
|
(
|
|
|
|
Entity,
|
|
|
|
&mut EntityId,
|
|
|
|
&mut UniqueId,
|
|
|
|
&Position,
|
|
|
|
&mut OldPosition,
|
|
|
|
),
|
|
|
|
Added<EntityKind>,
|
|
|
|
>,
|
|
|
|
mut manager: ResMut<EntityManager>,
|
|
|
|
) {
|
|
|
|
for (entity, mut id, uuid, pos, mut old_pos) in &mut entities {
|
|
|
|
*old_pos = OldPosition::new(pos.0);
|
|
|
|
|
|
|
|
if *id == EntityId::default() {
|
|
|
|
*id = manager.next_id();
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(conflict) = manager.id_to_entity.insert(id.0, entity) {
|
|
|
|
warn!(
|
|
|
|
"entity {entity:?} has conflicting entity ID of {} with entity {conflict:?}",
|
|
|
|
id.0
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(conflict) = manager.uuid_to_entity.insert(uuid.0, entity) {
|
|
|
|
warn!(
|
|
|
|
"entity {entity:?} has conflicting UUID of {} with entity {conflict:?}",
|
|
|
|
uuid.0
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(clippy::type_complexity)]
|
|
|
|
fn remove_despawned_from_manager(
|
|
|
|
entities: Query<(&EntityId, &UniqueId), (With<EntityKind>, With<Despawned>)>,
|
|
|
|
mut manager: ResMut<EntityManager>,
|
|
|
|
) {
|
|
|
|
for (id, uuid) in &entities {
|
|
|
|
manager.id_to_entity.remove(&id.0);
|
|
|
|
manager.uuid_to_entity.remove(&uuid.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn clear_status_changes(mut statuses: Query<&mut EntityStatuses, Changed<EntityStatuses>>) {
|
|
|
|
for mut statuses in &mut statuses {
|
|
|
|
statuses.0 = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn clear_animation_changes(
|
|
|
|
mut animations: Query<&mut EntityAnimations, Changed<EntityAnimations>>,
|
|
|
|
) {
|
|
|
|
for mut animations in &mut animations {
|
|
|
|
animations.0 = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn clear_tracked_data_changes(mut tracked_data: Query<&mut TrackedData, Changed<TrackedData>>) {
|
|
|
|
for mut tracked_data in &mut tracked_data {
|
|
|
|
tracked_data.clear_update_values();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Contains the `Instance` an entity is located in. For the coordinates
|
|
|
|
/// within the instance, see [`Position`].
|
|
|
|
#[derive(Component, Copy, Clone, PartialEq, Eq, Debug)]
|
|
|
|
pub struct Location(pub Entity);
|
|
|
|
|
|
|
|
impl Default for Location {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self(Entity::PLACEHOLDER)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq<OldLocation> for Location {
|
|
|
|
fn eq(&self, other: &OldLocation) -> bool {
|
|
|
|
self.0 == other.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The value of [`Location`] from the end of the previous tick.
|
|
|
|
///
|
|
|
|
/// **NOTE**: You should not modify this component after the entity is spawned.
|
|
|
|
#[derive(Component, Copy, Clone, PartialEq, Eq, Debug)]
|
|
|
|
pub struct OldLocation(Entity);
|
|
|
|
|
|
|
|
impl OldLocation {
|
|
|
|
pub fn new(instance: Entity) -> Self {
|
|
|
|
Self(instance)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get(&self) -> Entity {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for OldLocation {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self(Entity::PLACEHOLDER)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq<Location> for OldLocation {
|
|
|
|
fn eq(&self, other: &Location) -> bool {
|
|
|
|
self.0 == other.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Component, Copy, Clone, PartialEq, Default, Debug)]
|
|
|
|
pub struct Position(pub DVec3);
|
|
|
|
|
|
|
|
impl Position {
|
|
|
|
pub fn new(pos: impl Into<DVec3>) -> Self {
|
|
|
|
Self(pos.into())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn chunk_pos(&self) -> ChunkPos {
|
|
|
|
ChunkPos::from_dvec3(self.0)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get(self) -> DVec3 {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set(&mut self, pos: impl Into<DVec3>) {
|
|
|
|
self.0 = pos.into();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq<OldPosition> for Position {
|
|
|
|
fn eq(&self, other: &OldPosition) -> bool {
|
|
|
|
self.0 == other.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The value of [`Position`] from the end of the previous tick.
|
|
|
|
///
|
|
|
|
/// **NOTE**: You should not modify this component after the entity is spawned.
|
|
|
|
#[derive(Component, Copy, Clone, PartialEq, Default, Debug)]
|
|
|
|
pub struct OldPosition(DVec3);
|
|
|
|
|
|
|
|
impl OldPosition {
|
|
|
|
pub fn new(pos: impl Into<DVec3>) -> Self {
|
|
|
|
Self(pos.into())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get(self) -> DVec3 {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn chunk_pos(self) -> ChunkPos {
|
|
|
|
ChunkPos::from_dvec3(self.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq<Position> for OldPosition {
|
|
|
|
fn eq(&self, other: &Position) -> bool {
|
|
|
|
self.0 == other.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Describes the direction an entity is looking using pitch and yaw angles.
|
|
|
|
#[derive(Component, Copy, Clone, PartialEq, Default, Debug)]
|
|
|
|
pub struct Look {
|
|
|
|
/// The yaw angle in degrees.
|
|
|
|
pub yaw: f32,
|
|
|
|
/// The pitch angle in degrees.
|
|
|
|
pub pitch: f32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Look {
|
|
|
|
pub const fn new(yaw: f32, pitch: f32) -> Self {
|
|
|
|
Self { yaw, pitch }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets a normalized direction vector from the yaw and pitch.
|
|
|
|
pub fn vec(self) -> Vec3 {
|
|
|
|
let (yaw_sin, yaw_cos) = (self.yaw + 90.0).to_radians().sin_cos();
|
|
|
|
let (pitch_sin, pitch_cos) = (-self.pitch).to_radians().sin_cos();
|
|
|
|
|
|
|
|
Vec3::new(yaw_cos * pitch_cos, pitch_sin, yaw_sin * pitch_cos)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets the yaw and pitch using a normalized direction vector.
|
|
|
|
pub fn set_vec(&mut self, dir: Vec3) {
|
|
|
|
debug_assert!(
|
|
|
|
dir.is_normalized(),
|
|
|
|
"the direction vector should be normalized"
|
|
|
|
);
|
|
|
|
|
|
|
|
// Preserve the current yaw if we're looking straight up or down.
|
|
|
|
if dir.x != 0.0 || dir.z != 0.0 {
|
|
|
|
self.yaw = f32::atan2(dir.z, dir.x).to_degrees() - 90.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.pitch = -(dir.y).asin().to_degrees();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Component, Copy, Clone, PartialEq, Eq, Default, Debug)]
|
|
|
|
pub struct OnGround(pub bool);
|
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
/// A Minecraft entity's ID according to the protocol.
|
|
|
|
///
|
|
|
|
/// IDs should be _unique_ for the duration of the server and _constant_ for
|
|
|
|
/// the lifetime of the entity. IDs of -1 (the default) will be assigned to
|
|
|
|
/// something else on the tick the entity is added. If you need to know the ID
|
|
|
|
/// ahead of time, set this component to the value returned by
|
|
|
|
/// [`EntityManager::next_id`] before spawning.
|
|
|
|
#[derive(Component, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
|
|
|
pub struct EntityId(i32);
|
|
|
|
|
|
|
|
impl EntityId {
|
|
|
|
/// Returns the underlying entity ID as an integer.
|
|
|
|
pub fn get(self) -> i32 {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
}
|
2022-04-15 07:55:45 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
/// Returns an entity ID of -1.
|
|
|
|
impl Default for EntityId {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self(-1)
|
2022-06-30 04:09:00 +10:00
|
|
|
}
|
2023-02-12 04:51:53 +11:00
|
|
|
}
|
2022-06-30 04:09:00 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
#[derive(Component, Copy, Clone, PartialEq, Default, Debug)]
|
|
|
|
pub struct HeadYaw(pub f32);
|
|
|
|
|
|
|
|
/// Entity velocity in m/s.
|
|
|
|
#[derive(Component, Copy, Clone, Default, Debug)]
|
|
|
|
pub struct Velocity(pub Vec3);
|
2022-11-29 22:37:32 +11:00
|
|
|
|
Reorganize Project (#321)
## Description
- `valence` and `valence_protocol` have been divided into smaller crates
in order to parallelize the build and improve IDE responsiveness. In the
process, code architecture has been made clearer by removing circular
dependencies between modules. `valence` is now just a shell around the
other crates.
- `workspace.packages` and `workspace.dependencies` are now used. This
makes dependency managements and crate configuration much easier.
- `valence_protocol` is no more. Most things from `valence_protocol`
ended up in `valence_core`. We won't advertise `valence_core` as a
general-purpose protocol library since it contains too much
valence-specific stuff. Closes #308.
- Networking code (login, initial TCP connection handling, etc.) has
been extracted into the `valence_network` crate. The API has been
expanded and improved with better defaults. Player counts and initial
connections to the server are now tracked separately. Player counts
function by default without any user configuration.
- Some crates like `valence_anvil`, `valence_network`,
`valence_player_list`, `valence_inventory`, etc. are now optional. They
can be enabled/disabled with feature flags and `DefaultPlugins` just
like bevy.
- Whole-server unit tests have been moved to `valence/src/tests` in
order to avoid [cyclic
dev-dependencies](https://github.com/rust-lang/cargo/issues/4242).
- Tools like `valence_stresser` and `packet_inspector` have been moved
to a new `tools` directory. Renamed `valence_stresser` to `stresser`.
Closes #241.
- Moved all benches to `valence/benches/` to make them easier to run and
organize.
Ignoring transitive dependencies and `valence_core`, here's what the
dependency graph looks like now:
```mermaid
graph TD
network --> client
client --> instance
biome --> registry
dimension --> registry
instance --> biome
instance --> dimension
instance --> entity
player_list --> client
inventory --> client
anvil --> instance
entity --> block
```
### Issues
- Inventory tests inspect many private implementation details of the
inventory module, forcing us to mark things as `pub` and
`#[doc(hidden)]`. It would be ideal if the tests only looked at
observable behavior.
- Consider moving packets in `valence_core` elsewhere. `Particle` wants
to use `BlockState`, but that's defined in `valence_block`, so we can't
use it without causing cycles.
- Unsure what exactly should go in `valence::prelude`.
- This could use some more tests of course, but I'm holding off on that
until I'm confident this is the direction we want to take things.
## TODOs
- [x] Update examples.
- [x] Update benches.
- [x] Update main README.
- [x] Add short READMEs to crates.
- [x] Test new schedule to ensure behavior is the same.
- [x] Update tools.
- [x] Copy lints to all crates.
- [x] Fix docs, clippy, etc.
2023-04-22 07:43:59 +10:00
|
|
|
impl Velocity {
|
|
|
|
pub fn to_packet_units(self) -> [i16; 3] {
|
|
|
|
// The saturating casts to i16 are desirable.
|
|
|
|
(8000.0 / DEFAULT_TPS.get() as f32 * self.0)
|
|
|
|
.to_array()
|
|
|
|
.map(|v| v as i16)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
#[derive(Component, Copy, Clone, Default, Debug)]
|
|
|
|
pub struct EntityStatuses(pub u64);
|
2022-04-15 07:55:45 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
impl EntityStatuses {
|
|
|
|
pub fn trigger(&mut self, status: EntityStatus) {
|
|
|
|
self.set(status, true);
|
2022-12-11 21:37:02 +11:00
|
|
|
}
|
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
pub fn set(&mut self, status: EntityStatus, triggered: bool) {
|
|
|
|
self.0 |= (triggered as u64) << status as u64;
|
2022-12-11 21:37:02 +11:00
|
|
|
}
|
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
pub fn get(&self, status: EntityStatus) -> bool {
|
|
|
|
(self.0 >> status as u64) & 1 == 1
|
2022-04-15 07:55:45 +10:00
|
|
|
}
|
2022-05-16 19:36:14 +10:00
|
|
|
}
|
2022-04-15 07:55:45 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
#[derive(Component, Default, Debug)]
|
|
|
|
pub struct EntityAnimations(pub u8);
|
2023-03-16 10:12:59 +11:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
impl EntityAnimations {
|
|
|
|
pub fn trigger(&mut self, anim: EntityAnimation) {
|
|
|
|
self.set(anim, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set(&mut self, anim: EntityAnimation, triggered: bool) {
|
|
|
|
self.0 |= (triggered as u8) << anim as u8;
|
2023-03-16 10:12:59 +11:00
|
|
|
}
|
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
pub fn get(&self, anim: EntityAnimation) -> bool {
|
|
|
|
(self.0 >> anim as u8) & 1 == 1
|
2023-03-16 10:12:59 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
/// Extra integer data passed to the entity spawn packet. The meaning depends on
|
|
|
|
/// the type of entity being spawned.
|
2022-07-11 22:08:02 +10:00
|
|
|
///
|
2023-03-22 17:29:38 +11:00
|
|
|
/// Some examples:
|
|
|
|
/// - **Experience Orb**: Experience count
|
|
|
|
/// - **(Glowing) Item Frame**: Rotation
|
|
|
|
/// - **Painting**: Rotation
|
|
|
|
/// - **Falling Block**: Block state
|
|
|
|
/// - **Fishing Bobber**: Hook entity ID
|
|
|
|
/// - **Warden**: Initial pose
|
|
|
|
#[derive(Component, Default, Debug)]
|
|
|
|
pub struct ObjectData(pub i32);
|
|
|
|
|
|
|
|
/// The range of packet bytes for this entity within the cell the entity is
|
|
|
|
/// located in. For internal use only.
|
|
|
|
#[derive(Component, Default, Debug)]
|
Reorganize Project (#321)
## Description
- `valence` and `valence_protocol` have been divided into smaller crates
in order to parallelize the build and improve IDE responsiveness. In the
process, code architecture has been made clearer by removing circular
dependencies between modules. `valence` is now just a shell around the
other crates.
- `workspace.packages` and `workspace.dependencies` are now used. This
makes dependency managements and crate configuration much easier.
- `valence_protocol` is no more. Most things from `valence_protocol`
ended up in `valence_core`. We won't advertise `valence_core` as a
general-purpose protocol library since it contains too much
valence-specific stuff. Closes #308.
- Networking code (login, initial TCP connection handling, etc.) has
been extracted into the `valence_network` crate. The API has been
expanded and improved with better defaults. Player counts and initial
connections to the server are now tracked separately. Player counts
function by default without any user configuration.
- Some crates like `valence_anvil`, `valence_network`,
`valence_player_list`, `valence_inventory`, etc. are now optional. They
can be enabled/disabled with feature flags and `DefaultPlugins` just
like bevy.
- Whole-server unit tests have been moved to `valence/src/tests` in
order to avoid [cyclic
dev-dependencies](https://github.com/rust-lang/cargo/issues/4242).
- Tools like `valence_stresser` and `packet_inspector` have been moved
to a new `tools` directory. Renamed `valence_stresser` to `stresser`.
Closes #241.
- Moved all benches to `valence/benches/` to make them easier to run and
organize.
Ignoring transitive dependencies and `valence_core`, here's what the
dependency graph looks like now:
```mermaid
graph TD
network --> client
client --> instance
biome --> registry
dimension --> registry
instance --> biome
instance --> dimension
instance --> entity
player_list --> client
inventory --> client
anvil --> instance
entity --> block
```
### Issues
- Inventory tests inspect many private implementation details of the
inventory module, forcing us to mark things as `pub` and
`#[doc(hidden)]`. It would be ideal if the tests only looked at
observable behavior.
- Consider moving packets in `valence_core` elsewhere. `Particle` wants
to use `BlockState`, but that's defined in `valence_block`, so we can't
use it without causing cycles.
- Unsure what exactly should go in `valence::prelude`.
- This could use some more tests of course, but I'm holding off on that
until I'm confident this is the direction we want to take things.
## TODOs
- [x] Update examples.
- [x] Update benches.
- [x] Update main README.
- [x] Add short READMEs to crates.
- [x] Test new schedule to ensure behavior is the same.
- [x] Update tools.
- [x] Copy lints to all crates.
- [x] Fix docs, clippy, etc.
2023-04-22 07:43:59 +10:00
|
|
|
pub struct PacketByteRange(pub Range<usize>);
|
2023-03-22 17:29:38 +11:00
|
|
|
|
|
|
|
/// Cache for all the tracked data of an entity. Used for the
|
|
|
|
/// [`EntityTrackerUpdateS2c`][packet] packet.
|
2022-07-11 22:08:02 +10:00
|
|
|
///
|
2023-05-29 18:36:11 +10:00
|
|
|
/// [packet]: crate::packet::EntityTrackerUpdateS2c
|
2023-03-22 17:29:38 +11:00
|
|
|
#[derive(Component, Default, Debug)]
|
|
|
|
pub struct TrackedData {
|
|
|
|
init_data: Vec<u8>,
|
|
|
|
/// A map of tracked data indices to the byte length of the entry in
|
|
|
|
/// `init_data`.
|
|
|
|
init_entries: Vec<(u8, u32)>,
|
|
|
|
update_data: Vec<u8>,
|
2022-05-16 19:36:14 +10:00
|
|
|
}
|
2022-04-15 07:55:45 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
impl TrackedData {
|
|
|
|
/// Returns initial tracked data for the entity, ready to be sent in the
|
|
|
|
/// [`EntityTrackerUpdateS2c`][packet] packet. This is used when the entity
|
|
|
|
/// enters the view of a client.
|
2023-02-12 04:51:53 +11:00
|
|
|
///
|
2023-05-29 18:36:11 +10:00
|
|
|
/// [packet]: crate::packet::EntityTrackerUpdateS2c
|
2023-03-22 17:29:38 +11:00
|
|
|
pub fn init_data(&self) -> Option<&[u8]> {
|
|
|
|
if self.init_data.len() > 1 {
|
|
|
|
Some(&self.init_data)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
2022-11-29 22:37:32 +11:00
|
|
|
}
|
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
/// Contains updated tracked data for the entity, ready to be sent in the
|
|
|
|
/// [`EntityTrackerUpdateS2c`][packet] packet. This is used when tracked
|
|
|
|
/// data is changed and the client is already in view of the entity.
|
|
|
|
///
|
2023-05-29 18:36:11 +10:00
|
|
|
/// [packet]: crate::packet::EntityTrackerUpdateS2c
|
2023-03-22 17:29:38 +11:00
|
|
|
pub fn update_data(&self) -> Option<&[u8]> {
|
|
|
|
if self.update_data.len() > 1 {
|
|
|
|
Some(&self.update_data)
|
|
|
|
} else {
|
|
|
|
None
|
2023-02-12 04:51:53 +11:00
|
|
|
}
|
2022-11-29 22:37:32 +11:00
|
|
|
}
|
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
pub fn insert_init_value(&mut self, index: u8, type_id: u8, value: impl Encode) {
|
|
|
|
debug_assert!(
|
|
|
|
index != 0xff,
|
|
|
|
"index of 0xff is reserved for the terminator"
|
|
|
|
);
|
2022-07-28 00:10:35 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
self.remove_init_value(index);
|
2022-07-28 00:10:35 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
self.init_data.pop(); // Remove terminator.
|
2022-07-28 00:10:35 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
// Append the new value to the end.
|
|
|
|
let len_before = self.init_data.len();
|
2022-07-28 00:10:35 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
self.init_data.extend_from_slice(&[index, type_id]);
|
|
|
|
if let Err(e) = value.encode(&mut self.init_data) {
|
|
|
|
warn!("failed to encode initial tracked data: {e:#}");
|
|
|
|
}
|
2023-02-12 04:51:53 +11:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
let len = self.init_data.len() - len_before;
|
2022-07-04 08:31:24 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
self.init_entries.push((index, len as u32));
|
2022-07-04 08:31:24 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
self.init_data.push(0xff); // Add terminator.
|
2022-12-11 21:37:02 +11:00
|
|
|
}
|
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
pub fn remove_init_value(&mut self, index: u8) -> bool {
|
|
|
|
let mut start = 0;
|
2022-05-16 19:36:14 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
for (pos, &(idx, len)) in self.init_entries.iter().enumerate() {
|
|
|
|
if idx == index {
|
|
|
|
let end = start + len as usize;
|
2022-06-30 04:09:00 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
self.init_data.drain(start..end);
|
|
|
|
self.init_entries.remove(pos);
|
2022-05-16 19:36:14 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
return true;
|
|
|
|
}
|
2022-05-16 19:36:14 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
start += len as usize;
|
2022-06-30 04:09:00 +10:00
|
|
|
}
|
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
false
|
2022-05-16 19:36:14 +10:00
|
|
|
}
|
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
pub fn append_update_value(&mut self, index: u8, type_id: u8, value: impl Encode) {
|
|
|
|
debug_assert!(
|
|
|
|
index != 0xff,
|
|
|
|
"index of 0xff is reserved for the terminator"
|
|
|
|
);
|
|
|
|
|
|
|
|
self.update_data.pop(); // Remove terminator.
|
|
|
|
|
|
|
|
self.update_data.extend_from_slice(&[index, type_id]);
|
|
|
|
if let Err(e) = value.encode(&mut self.update_data) {
|
|
|
|
warn!("failed to encode updated tracked data: {e:#}");
|
2022-06-30 04:09:00 +10:00
|
|
|
}
|
2023-03-22 17:29:38 +11:00
|
|
|
|
|
|
|
self.update_data.push(0xff); // Add terminator.
|
2022-06-30 04:09:00 +10:00
|
|
|
}
|
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
pub fn clear_update_values(&mut self) {
|
|
|
|
self.update_data.clear();
|
2022-05-16 19:36:14 +10:00
|
|
|
}
|
2023-03-22 17:29:38 +11:00
|
|
|
}
|
2022-05-16 19:36:14 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encode, Decode)]
|
|
|
|
pub struct VillagerData {
|
|
|
|
pub kind: VillagerKind,
|
|
|
|
pub profession: VillagerProfession,
|
|
|
|
pub level: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl VillagerData {
|
|
|
|
pub const fn new(kind: VillagerKind, profession: VillagerProfession, level: i32) -> Self {
|
|
|
|
Self {
|
|
|
|
kind,
|
|
|
|
profession,
|
|
|
|
level,
|
2022-06-30 04:09:00 +10:00
|
|
|
}
|
|
|
|
}
|
2023-03-22 17:29:38 +11:00
|
|
|
}
|
2022-06-30 04:09:00 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
impl Default for VillagerData {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
kind: Default::default(),
|
|
|
|
profession: Default::default(),
|
|
|
|
level: 1,
|
|
|
|
}
|
2022-05-16 19:36:14 +10:00
|
|
|
}
|
2023-03-22 17:29:38 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encode, Decode)]
|
|
|
|
pub enum VillagerKind {
|
|
|
|
Desert,
|
|
|
|
Jungle,
|
|
|
|
#[default]
|
|
|
|
Plains,
|
|
|
|
Savanna,
|
|
|
|
Snow,
|
|
|
|
Swamp,
|
|
|
|
Taiga,
|
|
|
|
}
|
2022-05-16 19:36:14 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encode, Decode)]
|
|
|
|
pub enum VillagerProfession {
|
|
|
|
#[default]
|
|
|
|
None,
|
|
|
|
Armorer,
|
|
|
|
Butcher,
|
|
|
|
Cartographer,
|
|
|
|
Cleric,
|
|
|
|
Farmer,
|
|
|
|
Fisherman,
|
|
|
|
Fletcher,
|
|
|
|
Leatherworker,
|
|
|
|
Librarian,
|
|
|
|
Mason,
|
|
|
|
Nitwit,
|
|
|
|
Shepherd,
|
|
|
|
Toolsmith,
|
|
|
|
Weaponsmith,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encode, Decode)]
|
|
|
|
pub enum Pose {
|
|
|
|
#[default]
|
|
|
|
Standing,
|
|
|
|
FallFlying,
|
|
|
|
Sleeping,
|
|
|
|
Swimming,
|
|
|
|
SpinAttack,
|
|
|
|
Sneaking,
|
|
|
|
LongJumping,
|
|
|
|
Dying,
|
|
|
|
Croaking,
|
|
|
|
UsingTongue,
|
|
|
|
Roaring,
|
|
|
|
Sniffing,
|
|
|
|
Emerging,
|
|
|
|
Digging,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encode, Decode)]
|
|
|
|
pub enum BoatKind {
|
|
|
|
#[default]
|
|
|
|
Oak,
|
|
|
|
Spruce,
|
|
|
|
Birch,
|
|
|
|
Jungle,
|
|
|
|
Acacia,
|
|
|
|
DarkOak,
|
|
|
|
}
|
2022-06-30 04:09:00 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encode, Decode)]
|
|
|
|
pub enum CatKind {
|
|
|
|
Tabby,
|
|
|
|
#[default]
|
|
|
|
Black,
|
|
|
|
Red,
|
|
|
|
Siamese,
|
|
|
|
BritishShorthair,
|
|
|
|
Calico,
|
|
|
|
Persian,
|
|
|
|
Ragdoll,
|
|
|
|
White,
|
|
|
|
Jellie,
|
|
|
|
AllBlack,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encode, Decode)]
|
|
|
|
pub enum FrogKind {
|
|
|
|
#[default]
|
|
|
|
Temperate,
|
|
|
|
Warm,
|
|
|
|
Cold,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encode, Decode)]
|
|
|
|
pub enum PaintingKind {
|
|
|
|
#[default]
|
|
|
|
Kebab,
|
|
|
|
Aztec,
|
|
|
|
Alban,
|
|
|
|
Aztec2,
|
|
|
|
Bomb,
|
|
|
|
Plant,
|
|
|
|
Wasteland,
|
|
|
|
Pool,
|
|
|
|
Courbet,
|
|
|
|
Sea,
|
|
|
|
Sunset,
|
|
|
|
Creebet,
|
|
|
|
Wanderer,
|
|
|
|
Graham,
|
|
|
|
Match,
|
|
|
|
Bust,
|
|
|
|
Stage,
|
|
|
|
Void,
|
|
|
|
SkullAndRoses,
|
|
|
|
Wither,
|
|
|
|
Fighters,
|
|
|
|
Pointer,
|
|
|
|
Pigscene,
|
|
|
|
BurningSkull,
|
|
|
|
Skeleton,
|
|
|
|
Earth,
|
|
|
|
Wind,
|
|
|
|
Water,
|
|
|
|
Fire,
|
|
|
|
DonkeyKong,
|
|
|
|
}
|
|
|
|
|
2023-04-01 08:58:47 +11:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encode, Decode)]
|
|
|
|
pub enum SnifferState {
|
|
|
|
#[default]
|
|
|
|
Idling,
|
|
|
|
FeelingHappy,
|
|
|
|
Scenting,
|
|
|
|
Sniffing,
|
|
|
|
Searching,
|
|
|
|
Digging,
|
|
|
|
Rising,
|
|
|
|
}
|
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug, Encode, Decode)]
|
|
|
|
pub struct EulerAngle {
|
|
|
|
pub pitch: f32,
|
|
|
|
pub yaw: f32,
|
|
|
|
pub roll: f32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
struct OptionalInt(Option<i32>);
|
|
|
|
|
|
|
|
impl Encode for OptionalInt {
|
|
|
|
fn encode(&self, w: impl std::io::Write) -> anyhow::Result<()> {
|
|
|
|
if let Some(n) = self.0 {
|
|
|
|
VarInt(n.wrapping_add(1))
|
|
|
|
} else {
|
|
|
|
VarInt(0)
|
2022-06-30 04:09:00 +10:00
|
|
|
}
|
2023-03-22 17:29:38 +11:00
|
|
|
.encode(w)
|
2022-06-30 04:09:00 +10:00
|
|
|
}
|
2023-03-22 17:29:38 +11:00
|
|
|
}
|
2022-06-30 04:09:00 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
impl Decode<'_> for OptionalInt {
|
|
|
|
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
|
|
|
let n = VarInt::decode(r)?.0;
|
2022-05-17 19:58:43 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
Ok(Self(if n == 0 {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(n.wrapping_sub(1))
|
|
|
|
}))
|
2022-06-30 04:09:00 +10:00
|
|
|
}
|
2023-03-22 17:29:38 +11:00
|
|
|
}
|
2022-06-30 04:09:00 +10:00
|
|
|
|
2023-04-01 08:58:47 +11:00
|
|
|
/// A [`Resource`] which maintains information about all spawned Minecraft
|
|
|
|
/// entities.
|
2023-03-22 17:29:38 +11:00
|
|
|
#[derive(Resource, Debug)]
|
|
|
|
pub struct EntityManager {
|
|
|
|
/// Maps protocol IDs to ECS entities.
|
|
|
|
id_to_entity: FxHashMap<i32, Entity>,
|
|
|
|
uuid_to_entity: FxHashMap<Uuid, Entity>,
|
|
|
|
next_id: Wrapping<i32>,
|
|
|
|
}
|
2023-02-12 04:51:53 +11:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
impl EntityManager {
|
|
|
|
fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
id_to_entity: FxHashMap::default(),
|
|
|
|
uuid_to_entity: FxHashMap::default(),
|
|
|
|
next_id: Wrapping(1), // Skip 0.
|
|
|
|
}
|
2022-07-04 17:48:21 +10:00
|
|
|
}
|
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
/// Returns the next unique entity ID and increments the counter.
|
|
|
|
pub fn next_id(&mut self) -> EntityId {
|
|
|
|
if self.next_id.0 == 0 {
|
|
|
|
warn!("entity ID overflow!");
|
|
|
|
// ID 0 is reserved for clients, so skip over it.
|
|
|
|
self.next_id.0 = 1;
|
2022-09-18 16:14:48 +10:00
|
|
|
}
|
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
let id = EntityId(self.next_id.0);
|
2022-09-18 16:14:48 +10:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
self.next_id += 1;
|
|
|
|
|
|
|
|
id
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the entity with the given entity ID.
|
2023-04-09 05:55:31 +10:00
|
|
|
pub fn get_by_id(&self, entity_id: i32) -> Option<Entity> {
|
2023-03-22 17:29:38 +11:00
|
|
|
self.id_to_entity.get(&entity_id).cloned()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the entity with the given UUID.
|
2023-04-09 05:55:31 +10:00
|
|
|
pub fn get_by_uuid(&self, uuid: Uuid) -> Option<Entity> {
|
2023-03-22 17:29:38 +11:00
|
|
|
self.uuid_to_entity.get(&uuid).cloned()
|
|
|
|
}
|
|
|
|
}
|
2022-11-01 21:11:51 +11:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
// TODO: should `set_if_neq` behavior be the default behavior for setters?
|
|
|
|
macro_rules! flags {
|
|
|
|
(
|
|
|
|
$(
|
|
|
|
$component:path {
|
|
|
|
$($flag:ident: $offset:literal),* $(,)?
|
2022-11-01 21:11:51 +11:00
|
|
|
}
|
2023-03-22 17:29:38 +11:00
|
|
|
)*
|
|
|
|
|
|
|
|
) => {
|
|
|
|
$(
|
|
|
|
impl $component {
|
|
|
|
$(
|
|
|
|
#[doc = "Gets the bit at offset "]
|
|
|
|
#[doc = stringify!($offset)]
|
|
|
|
#[doc = "."]
|
|
|
|
#[inline]
|
|
|
|
pub const fn $flag(&self) -> bool {
|
|
|
|
(self.0 >> $offset) & 1 == 1
|
|
|
|
}
|
|
|
|
|
|
|
|
paste! {
|
|
|
|
#[doc = "Sets the bit at offset "]
|
|
|
|
#[doc = stringify!($offset)]
|
|
|
|
#[doc = "."]
|
|
|
|
#[inline]
|
|
|
|
pub fn [< set_$flag >] (&mut self, $flag: bool) {
|
2023-04-01 08:58:47 +11:00
|
|
|
self.0 = (self.0 & !(1 << $offset)) | (($flag as i8) << $offset);
|
2023-03-22 17:29:38 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
)*
|
2022-09-18 16:14:48 +10:00
|
|
|
}
|
2023-03-22 17:29:38 +11:00
|
|
|
)*
|
|
|
|
}
|
|
|
|
}
|
2022-11-01 21:11:51 +11:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
flags! {
|
|
|
|
entity::Flags {
|
|
|
|
on_fire: 0,
|
|
|
|
sneaking: 1,
|
|
|
|
sprinting: 3,
|
|
|
|
swimming: 4,
|
|
|
|
invisible: 5,
|
|
|
|
glowing: 6,
|
|
|
|
fall_flying: 7,
|
|
|
|
}
|
|
|
|
persistent_projectile::ProjectileFlags {
|
|
|
|
critical: 0,
|
|
|
|
no_clip: 1,
|
|
|
|
}
|
|
|
|
living::LivingFlags {
|
|
|
|
using_item: 0,
|
|
|
|
off_hand_active: 1,
|
|
|
|
using_riptide: 2,
|
|
|
|
}
|
|
|
|
player::PlayerModelParts {
|
|
|
|
cape: 0,
|
|
|
|
jacket: 1,
|
|
|
|
left_sleeve: 2,
|
|
|
|
right_sleeve: 3,
|
|
|
|
left_pants_leg: 4,
|
|
|
|
right_pants_leg: 5,
|
|
|
|
hat: 6,
|
|
|
|
}
|
|
|
|
player::MainArm {
|
|
|
|
right: 0,
|
|
|
|
}
|
|
|
|
armor_stand::ArmorStandFlags {
|
|
|
|
small: 0,
|
|
|
|
show_arms: 1,
|
|
|
|
hide_base_plate: 2,
|
|
|
|
marker: 3,
|
|
|
|
}
|
|
|
|
mob::MobFlags {
|
|
|
|
ai_disabled: 0,
|
|
|
|
left_handed: 1,
|
|
|
|
attacking: 2,
|
|
|
|
}
|
|
|
|
bat::BatFlags {
|
|
|
|
hanging: 0,
|
|
|
|
}
|
|
|
|
abstract_horse::HorseFlags {
|
|
|
|
tamed: 1,
|
|
|
|
saddled: 2,
|
|
|
|
bred: 3,
|
|
|
|
eating_grass: 4,
|
|
|
|
angry: 5,
|
|
|
|
eating: 6,
|
|
|
|
}
|
|
|
|
fox::FoxFlags {
|
|
|
|
sitting: 0,
|
|
|
|
crouching: 2,
|
|
|
|
rolling_head: 3,
|
|
|
|
chasing: 4,
|
|
|
|
sleeping: 5,
|
|
|
|
walking: 6,
|
|
|
|
aggressive: 7,
|
|
|
|
}
|
|
|
|
panda::PandaFlags {
|
|
|
|
sneezing: 1,
|
|
|
|
playing: 2,
|
|
|
|
sitting: 3,
|
|
|
|
lying_on_back: 4,
|
|
|
|
}
|
|
|
|
tameable::TameableFlags {
|
|
|
|
sitting_pose: 0,
|
|
|
|
tamed: 2,
|
|
|
|
}
|
|
|
|
iron_golem::IronGolemFlags {
|
|
|
|
player_created: 0,
|
|
|
|
}
|
|
|
|
snow_golem::SnowGolemFlags {
|
|
|
|
has_pumpkin: 4,
|
|
|
|
}
|
|
|
|
blaze::BlazeFlags {
|
|
|
|
fire_active: 0,
|
|
|
|
}
|
|
|
|
vex::VexFlags {
|
|
|
|
charging: 0,
|
|
|
|
}
|
|
|
|
spider::SpiderFlags {
|
|
|
|
climbing_wall: 0,
|
2022-12-11 21:37:02 +11:00
|
|
|
}
|
2023-03-22 17:29:38 +11:00
|
|
|
}
|
2022-12-11 21:37:02 +11:00
|
|
|
|
2023-03-22 17:29:38 +11:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn insert_remove_init_tracked_data() {
|
|
|
|
let mut td = TrackedData::default();
|
|
|
|
|
|
|
|
td.insert_init_value(0, 3, "foo");
|
|
|
|
td.insert_init_value(10, 6, "bar");
|
|
|
|
td.insert_init_value(5, 9, "baz");
|
|
|
|
|
|
|
|
assert!(td.remove_init_value(10));
|
|
|
|
assert!(!td.remove_init_value(10));
|
|
|
|
|
|
|
|
// Insertion overwrites value at index 0.
|
|
|
|
td.insert_init_value(0, 64, "quux");
|
|
|
|
|
|
|
|
assert!(td.remove_init_value(0));
|
|
|
|
assert!(td.remove_init_value(5));
|
|
|
|
|
|
|
|
assert!(td.init_data.as_slice().is_empty() || td.init_data.as_slice() == [0xff]);
|
|
|
|
assert!(td.init_data().is_none());
|
|
|
|
|
|
|
|
assert!(td.update_data.is_empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn get_set_flags() {
|
|
|
|
let mut flags = entity::Flags(0);
|
|
|
|
|
|
|
|
flags.set_on_fire(true);
|
|
|
|
let before = flags.clone();
|
|
|
|
assert_ne!(flags.0, 0);
|
|
|
|
flags.set_on_fire(true);
|
|
|
|
assert_eq!(before, flags);
|
|
|
|
flags.set_on_fire(false);
|
|
|
|
assert_eq!(flags.0, 0);
|
2022-09-10 10:45:38 +10:00
|
|
|
}
|
2022-09-10 14:59:10 +10:00
|
|
|
}
|