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.

692 lines
13 KiB

5 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
1 year ago
4 years ago
4 years ago
5 years ago
1 year ago
4 years ago
4 years ago
4 years ago
4 years ago
1 year 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. #[nodebug]
  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(0x1A)]
  261. pub struct LargeDialog {
  262. padding: [u32; 0x02],
  263. msg: String,
  264. }
  265. impl LargeDialog {
  266. pub fn new(mut msg: String) -> LargeDialog {
  267. if !msg.ends_with('\0') {
  268. msg.push('\0');
  269. }
  270. LargeDialog {
  271. padding: [0, 0x45000000],
  272. msg: msg,
  273. }
  274. }
  275. }
  276. #[pso_packet(0x64, manual_flag)]
  277. pub struct JoinRoom {
  278. pub flag: u32, // # of elements in players
  279. pub maps: [u32; 0x20],
  280. pub players: [PlayerHeader; 4],
  281. pub client: u8,
  282. pub leader: u8,
  283. pub one: u8,
  284. pub difficulty: u8, // TODO: enum
  285. pub battle: u8,
  286. pub event: u8,
  287. pub section: u8,
  288. pub challenge: u8,
  289. pub random_seed: u32,
  290. pub episode: u8,
  291. pub one2: u8,
  292. pub single_player: u8,
  293. pub unknown: u8,
  294. }
  295. #[pso_packet(0x65, manual_flag)]
  296. pub struct AddToRoom {
  297. pub flag: u32,
  298. pub client: u8,
  299. pub leader: u8,
  300. pub one: u8,
  301. pub lobby: u8,
  302. pub block: u16,
  303. pub event: u16,
  304. pub padding: u32,
  305. pub playerinfo: PlayerInfo,
  306. }
  307. #[pso_packet(0x69)]
  308. pub struct LeaveLobby {
  309. client: u8,
  310. leader: u8,
  311. _padding: u16,
  312. }
  313. impl LeaveLobby {
  314. pub fn new(client: u8, leader: u8) -> LeaveLobby {
  315. LeaveLobby {
  316. client: client,
  317. leader: leader,
  318. _padding: 0,
  319. }
  320. }
  321. }
  322. #[pso_packet(0x66)]
  323. pub struct LeaveRoom {
  324. client: u8,
  325. leader: u8,
  326. _padding: u16,
  327. }
  328. impl LeaveRoom {
  329. pub fn new(client: u8, leader: u8) -> LeaveRoom {
  330. LeaveRoom {
  331. client: client,
  332. leader: leader,
  333. _padding: 0,
  334. }
  335. }
  336. }
  337. #[pso_packet(0x06)]
  338. pub struct PlayerChat {
  339. pub unknown: u32,
  340. pub guildcard: u32,
  341. pub message: String,
  342. }
  343. impl PlayerChat {
  344. pub fn new(guildcard: u32, message: String) -> PlayerChat {
  345. PlayerChat {
  346. unknown: 0x00010000,
  347. guildcard: guildcard,
  348. message: message,
  349. }
  350. }
  351. }
  352. #[pso_packet(0x8A)]
  353. pub struct RoomNameRequest {
  354. }
  355. #[pso_packet(0x8A)]
  356. pub struct RoomNameResponse {
  357. pub name: String,
  358. }
  359. #[pso_packet(0x6ED)]
  360. pub struct UpdateTechMenu {
  361. pub config: [u8; 0x28],
  362. }
  363. #[pso_packet(0x7ED)]
  364. pub struct UpdateConfig{
  365. pub config: [u8; 0xE8],
  366. }
  367. #[pso_packet(0xD8)]
  368. pub struct ViewInfoboardRequest {
  369. }
  370. #[pso_packet(0xDE)]
  371. pub struct RareMonsterList{
  372. pub ids: [u16; 16],
  373. }
  374. #[derive(PSOPacketData, Clone)]
  375. pub struct InfoboardResponse {
  376. pub name: [u16; 16],
  377. pub message: [u16; 172],
  378. }
  379. #[pso_packet(0xD8)]
  380. pub struct ViewInfoboardResponse {
  381. pub response: Vec<InfoboardResponse>,
  382. }
  383. #[pso_packet(0xD9)]
  384. pub struct WriteInfoboard {
  385. pub message: String,
  386. }
  387. #[pso_packet(0x08)]
  388. pub struct RoomListRequest {
  389. }
  390. #[derive(PSOPacketData, Clone)]
  391. pub struct RoomList {
  392. pub menu_id: u32,
  393. pub item_id: u32,
  394. pub difficulty: u8,
  395. pub players: u8,
  396. pub name: [u16; 16],
  397. pub episode: u8,
  398. pub flags: u8,
  399. }
  400. #[pso_packet(0x08)]
  401. pub struct RoomListResponse {
  402. pub baseroom: RoomList,
  403. pub rooms: Vec<RoomList>,
  404. }
  405. #[derive(PSOPacketData, Clone, Copy, Default)]
  406. pub struct LobbyEntry {
  407. menu_id: u32,
  408. item_id: u32,
  409. padding: u32,
  410. }
  411. impl LobbyEntry {
  412. pub fn new(menu_id: u32, lobby_id: u32) -> LobbyEntry {
  413. LobbyEntry {
  414. menu_id: menu_id,
  415. item_id: lobby_id,
  416. padding: 0,
  417. }
  418. }
  419. }
  420. #[pso_packet(0x83, manual_flag)]
  421. pub struct LobbyList {
  422. flag: u32,
  423. entries: [LobbyEntry; 16],
  424. }
  425. impl LobbyList {
  426. pub fn new() -> LobbyList {
  427. let lobbies = (0..16).fold([LobbyEntry::default(); 16],
  428. |mut acc, index| {
  429. acc[index].menu_id = LOBBY_MENU_ID;
  430. acc[index].item_id = index as u32;
  431. acc
  432. });
  433. LobbyList {
  434. flag: 0x0F,
  435. entries: lobbies,
  436. }
  437. }
  438. }
  439. #[pso_packet(0x6F)]
  440. pub struct DoneBursting {
  441. }
  442. #[pso_packet(0x16F)]
  443. pub struct DoneBursting2 {
  444. }
  445. #[pso_packet(0x98)]
  446. pub struct ClientCharacterData {
  447. pub data: [u8; 2088],
  448. }
  449. #[pso_packet(0xA2, manual_flag)]
  450. pub struct RequestQuestList {
  451. pub flag: u32,
  452. }
  453. #[derive(PSOPacketData, Clone, Copy)]
  454. pub struct QuestCategory {
  455. pub menu_id: u32,
  456. pub option_id: u32,
  457. pub name: [u16; 32],
  458. pub description: [u16; 122],
  459. }
  460. #[pso_packet(0xA2)]
  461. pub struct QuestCategoryList {
  462. pub quest_categories: Vec<QuestCategory>,
  463. }
  464. #[derive(PSOPacketData, Clone, Copy)]
  465. pub struct QuestEntry {
  466. pub menu_id: u32,
  467. pub category_id: u16,
  468. pub quest_id: u16,
  469. pub name: [u16; 32],
  470. pub description: [u16; 122],
  471. }
  472. #[pso_packet(0xA2)]
  473. pub struct QuestOptionList {
  474. pub quests: Vec<QuestEntry>,
  475. }
  476. #[pso_packet(0xA3)]
  477. pub struct QuestDetail {
  478. description: [u16; 288]
  479. }
  480. #[pso_packet(0x09)]
  481. pub struct QuestDetailRequest {
  482. pub menu: u32,
  483. pub category: u16,
  484. pub quest: u16,
  485. }
  486. #[pso_packet(0x10)]
  487. pub struct QuestMenuSelect {
  488. pub menu: u32,
  489. pub category: u16,
  490. pub quest: u16,
  491. }
  492. #[pso_packet(0x44)]
  493. pub struct QuestHeader {
  494. pub unknown1: [u8; 0x24],
  495. pub filename: [u8; 16],
  496. pub length: u32,
  497. pub name: [u8; 16],
  498. pub unknown2: [u8; 8],
  499. }
  500. #[pso_packet(0x44)]
  501. pub struct QuestFileRequest {
  502. pub filename: [u8; 16],
  503. }
  504. #[pso_packet(0x13, no_flag)]
  505. pub struct QuestChunk {
  506. pub chunk_num: u32,
  507. pub filename: [u8; 16],
  508. #[nodebug]
  509. pub blob: [u8; 0x400],
  510. pub blob_length: u32,
  511. pub unknown: u32,
  512. }
  513. #[pso_packet(0x13, no_flag)]
  514. pub struct QuestChunkAck {
  515. pub chunk_num: u32,
  516. filename: [u8; 16],
  517. }
  518. #[pso_packet(0xAC)]
  519. pub struct DoneLoadingQuest {
  520. }
  521. #[pso_packet(0xE7)]
  522. pub struct FullCharacterData {
  523. pub character: character::FullCharacter
  524. }
  525. #[pso_packet(0x1ED)]
  526. pub struct SaveOptions {
  527. pub options: u32,
  528. }
  529. #[derive(PSOPacketData, Clone, Copy, Default)]
  530. pub struct TradeItem {
  531. pub item_data: [u8; 12],
  532. pub item_id: u32,
  533. pub item_data2: [u8; 4],
  534. }
  535. #[pso_packet(0xD0)]
  536. pub struct ItemsToTrade {
  537. pub trade_target: u8,
  538. pub unknown2: u8,
  539. pub count: u16,
  540. pub items: [TradeItem; 32],
  541. }
  542. #[pso_packet(0xD1)]
  543. pub struct AcknowledgeTrade {
  544. }
  545. #[pso_packet(0xD2)]
  546. pub struct TradeConfirmed {
  547. }
  548. #[pso_packet(0xD4)]
  549. pub struct CancelTrade {
  550. }
  551. #[pso_packet(0xD4, manual_flag)]
  552. pub struct TradeSuccessful {
  553. flag: u32,
  554. }
  555. impl std::default::Default for TradeSuccessful {
  556. fn default() -> TradeSuccessful {
  557. TradeSuccessful {
  558. flag: 1,
  559. }
  560. }
  561. }
  562. #[pso_packet(0xDA, no_flag)]
  563. pub struct LobbyEvent {
  564. pub event: u32,
  565. }
  566. #[pso_packet(0x4ED)]
  567. pub struct KeyboardConfig {
  568. pub keyboard_config: [u8; 364],
  569. }
  570. #[pso_packet(0x5ED)]
  571. pub struct GamepadConfig {
  572. pub gamepad_config: [u8; 56],
  573. }
  574. // same struct as libpso::packet::messages::GuildcardRecv
  575. #[pso_packet(0x4E8)]
  576. pub struct GuildcardAccept {
  577. id: u32,
  578. name: [u16; 0x18],
  579. team: [u16; 0x10],
  580. desc: [u16; 0x58],
  581. one: u8,
  582. language: u8,
  583. section_id: u8,
  584. class: u8,
  585. }