azalea_world/
container.rs1use std::{
2 collections::HashMap,
3 sync::{Arc, Weak},
4};
5
6use azalea_core::registry_holder::RegistryHolder;
7use azalea_registry::identifier::Identifier;
8use bevy_ecs::{component::Component, resource::Resource};
9use derive_more::{Deref, DerefMut};
10use nohash_hasher::IntMap;
11use parking_lot::RwLock;
12use rustc_hash::FxHashMap;
13use tracing::{debug, error};
14
15use crate::{ChunkStorage, Instance};
16
17#[derive(Default, Resource)]
22pub struct InstanceContainer {
23 pub instances: FxHashMap<Identifier, Weak<RwLock<Instance>>>,
36}
37
38impl InstanceContainer {
39 pub fn new() -> Self {
40 InstanceContainer::default()
41 }
42
43 pub fn get(&self, name: &InstanceName) -> Option<Arc<RwLock<Instance>>> {
47 self.instances.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: Identifier,
56 height: u32,
57 min_y: i32,
58 default_registries: &RegistryHolder,
59 ) -> Arc<RwLock<Instance>> {
60 match self.instances.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(Instance {
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 instance {name}");
85 self.instances.insert(name, Arc::downgrade(&world));
86 world
87 }
88 }
89 }
90}
91
92#[derive(Component, Clone, Debug, PartialEq, Deref, DerefMut, Hash, Eq)]
97#[doc(alias("worldname", "world name"))]
98pub struct InstanceName(pub Identifier);