use std::io::{self, Write, Read};
use glam::Vec3A;
use crate::util::io::*;
use super::{Element, SimpleElement, TopElement, NoopElement, ElementLength, ElementIdRange};
use super::entity::{MethodCall};
pub mod id {
use super::ElementIdRange;
pub const UPDATE_FREQUENCY_NOTIFICATION: u8 = 0x02;
pub const SET_GAME_TIME: u8 = 0x03;
pub const RESET_ENTITIES: u8 = 0x04;
pub const CREATE_BASE_PLAYER: u8 = 0x05;
pub const CREATE_CELL_PLAYER: u8 = 0x06;
pub const TICK_SYNC: u8 = 0x13;
pub const SELECT_PLAYER_ENTITY: u8 = 0x1A;
pub const FORCED_POSITION: u8 = 0x1B;
pub const ENTITY_METHOD: ElementIdRange = ElementIdRange::new(0xA7, 0xFE);
}
#[derive(Debug, Clone)]
pub struct UpdateFrequencyNotification {
pub frequency: u8,
pub game_time: u32,
}
impl SimpleElement for UpdateFrequencyNotification {
fn encode(&self, write: &mut impl Write) -> io::Result<()> {
write.write_u8(self.frequency)?;
write.write_u16(1)?;
write.write_u32(self.game_time)
}
fn decode(read: &mut impl Read, _len: usize) -> io::Result<Self> {
Ok(Self {
frequency: read.read_u8()?,
game_time: { read.read_u16()?; read.read_u32()? },
})
}
}
impl TopElement for UpdateFrequencyNotification {
const LEN: ElementLength = ElementLength::Fixed(7);
}
#[derive(Debug, Clone)]
pub struct SetGameTime {
pub game_time: u32,
}
impl SimpleElement for SetGameTime {
fn encode(&self, write: &mut impl Write) -> io::Result<()> {
write.write_u32(self.game_time)
}
fn decode(read: &mut impl Read, _len: usize) -> io::Result<Self> {
Ok(Self { game_time: read.read_u32()? })
}
}
impl TopElement for SetGameTime {
const LEN: ElementLength = ElementLength::Fixed(4);
}
#[derive(Debug, Clone)]
pub struct ResetEntities {
pub keep_player_on_base: bool,
}
impl SimpleElement for ResetEntities {
fn encode(&self, write: &mut impl Write) -> io::Result<()> {
write.write_bool(self.keep_player_on_base)
}
fn decode(read: &mut impl Read, _len: usize) -> io::Result<Self> {
Ok(Self { keep_player_on_base: read.read_bool()? })
}
}
impl TopElement for ResetEntities {
const LEN: ElementLength = ElementLength::Fixed(1);
}
#[derive(Debug, Clone)]
pub struct CreateBasePlayer<E> {
pub entity_id: u32,
pub entity_type: u16,
pub unk: String,
pub entity_data: E,
pub entity_components_count: u8,
}
impl<E: Element<Config = ()>> SimpleElement for CreateBasePlayer<E> {
fn encode(&self, write: &mut impl Write) -> io::Result<()> {
write.write_u32(self.entity_id)?;
write.write_u16(self.entity_type)?;
write.write_string_variable(&self.unk)?;
self.entity_data.encode(&mut *write, &())?;
write.write_u8(self.entity_components_count)
}
fn decode(read: &mut impl Read, len: usize) -> io::Result<Self> {
Ok(Self {
entity_id: read.read_u32()?,
entity_type: read.read_u16()?,
unk: read.read_string_variable()?,
entity_data: E::decode(&mut *read, len - 7, &())?,
entity_components_count: read.read_u8()?,
})
}
}
impl<E: Element<Config = ()>> TopElement for CreateBasePlayer<E> {
const LEN: ElementLength = ElementLength::Variable16;
}
#[derive(Debug, Clone)]
pub struct TickSync {
pub tick: u8,
}
impl SimpleElement for TickSync {
fn encode(&self, write: &mut impl Write) -> io::Result<()> {
write.write_u8(self.tick)
}
fn decode(read: &mut impl Read, _len: usize) -> io::Result<Self> {
Ok(Self { tick: read.read_u8()? })
}
}
impl TopElement for TickSync {
const LEN: ElementLength = ElementLength::Fixed(1);
}
#[derive(Debug, Default, Clone, Copy)]
pub struct SelectPlayerEntity;
impl NoopElement for SelectPlayerEntity { }
impl TopElement for SelectPlayerEntity {
const LEN: ElementLength = ElementLength::Fixed(0);
}
#[derive(Debug, Clone)]
pub struct ForcedPosition {
pub entity_id: u32,
pub space_id: u32,
pub vehicle_entity_id: u32,
pub position: Vec3A,
pub direction: Vec3A,
}
impl SimpleElement for ForcedPosition {
fn encode(&self, write: &mut impl Write) -> io::Result<()> {
write.write_u32(self.entity_id)?;
write.write_u32(self.space_id)?;
write.write_u32(self.vehicle_entity_id)?;
write.write_vec3(self.position)?;
write.write_vec3(self.direction)
}
fn decode(read: &mut impl Read, _len: usize) -> io::Result<Self> {
Ok(Self {
entity_id: read.read_u32()?,
space_id: read.read_u32()?,
vehicle_entity_id: read.read_u32()?,
position: read.read_vec3()?,
direction: read.read_vec3()?,
})
}
}
pub const ENTITY_METHOD_ID_RANGE: ElementIdRange = ElementIdRange::new(0x4E, 0xA6);
pub struct EntityMethod<M: MethodCall> {
pub method: M,
}
impl<M: MethodCall> EntityMethod<M> {
}