new drone, convert some macros to functions #32
							
								
								
									
										33
									
								
								.drone.yml
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								.drone.yml
									
									
									
									
									
								
							| @ -3,8 +3,14 @@ kind: pipeline | ||||
| type: docker | ||||
| name: test libpso | ||||
| 
 | ||||
| concurrency: | ||||
|     limit: 1 | ||||
| 
 | ||||
| environment: | ||||
|   CARGO_INCREMENTAL: false | ||||
| 
 | ||||
| steps: | ||||
| - name: cargo build | ||||
| - name: clean cache | ||||
|   image: rustlang/rust:nightly | ||||
|   volumes: | ||||
|   - name: cache | ||||
| @ -12,8 +18,8 @@ steps: | ||||
|   - name: target-cache | ||||
|     path: /drone/src/target | ||||
|   commands: | ||||
|   - cargo build  | ||||
| - name: cargo test | ||||
|   - cargo prune | ||||
| - name: build | ||||
|   image: rustlang/rust:nightly | ||||
|   volumes: | ||||
|   - name: cache | ||||
| @ -21,7 +27,25 @@ steps: | ||||
|   - name: target-cache | ||||
|     path: /drone/src/target | ||||
|   commands: | ||||
|   - cargo test | ||||
|   - cargo build | ||||
| - name: clippy! | ||||
|   image: rustlang/rust:nightly | ||||
|   volumes: | ||||
|   - name: cache | ||||
|     path: /usr/local/cargo | ||||
|   - name: target-cache | ||||
|     path: /drone/src/target | ||||
|   commands: | ||||
|   - cargo clippy -- --deny warnings | ||||
| - name: test | ||||
|   image: rustlang/rust:nightly | ||||
|   volumes: | ||||
|   - name: cache | ||||
|     path: /usr/local/cargo | ||||
|   - name: target-cache | ||||
|     path: /drone/src/target | ||||
|   commands: | ||||
|   - cargo test --jobs 1 | ||||
| 
 | ||||
| volumes: | ||||
| - name: cache | ||||
| @ -30,4 +54,3 @@ volumes: | ||||
| - name: target-cache | ||||
|   host: | ||||
|     path: /home/drone/cargo-cache | ||||
| 
 | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| [package] | ||||
| name = "libpso" | ||||
| version = "0.1.0" | ||||
| version = "0.0.1" | ||||
| authors = ["Jake Probst <jake.probst@gmail.com>"] | ||||
| edition = "2018" | ||||
| 
 | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| [package] | ||||
| name = "psopacket" | ||||
| version = "1.0.0" | ||||
| version = "0.0.1" | ||||
| authors = ["Jake Probst <jake.probst@gmail.com>"] | ||||
| edition = "2018" | ||||
| 
 | ||||
|  | ||||
| @ -149,14 +149,14 @@ fn generate_psopacket_impl(pkt_cmd: u16, name: syn::Ident, attrs: &Vec<AttrType> | ||||
|             fn from_bytes(data: &[u8]) -> Result<#name, PacketParseError> { | ||||
|                 let mut cur = std::io::Cursor::new(data); | ||||
|                 let mut b: [u8; 2] = [0; 2]; | ||||
|                 cur.read(&mut b).unwrap(); | ||||
|                 cur.read_exact(&mut b).unwrap(); | ||||
|                 let len = u16::from_le_bytes(b); | ||||
|                 cur.read(&mut b).unwrap(); | ||||
|                 cur.read_exact(&mut b).unwrap(); | ||||
|                 let cmd = u16::from_le_bytes(b); | ||||
|                 let mut f: [u8; 4] = [0; 4]; | ||||
| 
 | ||||
|                 let flag = if #include_flag { | ||||
|                     cur.read(&mut f).unwrap(); | ||||
|                     cur.read_exact(&mut f).unwrap(); | ||||
|                     u32::from_le_bytes(f) | ||||
|                 } | ||||
|                 else { 0 }; | ||||
| @ -542,9 +542,9 @@ fn generate_psomessage_impl(msg_cmd: u8, name: syn::Ident, attrs: &Vec<AttrType> | ||||
|             const CMD: u8 = #msg_cmd; | ||||
|             fn from_bytes<R: std::io::Read + std::io::Seek >(mut cur: &mut R) -> Result<#name, PacketParseError> { | ||||
|                 let mut buf1 = [0u8; 1]; | ||||
|                 cur.read(&mut buf1).unwrap(); | ||||
|                 cur.read_exact(&mut buf1).unwrap(); | ||||
|                 let cmd = buf1[0]; | ||||
|                 cur.read(&mut buf1).unwrap(); | ||||
|                 cur.read_exact(&mut buf1).unwrap(); | ||||
|                 let size = buf1[0]; | ||||
| 
 | ||||
|                 let mut subbuf = vec![0u8; size as usize * 4 - 2]; | ||||
|  | ||||
| @ -1,3 +1,4 @@ | ||||
| #![allow(clippy::module_inception)] | ||||
| pub mod settings; | ||||
| pub mod character; | ||||
| pub mod guildcard; | ||||
|  | ||||
| @ -48,7 +48,7 @@ impl PSOBBCipher { | ||||
|         for k in cipher.p_array.iter_mut() { | ||||
|             let mut pt = *k as u16; | ||||
|             pt = ((pt & 0x00FF) << 8) + ((pt & 0xFF00) >> 8); | ||||
|             *k = ((((*k >> 16) ^ pt as u32) << 16)) + pt as u32; | ||||
|             *k = (((*k >> 16) ^ pt as u32) << 16) + pt as u32; | ||||
|         } | ||||
| 
 | ||||
|         for i in 0..18 { | ||||
| @ -85,7 +85,7 @@ impl PSOBBCipher { | ||||
| } | ||||
| 
 | ||||
| impl PSOCipher for PSOBBCipher { | ||||
|     fn encrypt(&mut self, data: &Vec<u8>) -> Result<Vec<u8>, CipherError> { | ||||
|     fn encrypt(&mut self, data: &[u8]) -> Result<Vec<u8>, CipherError> { | ||||
|         let mut real_data = data.chunks(4).map(|k| { | ||||
|             u32::from_le_bytes([k[0], k[1], k[2], k[3]]) | ||||
|         }).collect::<Vec<_>>(); | ||||
| @ -106,9 +106,7 @@ impl PSOCipher for PSOBBCipher { | ||||
|             l ^= self.p_array[4]; | ||||
|             r ^= self.p_array[5]; | ||||
| 
 | ||||
|             let tmp = l; | ||||
|             l = r; | ||||
|             r = tmp; | ||||
|             std::mem::swap(&mut l, &mut r); | ||||
| 
 | ||||
|             result.extend_from_slice(&l.to_le_bytes()); | ||||
|             result.extend_from_slice(&r.to_le_bytes()); | ||||
| @ -117,7 +115,7 @@ impl PSOCipher for PSOBBCipher { | ||||
|         Ok(result) | ||||
|     } | ||||
| 
 | ||||
|     fn decrypt(&mut self, data: &Vec<u8>) -> Result<Vec<u8>, CipherError> { | ||||
|     fn decrypt(&mut self, data: &[u8]) -> Result<Vec<u8>, CipherError> { | ||||
|         if data.len() % 8 != 0 { | ||||
|             return Err(CipherError::InvalidSize); | ||||
|         } | ||||
| @ -139,9 +137,8 @@ impl PSOCipher for PSOBBCipher { | ||||
|             l ^= self.p_array[1]; | ||||
|             r ^= self.p_array[0]; | ||||
| 
 | ||||
|             let tmp = l; | ||||
|             l = r; | ||||
|             r = tmp; | ||||
| 
 | ||||
|             std::mem::swap(&mut l, &mut r); | ||||
| 
 | ||||
|             result.extend_from_slice(&l.to_le_bytes()); | ||||
|             result.extend_from_slice(&r.to_le_bytes()); | ||||
|  | ||||
| @ -10,8 +10,8 @@ pub enum CipherError { | ||||
| 
 | ||||
| 
 | ||||
| pub trait PSOCipher { | ||||
|     fn encrypt(&mut self, data: &Vec<u8>) -> Result<Vec<u8>, CipherError>; | ||||
|     fn decrypt(&mut self, data: &Vec<u8>) -> Result<Vec<u8>, CipherError>; | ||||
|     fn encrypt(&mut self, data: &[u8]) -> Result<Vec<u8>, CipherError>; | ||||
|     fn decrypt(&mut self, data: &[u8]) -> Result<Vec<u8>, CipherError>; | ||||
|     fn header_size(&self) -> usize; | ||||
|     fn block_size(&self) -> usize { | ||||
|         self.header_size() | ||||
| @ -24,12 +24,12 @@ pub struct NullCipher { | ||||
| } | ||||
| 
 | ||||
| impl PSOCipher for NullCipher { | ||||
|     fn encrypt(&mut self, data: &Vec<u8>) -> Result<Vec<u8>, CipherError> { | ||||
|         Ok(data.clone()) | ||||
|     fn encrypt(&mut self, data: &[u8]) -> Result<Vec<u8>, CipherError> { | ||||
|         Ok(data.to_vec()) | ||||
|     } | ||||
| 
 | ||||
|     fn decrypt(&mut self, data: &Vec<u8>) -> Result<Vec<u8>, CipherError> { | ||||
|         Ok(data.clone()) | ||||
|     fn decrypt(&mut self, data: &[u8]) -> Result<Vec<u8>, CipherError> { | ||||
|         Ok(data.to_vec()) | ||||
|     } | ||||
| 
 | ||||
|     fn header_size(&self) -> usize { | ||||
|  | ||||
| @ -31,15 +31,15 @@ impl PSOPCCipher { | ||||
|             eax = edi; | ||||
|             var1 = eax / W(55); | ||||
|             edx = eax - (var1 * W(55)); | ||||
|             ebx = ebx - esi; | ||||
|             edi = edi + W(0x15); | ||||
|             ebx -= esi; | ||||
|             edi += W(0x15); | ||||
|             stream[edx.0 as usize] = esi.0; | ||||
|             esi = ebx; | ||||
|             ebx = W(stream[edx.0 as usize]); | ||||
|         } | ||||
| 
 | ||||
|         let mut cipher = PSOPCCipher { | ||||
|             stream: stream, | ||||
|             stream, | ||||
|             offset: 1, | ||||
|         }; | ||||
|         
 | ||||
| @ -63,7 +63,7 @@ impl PSOPCCipher { | ||||
|         while edx > W(0) { | ||||
|             esi = W(self.stream[eax.0 as usize + 0x1F]); | ||||
|             ebp = W(self.stream[eax.0 as usize]); | ||||
|             ebp = ebp - esi; | ||||
|             ebp -= esi; | ||||
|             self.stream[eax.0 as usize] = ebp.0; | ||||
|             eax += W(1); | ||||
|             edx -= W(1); | ||||
| @ -74,7 +74,7 @@ impl PSOPCCipher { | ||||
|         while edx > W(0) { | ||||
|             esi = W(self.stream[eax.0 as usize - 0x18]); | ||||
|             ebp = W(self.stream[eax.0 as usize]); | ||||
|             ebp = ebp - esi; | ||||
|             ebp -= esi; | ||||
|             self.stream[eax.0 as usize] = ebp.0; | ||||
|             eax += W(1); | ||||
|             edx -= W(1); | ||||
| @ -94,7 +94,7 @@ impl PSOPCCipher { | ||||
| } | ||||
| 
 | ||||
| impl PSOCipher for PSOPCCipher { | ||||
|     fn encrypt(&mut self, data: &Vec<u8>) -> Result<Vec<u8>, CipherError> { | ||||
|     fn encrypt(&mut self, data: &[u8]) -> Result<Vec<u8>, CipherError> { | ||||
|         let mut result = Vec::new(); | ||||
|         if data.len() % 4 != 0 { | ||||
|             return Err(CipherError::InvalidSize) | ||||
| @ -108,7 +108,7 @@ impl PSOCipher for PSOPCCipher { | ||||
|         Ok(result) | ||||
|     } | ||||
|     
 | ||||
|     fn decrypt(&mut self, data: &Vec<u8>) -> Result<Vec<u8>, CipherError> { | ||||
|     fn decrypt(&mut self, data: &[u8]) -> Result<Vec<u8>, CipherError> { | ||||
|         self.encrypt(data) | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -4,7 +4,7 @@ pub mod crypto; | ||||
| pub mod packet; | ||||
| pub mod character; | ||||
| pub mod util; | ||||
| pub mod item; | ||||
| //pub mod item;
 | ||||
| 
 | ||||
| use std::io::{Read, Seek}; | ||||
| #[derive(Debug, PartialEq)] | ||||
| @ -119,7 +119,7 @@ impl PSOPacketData for ConsumingBlob { | ||||
|         let mut blob: Vec<u8> = Vec::new(); | ||||
|         cursor.read_to_end(&mut blob).map_err(|_| PacketParseError::ReadError)?; | ||||
|         Ok(ConsumingBlob { | ||||
|             blob: blob, | ||||
|             blob, | ||||
|         }) | ||||
|     } | ||||
|     fn as_bytes(&self) -> Vec<u8> { | ||||
|  | ||||
| @ -1,7 +1,8 @@ | ||||
| use chrono::{DateTime, Utc}; | ||||
| 
 | ||||
| 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; | ||||
| 
 | ||||
| @ -23,9 +24,9 @@ impl LoginWelcome { | ||||
|         let mut copyright = [0u8; 0x60]; | ||||
|         copyright[..0x4B].clone_from_slice(b"Phantasy Star Online Blue Burst Game Server. Copyright 1999-2004 SONICTEAM."); | ||||
|         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
 | ||||
| } | ||||
| 
 | ||||
| impl Session { | ||||
|     pub fn new() -> Session { | ||||
| impl Default for Session { | ||||
|     fn default() -> Session { | ||||
|         Session { | ||||
|             version: [0; 30], | ||||
|             session_id: 0, | ||||
| @ -179,12 +180,12 @@ pub struct LoginResponse { | ||||
| impl LoginResponse { | ||||
|     pub fn by_status(status: AccountStatus, session: Session) -> LoginResponse { | ||||
|         LoginResponse { | ||||
|             status: status, | ||||
|             status, | ||||
|             tag: 0x00010000, | ||||
|             //tag: 0x00000100,
 | ||||
|             guildcard: 0, | ||||
|             team_id: 0, | ||||
|             session: session, | ||||
|             session, | ||||
|             caps: 0x00000102, | ||||
|         } | ||||
|     } | ||||
| @ -193,9 +194,9 @@ impl LoginResponse { | ||||
|             status: AccountStatus::Ok, | ||||
|             tag: 0x00010000, | ||||
|             //tag: 0x00000100,
 | ||||
|             guildcard: guildcard, | ||||
|             team_id: team_id, | ||||
|             session: session, | ||||
|             guildcard, | ||||
|             team_id, | ||||
|             session, | ||||
|             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 { | ||||
|         SendKeyAndTeamSettings { | ||||
|             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; 8], | ||||
|             team_priv: 0, | ||||
| @ -254,8 +255,8 @@ pub struct RedirectClient { | ||||
| impl RedirectClient { | ||||
|     pub fn new(ip: u32, port: u16) -> RedirectClient { | ||||
|         RedirectClient { | ||||
|             ip: ip, | ||||
|             port: port, | ||||
|             ip, | ||||
|             port, | ||||
|             padding: 0, | ||||
|         } | ||||
|     } | ||||
| @ -275,7 +276,7 @@ pub struct ChecksumAck { | ||||
| impl ChecksumAck { | ||||
|     pub fn new(ack: u32) -> ChecksumAck { | ||||
|         ChecksumAck { | ||||
|             ack: ack, | ||||
|             ack, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -314,7 +315,7 @@ impl GuildcardDataHeader { | ||||
|         GuildcardDataHeader { | ||||
|             one: 1, | ||||
|             len: len as u32, | ||||
|             checksum: checksum | ||||
|             checksum, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -330,7 +331,6 @@ pub struct GuildcardDataChunk { | ||||
|     _unknown: u32, | ||||
|     chunk: u32, | ||||
|     pub buffer: [u8; GUILD_CARD_CHUNK_SIZE], | ||||
| 
 | ||||
|     len: usize, | ||||
| } | ||||
| 
 | ||||
| @ -338,9 +338,9 @@ impl GuildcardDataChunk { | ||||
|     pub fn new(chunk: u32, buffer: [u8; GUILD_CARD_CHUNK_SIZE], len: usize) -> GuildcardDataChunk { | ||||
|         GuildcardDataChunk { | ||||
|             _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 { | ||||
|     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 { | ||||
|     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), | ||||
|                 item: 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, | ||||
|             guildcard: 0, | ||||
|             team_id: 0, | ||||
|             session: Session::new(), | ||||
|             session: Session::default(), | ||||
|             caps: 0, | ||||
|         }; | ||||
| 
 | ||||
| @ -560,7 +560,7 @@ mod tests { | ||||
|     #[test] | ||||
|     fn test_session_size() { | ||||
|         use super::PSOPacketData; | ||||
|         let session = super::Session::new(); | ||||
|         let session = super::Session::default(); | ||||
|         assert!(session.as_bytes().len() == 40); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -764,21 +764,21 @@ impl PSOPacketData for TradeRequestCommand { | ||||
|                      0, 0, | ||||
|                      0, 0, 0, 0] | ||||
|                     .into_iter() | ||||
|                     .chain(meseta.to_le_bytes().to_vec().into_iter()) | ||||
|                     .chain(meseta.to_le_bytes().iter().copied()) | ||||
|                     .collect() | ||||
|             }, | ||||
|             TradeRequestCommand::AddItem(item_id, amount) => { | ||||
|                 vec![1u8, 0, 0, 0] | ||||
|                     .into_iter() | ||||
|                     .chain(item_id.to_le_bytes().to_vec().into_iter()) | ||||
|                     .chain(amount.to_le_bytes().to_vec().into_iter()) | ||||
|                     .chain(item_id.to_le_bytes().iter().copied()) | ||||
|                     .chain(amount.to_le_bytes().iter().copied()) | ||||
|                     .collect() | ||||
|             }, | ||||
|             TradeRequestCommand::RemoveItem(item_id, amount) => { | ||||
|                 vec![2u8, 0, 0, 0] | ||||
|                     .into_iter() | ||||
|                     .chain(item_id.to_le_bytes().to_vec().into_iter()) | ||||
|                     .chain(amount.to_le_bytes().to_vec().into_iter()) | ||||
|                     .chain(item_id.to_le_bytes().iter().copied()) | ||||
|                     .chain(amount.to_le_bytes().iter().copied()) | ||||
|                     .collect() | ||||
|             }, | ||||
|             TradeRequestCommand::Confirm => { | ||||
| @ -1178,7 +1178,7 @@ pub enum GameMessage { | ||||
|     PlayerTelepipe(PlayerTelepipe), | ||||
|     NpcSpawn(NpcSpawn), | ||||
|     ActivateBossWarp(ActivateBossWarp), | ||||
|     PlayerJoiningGame(PlayerJoiningGame), | ||||
|     PlayerJoiningGame(Box<PlayerJoiningGame>), | ||||
|     PlayerJoiningGame2(PlayerJoiningGame2), | ||||
|     BurstDone(BurstDone), | ||||
|     WordSelect(WordSelect), | ||||
| @ -1346,7 +1346,7 @@ impl PSOPacketData for GameMessage { | ||||
|             PlayerTelepipe::CMD => Ok(GameMessage::PlayerTelepipe(PlayerTelepipe::from_bytes(&mut cur)?)), | ||||
|             NpcSpawn::CMD => Ok(GameMessage::NpcSpawn(NpcSpawn::from_bytes(&mut cur)?)), | ||||
|             ActivateBossWarp::CMD => Ok(GameMessage::ActivateBossWarp(ActivateBossWarp::from_bytes(&mut cur)?)), | ||||
|             PlayerJoiningGame::CMD => Ok(GameMessage::PlayerJoiningGame(PlayerJoiningGame::from_bytes(&mut cur)?)), | ||||
|             PlayerJoiningGame::CMD => Ok(GameMessage::PlayerJoiningGame(Box::new(PlayerJoiningGame::from_bytes(&mut cur)?))), | ||||
|             PlayerJoiningGame2::CMD => Ok(GameMessage::PlayerJoiningGame2(PlayerJoiningGame2::from_bytes(&mut cur)?)), | ||||
|             BurstDone::CMD => Ok(GameMessage::BurstDone(BurstDone::from_bytes(&mut cur)?)), | ||||
|             WordSelect::CMD => Ok(GameMessage::WordSelect(WordSelect::from_bytes(&mut cur)?)), | ||||
| @ -1427,7 +1427,7 @@ impl PSOPacketData for GameMessage { | ||||
|             _ => Err(PacketParseError::UnknownMessage(byte[0], | ||||
|                                                       { | ||||
|                                                           let mut b = vec![0; len[0] as usize * 4]; | ||||
|                                                           cur.read(&mut b).unwrap(); | ||||
|                                                           cur.read_exact(&mut b).unwrap(); | ||||
|                                                           b.to_vec() | ||||
|                                                       } | ||||
|             )), | ||||
|  | ||||
| @ -19,10 +19,10 @@ pub struct PatchWelcome { | ||||
| impl PatchWelcome { | ||||
|     pub fn new(server_key: u32, client_key: u32) -> PatchWelcome { | ||||
|         PatchWelcome { | ||||
|             copyright: b"Patch Server. Copyright SonicTeam, LTD. 2001".clone(), | ||||
|             copyright: *b"Patch Server. Copyright SonicTeam, LTD. 2001", | ||||
|             padding: [0; 20], | ||||
|             server_key: server_key, | ||||
|             client_key: client_key, | ||||
|             server_key, | ||||
|             client_key, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -58,8 +58,8 @@ impl StartFileSend { | ||||
|             *dst = *src | ||||
|         } | ||||
|         StartFileSend { | ||||
|             id: id, | ||||
|             size: size, | ||||
|             id, | ||||
|             size, | ||||
|             filename: f, | ||||
|         } | ||||
|     } | ||||
| @ -106,31 +106,22 @@ impl PSOPacket for FileSend { | ||||
| 
 | ||||
| impl std::fmt::Debug for FileSend { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||||
|         write!(f, "packet FileSend {{\n").unwrap(); | ||||
|         write!(f, "    chunk_num: {:?}\n", self.chunk_num).unwrap(); | ||||
|         write!(f, "    checksum: {:X?}\n", self.checksum).unwrap(); | ||||
|         write!(f, "    chunk_size: {:X?}\n", self.chunk_size).unwrap(); | ||||
|         write!(f, "    buffer: [...a large array ...]\n").unwrap(); | ||||
|         write!(f, "}}") | ||||
|         writeln!(f, "packet FileSend {{").unwrap(); | ||||
|         writeln!(f, "    chunk_num: {:?}", self.chunk_num).unwrap(); | ||||
|         writeln!(f, "    checksum: {:X?}", self.checksum).unwrap(); | ||||
|         writeln!(f, "    chunk_size: {:X?}", self.chunk_size).unwrap(); | ||||
|         writeln!(f, "    buffer: [...a large array ...]").unwrap(); | ||||
|         writeln!(f, "}}") | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| #[pso_packet(0x08, no_flag)] | ||||
| pub struct EndFileSend { | ||||
|     padding: u32, | ||||
| } | ||||
| 
 | ||||
| impl EndFileSend { | ||||
|     pub fn new() -> EndFileSend { | ||||
|         EndFileSend { | ||||
|             padding: 0, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #[pso_packet(0x0B, no_flag)] | ||||
| pub struct PatchStartList { | ||||
| } | ||||
| @ -169,7 +160,7 @@ impl FileInfo { | ||||
|             *dst = *src | ||||
|         }; | ||||
|         FileInfo { | ||||
|             id: id, | ||||
|             id, | ||||
|             filename: f, | ||||
|         } | ||||
|     } | ||||
| @ -200,8 +191,8 @@ pub struct FilesToPatchMetadata { | ||||
| impl FilesToPatchMetadata { | ||||
|     pub fn new(data_size: u32, file_count: u32) -> FilesToPatchMetadata { | ||||
|         FilesToPatchMetadata { | ||||
|             data_size: data_size, | ||||
|             file_count: file_count, | ||||
|             data_size, | ||||
|             file_count, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -221,7 +212,7 @@ impl Message { | ||||
|     pub fn new(mut msg: String) -> Message { | ||||
|         msg.push('\0'); | ||||
|         Message { | ||||
|             msg: msg, | ||||
|             msg, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -237,8 +228,8 @@ pub struct RedirectClient { | ||||
| impl RedirectClient { | ||||
|     pub fn new(ip: u32, port: u16) -> RedirectClient { | ||||
|         RedirectClient { | ||||
|             ip: ip, | ||||
|             port: port, | ||||
|             ip, | ||||
|             port, | ||||
|             padding: 0, | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| use psopacket::{pso_packet, PSOPacketData}; | ||||
| use crate::{PSOPacket, PacketParseError, PSOPacketData}; | ||||
| use crate::utf8_to_utf16_array; | ||||
| use crate::util::utf8_to_utf16_array; | ||||
| use crate::packet::messages::GameMessage; | ||||
| //use character::character::FullCharacter;
 | ||||
| use crate::character::character as character; | ||||
| @ -26,9 +26,9 @@ impl 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, | ||||
|             copyright, | ||||
|             server_key, | ||||
|             client_key, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -82,13 +82,13 @@ impl ShipBlockList { | ||||
|                 menu: BLOCK_MENU_ID, | ||||
|                 item: 0, | ||||
|                 flags: 0, | ||||
|                 name: utf8_to_utf16_array!(shipname, 0x11) | ||||
|                 name: utf8_to_utf16_array(shipname) | ||||
|             }, | ||||
|             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) | ||||
|                 name: utf8_to_utf16_array(format!("Block {}", i+1)) | ||||
|             }).collect() | ||||
|         } | ||||
|     } | ||||
| @ -149,8 +149,8 @@ pub struct BurstDone72 { | ||||
|     target: u8, | ||||
| } | ||||
| 
 | ||||
| impl BurstDone72 { | ||||
|     pub fn new() -> BurstDone72 { | ||||
| impl Default for BurstDone72 { | ||||
|     fn default() -> BurstDone72 { | ||||
|         BurstDone72 { | ||||
|             msg: 0x72, | ||||
|             len: 3, | ||||
| @ -169,7 +169,7 @@ pub struct Message { | ||||
| impl Message { | ||||
|     pub fn new(msg: GameMessage) -> Message { | ||||
|         Message { | ||||
|             msg: msg, | ||||
|             msg, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -184,7 +184,7 @@ impl DirectMessage { | ||||
|     pub fn new(target: u32, msg: GameMessage) -> DirectMessage { | ||||
|         DirectMessage { | ||||
|             flag: target, | ||||
|             msg: msg, | ||||
|             msg, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -280,7 +280,7 @@ impl SmallDialog { | ||||
|         } | ||||
|         SmallDialog { | ||||
|             padding: [0; 0x02], | ||||
|             msg: msg, | ||||
|             msg, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -299,7 +299,7 @@ impl RightText { | ||||
|         } | ||||
|         RightText { | ||||
|             padding: [0; 0x02], | ||||
|             msg: msg, | ||||
|             msg, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -317,7 +317,7 @@ impl SmallLeftDialog { | ||||
|         } | ||||
|         SmallLeftDialog { | ||||
|             padding: [0x00004500, 0x45004500], | ||||
|             msg: msg, | ||||
|             msg, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -335,7 +335,7 @@ impl LargeDialog { | ||||
|         } | ||||
|         LargeDialog { | ||||
|             padding: [0, 0x45000000], | ||||
|             msg: msg, | ||||
|             msg, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -383,8 +383,8 @@ pub struct LeaveLobby { | ||||
| impl LeaveLobby { | ||||
|     pub fn new(client: u8, leader: u8) -> LeaveLobby { | ||||
|         LeaveLobby { | ||||
|             client: client, | ||||
|             leader: leader, | ||||
|             client, | ||||
|             leader, | ||||
|             _padding: 0, | ||||
|         } | ||||
|     } | ||||
| @ -400,8 +400,8 @@ pub struct LeaveRoom { | ||||
| impl LeaveRoom { | ||||
|     pub fn new(client: u8, leader: u8) -> LeaveRoom { | ||||
|         LeaveRoom { | ||||
|             client: client, | ||||
|             leader: leader, | ||||
|             client, | ||||
|             leader, | ||||
|             _padding: 0, | ||||
|         } | ||||
|     } | ||||
| @ -418,8 +418,8 @@ impl PlayerChat { | ||||
|     pub fn new(guildcard: u32, message: String) -> PlayerChat { | ||||
|         PlayerChat { | ||||
|             unknown: 0x00010000, | ||||
|             guildcard: guildcard, | ||||
|             message: message, | ||||
|             guildcard, | ||||
|             message, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -501,7 +501,7 @@ pub struct LobbyEntry { | ||||
| impl LobbyEntry { | ||||
|     pub fn new(menu_id: u32, lobby_id: u32) -> LobbyEntry { | ||||
|         LobbyEntry { | ||||
|             menu_id: menu_id, | ||||
|             menu_id, | ||||
|             item_id: lobby_id, | ||||
|             padding: 0, | ||||
|         } | ||||
| @ -514,8 +514,8 @@ pub struct LobbyList { | ||||
|     entries: [LobbyEntry; 16], | ||||
| } | ||||
| 
 | ||||
| impl LobbyList { | ||||
|     pub fn new() -> LobbyList { | ||||
| impl Default for LobbyList { | ||||
|     fn default() -> LobbyList { | ||||
|         let lobbies = (0..16).fold([LobbyEntry::default(); 16], | ||||
|             |mut acc, index| { | ||||
|                 acc[index].menu_id = LOBBY_MENU_ID; | ||||
|  | ||||
							
								
								
									
										50
									
								
								src/util.rs
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								src/util.rs
									
									
									
									
									
								
							| @ -2,7 +2,7 @@ | ||||
| pub fn array_to_utf8<const X: usize>(array: [u8; X]) -> Result<String, std::string::FromUtf8Error> { | ||||
|     String::from_utf8(array.to_vec()) | ||||
|         .map(|mut s| { | ||||
|             if let Some(index) = s.find("\u{0}") { | ||||
|             if let Some(index) = s.find('\u{0}') { | ||||
|                 s.truncate(index); | ||||
|             } | ||||
|             s | ||||
| @ -12,35 +12,23 @@ pub fn array_to_utf8<const X: usize>(array: [u8; X]) -> Result<String, std::stri | ||||
| pub fn array_to_utf16(array: &[u8]) -> String { | ||||
|     unsafe { | ||||
|         let (_, data, _) = array.align_to(); | ||||
|         String::from_utf16_lossy(&data).trim_matches(char::from(0)).into() | ||||
|         String::from_utf16_lossy(data).trim_matches(char::from(0)).into() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // TODO: const fn version of this! (helpful with tests)
 | ||||
| #[macro_export] | ||||
| macro_rules! utf8_to_array { | ||||
|     ($s: expr, $size: expr) => { | ||||
|         { | ||||
|             let mut array = [0u8; $size]; | ||||
|             let bytes = $s.as_bytes(); | ||||
|             array[..bytes.len()].clone_from_slice(&bytes); | ||||
|             array | ||||
|         } | ||||
|     } | ||||
| pub fn utf8_to_array<const N: usize>(s: impl Into<String>) -> [u8; N] { | ||||
|     let mut array = [0u8; N]; | ||||
|     let s = s.into(); | ||||
|     let bytes = s.as_bytes(); | ||||
|     array[..bytes.len()].clone_from_slice(bytes); | ||||
|     array | ||||
| } | ||||
| 
 | ||||
| #[macro_export] | ||||
| macro_rules! utf8_to_utf16_array { | ||||
|     ($s: expr, $size: expr) => { | ||||
|         { | ||||
|             let mut array = [0u16; $size]; | ||||
|             //let bytes = $s.as_bytes();
 | ||||
|             let bytes = $s.encode_utf16().collect::<Vec<_>>(); | ||||
|             array[..bytes.len()].clone_from_slice(&bytes); | ||||
|             array | ||||
|         } | ||||
|     } | ||||
| pub fn utf8_to_utf16_array<const N: usize>(s: impl Into<String>) -> [u16; N] { | ||||
|     let mut array = [0u16; N]; | ||||
|     let bytes = s.into().encode_utf16().collect::<Vec<_>>(); | ||||
|     array[..bytes.len()].clone_from_slice(&bytes); | ||||
|     array | ||||
| } | ||||
| 
 | ||||
| pub fn vec_to_array<T: Default + Copy, const N: usize>(vec: Vec<T>) -> [T; N] { | ||||
| @ -53,10 +41,12 @@ pub fn vec_to_array<T: Default + Copy, const N: usize>(vec: Vec<T>) -> [T; N] { | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| mod test { | ||||
|     use super::*; | ||||
| 
 | ||||
|     #[test] | ||||
|     fn test_utf8_to_array() { | ||||
|         let s = "asdf".to_owned(); | ||||
|         let a = utf8_to_array!(s, 8); | ||||
|         let a = utf8_to_array(s); | ||||
| 
 | ||||
|         let mut e = [0u8; 8]; | ||||
|         e[..4].clone_from_slice(b"asdf"); | ||||
| @ -64,14 +54,14 @@ mod test { | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn utf8_to_utf16_array() { | ||||
|         let utf16 = utf8_to_utf16_array!("asdf", 16); | ||||
|     fn test_utf8_to_utf16_array() { | ||||
|         let utf16 = utf8_to_utf16_array("asdf"); | ||||
|         assert!(utf16 == [97, 115, 100, 102, 0,0,0,0,0,0,0,0,0,0,0,0]) | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn utf8_to_utf16_array_unicode() { | ||||
|         let utf16 = utf8_to_utf16_array!("あいうえお", 16); | ||||
|     fn test_utf8_to_utf16_array_unicode() { | ||||
|         let utf16 = utf8_to_utf16_array("あいうえお"); | ||||
|         assert!(utf16 == [0x3042 , 0x3044, 0x3046, 0x3048, 0x304A, 0,0,0,0,0,0,0,0,0,0,0]) | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user