azalea_world/
container.rs1use std::{
2 collections::HashMap,
3 sync::{Arc, Weak},
4};
5
6use azalea_core::{registry_holder::RegistryHolder, resource_location::ResourceLocation};
7use bevy_ecs::{component::Component, resource::Resource};
8use derive_more::{Deref, DerefMut};
9use nohash_hasher::IntMap;
10use parking_lot::RwLock;
11use rustc_hash::FxHashMap;
12use tracing::{debug, error};
13
14use crate::{ChunkStorage, Instance};
15
16#[derive(Default, Resource)]
21pub struct InstanceContainer {
22 pub instances: FxHashMap<ResourceLocation, Weak<RwLock<Instance>>>,
35}
36
37impl InstanceContainer {
38 pub fn new() -> Self {
39 InstanceContainer::default()
40 }
41
42 pub fn get(&self, name: &InstanceName) -> Option<Arc<RwLock<Instance>>> {
45 self.instances.get(name).and_then(|world| world.upgrade())
46 }
47
48 #[must_use = "the world will be immediately forgotten if unused"]
51 pub fn get_or_insert(
52 &mut self,
53 name: ResourceLocation,
54 height: u32,
55 min_y: i32,
56 default_registries: &RegistryHolder,
57 ) -> Arc<RwLock<Instance>> {
58 match self.instances.get(&name).and_then(|world| world.upgrade()) {
59 Some(existing_lock) => {
60 let existing = existing_lock.read();
61 if existing.chunks.height != height {
62 error!(
63 "Shared world height mismatch: {} != {height}",
64 existing.chunks.height
65 );
66 }
67 if existing.chunks.min_y != min_y {
68 error!(
69 "Shared world min_y mismatch: {} != {min_y}",
70 existing.chunks.min_y
71 );
72 }
73 existing_lock.clone()
74 }
75 _ => {
76 let world = Arc::new(RwLock::new(Instance {
77 chunks: ChunkStorage::new(height, min_y),
78 entities_by_chunk: HashMap::new(),
79 entity_by_id: IntMap::default(),
80 registries: default_registries.clone(),
81 }));
82 debug!("Added new instance {name}");
83 self.instances.insert(name, Arc::downgrade(&world));
84 world
85 }
86 }
87 }
88}
89
90#[derive(Component, Clone, Debug, PartialEq, Deref, DerefMut)]
95#[doc(alias("worldname", "world name"))]
96pub struct InstanceName(pub ResourceLocation);