mindustry logic execution, map- and schematic- parsing and rendering
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use std::error::Error;
use std::fmt;

use crate::content::{Content, Type};

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Team(u8);

impl Team {
    #[must_use]
    pub fn of(id: u8) -> Self {
        Self(id)
    }

    #[must_use]
    pub fn is_base(&self) -> bool {
        self.0 < 6
    }
}

impl From<u8> for Team {
    fn from(value: u8) -> Self {
        Team::of(value)
    }
}

impl TryFrom<u16> for Team {
    type Error = TryFromU16Error;

    fn try_from(value: u16) -> Result<Self, Self::Error> {
        if u8::try_from(value).is_ok() {
            Ok(Team(value as u8))
        } else {
            Err(TryFromU16Error(value))
        }
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct TryFromU16Error(pub u16);

impl From<Team> for u8 {
    fn from(value: Team) -> Self {
        value.0
    }
}

impl From<Team> for u16 {
    fn from(value: Team) -> Self {
        u16::from(value.0)
    }
}

impl fmt::Display for Team {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.0 {
            0 => f.write_str("Derelict"),
            1 => f.write_str("Sharded"),
            2 => f.write_str("Crux"),
            3 => f.write_str("Malis"),
            4 => f.write_str("Green"),
            5 => f.write_str("Blue"),
            id => write!(f, "Team #{id}"),
        }
    }
}

impl fmt::Display for TryFromU16Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "no content of type Team for value {}", self.0)
    }
}

impl Error for TryFromU16Error {}

const TEAM_NAMES: &str = include_str!("../res/team_names.txt");

impl Content for Team {
    fn get_type(&self) -> Type {
        Type::Team
    }

    fn get_id(&self) -> u16 {
        u16::from(self.0)
    }

    fn get_name(&self) -> &'static str {
        match self.0 {
            0 => "derelict",
            1 => "sharded",
            2 => "crux",
            3 => "malis",
            4 => "green",
            5 => "blue",
            // dark magic: offsets manually computed, then rely on the format "...|team#{i}|..."
            i @ 6..=9 => {
                // length: 7 ("team#" (5) + 1 digit + "|" (1))
                let s = ((i - 6) as usize) * 7;
                &TEAM_NAMES[s..s + 6] // exclude the trailing "|"
            }
            i @ 10..=99 => {
                // length: 8 ("team#" (5) + 2 digits + "|" (1))
                let s = 28 + ((i - 10) as usize) * 8;
                &TEAM_NAMES[s..s + 7] // exclude the trailing "|"
            }
            i @ 100..=255 => {
                // length: 9 ("team#" (5) + 3 digits + "|" (1))
                let s = 748 + ((i - 100) as usize) * 9;
                &TEAM_NAMES[s..s + 8] // exclude the trailing "|"
            }
        }
    }
}

#[allow(dead_code)]
pub const DERELICT: Team = Team(0);
#[allow(dead_code)]
pub const SHARDED: Team = Team(1);
#[allow(dead_code)]
pub const CRUX: Team = Team(2);
#[allow(dead_code)]
pub const MALIS: Team = Team(3);
#[allow(dead_code)]
pub const GREEN: Team = Team(4);
#[allow(dead_code)]
pub const BLUE: Team = Team(5);