use chrono::{DateTime, Utc};
use crate::{raw_structs::HMODULE, unofficial_extras::raw_structs_keybinds};
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum UserRole {
SquadLeader = 0,
Lieutenant = 1,
Member = 2,
Invited = 3,
Applied = 4,
None = 5,
Invalid = 6,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct UserInfoOwned {
pub account_name: Option<String>,
pub join_time: u64,
pub role: UserRole,
pub subgroup: u8,
pub ready_status: bool,
}
impl From<UserInfo<'_>> for UserInfoOwned {
fn from(user: UserInfo<'_>) -> Self {
Self {
account_name: user.account_name.map(|x| x.to_string()),
join_time: user.join_time,
role: user.role,
subgroup: user.subgroup,
ready_status: user.ready_status,
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct UserInfo<'a> {
pub account_name: Option<&'a str>,
pub join_time: u64,
pub role: UserRole,
pub subgroup: u8,
pub ready_status: bool,
}
#[repr(C)]
pub struct RawUserInfo {
pub account_name: *const u8,
pub join_time: u64,
pub role: UserRole,
pub subgroup: u8,
pub ready_status: bool,
}
#[repr(i32)]
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum Language {
English = 0,
French = 2,
German = 3,
Spanish = 4,
Chinese = 5,
}
#[repr(u8)]
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[non_exhaustive]
pub enum ChannelType {
Party = 0,
Squad = 1,
_Reserved = 2,
Invalid = 3,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct SquadMessageInfo<'a> {
pub channel_id: u32,
pub channel_type: ChannelType,
pub subgroup: u8,
pub is_broadcast: bool,
pub timestamp: DateTime<Utc>,
pub account_name: &'a str,
pub character_name: &'a str,
pub text: &'a str,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct NpcMessageInfo<'a> {
pub character_name: &'a str,
pub message: &'a str,
pub timestamp: DateTime<Utc>,
}
#[repr(C)]
pub struct RawSquadMessageInfo {
pub channel_id: u32,
pub channel_type: ChannelType,
pub subgroup: u8,
pub is_broadcast: u8,
pub timestamp: *const u8,
pub timestamp_length: u64,
pub account_name: *const u8,
pub account_name_length: u64,
pub character_name: *const u8,
pub character_name_length: u64,
pub text: *const u8,
pub text_length: u64,
}
#[repr(C)]
pub struct RawNpcMessageInfo {
pub character_name: *const u8,
pub character_name_length: u64,
pub message: *const u8,
pub message_length: u64,
pub timestamp: u64,
}
#[repr(C)]
pub struct RawExtrasAddonInfo {
pub api_version: u32,
pub max_info_version: u32,
pub string_version: *const u8,
pub self_account_name: *const u8,
pub extras_handle: HMODULE,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[non_exhaustive]
pub enum ChatMessageType {
Squad = 0,
NPC = 1,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum ChatMessageInfo2<'a> {
Squad(SquadMessageInfo<'a>),
Npc(NpcMessageInfo<'a>),
}
#[repr(C)]
pub union RawChatMessageInfo2 {
pub squad_message_info: *const RawSquadMessageInfo,
pub npc_message_info: *const RawNpcMessageInfo,
}
pub type RawSquadUpdateCallbackSignature = unsafe extern "C" fn(*const RawUserInfo, u64);
pub type RawLanguageChangedCallbackSignature = unsafe extern "C" fn(Language);
pub type RawKeyBindChangedCallbackSignature =
unsafe extern "C" fn(raw_structs_keybinds::KeyBindChanged);
pub type RawChatMessageCallbackSignature = unsafe extern "C" fn(*const RawSquadMessageInfo);
pub type RawChatMessage2CallbackSignature =
unsafe extern "C" fn(ChatMessageType, RawChatMessageInfo2);
#[repr(C)]
pub struct RawExtrasSubscriberInfoHeader {
pub info_version: u32,
pub _unused1: u32,
}
use std::{
iter::Map,
ops::{Deref, DerefMut},
slice::Iter,
};
pub type ExtrasSquadUpdateCallback = fn(UserInfoIter);
pub type ExtrasChatMessageCallback = fn(&SquadMessageInfo);
pub type ExtrasChatMessage2Callback = fn(&ChatMessageInfo2);
pub type UserInfoIter<'a> = Map<Iter<'a, RawUserInfo>, UserConvert>;
pub type UserConvert = for<'r> fn(&'r RawUserInfo) -> UserInfo<'r>;
#[repr(C)]
pub struct RawExtrasSubscriberInfo<T> {
pub header: RawExtrasSubscriberInfoHeader,
pub content: T,
}
impl<T> Deref for RawExtrasSubscriberInfo<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.content
}
}
impl<T> DerefMut for RawExtrasSubscriberInfo<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.content
}
}
#[repr(C)]
pub struct InfoV1 {
pub subscriber_name: *const u8,
pub squad_update_callback: Option<RawSquadUpdateCallbackSignature>,
pub language_changed_callback: Option<RawLanguageChangedCallbackSignature>,
pub key_bind_changed_callback: Option<RawKeyBindChangedCallbackSignature>,
}
#[repr(C)]
pub struct InfoV2 {
pub v1: InfoV1,
pub chat_message_callback: Option<RawChatMessageCallbackSignature>,
}
impl Deref for InfoV2 {
type Target = InfoV1;
fn deref(&self) -> &Self::Target {
&self.v1
}
}
impl DerefMut for InfoV2 {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.v1
}
}
#[repr(C)]
pub struct InfoV3 {
pub v2: InfoV2,
pub chat_message_callback2: Option<RawChatMessage2CallbackSignature>,
}
impl Deref for InfoV3 {
type Target = InfoV2;
fn deref(&self) -> &Self::Target {
&self.v2
}
}
impl DerefMut for InfoV3 {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.v2
}
}
pub type RawExtrasSubscriberInitSignature =
unsafe extern "C" fn(&RawExtrasAddonInfo, &mut RawExtrasSubscriberInfoHeader);
pub type ExtrasInitFunc = fn(Option<&str>, Option<&'static str>);