veloren_common_state/plugin/
memory_manager.rs1use common::{
2 comp::{Health, Player},
3 uid::{IdMaps, Uid},
4};
5use specs::{
6 Component, Entities, Entity, Read, ReadStorage, WriteStorage, storage::GenericReadStorage,
7};
8use std::sync::atomic::{AtomicPtr, Ordering};
9
10pub struct EcsWorld<'a, 'b> {
11 pub entities: &'b Entities<'a>,
12 pub health: EcsComponentAccess<'a, 'b, Health>,
13 pub uid: EcsComponentAccess<'a, 'b, Uid>,
14 pub player: EcsComponentAccess<'a, 'b, Player>,
15 pub id_maps: &'b Read<'a, IdMaps>,
16}
17
18pub enum EcsComponentAccess<'a, 'b, T: Component> {
19 Read(&'b ReadStorage<'a, T>),
20 ReadOwned(ReadStorage<'a, T>),
21 Write(&'b WriteStorage<'a, T>),
22 WriteOwned(WriteStorage<'a, T>),
23}
24
25impl<T: Component> EcsComponentAccess<'_, '_, T> {
26 pub fn get(&self, entity: Entity) -> Option<&T> {
27 match self {
28 EcsComponentAccess::Read(e) => e.get(entity),
29 EcsComponentAccess::Write(e) => e.get(entity),
30 EcsComponentAccess::ReadOwned(e) => e.get(entity),
31 EcsComponentAccess::WriteOwned(e) => e.get(entity),
32 }
33 }
34}
35
36impl<'a, 'b, T: Component> From<&'b ReadStorage<'a, T>> for EcsComponentAccess<'a, 'b, T> {
37 fn from(a: &'b ReadStorage<'a, T>) -> Self { Self::Read(a) }
38}
39
40impl<'a, T: Component> From<ReadStorage<'a, T>> for EcsComponentAccess<'a, '_, T> {
41 fn from(a: ReadStorage<'a, T>) -> Self { Self::ReadOwned(a) }
42}
43
44impl<'a, 'b, T: Component> From<&'b WriteStorage<'a, T>> for EcsComponentAccess<'a, 'b, T> {
45 fn from(a: &'b WriteStorage<'a, T>) -> Self { Self::Write(a) }
46}
47
48impl<'a, T: Component> From<WriteStorage<'a, T>> for EcsComponentAccess<'a, '_, T> {
49 fn from(a: WriteStorage<'a, T>) -> Self { Self::WriteOwned(a) }
50}
51
52pub struct EcsAccessManager {
54 ecs_pointer: AtomicPtr<EcsWorld<'static, 'static>>,
55}
56
57impl Default for EcsAccessManager {
58 fn default() -> Self {
59 Self {
60 ecs_pointer: AtomicPtr::new(std::ptr::null_mut()),
61 }
62 }
63}
64
65impl EcsAccessManager {
66 pub fn execute_with<T>(&self, world: &EcsWorld, func: impl FnOnce() -> T) -> T {
69 let _guard = scopeguard::guard((), |_| {
70 self.ecs_pointer
72 .store(std::ptr::null_mut(), Ordering::Relaxed);
73 });
74 self.ecs_pointer
75 .store(world as *const _ as *mut _, Ordering::Relaxed);
76 func()
77 }
78
79 pub unsafe fn get(&self) -> Option<&EcsWorld> {
92 self.ecs_pointer.load(Ordering::Relaxed).as_ref()
94 }
95}