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.

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