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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
use serde::{Serialize, Deserialize};
use bincode::{serialize, deserialize};

/// A Bloke (from a `*.bloke` file).
///
/// A Bloke File stores your Bloke (`*.bloke`).  Games may render the Bloke according to their own
/// style, and don't have to read all of the fields.  For creating your Bloke, their will be a
/// public domain standard bloke renderer, that does read all of the fields and adjust rendering
/// appropriately.  The file is a simple format of listing shorts (integers 0-65535) which specify
/// how much of an attribute the Bloke has.
///
/// The file format is always 192 bytes uncompressed.  It describes a human-like figure by
/// attributes that are measured on 16-bit continuums.  It does not store a binary bit for gender.
/// It also does not include clothing or jewelery (video games often have their own in game as
/// items).  What is included are other stylistic choices like hair dye and nail polish.  Video
/// games may also apply this format to other imaginary life forms in game, which are not human
/// (example: a game where you play as an alien).
#[derive(Serialize, Deserialize, PartialEq, Debug)]
pub struct Bloke {
    /// Version must be 1
    pub version: u16,
    /// Default: 32768 (65535 = tall arch, 0 = flat feet)
    pub height_arch: u16,
    /// Default: 32768 (65535 = tall legs, 0 = short legs)
    pub height_leg: u16,
    /// Default: 32768 (65535 = tall body, 0 = short body)
    pub height_body: u16,
    /// Default: 32768 (65535 = long neck, 0 = short neck)
    pub height_neck: u16,
    /// Default: 32768 (65535 = tall head, 0 = short head)
    pub height_head: u16,
    /// Default: 32768 (65535 = tall/thick hair, 0 = bald)
    pub height_hair: u16,
    /// Default: 32768 (65535 = big feet, 0 = small feet)
    pub length_foot: u16,
    /// Default: 32768 (65535 = long toes, 0 = short toes)
    pub length_toes: u16,
    /// Default: 32768 (65535 = fat leg, 0 = no-fat leg)
    pub size_legs: u16,
    /// Default: 32768 (65535 = big knee, 0 = no visible knee)
    pub size_knee: u16,
    /// Default: 32768 (65535 = muscular lower leg, 0 = no-muscles lower leg)
    pub size_calf: u16,
    /// Default: 32768 (65535 = muscular upper leg, 0 = no-muscles upper leg)
    pub size_hamstring: u16,
    /// Default: 32768 (65535 = big butt, 0 = small butt)
    pub size_butt: u16,
    /// Default: 32768 (65535 = wide body, 0 = thin body)
    pub size_body: u16,
    /// Default: 32768 (65535 = beer gut, 0 = flat stomach)
    pub size_belly: u16,
    /// Default: 32768 (65535 = has chest, 0 = flat chest)
    pub size_chest: u16,
    /// Default: 32768 (65535 = big arch spine, 0 = straight spine)
    pub size_spine: u16,
    /// Default: 32768 (65535 = hunched over spine, 0 = straight spine)
    pub size_hunch: u16,
    /// Default: 32768 (65535 = sloped shoulder, 0 = flat shoulder)
    pub size_shoulder: u16,
    /// Default: 32768 (65535 = muscular arms, 0 = no-muscle arms)
    pub size_arm_muscle: u16,
    /// Default: 32768 (65535 = fat arms, 0 = no-fat arms)
    pub size_arm_fat: u16,
    /// Default: 32768 (65535 = big elbow, 0 = no visible elbow)
    pub size_elbow: u16,
    /// Default: 32768 (65535 = big hands, 0 = small hands)
    pub size_hand: u16,
    /// Default: 32768 (65535 = long fingers, 0 = short fingers)
    pub size_finger: u16,
    /// Default: 32768 (65535 = big head, 0 = small head)
    pub size_head: u16,
    /// Default: 32768 (65535 = big nose, 0 = small nose)
    pub size_nose: u16,
    /// Default: 32768 (65535 = pointy nose, 0 = flat nose)
    pub size_nosepoint: u16,
    /// Default: 32768 (65535 = big nostrils, 0 = small nostrils)
    pub size_nostril: u16,
    /// Default: 32768 (65535 = wide mouth, 0 = small mouth)
    pub size_mouth: u16,
    /// Default: 32768 (65535 = big lips, 0 = no lips)
    pub size_lips: u16,
    /// Default: 32768 (65535 = big eyes, 0 = small eyes)
    pub size_eyes: u16,
    /// Default: 32768 (65535 = eyes rest mostly closed, 0 = eyes rest mostly open)
    pub size_eyelid: u16,
    /// Default: 32768 (65535 = concave/deep around eyes, 0 = eyes as far out as forehead)
    pub size_eyearea: u16,
    /// Default: 32768u16 (65535 = long eyelashes, 0 = short eyelashes)
    pub size_eyelash: u16,
    /// Default: 32768u16 (65535 = curved upwards, 0 = curved downwards)
    pub size_eyelashcurve: u16,
    /// Default: 32768u16 (65535 = ears stick out, 0 = flat ears)
    pub size_ear: u16,
    /// Default: 32768u16 (65535 = double chin, 0 = mouth very close to chin)
    pub size_chin: u16,
    /// Default: 32768u16 (65535 = spaced out face, 0 = compact face)
    pub size_face: u16,
    /// Default: 32768u16 (65535 = tall forehead, 0 = short forehead)
    pub size_forehead: u16,
    /// Default: 32768u16 (65535 = convex/chipmunk cheeks, 0 = concave/bony cheeks)
    pub size_cheek: u16,
    /// Default: 0u16 (65535 = long mustache (extends off face), 0 = no mustache)
    pub size_mustache: u16,
    /// Default: 0u16 (65535 = long beard (down to knees), 0 = no beard)
    pub size_beard: u16,
    /// Default: 32768u16 (65535 = thick/long hair on sides, 0 = shaved on sides hair)
    pub size_sidehair: u16,
    /// Default: 32768u16 (65535 = long hair, 0 = shaved)
    pub size_bodyhair: u16,
    /// Default: 32768u16 (65535 = protruding bottom of chin, 0 = rounded bottom of chin)
    pub size_chinextend: u16,
    /// Default: 32768u16 (65535 = back of head extends, 0 = back of head is flat with neck)
    pub size_backhead: u16,
    /// Default: 32768u16 (65535 = hair down to ankles, 0 = hair to top of ears)
    pub size_longhair: u16,
    /// Default: 32768u16 (65535 = wide hips, 0 = small hips)
    pub size_hips: u16,
    /// Default: 32768u16 (65535 = wide waist, 0 = small waist)
    pub size_waist: u16,
    /// Default: 32768u16 (65535 = wide ankles, 0 = small ankles)
    pub size_ankle: u16,
    /// Default: 32768u16 (65535 = long foot hair, 0 = no foot hair)
    pub size_foothair: u16,
    /// Default: 32768u16 (65535 = long armpit hair, 0 = no armpit hair)
    pub size_armpithair: u16,
    /// Default: 32768u16 (65535 = long nose hair, 0 = no nose hair)
    pub size_nosehair: u16,
    /// Default: 32768u16 (65535 = thick eyebrows, 0 = thin eyebrows)
    pub thickness_eyebrow: u16,
    /// Default: 32768u16 (65535 = unibrow, 0 = no eyebrows)
    pub width_eyebrow: u16,
    /// Default: 32768 (65535 = round body, 0 = straight body)
    pub roundness_body: u16,
    /// Default: 32768u16 (65535 = finger rounded edges, 0 = finger right angles)
    pub roundness_finger: u16,
    /// Default: 32768u16 (65535 = round head, 0 = almost-cubelike-head)
    pub roundness_head: u16,
    /// Default: 32768u16 (65535 = round ear, 0 = pointy ear)
    pub roundness_ear: u16,
    /// Default: 32768u16 (65535 = long fingernails, 0 = short fingernails)
    pub len_nail: u16,
    /// Default: 32768u16 (65535 = long, 0 = short)
    pub len_arm: u16,
    /// Default: 32768u16 (65535 = eyes far apart, 0 = eyes close to each other)
    pub dist_eye: u16,
    /// Default: 32768u16 (65535 = wrinkly skin, 32768 = rough skin, 0 = shiny smooth skin)
    pub skin: u16,
    /// Default: 32768 (65535 = face & limb freckles, 32768 = limb freckles, 0 = no freckles)
    pub has_freckles: u16,
    /// Default: 0b1111_1111_1111_1111 (4 bit = 4 teeth, top left, right, bottom left, right)
    pub has_teeth: u16,
    /// Default: 0 (65535 = yellow, 0 = white)
    pub color_teeth: u16,
    /// Default: 32768u16 (65535 = light red, 0 = light blue)
    pub color_lip: u16,
    /// Default: 32768u16 (65535 = more brown-red color, 0 = more brown-blue color)
    pub color_skinhue: u16,
    /// Default: 32768u16 (65535 = dark (black) skin, 0 = light (white) skin)
    pub color_skinshade: u16,
    /// Default: (32 bit RGBA)
    pub color_headhair1: u32,
    /// Default: (32 bit RGBA)
    pub color_headhair2: u32,
    /// Default: (32 bit RGBA)
    pub color_headhair3: u32,
    /// Default: (32 bit RGBA)
    pub color_bodyhair: u32,
    /// Default: (32 bit RGBA)
    pub color_mustache: u32,
    /// Default: (32 bit RGBA)
    pub color_beard: u32,
    /// Default: (32 bit RGBA)
    pub color_foothair: u32,
    /// Default: (32 bit RGBA)
    pub color_armpithair: u32,
    /// Default: (32 bit RGBA)
    pub color_eyelash: u32,
    /// Default: (32 bit RGBA)
    pub color_eyebrow: u32,
    /// Default: (32 bit RGBA)
    pub color_eye: u32,
    /// Default: (32 bit RGBA)
    pub color_fingertoenail: u32,
    /// Default: 32768u16 (65535 = high pitched, 0 = low pitched)
    pub voice_pitch: u16,
    /// Default: 0u16 (TODO)
    pub voice_waveform: u16,
}

impl Bloke {
    pub fn save(&self) -> Vec<u8> {
        serialize(self).unwrap()
    }

    pub fn load(data: &[u8]) -> Bloke {
        deserialize(data).unwrap()
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn filesize() {
        assert_eq!(std::mem::size_of::<crate::Bloke>(), 192)
    }
}