veloren_server/
location.rs1use common::comp::Content;
2use hashbrown::HashMap;
3use std::fmt;
4use vek::*;
5
6#[derive(Debug)]
7pub enum LocationError<'a> {
8 InvalidName(String),
9 DuplicateName(String),
10 DoesNotExist(&'a str),
11}
12
13impl<'a> From<LocationError<'a>> for Content {
14 fn from(value: LocationError<'a>) -> Self {
15 match value {
16 LocationError::InvalidName(location) => {
17 Content::localized_with_args("command-location-invalid", [("location", location)])
18 },
19 LocationError::DuplicateName(location) => {
20 Content::localized_with_args("command-location-duplicate", [("location", location)])
21 },
22 LocationError::DoesNotExist(location) => {
23 Content::localized_with_args("command-location-not-found", [("location", location)])
24 },
25 }
26 }
27}
28
29impl fmt::Display for LocationError<'_> {
30 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
31 match self {
32 Self::InvalidName(name) => write!(
33 f,
34 "Location name '{}' is invalid. Names may only contain lowercase ASCII and \
35 underscores",
36 name
37 ),
38 Self::DuplicateName(name) => write!(
39 f,
40 "Location '{}' already exists, consider deleting it first",
41 name
42 ),
43 Self::DoesNotExist(name) => write!(f, "Location '{}' does not exist", name),
44 }
45 }
46}
47
48#[derive(Default)]
51pub struct Locations {
52 locations: HashMap<String, Vec3<f32>>,
53}
54
55impl Locations {
56 pub fn insert(&mut self, name: String, pos: Vec3<f32>) -> Result<(), LocationError<'static>> {
57 if name.chars().all(|c| c.is_ascii_lowercase() || c == '_') {
58 self.locations
59 .try_insert(name, pos)
60 .map(|_| ())
61 .map_err(|o| LocationError::DuplicateName(o.entry.key().clone()))
62 } else {
63 Err(LocationError::InvalidName(name))
64 }
65 }
66
67 pub fn get<'a>(&self, name: &'a str) -> Result<Vec3<f32>, LocationError<'a>> {
68 self.locations
69 .get(name)
70 .copied()
71 .ok_or(LocationError::DoesNotExist(name))
72 }
73
74 pub fn iter(&self) -> impl Iterator<Item = &String> { self.locations.keys() }
75
76 pub fn remove<'a>(&mut self, name: &'a str) -> Result<(), LocationError<'a>> {
77 self.locations
78 .remove(name)
79 .map(|_| ())
80 .ok_or(LocationError::DoesNotExist(name))
81 }
82}