#![allow(dead_code)] use std::collections::HashMap; use std::convert::Into; use serde::{Serialize, Deserialize}; use libpso::character::settings; use libpso::util::vec_to_array; use crate::entity::account::*; use crate::entity::character::*; use crate::entity::item::*; use crate::entity::room::*; use crate::ship::map::MapArea; use crate::ship::room::{Episode, Difficulty}; use crate::ship::monster::MonsterType; #[derive(Debug, sqlx::FromRow)] pub struct PgUserAccount { id: i32, username: String, password: String, banned: Option>, muted: Option>, created_at: chrono::DateTime, flags: i32, activated: bool, at_login: bool, at_character: bool, at_ship: bool, } impl From for UserAccountEntity { fn from(other: PgUserAccount) -> UserAccountEntity { UserAccountEntity { id: UserAccountId(other.id as u32), username: other.username, password: other.password, banned_until: other.banned, muted_until: other.muted, created_at: other.created_at, flags: other.flags as u32, guildcard: other.id as u32 + 1, team_id: None, activated: other.activated, at_login: other.at_login, at_character: other.at_character, at_ship: other.at_ship, } } } #[derive(Debug, sqlx::FromRow)] pub struct PgUserSettings { id: i32, user_account: i32, blocked_users: Vec, //[u32; 0x1E], key_config: Vec, //[u8; 0x16C], joystick_config: Vec, //[u8; 0x38], option_flags: i32, shortcuts: Vec, //[u8; 0xA40], symbol_chats: Vec, //[u8; 0x4E0], team_name: Vec, //[u16; 0x10], } impl From for UserSettingsEntity { fn from(other: PgUserSettings) -> UserSettingsEntity { UserSettingsEntity { id: UserSettingsId(other.id as u32), user_id: UserAccountId(other.user_account as u32), settings: settings::UserSettings { blocked_users: vec_to_array(other.blocked_users.chunks(4).map(|b| u32::from_le_bytes([b[0], b[1], b[2], b[3]])).collect()), keyboard_config: vec_to_array(other.key_config), gamepad_config: vec_to_array(other.joystick_config), option_flags: other.option_flags as u32, shortcuts: vec_to_array(other.shortcuts), symbol_chats: vec_to_array(other.symbol_chats), team_name: vec_to_array(other.team_name.chunks(2).map(|b| u16::from_le_bytes([b[0], b[1]])).collect()), } } } } #[derive(sqlx::Type, Debug)] #[sqlx(rename_all = "lowercase")] pub enum PgCharacterClass { HUmar, HUnewearl, HUcast, HUcaseal, RAmar, RAmarl, RAcast, RAcaseal, FOmar, FOmarl, FOnewm, FOnewearl, } impl From for CharacterClass { fn from(other: PgCharacterClass) -> CharacterClass { match other{ PgCharacterClass::HUmar => CharacterClass::HUmar, PgCharacterClass::HUnewearl => CharacterClass::HUnewearl, PgCharacterClass::HUcast => CharacterClass::HUcast, PgCharacterClass::HUcaseal => CharacterClass::HUcaseal, PgCharacterClass::RAmar => CharacterClass::RAmar, PgCharacterClass::RAmarl => CharacterClass::RAmarl, PgCharacterClass::RAcast => CharacterClass::RAcast, PgCharacterClass::RAcaseal => CharacterClass::RAcaseal, PgCharacterClass::FOmar => CharacterClass::FOmar, PgCharacterClass::FOmarl => CharacterClass::FOmarl, PgCharacterClass::FOnewm => CharacterClass::FOnewm, PgCharacterClass::FOnewearl => CharacterClass::FOnewearl, } } } impl From for PgCharacterClass { fn from(other: CharacterClass) -> PgCharacterClass { match other { CharacterClass::HUmar => PgCharacterClass::HUmar, CharacterClass::HUnewearl => PgCharacterClass::HUnewearl, CharacterClass::HUcast => PgCharacterClass::HUcast, CharacterClass::HUcaseal => PgCharacterClass::HUcaseal, CharacterClass::RAmar => PgCharacterClass::RAmar, CharacterClass::RAmarl => PgCharacterClass::RAmarl, CharacterClass::RAcast => PgCharacterClass::RAcast, CharacterClass::RAcaseal => PgCharacterClass::RAcaseal, CharacterClass::FOmar => PgCharacterClass::FOmar, CharacterClass::FOmarl => PgCharacterClass::FOmarl, CharacterClass::FOnewm => PgCharacterClass::FOnewm, CharacterClass::FOnewearl => PgCharacterClass::FOnewearl, } } } #[derive(sqlx::Type, Debug)] #[sqlx(rename_all = "lowercase")] pub enum PgSectionId { Viridia, Greenill, Skyly, Bluefull, Purplenum, Pinkal, Redria, Oran, Yellowboze, Whitill, } impl From for SectionID { fn from(other: PgSectionId) -> SectionID { match other { PgSectionId::Viridia => SectionID::Viridia, PgSectionId::Greenill => SectionID::Greenill, PgSectionId::Skyly => SectionID::Skyly, PgSectionId::Bluefull => SectionID::Bluefull, PgSectionId::Purplenum => SectionID::Purplenum, PgSectionId::Pinkal => SectionID::Pinkal, PgSectionId::Redria => SectionID::Redria, PgSectionId::Oran => SectionID::Oran, PgSectionId::Yellowboze => SectionID::Yellowboze, PgSectionId::Whitill => SectionID::Whitill, } } } impl From for PgSectionId { fn from(other: SectionID) -> PgSectionId { match other { SectionID::Viridia => PgSectionId::Viridia, SectionID::Greenill => PgSectionId::Greenill, SectionID::Skyly => PgSectionId::Skyly, SectionID::Bluefull => PgSectionId::Bluefull, SectionID::Purplenum => PgSectionId::Purplenum, SectionID::Pinkal => PgSectionId::Pinkal, SectionID::Redria => PgSectionId::Redria, SectionID::Oran => PgSectionId::Oran, SectionID::Yellowboze => PgSectionId::Yellowboze, SectionID::Whitill => PgSectionId::Whitill, } } } #[derive(Debug, sqlx::FromRow)] pub struct PgCharacter { pub id: i32, user_account: i32, pub slot: i16, name: String, exp: i32, class: String, section_id: String, costume: i16, skin: i16, face: i16, head: i16, hair: i16, hair_r: i16, hair_g: i16, hair_b: i16, prop_x: f32, prop_y: f32, techs: Vec, config: Vec, infoboard: String, guildcard: String, option_flags: i32, power: i16, mind: i16, def: i16, evade: i16, luck: i16, hp: i16, tp: i16, tech_menu: Vec, playtime: i32, } impl From for CharacterEntity { fn from(other: PgCharacter) -> CharacterEntity { CharacterEntity { id: CharacterEntityId(other.id as u32), user_id: UserAccountId(other.user_account as u32), slot: other.slot as u32, name: other.name, exp: other.exp as u32, char_class: other.class.parse().unwrap(), section_id: other.section_id.parse().unwrap(), appearance: CharacterAppearance { costume: other.costume as u16, skin: other.skin as u16, face: other.face as u16, head: other.head as u16, hair: other.hair as u16, hair_r: other.hair_r as u16, hair_g: other.hair_g as u16, hair_b: other.hair_b as u16, prop_x: other.prop_x, prop_y: other.prop_y, }, techs: CharacterTechniques { techs: other.techs.iter().enumerate().take(19).filter(|(_, t)| **t != 0xFF).map(|(i, t)| (tech::Technique::from_value(i as u8), TechLevel(*t + 1)) ).collect() }, config: CharacterConfig { raw_data: vec_to_array(other.config) }, info_board: CharacterInfoboard { board: libpso::utf8_to_utf16_array!(other.infoboard, 172), }, guildcard: CharacterGuildCard { description: other.guildcard, }, option_flags: other.option_flags as u32, materials: CharacterMaterials { power: other.power as u32, mind: other.mind as u32, def: other.def as u32, evade: other.evade as u32, luck: other.luck as u32, hp: other.hp as u32, tp: other.tp as u32, }, tech_menu: CharacterTechMenu { tech_menu: vec_to_array(other.tech_menu) }, playtime: other.playtime as u32, } } } #[derive(Debug, sqlx::FromRow)] pub struct PgGuildCard { } #[derive(Debug, Serialize, Deserialize)] pub struct PgWeapon { weapon: weapon::WeaponType, special: Option, grind: u8, attrs: HashMap, tekked: bool, } impl From for PgWeapon { fn from(other: weapon::Weapon) -> PgWeapon { PgWeapon { weapon: other.weapon, special: other.special, grind: other.grind, attrs: other.attrs.iter().flatten().map(|attr| (attr.attr, attr.value)).collect(), tekked: other.tekked, } } } impl From for weapon::Weapon { fn from(other: PgWeapon) -> weapon::Weapon { let mut attrs: [Option; 3] = [None; 3]; for (attr, (atype, value)) in attrs.iter_mut().zip(other.attrs.iter()) { *attr = Some(weapon::WeaponAttribute { attr: *atype, value: *value }); } weapon::Weapon { weapon: other.weapon, special: other.special, grind: other.grind, attrs, tekked: other.tekked, } } } #[derive(Debug, sqlx::FromRow)] pub struct PgWeaponModifier { pub weapon: i32, pub modifier: sqlx::types::Json, } #[derive(Debug, Serialize, Deserialize)] pub struct PgArmor { armor: armor::ArmorType, dfp: u8, evp: u8, slots: u8, } impl From for PgArmor { fn from(other: armor::Armor) -> PgArmor { PgArmor { armor: other.armor, dfp: other.dfp, evp: other.evp, slots: other.slots, } } } impl From for armor::Armor { fn from(other: PgArmor) -> armor::Armor { armor::Armor { armor: other.armor, dfp: other.dfp, evp: other.evp, slots: other.slots, } } } #[derive(Debug, Serialize, Deserialize)] pub struct PgShield { shield: shield::ShieldType, dfp: u8, evp: u8, } impl From for PgShield { fn from(other: shield::Shield) -> PgShield { PgShield { shield: other.shield, dfp: other.dfp, evp: other.evp, } } } impl From for shield::Shield { fn from(other: PgShield) -> shield::Shield { shield::Shield { shield: other.shield, dfp: other.dfp, evp: other.evp, } } } #[derive(Debug, Serialize, Deserialize)] pub struct PgUnit { unit: unit::UnitType, modifier: Option, } impl From for PgUnit { fn from(other: unit::Unit) -> PgUnit { PgUnit { unit: other.unit, modifier: other.modifier, } } } impl From for unit::Unit { fn from(other: PgUnit) -> unit::Unit { unit::Unit { unit: other.unit, modifier: other.modifier, } } } #[derive(Debug, Serialize, Deserialize)] pub struct PgTool { pub tool: tool::ToolType, } impl From for PgTool { fn from(other: tool::Tool) -> PgTool { PgTool { tool: other.tool, } } } impl From for tool::Tool { fn from(other: PgTool) -> tool::Tool { tool::Tool { tool: other.tool, } } } #[derive(Debug, Serialize, Deserialize)] pub struct PgTechDisk { tech: tech::Technique, level: u32, } impl From for PgTechDisk { fn from(other: tech::TechniqueDisk) -> PgTechDisk { PgTechDisk { tech: other.tech, level: other.level, } } } impl From for tech::TechniqueDisk { fn from(other: PgTechDisk) -> tech::TechniqueDisk { tech::TechniqueDisk { tech: other.tech, level: other.level } } } #[derive(Debug, Serialize, Deserialize)] pub struct PgMag { mag: mag::MagType, synchro: u8, color: u8, } impl From for PgMag { fn from(other: mag::Mag) -> PgMag { PgMag { mag: other.mag, synchro: other.synchro, color: other.color, } } } impl From for mag::Mag { fn from(other: PgMag) -> mag::Mag { /*mag::Mag { mag: self.mag, synchro: self.synchro, color: self.color, def: 500, pow: 0, dex: 0, mnd: 0, iq: 0, photon_blast: [None; 3], class: CharacterClass::HUmar, id: SectionID::Viridia, }*/ let mut mag = mag::Mag::baby_mag(other.color as u16); mag.mag = other.mag; mag.synchro = other.synchro; mag } } #[derive(Debug, Serialize, Deserialize)] pub struct PgESWeapon { esweapon: esweapon::ESWeaponType, special: Option, name: String, grind: u8, } impl From for PgESWeapon { fn from(other: esweapon::ESWeapon) -> PgESWeapon { PgESWeapon { esweapon: other.esweapon, special: other.special, name: other.name, grind: other.grind, } } } impl From for esweapon::ESWeapon { fn from(other: PgESWeapon) -> esweapon::ESWeapon { esweapon::ESWeapon { esweapon: other.esweapon, special: other.special, name: other.name, grind: other.grind, } } } #[derive(Debug, Serialize, Deserialize)] pub enum PgItemDetail { Weapon(PgWeapon), Armor(PgArmor), Shield(PgShield), Unit(PgUnit), Tool(PgTool), TechDisk(PgTechDisk), Mag(PgMag), ESWeapon(PgESWeapon), } impl From for PgItemDetail { fn from(other: ItemDetail) -> PgItemDetail { match other { ItemDetail::Weapon(weapon) => PgItemDetail::Weapon(weapon.into()), ItemDetail::Armor(armor) => PgItemDetail::Armor(armor.into()), ItemDetail::Shield(shield) => PgItemDetail::Shield(shield.into()), ItemDetail::Unit(unit) => PgItemDetail::Unit(unit.into()), ItemDetail::Tool(tool) => PgItemDetail::Tool(tool.into()), ItemDetail::TechniqueDisk(tech_disk) => PgItemDetail::TechDisk(tech_disk.into()), ItemDetail::Mag(mag) => PgItemDetail::Mag(mag.into()), ItemDetail::ESWeapon(esweapon) => PgItemDetail::ESWeapon(esweapon.into()), } } } impl From for ItemDetail { fn from(other: PgItemDetail) -> ItemDetail { match other { PgItemDetail::Weapon(weapon) => ItemDetail::Weapon(weapon.into()), PgItemDetail::Armor(armor) => ItemDetail::Armor(armor.into()), PgItemDetail::Shield(shield) => ItemDetail::Shield(shield.into()), PgItemDetail::Unit(unit) => ItemDetail::Unit(unit.into()), PgItemDetail::Tool(tool) => ItemDetail::Tool(tool.into()), PgItemDetail::TechDisk(tech_disk) => ItemDetail::TechniqueDisk(tech_disk.into()), PgItemDetail::Mag(mag) => ItemDetail::Mag(mag.into()), PgItemDetail::ESWeapon(esweapon) => ItemDetail::ESWeapon(esweapon.into()), } } } #[derive(Debug, sqlx::FromRow)] pub struct PgItem { pub id: i32, pub item: sqlx::types::Json, } #[derive(Debug, Serialize, Deserialize)] pub enum PgItemNoteDetail { CharacterCreation { character_id: u32, }, EnemyDrop { character_id: u32, room_id: u32, monster_type: MonsterType, map_area: MapArea, x: f32, y: f32, z: f32, }, BoxDrop { character_id: u32, room_id: u32, map_area: MapArea, x: f32, y: f32, z: f32, }, Pickup { character_id: u32, }, PlayerDrop { character_id: u32, map_area: MapArea, x: f32, y: f32, z: f32, }, Consumed { character_id: u32, }, FedToMag { character_id: u32, mag: u32, }, BoughtAtShop { character_id: u32, }, SoldToShop { character_id: u32, }, Trade { trade_id: u32, character_to: u32, character_from: u32, }, Withdraw { character_id: u32, bank: BankIdentifier, }, Deposit { character_id: u32, bank: BankIdentifier, }, FloorLimitReached { map_area: MapArea, } } impl From for PgItemNoteDetail { fn from(other: ItemNote) -> PgItemNoteDetail { match other { ItemNote::CharacterCreation{character_id} => PgItemNoteDetail::CharacterCreation { character_id: character_id.0, }, ItemNote::EnemyDrop{character_id, room_id, monster_type, map_area, x, y, z} => PgItemNoteDetail::EnemyDrop { character_id: character_id.0, room_id: room_id.0, monster_type, map_area, x,y,z, }, ItemNote::BoxDrop{character_id, room_id, map_area, x, y, z} => PgItemNoteDetail::BoxDrop { character_id: character_id.0, room_id: room_id.0, map_area, x,y,z, }, ItemNote::Pickup{character_id} => PgItemNoteDetail::Pickup { character_id: character_id.0, }, ItemNote::PlayerDrop{character_id, map_area, x, y, z} => PgItemNoteDetail::PlayerDrop { character_id: character_id.0, map_area, x,y,z, }, ItemNote::Consumed{character_id} => PgItemNoteDetail::Consumed { character_id: character_id.0, }, ItemNote::FedToMag{character_id, mag} => PgItemNoteDetail::FedToMag{ character_id: character_id.0, mag: mag.0 }, ItemNote::BoughtAtShop{character_id} => PgItemNoteDetail::BoughtAtShop { character_id: character_id.0, }, ItemNote::SoldToShop{character_id} => PgItemNoteDetail::SoldToShop { character_id: character_id.0, }, ItemNote::Trade{trade_id, character_to, character_from} => PgItemNoteDetail::Trade { trade_id: trade_id.0, character_to: character_to.0, character_from: character_from.0, }, ItemNote::Withdraw{character_id, bank} => { PgItemNoteDetail::Withdraw { character_id: character_id.0, bank, } }, ItemNote::Deposit{character_id, bank} => { PgItemNoteDetail::Deposit { character_id: character_id.0, bank, } }, ItemNote::FloorLimitReached { map_area } => { PgItemNoteDetail::FloorLimitReached { map_area, } }, } } } impl From for ItemNote { fn from(other: PgItemNoteDetail) -> ItemNote { match other { PgItemNoteDetail::CharacterCreation{character_id} => ItemNote::CharacterCreation { character_id: CharacterEntityId(character_id), }, PgItemNoteDetail::EnemyDrop{character_id, room_id, monster_type, map_area, x, y, z} => ItemNote::EnemyDrop { character_id: CharacterEntityId(character_id), room_id: RoomEntityId(room_id), monster_type, map_area, x,y,z, }, PgItemNoteDetail::BoxDrop{character_id, room_id, map_area, x, y, z} => ItemNote::BoxDrop { character_id: CharacterEntityId(character_id), room_id: RoomEntityId(room_id), map_area, x,y,z, }, PgItemNoteDetail::Pickup{character_id} => ItemNote::Pickup { character_id: CharacterEntityId(character_id), }, PgItemNoteDetail::PlayerDrop{character_id, map_area, x, y, z} => ItemNote::PlayerDrop { character_id: CharacterEntityId(character_id), map_area, x,y,z, }, PgItemNoteDetail::Consumed{character_id} => ItemNote::Consumed { character_id: CharacterEntityId(character_id), }, PgItemNoteDetail::FedToMag{character_id, mag} => ItemNote::FedToMag{ character_id: CharacterEntityId(character_id), mag: ItemEntityId(mag) }, PgItemNoteDetail::BoughtAtShop{character_id} => ItemNote::BoughtAtShop { character_id: CharacterEntityId(character_id), }, PgItemNoteDetail::SoldToShop{character_id} => ItemNote::SoldToShop { character_id: CharacterEntityId(character_id), }, PgItemNoteDetail::Trade {trade_id, character_to, character_from} => ItemNote::Trade { trade_id: TradeId(trade_id), character_to: CharacterEntityId(character_to), character_from: CharacterEntityId(character_from), }, PgItemNoteDetail::Withdraw{character_id, bank} => ItemNote::Withdraw { character_id: CharacterEntityId(character_id), bank, }, PgItemNoteDetail::Deposit{character_id, bank} => ItemNote::Deposit { character_id: CharacterEntityId(character_id), bank, }, PgItemNoteDetail::FloorLimitReached { map_area } => ItemNote::FloorLimitReached { map_area, }, } } } #[derive(Debug, sqlx::FromRow)] pub struct PgItemNote { //pub id: i32, pub note: sqlx::types::Json, created_at: chrono::DateTime, } #[derive(Debug, Serialize, Deserialize)] pub enum PgMagModifierDetail { FeedMag(i32), BankMag, MagCell(i32), OwnerChange(CharacterClass, SectionID) } impl From for PgMagModifierDetail { fn from(other: mag::MagModifier) -> PgMagModifierDetail { match other { mag::MagModifier::FeedMag{food} => PgMagModifierDetail::FeedMag(food.0 as i32), mag::MagModifier::BankMag => PgMagModifierDetail::BankMag, mag::MagModifier::MagCell(cell) => PgMagModifierDetail::MagCell(cell.0 as i32), mag::MagModifier::OwnerChange(class, section_id) => PgMagModifierDetail::OwnerChange(class, section_id), } } } impl From for mag::MagModifier { fn from(other: PgMagModifierDetail) -> mag::MagModifier { match other { PgMagModifierDetail::FeedMag(food) => mag::MagModifier::FeedMag{food: ItemEntityId(food as u32)}, PgMagModifierDetail::BankMag => mag::MagModifier::BankMag, PgMagModifierDetail::MagCell(cell) => mag::MagModifier::MagCell(ItemEntityId(cell as u32)), PgMagModifierDetail::OwnerChange(class, section_id) => mag::MagModifier::OwnerChange(class, section_id), } } } #[derive(Debug, sqlx::FromRow)] pub struct PgMagModifier { mag: i32, pub modifier: sqlx::types::Json, created_at: chrono::DateTime, } #[derive(Debug, sqlx::FromRow)] pub struct PgItemEntity { pub id: i32, pub item: sqlx::types::Json, } /* #[derive(Debug, sqlx::FromRow)] pub struct PgItemWithLocation { pub id: i32, pub item: sqlx::types::Json, pub location: sqlx::types::Json, } */ impl From for ItemEntity { fn from(other: PgItemEntity) -> ItemEntity { ItemEntity { id: ItemEntityId(other.id as u32), item: other.item.0.into(), } } } #[derive(Debug, sqlx::FromRow)] pub struct PgMagModifierWithParameters { pub mag: i32, pub modifier: sqlx::types::Json, pub feed: Option>, pub cell: Option>, } #[derive(Debug, Serialize, Deserialize)] #[serde(untagged)] pub enum PgInventoryItemEntity { Individual(i32), Stacked(Vec), } #[derive(Debug, sqlx::FromRow)] pub struct PgInventoryEntity { pub pchar: i32, pub items: sqlx::types::Json>, } #[derive(Debug, sqlx::FromRow)] pub struct PgBankEntity { pub pchar: i32, pub items: sqlx::types::Json>, pub name: String, } #[derive(Debug, sqlx::FromRow)] pub struct PgEquipped { pchar: i32, weapon: Option, armor: Option, shield: Option, unit0: Option, unit1: Option, unit2: Option, unit3: Option, mag: Option, } impl From for EquippedEntity{ fn from(other: PgEquipped) -> EquippedEntity { EquippedEntity { weapon: other.weapon.map(|i| ItemEntityId(i as u32)), armor: other.armor.map(|i| ItemEntityId(i as u32)), shield: other.shield.map(|i| ItemEntityId(i as u32)), unit: [other.unit0.map(|i| ItemEntityId(i as u32)), other.unit1.map(|i| ItemEntityId(i as u32)), other.unit2.map(|i| ItemEntityId(i as u32)), other.unit3.map(|i| ItemEntityId(i as u32)), ], mag: other.mag.map(|i| ItemEntityId(i as u32)), } } } impl From<(CharacterEntityId, EquippedEntity)> for PgEquipped { fn from(char_equips: (CharacterEntityId, EquippedEntity)) -> PgEquipped { PgEquipped { pchar: (char_equips.0).0 as i32, weapon: char_equips.1.weapon.map(|i| i.0 as i32), armor: char_equips.1.armor.map(|i| i.0 as i32), shield: char_equips.1.shield.map(|i| i.0 as i32), unit0: char_equips.1.unit[0].map(|i| i.0 as i32), unit1: char_equips.1.unit[1].map(|i| i.0 as i32), unit2: char_equips.1.unit[2].map(|i| i.0 as i32), unit3: char_equips.1.unit[3].map(|i| i.0 as i32), mag: char_equips.1.mag.map(|i| i.0 as i32), } } } #[derive(Debug, sqlx::FromRow)] pub struct PgTradeEntity { id: i32, character1: i32, character2: i32, } impl From for TradeEntity { fn from(other: PgTradeEntity) -> TradeEntity { TradeEntity { id: TradeId(other.id as u32), character1: CharacterEntityId(other.character1 as u32), character2: CharacterEntityId(other.character2 as u32), } } } #[derive(Debug, sqlx::FromRow, Serialize)] pub struct PgRoomEntity { id: i32, name: String, section_id: i8, mode: i8, episode: i8, difficulty: i8, } impl From for RoomEntity { fn from(other: PgRoomEntity) -> RoomEntity { RoomEntity { id: RoomEntityId(other.id as u32), name: other.name, section_id: SectionID::from(other.section_id as u8), mode: RoomEntityMode::from(other.mode as u8), episode: Episode::try_from(other.episode as u8).unwrap(), difficulty: Difficulty::try_from(other.difficulty as u8).unwrap(), } } }