You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

367 lines
7.1 KiB

use psopacket::{pso_packet, PSOPacketData};
use crate::{PSOPacket, PacketParseError, PSOPacketData};
use crate::utf8_to_utf16_array;
use crate::packet::messages::GameMessage;
//use character::character::FullCharacter;
use crate::character::character as character;
use crate::ConsumingBlob;
use std::io::Read;
const BLOCK_MENU_ID: u32 = 1;
pub const ROOM_MENU_ID: u32 = 2;
#[pso_packet(0x03)]
pub struct ShipWelcome {
#[utf8]
copyright: [u8; 0x60],
server_key: [u8; 48],
client_key: [u8; 48],
}
impl ShipWelcome {
pub fn new(server_key: [u8; 48], client_key: [u8; 48]) -> ShipWelcome {
let mut copyright = [0u8; 0x60];
copyright[..0x4B].clone_from_slice(b"Phantasy Star Online Blue Burst Game Server. Copyright 1999-2004 SONICTEAM.");
ShipWelcome {
copyright: copyright,
server_key: server_key,
client_key: client_key,
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct BlockEntry {
menu: u32,
item: u32,
flags: u16,
name: [u16; 0x11],
}
impl PSOPacketData for BlockEntry {
fn from_bytes<R: Read>(_cursor: &mut R) -> Result<Self, PacketParseError> {
unimplemented!();
}
fn as_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.extend_from_slice(&u32::to_le_bytes(self.menu));
bytes.extend_from_slice(&u32::to_le_bytes(self.item));
bytes.extend_from_slice(&u16::to_le_bytes(self.flags));
bytes.extend_from_slice(&unsafe { std::mem::transmute::<[u16; 0x11], [u8; 0x11*2]>(self.name) });
bytes
}
}
#[pso_packet(0xA1)]
pub struct ShipBlockList {
shipblock: BlockEntry,
blocks: Vec<BlockEntry>
}
impl ShipBlockList {
pub fn new(shipname: &str, num_blocks: usize) -> ShipBlockList {
ShipBlockList {
shipblock: BlockEntry {
menu: BLOCK_MENU_ID,
item: 0,
flags: 0,
name: utf8_to_utf16_array!(shipname, 0x11)
},
blocks: (0..num_blocks).map(|i| BlockEntry {
menu: BLOCK_MENU_ID,
item: i as u32 + 1,
flags: 0,
name: utf8_to_utf16_array!(format!("Block {}", i+1), 0x11)
}).collect()
}
}
}
// TODO: menu should be an enum
// TODO: or perhaps MenuSelect should be broken up into different structs based on menu
// TODO: i.e. ShipMenuSelect, BlockMenuSelect, etc
#[pso_packet(0x10)]
pub struct MenuSelect {
pub menu: u32,
pub item: u32,
}
#[pso_packet(0xE7)]
pub struct FullCharacter {
#[no_debug]
character: character::FullCharacter,
}
#[pso_packet(0x95)]
pub struct CharDataRequest {
}
// TODO: what does this even do?
#[pso_packet(0x61)]
pub struct CharData {
_unknown: [u8; 0x828]
}
#[pso_packet(0x60)]
pub struct Message {
msg: GameMessage,
}
impl Message {
pub fn new(msg: GameMessage) -> Message {
Message {
msg: msg,
}
}
}
#[pso_packet(0x62, manual_flag)]
pub struct DirectMessage {
flag: u32,
msg: GameMessage
}
impl DirectMessage {
pub fn new(target: u32, msg: GameMessage) -> DirectMessage {
DirectMessage {
flag: target,
msg: msg,
}
}
}
#[pso_packet(0x6D, manual_flag)]
struct Like62ButCooler {
pub flag: u32,
pub blob: ConsumingBlob,
}
#[derive(PSOPacketData, Clone, Copy, Default)]
pub struct PlayerHeader {
pub tag: u32,
pub guildcard: u32,
pub _unknown1: [u32; 5],
pub client_id: u32,
pub name: [u16; 16],
pub _unknown2: u32,
}
#[derive(PSOPacketData, Clone)]
pub struct PlayerInfo {
pub header: PlayerHeader,
pub inventory: character::Inventory,
pub character: character::Character,
}
#[pso_packet(0x67)]
pub struct JoinLobby {
pub client: u8,
pub leader: u8,
pub one: u8,
pub lobby: u8,
pub block: u16,
pub event: u16,
pub padding: u32,
pub playerinfo: Vec<PlayerInfo>,
}
#[pso_packet(0x68, manual_flag)]
pub struct AddToLobby {
flag: u32,
pub client: u8,
pub leader: u8,
pub one: u8,
pub lobby: u8,
pub block: u16,
pub event: u16,
pub padding: u32,
pub playerinfo: PlayerInfo,
}
#[pso_packet(0xC1)]
pub struct CreateRoom {
unknown: [u32; 2],
name: [u16; 16],
password: [u16; 16],
difficulty: u8,
battle: u8,
challenge: u8,
episode: u8,
single_player: u8,
padding: [u8; 3],
}
#[pso_packet(0x01)]
pub struct SmallDialog {
padding: [u32; 0x02],
msg: String,
}
impl SmallDialog {
pub fn new(msg: String) -> SmallDialog {
SmallDialog {
padding: [0; 0x02],
msg: msg,
}
}
}
#[pso_packet(0x64, manual_flag)]
pub struct JoinRoom {
flag: u32, // # of elements in players
maps: [u32; 0x20],
players: [PlayerHeader; 4],
client_id: u8,
leader_id: u8,
one: u8,
difficulty: u8, // TODO: enum
battle: u8,
event: u8,
section: u8,
challenge: u8,
random_seed: u32,
episode: u8,
one2: u8,
single_player: u8,
unknown: u8,
}
impl JoinRoom {
/*fn new() -> JoinRoom {
JoinRoom {
}
}*/
}
#[pso_packet(0x65, manual_flag)]
pub struct AddToRoom {
flag: u32,
pub client: u8,
pub leader: u8,
pub one: u8,
pub lobby: u8,
pub block: u16,
pub event: u16,
pub padding: u32,
pub playerinfo: PlayerInfo,
}
#[pso_packet(0x69)]
pub struct LeaveLobby {
client: u8,
leader: u8,
_padding: u16,
}
impl LeaveLobby {
pub fn new(client: u8, leader: u8) -> LeaveLobby {
LeaveLobby {
client: client,
leader: leader,
_padding: 0,
}
}
}
#[pso_packet(0x66)]
pub struct LeaveRoom {
client: u8,
leader: u8,
_padding: u16,
}
impl LeaveRoom {
pub fn new(client: u8, leader: u8) -> LeaveRoom {
LeaveRoom {
client: client,
leader: leader,
_padding: 0,
}
}
}
#[pso_packet(0x06)]
pub struct PlayerChat {
pub unknown: u32,
pub guildcard: u32,
pub message: String,
}
impl PlayerChat {
pub fn new(guildcard: u32, message: String) -> PlayerChat {
PlayerChat {
unknown: 0x00010000,
guildcard: guildcard,
message: message,
}
}
}
#[pso_packet(0x8A)]
pub struct RoomNameRequest {
}
#[pso_packet(0x8A)]
pub struct RoomNameResponse {
pub name: String,
}
#[pso_packet(0x7ED)]
pub struct UpdateConfig{
pub config: [u8; 0xE8],
}
#[pso_packet(0xD8)]
pub struct ViewInfoboardRequest {
}
#[derive(PSOPacketData, Clone)]
pub struct InfoboardResponse {
pub name: [u16; 16],
pub message: [u16; 172],
}
#[pso_packet(0xD8)]
pub struct ViewInfoboardResponse {
pub response: Vec<InfoboardResponse>,
}
#[pso_packet(0xD9)]
pub struct WriteInfoboard {
pub message: String,
}
#[pso_packet(0x08)]
pub struct RoomListRequest {
}
#[derive(PSOPacketData, Clone)]
pub struct RoomList {
pub menu_id: u32,
pub item_id: u32,
pub difficulty: u8,
pub players: u8,
pub name: [u16; 16],
pub episode: u8,
pub flags: u8,
}
#[pso_packet(0x08)]
pub struct RoomListResponse {
pub baseroom: RoomList,
pub rooms: Vec<RoomList>,
}