veloren_common_state/
special_areas.rs1use common::depot::{Depot, Id};
2use hashbrown::{HashMap, hash_map};
3use std::{
4 marker::PhantomData,
5 ops::{Deref, DerefMut},
6};
7use vek::*;
8
9#[derive(Default)]
10pub struct AreasContainer<Kind>(Areas, PhantomData<Kind>);
11
12#[derive(Default)]
13pub struct BuildArea;
14
15#[derive(Default)]
16pub struct NoDurabilityArea;
17
18#[derive(Default)]
20pub struct BattleModeChangeArea;
21
22#[derive(Default)]
26pub struct Areas {
27 areas: Depot<Aabb<i32>>,
28 area_names: HashMap<String, Id<Aabb<i32>>>,
29}
30
31pub enum SpecialAreaError {
32 Reserved,
34 NotFound,
36}
37
38const RESERVED_BUILD_AREA_NAMES: &[&str] = &["world"];
40
41impl Areas {
42 pub fn areas(&self) -> &Depot<Aabb<i32>> { &self.areas }
43
44 pub fn area_metas(&self) -> &HashMap<String, Id<Aabb<i32>>> { &self.area_names }
45
46 pub fn insert(&mut self, area_name: String, area: Aabb<i32>) -> Result<Id<Aabb<i32>>, String> {
48 let area_name_entry = match self.area_names.entry(area_name) {
49 hash_map::Entry::Occupied(o) => return Err(o.key().to_string()),
50 hash_map::Entry::Vacant(v) => v,
51 };
52 let bb_id = self.areas.insert(area.made_valid());
53 area_name_entry.insert(bb_id);
54 Ok(bb_id)
55 }
56
57 pub fn remove(&mut self, area_name: &str) -> Result<Aabb<i32>, SpecialAreaError> {
58 if RESERVED_BUILD_AREA_NAMES.contains(&area_name) {
59 return Err(SpecialAreaError::Reserved);
60 }
61 let bb_id = self
62 .area_names
63 .remove(area_name)
64 .ok_or(SpecialAreaError::NotFound)?;
65 let area = self.areas.remove(bb_id).expect(
66 "Entries in `areas` are added before entries in `area_names` in `insert`, and that is \
67 the only exposed way to add elements to `area_names`.",
68 );
69 Ok(area)
70 }
71}
72
73impl<Kind> Deref for AreasContainer<Kind>
74where
75 Kind: AreaKind,
76{
77 type Target = Areas;
78
79 fn deref(&self) -> &Self::Target { &self.0 }
80}
81
82impl<Kind> DerefMut for AreasContainer<Kind>
83where
84 Kind: AreaKind,
85{
86 fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
87}
88
89pub trait AreaKind {
90 fn display() -> &'static str;
91}
92
93impl AreaKind for BuildArea {
94 fn display() -> &'static str { "build" }
95}
96
97impl AreaKind for NoDurabilityArea {
98 fn display() -> &'static str { "durability free" }
99}
100
101impl AreaKind for BattleModeChangeArea {
102 fn display() -> &'static str { "battlemode change" }
103}