1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 14:26:04 +00:00

some ecs stuff in az-client

This commit is contained in:
mat 2022-12-24 20:13:53 -06:00
parent 13fc403484
commit 8a93a2c158
7 changed files with 113 additions and 63 deletions

1
Cargo.lock generated
View file

@ -276,6 +276,7 @@ dependencies = [
"azalea-crypto",
"azalea-physics",
"azalea-protocol",
"azalea-registry",
"azalea-world",
"log",
"nohash-hasher",

View file

@ -11,14 +11,15 @@ version = "0.5.0"
[dependencies]
anyhow = "1.0.59"
async-trait = "0.1.58"
azalea-auth = {path = "../azalea-auth", version = "0.5.0" }
azalea-block = {path = "../azalea-block", version = "0.5.0" }
azalea-chat = {path = "../azalea-chat", version = "0.5.0" }
azalea-core = {path = "../azalea-core", version = "0.5.0" }
azalea-crypto = {path = "../azalea-crypto", version = "0.5.0" }
azalea-physics = {path = "../azalea-physics", version = "0.5.0" }
azalea-protocol = {path = "../azalea-protocol", version = "0.5.0" }
azalea-world = {path = "../azalea-world", version = "0.5.0" }
azalea-auth = {path = "../azalea-auth", version = "0.5.0"}
azalea-block = {path = "../azalea-block", version = "0.5.0"}
azalea-chat = {path = "../azalea-chat", version = "0.5.0"}
azalea-core = {path = "../azalea-core", version = "0.5.0"}
azalea-crypto = {path = "../azalea-crypto", version = "0.5.0"}
azalea-physics = {path = "../azalea-physics", version = "0.5.0"}
azalea-protocol = {path = "../azalea-protocol", version = "0.5.0"}
azalea-registry = {path = "../azalea-registry", version = "0.5.0"}
azalea-world = {path = "../azalea-world", version = "0.5.0"}
log = "0.4.17"
nohash-hasher = "0.2.0"
once_cell = "1.16.0"

View file

@ -29,7 +29,11 @@ use azalea_protocol::{
resolver, ServerAddress,
};
use azalea_world::{
entity::{metadata, Entity, EntityData, EntityMetadata},
entity::{
self,
metadata::{self, PlayerMetadataBundle},
EntityId,
},
PartialWorld, WeakWorld, WeakWorldContainer,
};
use log::{debug, error, info, trace, warn};
@ -40,6 +44,7 @@ use std::{
collections::HashMap,
fmt::Debug,
io::{self, Cursor},
ops::DerefMut,
sync::Arc,
};
use thiserror::Error;
@ -90,7 +95,7 @@ pub struct Client {
pub profile: GameProfile,
pub read_conn: Arc<tokio::sync::Mutex<ReadConnection<ClientboundGamePacket>>>,
pub write_conn: Arc<tokio::sync::Mutex<WriteConnection<ServerboundGamePacket>>>,
pub entity_id: Arc<RwLock<u32>>,
pub entity_id: Arc<RwLock<EntityId>>,
/// The world that this client has access to. This supports shared worlds.
pub world: Arc<RwLock<PartialWorld>>,
/// A container of world names to worlds. If we're not using a shared world
@ -179,7 +184,7 @@ impl Client {
read_conn,
write_conn,
// default our id to 0, it'll be set later
entity_id: Arc::new(RwLock::new(0)),
entity_id: Arc::new(RwLock::new(EntityId(0))),
world: Arc::new(RwLock::new(PartialWorld::default())),
world_container: world_container
.unwrap_or_else(|| Arc::new(RwLock::new(WeakWorldContainer::new()))),
@ -523,18 +528,27 @@ impl Client {
*world_lock = PartialWorld::new(
client.client_information.read().view_distance.into(),
weak_world,
Some(p.player_id),
Some(EntityId(p.player_id)),
);
let entity = EntityData::new(
client.profile.uuid,
Vec3::default(),
EntityMetadata::Player(metadata::Player::default()),
);
// make it so other entities don't update this entity in a shared world
world_lock.add_entity(p.player_id, entity);
let player_bundle = entity::PlayerBundle {
entity: entity::EntityBundle::new(
client.profile.uuid,
Vec3::default(),
azalea_registry::EntityKind::Player,
),
metadata: PlayerMetadataBundle::default(),
};
// let entity = EntityData::new(
// client.profile.uuid,
// Vec3::default(),
// EntityMetadata::Player(metadata::Player::default()),
// );
// the first argument makes it so other entities don't update this entity in a
// shared world
world_lock.add_entity(EntityId(p.player_id), player_bundle);
*client.entity_id.write() = p.player_id;
*client.entity_id.write() = EntityId(p.player_id);
}
// send the client information that we have set
@ -600,54 +614,59 @@ impl Client {
let (new_pos, y_rot, x_rot) = {
let player_entity_id = *client.entity_id.read();
let mut world_lock = client.world();
// let mut player_entity = world_lock.entity_mut(player_entity_id).unwrap();
let (physics, position) =
world_lock
.entity_storage
.read()
.query_entity_mut::<(&mut entity::Physics, &entity::Position)>(
player_entity_id,
);
let mut world_lock = client.world.write();
let mut player_entity = world_lock.entity_mut(player_entity_id).unwrap();
let delta_movement = player_entity.delta;
let delta_movement = physics.delta;
let is_x_relative = p.relative_arguments.x;
let is_y_relative = p.relative_arguments.y;
let is_z_relative = p.relative_arguments.z;
let (delta_x, new_pos_x) = if is_x_relative {
player_entity.last_pos.x += p.x;
(delta_movement.x, player_entity.pos().x + p.x)
physics.last_pos.x += p.x;
(delta_movement.x, position.x + p.x)
} else {
player_entity.last_pos.x = p.x;
physics.last_pos.x = p.x;
(0.0, p.x)
};
let (delta_y, new_pos_y) = if is_y_relative {
player_entity.last_pos.y += p.y;
(delta_movement.y, player_entity.pos().y + p.y)
physics.last_pos.y += p.y;
(delta_movement.y, position.y + p.y)
} else {
player_entity.last_pos.y = p.y;
physics.last_pos.y = p.y;
(0.0, p.y)
};
let (delta_z, new_pos_z) = if is_z_relative {
player_entity.last_pos.z += p.z;
(delta_movement.z, player_entity.pos().z + p.z)
physics.last_pos.z += p.z;
(delta_movement.z, position.z + p.z)
} else {
player_entity.last_pos.z = p.z;
physics.last_pos.z = p.z;
(0.0, p.z)
};
let mut y_rot = p.y_rot;
let mut x_rot = p.x_rot;
if p.relative_arguments.x_rot {
x_rot += player_entity.x_rot;
x_rot += physics.x_rot;
}
if p.relative_arguments.y_rot {
y_rot += player_entity.y_rot;
y_rot += physics.y_rot;
}
player_entity.delta = Vec3 {
physics.delta = Vec3 {
x: delta_x,
y: delta_y,
z: delta_z,
};
player_entity.set_rotation(y_rot, x_rot);
entity::set_rotation(physics.deref_mut(), y_rot, x_rot);
// TODO: minecraft sets "xo", "yo", and "zo" here but idk what that means
// so investigate that ig
let new_pos = Vec3 {
@ -783,8 +802,12 @@ impl Client {
}
ClientboundGamePacket::AddEntity(p) => {
debug!("Got add entity packet {:?}", p);
let entity = EntityData::from(p);
client.world.write().add_entity(p.id, entity);
// let entity = EntityData::from(p);
let bundle = p.as_entity_bundle();
let world = client.world();
world.add_entity(p.id, bundle);
let entity = world.entity_storage.write().ecs_entity(p.id);
p.apply_metadata(entity);
}
ClientboundGamePacket::SetEntityData(p) => {
debug!("Got set entity data packet {:?}", p);
@ -1049,19 +1072,19 @@ impl Client {
self.world.read().shared.clone()
}
/// Returns the entity associated to the player.
pub fn entity(&self) -> Entity<Arc<WeakWorld>> {
let entity_id = *self.entity_id.read();
// /// Returns the entity associated to the player.
// pub fn entity(&self) -> Entity<Arc<WeakWorld>> {
// let entity_id = *self.entity_id.read();
let world = self.world();
let entity_data = world
.entity_storage
.read()
.get_by_id(entity_id)
.expect("Player entity should be in the given world");
let entity_ptr = unsafe { entity_data.as_ptr() };
Entity::new(world, entity_id, entity_ptr)
}
// let world = self.world();
// let entity_data = world
// .entity_storage
// .read()
// .get_by_id(entity_id)
// .expect("Player entity should be in the given world");
// let entity_ptr = unsafe { entity_data.as_ptr() };
// Entity::new(world, entity_id, entity_ptr)
// }
/// Returns whether we have a received the login packet yet.
pub fn logged_in(&self) -> bool {

View file

@ -41,12 +41,11 @@ pub struct ClientboundAddEntityPacket {
// }
impl ClientboundAddEntityPacket {
fn as_bundle(&self) -> EntityBundle {
pub fn as_entity_bundle(&self) -> EntityBundle {
EntityBundle::new(self.uuid, self.position, self.entity_type)
}
pub fn apply_to_entity(&self, entity: &mut bevy_ecs::world::EntityMut) {
pub fn apply_metadata(&self, entity: &mut bevy_ecs::world::EntityMut) {
apply_default_metadata(entity, self.entity_type);
entity.insert(self.as_bundle());
}
}

View file

@ -254,6 +254,9 @@ pub struct Physics {
}
/// A component NewType for [`azalea_registry::EntityKind`].
///
/// Most of the time, you should be using `azalea_registry::EntityKind`
/// instead.
#[derive(Component, Clone, Copy, Debug, PartialEq, Deref)]
pub struct EntityKind(azalea_registry::EntityKind);

View file

@ -133,7 +133,7 @@ impl PartialEntityStorage {
if self.loaded_entity_ids.remove(&id) {
let mut shared = self.shared.write();
let mut query = shared.query::<(&Position, &EntityUuid)>();
let mut query = shared.query_to_state::<(&Position, &EntityUuid)>();
let (pos, uuid) = query.get(&mut shared.ecs, id.into()).expect(
"If the entity was being loaded by this storage, it must be in the shared
storage.",
@ -210,7 +210,7 @@ impl PartialEntityStorage {
/// shared storage, unless there are no other references to them.
pub fn clear_chunk(&mut self, chunk: &ChunkPos) {
let mut shared = self.shared.write();
let mut query = shared.query::<&EntityUuid>();
let mut query = shared.query_to_state::<&EntityUuid>();
if let Some(entities) = shared.ids_by_chunk.get(chunk).cloned() {
for &id in entities.iter() {
@ -296,7 +296,9 @@ impl WeakEntityStorage {
}
}
pub fn query<Q: WorldQuery>(&mut self) -> QueryState<Q, ()> {
/// Query the ecs to get a [`QueryState`]. You should probably use
/// [`Self::query_entity`] or [`Self::query_entity_mut`] instead.
pub fn query_to_state<Q: WorldQuery>(&mut self) -> QueryState<Q, ()> {
self.ecs.query::<Q>()
}
@ -333,6 +335,29 @@ impl WeakEntityStorage {
.or_default()
.insert(entity_id);
}
/// This can only be called for read-only queries, see
/// [`Self::query_entity_mut`] for write-queries.
pub fn query_entity<'w, Q: WorldQuery>(
&'w mut self,
entity_id: EntityId,
) -> bevy_ecs::query::ROQueryItem<'w, Q> {
let mut query = self.query_to_state::<Q>();
query.get(&self.ecs, entity_id.into()).unwrap()
}
pub fn query_entity_mut<'w, Q: WorldQuery>(&'w mut self, entity_id: EntityId) -> Q::Item<'w> {
let mut query = self.query_to_state::<Q>();
query.get_mut(&mut self.ecs, entity_id.into()).unwrap()
}
/// Returns an [`EntityMut`] for the given entity ID.
///
/// You only need this if you're going to be adding new components to the
/// entity. Otherwise, use [`Self::query_entity_mut`].
pub fn ecs_entity_mut(&mut self, entity_id: EntityId) -> EntityMut {
self.ecs.get_entity_mut(entity_id.into()).unwrap()
}
}
impl Debug for WeakEntityStorage {

View file

@ -165,7 +165,7 @@ impl WeakWorld {
}
pub fn query_entities<Q: WorldQuery>(&self) -> QueryState<Q, ()> {
self.entity_storage.write().query::<Q>()
self.entity_storage.write().query_to_state::<Q>()
}
/// Set an entity's position in the world.
@ -179,10 +179,8 @@ impl WeakWorld {
new_pos: Vec3,
) -> Result<(), MoveEntityError> {
let mut entity_storage = self.entity_storage.write();
let mut query = entity_storage.query::<(&mut Position, &mut Physics)>();
let (pos, physics) = query
.get_mut(&mut entity_storage.ecs, entity_id.into())
.unwrap();
let (pos, physics) =
entity_storage.query_entity_mut::<(&mut Position, &mut Physics)>(entity_id);
self.set_entity_pos_from_refs(entity_id, new_pos, pos.into_inner(), physics.into_inner())
}