2023-08-06 08:25:04 -04:00
|
|
|
// SPDX-FileCopyrightText: 2023 Joshua Goins <josh@redstrate.com>
|
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
2022-08-16 11:52:07 -04:00
|
|
|
use std::io::{Cursor, Seek, SeekFrom};
|
2022-08-07 16:19:04 -04:00
|
|
|
|
2023-08-06 08:25:04 -04:00
|
|
|
use binrw::BinRead;
|
|
|
|
use binrw::binrw;
|
2023-10-13 16:16:04 -04:00
|
|
|
use crate::ByteSpan;
|
2023-08-06 08:25:04 -04:00
|
|
|
|
2022-10-13 17:11:03 -04:00
|
|
|
#[binrw]
|
2022-09-15 16:26:31 -04:00
|
|
|
#[allow(dead_code)]
|
2022-10-13 17:11:03 -04:00
|
|
|
#[brw(little)]
|
2023-12-02 20:27:02 -05:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2022-10-13 17:11:03 -04:00
|
|
|
#[binrw]
|
|
|
|
#[brw(repr = u8)]
|
2022-08-07 16:19:04 -04:00
|
|
|
#[derive(Debug)]
|
2023-12-02 20:26:34 -05:00
|
|
|
pub enum EventFilter {
|
2022-08-07 16:19:04 -04:00
|
|
|
SystemMessages = 3,
|
|
|
|
Unknown = 20,
|
|
|
|
ProgressionMessage = 64,
|
|
|
|
NPCBattle = 41,
|
|
|
|
Unknown2 = 57,
|
|
|
|
Unknown7 = 29,
|
|
|
|
Unknown3 = 59,
|
|
|
|
EnemyBattle = 170,
|
2024-01-29 15:49:16 -05:00
|
|
|
Unknown4 = 581,
|
|
|
|
Unknown8 = 43,
|
|
|
|
Unknown9 = 60,
|
|
|
|
Unknown10 = 61,
|
|
|
|
Unknown11 = 62,
|
|
|
|
Unknown12 = 58,
|
|
|
|
Unknown13 = 169,
|
|
|
|
Unknown14 = 175,
|
|
|
|
Unknown15 = 42,
|
|
|
|
Unknown16 = 171,
|
|
|
|
Unknown17 = 177,
|
|
|
|
Unknown18 = 174,
|
|
|
|
Unknown19 = 47,
|
|
|
|
Unknown20 = 176,
|
|
|
|
Unknown21 = 44,
|
|
|
|
Unknown22 = 173,
|
|
|
|
Unknown23 = 46,
|
|
|
|
Unknown24 = 10,
|
|
|
|
Unknown25 = 185,
|
|
|
|
Unknown26 = 190,
|
|
|
|
Unknown27 = 11,
|
|
|
|
Unknown28 = 70,
|
|
|
|
Unknown29 = 105,
|
2022-08-07 16:19:04 -04:00
|
|
|
}
|
|
|
|
|
2022-10-13 17:11:03 -04:00
|
|
|
#[binrw]
|
2022-08-07 16:19:04 -04:00
|
|
|
#[derive(Debug)]
|
2022-10-13 17:11:03 -04:00
|
|
|
#[brw(repr = u8)]
|
2023-12-02 20:26:34 -05:00
|
|
|
pub enum EventChannel {
|
2022-08-07 16:19:04 -04:00
|
|
|
System = 0,
|
2024-01-29 15:49:16 -05:00
|
|
|
Unknown8 = 2,
|
2022-08-07 16:19:04 -04:00
|
|
|
ServerAnnouncement = 3,
|
2024-01-29 15:49:16 -05:00
|
|
|
Unknown9 = 8,
|
2022-08-07 16:19:04 -04:00
|
|
|
Unknown1 = 50,
|
|
|
|
Unknown7 = 29,
|
|
|
|
Others = 32,
|
|
|
|
Unknown5 = 41,
|
|
|
|
NPCEnemy = 51,
|
|
|
|
NPCFriendly = 59,
|
|
|
|
Unknown4 = 64,
|
|
|
|
Unknown6 = 170,
|
2024-01-29 15:49:16 -05:00
|
|
|
Unknown10 = 10,
|
|
|
|
Unknown11 = 66,
|
|
|
|
Unknown12 = 44,
|
|
|
|
Unknown13 = 40,
|
|
|
|
Unknown14 = 42,
|
|
|
|
Unknown15 = 11,
|
|
|
|
Unknown16 = 67,
|
|
|
|
Unknown17 = 68,
|
|
|
|
Unknown18 = 34,
|
|
|
|
Unknown19 = 110,
|
2022-08-07 16:19:04 -04:00
|
|
|
}
|
|
|
|
|
2022-10-13 17:11:03 -04:00
|
|
|
#[binrw]
|
2022-08-07 16:19:04 -04:00
|
|
|
#[derive(Debug)]
|
2022-09-15 16:26:31 -04:00
|
|
|
#[allow(dead_code)]
|
2022-10-13 17:11:03 -04:00
|
|
|
#[brw(little)]
|
2023-12-02 20:26:34 -05:00
|
|
|
/// Represents an entry in the chat log
|
2022-08-07 16:19:04 -04:00
|
|
|
pub struct ChatLogEntry {
|
2022-08-16 11:52:07 -04:00
|
|
|
timestamp: u32,
|
2023-12-02 20:26:34 -05:00
|
|
|
/// The event filter
|
|
|
|
pub filter: EventFilter,
|
|
|
|
/// The event channel
|
|
|
|
pub channel: EventChannel,
|
2022-08-07 16:19:04 -04:00
|
|
|
|
|
|
|
#[br(temp)]
|
2022-10-13 17:11:03 -04:00
|
|
|
#[bw(calc = 1)]
|
2023-09-22 19:17:24 -04:00
|
|
|
_garbage: u32,
|
2022-08-07 16:19:04 -04:00
|
|
|
|
2023-12-02 20:26:34 -05:00
|
|
|
/// The message
|
2022-10-13 17:11:03 -04:00
|
|
|
#[brw(ignore)]
|
2023-12-02 20:26:34 -05:00
|
|
|
pub message: String,
|
2022-08-07 16:19:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
2022-09-15 16:26:31 -04:00
|
|
|
#[allow(dead_code)]
|
2023-12-02 20:26:34 -05:00
|
|
|
/// Chat log, which contains previously recorded messages from other players
|
2022-08-07 16:19:04 -04:00
|
|
|
pub struct ChatLog {
|
2023-12-02 20:26:34 -05:00
|
|
|
pub entries: Vec<ChatLogEntry>,
|
2022-08-07 16:19:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ChatLog {
|
2023-12-02 20:26:34 -05:00
|
|
|
/// Reads an existing LOG file
|
2023-10-13 16:16:04 -04:00
|
|
|
pub fn from_existing(buffer: ByteSpan) -> 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
|
2024-01-29 15:49:16 -05:00
|
|
|
//cursor.seek(SeekFrom::Start(content_offset)).ok()?;
|
2022-08-07 16:19:04 -04:00
|
|
|
|
|
|
|
let mut entries = vec![];
|
|
|
|
|
2024-01-29 15:49:16 -05:00
|
|
|
for (i, offset) in header.offset_entries.iter().enumerate() {
|
|
|
|
let new_last_offset = content_offset + *offset as u64;
|
|
|
|
|
|
|
|
cursor.seek(SeekFrom::Start(new_last_offset)).ok()?;
|
2022-08-07 16:19:04 -04:00
|
|
|
|
|
|
|
let mut entry = ChatLogEntry::read(&mut cursor).expect("Unable to parse log message.");
|
|
|
|
|
2024-01-29 15:49:16 -05:00
|
|
|
let next_offset = if i + 1 == header.offset_entries.len() {
|
|
|
|
buffer.len()
|
|
|
|
} else {
|
|
|
|
(content_offset + header.offset_entries[i + 1] as u64) as usize
|
|
|
|
};
|
|
|
|
|
2022-08-07 16:19:04 -04:00
|
|
|
// TODO: handle the coloring properly, in some way
|
2022-08-16 11:52:07 -04:00
|
|
|
entry.message = String::from_utf8_lossy(
|
2024-01-29 15:49:16 -05:00
|
|
|
&buffer[cursor.position() as usize..next_offset],
|
2022-08-16 11:52:07 -04:00
|
|
|
)
|
2024-01-29 15:49:16 -05:00
|
|
|
.to_string();
|
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
|
|
|
}
|