|
@ -1,7 +1,8 @@ |
|
|
use chrono::{DateTime, Utc};
|
|
|
use chrono::{DateTime, Utc};
|
|
|
|
|
|
|
|
|
use psopacket::{pso_packet, PSOPacketData};
|
|
|
use psopacket::{pso_packet, PSOPacketData};
|
|
|
use crate::{PSOPacket, PacketParseError, PSOPacketData, utf8_to_utf16_array};
|
|
|
|
|
|
|
|
|
use crate::{PSOPacket, PacketParseError, PSOPacketData};
|
|
|
|
|
|
use crate::util::utf8_to_utf16_array;
|
|
|
|
|
|
|
|
|
use crate::character::character::SelectScreenCharacter;
|
|
|
use crate::character::character::SelectScreenCharacter;
|
|
|
|
|
|
|
|
@ -23,9 +24,9 @@ impl LoginWelcome { |
|
|
let mut copyright = [0u8; 0x60];
|
|
|
let mut copyright = [0u8; 0x60];
|
|
|
copyright[..0x4B].clone_from_slice(b"Phantasy Star Online Blue Burst Game Server. Copyright 1999-2004 SONICTEAM.");
|
|
|
copyright[..0x4B].clone_from_slice(b"Phantasy Star Online Blue Burst Game Server. Copyright 1999-2004 SONICTEAM.");
|
|
|
LoginWelcome {
|
|
|
LoginWelcome {
|
|
|
copyright: copyright,
|
|
|
|
|
|
server_key: server_key,
|
|
|
|
|
|
client_key: client_key,
|
|
|
|
|
|
|
|
|
copyright,
|
|
|
|
|
|
server_key,
|
|
|
|
|
|
client_key,
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@ -75,8 +76,8 @@ pub struct Session { |
|
|
pub character_slot: u8, // 1..=4
|
|
|
pub character_slot: u8, // 1..=4
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
impl Session {
|
|
|
|
|
|
pub fn new() -> Session {
|
|
|
|
|
|
|
|
|
impl Default for Session {
|
|
|
|
|
|
fn default() -> Session {
|
|
|
Session {
|
|
|
Session {
|
|
|
version: [0; 30],
|
|
|
version: [0; 30],
|
|
|
session_id: 0,
|
|
|
session_id: 0,
|
|
@ -179,12 +180,12 @@ pub struct LoginResponse { |
|
|
impl LoginResponse {
|
|
|
impl LoginResponse {
|
|
|
pub fn by_status(status: AccountStatus, session: Session) -> LoginResponse {
|
|
|
pub fn by_status(status: AccountStatus, session: Session) -> LoginResponse {
|
|
|
LoginResponse {
|
|
|
LoginResponse {
|
|
|
status: status,
|
|
|
|
|
|
|
|
|
status,
|
|
|
tag: 0x00010000,
|
|
|
tag: 0x00010000,
|
|
|
//tag: 0x00000100,
|
|
|
//tag: 0x00000100,
|
|
|
guildcard: 0,
|
|
|
guildcard: 0,
|
|
|
team_id: 0,
|
|
|
team_id: 0,
|
|
|
session: session,
|
|
|
|
|
|
|
|
|
session,
|
|
|
caps: 0x00000102,
|
|
|
caps: 0x00000102,
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@ -193,9 +194,9 @@ impl LoginResponse { |
|
|
status: AccountStatus::Ok,
|
|
|
status: AccountStatus::Ok,
|
|
|
tag: 0x00010000,
|
|
|
tag: 0x00010000,
|
|
|
//tag: 0x00000100,
|
|
|
//tag: 0x00000100,
|
|
|
guildcard: guildcard,
|
|
|
|
|
|
team_id: team_id,
|
|
|
|
|
|
session: session,
|
|
|
|
|
|
|
|
|
guildcard,
|
|
|
|
|
|
team_id,
|
|
|
|
|
|
session,
|
|
|
caps: 0x00000102,
|
|
|
caps: 0x00000102,
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@ -228,10 +229,10 @@ impl SendKeyAndTeamSettings { |
|
|
pub fn new(keyboard_config: [u8; 0x16C], gamepad_config: [u8; 0x38], guildcard: u32, team_id: u32) -> SendKeyAndTeamSettings {
|
|
|
pub fn new(keyboard_config: [u8; 0x16C], gamepad_config: [u8; 0x38], guildcard: u32, team_id: u32) -> SendKeyAndTeamSettings {
|
|
|
SendKeyAndTeamSettings {
|
|
|
SendKeyAndTeamSettings {
|
|
|
unknown: [0; 0x114],
|
|
|
unknown: [0; 0x114],
|
|
|
keyboard_config: keyboard_config,
|
|
|
|
|
|
gamepad_config: gamepad_config,
|
|
|
|
|
|
guildcard: guildcard,
|
|
|
|
|
|
team_id: team_id,
|
|
|
|
|
|
|
|
|
keyboard_config,
|
|
|
|
|
|
gamepad_config,
|
|
|
|
|
|
guildcard,
|
|
|
|
|
|
team_id,
|
|
|
//team_info: [0; 2],
|
|
|
//team_info: [0; 2],
|
|
|
team_info: [0; 8],
|
|
|
team_info: [0; 8],
|
|
|
team_priv: 0,
|
|
|
team_priv: 0,
|
|
@ -254,8 +255,8 @@ pub struct RedirectClient { |
|
|
impl RedirectClient {
|
|
|
impl RedirectClient {
|
|
|
pub fn new(ip: u32, port: u16) -> RedirectClient {
|
|
|
pub fn new(ip: u32, port: u16) -> RedirectClient {
|
|
|
RedirectClient {
|
|
|
RedirectClient {
|
|
|
ip: ip,
|
|
|
|
|
|
port: port,
|
|
|
|
|
|
|
|
|
ip,
|
|
|
|
|
|
port,
|
|
|
padding: 0,
|
|
|
padding: 0,
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@ -275,7 +276,7 @@ pub struct ChecksumAck { |
|
|
impl ChecksumAck {
|
|
|
impl ChecksumAck {
|
|
|
pub fn new(ack: u32) -> ChecksumAck {
|
|
|
pub fn new(ack: u32) -> ChecksumAck {
|
|
|
ChecksumAck {
|
|
|
ChecksumAck {
|
|
|
ack: ack,
|
|
|
|
|
|
|
|
|
ack,
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@ -314,7 +315,7 @@ impl GuildcardDataHeader { |
|
|
GuildcardDataHeader {
|
|
|
GuildcardDataHeader {
|
|
|
one: 1,
|
|
|
one: 1,
|
|
|
len: len as u32,
|
|
|
len: len as u32,
|
|
|
checksum: checksum
|
|
|
|
|
|
|
|
|
checksum,
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@ -330,7 +331,6 @@ pub struct GuildcardDataChunk { |
|
|
_unknown: u32,
|
|
|
_unknown: u32,
|
|
|
chunk: u32,
|
|
|
chunk: u32,
|
|
|
pub buffer: [u8; GUILD_CARD_CHUNK_SIZE],
|
|
|
pub buffer: [u8; GUILD_CARD_CHUNK_SIZE],
|
|
|
|
|
|
|
|
|
len: usize,
|
|
|
len: usize,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
@ -338,9 +338,9 @@ impl GuildcardDataChunk { |
|
|
pub fn new(chunk: u32, buffer: [u8; GUILD_CARD_CHUNK_SIZE], len: usize) -> GuildcardDataChunk {
|
|
|
pub fn new(chunk: u32, buffer: [u8; GUILD_CARD_CHUNK_SIZE], len: usize) -> GuildcardDataChunk {
|
|
|
GuildcardDataChunk {
|
|
|
GuildcardDataChunk {
|
|
|
_unknown: 0,
|
|
|
_unknown: 0,
|
|
|
chunk: chunk as u32,
|
|
|
|
|
|
buffer: buffer,
|
|
|
|
|
|
len: len,
|
|
|
|
|
|
|
|
|
chunk,
|
|
|
|
|
|
buffer,
|
|
|
|
|
|
len,
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@ -371,12 +371,12 @@ impl PSOPacket for GuildcardDataChunk { |
|
|
|
|
|
|
|
|
impl std::fmt::Debug for GuildcardDataChunk {
|
|
|
impl std::fmt::Debug for GuildcardDataChunk {
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
|
write!(f, "packet GuildcardDataChunk {{\n").unwrap();
|
|
|
|
|
|
write!(f, " flag: {:?}\n", 0).unwrap();
|
|
|
|
|
|
write!(f, " _unknown: {:#X?}\n", self._unknown).unwrap();
|
|
|
|
|
|
write!(f, " chunk: {:#X?}\n", self.chunk).unwrap();
|
|
|
|
|
|
write!(f, " buffer: [0..{:#X}]\n", self.len).unwrap();
|
|
|
|
|
|
write!(f, "}}")
|
|
|
|
|
|
|
|
|
writeln!(f, "packet GuildcardDataChunk {{").unwrap();
|
|
|
|
|
|
writeln!(f, " flag: {:?}", 0).unwrap();
|
|
|
|
|
|
writeln!(f, " _unknown: {:#X?}", self._unknown).unwrap();
|
|
|
|
|
|
writeln!(f, " chunk: {:#X?}", self.chunk).unwrap();
|
|
|
|
|
|
writeln!(f, " buffer: [0..{:#X}]", self.len).unwrap();
|
|
|
|
|
|
writeln!(f, "}}")
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
@ -428,9 +428,9 @@ impl PSOPacket for ParamDataHeader { |
|
|
|
|
|
|
|
|
impl std::fmt::Debug for ParamDataHeader {
|
|
|
impl std::fmt::Debug for ParamDataHeader {
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
|
write!(f, "packet ParamDataHeader{{\n").unwrap();
|
|
|
|
|
|
write!(f, " files: [..]\n").unwrap();
|
|
|
|
|
|
write!(f, "}}")
|
|
|
|
|
|
|
|
|
writeln!(f, "packet ParamDataHeader{{").unwrap();
|
|
|
|
|
|
writeln!(f, " files: [..]").unwrap();
|
|
|
|
|
|
writeln!(f, "}}")
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
@ -492,9 +492,9 @@ impl ShipList { |
|
|
menu: ships.get(0).map(|s| s.menu).unwrap_or(0),
|
|
|
menu: ships.get(0).map(|s| s.menu).unwrap_or(0),
|
|
|
item: 0,
|
|
|
item: 0,
|
|
|
flags: 0,
|
|
|
flags: 0,
|
|
|
name: utf8_to_utf16_array!("Ship", 0x11),
|
|
|
|
|
|
|
|
|
name: utf8_to_utf16_array("Ship"),
|
|
|
},
|
|
|
},
|
|
|
ships: ships,
|
|
|
|
|
|
|
|
|
ships,
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@ -517,7 +517,7 @@ mod tests { |
|
|
tag: 0,
|
|
|
tag: 0,
|
|
|
guildcard: 0,
|
|
|
guildcard: 0,
|
|
|
team_id: 0,
|
|
|
team_id: 0,
|
|
|
session: Session::new(),
|
|
|
|
|
|
|
|
|
session: Session::default(),
|
|
|
caps: 0,
|
|
|
caps: 0,
|
|
|
};
|
|
|
};
|
|
|
|
|
|
|
|
@ -560,7 +560,7 @@ mod tests { |
|
|
#[test]
|
|
|
#[test]
|
|
|
fn test_session_size() {
|
|
|
fn test_session_size() {
|
|
|
use super::PSOPacketData;
|
|
|
use super::PSOPacketData;
|
|
|
let session = super::Session::new();
|
|
|
|
|
|
|
|
|
let session = super::Session::default();
|
|
|
assert!(session.as_bytes().len() == 40);
|
|
|
assert!(session.as_bytes().len() == 40);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|