Browse Source

use proper data structs that convert to what pso wants

pbs
jake 5 years ago
parent
commit
a74941441b
  1. 34
      src/common/leveltable.rs
  2. 246
      src/entity/character.rs
  3. 105
      src/login/character.rs
  4. 17
      src/main.rs
  5. 94
      src/ship/character.rs
  6. 35
      src/ship/ship.rs

34
src/common/leveltable.rs

@ -1,7 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::File; use std::fs::File;
use serde_json::Value; use serde_json::Value;
use libpso::character::character::Class;
use crate::entity::character::CharacterClass;
#[derive(Default, Copy, Clone, Debug, PartialEq)] #[derive(Default, Copy, Clone, Debug, PartialEq)]
pub struct CharacterStats { pub struct CharacterStats {
@ -27,7 +27,7 @@ struct CharacterLevelEntry {
} }
pub struct CharacterLevelTable { pub struct CharacterLevelTable {
table: HashMap<Class, [CharacterLevelEntry; 200]>,
table: HashMap<CharacterClass, [CharacterLevelEntry; 200]>,
} }
@ -39,18 +39,18 @@ impl CharacterLevelTable {
for it in json.as_object().unwrap().iter(){ for it in json.as_object().unwrap().iter(){
let cl = match it.0.as_str() { let cl = match it.0.as_str() {
"HUmar" => Class::HUmar,
"HUnewearl" => Class::HUnewearl,
"HUcast" => Class::HUcast,
"HUcaseal" => Class::HUcaseal,
"RAmar" => Class::RAmar,
"RAmarl" => Class::RAmarl,
"RAcast" => Class::RAcast,
"RAcaseal" => Class::RAcaseal,
"FOmar" => Class::FOmar,
"FOmarl" => Class::FOmarl,
"FOnewm" => Class::FOnewm,
"FOnewearl" => Class::FOnewearl,
"HUmar" => CharacterClass::HUmar,
"HUnewearl" => CharacterClass::HUnewearl,
"HUcast" => CharacterClass::HUcast,
"HUcaseal" => CharacterClass::HUcaseal,
"RAmar" => CharacterClass::RAmar,
"RAmarl" => CharacterClass::RAmarl,
"RAcast" => CharacterClass::RAcast,
"RAcaseal" => CharacterClass::RAcaseal,
"FOmar" => CharacterClass::FOmar,
"FOmarl" => CharacterClass::FOmarl,
"FOnewm" => CharacterClass::FOnewm,
"FOnewearl" => CharacterClass::FOnewearl,
_ => panic!("unexpected class in char stats"), _ => panic!("unexpected class in char stats"),
}; };
@ -76,7 +76,7 @@ impl CharacterLevelTable {
} }
} }
pub fn get_stats_from_exp(&self, ch_class: Class, exp: u32) -> (u32, CharacterStats) {
pub fn get_stats_from_exp(&self, ch_class: CharacterClass, exp: u32) -> (u32, CharacterStats) {
if let Some(statlist) = self.table.get(&ch_class) { if let Some(statlist) = self.table.get(&ch_class) {
statlist statlist
.iter() .iter()
@ -107,7 +107,7 @@ mod test {
#[test] #[test]
fn test_stat_levels() { fn test_stat_levels() {
let table = CharacterLevelTable::new(); let table = CharacterLevelTable::new();
assert!(table.get_stats_from_exp(Class::FOmarl, 0) == (1, CharacterStats { hp: 20, atp: 13, mst: 53, evp: 35, dfp: 10, ata: 15, lck: 10 }));
assert!(table.get_stats_from_exp(Class::FOmarl, 1 << 17) == (36, CharacterStats { hp: 125, atp: 114, mst: 219, evp: 182, dfp: 42, ata: 213, lck: 10 }));
assert!(table.get_stats_from_exp(CharacterClass::FOmarl, 0) == (1, CharacterStats { hp: 20, atp: 13, mst: 53, evp: 35, dfp: 10, ata: 15, lck: 10 }));
assert!(table.get_stats_from_exp(CharacterClass::FOmarl, 1 << 17) == (36, CharacterStats { hp: 125, atp: 114, mst: 219, evp: 182, dfp: 42, ata: 213, lck: 10 }));
} }
} }

246
src/entity/character.rs

@ -1,9 +1,251 @@
use std::convert::{From, Into, TryFrom, TryInto};
use std::collections::HashMap;
use libpso::character::character; use libpso::character::character;
#[derive(Copy, Clone, Debug, Default)]
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub enum CharacterClass {
HUmar,
HUnewearl,
HUcast,
HUcaseal,
RAmar,
RAmarl,
RAcast,
RAcaseal,
FOmar,
FOmarl,
FOnewm,
FOnewearl,
}
// TODO: TryFrom
impl From<u8> for CharacterClass {
fn from(f: u8) -> CharacterClass {
match f {
0 => CharacterClass::HUmar,
1 => CharacterClass::HUnewearl,
2 => CharacterClass::HUcast,
3 => CharacterClass::RAmar,
4 => CharacterClass::RAcast,
5 => CharacterClass::RAcaseal,
6 => CharacterClass::FOmarl,
7 => CharacterClass::FOnewm,
8 => CharacterClass::FOnewearl,
9 => CharacterClass::HUcaseal,
10 => CharacterClass::RAmarl,
11 => CharacterClass::FOmar,
_ => panic!("unknown class")
}
}
}
impl Into<u8> for CharacterClass {
fn into(self) -> u8 {
match self {
CharacterClass::HUmar => 0,
CharacterClass::HUnewearl => 1,
CharacterClass::HUcast => 2,
CharacterClass::RAmar => 3,
CharacterClass::RAcast => 4,
CharacterClass::RAcaseal => 5,
CharacterClass::FOmarl => 6,
CharacterClass::FOnewm => 7,
CharacterClass::FOnewearl => 8,
CharacterClass::HUcaseal => 9,
CharacterClass::RAmarl => 10,
CharacterClass::FOmar => 11,
}
}
}
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub enum SectionID {
Viridia,
Greenill,
Skyly,
Bluefull,
Purplenum,
Pinkal,
Redria,
Oran,
Yellowboze,
Whitill,
}
impl From<u8> for SectionID {
fn from(id: u8) -> SectionID {
match id {
0 => SectionID::Viridia,
1 => SectionID::Greenill,
2 => SectionID::Skyly,
3 => SectionID::Bluefull,
4 => SectionID::Purplenum,
5 => SectionID::Pinkal,
6 => SectionID::Redria,
7 => SectionID::Oran,
8 => SectionID::Yellowboze,
9 => SectionID::Whitill,
_ => panic!(),
}
}
}
impl Into<u8> for SectionID {
fn into(self) -> u8 {
match self {
SectionID::Viridia => 0,
SectionID::Greenill => 1,
SectionID::Skyly => 2,
SectionID::Bluefull => 3,
SectionID::Purplenum => 4,
SectionID::Pinkal => 5,
SectionID::Redria => 6,
SectionID::Oran => 7,
SectionID::Yellowboze => 8,
SectionID::Whitill => 9,
}
}
}
#[derive(Clone, Debug, Default)]
pub struct CharacterAppearance {
pub costume: u16,
pub skin: u16,
pub face: u16,
pub head: u16,
pub hair: u16,
pub hair_r: u16,
pub hair_g: u16,
pub hair_b: u16,
pub prop_x: f32,
pub prop_y: f32,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Techniques {
Foie,
Gifoie,
Rafoie,
Zonde,
Gizonde,
Razonde,
Barta,
Gibarta,
Rabarta,
Grants,
Megid,
Shifta,
Deband,
Jellen,
Zalure,
Resta,
Anti,
Reverser,
Ryuker,
}
#[derive(Clone, Debug)]
pub struct TechLevel(u8);
#[derive(Clone, Debug)]
pub struct CharacterTechniques {
techs: HashMap<Techniques, TechLevel>
}
impl CharacterTechniques {
fn new() -> CharacterTechniques {
CharacterTechniques {
techs: HashMap::new(),
}
}
fn set_tech(&mut self, tech: Techniques, level: TechLevel) {
self.techs.insert(tech, level);
}
// from_bytes
fn as_bytes(&self) -> [u8; 20] {
self.techs.iter()
.fold([0xFF; 20], |mut techlist, (tech, level)| {
let index = match tech {
Techniques::Foie => 0,
Techniques::Gifoie => 1,
Techniques::Rafoie => 2,
Techniques::Zonde => 3,
Techniques::Gizonde => 4,
Techniques::Razonde => 5,
Techniques::Barta => 6,
Techniques::Gibarta => 7,
Techniques::Rabarta => 8,
Techniques::Grants => 9,
Techniques::Megid => 10,
Techniques::Shifta => 11,
Techniques::Deband => 12,
Techniques::Jellen => 13,
Techniques::Zalure => 14,
Techniques::Resta => 15,
Techniques::Anti => 16,
Techniques::Reverser => 17,
Techniques::Ryuker => 18,
};
techlist[index] = level.0;
techlist
})
}
}
#[derive(Clone)]
pub struct CharacterConfig {
raw_data: [u8; 0xE8],
}
impl CharacterConfig {
fn new() -> CharacterConfig {
CharacterConfig {
raw_data: [0; 0xE8],
}
}
}
#[derive(Clone)]
pub struct Character { pub struct Character {
pub id: u32, pub id: u32,
pub user_id: u32, pub user_id: u32,
pub slot: u32, pub slot: u32,
pub character: character::Character,
pub name: String,
pub exp: u32,
pub char_class: CharacterClass,
pub section_id: SectionID,
pub appearance: CharacterAppearance,
pub techs: CharacterTechniques,
pub config: CharacterConfig,
}
impl std::default::Default for Character {
fn default() -> Character {
Character {
id: 0,
user_id: 0,
slot: 0,
name: "".into(),
exp: 0,
char_class: CharacterClass::HUmar,
section_id: SectionID::Viridia,
appearance: CharacterAppearance::default(),
techs: CharacterTechniques::new(),
config: CharacterConfig::new(),
}
}
} }

105
src/login/character.rs

@ -8,6 +8,7 @@ use libpso::packet::login::*;
use libpso::{PacketParseError, PSOPacket}; use libpso::{PacketParseError, PSOPacket};
use libpso::crypto::bb::PSOBBCipher; use libpso::crypto::bb::PSOBBCipher;
use libpso::item; use libpso::item;
use libpso::character::character;
use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY}; use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY};
use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId}; use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId};
@ -17,7 +18,7 @@ use libpso::{utf8_to_array, utf8_to_utf16_array};
use crate::entity::gateway::EntityGateway; use crate::entity::gateway::EntityGateway;
use crate::entity::account::{UserAccount, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM}; use crate::entity::account::{UserAccount, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM};
use crate::entity::item::{ItemDetail, ItemLocation, Weapon, Armor, Shield, Tool}; use crate::entity::item::{ItemDetail, ItemLocation, Weapon, Armor, Shield, Tool};
use crate::entity::character::Character;
use crate::entity::character::{Character, CharacterClass};
use crate::login::login::get_login_status; use crate::login::login::get_login_status;
@ -183,19 +184,15 @@ pub struct CharacterServerState<EG: EntityGateway> {
} }
fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAccount, preview: &CharacterPreview) { fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAccount, preview: &CharacterPreview) {
let mut char = entity_gateway.new_character_by_user(&user); let mut char = entity_gateway.new_character_by_user(&user);
char.slot = preview.slot;
char.character = preview.character.as_character();
new_character_from_preview(&mut char, preview);
entity_gateway.set_character(&char); entity_gateway.set_character(&char);
let new_weapon = match char.character.ch_class {
0 | 1 | 2 | 9 => item::weapon::WeaponType::Saber,
3 | 4 | 5 | 11 => item::weapon::WeaponType::Handgun,
6 | 7 | 8 | 10 => item::weapon::WeaponType::Cane,
_ => panic!()
let new_weapon = match char.char_class {
CharacterClass::HUmar | CharacterClass::HUnewearl | CharacterClass::HUcast | CharacterClass::HUcaseal => item::weapon::WeaponType::Saber,
CharacterClass::RAmar | CharacterClass::RAmarl | CharacterClass::RAcast | CharacterClass::RAcaseal => item::weapon::WeaponType::Handgun,
CharacterClass::FOmar| CharacterClass::FOmarl| CharacterClass::FOnewm | CharacterClass::FOnewearl => item::weapon::WeaponType::Cane,
}; };
entity_gateway.new_item( entity_gateway.new_item(
@ -330,9 +327,13 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
if select.reason == 0 { if select.reason == 0 {
let chars = client.characters.as_ref().unwrap(); let chars = client.characters.as_ref().unwrap();
Ok(if let Some(char) = &chars[select.slot as usize] { Ok(if let Some(char) = &chars[select.slot as usize] {
let (level, stats) = self.level_table.get_stats_from_exp(char.char_class, char.exp);
vec![SendCharacterPacket::CharacterPreview(CharacterPreview { vec![SendCharacterPacket::CharacterPreview(CharacterPreview {
slot: select.slot, slot: select.slot,
character: char.character.as_select_screen(),
character: SelectScreenCharacterBuilder::new()
.character(&char)
.level(level)
.build()
})] })]
} }
else { else {
@ -525,6 +526,88 @@ impl<EG: EntityGateway> ServerState for CharacterServerState<EG> {
} }
} }
fn new_character_from_preview(character: &mut Character, preview: &CharacterPreview) {
character.slot = preview.slot;
character.name = String::from_utf16_lossy(&preview.character.name);
character.section_id = preview.character.section_id.into();
character.char_class = preview.character.ch_class.into();
character.appearance.costume = preview.character.costume;
character.appearance.skin = preview.character.skin;
character.appearance.face = preview.character.face;
character.appearance.head = preview.character.head;
character.appearance.hair = preview.character.hair;
character.appearance.hair_r = preview.character.hair_r;
character.appearance.hair_g = preview.character.hair_g;
character.appearance.hair_b = preview.character.hair_b;
character.appearance.prop_x = preview.character.prop_x;
character.appearance.prop_y = preview.character.prop_y;
}
struct SelectScreenCharacterBuilder<'a> {
character: Option<&'a Character>,
level: Option<u32>,
}
impl<'a> SelectScreenCharacterBuilder<'a> {
fn new() -> SelectScreenCharacterBuilder<'a> {
SelectScreenCharacterBuilder {
character: None,
level: None,
}
}
fn character(self, character: &'a Character) -> SelectScreenCharacterBuilder<'a> {
SelectScreenCharacterBuilder {
character: Some(character),
..self
}
}
fn level(self, level: u32) -> SelectScreenCharacterBuilder<'a> {
SelectScreenCharacterBuilder {
level: Some(level),
..self
}
}
fn build(self) -> character::SelectScreenCharacter {
let character = self.character.unwrap();
let level = self.level.unwrap();
character::SelectScreenCharacter {
//exp: character.exp,
level: level - 1,
//guildcard: character.guildcard,
//_unknown: character._unknown3,
//name_color: character.name_color,
//model: character.model,
//_unused: [0; 15],
//name_color_checksum: character.name_color_checksum,
section_id: character.section_id.into(),
ch_class: character.char_class.into(),
//v2flags: character.v2flags,
//version: character.version,
//v1flags: character.v1flags,
costume: character.appearance.costume,
skin: character.appearance.skin,
face: character.appearance.face,
head: character.appearance.head,
hair: character.appearance.hair,
hair_r: character.appearance.hair_r,
hair_g: character.appearance.hair_g,
hair_b: character.appearance.hair_b,
prop_x: character.appearance.prop_x,
prop_y: character.appearance.prop_y,
name: utf8_to_utf16_array!(character.name, 16),
//play_time: character.play_time,
..character::SelectScreenCharacter::default()
}
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;

17
src/main.rs

@ -75,11 +75,12 @@ fn main() {
entity_gateway.set_user(&fake_user); entity_gateway.set_user(&fake_user);
entity_gateway.create_user_settings_by_user(&fake_user); entity_gateway.create_user_settings_by_user(&fake_user);
let mut character = entity_gateway.new_character_by_user(&fake_user); let mut character = entity_gateway.new_character_by_user(&fake_user);
character.character.name = utf8_to_utf16_array!("Test Char 1", 0x10);
character.name = "Test Char 1".into();
entity_gateway.set_character(&character); entity_gateway.set_character(&character);
let mut character = entity_gateway.new_character_by_user(&fake_user); let mut character = entity_gateway.new_character_by_user(&fake_user);
character.slot = 2; character.slot = 2;
character.character.name = utf8_to_utf16_array!("Test Char 2", 0x10);
character.name = "\tE12345678".into();
character.exp = 80000000;
entity_gateway.set_character(&character); entity_gateway.set_character(&character);
let fake_user2 = UserAccount { let fake_user2 = UserAccount {
@ -96,11 +97,11 @@ fn main() {
entity_gateway.set_user(&fake_user2); entity_gateway.set_user(&fake_user2);
entity_gateway.create_user_settings_by_user(&fake_user2); entity_gateway.create_user_settings_by_user(&fake_user2);
let mut character = entity_gateway.new_character_by_user(&fake_user2); let mut character = entity_gateway.new_character_by_user(&fake_user2);
character.character.name = utf8_to_utf16_array!("Test Char 3", 0x10);
character.name = "Test Char 3".into();
entity_gateway.set_character(&character); entity_gateway.set_character(&character);
let mut character = entity_gateway.new_character_by_user(&fake_user2); let mut character = entity_gateway.new_character_by_user(&fake_user2);
character.slot = 2; character.slot = 2;
character.character.name = utf8_to_utf16_array!("Test Char 4", 0x10);
character.name = "Test Char 4".into();
entity_gateway.set_character(&character); entity_gateway.set_character(&character);
let fake_user3 = UserAccount { let fake_user3 = UserAccount {
@ -117,11 +118,11 @@ fn main() {
entity_gateway.set_user(&fake_user3); entity_gateway.set_user(&fake_user3);
entity_gateway.create_user_settings_by_user(&fake_user3); entity_gateway.create_user_settings_by_user(&fake_user3);
let mut character = entity_gateway.new_character_by_user(&fake_user3); let mut character = entity_gateway.new_character_by_user(&fake_user3);
character.character.name = utf8_to_utf16_array!("Test Char 5", 0x10);
character.name = "Test Char 5".into();
entity_gateway.set_character(&character); entity_gateway.set_character(&character);
let mut character = entity_gateway.new_character_by_user(&fake_user3); let mut character = entity_gateway.new_character_by_user(&fake_user3);
character.slot = 2; character.slot = 2;
character.character.name = utf8_to_utf16_array!("Test Char 6", 0x10);
character.name = "Test Char 6".into();
entity_gateway.set_character(&character); entity_gateway.set_character(&character);
let fake_user4 = UserAccount { let fake_user4 = UserAccount {
@ -138,11 +139,11 @@ fn main() {
entity_gateway.set_user(&fake_user4); entity_gateway.set_user(&fake_user4);
entity_gateway.create_user_settings_by_user(&fake_user4); entity_gateway.create_user_settings_by_user(&fake_user4);
let mut character = entity_gateway.new_character_by_user(&fake_user4); let mut character = entity_gateway.new_character_by_user(&fake_user4);
character.character.name = utf8_to_utf16_array!("Test Char 7", 0x10);
character.name = "Test Char 7".into();
entity_gateway.set_character(&character); entity_gateway.set_character(&character);
let mut character = entity_gateway.new_character_by_user(&fake_user4); let mut character = entity_gateway.new_character_by_user(&fake_user4);
character.slot = 2; character.slot = 2;
character.character.name = utf8_to_utf16_array!("Test Char 8", 0x10);
character.name = "Test Char 8".into();
entity_gateway.set_character(&character); entity_gateway.set_character(&character);
async_std::task::block_on(async move { async_std::task::block_on(async move {

94
src/ship/character.rs

@ -1,40 +1,41 @@
use crate::common::leveltable::CharacterStats;
use libpso::character::character; use libpso::character::character;
use crate::common::leveltable::CharacterStats;
use crate::entity::character::Character;
use crate::ship::items::Inventory; use crate::ship::items::Inventory;
pub struct CharacterBuilder<'a> {
character: Option<&'a character::Character>,
// TODO: exp
pub struct CharacterBytesBuilder<'a> {
character: Option<&'a Character>,
stats: Option<&'a CharacterStats>, stats: Option<&'a CharacterStats>,
level: Option<u32>, level: Option<u32>,
} }
impl<'a> CharacterBuilder<'a> {
pub fn new() -> CharacterBuilder<'a> {
CharacterBuilder {
impl<'a> CharacterBytesBuilder<'a> {
pub fn new() -> CharacterBytesBuilder<'a> {
CharacterBytesBuilder {
character: None, character: None,
stats: None, stats: None,
level: None, level: None,
} }
} }
pub fn character(self, character: &'a character::Character) -> CharacterBuilder<'a> {
CharacterBuilder {
pub fn character(self, character: &'a Character) -> CharacterBytesBuilder<'a> {
CharacterBytesBuilder {
character: Some(character), character: Some(character),
..self ..self
} }
} }
pub fn stats(self, stats: &'a CharacterStats) -> CharacterBuilder<'a> {
CharacterBuilder {
pub fn stats(self, stats: &'a CharacterStats) -> CharacterBytesBuilder<'a> {
CharacterBytesBuilder {
stats: Some(stats), stats: Some(stats),
..self ..self
} }
} }
pub fn level(self, level: u32) -> CharacterBuilder<'a> {
CharacterBuilder {
pub fn level(self, level: u32) -> CharacterBytesBuilder<'a> {
CharacterBytesBuilder {
level: Some(level), level: Some(level),
..self ..self
} }
@ -45,6 +46,7 @@ impl<'a> CharacterBuilder<'a> {
let stats = self.stats.unwrap(); let stats = self.stats.unwrap();
let level = self.level.unwrap(); let level = self.level.unwrap();
character::Character { character::Character {
name: libpso::utf8_to_utf16_array!(character.name, 16),
hp: stats.hp, hp: stats.hp,
atp: stats.atp, atp: stats.atp,
mst: stats.mst, mst: stats.mst,
@ -53,53 +55,83 @@ impl<'a> CharacterBuilder<'a> {
ata: stats.ata, ata: stats.ata,
lck: stats.lck, lck: stats.lck,
level: level, level: level,
..*character
section_id: character.section_id.into(),
ch_class: character.char_class.into(),
costume: character.appearance.costume,
skin: character.appearance.skin,
face: character.appearance.face,
head: character.appearance.head,
hair: character.appearance.hair,
hair_r: character.appearance.hair_r,
hair_g: character.appearance.hair_g,
hair_b: character.appearance.hair_b,
prop_x: character.appearance.prop_x,
prop_y: character.appearance.prop_y,
..character::Character::default()
} }
} }
} }
pub struct FullCharacterBuilder<'a> {
character: Option<&'a character::Character>,
pub struct FullCharacterBytesBuilder<'a> {
character: Option<&'a Character>,
stats: Option<&'a CharacterStats>,
level: Option<u32>,
inventory: Option<&'a Inventory>, inventory: Option<&'a Inventory>,
key_config: Option<&'a [u8; 0x16C]>, key_config: Option<&'a [u8; 0x16C]>,
joystick_config: Option<&'a [u8; 0x38]>, joystick_config: Option<&'a [u8; 0x38]>,
} }
impl<'a> FullCharacterBuilder<'a> {
pub fn new() -> FullCharacterBuilder<'a> {
FullCharacterBuilder {
impl<'a> FullCharacterBytesBuilder<'a> {
pub fn new() -> FullCharacterBytesBuilder<'a> {
FullCharacterBytesBuilder {
character: None, character: None,
stats: None,
level: None,
inventory: None, inventory: None,
key_config: None, key_config: None,
joystick_config: None, joystick_config: None,
} }
} }
pub fn character(self, character: &'a character::Character) -> FullCharacterBuilder<'a> {
FullCharacterBuilder {
pub fn character(self, character: &'a Character) -> FullCharacterBytesBuilder<'a> {
FullCharacterBytesBuilder {
character: Some(character), character: Some(character),
..self ..self
} }
} }
pub fn inventory(self, inventory: &'a Inventory) -> FullCharacterBuilder<'a> {
FullCharacterBuilder {
pub fn stats(self, stats: &'a CharacterStats) -> FullCharacterBytesBuilder<'a> {
FullCharacterBytesBuilder {
stats: Some(stats),
..self
}
}
pub fn level(self, level: u32) -> FullCharacterBytesBuilder<'a> {
FullCharacterBytesBuilder {
level: Some(level),
..self
}
}
pub fn inventory(self, inventory: &'a Inventory) -> FullCharacterBytesBuilder<'a> {
FullCharacterBytesBuilder {
inventory: Some(inventory), inventory: Some(inventory),
..self ..self
} }
} }
pub fn key_config(self, key_config: &'a [u8; 0x16C]) -> FullCharacterBuilder<'a> {
FullCharacterBuilder {
pub fn key_config(self, key_config: &'a [u8; 0x16C]) -> FullCharacterBytesBuilder<'a> {
FullCharacterBytesBuilder {
key_config: Some(key_config), key_config: Some(key_config),
..self ..self
} }
} }
pub fn joystick_config(self, joystick_config: &'a [u8; 0x38]) -> FullCharacterBuilder<'a> {
FullCharacterBuilder {
pub fn joystick_config(self, joystick_config: &'a [u8; 0x38]) -> FullCharacterBytesBuilder<'a> {
FullCharacterBytesBuilder {
joystick_config: Some(joystick_config), joystick_config: Some(joystick_config),
..self ..self
} }
@ -107,12 +139,18 @@ impl<'a> FullCharacterBuilder<'a> {
pub fn build(self) -> character::FullCharacter { pub fn build(self) -> character::FullCharacter {
let character = self.character.unwrap(); let character = self.character.unwrap();
let stats = self.stats.unwrap();
let level = self.level.unwrap();
let inventory = self.inventory.unwrap(); let inventory = self.inventory.unwrap();
let key_config = self.key_config.unwrap(); let key_config = self.key_config.unwrap();
let joystick_config = self.joystick_config.unwrap(); let joystick_config = self.joystick_config.unwrap();
character::FullCharacter { character::FullCharacter {
character: *character,
character: CharacterBytesBuilder::new()
.character(&character)
.stats(&stats)
.level(level - 1)
.build(),
inventory: character::Inventory { inventory: character::Inventory {
item_count: inventory.count() as u8, item_count: inventory.count() as u8,
items: inventory.as_client_inventory_items(), items: inventory.as_client_inventory_items(),

35
src/ship/ship.rs

@ -20,7 +20,7 @@ use crate::entity::character::Character;
use crate::entity::item::{ItemLocation, Item}; use crate::entity::item::{ItemLocation, Item};
use crate::login::login::get_login_status; use crate::login::login::get_login_status;
use crate::ship::location::{ClientLocation, LobbyId, RoomId, AreaType, MAX_ROOMS}; use crate::ship::location::{ClientLocation, LobbyId, RoomId, AreaType, MAX_ROOMS};
use crate::ship::character::{CharacterBuilder, FullCharacterBuilder};
use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder};
use crate::ship::items; use crate::ship::items;
use crate::ship::room; use crate::ship::room;
@ -162,13 +162,14 @@ impl<EG: EntityGateway> ShipServerState<EG> {
Ok(match get_login_status(&self.entity_gateway, pkt) { Ok(match get_login_status(&self.entity_gateway, pkt) {
Ok(user) => { Ok(user) => {
let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new());
response.guildcard = user.guildcard.map_or(24, |gc| gc) as u32;
response.guildcard = user.id as u32;
response.team_id = user.team_id.map_or(31, |ti| ti) as u32; response.team_id = user.team_id.map_or(31, |ti| ti) as u32;
let characters = self.entity_gateway.get_characters_by_user(&user); let characters = self.entity_gateway.get_characters_by_user(&user);
let character = characters let character = characters
.get(pkt.session.character_slot as usize) .get(pkt.session.character_slot as usize)
.ok_or(ShipError::InvalidSlot(id, pkt.session.character_slot as u32))?
.ok_or(ShipError::NoCharacterInSlot(id, pkt.session.character_slot as u32))?;
.ok_or(ShipError::InvalidSlot(id, pkt.session.character_slot as u32))?.as_ref()
.ok_or(ShipError::NoCharacterInSlot(id, pkt.session.character_slot as u32))?
.clone();
let settings = self.entity_gateway.get_user_settings_by_user(&user) let settings = self.entity_gateway.get_user_settings_by_user(&user)
.ok_or(ShipError::ClientNotFound(id))?; .ok_or(ShipError::ClientNotFound(id))?;
@ -191,14 +192,12 @@ impl<EG: EntityGateway> ShipServerState<EG> {
let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
client.block = pkt.item as u32; client.block = pkt.item as u32;
let (level, stats) = self.level_table.get_stats_from_exp(character::Class::from(client.character.character.ch_class), client.character.character.exp);
let (level, stats) = self.level_table.get_stats_from_exp(client.character.char_class, client.character.exp);
let fc = FullCharacterBuilder::new()
.character(&CharacterBuilder::new()
.character(&client.character.character)
let fc = FullCharacterBytesBuilder::new()
.character(&client.character)
.stats(&stats) .stats(&stats)
.level(level - 1)
.build())
.level(level)
.inventory(&client.inventory) .inventory(&client.inventory)
.key_config(&client.settings.settings.key_config) .key_config(&client.settings.settings.key_config)
.joystick_config(&client.settings.settings.joystick_config) .joystick_config(&client.settings.settings.joystick_config)
@ -221,9 +220,9 @@ impl<EG: EntityGateway> ShipServerState<EG> {
let playerinfo = clients.iter() let playerinfo = clients.iter()
.map(|room_client| { .map(|room_client| {
let client = self.clients.get(&room_client.client_id).ok_or(ShipError::ClientNotFound(id)).unwrap(); let client = self.clients.get(&room_client.client_id).ok_or(ShipError::ClientNotFound(id)).unwrap();
let (level, stats) = self.level_table.get_stats_from_exp(character::Class::from(client.character.character.ch_class), client.character.character.exp);
let c = CharacterBuilder::new()
.character(&client.character.character)
let (level, stats) = self.level_table.get_stats_from_exp(client.character.char_class, client.character.exp);
let c = CharacterBytesBuilder::new()
.character(&client.character)
.stats(&stats) .stats(&stats)
.level(level - 1) .level(level - 1)
.build(); .build();
@ -268,9 +267,9 @@ impl<EG: EntityGateway> ShipServerState<EG> {
}; };
let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
let (level, stats) = self.level_table.get_stats_from_exp(character::Class::from(client.character.character.ch_class), client.character.character.exp);
let c = CharacterBuilder::new()
.character(&client.character.character)
let (level, stats) = self.level_table.get_stats_from_exp(client.character.char_class, client.character.exp);
let c = CharacterBytesBuilder::new()
.character(&client.character)
.stats(&stats) .stats(&stats)
.level(level - 1) .level(level - 1)
.build(); .build();
@ -334,7 +333,7 @@ impl<EG: EntityGateway> ShipServerState<EG> {
fn player_chat(&mut self, id: ClientId, msg: &PlayerChat) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> { fn player_chat(&mut self, id: ClientId, msg: &PlayerChat) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
let cmsg = PlayerChat::new(client.user.guildcard.unwrap(), msg.message.clone());
let cmsg = PlayerChat::new(client.user.id, msg.message.clone());
Ok(Box::new(self.client_location.get_area_by_user(id).clients().iter() Ok(Box::new(self.client_location.get_area_by_user(id).clients().iter()
.map(move |client| { .map(move |client| {
@ -364,7 +363,7 @@ impl<EG: EntityGateway> ShipServerState<EG> {
guildcard: client.user.id, guildcard: client.user.id,
_unknown1: [0; 5], _unknown1: [0; 5],
client_id: 0, client_id: 0,
name: client.character.character.name,
name: libpso::utf8_to_utf16_array!(client.character.name, 16),
_unknown2: 2, _unknown2: 2,
}, PlayerHeader::default(), PlayerHeader::default(), PlayerHeader::default()]; }, PlayerHeader::default(), PlayerHeader::default(), PlayerHeader::default()];

Loading…
Cancel
Save