steel_core/entity/damage/history/
source.rs1use std::sync::Arc;
2
3use glam::DVec3;
4use steel_registry::{REGISTRY, TaggedRegistryExt, damage_type::DamageType};
5use steel_utils::Identifier;
6
7use super::DamageSource;
8use crate::entity::{EntityGeneration, SharedEntity, WeakEntity};
9
10struct WeakSourceEntity {
11 entity: WeakEntity,
12 generation: EntityGeneration,
13}
14
15impl WeakSourceEntity {
16 fn new(entity: &SharedEntity) -> Self {
17 Self {
18 entity: Arc::downgrade(entity),
19 generation: entity.generation(),
20 }
21 }
22
23 fn resolve(&self) -> ResolvedSourceEntity {
24 ResolvedSourceEntity {
25 entity: self.entity.upgrade(),
26 generation: self.generation,
27 }
28 }
29}
30
31pub(super) struct WeakDamageSource {
32 damage_type: &'static DamageType,
33 causing_entity: Option<WeakSourceEntity>,
34 direct_entity: Option<WeakSourceEntity>,
35 source_position: Option<DVec3>,
36}
37
38impl WeakDamageSource {
39 pub(super) fn new(source: &DamageSource) -> Self {
40 Self {
41 damage_type: source.damage_type,
42 causing_entity: source.causing_entity().map(WeakSourceEntity::new),
43 direct_entity: source.direct_entity().map(WeakSourceEntity::new),
44 source_position: source.source_position_raw(),
45 }
46 }
47
48 pub(super) fn resolve(&self) -> RecentDamageSource {
49 RecentDamageSource {
50 damage_type: self.damage_type,
51 causing_entity: self.causing_entity.as_ref().map(WeakSourceEntity::resolve),
52 direct_entity: self.direct_entity.as_ref().map(WeakSourceEntity::resolve),
53 source_position: self.source_position,
54 }
55 }
56}
57
58struct ResolvedSourceEntity {
59 entity: Option<SharedEntity>,
60 generation: EntityGeneration,
61}
62
63pub struct RecentDamageSource {
70 pub damage_type: &'static DamageType,
72 causing_entity: Option<ResolvedSourceEntity>,
73 direct_entity: Option<ResolvedSourceEntity>,
74 source_position: Option<DVec3>,
75}
76
77impl RecentDamageSource {
78 #[must_use]
80 pub fn causing_entity(&self) -> Option<&SharedEntity> {
81 self.causing_entity.as_ref()?.entity.as_ref()
82 }
83
84 #[must_use]
86 pub fn direct_entity(&self) -> Option<&SharedEntity> {
87 self.direct_entity.as_ref()?.entity.as_ref()
88 }
89
90 #[must_use]
92 pub fn causing_entity_generation(&self) -> Option<EntityGeneration> {
93 self.causing_entity.as_ref().map(|source| source.generation)
94 }
95
96 #[must_use]
98 pub fn direct_entity_generation(&self) -> Option<EntityGeneration> {
99 self.direct_entity.as_ref().map(|source| source.generation)
100 }
101
102 #[must_use]
104 pub fn is_direct(&self) -> bool {
105 self.causing_entity_generation() == self.direct_entity_generation()
106 }
107
108 #[must_use]
110 pub fn is(&self, tag: &Identifier) -> bool {
111 REGISTRY.damage_types.is_in_tag(self.damage_type, tag)
112 }
113
114 #[must_use]
116 pub fn source_position(&self) -> Option<DVec3> {
117 self.source_position
118 .or_else(|| self.direct_entity().map(|entity| entity.position()))
119 }
120
121 #[must_use]
123 pub const fn source_position_raw(&self) -> Option<DVec3> {
124 self.source_position
125 }
126}