pub const ME3_MAGIC: u32 = 0x666D726D;
pub const TLK_MAGIC: u32 = 0x006B6C54;
pub type WChar = u16;
pub type WString = Vec<u16>;
#[derive(Debug, Hash, serde::Serialize, serde::Deserialize)]
pub struct Tlk {
pub version: u32,
pub min_version: u32,
pub male_values: Vec<TlkString>,
pub female_values: Vec<TlkString>,
}
impl Tlk {
pub fn replace_male(&mut self, id: u32, value: WString) -> bool {
if let Some(entry) = self.male_values.iter_mut().find(|value| value.id == id) {
entry.value = value;
true
} else {
false
}
}
pub fn insert_male(&mut self, id: u32, value: WString) {
if self.replace_male(id, value.clone()) {
return;
}
self.male_values.push(TlkString { id, value })
}
pub fn replace_female(&mut self, id: u32, value: WString) -> bool {
if let Some(entry) = self.female_values.iter_mut().find(|value| value.id == id) {
entry.value = value;
true
} else {
false
}
}
pub fn insert_female(&mut self, id: u32, value: WString) {
if self.replace_female(id, value.clone()) {
return;
}
self.female_values.push(TlkString { id, value })
}
pub fn replace_male_utf8(&mut self, id: u32, value: String) -> bool {
if let Some(entry) = self.male_values.iter_mut().find(|value| value.id == id) {
entry.value = value.encode_utf16().collect();
true
} else {
false
}
}
pub fn insert_male_utf8(&mut self, id: u32, value: String) {
if self.replace_male_utf8(id, value.clone()) {
return;
}
self.male_values.push(TlkString {
id,
value: value.encode_utf16().collect(),
})
}
pub fn replace_female_utf8(&mut self, id: u32, value: String) -> bool {
if let Some(entry) = self.female_values.iter_mut().find(|value| value.id == id) {
entry.value = value.encode_utf16().collect();
true
} else {
false
}
}
pub fn insert_female_utf8(&mut self, id: u32, value: String) {
if self.replace_female_utf8(id, value.clone()) {
return;
}
self.female_values.push(TlkString {
id,
value: value.encode_utf16().collect(),
})
}
}
#[derive(Debug, Hash, serde::Serialize, serde::Deserialize)]
pub struct TlkString {
pub id: u32,
pub value: WString,
}
#[derive(Debug, Hash, serde::Serialize, serde::Deserialize)]
pub struct Coalesced {
pub version: u32,
pub files: Vec<CoalFile>,
}
#[derive(Debug, Hash, serde::Serialize, serde::Deserialize)]
pub struct CoalFile {
pub path: String,
pub sections: Vec<Section>,
}
#[derive(Debug, Hash, serde::Serialize, serde::Deserialize)]
pub struct Section {
pub name: String,
pub properties: Vec<Property>,
}
#[derive(Debug, Hash, serde::Serialize, serde::Deserialize)]
pub struct Property {
pub name: String,
pub values: Vec<Value>,
}
#[derive(Debug, Hash, serde::Serialize, serde::Deserialize)]
pub struct Value {
pub ty: ValueType,
pub text: Option<String>,
}
#[derive(Debug, Hash, serde::Serialize, serde::Deserialize, Clone, Copy)]
#[repr(u8)]
pub enum ValueType {
New = 0,
RemoveProperty = 1,
Add = 2,
AddUnique = 3,
Remove = 4,
}
pub struct UnknownValueType;
impl TryFrom<u8> for ValueType {
type Error = UnknownValueType;
fn try_from(value: u8) -> Result<Self, Self::Error> {
Ok(match value {
0 => Self::New,
1 => Self::RemoveProperty,
2 => Self::Add,
3 => Self::AddUnique,
4 => Self::Remove,
_ => return Err(UnknownValueType),
})
}
}
pub(crate) fn invert_huffman_tree(pairs: &mut Vec<(i32, i32)>) {
let last_index = (pairs.len() - 1) as i32;
pairs.reverse();
for pair in pairs {
if pair.0 > -1 {
pair.0 = last_index - pair.0
}
if pair.1 > -1 {
pair.1 = last_index - pair.1
}
}
}