From 42ec97d70c2045405bff7316fd8a3847eeac202a Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Sun, 7 Aug 2022 16:19:04 -0400 Subject: [PATCH] Add chat log parser --- src/lib.rs | 5 ++- src/log.rs | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/log.rs diff --git a/src/lib.rs b/src/lib.rs index e69877a..7b5ddac 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,4 +55,7 @@ pub mod exd; pub mod skeleton; // Reading file into files (FIIN). -pub mod fiin; \ No newline at end of file +pub mod fiin; + +// Reading and writing chat logs (LOG) +pub mod log; \ No newline at end of file diff --git a/src/log.rs b/src/log.rs new file mode 100644 index 0000000..200ed9b --- /dev/null +++ b/src/log.rs @@ -0,0 +1,95 @@ +use std::io::{Cursor, Seek, SeekFrom}; +use std::os::unix::raw::time_t; +use binrw::binread; +use crate::gamedata::MemoryBuffer; +use binrw::BinRead; + +#[binread] +pub struct ChatLogHeader { + content_size : u32, + file_size : u32, + + #[br(count = file_size - content_size)] + offset_entries : Vec +} + +#[binread] +#[br(repr = u8)] +#[derive(Debug)] +enum EventFilter { + SystemMessages = 3, + Unknown = 20, + ProgressionMessage = 64, + NPCBattle = 41, + Unknown2 = 57, + Unknown7 = 29, + Unknown3 = 59, + EnemyBattle = 170, +} + +#[binread] +#[derive(Debug)] +#[br(repr = u8)] +enum EventChannel { + System = 0, + ServerAnnouncement = 3, + Unknown1 = 50, + Unknown7 = 29, + Others = 32, + Unknown5 = 41, + NPCEnemy = 51, + NPCFriendly = 59, + Unknown4 = 64, + Unknown6 = 170, +} + +#[binread] +#[derive(Debug)] +pub struct ChatLogEntry { + timestamp : u32, + filter : EventFilter, + channel : EventChannel, + + #[br(temp)] + garbage : u32, + + #[br(ignore)] + message : String +} + +#[derive(Debug)] +pub struct ChatLog { + entries : Vec +} + +impl ChatLog { + pub fn from_existing(buffer : &MemoryBuffer) -> Option { + let mut cursor = Cursor::new(buffer); + + let header = ChatLogHeader::read(&mut cursor).expect("Cannot parse header."); + + let content_offset = (8 + header.file_size * 4) as u64; + + // beginning of content offset + cursor.seek(SeekFrom::Start(content_offset)); + + let mut entries = vec![]; + + for offset in header.offset_entries { + let new_last_offset = content_offset + offset as u64; + + let mut entry = ChatLogEntry::read(&mut cursor).expect("Unable to parse log message."); + + // TODO: handle the coloring properly, in some way + entry.message = String::from_utf8_lossy(&*buffer[cursor.position() as usize..new_last_offset as usize].to_vec()).to_string(); + + cursor.seek(SeekFrom::Start(new_last_offset)); + + entries.push(entry); + } + + Some(ChatLog { + entries + }) + } +} \ No newline at end of file