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.

668 lines
13 KiB

5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
4 years ago
5 years ago
5 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. use psopacket::{pso_packet, PSOPacketData};
  2. use crate::{PSOPacket, PacketParseError, PSOPacketData};
  3. use crate::utf8_to_utf16_array;
  4. use crate::packet::messages::GameMessage;
  5. //use character::character::FullCharacter;
  6. use crate::character::character as character;
  7. use crate::character::character::BankItem;
  8. use crate::ConsumingBlob;
  9. use std::io::Read;
  10. pub const BLOCK_MENU_ID: u32 = 2;
  11. pub const ROOM_MENU_ID: u32 = 3;
  12. pub const LOBBY_MENU_ID: u32 = 4;
  13. #[pso_packet(0x03)]
  14. pub struct ShipWelcome {
  15. #[utf8]
  16. copyright: [u8; 0x60],
  17. server_key: [u8; 48],
  18. client_key: [u8; 48],
  19. }
  20. impl ShipWelcome {
  21. pub fn new(server_key: [u8; 48], client_key: [u8; 48]) -> ShipWelcome {
  22. let mut copyright = [0u8; 0x60];
  23. copyright[..0x4B].clone_from_slice(b"Phantasy Star Online Blue Burst Game Server. Copyright 1999-2004 SONICTEAM.");
  24. ShipWelcome {
  25. copyright: copyright,
  26. server_key: server_key,
  27. client_key: client_key,
  28. }
  29. }
  30. }
  31. #[derive(Debug, PartialEq, Clone)]
  32. pub struct BlockEntry {
  33. menu: u32,
  34. item: u32,
  35. flags: u16,
  36. name: [u16; 0x11],
  37. }
  38. impl PSOPacketData for BlockEntry {
  39. fn from_bytes<R: Read>(_cursor: &mut R) -> Result<Self, PacketParseError> {
  40. unimplemented!();
  41. }
  42. fn as_bytes(&self) -> Vec<u8> {
  43. let mut bytes = Vec::new();
  44. bytes.extend_from_slice(&u32::to_le_bytes(self.menu));
  45. bytes.extend_from_slice(&u32::to_le_bytes(self.item));
  46. bytes.extend_from_slice(&u16::to_le_bytes(self.flags));
  47. bytes.extend_from_slice(&unsafe { std::mem::transmute::<[u16; 0x11], [u8; 0x11*2]>(self.name) });
  48. bytes
  49. }
  50. }
  51. #[pso_packet(0xA0)]
  52. pub struct RequestShipList {
  53. unknown: [u8; 24],
  54. }
  55. #[pso_packet(0xA1)]
  56. pub struct RequestShipBlockList {
  57. unknown: [u8; 24],
  58. }
  59. #[pso_packet(0xA1)]
  60. pub struct ShipBlockList {
  61. shipblock: BlockEntry,
  62. blocks: Vec<BlockEntry>
  63. }
  64. impl ShipBlockList {
  65. pub fn new(shipname: &str, num_blocks: usize) -> ShipBlockList {
  66. ShipBlockList {
  67. shipblock: BlockEntry {
  68. menu: BLOCK_MENU_ID,
  69. item: 0,
  70. flags: 0,
  71. name: utf8_to_utf16_array!(shipname, 0x11)
  72. },
  73. blocks: (0..num_blocks).map(|i| BlockEntry {
  74. menu: BLOCK_MENU_ID,
  75. item: i as u32 + 1,
  76. flags: 0,
  77. name: utf8_to_utf16_array!(format!("Block {}", i+1), 0x11)
  78. }).collect()
  79. }
  80. }
  81. }
  82. // TODO: menu should be an enum
  83. // TODO: or perhaps MenuSelect should be broken up into different structs based on menu
  84. // TODO: i.e. ShipMenuSelect, BlockMenuSelect, etc
  85. #[pso_packet(0x10)]
  86. pub struct MenuSelect {
  87. pub menu: u32,
  88. pub item: u32,
  89. }
  90. #[pso_packet(0x09)]
  91. pub struct MenuDetail {
  92. pub menu: u32,
  93. pub item: u32,
  94. }
  95. #[pso_packet(0x10)]
  96. pub struct RoomPasswordReq {
  97. pub menu: u32,
  98. pub item: u32,
  99. pub password: [u16; 16],
  100. }
  101. #[pso_packet(0x84)]
  102. pub struct LobbySelect {
  103. pub menu: u32,
  104. pub lobby: u32,
  105. }
  106. #[pso_packet(0xE7)]
  107. pub struct FullCharacter {
  108. #[no_debug]
  109. character: character::FullCharacter,
  110. }
  111. #[pso_packet(0x95)]
  112. pub struct CharDataRequest {
  113. }
  114. // TODO: what does this even do?
  115. #[pso_packet(0x61)]
  116. pub struct CharData {
  117. _unknown: [u8; 0x828]
  118. }
  119. #[pso_packet(0x60)]
  120. pub struct BurstDone72 {
  121. msg: u8,
  122. len: u8,
  123. client: u8,
  124. target: u8,
  125. }
  126. impl BurstDone72 {
  127. pub fn new() -> BurstDone72 {
  128. BurstDone72 {
  129. msg: 0x72,
  130. len: 3,
  131. client: 0x18,
  132. target: 0x08,
  133. }
  134. }
  135. }
  136. #[pso_packet(0x60)]
  137. pub struct Message {
  138. msg: GameMessage,
  139. }
  140. impl Message {
  141. pub fn new(msg: GameMessage) -> Message {
  142. Message {
  143. msg: msg,
  144. }
  145. }
  146. }
  147. #[pso_packet(0x62, manual_flag)]
  148. pub struct DirectMessage {
  149. flag: u32,
  150. msg: GameMessage
  151. }
  152. impl DirectMessage {
  153. pub fn new(target: u32, msg: GameMessage) -> DirectMessage {
  154. DirectMessage {
  155. flag: target,
  156. msg: msg,
  157. }
  158. }
  159. }
  160. // this is a bit of a weird packet, 0x6C is in the 0x60 family in terms of function
  161. // but this is the only packet I could find that uses it
  162. #[pso_packet(0x6C, no_flag)]
  163. struct BankItemList {
  164. pub aflag: u32,
  165. pub cmd: u8, // 0xBC
  166. pub unknown: [u8; 3],
  167. pub size: u32,
  168. pub checksum: u32,
  169. pub item_count: u32,
  170. pub meseta: u32,
  171. pub items: Vec<BankItem>,
  172. }
  173. #[pso_packet(0x6D, manual_flag)]
  174. struct Like62ButCooler {
  175. pub flag: u32,
  176. pub blob: ConsumingBlob,
  177. }
  178. #[derive(PSOPacketData, Clone, Copy, Default)]
  179. pub struct PlayerHeader {
  180. pub tag: u32,
  181. pub guildcard: u32,
  182. pub _unknown1: [u32; 5],
  183. pub client_id: u32,
  184. pub name: [u16; 16],
  185. pub _unknown2: u32,
  186. }
  187. #[derive(PSOPacketData, Clone)]
  188. pub struct PlayerInfo {
  189. pub header: PlayerHeader,
  190. pub inventory: character::Inventory,
  191. pub character: character::Character,
  192. }
  193. #[pso_packet(0x67)]
  194. pub struct JoinLobby {
  195. pub client: u8,
  196. pub leader: u8,
  197. pub one: u8,
  198. pub lobby: u8,
  199. pub block: u16,
  200. pub event: u16,
  201. pub padding: u32,
  202. pub playerinfo: Vec<PlayerInfo>,
  203. }
  204. #[pso_packet(0x68, manual_flag)]
  205. pub struct AddToLobby {
  206. flag: u32,
  207. pub client: u8,
  208. pub leader: u8,
  209. pub one: u8,
  210. pub lobby: u8,
  211. pub block: u16,
  212. pub event: u16,
  213. pub padding: u32,
  214. pub playerinfo: PlayerInfo,
  215. }
  216. #[pso_packet(0xC1)]
  217. pub struct CreateRoom {
  218. unknown: [u32; 2],
  219. name: [u16; 16],
  220. password: [u16; 16],
  221. difficulty: u8,
  222. battle: u8,
  223. challenge: u8,
  224. episode: u8,
  225. single_player: u8,
  226. padding: [u8; 3],
  227. }
  228. #[pso_packet(0x01)]
  229. pub struct SmallDialog {
  230. padding: [u32; 0x02],
  231. msg: String,
  232. }
  233. impl SmallDialog {
  234. pub fn new(mut msg: String) -> SmallDialog {
  235. if !msg.ends_with('\0') {
  236. msg.push('\0');
  237. }
  238. SmallDialog {
  239. padding: [0; 0x02],
  240. msg: msg,
  241. }
  242. }
  243. }
  244. #[pso_packet(0x11)]
  245. pub struct SmallLeftDialog {
  246. padding: [u32; 0x02],
  247. msg: String,
  248. }
  249. impl SmallLeftDialog {
  250. pub fn new(mut msg: String) -> SmallLeftDialog {
  251. if !msg.ends_with('\0') {
  252. msg.push('\0');
  253. }
  254. SmallLeftDialog {
  255. padding: [0x00004500, 0x45004500],
  256. msg: msg,
  257. }
  258. }
  259. }
  260. #[pso_packet(0x64, manual_flag)]
  261. pub struct JoinRoom {
  262. pub flag: u32, // # of elements in players
  263. pub maps: [u32; 0x20],
  264. pub players: [PlayerHeader; 4],
  265. pub client: u8,
  266. pub leader: u8,
  267. pub one: u8,
  268. pub difficulty: u8, // TODO: enum
  269. pub battle: u8,
  270. pub event: u8,
  271. pub section: u8,
  272. pub challenge: u8,
  273. pub random_seed: u32,
  274. pub episode: u8,
  275. pub one2: u8,
  276. pub single_player: u8,
  277. pub unknown: u8,
  278. }
  279. #[pso_packet(0x65, manual_flag)]
  280. pub struct AddToRoom {
  281. pub flag: u32,
  282. pub client: u8,
  283. pub leader: u8,
  284. pub one: u8,
  285. pub lobby: u8,
  286. pub block: u16,
  287. pub event: u16,
  288. pub padding: u32,
  289. pub playerinfo: PlayerInfo,
  290. }
  291. #[pso_packet(0x69)]
  292. pub struct LeaveLobby {
  293. client: u8,
  294. leader: u8,
  295. _padding: u16,
  296. }
  297. impl LeaveLobby {
  298. pub fn new(client: u8, leader: u8) -> LeaveLobby {
  299. LeaveLobby {
  300. client: client,
  301. leader: leader,
  302. _padding: 0,
  303. }
  304. }
  305. }
  306. #[pso_packet(0x66)]
  307. pub struct LeaveRoom {
  308. client: u8,
  309. leader: u8,
  310. _padding: u16,
  311. }
  312. impl LeaveRoom {
  313. pub fn new(client: u8, leader: u8) -> LeaveRoom {
  314. LeaveRoom {
  315. client: client,
  316. leader: leader,
  317. _padding: 0,
  318. }
  319. }
  320. }
  321. #[pso_packet(0x06)]
  322. pub struct PlayerChat {
  323. pub unknown: u32,
  324. pub guildcard: u32,
  325. pub message: String,
  326. }
  327. impl PlayerChat {
  328. pub fn new(guildcard: u32, message: String) -> PlayerChat {
  329. PlayerChat {
  330. unknown: 0x00010000,
  331. guildcard: guildcard,
  332. message: message,
  333. }
  334. }
  335. }
  336. #[pso_packet(0x8A)]
  337. pub struct RoomNameRequest {
  338. }
  339. #[pso_packet(0x8A)]
  340. pub struct RoomNameResponse {
  341. pub name: String,
  342. }
  343. #[pso_packet(0x7ED)]
  344. pub struct UpdateConfig{
  345. pub config: [u8; 0xE8],
  346. }
  347. #[pso_packet(0xD8)]
  348. pub struct ViewInfoboardRequest {
  349. }
  350. #[pso_packet(0xDE)]
  351. pub struct RareMonsterList{
  352. pub ids: [u16; 16],
  353. }
  354. #[derive(PSOPacketData, Clone)]
  355. pub struct InfoboardResponse {
  356. pub name: [u16; 16],
  357. pub message: [u16; 172],
  358. }
  359. #[pso_packet(0xD8)]
  360. pub struct ViewInfoboardResponse {
  361. pub response: Vec<InfoboardResponse>,
  362. }
  363. #[pso_packet(0xD9)]
  364. pub struct WriteInfoboard {
  365. pub message: String,
  366. }
  367. #[pso_packet(0x08)]
  368. pub struct RoomListRequest {
  369. }
  370. #[derive(PSOPacketData, Clone)]
  371. pub struct RoomList {
  372. pub menu_id: u32,
  373. pub item_id: u32,
  374. pub difficulty: u8,
  375. pub players: u8,
  376. pub name: [u16; 16],
  377. pub episode: u8,
  378. pub flags: u8,
  379. }
  380. #[pso_packet(0x08)]
  381. pub struct RoomListResponse {
  382. pub baseroom: RoomList,
  383. pub rooms: Vec<RoomList>,
  384. }
  385. #[derive(PSOPacketData, Clone, Copy, Default)]
  386. pub struct LobbyEntry {
  387. menu_id: u32,
  388. item_id: u32,
  389. padding: u32,
  390. }
  391. impl LobbyEntry {
  392. pub fn new(menu_id: u32, lobby_id: u32) -> LobbyEntry {
  393. LobbyEntry {
  394. menu_id: menu_id,
  395. item_id: lobby_id,
  396. padding: 0,
  397. }
  398. }
  399. }
  400. #[pso_packet(0x83, manual_flag)]
  401. pub struct LobbyList {
  402. flag: u32,
  403. entries: [LobbyEntry; 16],
  404. }
  405. impl LobbyList {
  406. pub fn new() -> LobbyList {
  407. let lobbies = (0..16).fold([LobbyEntry::default(); 16],
  408. |mut acc, index| {
  409. acc[index].menu_id = LOBBY_MENU_ID;
  410. acc[index].item_id = index as u32;
  411. acc
  412. });
  413. LobbyList {
  414. flag: 0x0F,
  415. entries: lobbies,
  416. }
  417. }
  418. }
  419. #[pso_packet(0x6F)]
  420. pub struct DoneBursting {
  421. }
  422. #[pso_packet(0x16F)]
  423. pub struct DoneBursting2 {
  424. }
  425. #[pso_packet(0x98)]
  426. pub struct ClientCharacterData {
  427. pub data: [u8; 2088],
  428. }
  429. #[pso_packet(0xA2, manual_flag)]
  430. pub struct RequestQuestList {
  431. pub flag: u32,
  432. }
  433. #[derive(PSOPacketData, Clone, Copy)]
  434. pub struct QuestCategory {
  435. pub menu_id: u32,
  436. pub option_id: u32,
  437. pub name: [u16; 32],
  438. pub description: [u16; 122],
  439. }
  440. #[pso_packet(0xA2)]
  441. pub struct QuestCategoryList {
  442. pub quest_categories: Vec<QuestCategory>,
  443. }
  444. #[derive(PSOPacketData, Clone, Copy)]
  445. pub struct QuestEntry {
  446. pub menu_id: u32,
  447. pub category_id: u16,
  448. pub quest_id: u16,
  449. pub name: [u16; 32],
  450. pub description: [u16; 122],
  451. }
  452. #[pso_packet(0xA2)]
  453. pub struct QuestOptionList {
  454. pub quests: Vec<QuestEntry>,
  455. }
  456. #[pso_packet(0xA3)]
  457. pub struct QuestDetail {
  458. description: [u16; 288]
  459. }
  460. #[pso_packet(0x09)]
  461. pub struct QuestDetailRequest {
  462. pub menu: u32,
  463. pub category: u16,
  464. pub quest: u16,
  465. }
  466. #[pso_packet(0x10)]
  467. pub struct QuestMenuSelect {
  468. pub menu: u32,
  469. pub category: u16,
  470. pub quest: u16,
  471. }
  472. #[pso_packet(0x44)]
  473. pub struct QuestHeader {
  474. pub unknown1: [u8; 0x24],
  475. pub filename: [u8; 16],
  476. pub length: u32,
  477. pub name: [u8; 16],
  478. pub unknown2: [u8; 8],
  479. }
  480. #[pso_packet(0x44)]
  481. pub struct QuestFileRequest {
  482. pub filename: [u8; 16],
  483. }
  484. #[pso_packet(0x13, no_flag)]
  485. pub struct QuestChunk {
  486. pub chunk_num: u32,
  487. pub filename: [u8; 16],
  488. pub blob: [u8; 0x400],
  489. pub blob_length: u32,
  490. pub unknown: u32,
  491. }
  492. #[pso_packet(0x13, no_flag)]
  493. pub struct QuestChunkAck {
  494. pub chunk_num: u32,
  495. filename: [u8; 16],
  496. }
  497. #[pso_packet(0xAC)]
  498. pub struct DoneLoadingQuest {
  499. }
  500. #[pso_packet(0xE7)]
  501. pub struct FullCharacterData {
  502. pub character: character::FullCharacter
  503. }
  504. #[pso_packet(0x1ED)]
  505. pub struct SaveOptions {
  506. pub options: u32,
  507. }
  508. #[derive(PSOPacketData, Clone, Copy, Default)]
  509. pub struct TradeItem {
  510. pub item_data: [u8; 12],
  511. pub item_id: u32,
  512. pub item_data2: [u8; 4],
  513. }
  514. #[pso_packet(0xD0)]
  515. pub struct ItemsToTrade {
  516. pub trade_target: u8,
  517. pub unknown2: u8,
  518. pub count: u16,
  519. pub items: [TradeItem; 32],
  520. }
  521. #[pso_packet(0xD1)]
  522. pub struct AcknowledgeTrade {
  523. }
  524. #[pso_packet(0xD2)]
  525. pub struct TradeConfirmed {
  526. }
  527. #[pso_packet(0xD4)]
  528. pub struct CancelTrade {
  529. }
  530. #[pso_packet(0xD4, manual_flag)]
  531. pub struct TradeSuccessful {
  532. flag: u32,
  533. }
  534. impl std::default::Default for TradeSuccessful {
  535. fn default() -> TradeSuccessful {
  536. TradeSuccessful {
  537. flag: 1,
  538. }
  539. }
  540. }
  541. #[pso_packet(0xDA, no_flag)]
  542. pub struct LobbyEvent {
  543. pub event: u32,
  544. }
  545. #[pso_packet(0x4ED)]
  546. pub struct KeyboardConfig {
  547. pub keyboard_config: [u8; 364],
  548. }
  549. #[pso_packet(0x5ED)]
  550. pub struct GamepadConfig {
  551. pub gamepad_config: [u8; 56],
  552. }
  553. // same struct as libpso::packet::messages::GuildcardRecv
  554. #[pso_packet(0x4E8)]
  555. pub struct GuildcardAccept {
  556. id: u32,
  557. name: [u16; 0x18],
  558. team: [u16; 0x10],
  559. desc: [u16; 0x58],
  560. one: u8,
  561. language: u8,
  562. section_id: u8,
  563. class: u8,
  564. }