pub mod everest;
pub mod mods;
pub mod session;
pub mod util;
pub mod vanilla;
use std::marker::PhantomData;
use everest::*;
use serde::{de::Visitor, Deserialize, Deserializer, Serialize};
use session::*;
use util::*;
use vanilla::*;
use chrono::NaiveDateTime;
pub type AreaCount = i16;
pub type StrawberryCount = u16;
pub type DeathCount = u64;
pub type DashCount = u64;
pub type JumpCount = u64;
pub type AreaId = u16;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SaveData {
#[doc(hidden)]
#[serde(rename = "@xmlns:xsi")]
xsi_url: String,
#[doc(hidden)]
#[serde(rename(serialize = "@xmlns:xsd", deserialize = "@xmlns:xsd"))]
xsd_url: String,
#[serde(rename = "Version")]
pub version: String,
#[serde(rename = "Name")]
pub name: String,
#[serde(rename = "Time")]
pub time: FileTime,
#[serde(rename = "LastSave")]
pub last_save: NaiveDateTime,
#[serde(rename = "CheatMode")]
pub cheat_mode: bool,
#[serde(rename = "AssistMode")]
pub assist_mode: bool,
#[serde(rename = "VariantMode")]
pub variant_mode: bool,
#[serde(rename = "Assists")]
pub assists: Assists,
#[serde(rename = "TheoSisterName")]
pub theo_sister_name: String,
#[serde(rename = "UnlockedAreas")]
pub unlocked_areas: AreaCount,
#[serde(rename = "TotalDeaths")]
pub total_deaths: DeathCount,
#[serde(rename = "TotalStrawberries")]
pub total_strawberries: StrawberryCount,
#[serde(rename = "TotalGoldenStrawberries")]
pub total_golden_strawberries: StrawberryCount,
#[serde(rename = "TotalJumps")]
pub total_jumps: JumpCount,
#[serde(rename = "TotalWallJumps")]
pub total_wall_jumps: JumpCount,
#[serde(rename = "TotalDashes")]
pub total_dashes: DashCount,
#[serde(rename = "Flags")]
pub flags: Flags,
#[serde(rename = "Poem")]
pub poem: Poem,
#[serde(rename = "SummitGems")]
#[serde(skip_serializing_if = "Option::is_none")]
pub summit_gems: Option<SummitGems>,
#[serde(rename = "RevealedChapter9")]
pub revealed_farewell: bool,
#[serde(rename = "LastArea")]
pub last_area: AreaRef,
#[serde(rename = "CurrentSession")]
#[serde(skip_serializing_if = "Option::is_none")]
pub current_session: Option<SavedSession>,
#[serde(rename = "Areas")]
pub areas: Areas,
#[serde(rename = "LevelSets")]
#[serde(default)]
#[serde(skip_serializing_if = "LevelSets::is_inner_empty")]
pub level_sets: LevelSets,
#[serde(rename = "LevelSetRecycleBin")]
#[serde(default)]
#[serde(skip_serializing_if = "LevelSets::is_inner_empty")]
pub level_set_recycle_bin: LevelSets,
#[serde(rename = "HasModdedSaveData")]
#[serde(default)]
pub has_modded_save_data: bool,
#[serde(rename = "LastArea_Safe")]
#[serde(skip_serializing_if = "Option::is_none")]
pub last_area_safe: Option<AreaRef>,
#[serde(rename = "CurrentSession_Safe")]
#[serde(skip_serializing_if = "Option::is_none")]
pub current_session_safe: Option<SavedSession>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ModSaveData {
#[doc(hidden)]
#[serde(rename(serialize = "@xmlns:xsi", deserialize = "@xmlns:xsi"))]
xsi_url: String,
#[doc(hidden)]
#[serde(rename(serialize = "@xmlns:xsd", deserialize = "@xmlns:xsd"))]
xsd_url: String,
#[serde(rename = "LevelSets")]
#[serde(default)]
#[serde(skip_serializing_if = "LevelSets::is_inner_empty")]
pub level_sets: LevelSets,
#[serde(rename = "LevelSetRecycleBin")]
#[serde(default)]
#[serde(skip_serializing_if = "LevelSets::is_inner_empty")]
pub level_set_recycle_bin: LevelSets,
#[serde(rename = "LastArea_Safe")]
#[serde(skip_serializing_if = "Option::is_none")]
pub last_area_safe: Option<AreaRef>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Assists {
#[serde(rename = "GameSpeed")]
pub game_speed: u8,
#[serde(rename = "Invincible")]
pub invincible: bool,
#[serde(rename = "DashMode")]
pub dash_mode: DashMode,
#[serde(rename = "DashAssist")]
pub dash_assist: bool,
#[serde(rename = "InfiniteStamina")]
pub infinite_stamina: bool,
#[serde(rename = "MirrorMode")]
pub mirror_mode: bool,
#[serde(rename = "ThreeSixtyDashing")]
pub full_dashing: bool,
#[serde(rename = "InvisibleMotion")]
pub invisible_motion: bool,
#[serde(rename = "NoGrabbing")]
pub no_grabbing: bool,
#[serde(rename = "LowFriction")]
pub low_friction: bool,
#[serde(rename = "SuperDashing")]
pub super_dash: bool,
#[serde(rename = "Hiccups")]
pub hiccups: bool,
#[serde(rename = "PlayAsBadeline")]
pub badeline: bool,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
pub enum DashMode {
Normal,
Two,
Infinite,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Flags {
#[serde(default)]
#[serde(rename = "string")]
#[serde(deserialize_with = "xsi_nil_weird_list_deserialization")]
pub(crate) flags: Vec<VanillaFlagsWrapper>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
pub struct VanillaFlagsWrapper {
#[serde(rename = "$text")]
pub(crate) flag: VanillaFlags,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Poem {
#[serde(default)]
pub(crate) string: Vec<String>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
pub enum VanillaFlags {
MetTheo,
TheoKnowsName,
}
fn xsi_nil_weird_list_deserialization<'de, D, T: Deserialize<'de> + 'de>(
deserializer: D,
) -> Result<Vec<T>, D::Error>
where D: Deserializer<'de> {
deserializer.deserialize_seq(WeirdSeqVisitor {
__de_lifetime: PhantomData,
})
}
#[derive(Default)]
struct WeirdSeqVisitor<'de, T: Deserialize<'de>> {
__de_lifetime: PhantomData<&'de T>,
}
impl<'de, T: Deserialize<'de>> Visitor<'de> for WeirdSeqVisitor<'de, T> {
type Value = Vec<T>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "A list of Deserialize elements")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where A: serde::de::SeqAccess<'de> {
let mut vec = Vec::new();
loop {
if let Ok(val) = seq.next_element() {
match val {
Some(v) => vec.push(v),
None => break,
}
}
}
Ok(vec)
}
}