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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use std::collections::HashMap;

use serde::{Deserialize, Serialize};

macro_rules! color_def {
    ($n:ident, $c:literal) => {
        fn $n(self) -> Self {
            self.color($c)
        }
    }
}

pub trait Colorize: Sized {
    fn bold(self) -> Self;
    fn italics(self) -> Self;
    fn color(self, code: &str) -> Self;
    fn hyperlink(self, link: &str) -> Self;
    fn size(self, size: i32) -> Self;

    color_def!(red, "f00");
    color_def!(green, "0f0");
    color_def!(blue, "00f");
    color_def!(yellow, "ff0");
    color_def!(teal, "0ff");
    color_def!(magenta, "f0f");
    color_def!(white, "fff");
    color_def!(black, "000");
    color_def!(dark_gray, "666");
    color_def!(light_gray, "bbb");
}

impl Colorize for String {
    fn bold(self) -> Self {
        format!("**{}**", self)
    }

    fn italics(self) -> Self {
        format!("*{}*", self)
    }

    fn color(self, code: &str) -> Self {
        format!("<color=\"{}\">{}</>", code, self)
    }

    fn hyperlink(self, link: &str) -> Self {
        format!("[{}]({})", self, link)
    }

    fn size(self, size: i32) -> Self {
        format!("<size=\"{}\">{}</>", self, size)
    }
}

/// A player.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Player {
    pub name: String,
    pub id: String,
    pub controller: String,
    pub state: String,
    pub host: Option<bool>,
}

/// A player position, which composes a `Player` and their position (a `(f64, f64, f64)`).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlayerPosition {
    pub player: Player,
    pub pos: Option<(f64, f64, f64)>,
}

/// Ghost brick data.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GhostBrick {
    #[serde(rename = "targetGrid")]
    pub target_grid: String,
    pub location: (f64, f64, f64),
    pub orientation: String,
}

/// Player paint data.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlayerPaint {
    #[serde(rename = "materialIndex")]
    pub material_index: String,
    #[serde(rename = "materialAlpha")]
    pub material_alpha: String,
    #[serde(rename = "material")]
    pub material: String,
    #[serde(rename = "color")]
    pub color: (u8, u8, u8),
}

/// Bounds data.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TemplateBounds {
    #[serde(rename = "minBound")]
    pub min_bound: (f64, f64, f64),
    #[serde(rename = "maxBound")]
    pub max_bound: (f64, f64, f64),
    pub center: (f64, f64, f64),
}

/// A plugin.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Plugin {
    pub name: String,
    pub description: String,
    pub author: String,
    pub config: HashMap<String, ConfigEntry>,
    pub commands: Vec<Command>,
}

/// A config entry.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConfigEntry {
    pub description: String,
    #[serde(rename = "type")]
    pub entry_type: String,
    #[serde(rename = "itemType")]
    pub item_type: Option<String>,
    #[serde(default)]
    pub default: serde_json::Value,
}

/// A config command.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Command {
    pub name: String,
    pub description: String,
    pub example: String,
    pub args: Vec<CommandArg>,
}

/// A config command arg.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommandArg {
    pub name: String,
    pub description: String,
    #[serde(default)]
    pub required: bool,
}