2022-08-07 16:19:04 -04:00
|
|
|
use crate::gamedata::MemoryBuffer;
|
2022-08-16 11:52:07 -04:00
|
|
|
use binrw::binread;
|
2022-08-07 16:19:04 -04:00
|
|
|
use binrw::BinRead;
|
2022-08-16 11:52:07 -04:00
|
|
|
use std::io::{Cursor, Seek, SeekFrom};
|
2022-08-07 16:19:04 -04:00
|
|
|
|
|
|
|
#[binread]
|
2022-09-15 16:26:31 -04:00
|
|
|
#[allow(dead_code)]
|
2022-08-07 16:19:04 -04:00
|
|
|
pub struct ChatLogHeader {
|
2022-08-16 11:52:07 -04:00
|
|
|
content_size: u32,
|
|
|
|
file_size: u32,
|
2022-08-07 16:19:04 -04:00
|
|
|
|
|
|
|
#[br(count = file_size - content_size)]
|
2022-08-16 11:52:07 -04:00
|
|
|
offset_entries: Vec<u32>,
|
2022-08-07 16:19:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[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)]
|
2022-09-15 16:26:31 -04:00
|
|
|
#[allow(dead_code)]
|
2022-08-07 16:19:04 -04:00
|
|
|
pub struct ChatLogEntry {
|
2022-08-16 11:52:07 -04:00
|
|
|
timestamp: u32,
|
|
|
|
filter: EventFilter,
|
|
|
|
channel: EventChannel,
|
2022-08-07 16:19:04 -04:00
|
|
|
|
|
|
|
#[br(temp)]
|
2022-08-16 11:52:07 -04:00
|
|
|
garbage: u32,
|
2022-08-07 16:19:04 -04:00
|
|
|
|
|
|
|
#[br(ignore)]
|
2022-08-16 11:52:07 -04:00
|
|
|
message: String,
|
2022-08-07 16:19:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
2022-09-15 16:26:31 -04:00
|
|
|
#[allow(dead_code)]
|
2022-08-07 16:19:04 -04:00
|
|
|
pub struct ChatLog {
|
2022-08-16 11:52:07 -04:00
|
|
|
entries: Vec<ChatLogEntry>,
|
2022-08-07 16:19:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ChatLog {
|
2022-08-16 11:52:07 -04:00
|
|
|
pub fn from_existing(buffer: &MemoryBuffer) -> Option<ChatLog> {
|
2022-08-07 16:19:04 -04:00
|
|
|
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
|
2022-08-09 23:39:15 -04:00
|
|
|
cursor.seek(SeekFrom::Start(content_offset)).ok()?;
|
2022-08-07 16:19:04 -04:00
|
|
|
|
|
|
|
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
|
2022-08-16 11:52:07 -04:00
|
|
|
entry.message = String::from_utf8_lossy(
|
|
|
|
&*buffer[cursor.position() as usize..new_last_offset as usize].to_vec(),
|
|
|
|
)
|
|
|
|
.to_string();
|
2022-08-07 16:19:04 -04:00
|
|
|
|
2022-08-09 23:39:15 -04:00
|
|
|
cursor.seek(SeekFrom::Start(new_last_offset)).ok()?;
|
2022-08-07 16:19:04 -04:00
|
|
|
|
|
|
|
entries.push(entry);
|
|
|
|
}
|
|
|
|
|
2022-08-16 11:52:07 -04:00
|
|
|
Some(ChatLog { entries })
|
2022-08-07 16:19:04 -04:00
|
|
|
}
|
2022-08-16 11:52:07 -04:00
|
|
|
}
|