Serialize option enums to u8, for backward compatibility.

This commit is contained in:
Lyle Mantooth 2022-06-04 09:29:47 -04:00
parent 41be111857
commit 8901e0e8b0
Signed by: IslandUsurper
GPG key ID: 6DB52EAE123A5789
2 changed files with 217 additions and 80 deletions

View file

@ -1,9 +1,12 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use serde::{Deserialize, Serialize};
use crate::InvalidEnumError; use crate::InvalidEnumError;
#[derive(Debug)] #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[repr(u8)] #[repr(u8)]
#[serde(into = "u8", try_from = "u8")]
pub enum BossType { pub enum BossType {
Kholdstare, Kholdstare,
Moldorm, Moldorm,
@ -22,6 +25,29 @@ pub enum BossType {
NoBoss = 255, NoBoss = 255,
} }
impl From<BossType> for u8 {
fn from(t: BossType) -> u8 {
use BossType::*;
match t {
Kholdstare => 0,
Moldorm => 1,
Mothula => 2,
Vitreous => 3,
Helmasaur => 4,
Armos => 5,
Lanmola => 6,
Blind => 7,
Arrghus => 8,
Trinexx => 9,
Agahnim => 10,
Agahnim2 => 11,
Ganon => 12,
NoBoss => 255,
}
}
}
impl TryFrom<u8> for BossType { impl TryFrom<u8> for BossType {
type Error = InvalidEnumError<Self>; type Error = InvalidEnumError<Self>;

View file

@ -3,10 +3,12 @@ use std::fmt;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::path::PathBuf; use std::path::PathBuf;
use serde::{Deserialize, Serialize};
use crate::bosses::BossType; use crate::bosses::BossType;
use crate::InvalidEnumError; use crate::InvalidEnumError;
#[derive(Debug, Default)] #[derive(Debug, Default, Deserialize, Serialize)]
pub struct ManualBosses { pub struct ManualBosses {
pub eastern_palace: String, pub eastern_palace: String,
pub desert_palace: String, pub desert_palace: String,
@ -26,7 +28,8 @@ pub struct ManualBosses {
pub ganon: String, pub ganon: String,
} }
#[derive(Debug)] #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[serde(into = "u8", try_from = "u8")]
pub enum RandomizeEnemiesType { pub enum RandomizeEnemiesType {
Basic, Basic,
Normal, Normal,
@ -35,6 +38,20 @@ pub enum RandomizeEnemiesType {
Insanity, Insanity,
} }
impl From<RandomizeEnemiesType> for u8 {
fn from(t: RandomizeEnemiesType) -> u8 {
use RandomizeEnemiesType::*;
match t {
Basic => 0,
Normal => 1,
Hard => 2,
Chaos => 3,
Insanity => 4,
}
}
}
impl TryFrom<u8> for RandomizeEnemiesType { impl TryFrom<u8> for RandomizeEnemiesType {
type Error = InvalidEnumError<Self>; type Error = InvalidEnumError<Self>;
@ -50,7 +67,8 @@ impl TryFrom<u8> for RandomizeEnemiesType {
} }
} }
#[derive(Debug)] #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[serde(into = "u8", try_from = "u8")]
pub enum RandomizeEnemyHpType { pub enum RandomizeEnemyHpType {
Easy, Easy,
Medium, Medium,
@ -58,6 +76,19 @@ pub enum RandomizeEnemyHpType {
Patty Patty
} }
impl From<RandomizeEnemyHpType> for u8 {
fn from(t: RandomizeEnemyHpType) -> u8 {
use RandomizeEnemyHpType::*;
match t {
Easy => 0,
Medium => 1,
Hard => 2,
Patty => 3,
}
}
}
impl TryFrom<u8> for RandomizeEnemyHpType { impl TryFrom<u8> for RandomizeEnemyHpType {
type Error = InvalidEnumError<Self>; type Error = InvalidEnumError<Self>;
@ -72,13 +103,26 @@ impl TryFrom<u8> for RandomizeEnemyHpType {
} }
} }
#[derive(Debug)] #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[serde(into = "u8", try_from = "u8")]
pub enum RandomizeBossesType { pub enum RandomizeBossesType {
Basic, Basic,
Normal, Normal,
Chaos Chaos
} }
impl From<RandomizeBossesType> for u8 {
fn from(t: RandomizeBossesType) -> u8 {
use RandomizeBossesType::*;
match t {
Basic => 0,
Normal => 1,
Chaos => 2,
}
}
}
impl TryFrom<u8> for RandomizeBossesType { impl TryFrom<u8> for RandomizeBossesType {
type Error = InvalidEnumError<Self>; type Error = InvalidEnumError<Self>;
@ -92,11 +136,18 @@ impl TryFrom<u8> for RandomizeBossesType {
} }
} }
#[derive(Debug)] #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[serde(into = "u8", try_from = "u8")]
pub enum SwordType { pub enum SwordType {
Normal Normal
} }
impl From<SwordType> for u8 {
fn from(_t: SwordType) -> u8 {
0
}
}
impl TryFrom<u8> for SwordType { impl TryFrom<u8> for SwordType {
type Error = InvalidEnumError<Self>; type Error = InvalidEnumError<Self>;
@ -108,11 +159,18 @@ impl TryFrom<u8> for SwordType {
} }
} }
#[derive(Debug)] #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[serde(into = "u8", try_from = "u8")]
pub enum ShieldType { pub enum ShieldType {
Normal Normal
} }
impl From<ShieldType> for u8 {
fn from(_t: ShieldType) -> u8 {
0
}
}
impl TryFrom<u8> for ShieldType { impl TryFrom<u8> for ShieldType {
type Error = InvalidEnumError<Self>; type Error = InvalidEnumError<Self>;
@ -124,7 +182,8 @@ impl TryFrom<u8> for ShieldType {
} }
} }
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[serde(into = "u8", try_from = "u8")]
pub enum AbsorbableType { pub enum AbsorbableType {
Heart, Heart,
GreenRupee, GreenRupee,
@ -142,6 +201,29 @@ pub enum AbsorbableType {
BigKey, BigKey,
} }
impl From<AbsorbableType> for u8 {
fn from(t: AbsorbableType) -> u8 {
use AbsorbableType::*;
match t {
Heart => 0,
GreenRupee => 1,
BlueRupee => 2,
RedRupee => 3,
Bomb1 => 4,
Bomb4 => 5,
Bomb8 => 6,
SmallMagic => 7,
FullMagic => 8,
Arrow5 => 9,
Arrow10 => 10,
Fairy => 11,
Key => 12,
BigKey => 13,
}
}
}
impl TryFrom<u8> for AbsorbableType { impl TryFrom<u8> for AbsorbableType {
type Error = InvalidEnumError<Self>; type Error = InvalidEnumError<Self>;
@ -150,16 +232,17 @@ impl TryFrom<u8> for AbsorbableType {
0 => Ok(Self::Heart), 0 => Ok(Self::Heart),
1 => Ok(Self::GreenRupee), 1 => Ok(Self::GreenRupee),
2 => Ok(Self::BlueRupee), 2 => Ok(Self::BlueRupee),
3 => Ok(Self::Bomb1), 3 => Ok(Self::RedRupee),
4 => Ok(Self::Bomb4), 4 => Ok(Self::Bomb1),
5 => Ok(Self::Bomb8), 5 => Ok(Self::Bomb4),
6 => Ok(Self::SmallMagic), 6 => Ok(Self::Bomb8),
7 => Ok(Self::FullMagic), 7 => Ok(Self::SmallMagic),
8 => Ok(Self::Arrow5), 8 => Ok(Self::FullMagic),
9 => Ok(Self::Arrow10), 9 => Ok(Self::Arrow5),
10 => Ok(Self::Fairy), 10 => Ok(Self::Arrow10),
11 => Ok(Self::Key), 11 => Ok(Self::Fairy),
12 => Ok(Self::BigKey), 12 => Ok(Self::Key),
13 => Ok(Self::BigKey),
_ => Err(InvalidEnumError(PhantomData)) _ => Err(InvalidEnumError(PhantomData))
} }
} }
@ -190,7 +273,8 @@ impl fmt::Display for AbsorbableType {
} }
} }
#[derive(Debug)] #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[serde(into = "u8", try_from = "u8")]
pub enum HeartBeepSpeed { pub enum HeartBeepSpeed {
Normal, Normal,
Half, Half,
@ -204,6 +288,19 @@ impl Default for HeartBeepSpeed {
} }
} }
impl From<HeartBeepSpeed> for u8 {
fn from(speed: HeartBeepSpeed) -> u8 {
use HeartBeepSpeed::*;
match speed {
Normal => 0,
Half => 1,
Quarter => 2,
Off => 3,
}
}
}
impl TryFrom<u8> for HeartBeepSpeed { impl TryFrom<u8> for HeartBeepSpeed {
type Error = InvalidEnumError<Self>; type Error = InvalidEnumError<Self>;
@ -218,7 +315,7 @@ impl TryFrom<u8> for HeartBeepSpeed {
} }
} }
#[derive(Debug)] #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub enum BeeLevel { pub enum BeeLevel {
Level1, Level1,
Level2, Level2,
@ -241,6 +338,19 @@ impl fmt::Display for BeeLevel {
} }
} }
impl From<BeeLevel> for u8 {
fn from(level: BeeLevel) -> u8 {
use BeeLevel::*;
match level {
Level1 => 0,
Level2 => 1,
Level3 => 2,
Level4 => 3,
}
}
}
impl TryFrom<u8> for BeeLevel { impl TryFrom<u8> for BeeLevel {
type Error = InvalidEnumError<Self>; type Error = InvalidEnumError<Self>;
@ -255,7 +365,7 @@ impl TryFrom<u8> for BeeLevel {
} }
} }
#[derive(Debug)] #[derive(Debug, Deserialize, Serialize)]
pub struct OptionFlags { pub struct OptionFlags {
pub randomize_enemies: bool, pub randomize_enemies: bool,
pub randomize_enemies_type: RandomizeEnemiesType, pub randomize_enemies_type: RandomizeEnemiesType,
@ -341,16 +451,17 @@ impl OptionFlags {
absorbable_types.insert(AbsorbableType::Heart, bytes[10] != 0); absorbable_types.insert(AbsorbableType::Heart, bytes[10] != 0);
absorbable_types.insert(AbsorbableType::GreenRupee, bytes[11] != 0); absorbable_types.insert(AbsorbableType::GreenRupee, bytes[11] != 0);
absorbable_types.insert(AbsorbableType::BlueRupee, bytes[12] != 0); absorbable_types.insert(AbsorbableType::BlueRupee, bytes[12] != 0);
absorbable_types.insert(AbsorbableType::Bomb1, bytes[13] != 0); absorbable_types.insert(AbsorbableType::RedRupee, bytes[13] != 0);
absorbable_types.insert(AbsorbableType::Bomb4, bytes[14] != 0); absorbable_types.insert(AbsorbableType::Bomb1, bytes[14] != 0);
absorbable_types.insert(AbsorbableType::Bomb8, bytes[15] != 0); absorbable_types.insert(AbsorbableType::Bomb4, bytes[15] != 0);
absorbable_types.insert(AbsorbableType::SmallMagic, bytes[16] != 0); absorbable_types.insert(AbsorbableType::Bomb8, bytes[16] != 0);
absorbable_types.insert(AbsorbableType::FullMagic, bytes[17] != 0); absorbable_types.insert(AbsorbableType::SmallMagic, bytes[17] != 0);
absorbable_types.insert(AbsorbableType::Arrow5, bytes[18] != 0); absorbable_types.insert(AbsorbableType::FullMagic, bytes[18] != 0);
absorbable_types.insert(AbsorbableType::Arrow10, bytes[19] != 0); absorbable_types.insert(AbsorbableType::Arrow5, bytes[19] != 0);
absorbable_types.insert(AbsorbableType::Fairy, bytes[20] != 0); absorbable_types.insert(AbsorbableType::Arrow10, bytes[20] != 0);
absorbable_types.insert(AbsorbableType::Key, bytes[21] != 0); absorbable_types.insert(AbsorbableType::Fairy, bytes[21] != 0);
absorbable_types.insert(AbsorbableType::BigKey, bytes[22] != 0); absorbable_types.insert(AbsorbableType::Key, bytes[21] != 1);
absorbable_types.insert(AbsorbableType::BigKey, bytes[23] != 0);
Ok(OptionFlags { Ok(OptionFlags {
randomize_enemies: bytes[0] != 0, randomize_enemies: bytes[0] != 0,
@ -364,55 +475,55 @@ impl OptionFlags {
enemies_absorbable: bytes[8] != 0, enemies_absorbable: bytes[8] != 0,
absorbable_spawn_rate: bytes[9], absorbable_spawn_rate: bytes[9],
absorbable_types, absorbable_types,
boss_madness: bytes[23] != 0, boss_madness: bytes[24] != 0,
randomize_bosses: bytes[24] != 0, randomize_bosses: bytes[25] != 0,
randomize_bosses_type: bytes[25].try_into()?, randomize_bosses_type: bytes[26].try_into()?,
randomize_boss_health: bytes[26] != 0, randomize_boss_health: bytes[27] != 0,
randomize_boss_health_min_amount: bytes[27], randomize_boss_health_min_amount: bytes[28],
randomize_boss_health_max_amount: bytes[28], randomize_boss_health_max_amount: bytes[29],
randomize_boss_damage: bytes[29] != 0, randomize_boss_damage: bytes[30] != 0,
randomize_boss_damage_min_amount: bytes[30], randomize_boss_damage_min_amount: bytes[31],
randomize_boss_damage_max_amount: bytes[31], randomize_boss_damage_max_amount: bytes[32],
randomize_boss_behavior: bytes[32] != 0, randomize_boss_behavior: bytes[33] != 0,
randomize_dungeon_palettes: bytes[33] != 0, randomize_dungeon_palettes: bytes[34] != 0,
set_blackout_mode: bytes[34] != 0, set_blackout_mode: bytes[35] != 0,
randomize_overworld_palettes: bytes[35] != 0, randomize_overworld_palettes: bytes[36] != 0,
randomize_sprite_palettes: bytes[36] != 0, randomize_sprite_palettes: bytes[37] != 0,
set_advanced_sprite_palettes: bytes[37] != 0, set_advanced_sprite_palettes: bytes[38] != 0,
puke_mode: bytes[38] != 0, puke_mode: bytes[39] != 0,
negative_mode: bytes[39] != 0, negative_mode: bytes[40] != 0,
grayscale_mode: bytes[40] != 0, grayscale_mode: bytes[41] != 0,
generate_spoilers: bytes[41] != 0, generate_spoilers: bytes[42] != 0,
randomize_link_sprite_palette: bytes[42] != 0, randomize_link_sprite_palette: bytes[43] != 0,
randomize_pots: bytes[43] != 0, randomize_pots: bytes[44] != 0,
shuffle_music: bytes[44] != 0, shuffle_music: bytes[45] != 0,
bootleg_magic: bytes[45] != 0, bootleg_magic: bytes[46] != 0,
debug_mode: bytes[46] != 0, debug_mode: bytes[47] != 0,
custom_bosses: bytes[47] != 0, custom_bosses: bytes[48] != 0,
heart_beep_speed: bytes[48].try_into()?, heart_beep_speed: bytes[49].try_into()?,
alternate_gfx: bytes[49] != 0, alternate_gfx: bytes[50] != 0,
// Skip byte 50 (shield_graphics) // Skip byte 51 (shield_graphics)
shuffle_enemy_damage_groups: bytes[51] != 0, shuffle_enemy_damage_groups: bytes[52] != 0,
enemy_damage_chaos_mode: bytes[52] != 0, enemy_damage_chaos_mode: bytes[53] != 0,
// Skip byte 53 (sword_graphics) // Skip byte 54 (sword_graphics)
bee_mizer: bytes[54] != 0, bee_mizer: bytes[55] != 0,
bees_level: bytes[55].try_into()?, bees_level: bytes[56].try_into()?,
debug_force_enemy: bytes[56] != 0, debug_force_enemy: bytes[57] != 0,
debug_force_enemy_id: bytes[57], debug_force_enemy_id: bytes[58],
debug_force_boss: bytes[58] != 0, debug_force_boss: bytes[59] != 0,
debug_force_boss_id: bytes[59].try_into()?, debug_force_boss_id: bytes[60].try_into()?,
debug_open_shutter_doors: bytes[60] != 0, debug_open_shutter_doors: bytes[61] != 0,
debug_force_enemy_damage_zero: bytes[61] != 0, debug_force_enemy_damage_zero: bytes[62] != 0,
debug_show_room_id_in_rupee_counter: bytes[62] != 0, debug_show_room_id_in_rupee_counter: bytes[63] != 0,
o_h_k_o: bytes[63] != 0, o_h_k_o: bytes[64] != 0,
randomize_tile_trap_pattern: bytes[64] != 0, randomize_tile_trap_pattern: bytes[65] != 0,
randomize_tile_trap_floor_tile: bytes[65] != 0, randomize_tile_trap_floor_tile: bytes[66] != 0,
allow_killable_thief: bytes[66] != 0, allow_killable_thief: bytes[67] != 0,
randomize_sprite_on_hit: bytes[67] != 0, randomize_sprite_on_hit: bytes[68] != 0,
hero_mode: bytes[68] != 0, hero_mode: bytes[69] != 0,
increase_brightness: bytes[69] != 0, increase_brightness: bytes[70] != 0,
mute_music_enable_msu_1: bytes[70] != 0, mute_music_enable_msu_1: bytes[71] != 0,
agahnim_bounce_balls: bytes[71] != 0, agahnim_bounce_balls: bytes[72] != 0,
..Default::default() ..Default::default()
}) })
} }