add tools

This commit is contained in:
amizing25 2024-03-29 16:49:57 +07:00
parent 7c1d485ad5
commit 1681485ccb
7 changed files with 11746 additions and 83 deletions

10831
freesr-data.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,47 +1,151 @@
use super::*;
use crate::net::tools::{self, BattleType, Monster};
static BATTLE_LINEUP: [u32; 4] = [1309, 1308, 1307, 1315];
use super::*;
pub async fn on_start_cocoon_stage_cs_req(
session: &mut PlayerSession,
body: &StartCocoonStageCsReq,
) -> Result<()> {
let player = tools::JsonData::load().await;
let mut battle_info = SceneBattleInfo {
stage_id: player.battle_config.stage_id,
logic_random_seed: 4444,
battle_id: 1,
kimmjioaodn: player.battle_config.cycle_count,
..Default::default()
};
// avatars
for i in 0..4 {
let avatar_id = &player.lineups.get(&i).unwrap_or(&0);
if **avatar_id == 0 {
continue;
}
if let Some(avatar) = player.avatars.get(&avatar_id) {
let (battle_avatar, techs) = avatar.to_battle_avatar_proto(
i,
player
.lightcones
.iter()
.find(|v| v.equip_avatar == avatar.avatar_id),
player
.relics
.iter()
.filter(|v| v.equip_avatar == avatar.avatar_id)
.collect::<Vec<_>>(),
);
for tech in techs {
battle_info.buff_list.push(tech);
}
battle_info.battle_avatar_list.push(battle_avatar);
};
}
// custom stats for avatars
for stat in &player.battle_config.custom_stats {
for avatar in &mut battle_info.battle_avatar_list {
if avatar.relic_list.len() == 0 {
avatar.relic_list.push(BattleRelic {
id: 61011,
main_affix_id: 1,
level: 1,
..Default::default()
})
}
if let Some(sub_affix) = avatar.relic_list[0]
.sub_affix_list
.iter_mut()
.find(|v| v.affix_id == stat.sub_affix_id)
{
sub_affix.cnt = stat.count;
} else {
avatar.relic_list[0].sub_affix_list.push(RelicAffix {
affix_id: stat.sub_affix_id,
cnt: stat.count,
step: stat.step,
})
}
}
}
// blessings
for blessing in &player.battle_config.blessings {
let mut buffs = BattleBuff {
id: blessing.id,
level: blessing.level,
wave_flag: 0xffffffff,
owner_index: 0xffffffff,
..Default::default()
};
if let Some(dynamic_key) = &blessing.dynamic_key {
buffs
.dynamic_values
.insert(dynamic_key.key.clone(), dynamic_key.value as f32);
};
battle_info.buff_list.push(buffs);
}
// pf score object
if player.battle_config.battle_type == BattleType::PF {
let mut battle_target = Hbinjjdphdo::default();
battle_target.bgnpebhgelb.push(BattleTarget {
id: 10001,
progress: 0,
..Default::default()
});
battle_info.ichnbmifjdi.insert(1, battle_target);
for i in 2..=4 {
battle_info
.ichnbmifjdi
.insert(i, Hbinjjdphdo::default());
}
battle_info.ichnbmifjdi.insert(
5,
Hbinjjdphdo {
bgnpebhgelb: vec![
BattleTarget {
id: 2001,
progress: 0,
..Default::default()
},
BattleTarget {
id: 2002,
progress: 0,
..Default::default()
},
],
},
);
}
// SU
if player.battle_config.battle_type == BattleType::SU {
battle_info
.mpobegkcikn
.push(Npjnkmmjfdf {
chgdaadjepi: player.battle_config.path_resonance_id,
status: Some(Agpocmnmmdi {
sp: Some(AmountInfo {
cur_amount: 10_000,
max_amount: 10_000,
}),
}),
..Default::default()
})
}
// monsters
battle_info.monster_wave_list = Monster::to_scene_monster_waves(&player.battle_config.monsters);
let rsp = StartCocoonStageScRsp {
retcode: 0,
prop_entity_id: body.prop_entity_id,
cocoon_id: body.cocoon_id,
wave: body.wave,
battle_info: Some(SceneBattleInfo {
stage_id: 201012311,
logic_random_seed: 4444,
battle_id: 1,
battle_avatar_list: BATTLE_LINEUP
.iter()
.enumerate()
.map(|(idx, id)| BattleAvatar {
index: idx as u32,
id: *id,
level: 80,
promotion: 6,
rank: 6,
hp: 10000,
avatar_type: 3,
sp: Some(AmountInfo {
cur_amount: 10000,
max_amount: 10000,
}),
..Default::default()
})
.collect(),
monster_wave_list: vec![SceneMonsterWave {
monster_list: vec![SceneMonsterParam {
monster_id: 3013010,
..Default::default()
}],
..Default::default()
}],
..Default::default()
}),
battle_info: Some(battle_info),
};
session.send(CMD_START_COCOON_STAGE_SC_RSP, rsp).await

View File

@ -1,38 +1,31 @@
use super::*;
use std::collections::BTreeMap;
static STARTING_LINEUP: [u32; 4] = [1309, 1308, 1307, 1315];
use crate::net::tools::{self, AvatarJson};
use super::*;
pub async fn on_get_all_lineup_data_cs_req(
session: &mut PlayerSession,
_body: &GetAllLineupDataCsReq,
) -> Result<()> {
let player = tools::JsonData::load().await;
let lineup = LineupInfo {
extra_lineup_type: ExtraLineupType::LineupNone.into(),
name: "Squad 1".to_string(),
// mp: 5,
// leader_slot: 0,
// max_mp: 5,
avatar_list: AvatarJson::to_lineup_avatars(&player.lineups, &player.avatars),
..Default::default()
};
session
.send(
CMD_GET_ALL_LINEUP_DATA_SC_RSP,
GetAllLineupDataScRsp {
retcode: 0,
cur_index: 0,
lineup_list: vec![LineupInfo {
plane_id: 10001,
name: String::from("Lineup 1"),
index: 0,
avatar_list: STARTING_LINEUP
.iter()
.enumerate()
.map(|(idx, id)| LineupAvatar {
id: *id,
slot: idx as u32,
hp: 10000,
sp: Some(AmountInfo {
cur_amount: 10000,
max_amount: 10000,
}),
satiety: 100,
avatar_type: 3,
})
.collect(),
..Default::default()
}],
lineup_list: vec![lineup],
..Default::default()
},
)
.await
@ -42,37 +35,142 @@ pub async fn on_get_cur_lineup_data_cs_req(
session: &mut PlayerSession,
_body: &GetCurLineupDataCsReq,
) -> Result<()> {
let player = tools::JsonData::load().await;
let mut lineup = LineupInfo {
extra_lineup_type: ExtraLineupType::LineupNone.into(),
name: "Squad 1".to_string(),
// mp: 5,
// leader_slot: 0,
// max_mp: 5,
..Default::default()
};
let avatar_ids = player
.avatars
.iter()
.map(|(_, v)| v.avatar_id)
.collect::<Vec<_>>();
let mut avatars = player
.lineups
.iter()
.filter(|(_slot, v)| v > &&0 && avatar_ids.contains(v))
.map(|(slot, avatar_id)| {
player
.avatars
.get(avatar_id)
.unwrap()
.to_lineup_avatar_proto(*slot)
})
.collect::<Vec<LineupAvatar>>();
lineup.avatar_list.append(&mut avatars);
session
.send(
CMD_GET_CUR_LINEUP_DATA_SC_RSP,
GetCurLineupDataScRsp {
retcode: 0,
lineup: Some(LineupInfo {
plane_id: 10001,
name: String::from("Lineup 1"),
index: 0,
avatar_list: STARTING_LINEUP
.iter()
.enumerate()
.map(|(idx, id)| LineupAvatar {
id: *id,
slot: idx as u32,
hp: 10000,
sp: Some(AmountInfo {
cur_amount: 10000,
max_amount: 10000,
}),
satiety: 100,
avatar_type: 3,
})
.collect(),
..Default::default()
}),
lineup: Some(lineup),
..Default::default()
},
)
.await
}
pub async fn on_join_lineup_cs_req(
session: &mut PlayerSession,
body: &JoinLineupCsReq,
) -> Result<()> {
// update lineups
// TODO: FIX THESE SHIT
{
let mut player = tools::JsonData::load().await;
let lineups = &mut player.lineups;
lineups.insert(body.slot, body.base_avatar_id);
player.save_lineup().await;
}
{
let player = tools::JsonData::load().await;
let lineups = &player.lineups;
refresh_lineup(session, &lineups, &player.avatars).await?;
}
session.send(CMD_JOIN_LINEUP_SC_RSP, JoinLineupScRsp::default())
.await?;
Ok(())
}
pub async fn on_replace_lineup_cs_req(
_session: &mut PlayerSession,
req: &ReplaceLineupCsReq,
) -> Result<()> {
{
let mut player = tools::JsonData::load().await;
let lineups = &mut player.lineups;
for (slot, avatar_id) in &mut *lineups {
if let Some(lineup) = req.jkifflmenfn.get(*slot as usize) {
*avatar_id = lineup.id;
} else {
*avatar_id = 0;
}
}
player.save_lineup().await;
}
{
let player = tools::JsonData::load().await;
let lineups = &player.lineups;
refresh_lineup(_session, &lineups, &player.avatars).await?;
}
_session.send(CMD_JOIN_LINEUP_SC_RSP, JoinLineupScRsp::default())
.await?;
Ok(())
}
pub async fn on_quit_lineup_cs_req(
_session: &mut PlayerSession,
_: &QuitLineupCsReq,
) -> Result<()> {
_session.send(CMD_JOIN_LINEUP_SC_RSP, JoinLineupScRsp::default())
.await?;
Ok(())
}
async fn refresh_lineup(
sess: &mut PlayerSession,
lineups: &BTreeMap<u32, u32>,
avatars: &BTreeMap<u32, AvatarJson>,
) -> Result<()> {
let lineup = LineupInfo {
extra_lineup_type: ExtraLineupType::LineupNone.into(),
name: "Squad 1".to_string(),
avatar_list: AvatarJson::to_lineup_avatars(lineups, avatars),
..Default::default()
};
sess.send(
CMD_SYNC_LINEUP_NOTIFY,
SyncLineupNotify {
lineup: Some(lineup),
reason_list: vec![]
},
)
.await?;
Ok(())
}
pub async fn on_change_lineup_leader_cs_req(
session: &mut PlayerSession,
body: &ChangeLineupLeaderCsReq,

View File

@ -3,6 +3,8 @@ pub mod gateway;
mod handlers;
mod packet;
mod session;
mod tools;
pub use packet::NetPacket;
pub use session::PlayerSession;

View File

@ -641,18 +641,18 @@ trait_handler! {
// ExtraLineupDestroyNotify 763;
// GetLineupAvatarDataCsReq 768;
// SwitchLineupIndexScRsp 795;
// JoinLineupCsReq 702;
JoinLineupCsReq 702;
// GetAllLineupDataScRsp 716;
// SetLineupNameCsReq 742;
// ChangeLineupLeaderScRsp 733;
ChangeLineupLeaderCsReq 706;
// ReplaceLineupCsReq 785;
ReplaceLineupCsReq 785;
// SwapLineupCsReq 786;
// QuitLineupScRsp 743;
// GetLineupAvatarDataScRsp 796;
// ReplaceLineupScRsp 756;
// GetStageLineupCsReq 734;
// QuitLineupCsReq 719;
QuitLineupCsReq 719;
// SetLineupNameScRsp 737;
// SwitchLineupIndexCsReq 759;
GetCurLineupDataCsReq 762;

608
gameserver/src/net/tools.rs Normal file
View File

@ -0,0 +1,608 @@
use proto::{Avatar, AvatarSkillTree, BattleAvatar};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};
use proto::*;
// AVATAR
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct AvatarJson {
#[serde(alias = "ownerUid")]
pub owner_uid: u32,
#[serde(alias = "avatarId")]
pub avatar_id: u32,
pub data: AvatarData,
pub level: u32,
pub promotion: u32,
// pub rank: u32,
#[serde(alias = "use_technique")]
#[serde(alias = "useTechnique")]
pub techniques: Vec<u32>,
#[serde(alias = "spValue")]
pub sp_value: Option<u32>,
#[serde(alias = "spMax")]
pub sp_max: Option<u32>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct AvatarData {
pub rank: u32,
pub skills: BTreeMap<u32, u32>,
}
impl AvatarJson {
pub fn to_avatar_proto(
&self,
lightcone: Option<&Lightcone>,
relics: Vec<&Relic>,
) -> Avatar {
Avatar {
base_avatar_id: self.avatar_id,
exp: 0,
level: self.level,
promotion: self.promotion,
rank: self.data.rank,
skilltree_list: self
.data
.skills
.iter()
.map(|v| AvatarSkillTree {
point_id: *v.0,
level: *v.1,
})
.collect::<Vec<_>>(),
equipment_unique_id: if let Some(lc) = lightcone {
lc.internal_uid
} else {
0
},
amafpakcckf: relics
.iter()
.map(|v| v.to_equipment_relic_proto())
.collect::<Vec<_>>(),
..Default::default()
}
}
pub fn to_battle_avatar_proto(
&self,
index: u32,
lightcone: Option<&Lightcone>,
relics: Vec<&Relic>,
) -> (BattleAvatar, Vec<BattleBuff>) {
let battle_avatar = BattleAvatar {
index,
avatar_type: AvatarType::AvatarFormalType.into(),
id: self.avatar_id,
level: self.level,
rank: self.data.rank,
skilltree_list: self
.data
.skills
.iter()
.map(|v| AvatarSkillTree {
point_id: *v.0,
level: *v.1,
})
.collect::<Vec<_>>(),
equipment_list: if let Some(lc) = lightcone {
vec![lc.to_battle_equipment_proto()]
} else {
vec![]
},
hp: 10_000,
promotion: self.promotion,
relic_list: relics
.iter()
.map(|v| v.to_battle_relic_proto())
.collect::<Vec<_>>(),
world_level: 6,
sp: Some(AmountInfo {
cur_amount: self.sp_value.unwrap_or(10_000),
max_amount: self.sp_max.unwrap_or(10_000),
}),
..Default::default()
};
let mut battle_buff = Vec::<BattleBuff>::new();
for buff_id in &self.techniques {
battle_buff.push(BattleBuff {
wave_flag: 0xffffffff,
owner_index: index as u32,
level: 1,
id: *buff_id,
..Default::default()
});
}
(battle_avatar, battle_buff)
}
pub fn to_lineup_avatar_proto(&self, slot: u32) -> LineupAvatar {
LineupAvatar {
id: self.avatar_id,
hp: 10_000,
satiety: 100,
avatar_type: AvatarType::AvatarFormalType.into(),
sp: Some(AmountInfo {
cur_amount: self.sp_value.unwrap_or(10_000),
max_amount: self.sp_max.unwrap_or(10_000),
}),
slot,
}
}
pub fn to_lineup_avatars(
lineups: &BTreeMap<u32, u32>,
avatars: &BTreeMap<u32, AvatarJson>,
) -> Vec<LineupAvatar> {
let avatar_ids = avatars.iter().map(|(_, v)| v.avatar_id).collect::<Vec<_>>();
lineups
.iter()
.filter(|(_slot, v)| v > &&0 && avatar_ids.contains(v))
.map(|(slot, avatar_id)| {
avatars
.get(avatar_id)
.unwrap()
.to_lineup_avatar_proto(*slot)
})
.collect::<Vec<LineupAvatar>>()
}
pub fn to_lineup_info(lineups: &BTreeMap<u32, u32>) -> LineupInfo {
let mut lineup_info = LineupInfo {
extra_lineup_type: ExtraLineupType::LineupNone.into(),
name: "Squad 1".to_string(),
// mp: 5,
// leader_slot: 0,
// max_mp: 5,
..Default::default()
};
for (_, id) in lineups {
if *id == 0 {
continue;
}
lineup_info.avatar_list.push(LineupAvatar {
id: *id,
hp: 10_000,
satiety: 100,
avatar_type: AvatarType::AvatarFormalType.into(),
sp: Some(AmountInfo {
cur_amount: 10_000,
max_amount: 10_000,
}),
slot: lineup_info.avatar_list.len() as u32,
});
}
lineup_info
}
}
// LIGHTCONE
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Lightcone {
pub level: u32,
#[serde(alias = "itemId")]
pub item_id: u32,
#[serde(alias = "equipAvatar")]
pub equip_avatar: u32,
pub rank: u32,
pub promotion: u32,
#[serde(alias = "internalUid")]
pub internal_uid: u32,
}
impl Lightcone {
pub fn to_equipment_proto(&self) -> Equipment {
Equipment {
base_avatar_id: self.equip_avatar,
exp: 0,
is_protected: false,
level: self.level,
promotion: self.promotion,
rank: self.rank,
tid: self.item_id,
unique_id: self.internal_uid,
..Default::default()
}
}
pub fn to_battle_equipment_proto(&self) -> BattleEquipment {
BattleEquipment {
id: self.item_id,
level: self.level,
promotion: self.promotion,
rank: self.rank,
}
}
}
// RELIC
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Relic {
pub level: u32,
#[serde(alias = "relicId")]
pub relic_id: u32,
#[serde(alias = "relicSetId")]
pub relic_set_id: u32,
#[serde(alias = "mainAffixId")]
pub main_affix_id: u32,
#[serde(alias = "subAffixes")]
pub sub_affixes: Vec<SubAffix>,
#[serde(alias = "internalUid")]
pub internal_uid: u32,
#[serde(alias = "equipAvatar")]
pub equip_avatar: u32,
}
#[derive(Debug, Serialize, Deserialize, Default, Clone)]
pub struct SubAffix {
#[serde(alias = "subAffixId")]
pub sub_affix_id: u32,
pub count: u32,
pub step: u32,
}
impl Relic {
pub fn to_relic_proto(&self) -> proto::Relic {
proto::Relic {
base_avatar_id: self.equip_avatar,
exp: 0,
is_protected: false,
level: self.level,
main_affix_id: self.main_affix_id,
tid: self.relic_id,
unique_id: self.internal_uid,
sub_affix_list: self
.sub_affixes
.iter()
.map(|v| RelicAffix {
affix_id: v.sub_affix_id,
cnt: v.count,
step: v.step,
})
.collect::<Vec<_>>(),
..Default::default()
}
}
pub fn to_battle_relic_proto(&self) -> BattleRelic {
BattleRelic {
id: self.relic_id,
level: self.level,
main_affix_id: self.main_affix_id,
unique_id: self.internal_uid,
sub_affix_list: self
.sub_affixes
.iter()
.map(|v| RelicAffix {
affix_id: v.sub_affix_id,
cnt: v.count,
step: v.step,
})
.collect::<Vec<_>>(),
..Default::default()
}
}
pub fn to_equipment_relic_proto(&self) -> EquipRelic {
EquipRelic {
ipnhjoomhdm: 0, //slot
llepdadmfdo: self.internal_uid,
}
}
}
// MONSTER
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
pub struct Monster {
pub level: u32,
#[serde(alias = "monsterId")]
pub monster_id: u32,
#[serde(default)]
pub max_hp: u32,
}
#[allow(dead_code)]
impl Monster {
fn to_scene_monster_info(&self) -> SceneMonsterParam {
SceneMonsterParam {
monster_id: self.monster_id,
max_hp: self.max_hp,
aiapcboelmg: self.max_hp,
}
}
pub fn to_scene_monster_wave(wave_index: u32, monsters: &Vec<Self>) -> SceneMonsterWave {
let mut wave_index = wave_index;
if wave_index <= 0 {
wave_index += 1;
}
SceneMonsterWave {
iilhbcalikm: wave_index, // wave indexx??
ejahmdkklbn: Some(Holldlkceof { // monster param
level: monsters.iter().map(|v| v.level).max().unwrap_or(95),
..Default::default()
}),
monster_list: monsters
.iter()
.map(|v| v.to_scene_monster_info())
.collect::<Vec<_>>(),
..Default::default()
}
}
pub fn to_scene_monster_waves(monsters: &Vec<Vec<Self>>) -> Vec<SceneMonsterWave> {
monsters
.iter()
.enumerate()
.map(|(i, v)| Self::to_scene_monster_wave(i as u32, v))
.collect::<_>()
}
}
// BATTLE CONFIG
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BattleConfig {
pub battle_type: BattleType,
pub monsters: Vec<Vec<Monster>>,
pub blessings: Vec<BattleBuffJson>,
pub stage_id: u32,
pub cycle_count: u32,
pub path_resonance_id: u32,
pub custom_stats: Vec<SubAffix>,
}
impl Default for BattleConfig {
fn default() -> Self {
Self {
battle_type: Default::default(),
monsters: vec![vec![Monster {
level: 60,
monster_id: 3014022,
max_hp: 0,
}]],
stage_id: 201012311,
blessings: Default::default(),
cycle_count: Default::default(),
path_resonance_id: Default::default(),
custom_stats: Default::default(),
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub enum BattleType {
DEFAULT = 0,
MOC = 1,
PF = 2,
SU = 3,
}
impl Default for BattleType {
fn default() -> Self {
Self::DEFAULT
}
}
// BATTLE BUFFS
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
pub struct BattleBuffJson {
pub level: u32,
pub id: u32,
pub dynamic_key: Option<DynamicKey>,
}
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
pub struct DynamicKey {
pub key: String,
pub value: u32,
}
#[allow(dead_code)]
impl BattleBuffJson {
pub fn to_battle_buff_proto(&self) -> proto::BattleBuff {
proto::BattleBuff {
id: self.id,
level: self.level,
wave_flag: 0xffffffff,
owner_index: 0xffffffff,
dynamic_values: if let Some(dyn_key) = &self.dynamic_key {
HashMap::from([(dyn_key.key.clone(), dyn_key.value as f32)])
} else {
Default::default()
},
..Default::default()
}
}
}
// SCENE
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Scene {
pub plane_id: u32,
pub floor_id: u32,
pub entry_id: u32,
}
impl Default for Scene {
fn default() -> Self {
Self {
entry_id: 2032101,
plane_id: 20321,
floor_id: 20321001,
}
}
}
// Position
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
pub struct Position {
pub x: i32,
pub y: i32,
pub z: i32,
pub rot_y: i32,
}
impl Position {
pub fn is_empty(&self) -> bool {
return self.x == 0 && self.y == 0 && self.z == 0;
}
pub fn to_motion(&self) -> MotionInfo {
MotionInfo {
// rot
eiaoiankefd: Some(Vector {
baimdminomk: 0,
bemlopmcgch: self.rot_y,
bagloppgnpb: 0,
}),
// pos
aomilajjmii: Some(Vector {
baimdminomk: self.x,
bemlopmcgch: self.y,
bagloppgnpb: self.z,
}),
}
}
}
// FREESR-DATA.json
#[derive(Debug, Serialize, Deserialize)]
pub struct JsonData {
pub lightcones: Vec<Lightcone>,
pub relics: Vec<Relic>,
pub avatars: BTreeMap<u32, AvatarJson>,
#[serde(default)]
pub battle_config: BattleConfig,
#[serde(default)]
pub lineups: BTreeMap<u32, u32>,
#[serde(default)]
pub position: Position,
#[serde(default)]
pub scene: Scene,
#[serde(default)]
pub main_character: MainCharacter,
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct JsonData2 {
#[serde(default)]
pub lineups: BTreeMap<u32, u32>,
#[serde(default)]
pub position: Position,
#[serde(default)]
pub scene: Scene,
#[serde(default)]
pub main_character: MainCharacter,
}
#[derive(Serialize, Deserialize, Clone, Debug, Copy)]
pub enum MainCharacter {
MalePyhsical = 8001,
FemalePhysical = 8002,
MalePreservation = 8003,
FemalePreservation = 8004,
MaleHarmony = 8005,
FemaleHarmony = 8006,
}
impl Default for MainCharacter {
fn default() -> Self {
Self::FemaleHarmony
}
}
impl JsonData {
pub async fn load() -> Self {
let mut json: JsonData = match serde_json::from_str(&tokio::fs::read_to_string("freesr-data.json").await.unwrap_or_default()) {
Ok(db) => db,
Err(err) => {
println!("{:#?}", err);
Self::create_dummy().await
}
};
let json2: JsonData2 = serde_json::from_str(&tokio::fs::read_to_string("persistent").await.unwrap_or_default()).unwrap_or_default();
json.lineups = json2.lineups;
json.position = json2.position;
json.scene = json2.scene;
json.main_character = json2.main_character;
json
}
async fn create_dummy() -> Self {
let mut db = Self {
lightcones: vec![],
relics: vec![],
avatars: BTreeMap::<u32, AvatarJson>::new(),
lineups: BTreeMap::<u32, u32>::new(),
scene: Default::default(),
position: Default::default(),
battle_config: Default::default(),
main_character: Default::default(),
};
db.avatars.insert(
8004,
AvatarJson {
avatar_id: 8004,
level: 80,
promotion: 6,
sp_max: Some(10_000),
sp_value: Some(10_000),
owner_uid: 0,
techniques: vec![],
data: AvatarData {
rank: 6,
skills: BTreeMap::from([
(800401, 6),
(800402, 10),
(800403, 10),
(800404, 10),
(800405, 1),
]),
},
},
);
db.lineups.insert(0, 8004);
db.save().await;
db
}
pub async fn save_lineup(&self) {
self.save().await;
}
pub async fn save(&self) {
let json = serde_json::to_string_pretty(&self).unwrap();
let _ = tokio::fs::write("freesr-data.json", json.as_bytes()).await;
let _ = tokio::fs::write("persistent", serde_json::to_string_pretty(&JsonData2 {
lineups: self.lineups.clone(),
main_character: self.main_character,
position: self.position.clone(),
scene: self.scene.clone()
}).unwrap().as_bytes()).await;
}
}

20
persistent Normal file
View File

@ -0,0 +1,20 @@
{
"lineups": {
"0": 1315,
"1": 1309,
"2": 1303,
"3": 1217
},
"position": {
"x": 34639,
"y": 192819,
"z": 435863,
"rot_y": 26508
},
"scene": {
"plane_id": 20313,
"floor_id": 20313001,
"entry_id": 2031301
},
"main_character": "FemaleHarmony"
}