1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use std::{collections::HashMap, hash::Hash};

use crate::{EntityDoesNotExistError, KeyGenerator, NetEntity, NetEntityConverter, OwnedNetEntity};

pub struct LocalWorldManager<E: Copy + Eq + Hash> {
    host_entity_generator: KeyGenerator<NetEntity>,
    world_to_local_entity: HashMap<E, OwnedNetEntity>,
    local_to_world_entity: HashMap<OwnedNetEntity, E>,
}

impl<E: Copy + Eq + Hash> LocalWorldManager<E> {
    pub fn new() -> Self {
        Self {
            host_entity_generator: KeyGenerator::new(),
            world_to_local_entity: HashMap::new(),
            local_to_world_entity: HashMap::new(),
        }
    }

    // Host entities

    pub(crate) fn host_spawn_entity(&mut self, entity: &E) {
        let net_entity = self.host_entity_generator.generate().to_host_owned();

        if self.world_to_local_entity.contains_key(entity) {
            panic!("Entity already exists!");
        }
        if self.local_to_world_entity.contains_key(&net_entity) {
            panic!("Net Entity already exists!");
        }

        self.world_to_local_entity.insert(*entity, net_entity);
        self.local_to_world_entity.insert(net_entity, *entity);
    }

    pub(crate) fn host_despawn_entity(&mut self, entity: &E) {
        let net_entity = self
            .world_to_local_entity
            .remove(entity)
            .expect("Entity does not exist!");
        if !self.local_to_world_entity.contains_key(&net_entity) {
            panic!("Net Entity does not exist!");
        }
        self.local_to_world_entity.remove(&net_entity);
        self.host_entity_generator
            .recycle_key(&net_entity.to_unowned());
    }

    // Remote entities

    pub(crate) fn get_remote_entity(&self, net_entity: &NetEntity) -> E {
        let owned_net_entity = net_entity.to_remote_owned();

        if let Some(world_entity) = self.local_to_world_entity.get(&owned_net_entity) {
            return *world_entity;
        }
        panic!("Attempting to access remote entity which does not exist!")
    }

    pub(crate) fn remote_entities(&self) -> Vec<E> {
        let mut output = Vec::new();
        for (owned_net_entity, entity) in &self.local_to_world_entity {
            if owned_net_entity.is_host() {
                continue;
            }
            output.push(*entity);
        }
        return output;
    }

    pub(crate) fn remote_spawn_entity(&mut self, entity: &E, net_entity: &NetEntity) {
        let owned_net_entity = net_entity.to_remote_owned();

        if self.world_to_local_entity.contains_key(entity) {
            panic!("Entity already exists!");
        }
        if self.local_to_world_entity.contains_key(&owned_net_entity) {
            panic!("Net Entity already exists!");
        }

        self.world_to_local_entity.insert(*entity, owned_net_entity);
        self.local_to_world_entity.insert(owned_net_entity, *entity);
    }

    pub(crate) fn remote_despawn_entity(&mut self, net_entity: &NetEntity) -> E {
        let owned_net_entity = net_entity.to_remote_owned();

        if let Some(world_entity) = self.local_to_world_entity.remove(&owned_net_entity) {
            if self.world_to_local_entity.remove(&world_entity).is_none() {
                panic!("Entity already exists!");
            } else {
                return world_entity;
            }
        } else {
            panic!("Trying to despawn a remote entity that does not exist!");
        }
    }
}

impl<E: Copy + Eq + Hash> NetEntityConverter<E> for LocalWorldManager<E> {
    fn entity_to_net_entity(&self, entity: &E) -> Result<OwnedNetEntity, EntityDoesNotExistError> {
        if let Some(net_entity) = self.world_to_local_entity.get(entity) {
            return Ok(*net_entity);
        } else {
            return Err(EntityDoesNotExistError);
        }
    }

    fn net_entity_to_entity(
        &self,
        net_entity: &OwnedNetEntity,
    ) -> Result<E, EntityDoesNotExistError> {
        if let Some(entity) = self.local_to_world_entity.get(net_entity) {
            return Ok(*entity);
        } else {
            return Err(EntityDoesNotExistError);
        }
    }
}