unity_mirror_rs/unity_engine/
world.rs

1use crate::commons::action::SelfMutAction;
2use crate::commons::RevelArc;
3use crate::commons::RevelWeak;
4use crate::metadata_settings::Metadata;
5use crate::unity_engine::game_object::GameObject;
6use once_cell::sync::Lazy;
7use std::collections::HashMap;
8use std::ops::{Deref, DerefMut};
9use std::sync::atomic::AtomicIsize;
10use std::sync::atomic::Ordering::SeqCst;
11
12static mut WORLDS: Lazy<Vec<RevelArc<World>>> = Lazy::new(|| Vec::new());
13static mut ACTIVE_WORLD_INDEX: AtomicIsize = AtomicIsize::new(-1);
14static mut DONT_DESTROY_OBJECT: Lazy<HashMap<u64, RevelArc<GameObject>>> =
15    Lazy::new(|| HashMap::default());
16
17#[derive(Default)]
18pub struct World {
19    #[allow(unused)]
20    scene_name: String,
21    scene_path: String,
22    game_objects: HashMap<u64, RevelArc<GameObject>>,
23}
24
25static mut SCENE_LOADED_ACTION: Lazy<SelfMutAction<(String, LoadSceneMode), ()>> =
26    Lazy::new(|| SelfMutAction::default());
27
28impl World {
29    fn new(scene_path: &str) -> Self {
30        match Metadata::get_scene(scene_path) {
31            None => {
32                panic!(
33                    "Failed to load scene '{}'. Please check if the scene exists in the metadata.",
34                    scene_path
35                )
36            }
37            Some(scene_metadata) => {
38                let mut world = World {
39                    scene_name: scene_path.to_string(),
40                    scene_path: scene_path.to_string(),
41                    game_objects: Default::default(),
42                };
43                for (_, metadata_prefab) in scene_metadata.iter() {
44                    let arc_game_object = GameObject::instance(metadata_prefab);
45                    world
46                        .game_objects
47                        .insert(arc_game_object.id, arc_game_object);
48                }
49                world
50            }
51        }
52    }
53
54    fn destroy_all_game_object(&mut self) {
55        for (_id, arc_game_object) in self.game_objects.iter_mut() {
56            arc_game_object.on_disable();
57        }
58        for (_id, arc_game_object) in self.game_objects.iter_mut() {
59            arc_game_object.on_destroy();
60        }
61    }
62
63    fn destroy_game_object_with_id(&mut self, id: &u64) {
64        if let Some(mut removed_arc_game_object) = self.game_objects.remove(id) {
65            removed_arc_game_object.on_disable();
66            removed_arc_game_object.on_destroy();
67        }
68    }
69
70    pub fn add_game_object(&mut self, arc_game_object: RevelArc<GameObject>) {
71        self.game_objects
72            .insert(arc_game_object.id, arc_game_object);
73    }
74
75    pub fn get_scene_path(&self) -> String {
76        return self.scene_path.clone();
77    }
78}
79
80pub enum LoadSceneMode {
81    Single,
82    Additive,
83}
84
85pub struct WorldManagerStatic {
86    loading: bool,
87}
88
89impl WorldManagerStatic {
90    #[allow(unused)]
91    pub(crate) fn loading(&self) -> bool {
92        self.loading
93    }
94    pub(crate) fn set_loading(&mut self, loading: bool) {
95        self.loading = loading;
96    }
97}
98
99static mut WORLD_MANAGER_STATIC: Lazy<WorldManagerStatic> =
100    Lazy::new(|| WorldManagerStatic { loading: false });
101
102pub struct WorldManager;
103
104impl Deref for WorldManager {
105    type Target = WorldManagerStatic;
106
107    fn deref(&self) -> &Self::Target {
108        #[allow(static_mut_refs)]
109        unsafe {
110            &*WORLD_MANAGER_STATIC
111        }
112    }
113}
114
115impl DerefMut for WorldManager {
116    fn deref_mut(&mut self) -> &mut Self::Target {
117        #[allow(static_mut_refs)]
118        unsafe {
119            &mut *WORLD_MANAGER_STATIC
120        }
121    }
122}
123
124impl WorldManager {
125    pub fn load_scene(scene_path: &str, mode: LoadSceneMode) -> usize {
126        #[allow(static_mut_refs)]
127        unsafe {
128            Self.loading = true;
129            let world = World::new(scene_path);
130            let i = match mode {
131                LoadSceneMode::Single => {
132                    WORLDS
133                        .iter_mut()
134                        .for_each(|world| world.destroy_all_game_object());
135                    WORLDS.clear();
136                    WORLDS.push(RevelArc::new(world));
137                    Self::set_active_scene(0)
138                }
139                LoadSceneMode::Additive => {
140                    WORLDS.push(RevelArc::new(world));
141                    WORLDS.len() - 1
142                }
143            };
144            SCENE_LOADED_ACTION.call((scene_path.to_string(), mode));
145            Self.loading = false;
146            i
147        }
148    }
149
150    pub fn set_scene_loaded(f: SelfMutAction<(String, LoadSceneMode), ()>) {
151        #[allow(static_mut_refs)]
152        unsafe {
153            *SCENE_LOADED_ACTION = f;
154        }
155    }
156
157    pub fn set_active_scene(index: usize) -> usize {
158        #[allow(static_mut_refs)]
159        unsafe {
160            if index > WORLDS.len() {
161                panic!("Invalid world index: {}", index);
162            }
163            ACTIVE_WORLD_INDEX.store(index as isize, SeqCst);
164        }
165        index
166    }
167
168    pub fn active_world() -> RevelWeak<World> {
169        #[allow(static_mut_refs)]
170        unsafe {
171            let index = ACTIVE_WORLD_INDEX.load(SeqCst);
172            if index >= 0 {
173                if let Some(world) = WORLDS.get(index as usize) {
174                    return world.downgrade();
175                }
176            }
177            RevelWeak::default()
178        }
179    }
180
181    pub fn dont_destroy_object(arc_game_object: RevelArc<GameObject>) -> RevelWeak<GameObject> {
182        #[allow(static_mut_refs)]
183        unsafe {
184            let id = arc_game_object.id;
185
186            let index = ACTIVE_WORLD_INDEX.load(std::sync::atomic::Ordering::SeqCst);
187
188            if let Some(world) = WORLDS.get_mut(index as usize) {
189                if world.game_objects.contains_key(&id) {
190                    world.game_objects.remove(&id);
191                }
192            }
193
194            if DONT_DESTROY_OBJECT.contains_key(&id) {
195                panic!(
196                    "GameObject with ID {} already exists in the dont_destroy_object world.",
197                    id
198                );
199            }
200            let weak_game_object = arc_game_object.downgrade();
201            DONT_DESTROY_OBJECT.insert(id, arc_game_object);
202            weak_game_object
203        }
204    }
205
206    pub fn destroy(id: &u64) {
207        #[allow(static_mut_refs)]
208        unsafe {
209            if let Some(mut arc_game_object) = DONT_DESTROY_OBJECT.remove(id) {
210                arc_game_object.on_disable();
211                arc_game_object.on_destroy();
212            } else {
213                let index = ACTIVE_WORLD_INDEX.load(std::sync::atomic::Ordering::SeqCst);
214                if let Some(world) = WORLDS.get_mut(index as usize) {
215                    world.destroy_game_object_with_id(id);
216                }
217            }
218        }
219    }
220
221    pub fn root_game_objects() -> Vec<RevelWeak<GameObject>> {
222        #[allow(static_mut_refs)]
223        unsafe {
224            let mut root_game_objects = vec![];
225
226            let index = ACTIVE_WORLD_INDEX.load(SeqCst);
227            if index >= 0 {
228                if let Some(world) = WORLDS.get(index as usize) {
229                    let world_root_game_objects = world
230                        .game_objects
231                        .values()
232                        .map(|arc_game_object| arc_game_object.downgrade())
233                        .collect::<Vec<_>>();
234                    root_game_objects.extend(world_root_game_objects);
235                }
236            }
237
238            let dont_destroy_objects = DONT_DESTROY_OBJECT
239                .values()
240                .filter(|arc_game_object| {
241                    arc_game_object.parent.upgradable()
242                    // if let Ok(game_object) = arc_game_object.read() {
243                    //     game_object.parent.is_none()
244                    // } else {
245                    //     false
246                    // }
247                })
248                .map(|arc_game_object| arc_game_object.downgrade())
249                .collect::<Vec<_>>();
250            root_game_objects.extend(dont_destroy_objects);
251            root_game_objects
252        }
253    }
254}
255
256impl WorldManager {
257    pub(super) fn fixed_update() {
258        #[allow(static_mut_refs)]
259        unsafe {
260            for (_, game_object) in DONT_DESTROY_OBJECT.iter_mut() {
261                game_object.fixed_update();
262            }
263            for world in WORLDS.iter_mut() {
264                for (_, game_object) in world.game_objects.iter_mut() {
265                    game_object.fixed_update();
266                }
267            }
268        }
269    }
270
271    pub(super) fn update() {
272        #[allow(static_mut_refs)]
273        unsafe {
274            for (_, game_object) in DONT_DESTROY_OBJECT.iter_mut() {
275                game_object.update();
276            }
277            for world in WORLDS.iter_mut() {
278                for (_, game_object) in world.game_objects.iter_mut() {
279                    game_object.update();
280                }
281            }
282        }
283    }
284
285    pub(super) fn late_update() {
286        #[allow(static_mut_refs)]
287        unsafe {
288            for (_, game_object) in DONT_DESTROY_OBJECT.iter_mut() {
289                game_object.late_update();
290            }
291            for world in WORLDS.iter_mut() {
292                for (_, game_object) in world.game_objects.iter_mut() {
293                    game_object.late_update();
294                }
295            }
296        }
297    }
298}
299
300#[cfg(test)]
301mod tests {
302    use super::*;
303
304    #[test]
305    fn test_change_scene() {
306        // WorldManager::load_scene("Assets/Scenes/LobbyScene.unity", LoadSceneMode::Single);
307        WorldManager::load_scene("Assets/Scenes/RoomScene.unity", LoadSceneMode::Single);
308        // WorldManager::set_active_scene(1);
309        // let network_room_player_prefab =
310        //     Metadata::get_prefab("Assets/Prefabs/NetworkRoomPlayer.prefab").unwrap();
311        //
312        // let arc_game_object = GameObject::instance(&network_room_player_prefab);
313        // let id = arc_game_object.read().unwrap().id;
314        // WorldManager::dont_destroy_object(arc_game_object);
315
316        // let vec = WorldManager::root_game_objects();
317        // vec.iter().for_each(|weak_game_object| {
318        //     if let Some(game_object) = weak_game_object.get() {
319        //         println!("{}", game_object.name);
320        //         if let Some(weak_network_identity) =
321        //             game_object.try_get_component::<NetworkIdentity>()
322        //         {
323        //             println!("{}", weak_network_identity.net_id());
324        //             // if let Some(read) = weak_network_identity.read() {
325        //             //     println!("{}", read.net_id());
326        //             // }
327        //         }
328        //     }
329        // });
330
331        // let mut looper = GameLooper::new();
332        // looper.run();
333
334        // WorldManager::change_scene("Assets/Scenes/LobbyScene.unity");
335        // WorldManager::change_scene("Assets/Scenes/RoomScene.unity");
336        // WorldManager::change_scene("Assets/Scenes/RoomScene.unity");
337    }
338}