azalea_world/
container.rs1use std::{
2 collections::HashMap,
3 fmt::{self, Display},
4 sync::{Arc, Weak},
5};
6
7use azalea_core::registry_holder::RegistryHolder;
8use azalea_registry::identifier::Identifier;
9use bevy_ecs::{component::Component, resource::Resource};
10use derive_more::{Deref, DerefMut};
11use nohash_hasher::IntMap;
12use parking_lot::RwLock;
13use rustc_hash::FxHashMap;
14use tracing::{debug, error};
15
16use crate::{ChunkStorage, World};
17
18#[derive(Default, Resource)]
23pub struct Worlds {
24 pub map: FxHashMap<WorldName, Weak<RwLock<World>>>,
36}
37
38impl Worlds {
39 pub fn new() -> Self {
40 Worlds::default()
41 }
42
43 pub fn get(&self, name: &WorldName) -> Option<Arc<RwLock<World>>> {
47 self.map.get(name).and_then(|world| world.upgrade())
48 }
49
50 #[must_use = "the world will be immediately forgotten if unused"]
53 pub fn get_or_insert(
54 &mut self,
55 name: WorldName,
56 height: u32,
57 min_y: i32,
58 default_registries: &RegistryHolder,
59 ) -> Arc<RwLock<World>> {
60 match self.map.get(&name).and_then(|world| world.upgrade()) {
61 Some(existing_lock) => {
62 let existing = existing_lock.read();
63 if existing.chunks.height != height {
64 error!(
65 "Shared world height mismatch: {} != {height}",
66 existing.chunks.height
67 );
68 }
69 if existing.chunks.min_y != min_y {
70 error!(
71 "Shared world min_y mismatch: {} != {min_y}",
72 existing.chunks.min_y
73 );
74 }
75 existing_lock.clone()
76 }
77 _ => {
78 let world = Arc::new(RwLock::new(World {
79 chunks: ChunkStorage::new(height, min_y),
80 entities_by_chunk: HashMap::new(),
81 entity_by_id: IntMap::default(),
82 registries: default_registries.clone(),
83 }));
84 debug!("Added new world {name:?}");
85 self.map.insert(name, Arc::downgrade(&world));
86 world
87 }
88 }
89 }
90}
91
92#[derive(Clone, Component, Debug, Deref, DerefMut, Eq, Hash, PartialEq)]
97#[doc(alias("dimension"))]
98pub struct WorldName(pub Identifier);
99impl WorldName {
100 pub fn new(name: &str) -> Self {
102 Self(Identifier::new(name))
103 }
104}
105impl Display for WorldName {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 self.0.fmt(f)
108 }
109}
110impl From<Identifier> for WorldName {
111 fn from(ident: Identifier) -> Self {
112 Self(ident)
113 }
114}