use proper data structs that convert to what pso wants
This commit is contained in:
parent
81043891a1
commit
a74941441b
@ -1,7 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use serde_json::Value;
|
||||
use libpso::character::character::Class;
|
||||
use crate::entity::character::CharacterClass;
|
||||
|
||||
#[derive(Default, Copy, Clone, Debug, PartialEq)]
|
||||
pub struct CharacterStats {
|
||||
@ -27,7 +27,7 @@ struct CharacterLevelEntry {
|
||||
}
|
||||
|
||||
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(){
|
||||
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"),
|
||||
};
|
||||
|
||||
@ -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) {
|
||||
statlist
|
||||
.iter()
|
||||
@ -107,7 +107,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_stat_levels() {
|
||||
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 }));
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,251 @@
|
||||
use std::convert::{From, Into, TryFrom, TryInto};
|
||||
use std::collections::HashMap;
|
||||
|
||||
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 id: u32,
|
||||
pub user_id: 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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use libpso::packet::login::*;
|
||||
use libpso::{PacketParseError, PSOPacket};
|
||||
use libpso::crypto::bb::PSOBBCipher;
|
||||
use libpso::item;
|
||||
use libpso::character::character;
|
||||
|
||||
use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY};
|
||||
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::account::{UserAccount, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM};
|
||||
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;
|
||||
|
||||
@ -183,19 +184,15 @@ pub struct CharacterServerState<EG: EntityGateway> {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAccount, preview: &CharacterPreview) {
|
||||
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);
|
||||
|
||||
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(
|
||||
@ -330,9 +327,13 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
||||
if select.reason == 0 {
|
||||
let chars = client.characters.as_ref().unwrap();
|
||||
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 {
|
||||
slot: select.slot,
|
||||
character: char.character.as_select_screen(),
|
||||
character: SelectScreenCharacterBuilder::new()
|
||||
.character(&char)
|
||||
.level(level)
|
||||
.build()
|
||||
})]
|
||||
}
|
||||
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)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
17
src/main.rs
17
src/main.rs
@ -75,11 +75,12 @@ fn main() {
|
||||
entity_gateway.set_user(&fake_user);
|
||||
entity_gateway.create_user_settings_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);
|
||||
let mut character = entity_gateway.new_character_by_user(&fake_user);
|
||||
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);
|
||||
|
||||
let fake_user2 = UserAccount {
|
||||
@ -96,11 +97,11 @@ fn main() {
|
||||
entity_gateway.set_user(&fake_user2);
|
||||
entity_gateway.create_user_settings_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);
|
||||
let mut character = entity_gateway.new_character_by_user(&fake_user2);
|
||||
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);
|
||||
|
||||
let fake_user3 = UserAccount {
|
||||
@ -117,11 +118,11 @@ fn main() {
|
||||
entity_gateway.set_user(&fake_user3);
|
||||
entity_gateway.create_user_settings_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);
|
||||
let mut character = entity_gateway.new_character_by_user(&fake_user3);
|
||||
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);
|
||||
|
||||
let fake_user4 = UserAccount {
|
||||
@ -138,11 +139,11 @@ fn main() {
|
||||
entity_gateway.set_user(&fake_user4);
|
||||
entity_gateway.create_user_settings_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);
|
||||
let mut character = entity_gateway.new_character_by_user(&fake_user4);
|
||||
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);
|
||||
|
||||
async_std::task::block_on(async move {
|
||||
|
@ -1,40 +1,41 @@
|
||||
use crate::common::leveltable::CharacterStats;
|
||||
use libpso::character::character;
|
||||
use crate::common::leveltable::CharacterStats;
|
||||
use crate::entity::character::Character;
|
||||
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>,
|
||||
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,
|
||||
stats: 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),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stats(self, stats: &'a CharacterStats) -> CharacterBuilder<'a> {
|
||||
CharacterBuilder {
|
||||
pub fn stats(self, stats: &'a CharacterStats) -> CharacterBytesBuilder<'a> {
|
||||
CharacterBytesBuilder {
|
||||
stats: Some(stats),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn level(self, level: u32) -> CharacterBuilder<'a> {
|
||||
CharacterBuilder {
|
||||
pub fn level(self, level: u32) -> CharacterBytesBuilder<'a> {
|
||||
CharacterBytesBuilder {
|
||||
level: Some(level),
|
||||
..self
|
||||
}
|
||||
@ -45,6 +46,7 @@ impl<'a> CharacterBuilder<'a> {
|
||||
let stats = self.stats.unwrap();
|
||||
let level = self.level.unwrap();
|
||||
character::Character {
|
||||
name: libpso::utf8_to_utf16_array!(character.name, 16),
|
||||
hp: stats.hp,
|
||||
atp: stats.atp,
|
||||
mst: stats.mst,
|
||||
@ -53,53 +55,83 @@ impl<'a> CharacterBuilder<'a> {
|
||||
ata: stats.ata,
|
||||
lck: stats.lck,
|
||||
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>,
|
||||
key_config: Option<&'a [u8; 0x16C]>,
|
||||
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,
|
||||
stats: None,
|
||||
level: None,
|
||||
inventory: None,
|
||||
key_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),
|
||||
..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),
|
||||
..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),
|
||||
..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),
|
||||
..self
|
||||
}
|
||||
@ -107,12 +139,18 @@ impl<'a> FullCharacterBuilder<'a> {
|
||||
|
||||
pub fn build(self) -> character::FullCharacter {
|
||||
let character = self.character.unwrap();
|
||||
let stats = self.stats.unwrap();
|
||||
let level = self.level.unwrap();
|
||||
let inventory = self.inventory.unwrap();
|
||||
let key_config = self.key_config.unwrap();
|
||||
let joystick_config = self.joystick_config.unwrap();
|
||||
|
||||
|
||||
character::FullCharacter {
|
||||
character: *character,
|
||||
character: CharacterBytesBuilder::new()
|
||||
.character(&character)
|
||||
.stats(&stats)
|
||||
.level(level - 1)
|
||||
.build(),
|
||||
inventory: character::Inventory {
|
||||
item_count: inventory.count() as u8,
|
||||
items: inventory.as_client_inventory_items(),
|
||||
|
@ -20,7 +20,7 @@ use crate::entity::character::Character;
|
||||
use crate::entity::item::{ItemLocation, Item};
|
||||
use crate::login::login::get_login_status;
|
||||
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::room;
|
||||
|
||||
@ -162,13 +162,14 @@ impl<EG: EntityGateway> ShipServerState<EG> {
|
||||
Ok(match get_login_status(&self.entity_gateway, pkt) {
|
||||
Ok(user) => {
|
||||
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;
|
||||
let characters = self.entity_gateway.get_characters_by_user(&user);
|
||||
let character = characters
|
||||
.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)
|
||||
.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))?;
|
||||
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)
|
||||
.stats(&stats)
|
||||
.level(level - 1)
|
||||
.build())
|
||||
let fc = FullCharacterBytesBuilder::new()
|
||||
.character(&client.character)
|
||||
.stats(&stats)
|
||||
.level(level)
|
||||
.inventory(&client.inventory)
|
||||
.key_config(&client.settings.settings.key_config)
|
||||
.joystick_config(&client.settings.settings.joystick_config)
|
||||
@ -221,9 +220,9 @@ impl<EG: EntityGateway> ShipServerState<EG> {
|
||||
let playerinfo = clients.iter()
|
||||
.map(|room_client| {
|
||||
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)
|
||||
.level(level - 1)
|
||||
.build();
|
||||
@ -268,9 +267,9 @@ impl<EG: EntityGateway> ShipServerState<EG> {
|
||||
};
|
||||
|
||||
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)
|
||||
.level(level - 1)
|
||||
.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> {
|
||||
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()
|
||||
.map(move |client| {
|
||||
@ -364,7 +363,7 @@ impl<EG: EntityGateway> ShipServerState<EG> {
|
||||
guildcard: client.user.id,
|
||||
_unknown1: [0; 5],
|
||||
client_id: 0,
|
||||
name: client.character.character.name,
|
||||
name: libpso::utf8_to_utf16_array!(client.character.name, 16),
|
||||
_unknown2: 2,
|
||||
}, PlayerHeader::default(), PlayerHeader::default(), PlayerHeader::default()];
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user