Prevented pet damage

This commit is contained in:
Joshua Barretto 2020-07-07 01:01:39 +01:00
parent f77d2f06c6
commit e626f6255f
14 changed files with 111 additions and 50 deletions

View File

@ -1,9 +1,9 @@
use crate::path::Chaser; use crate::{path::Chaser, sync::Uid};
use specs::{Component, Entity as EcsEntity}; use specs::{Component, Entity as EcsEntity, FlaggedStorage};
use specs_idvs::IdvStorage; use specs_idvs::IdvStorage;
use vek::*; use vek::*;
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Alignment { pub enum Alignment {
/// Wild animals and gentle giants /// Wild animals and gentle giants
Wild, Wild,
@ -14,7 +14,7 @@ pub enum Alignment {
/// Farm animals and pets of villagers /// Farm animals and pets of villagers
Tame, Tame,
/// Pets you've tamed with a collar /// Pets you've tamed with a collar
Owned(EcsEntity), Owned(Uid),
} }
impl Alignment { impl Alignment {
@ -51,7 +51,7 @@ impl Alignment {
} }
impl Component for Alignment { impl Component for Alignment {
type Storage = IdvStorage<Self>; type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
} }
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]

View File

@ -7,7 +7,8 @@
bool_to_option, bool_to_option,
label_break_value, label_break_value,
trait_alias, trait_alias,
type_alias_impl_trait type_alias_impl_trait,
option_zip,
)] )]
#[macro_use] extern crate serde_derive; #[macro_use] extern crate serde_derive;

View File

@ -17,6 +17,7 @@ sum_type! {
LightEmitter(comp::LightEmitter), LightEmitter(comp::LightEmitter),
Item(comp::Item), Item(comp::Item),
Scale(comp::Scale), Scale(comp::Scale),
Alignment(comp::Alignment),
MountState(comp::MountState), MountState(comp::MountState),
Mounting(comp::Mounting), Mounting(comp::Mounting),
Mass(comp::Mass), Mass(comp::Mass),
@ -43,6 +44,7 @@ sum_type! {
LightEmitter(PhantomData<comp::LightEmitter>), LightEmitter(PhantomData<comp::LightEmitter>),
Item(PhantomData<comp::Item>), Item(PhantomData<comp::Item>),
Scale(PhantomData<comp::Scale>), Scale(PhantomData<comp::Scale>),
Alignment(PhantomData<comp::Alignment>),
MountState(PhantomData<comp::MountState>), MountState(PhantomData<comp::MountState>),
Mounting(PhantomData<comp::Mounting>), Mounting(PhantomData<comp::Mounting>),
Mass(PhantomData<comp::Mass>), Mass(PhantomData<comp::Mass>),
@ -69,6 +71,7 @@ impl sync::CompPacket for EcsCompPacket {
EcsCompPacket::LightEmitter(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::LightEmitter(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Item(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Item(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Scale(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Scale(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Alignment(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::MountState(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::MountState(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Mounting(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Mounting(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Mass(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Mass(comp) => sync::handle_insert(comp, entity, world),
@ -93,6 +96,7 @@ impl sync::CompPacket for EcsCompPacket {
EcsCompPacket::LightEmitter(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::LightEmitter(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Item(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Item(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Scale(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Scale(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Alignment(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::MountState(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::MountState(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Mounting(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Mounting(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Mass(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Mass(comp) => sync::handle_modify(comp, entity, world),
@ -119,6 +123,7 @@ impl sync::CompPacket for EcsCompPacket {
}, },
EcsCompPhantom::Item(_) => sync::handle_remove::<comp::Item>(entity, world), EcsCompPhantom::Item(_) => sync::handle_remove::<comp::Item>(entity, world),
EcsCompPhantom::Scale(_) => sync::handle_remove::<comp::Scale>(entity, world), EcsCompPhantom::Scale(_) => sync::handle_remove::<comp::Scale>(entity, world),
EcsCompPhantom::Alignment(_) => sync::handle_remove::<comp::Alignment>(entity, world),
EcsCompPhantom::MountState(_) => sync::handle_remove::<comp::MountState>(entity, world), EcsCompPhantom::MountState(_) => sync::handle_remove::<comp::MountState>(entity, world),
EcsCompPhantom::Mounting(_) => sync::handle_remove::<comp::Mounting>(entity, world), EcsCompPhantom::Mounting(_) => sync::handle_remove::<comp::Mounting>(entity, world),
EcsCompPhantom::Mass(_) => sync::handle_remove::<comp::Mass>(entity, world), EcsCompPhantom::Mass(_) => sync::handle_remove::<comp::Mass>(entity, world),

View File

@ -123,6 +123,7 @@ impl State {
ecs.register::<comp::Gravity>(); ecs.register::<comp::Gravity>();
ecs.register::<comp::CharacterState>(); ecs.register::<comp::CharacterState>();
ecs.register::<comp::Object>(); ecs.register::<comp::Object>();
ecs.register::<comp::Alignment>();
// Register components send from clients -> server // Register components send from clients -> server
ecs.register::<comp::Controller>(); ecs.register::<comp::Controller>();
@ -146,7 +147,6 @@ impl State {
ecs.register::<comp::Last<comp::Vel>>(); ecs.register::<comp::Last<comp::Vel>>();
ecs.register::<comp::Last<comp::Ori>>(); ecs.register::<comp::Last<comp::Ori>>();
ecs.register::<comp::Agent>(); ecs.register::<comp::Agent>();
ecs.register::<comp::Alignment>();
ecs.register::<comp::WaypointArea>(); ecs.register::<comp::WaypointArea>();
ecs.register::<comp::ForceUpdate>(); ecs.register::<comp::ForceUpdate>();
ecs.register::<comp::InventoryUpdate>(); ecs.register::<comp::InventoryUpdate>();

View File

@ -31,11 +31,13 @@ impl CharacterBehavior for Data {
handle_move(data, &mut update, 0.3); handle_move(data, &mut update, 0.3);
handle_jump(data, &mut update); handle_jump(data, &mut update);
if !self.exhausted && if self.holdable { if !self.exhausted
data.inputs.holding_ability_key() || self.prepare_timer < self.prepare_duration && if self.holdable {
} else { data.inputs.holding_ability_key() || self.prepare_timer < self.prepare_duration
self.prepare_timer < self.prepare_duration } else {
} { self.prepare_timer < self.prepare_duration
}
{
// Prepare (draw the bow) // Prepare (draw the bow)
update.character = CharacterState::BasicRanged(Data { update.character = CharacterState::BasicRanged(Data {
prepare_timer: self.prepare_timer + Duration::from_secs_f32(data.dt.0), prepare_timer: self.prepare_timer + Duration::from_secs_f32(data.dt.0),

View File

@ -45,6 +45,24 @@ impl Body {
Body::QuadrupedLow(_) => 120.0, Body::QuadrupedLow(_) => 120.0,
} }
} }
pub fn base_ori_rate(&self) -> f32 {
match self {
Body::Humanoid(_) => 20.0,
Body::QuadrupedSmall(_) => 15.0,
Body::QuadrupedMedium(_) => 10.0,
Body::BirdMedium(_) => 30.0,
Body::FishMedium(_) => 5.0,
Body::Dragon(_) => 5.0,
Body::BirdSmall(_) => 35.0,
Body::FishSmall(_) => 10.0,
Body::BipedLarge(_) => 12.0,
Body::Object(_) => 5.0,
Body::Golem(_) => 8.0,
Body::Critter(_) => 35.0,
Body::QuadrupedLow(_) => 12.0,
}
}
} }
/// Handles updating `Components` to move player based on state of `JoinData` /// Handles updating `Components` to move player based on state of `JoinData`
@ -68,10 +86,10 @@ fn basic_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
update.vel.0 = update.vel.0 =
update.vel.0 + Vec2::broadcast(data.dt.0) * data.inputs.move_dir * accel * efficiency; update.vel.0 + Vec2::broadcast(data.dt.0) * data.inputs.move_dir * accel * efficiency;
handle_orientation(data, update, 20.0); handle_orientation(data, update, data.body.base_ori_rate());
} }
pub fn handle_orientation(data: &JoinData, update: &mut StateUpdate, strength: f32) { pub fn handle_orientation(data: &JoinData, update: &mut StateUpdate, rate: f32) {
// Set direction based on move direction // Set direction based on move direction
let ori_dir = if update.character.is_attack() || update.character.is_block() { let ori_dir = if update.character.is_attack() || update.character.is_block() {
data.inputs.look_dir.xy() data.inputs.look_dir.xy()
@ -82,7 +100,7 @@ pub fn handle_orientation(data: &JoinData, update: &mut StateUpdate, strength: f
}; };
// Smooth orientation // Smooth orientation
update.ori.0 = Dir::slerp_to_vec3(update.ori.0, ori_dir.into(), strength * data.dt.0); update.ori.0 = Dir::slerp_to_vec3(update.ori.0, ori_dir.into(), rate * data.dt.0);
} }
/// Updates components to move player as if theyre swimming /// Updates components to move player as if theyre swimming

View File

@ -245,7 +245,11 @@ impl<'a> System<'a> for Sys {
alignments alignments
.get(*target) .get(*target)
.copied() .copied()
.unwrap_or(Alignment::Owned(*target)), .unwrap_or(uids
.get(*target)
.copied()
.map(Alignment::Owned)
.unwrap_or(Alignment::Wild)),
) { ) {
if let Some(dir) = Dir::from_unnormalized(tgt_pos.0 - pos.0) { if let Some(dir) = Dir::from_unnormalized(tgt_pos.0 - pos.0) {
inputs.look_dir = dir; inputs.look_dir = dir;
@ -419,7 +423,10 @@ impl<'a> System<'a> for Sys {
// Follow owner if we're too far, or if they're under attack // Follow owner if we're too far, or if they're under attack
if let Some(Alignment::Owned(owner)) = alignment.copied() { if let Some(Alignment::Owned(owner)) = alignment.copied() {
if let Some(owner_pos) = positions.get(owner) { (|| {
let owner = uid_allocator.retrieve_entity_internal(owner.id())?;
let owner_pos = positions.get(owner)?;
let dist_sqrd = pos.0.distance_squared(owner_pos.0); let dist_sqrd = pos.0.distance_squared(owner_pos.0);
if dist_sqrd > MAX_FOLLOW_DIST.powf(2.0) && !agent.activity.is_follow() { if dist_sqrd > MAX_FOLLOW_DIST.powf(2.0) && !agent.activity.is_follow() {
agent.activity = Activity::Follow { agent.activity = Activity::Follow {
@ -429,28 +436,27 @@ impl<'a> System<'a> for Sys {
} }
// Attack owner's attacker // Attack owner's attacker
if let Some(owner_stats) = stats.get(owner) { let owner_stats = stats.get(owner)?;
if owner_stats.health.last_change.0 < 5.0 { if owner_stats.health.last_change.0 < 5.0 {
if let comp::HealthSource::Attack { by } = if let comp::HealthSource::Attack { by } =
owner_stats.health.last_change.1.cause owner_stats.health.last_change.1.cause
{ {
if !agent.activity.is_attack() { if !agent.activity.is_attack() {
if let Some(attacker) = let attacker = uid_allocator.retrieve_entity_internal(by.id())?;
uid_allocator.retrieve_entity_internal(by.id())
{ agent.activity = Activity::Attack {
agent.activity = Activity::Attack { target: attacker,
target: attacker, chaser: Chaser::default(),
chaser: Chaser::default(), time: time.0,
time: time.0, been_close: false,
been_close: false, powerup: 0.0,
powerup: 0.0, };
};
}
}
} }
} }
} }
}
Some(())
})();
} }
debug_assert!(inputs.move_dir.map(|e| !e.is_nan()).reduce_and()); debug_assert!(inputs.move_dir.map(|e| !e.is_nan()).reduce_and());

View File

@ -119,12 +119,15 @@ impl<'a> System<'a> for Sys {
// healthchange = (healthchange / 1.5).min(-1.0); // healthchange = (healthchange / 1.5).min(-1.0);
//} //}
// TODO: remove this when there is a better way to target healing // TODO: remove this when there is a better way to deal with alignment
// Don't heal npc's hp // Don't heal NPCs
if alignment_b_maybe if (healthchange > 0.0 && alignment_b_maybe
.map(|a| !a.is_friendly_to_players()) .map(|a| !a.is_friendly_to_players())
.unwrap_or(true) .unwrap_or(true))
&& healthchange > 0.0 // Don't hurt pets
|| (healthchange < 0.0 && alignment_b_maybe
.map(|b| Alignment::Owned(*uid).passive_towards(*b))
.unwrap_or(false))
{ {
healthchange = 0.0; healthchange = 0.0;
} }

View File

@ -1,6 +1,7 @@
use crate::{ use crate::{
comp::{ comp::{
projectile, Energy, EnergySource, HealthSource, Ori, PhysicsState, Pos, Projectile, Vel, projectile, Energy, EnergySource, HealthSource, Ori, PhysicsState, Pos, Projectile, Vel,
Alignment,
}, },
event::{EventBus, LocalEvent, ServerEvent}, event::{EventBus, LocalEvent, ServerEvent},
state::DeltaTime, state::DeltaTime,
@ -27,6 +28,7 @@ impl<'a> System<'a> for Sys {
WriteStorage<'a, Ori>, WriteStorage<'a, Ori>,
WriteStorage<'a, Projectile>, WriteStorage<'a, Projectile>,
WriteStorage<'a, Energy>, WriteStorage<'a, Energy>,
ReadStorage<'a, Alignment>,
); );
fn run( fn run(
@ -43,6 +45,7 @@ impl<'a> System<'a> for Sys {
mut orientations, mut orientations,
mut projectiles, mut projectiles,
mut energies, mut energies,
alignments,
): Self::SystemData, ): Self::SystemData,
) { ) {
let mut local_emitter = local_bus.emitter(); let mut local_emitter = local_bus.emitter();
@ -82,7 +85,17 @@ impl<'a> System<'a> for Sys {
for effect in projectile.hit_entity.drain(..) { for effect in projectile.hit_entity.drain(..) {
match effect { match effect {
projectile::Effect::Damage(change) => { projectile::Effect::Damage(change) => {
if other != projectile.owner.unwrap() { let owner_uid = projectile.owner.unwrap();
// Hacky: remove this when groups get implemented
let passive = uid_allocator
.retrieve_entity_internal(other.into())
.and_then(|other|
alignments
.get(other)
.map(|a| Alignment::Owned(owner_uid)
.passive_towards(*a)))
.unwrap_or(false);
if other != projectile.owner.unwrap() && !passive {
server_emitter.emit(ServerEvent::Damage { uid: other, change }); server_emitter.emit(ServerEvent::Damage { uid: other, change });
} }
}, },

View File

@ -507,7 +507,8 @@ fn handle_spawn(
String String
) { ) {
(Some(opt_align), Some(npc::NpcBody(id, mut body)), opt_amount, opt_ai) => { (Some(opt_align), Some(npc::NpcBody(id, mut body)), opt_amount, opt_ai) => {
if let Some(alignment) = parse_alignment(target, &opt_align) { let uid = server.state.read_component_cloned(target).expect("Expected player to have a UID");
if let Some(alignment) = parse_alignment(uid, &opt_align) {
let amount = opt_amount let amount = opt_amount
.and_then(|a| a.parse().ok()) .and_then(|a| a.parse().ok())
.filter(|x| *x > 0) .filter(|x| *x > 0)
@ -715,7 +716,7 @@ fn handle_help(
} }
} }
fn parse_alignment(owner: EcsEntity, alignment: &str) -> Option<comp::Alignment> { fn parse_alignment(owner: Uid, alignment: &str) -> Option<comp::Alignment> {
match alignment { match alignment {
"wild" => Some(comp::Alignment::Wild), "wild" => Some(comp::Alignment::Wild),
"enemy" => Some(comp::Alignment::Enemy), "enemy" => Some(comp::Alignment::Enemy),

View File

@ -188,13 +188,15 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
let reinsert = if let Some(pos) = let reinsert = if let Some(pos) =
state.read_storage::<comp::Pos>().get(entity) state.read_storage::<comp::Pos>().get(entity)
{ {
let uid = state.read_component_cloned(entity)
.expect("Expected player to have a UID");
if ( if (
&state.read_storage::<comp::Alignment>(), &state.read_storage::<comp::Alignment>(),
&state.read_storage::<comp::Agent>(), &state.read_storage::<comp::Agent>(),
) )
.join() .join()
.filter(|(alignment, _)| { .filter(|(alignment, _)| {
alignment == &&comp::Alignment::Owned(entity) alignment == &&comp::Alignment::Owned(uid)
}) })
.count() .count()
>= 3 >= 3
@ -222,7 +224,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
} { } {
let _ = state.ecs().write_storage().insert( let _ = state.ecs().write_storage().insert(
tameable_entity, tameable_entity,
comp::Alignment::Owned(entity), comp::Alignment::Owned(uid),
); );
let _ = state let _ = state
.ecs() .ecs()

View File

@ -171,7 +171,7 @@ impl StateExt for State {
}); });
self.write_component(entity, comp::Gravity(1.0)); self.write_component(entity, comp::Gravity(1.0));
self.write_component(entity, comp::CharacterState::default()); self.write_component(entity, comp::CharacterState::default());
self.write_component(entity, comp::Alignment::Owned(entity)); self.write_component(entity, comp::Alignment::Owned(self.read_component_cloned(entity).unwrap()));
// Set the character id for the player // Set the character id for the player
// TODO this results in a warning in the console: "Error modifying synced // TODO this results in a warning in the console: "Error modifying synced

View File

@ -2,7 +2,7 @@ use super::SysTimer;
use common::{ use common::{
comp::{ comp::{
Body, CanBuild, CharacterState, Collider, Energy, Gravity, Item, LightEmitter, Loadout, Body, CanBuild, CharacterState, Collider, Energy, Gravity, Item, LightEmitter, Loadout,
Mass, MountState, Mounting, Ori, Player, Pos, Scale, Stats, Sticky, Vel, Mass, MountState, Mounting, Ori, Player, Pos, Scale, Stats, Sticky, Vel, Alignment,
}, },
msg::EcsCompPacket, msg::EcsCompPacket,
sync::{CompSyncPackage, EntityPackage, EntitySyncPackage, Uid, UpdateTracker, WorldSyncExt}, sync::{CompSyncPackage, EntityPackage, EntitySyncPackage, Uid, UpdateTracker, WorldSyncExt},
@ -48,6 +48,7 @@ pub struct TrackedComps<'a> {
pub scale: ReadStorage<'a, Scale>, pub scale: ReadStorage<'a, Scale>,
pub mounting: ReadStorage<'a, Mounting>, pub mounting: ReadStorage<'a, Mounting>,
pub mount_state: ReadStorage<'a, MountState>, pub mount_state: ReadStorage<'a, MountState>,
pub alignment: ReadStorage<'a, Alignment>,
pub mass: ReadStorage<'a, Mass>, pub mass: ReadStorage<'a, Mass>,
pub collider: ReadStorage<'a, Collider>, pub collider: ReadStorage<'a, Collider>,
pub sticky: ReadStorage<'a, Sticky>, pub sticky: ReadStorage<'a, Sticky>,
@ -104,6 +105,10 @@ impl<'a> TrackedComps<'a> {
.get(entity) .get(entity)
.cloned() .cloned()
.map(|c| comps.push(c.into())); .map(|c| comps.push(c.into()));
self.alignment
.get(entity)
.cloned()
.map(|c| comps.push(c.into()));
self.mass.get(entity).copied().map(|c| comps.push(c.into())); self.mass.get(entity).copied().map(|c| comps.push(c.into()));
self.collider self.collider
.get(entity) .get(entity)
@ -146,6 +151,7 @@ pub struct ReadTrackers<'a> {
pub scale: ReadExpect<'a, UpdateTracker<Scale>>, pub scale: ReadExpect<'a, UpdateTracker<Scale>>,
pub mounting: ReadExpect<'a, UpdateTracker<Mounting>>, pub mounting: ReadExpect<'a, UpdateTracker<Mounting>>,
pub mount_state: ReadExpect<'a, UpdateTracker<MountState>>, pub mount_state: ReadExpect<'a, UpdateTracker<MountState>>,
pub alignment: ReadExpect<'a, UpdateTracker<Alignment>>,
pub mass: ReadExpect<'a, UpdateTracker<Mass>>, pub mass: ReadExpect<'a, UpdateTracker<Mass>>,
pub collider: ReadExpect<'a, UpdateTracker<Collider>>, pub collider: ReadExpect<'a, UpdateTracker<Collider>>,
pub sticky: ReadExpect<'a, UpdateTracker<Sticky>>, pub sticky: ReadExpect<'a, UpdateTracker<Sticky>>,
@ -178,6 +184,7 @@ impl<'a> ReadTrackers<'a> {
.with_component(&comps.uid, &*self.scale, &comps.scale, filter) .with_component(&comps.uid, &*self.scale, &comps.scale, filter)
.with_component(&comps.uid, &*self.mounting, &comps.mounting, filter) .with_component(&comps.uid, &*self.mounting, &comps.mounting, filter)
.with_component(&comps.uid, &*self.mount_state, &comps.mount_state, filter) .with_component(&comps.uid, &*self.mount_state, &comps.mount_state, filter)
.with_component(&comps.uid, &*self.alignment, &comps.alignment, filter)
.with_component(&comps.uid, &*self.mass, &comps.mass, filter) .with_component(&comps.uid, &*self.mass, &comps.mass, filter)
.with_component(&comps.uid, &*self.collider, &comps.collider, filter) .with_component(&comps.uid, &*self.collider, &comps.collider, filter)
.with_component(&comps.uid, &*self.sticky, &comps.sticky, filter) .with_component(&comps.uid, &*self.sticky, &comps.sticky, filter)
@ -207,6 +214,7 @@ pub struct WriteTrackers<'a> {
scale: WriteExpect<'a, UpdateTracker<Scale>>, scale: WriteExpect<'a, UpdateTracker<Scale>>,
mounting: WriteExpect<'a, UpdateTracker<Mounting>>, mounting: WriteExpect<'a, UpdateTracker<Mounting>>,
mount_state: WriteExpect<'a, UpdateTracker<MountState>>, mount_state: WriteExpect<'a, UpdateTracker<MountState>>,
alignment: WriteExpect<'a, UpdateTracker<Alignment>>,
mass: WriteExpect<'a, UpdateTracker<Mass>>, mass: WriteExpect<'a, UpdateTracker<Mass>>,
collider: WriteExpect<'a, UpdateTracker<Collider>>, collider: WriteExpect<'a, UpdateTracker<Collider>>,
sticky: WriteExpect<'a, UpdateTracker<Sticky>>, sticky: WriteExpect<'a, UpdateTracker<Sticky>>,
@ -228,6 +236,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
trackers.scale.record_changes(&comps.scale); trackers.scale.record_changes(&comps.scale);
trackers.mounting.record_changes(&comps.mounting); trackers.mounting.record_changes(&comps.mounting);
trackers.mount_state.record_changes(&comps.mount_state); trackers.mount_state.record_changes(&comps.mount_state);
trackers.alignment.record_changes(&comps.alignment);
trackers.mass.record_changes(&comps.mass); trackers.mass.record_changes(&comps.mass);
trackers.collider.record_changes(&comps.collider); trackers.collider.record_changes(&comps.collider);
trackers.sticky.record_changes(&comps.sticky); trackers.sticky.record_changes(&comps.sticky);
@ -282,6 +291,7 @@ pub fn register_trackers(world: &mut World) {
world.register_tracker::<Scale>(); world.register_tracker::<Scale>();
world.register_tracker::<Mounting>(); world.register_tracker::<Mounting>();
world.register_tracker::<MountState>(); world.register_tracker::<MountState>();
world.register_tracker::<Alignment>();
world.register_tracker::<Mass>(); world.register_tracker::<Mass>();
world.register_tracker::<Collider>(); world.register_tracker::<Collider>();
world.register_tracker::<Sticky>(); world.register_tracker::<Sticky>();

View File

@ -57,9 +57,9 @@ impl SessionState {
.set_fov_deg(global_state.settings.graphics.fov); .set_fov_deg(global_state.settings.graphics.fov);
let hud = Hud::new(global_state, &client.borrow()); let hud = Hud::new(global_state, &client.borrow());
{ {
let my_entity = client.borrow().entity(); let mut client = client.borrow_mut();
let my_entity = client.entity();
client client
.borrow_mut()
.state_mut() .state_mut()
.ecs_mut() .ecs_mut()
.insert(MyEntity(my_entity)); .insert(MyEntity(my_entity));