use std::ptr::NonNull;
use crate::{
DLVector,
cs::{MultiplayRole, MultiplayType, SummonParamType},
dltx::DLString,
fd4::{FD4StepBase, FD4StepBaseInterface, FD4Time},
from_net::{FNString, FNVector},
position::BlockPosition,
stl::DLList,
};
use shared::{OwnedPtr, StepperStates};
use super::{BlockId, CSEzTask, CSEzUpdateTask};
#[repr(C)]
#[shared::singleton("CSNetMan")]
pub struct CSNetMan {
vftable: usize,
unk8: u32,
unkc: u32,
unk10: [u8; 5],
freeze_game: bool,
unk16: bool,
unk17: bool,
pub low_fps_penalty: bool,
pub server_connection_lost: bool,
unk1a: bool,
unk1b: u8,
pub block_id: BlockId,
unk20: BlockId,
pub play_region_id: u32,
unk28: [u8; 0x40],
sos_db: usize,
wandering_ghost_db: usize,
pub blood_message_db: OwnedPtr<CSNetBloodMessageDb>,
bloodstain_db: usize,
bonfire_db: usize,
spiritual_statue_db: usize,
unk98: usize,
unka0: usize,
pub breakin_manager: OwnedPtr<BreakInManager>,
pub quickmatch_manager: OwnedPtr<QuickmatchManager>,
visitor_db: usize,
penalty_manager: usize,
pub update_task: CSEzUpdateTask<CSEzTask, Self>,
unkf0: u32,
unkf4: u32, unkf8: usize,
}
#[repr(C)]
pub struct CSNetBloodMessageDb {
vftable: usize,
pub entries: DLList<OwnedPtr<CSNetBloodMessageDbItem>>,
unk20: usize,
pub created_data: DLList<usize>,
unk40: DLList<usize>,
unk58: usize,
blood_message_ins_man_1: usize,
blood_message_ins_man_2: usize,
pub discovered_messages: DLList<OwnedPtr<OwnedPtr<CSNetBloodMessageDbItem>>>,
unk88: [u8; 0xD0],
evaluate_job: usize,
unk160: usize,
}
#[repr(C)]
pub struct CSNetBloodMessageDbItem {
vftable: usize,
unk8: u32,
unkc: u32,
unk10: u32,
pub block_id: BlockId,
unk18: u32,
pub position_x: f32,
pub position_y: f32,
pub position_z: f32,
pub angle: f32,
pub template1: u16,
pub gesture_param: u16,
pub part1: u16,
pub infix: u16,
pub template2: u16,
pub part2: u16,
unk38: u16,
unk3a: u16,
unk3c: u16,
unk3e: u16,
pub message_id: u64,
unk48: u32,
}
#[repr(C)]
pub struct BreakInData {
pub block_id: BlockId,
pub block_pos: BlockPosition,
pub entryfilelist_id: i32,
pub summon_param_type: SummonParamType,
pub multiplay_role: MultiplayRole,
pub has_password: bool,
unk1e: u8,
pub join_data: FNVector<u8>,
}
#[repr(C)]
pub struct BreakInPointManager {
breakin_points: DLList<()>,
unk18: [u8; 0x10],
}
#[repr(C)]
pub struct BreakInAreaList {
pub areas: DLVector<u32>,
pub count: u32,
}
#[repr(u32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum BreakInSearchState {
Idle = 0,
InSearch = 1,
ConnectionAttempt = 2,
CheckingResponse = 3,
}
#[repr(C)]
pub struct BreakInTarget {
pub player_id: u32,
pub external_id: FNString,
pub play_region: u32,
}
#[repr(C)]
pub struct BreakInManager {
pub multiplay_type: MultiplayType,
pub targets: FNVector<BreakInTarget>,
unk20: FNVector<()>,
pub data: BreakInData,
pub point_manager: BreakInPointManager,
rebreakin_pos_step: usize,
pub error_code: i32,
pub areas: BreakInAreaList,
unkd0: usize,
unkd8: usize,
pub invasion_search_state: BreakInSearchState,
pub last_update_invasion_search_state: BreakInSearchState,
pub attempt_interval_timer: FD4Time,
pub time_out_timer: FD4Time,
pub is_yellow_costume_region: bool,
pub is_multi_region: bool,
}
#[repr(C)]
pub struct QuickmatchManager {
pub quickmatching_ctrl: OwnedPtr<CSQuickMatchingCtrl>,
pub battle_royal_context: OwnedPtr<CSBattleRoyalContext>,
active_battle_royal_context: Option<NonNull<CSBattleRoyalContext>>,
unk18: u32,
pub utility_sp_effects: [u32; 11],
}
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, StepperStates)]
pub enum CSQuickMatchingCtrlState {
NotExecuting = -1,
None = 0,
SearchRegister = 1,
SearchRegisterWait = 2,
GuestInviteWait = 3,
GuestWaitSession = 4,
GuestReadyWait = 5,
GuestMoveMap = 6,
GuestInGame = 7,
HostWaitSession = 8,
HostInvite = 9,
HostReadyWait = 10,
HostReadyWaitBlockList = 11,
HostMoveMap = 12,
HostInGame = 13,
Unregister = 14,
}
#[repr(C)]
pub struct CSQuickMatchingCtrl {
pub stepper: FD4StepBase<Self, FD4StepBaseInterface, CSQuickMatchingCtrlState>,
pub context: NonNull<CSBattleRoyalContext>,
menu_job: usize,
unkb8: FD4Time,
unkc8: bool,
unkc9: bool,
unkca: bool,
unkcb: bool,
unkcc: bool,
unkcd: bool,
unkce: [u8; 5],
unkd3: bool,
pub move_map_timed_out: bool,
}
#[repr(C)]
pub struct CSBattleRoyalContext {
pub quickmatch_context: CSQuickMatchContext,
pub match_player_count: u32,
pub setting: QuickMatchSettings,
pub current_player_count: u32,
pub venue: QuickMatchVenue,
pub password: DLString,
pub is_fixed_map: bool,
unkf1: u8,
unkf2: u8,
unkf3: u8,
unkf4: u32,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum QuickMatchSize {
Duel,
OneVsOne,
TwoVsTwo,
ThreeVsThree,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct QuickMatchSettings(pub u32);
impl QuickMatchSettings {
pub const fn spirit_ashes_allowed(self) -> bool {
self.0 >= 10
}
pub const fn is_brawl_mode(self) -> bool {
matches!(self.0 % 10, 1..=3)
}
pub const fn is_team_mode(self) -> bool {
matches!(self.0 % 10, 4..=9)
}
pub const fn is_allies_password_mode(self) -> bool {
matches!(self.0 % 10, 7..=9)
}
pub const fn match_size(self) -> QuickMatchSize {
match self.0 % 10 {
1 | 4 | 7 => QuickMatchSize::OneVsOne,
2 | 5 | 8 => QuickMatchSize::TwoVsTwo,
3 | 6 | 9 => QuickMatchSize::ThreeVsThree,
_ => QuickMatchSize::Duel,
}
}
}
#[repr(C)]
pub struct CSQuickMatchContext {
vtable: usize,
pub match_settings: QuickMatchSettings,
pub match_map: QuickMatchArena,
pub spawn_data: QuickmatchSpawnData,
pub arena_list: FNVector<QuickMatchArena>,
unk40: DLVector<usize>,
unk60: DLVector<usize>,
pub participants: DLList<QuickmatchParticipant>,
unk98: u8,
pub error_state: u8,
unk9a: u8,
unk9b: u8,
pub venue: QuickMatchVenue,
unka0: u32,
unka4: u32,
unka8: u32,
unkac: u32,
}
#[repr(C)]
pub struct QuickmatchSpawnData {
pub block_id: BlockId,
pub block_position: BlockPosition,
pub role: u32,
}
#[repr(C)]
pub struct QuickmatchParticipant {}
#[repr(u32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum QuickMatchVenue {
Invalid = 0,
RoyalColosseum = 1,
LimgraveColosseum = 2,
CaelidColosseum = 3,
}
#[repr(u32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum QuickMatchArena {
Invalid = 0,
RoyalColosseum = 4500000,
LimgraveColosseum = 4502000,
CaelidColosseum = 4501000,
}