mirror of
https://github.com/redstrate/Kawari.git
synced 2025-05-13 07:07:45 +00:00
Replace (most of) the remaining Excel parsing with Physis Sheets
The only one remaining is for Item data, but that can't be ported yet because the new API only fetches the first page for now.
This commit is contained in:
parent
df789b52c9
commit
9787126a1b
8 changed files with 53 additions and 110 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1028,7 +1028,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "physis-sheets"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/redstrate/PhysisSheets#ca42d72fc8a76211d67f6bd4698a45c7da0037fb"
|
||||
source = "git+https://github.com/redstrate/PhysisSheets#4d11e27a1e31bb482184626d1e7a51fc5e673674"
|
||||
dependencies = [
|
||||
"physis",
|
||||
]
|
||||
|
|
|
@ -104,4 +104,4 @@ rkon = { version = "0.1" }
|
|||
tower-http = { version = "0.6", features = ["fs"] }
|
||||
|
||||
# excel sheet data
|
||||
physis-sheets = { git = "https://github.com/redstrate/PhysisSheets", features = ["Warp"], default-features = false }
|
||||
physis-sheets = { git = "https://github.com/redstrate/PhysisSheets", features = ["Warp", "Tribe", "ClassJob", "World", "TerritoryType", "Race"], default-features = false }
|
||||
|
|
|
@ -27,7 +27,9 @@ async fn main() {
|
|||
tracing::info!("Server started on {addr}");
|
||||
|
||||
let mut game_data = GameData::new();
|
||||
let world_name = game_data.get_world_name(config.world.world_id);
|
||||
let world_name = game_data
|
||||
.get_world_name(config.world.world_id)
|
||||
.expect("Unknown world name");
|
||||
|
||||
loop {
|
||||
let (socket, _) = listener.accept().await.unwrap();
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use physis::common::{Language, Platform};
|
||||
use physis::exd::{EXD, ExcelRowKind};
|
||||
use physis::exh::EXH;
|
||||
use physis_sheets::Warp::Warp;
|
||||
use physis_sheets::ClassJob::ClassJobSheet;
|
||||
use physis_sheets::World::WorldSheet;
|
||||
use physis_sheets::{Tribe::TribeSheet, Warp::WarpSheet};
|
||||
|
||||
use crate::{common::Attributes, config::get_config};
|
||||
|
||||
|
@ -44,72 +46,35 @@ impl GameData {
|
|||
}
|
||||
|
||||
/// Gets the world name from an id into the World Excel sheet.
|
||||
pub fn get_world_name(&mut self, world_id: u16) -> String {
|
||||
let exh = self.game_data.read_excel_sheet_header("World").unwrap();
|
||||
let exd = self
|
||||
.game_data
|
||||
.read_excel_sheet("World", &exh, Language::None, 0)
|
||||
.unwrap();
|
||||
pub fn get_world_name(&mut self, world_id: u16) -> Option<String> {
|
||||
let sheet = WorldSheet::read_from(&mut self.game_data, Language::None)?;
|
||||
let row = sheet.get_row(world_id as u32)?;
|
||||
|
||||
let ExcelRowKind::SingleRow(world_row) = &exd.get_row(world_id as u32).unwrap() else {
|
||||
panic!("Expected a single row!")
|
||||
};
|
||||
|
||||
let physis::exd::ColumnData::String(name) = &world_row.columns[1] else {
|
||||
panic!("Unexpected type!");
|
||||
};
|
||||
|
||||
name.clone()
|
||||
row.Name().into_string().map(|x| x.clone())
|
||||
}
|
||||
|
||||
/// Gets the starting city-state from a given class/job id.
|
||||
pub fn get_citystate(&mut self, classjob_id: u16) -> u8 {
|
||||
let exh = self.game_data.read_excel_sheet_header("ClassJob").unwrap();
|
||||
let exd = self
|
||||
.game_data
|
||||
.read_excel_sheet("ClassJob", &exh, Language::English, 0)
|
||||
.unwrap();
|
||||
pub fn get_citystate(&mut self, classjob_id: u16) -> Option<u8> {
|
||||
let sheet = ClassJobSheet::read_from(&mut self.game_data, Language::English)?;
|
||||
let row = sheet.get_row(classjob_id as u32)?;
|
||||
|
||||
let ExcelRowKind::SingleRow(world_row) = &exd.get_row(classjob_id as u32).unwrap() else {
|
||||
panic!("Expected a single row!")
|
||||
};
|
||||
|
||||
let physis::exd::ColumnData::UInt8(town_id) = &world_row.columns[33] else {
|
||||
panic!("Unexpected type!");
|
||||
};
|
||||
|
||||
*town_id
|
||||
row.StartingTown().into_u8().map(|x| *x)
|
||||
}
|
||||
|
||||
pub fn get_racial_base_attributes(&mut self, tribe_id: u8) -> Attributes {
|
||||
pub fn get_racial_base_attributes(&mut self, tribe_id: u8) -> Option<Attributes> {
|
||||
// The Tribe Excel sheet only has deltas (e.g. 2 or -2) which are applied to a base 20 number... from somewhere
|
||||
let base_stat = 20;
|
||||
|
||||
let exh = self.game_data.read_excel_sheet_header("Tribe").unwrap();
|
||||
let exd = self
|
||||
.game_data
|
||||
.read_excel_sheet("Tribe", &exh, Language::English, 0)
|
||||
.unwrap();
|
||||
let sheet = TribeSheet::read_from(&mut self.game_data, Language::English)?;
|
||||
let row = sheet.get_row(tribe_id as u32)?;
|
||||
|
||||
let ExcelRowKind::SingleRow(tribe_row) = &exd.get_row(tribe_id as u32).unwrap() else {
|
||||
panic!("Expected a single row!")
|
||||
};
|
||||
|
||||
let get_column = |column_index: usize| {
|
||||
let physis::exd::ColumnData::Int8(delta) = &tribe_row.columns[column_index] else {
|
||||
panic!("Unexpected type!");
|
||||
};
|
||||
|
||||
*delta
|
||||
};
|
||||
|
||||
Attributes {
|
||||
strength: (base_stat + get_column(4)) as u32,
|
||||
dexterity: (base_stat + get_column(6)) as u32,
|
||||
vitality: (base_stat + get_column(5)) as u32,
|
||||
intelligence: (base_stat + get_column(7)) as u32,
|
||||
mind: (base_stat + get_column(8)) as u32,
|
||||
}
|
||||
Some(Attributes {
|
||||
strength: (base_stat + row.STR().into_i8()?) as u32,
|
||||
dexterity: (base_stat + row.DEX().into_i8()?) as u32,
|
||||
vitality: (base_stat + row.VIT().into_i8()?) as u32,
|
||||
intelligence: (base_stat + row.INT().into_i8()?) as u32,
|
||||
mind: (base_stat + row.MND().into_i8()?) as u32,
|
||||
})
|
||||
}
|
||||
|
||||
/// Gets the primary model ID for a given item ID
|
||||
|
@ -133,9 +98,8 @@ impl GameData {
|
|||
|
||||
/// Returns the pop range object id that's associated with the warp id
|
||||
pub fn get_warp(&mut self, warp_id: u32) -> Option<(u32, u16)> {
|
||||
let warp_sheet = Warp::read_from(&mut self.game_data, Language::English)?;
|
||||
|
||||
let row = warp_sheet.get_row(warp_id)?;
|
||||
let sheet = WarpSheet::read_from(&mut self.game_data, Language::English)?;
|
||||
let row = sheet.get_row(warp_id)?;
|
||||
|
||||
let pop_range_id = row.PopRange().into_u32()?;
|
||||
let zone_id = row.TerritoryType().into_u16()?;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use physis::{common::Language, exd::ExcelRowKind};
|
||||
use physis::common::Language;
|
||||
use physis_sheets::Race::RaceSheet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::common::GameData;
|
||||
|
@ -122,34 +123,19 @@ impl<'a> Iterator for InventoryIterator<'a> {
|
|||
impl Inventory {
|
||||
/// Equip the starting items for a given race
|
||||
pub fn equip_racial_items(&mut self, race_id: u8, gender: u8, game_data: &mut GameData) {
|
||||
let exh = game_data.game_data.read_excel_sheet_header("Race").unwrap();
|
||||
let exd = game_data
|
||||
.game_data
|
||||
.read_excel_sheet("Race", &exh, Language::English, 0)
|
||||
.unwrap();
|
||||
|
||||
let ExcelRowKind::SingleRow(world_row) = &exd.get_row(race_id as u32).unwrap() else {
|
||||
panic!("Expected a single row!")
|
||||
};
|
||||
|
||||
let get_column = |column_index: usize| {
|
||||
let physis::exd::ColumnData::Int32(item_id) = &world_row.columns[column_index] else {
|
||||
panic!("Unexpected type!");
|
||||
};
|
||||
|
||||
*item_id
|
||||
};
|
||||
let sheet = RaceSheet::read_from(&mut game_data.game_data, Language::English).unwrap();
|
||||
let row = sheet.get_row(race_id as u32).unwrap();
|
||||
|
||||
if gender == 0 {
|
||||
self.equipped.body = Item::new(1, get_column(2) as u32);
|
||||
self.equipped.hands = Item::new(1, get_column(3) as u32);
|
||||
self.equipped.legs = Item::new(1, get_column(4) as u32);
|
||||
self.equipped.feet = Item::new(1, get_column(5) as u32);
|
||||
self.equipped.body = Item::new(1, *row.RSEMBody().into_i32().unwrap() as u32);
|
||||
self.equipped.hands = Item::new(1, *row.RSEMHands().into_i32().unwrap() as u32);
|
||||
self.equipped.legs = Item::new(1, *row.RSEMLegs().into_i32().unwrap() as u32);
|
||||
self.equipped.feet = Item::new(1, *row.RSEMFeet().into_i32().unwrap() as u32);
|
||||
} else {
|
||||
self.equipped.body = Item::new(1, get_column(6) as u32);
|
||||
self.equipped.hands = Item::new(1, get_column(7) as u32);
|
||||
self.equipped.legs = Item::new(1, get_column(8) as u32);
|
||||
self.equipped.feet = Item::new(1, get_column(9) as u32);
|
||||
self.equipped.body = Item::new(1, *row.RSEFBody().into_i32().unwrap() as u32);
|
||||
self.equipped.hands = Item::new(1, *row.RSEFHands().into_i32().unwrap() as u32);
|
||||
self.equipped.legs = Item::new(1, *row.RSEFLegs().into_i32().unwrap() as u32);
|
||||
self.equipped.feet = Item::new(1, *row.RSEFFeet().into_i32().unwrap() as u32);
|
||||
}
|
||||
|
||||
// TODO: don't hardcode
|
||||
|
|
|
@ -834,8 +834,9 @@ impl ZoneConnection {
|
|||
{
|
||||
let mut game_data = self.gamedata.lock().unwrap();
|
||||
|
||||
attributes =
|
||||
game_data.get_racial_base_attributes(chara_details.chara_make.customize.subrace);
|
||||
attributes = game_data
|
||||
.get_racial_base_attributes(chara_details.chara_make.customize.subrace)
|
||||
.expect("Failed to read racial attributes");
|
||||
}
|
||||
|
||||
let ipc = ServerZoneIpcSegment {
|
||||
|
|
|
@ -28,7 +28,9 @@ pub async fn handle_custom_ipc(connection: &mut ZoneConnection, data: &CustomIpc
|
|||
{
|
||||
let mut game_data = connection.gamedata.lock().unwrap();
|
||||
|
||||
city_state = game_data.get_citystate(chara_make.classjob_id as u16);
|
||||
city_state = game_data
|
||||
.get_citystate(chara_make.classjob_id as u16)
|
||||
.expect("Unknown citystate");
|
||||
}
|
||||
|
||||
let mut inventory = Inventory::default();
|
||||
|
@ -122,7 +124,9 @@ pub async fn handle_custom_ipc(connection: &mut ZoneConnection, data: &CustomIpc
|
|||
let world_name;
|
||||
{
|
||||
let mut game_data = connection.gamedata.lock().unwrap();
|
||||
world_name = game_data.get_world_name(config.world.world_id);
|
||||
world_name = game_data
|
||||
.get_world_name(config.world.world_id)
|
||||
.expect("Couldn't read world name");
|
||||
}
|
||||
|
||||
let characters;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use physis::{
|
||||
common::Language,
|
||||
exd::ExcelRowKind,
|
||||
gamedata::GameData,
|
||||
layer::{
|
||||
ExitRangeInstanceObject, InstanceObject, LayerEntryData, LayerGroup, PopRangeInstanceObject,
|
||||
},
|
||||
};
|
||||
use physis_sheets::TerritoryType::TerritoryTypeSheet;
|
||||
|
||||
/// Represents a loaded zone
|
||||
#[derive(Default)]
|
||||
|
@ -27,25 +27,11 @@ impl Zone {
|
|||
..Default::default()
|
||||
};
|
||||
|
||||
let Some(exh) = game_data.read_excel_sheet_header("TerritoryType") else {
|
||||
return zone;
|
||||
};
|
||||
let Some(exd) = game_data.read_excel_sheet("TerritoryType", &exh, Language::None, 0) else {
|
||||
return zone;
|
||||
};
|
||||
|
||||
let Some(territory_type_row) = &exd.get_row(id as u32) else {
|
||||
return zone;
|
||||
};
|
||||
|
||||
let ExcelRowKind::SingleRow(territory_type_row) = territory_type_row else {
|
||||
panic!("Expected a single row!")
|
||||
};
|
||||
let sheet = TerritoryTypeSheet::read_from(game_data, Language::None).unwrap();
|
||||
let row = sheet.get_row(id as u32).unwrap();
|
||||
|
||||
// e.g. ffxiv/fst_f1/fld/f1f3/level/f1f3
|
||||
let physis::exd::ColumnData::String(bg_path) = &territory_type_row.columns[1] else {
|
||||
panic!("Unexpected type!");
|
||||
};
|
||||
let bg_path = row.Bg().into_string().unwrap();
|
||||
|
||||
let Some(level_index) = bg_path.find("/level/") else {
|
||||
return zone;
|
||||
|
|
Loading…
Add table
Reference in a new issue