Compare commits
	
		
			9 Commits
		
	
	
		
			master
			...
			cleanupper
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 0e2cac0f1b | |||
| 552f7d5774 | |||
| 05d505836c | |||
| 240ddc7e84 | |||
| c309e51f02 | |||
| d975874a64 | |||
| c7ea9c03e9 | |||
| 30739b5d87 | |||
| 908b58f1b9 | 
| @ -5,6 +5,8 @@ authors = ["Jake Probst <jake.probst@gmail.com>"] | ||||
| edition = "2018" | ||||
| 
 | ||||
| [dependencies] | ||||
| psopacket = { path = "psopacket" } | ||||
| rand = "0.6.5" | ||||
| chrono = "*" | ||||
| psopacket = { path = "psopacket" } | ||||
| serde = { version = "1.0", features = ["derive"]} | ||||
| strum = { version = "0.25.0", features = ["derive"] } | ||||
|  | ||||
| @ -8,6 +8,6 @@ edition = "2018" | ||||
| proc-macro = true | ||||
| 
 | ||||
| [dependencies] | ||||
| syn = {version = "1.0", features=["full", "extra-traits", "parsing"]} | ||||
| syn = {version = "2.0.39", features=["full", "extra-traits", "parsing"]} | ||||
| quote = "1.0" | ||||
| proc-macro2 = "1.0" | ||||
|  | ||||
| @ -6,8 +6,10 @@ | ||||
| extern crate proc_macro; | ||||
| 
 | ||||
| use proc_macro::TokenStream; | ||||
| use syn::{parse_macro_input, ItemStruct, NestedMeta, DeriveInput, Field}; | ||||
| use syn::{parse_macro_input, ItemStruct, DeriveInput, Field}; | ||||
| use syn::punctuated::Iter; | ||||
| use syn::punctuated::Punctuated; | ||||
| use syn::parse::Parse; | ||||
| use quote::quote; | ||||
| 
 | ||||
| #[derive(Debug, PartialEq)] | ||||
| @ -308,7 +310,7 @@ fn get_struct_fields(fields: Iter<Field>) -> Result<Vec<AttrType>, TokenStream> | ||||
|         } | ||||
|         let mut attr_meta = AttrMeta::None; | ||||
|         for attr in &field.attrs { | ||||
|             attr_meta = match attr.path.segments[0].ident.to_string().as_str() { | ||||
|             attr_meta = match attr.path().segments[0].ident.to_string().as_str() { | ||||
|                 "utf8" => AttrMeta::Utf8, | ||||
|                 "utf16" => AttrMeta::Utf16, | ||||
|                 "nodebug" => AttrMeta::NoDebug, | ||||
| @ -345,35 +347,52 @@ fn get_struct_fields(fields: Iter<Field>) -> Result<Vec<AttrType>, TokenStream> | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #[proc_macro_attribute] | ||||
| pub fn pso_packet(attr: TokenStream, item: TokenStream) -> TokenStream { | ||||
|     let args = parse_macro_input!(attr as syn::AttributeArgs); | ||||
|     let mut cmd = 0; | ||||
|     let mut flag = true; | ||||
|     let mut manual_flag = false; | ||||
|     for a in args { | ||||
|         match &a { | ||||
|             NestedMeta::Lit(lit) => { | ||||
|                 if let syn::Lit::Int(litint) = lit { | ||||
|                     cmd = litint.base10_parse().unwrap(); | ||||
|                 } | ||||
|             }, | ||||
|             NestedMeta::Meta(k) => { | ||||
|                 if let syn::Meta::Path(syn::Path {segments, ..}) = k { | ||||
|                     match segments[0].ident.to_string().as_str() { | ||||
|                         "no_flag" => flag = false, | ||||
|                         "manual_flag" => { | ||||
|                             flag = false; | ||||
|                             manual_flag = true; | ||||
|                         }, | ||||
|                         _ => { | ||||
|                             return syn::Error::new(segments[0].ident.span(), "unknown macro param").to_compile_error().into(); | ||||
| #[derive(Debug)] | ||||
| struct PSOPacketAttrs { | ||||
|     cmd: u16, | ||||
|     flag: bool, | ||||
|     manual_flag: bool, | ||||
| } | ||||
| 
 | ||||
| impl Parse for PSOPacketAttrs { | ||||
|     fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> { | ||||
|         let vars = Punctuated::<syn::Expr, syn::Token![,]>::parse_terminated(input)?; | ||||
| 
 | ||||
|         let (cmd, flag, manual_flag) = vars | ||||
|             .into_iter() | ||||
|             .fold((None, true, false), |mut acc, attr| { | ||||
|                 match attr { | ||||
|                     syn::Expr::Lit(lit) => { | ||||
|                         if let syn::Lit::Int(int) = lit.lit { | ||||
|                             acc.0 = int.base10_parse().ok(); | ||||
|                         } | ||||
|                     }, | ||||
|                     syn::Expr::Path(path) => { | ||||
|                         if path.path.is_ident("no_flag") { | ||||
|                             acc.1 = false; | ||||
|                         } | ||||
|                         if path.path.is_ident("manual_flag") { | ||||
|                             acc.1 = false; | ||||
|                             acc.2 = true; | ||||
|                         } | ||||
|                     } | ||||
|                     _ => {}, | ||||
|                 } | ||||
|             }, | ||||
|         } | ||||
|                 acc | ||||
|             }); | ||||
|         Ok(PSOPacketAttrs { | ||||
|             cmd: cmd.unwrap(), | ||||
|             flag, | ||||
|             manual_flag | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #[proc_macro_attribute] | ||||
| pub fn pso_packet(attr: TokenStream, item: TokenStream) -> TokenStream { | ||||
|     let args = parse_macro_input!(attr as PSOPacketAttrs); | ||||
| 
 | ||||
|     let pkt_struct = parse_macro_input!(item as ItemStruct); | ||||
|     let attrs = match get_struct_fields(pkt_struct.fields.iter()) { | ||||
| @ -381,7 +400,7 @@ pub fn pso_packet(attr: TokenStream, item: TokenStream) -> TokenStream { | ||||
|         Err(err) => return err | ||||
|     }; | ||||
| 
 | ||||
|     if manual_flag { | ||||
|     if args.manual_flag { | ||||
|         match &attrs[0] { | ||||
|             AttrType::Array(_, ident, _, _) => { | ||||
|                 if ident.to_string() != "flag" { | ||||
| @ -397,7 +416,7 @@ pub fn pso_packet(attr: TokenStream, item: TokenStream) -> TokenStream { | ||||
|     } | ||||
| 
 | ||||
|     let struct_def = generate_struct_def(pkt_struct.ident.clone(), &attrs); | ||||
|     let psopacket_impl = generate_psopacket_impl(cmd, pkt_struct.ident.clone(), &attrs, flag); | ||||
|     let psopacket_impl = generate_psopacket_impl(args.cmd, pkt_struct.ident.clone(), &attrs, args.flag); | ||||
|     let debug_impl =  generate_debug_impl(pkt_struct.ident.clone(), &attrs); | ||||
|     let partialeq_impl =  generate_partialeq_impl(pkt_struct.ident.clone(), &attrs); | ||||
| 
 | ||||
| @ -588,18 +607,10 @@ fn generate_psomessage_impl(msg_cmd: u8, name: syn::Ident, attrs: &Vec<AttrType> | ||||
| 
 | ||||
| #[proc_macro_attribute] | ||||
| pub fn pso_message(attr: TokenStream, item: TokenStream) -> TokenStream { | ||||
|     let args = parse_macro_input!(attr as syn::AttributeArgs); | ||||
|     let mut cmd = 0; | ||||
|     for a in args { | ||||
|         if let NestedMeta::Lit(lit) = a { | ||||
|             if let syn::Lit::Int(litint) = lit { | ||||
|                 cmd = litint.base10_parse().unwrap(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     let cmd = parse_macro_input!(attr as syn::LitInt).base10_parse().unwrap(); | ||||
|     let pkt_struct = parse_macro_input!(item as ItemStruct); | ||||
|     let mut attrs = match get_struct_fields(pkt_struct.fields.iter()) { | ||||
| 
 | ||||
|     let mut fields = match get_struct_fields(pkt_struct.fields.iter()) { | ||||
|         Ok(a) => a, | ||||
|         Err(err) => return err | ||||
|     }; | ||||
| @ -617,13 +628,13 @@ pub fn pso_message(attr: TokenStream, item: TokenStream) -> TokenStream { | ||||
|             segments: punctuated | ||||
|         } | ||||
|     }; | ||||
|     attrs.insert(0, AttrType::Value(u8tpath.clone(), syn::Ident::new("target", proc_macro2::Span::call_site()), AttrMeta::None)); | ||||
|     attrs.insert(0, AttrType::Value(u8tpath, syn::Ident::new("client", proc_macro2::Span::call_site()), AttrMeta::None)); | ||||
|     fields.insert(0, AttrType::Value(u8tpath.clone(), syn::Ident::new("target", proc_macro2::Span::call_site()), AttrMeta::None)); | ||||
|     fields.insert(0, AttrType::Value(u8tpath, syn::Ident::new("client", proc_macro2::Span::call_site()), AttrMeta::None)); | ||||
| 
 | ||||
|     let struct_def = generate_struct_def(pkt_struct.ident.clone(), &attrs); | ||||
|     let psopacket_impl = generate_psomessage_impl(cmd, pkt_struct.ident.clone(), &attrs); | ||||
|     let debug_impl =  generate_debug_impl(pkt_struct.ident.clone(), &attrs); | ||||
|     let partialeq_impl =  generate_partialeq_impl(pkt_struct.ident.clone(), &attrs); | ||||
|     let struct_def = generate_struct_def(pkt_struct.ident.clone(), &fields); | ||||
|     let psopacket_impl = generate_psomessage_impl(cmd, pkt_struct.ident.clone(), &fields); | ||||
|     let debug_impl =  generate_debug_impl(pkt_struct.ident.clone(), &fields); | ||||
|     let partialeq_impl =  generate_partialeq_impl(pkt_struct.ident.clone(), &fields); | ||||
| 
 | ||||
|     let q = quote!{ | ||||
|         #[derive(Clone)] | ||||
| @ -636,19 +647,7 @@ pub fn pso_message(attr: TokenStream, item: TokenStream) -> TokenStream { | ||||
|     q.into() | ||||
| } | ||||
| 
 | ||||
| #[proc_macro_derive(PSOPacketData)] | ||||
| pub fn pso_packet_data(input: TokenStream) -> TokenStream { | ||||
|     let derive = parse_macro_input!(input as DeriveInput); | ||||
| 
 | ||||
|     let name = derive.ident; | ||||
| 
 | ||||
|     let fields = if let syn::Data::Struct(strct) = derive.data { | ||||
|         strct.fields | ||||
|     } | ||||
|     else { | ||||
|         return syn::Error::new(name.span(), "PSOPacketData only works on structs").to_compile_error().into(); | ||||
|     }; | ||||
| 
 | ||||
| fn pso_packet_data_struct(name: syn::Ident, fields: syn::Fields) -> TokenStream { | ||||
|     let attrs = match get_struct_fields(fields.iter()) { | ||||
|         Ok(a) => a, | ||||
|         Err(err) => return err | ||||
| @ -684,3 +683,75 @@ pub fn pso_packet_data(input: TokenStream) -> TokenStream { | ||||
| 
 | ||||
|     q.into() | ||||
| } | ||||
| 
 | ||||
| fn pso_packet_data_enum<'a>(name: syn::Ident, repr_type: syn::Ident, variants: impl Iterator<Item = &'a syn::Variant> + Clone) -> TokenStream { | ||||
|     let value_to_variant = variants | ||||
|         .clone() | ||||
|         .enumerate() | ||||
|         .map(|(i, variant)| { | ||||
|             let variant = &variant.ident; | ||||
|             quote! { | ||||
|                 #i => #name::#variant, | ||||
|             } | ||||
|         }) | ||||
|         .collect::<Vec<_>>(); | ||||
| 
 | ||||
|     let variant_to_value = variants | ||||
|         .enumerate() | ||||
|         .map(|(i, variant)| { | ||||
|             let variant = &variant.ident; | ||||
|             quote! { | ||||
|                 #name::#variant => #repr_type::to_le_bytes(#i as #repr_type).to_vec(), | ||||
|             } | ||||
|         }) | ||||
|         .collect::<Vec<_>>(); | ||||
|     let impl_pso_data_packet = quote! { | ||||
|         impl PSOPacketData for #name { | ||||
|             fn from_bytes<R: std::io::Read + std::io::Seek>(mut cur: &mut R) -> Result<Self, PacketParseError> { | ||||
|                 let mut buf = #repr_type::default().to_le_bytes(); | ||||
|                 cur.read_exact(&mut buf).unwrap(); | ||||
|                 let value = #repr_type::from_le_bytes(buf); | ||||
| 
 | ||||
|                 Ok(match value as usize { | ||||
|                     #(#value_to_variant)* | ||||
|                     _ => return Err(PacketParseError::InvalidValue) | ||||
|                 }) | ||||
|             } | ||||
| 
 | ||||
|             fn as_bytes(&self) -> Vec<#repr_type> { | ||||
|                 match self { | ||||
|                     #(#variant_to_value)* | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     impl_pso_data_packet.into() | ||||
| } | ||||
| 
 | ||||
| #[proc_macro_derive(PSOPacketData)] | ||||
| pub fn pso_packet_data(input: TokenStream) -> TokenStream { | ||||
|     let derive = parse_macro_input!(input as DeriveInput); | ||||
| 
 | ||||
|     let name = derive.ident; | ||||
| 
 | ||||
|     if let syn::Data::Struct(strct) = derive.data { | ||||
|         pso_packet_data_struct(name, strct.fields) | ||||
|     } | ||||
|     else if let syn::Data::Enum(enm) = derive.data { | ||||
|         let repr_type = derive.attrs.iter().fold(None, |mut repr_type, attr| { | ||||
|             if attr.path().is_ident("repr") { | ||||
|                 attr.parse_nested_meta(|meta| { | ||||
|                     repr_type = Some(meta.path.get_ident().cloned().unwrap()); | ||||
|                     Ok(()) | ||||
|                 }).unwrap(); | ||||
|             } | ||||
|             repr_type | ||||
|         }); | ||||
| 
 | ||||
|         pso_packet_data_enum(name, repr_type.unwrap(), enm.variants.iter()) | ||||
|     } | ||||
|     else { | ||||
|         syn::Error::new(name.span(), "PSOPacketData only works on structs and enums").to_compile_error().into() | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,12 +1,13 @@ | ||||
| // TODO: ch_class to CharacterClass enum
 | ||||
| // TODO: section_id to SectionId enum
 | ||||
| // TODO: techniques to enum
 | ||||
| use psopacket::PSOPacketData; | ||||
| use crate::{PSOPacketData, PacketParseError}; | ||||
| use serde::{Serialize, Deserialize}; | ||||
| 
 | ||||
| #[repr(u32)] | ||||
| #[derive(Copy, Clone, Hash, PartialEq, Eq)] | ||||
| pub enum Class { | ||||
| 
 | ||||
| #[repr(u8)] | ||||
| #[derive(PSOPacketData, Default, Debug, Copy, Clone, Hash, PartialEq, Eq, strum::Display, strum::EnumString, Serialize, Deserialize)] | ||||
| pub enum CharacterClass { | ||||
|     #[default] | ||||
|     HUmar, | ||||
|     HUnewearl, | ||||
|     HUcast, | ||||
| @ -21,29 +22,78 @@ pub enum Class { | ||||
|     FOnewearl, | ||||
| } | ||||
| 
 | ||||
| impl std::convert::From<u8> for Class { | ||||
|     fn from(f: u8) -> Class { | ||||
| // TODO: TryFrom
 | ||||
| impl std::convert::From<u8> for CharacterClass { | ||||
|     fn from(f: u8) -> CharacterClass { | ||||
|         match f { | ||||
|             0 => Class::HUmar, | ||||
|             1 => Class::HUnewearl, | ||||
|             2 => Class::HUcast, | ||||
|             3 => Class::RAmar, | ||||
|             4 => Class::RAcast, | ||||
|             5 => Class::RAcaseal, | ||||
|             6 => Class::FOmarl, | ||||
|             7 => Class::FOnewm, | ||||
|             8 => Class::FOnewearl, | ||||
|             9 => Class::HUcaseal, | ||||
|             10 => Class::RAmarl, | ||||
|             11 => Class::FOmar, | ||||
|             0 => CharacterClass::HUmar, | ||||
|             1 => CharacterClass::HUnewearl, | ||||
|             2 => CharacterClass::HUcast, | ||||
|             3 => CharacterClass::RAmar, | ||||
|             4 => CharacterClass::RAcast, | ||||
|             5 => CharacterClass::RAcaseal, | ||||
|             6 => CharacterClass::FOmarl, | ||||
|             7 => CharacterClass::FOnewm, | ||||
|             8 => CharacterClass::FOnewearl, | ||||
|             9 => CharacterClass::HUcaseal, | ||||
|             10 => CharacterClass::RAmarl, | ||||
|             11 => CharacterClass::FOmar, | ||||
|             _ => panic!("unknown class") | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<CharacterClass> for u8 { | ||||
|     fn from(other: CharacterClass) -> u8 { | ||||
|         match other { | ||||
|              CharacterClass::HUmar => 0, | ||||
|              CharacterClass::HUnewearl => 1, | ||||
|              CharacterClass::HUcast => 2, | ||||
|              CharacterClass::RAmar => 3, | ||||
|              CharacterClass::RAcast => 4, | ||||
|              CharacterClass::RAcaseal => 5, | ||||
|              CharacterClass::FOmarl => 6, | ||||
|              CharacterClass::FOnewm => 7, | ||||
|              CharacterClass::FOnewearl => 8, | ||||
|              CharacterClass::HUcaseal => 9, | ||||
|              CharacterClass::FOmar => 10, | ||||
|              CharacterClass::RAmarl => 11, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl CharacterClass { | ||||
|     pub fn is_human(&self) -> bool { | ||||
|         matches!(self, | ||||
|                  CharacterClass::HUmar | | ||||
|                  CharacterClass::RAmar | | ||||
|                  CharacterClass::RAmarl | | ||||
|                  CharacterClass::FOmar | | ||||
|                  CharacterClass::FOmarl) | ||||
|     } | ||||
| 
 | ||||
|     pub fn is_newman(&self) -> bool { | ||||
|         matches!(self, | ||||
|                  CharacterClass::HUnewearl | | ||||
|                  CharacterClass::FOnewm | | ||||
|                  CharacterClass::FOnewearl) | ||||
|     } | ||||
| 
 | ||||
|     pub fn is_android(&self) -> bool { | ||||
|         matches!(self, | ||||
|                  CharacterClass::HUcast | | ||||
|                  CharacterClass::HUcaseal | | ||||
|                  CharacterClass::RAcast | | ||||
|                  CharacterClass::RAcaseal) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #[repr(u8)] | ||||
| #[derive(PSOPacketData, Default, Debug, Copy, Clone, Hash, PartialEq, Eq, strum::Display, strum::EnumString, Serialize, Deserialize)] | ||||
| pub enum SectionID { | ||||
|     #[default] | ||||
|     Viridia, | ||||
|     Greenill, | ||||
|     Skyly, | ||||
| @ -56,6 +106,42 @@ pub enum SectionID { | ||||
|     Whitill, | ||||
| } | ||||
| 
 | ||||
| // TODO: TryFrom
 | ||||
| impl From<u8> for SectionID { | ||||
|     fn from(id: u8) -> SectionID { | ||||
|         match id { | ||||
|             0 => SectionID::Viridia, | ||||
|             1 => SectionID::Greenill, | ||||
|             2 => SectionID::Skyly, | ||||
|             3 => SectionID::Bluefull, | ||||
|             4 => SectionID::Purplenum, | ||||
|             5 => SectionID::Pinkal, | ||||
|             6 => SectionID::Redria, | ||||
|             7 => SectionID::Oran, | ||||
|             8 => SectionID::Yellowboze, | ||||
|             9 => SectionID::Whitill, | ||||
|             _ => panic!(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<SectionID> for u8 { | ||||
|     fn from(other: SectionID) -> u8 { | ||||
|         match other { | ||||
|             SectionID::Viridia => 0, | ||||
|             SectionID::Greenill => 1, | ||||
|             SectionID::Skyly => 2, | ||||
|             SectionID::Bluefull => 3, | ||||
|             SectionID::Purplenum => 4, | ||||
|             SectionID::Pinkal => 5, | ||||
|             SectionID::Redria => 6, | ||||
|             SectionID::Oran => 7, | ||||
|             SectionID::Yellowboze => 8, | ||||
|             SectionID::Whitill => 9, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #[derive(PSOPacketData, Copy, Clone)] | ||||
| @ -80,8 +166,8 @@ pub struct Character { | ||||
|     pub _unused: [u8; 11], | ||||
|     pub play_time: u32, | ||||
|     pub name_color_checksum: u32, | ||||
|     pub section_id: u8, | ||||
|     pub ch_class: u8, | ||||
|     pub section_id: SectionID, | ||||
|     pub ch_class: CharacterClass, | ||||
|     pub v2flags: u8, | ||||
|     pub version: u8, | ||||
|     pub v1flags: u32, | ||||
| @ -149,8 +235,8 @@ pub struct SelectScreenCharacter { | ||||
|     pub model: u8, | ||||
|     pub _unused: [u8; 15], | ||||
|     pub name_color_checksum: u32, | ||||
|     pub section_id: u8, | ||||
|     pub ch_class: u8, | ||||
|     pub section_id: SectionID, | ||||
|     pub ch_class: CharacterClass, | ||||
|     pub v2flags: u8, | ||||
|     pub version: u8, | ||||
|     pub v1flags: u32, | ||||
| @ -301,8 +387,8 @@ pub struct FullCharacter { | ||||
|     pub guildcard_desc: [u16; 88], | ||||
|     pub _reserved1: u8, | ||||
|     pub _reserved2: u8, | ||||
|     pub section_id: u8, | ||||
|     pub char_class: u8, | ||||
|     pub section_id: SectionID, | ||||
|     pub char_class: CharacterClass, | ||||
|     pub _unknown2: u32, | ||||
|     pub symbol_chats: [u8; 0x4E0], | ||||
|     pub shortcuts: [u8; 2624], | ||||
|  | ||||
| @ -2,3 +2,5 @@ | ||||
| pub mod settings; | ||||
| pub mod character; | ||||
| pub mod guildcard; | ||||
| 
 | ||||
| pub use character::{SectionID, CharacterClass}; | ||||
|  | ||||
| @ -1,25 +1,37 @@ | ||||
| #![allow(dead_code)] | ||||
| pub mod weapon; | ||||
| pub mod tool; | ||||
| pub mod armor; | ||||
| pub mod shield; | ||||
| //pub mod tool;
 | ||||
| //pub mod armor;
 | ||||
| //pub mod shield;
 | ||||
| 
 | ||||
| use std::io::{Read, Seek}; | ||||
| use crate::{PacketParseError}; | ||||
| //use std::io::{Read, Seek};
 | ||||
| //use crate::{PacketParseError};
 | ||||
| 
 | ||||
| 
 | ||||
| pub trait ItemBytes { | ||||
|     fn as_bytes(&self) -> [u8; 16] { | ||||
|         // this is one of those things that should be easier than it is
 | ||||
|         let mut result = [0; 16]; | ||||
|         let (left, right) = result.split_at_mut(12); | ||||
|         left.copy_from_slice(&self.as_bytes_upper()); | ||||
|         right.copy_from_slice(&self.as_bytes_lower()); | ||||
|         result | ||||
|     } | ||||
|     fn as_bytes_upper(&self) -> [u8; 12]; | ||||
|     fn as_bytes_lower(&self) -> [u8; 4]; | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Copy, Clone)] | ||||
| pub enum Item { | ||||
|     Weapon(weapon::Weapon), | ||||
|     Armor(armor::Armor), | ||||
|     Shield(shield::Shield), | ||||
|     //Armor(armor::Armor),
 | ||||
|     //Shield(shield::Shield),
 | ||||
|     //Unit(Unit),
 | ||||
|     //Mag(Mag),
 | ||||
|     Tool(tool::Tool), | ||||
|     //Tool(tool::Tool),
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* | ||||
| impl Item { | ||||
|     fn from_bytes<R: Read + Seek>(_cursor: &mut R) -> Result<Self, PacketParseError> { | ||||
|         unimplemented!() | ||||
| @ -27,9 +39,9 @@ impl Item { | ||||
|     pub fn as_bytes(&self) -> [u8; 16] { | ||||
|         match self { | ||||
|             Item::Weapon(wep) => wep.as_bytes(), | ||||
|             Item::Armor(armor) => armor.as_bytes(), | ||||
|             Item::Shield(shield) => shield.as_bytes(), | ||||
|             Item::Tool(tool) => tool.as_bytes(), | ||||
|             //Item::Armor(armor) => armor.as_bytes(),
 | ||||
|             //Item::Shield(shield) => shield.as_bytes(),
 | ||||
|             //Item::Tool(tool) => tool.as_bytes(),
 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -41,3 +53,4 @@ impl Item { | ||||
|     } | ||||
|     
 | ||||
| } | ||||
| */ | ||||
|  | ||||
							
								
								
									
										1613
									
								
								src/item/weapon.rs
									
									
									
									
									
								
							
							
						
						
									
										1613
									
								
								src/item/weapon.rs
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										31
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								src/lib.rs
									
									
									
									
									
								
							| @ -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)] | ||||
| @ -624,4 +624,33 @@ mod test { | ||||
|             d: vec![9,9,9,8], | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn test_derive_pso_packet_data_on_simple_enum() { | ||||
|         #[repr(u8)] | ||||
|         #[derive(PSOPacketData, Eq, PartialEq)] | ||||
|         enum Q { | ||||
|             A, | ||||
|             B, | ||||
|             C, | ||||
|         } | ||||
| 
 | ||||
|         let q = Q::A.as_bytes(); | ||||
|         assert!(q == vec![0]); | ||||
| 
 | ||||
|         let q = Q::B.as_bytes(); | ||||
|         assert!(q == vec![1]); | ||||
| 
 | ||||
|         let q = Q::C.as_bytes(); | ||||
|         assert!(q == vec![2]); | ||||
| 
 | ||||
|         let q = Q::from_bytes(&mut std::io::Cursor::new(vec![0])).unwrap(); | ||||
|         assert!(q == Q::A); | ||||
| 
 | ||||
|         let q = Q::from_bytes(&mut std::io::Cursor::new(vec![1])).unwrap(); | ||||
|         assert!(q == Q::B); | ||||
| 
 | ||||
|         let q = Q::from_bytes(&mut std::io::Cursor::new(vec![2])).unwrap(); | ||||
|         assert!(q == Q::C); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -489,7 +489,7 @@ impl ShipList { | ||||
|     pub fn new(ships: Vec<ShipListEntry>) -> ShipList { | ||||
|         ShipList { | ||||
|             baseship: ShipListEntry { | ||||
|                 menu: ships.get(0).map(|s| s.menu).unwrap_or(0), | ||||
|                 menu: ships.first().map(|s| s.menu).unwrap_or(0), | ||||
|                 item: 0, | ||||
|                 flags: 0, | ||||
|                 name: utf8_to_utf16_array("Ship"), | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user