use std::io::{self, Read, Write};
use crate::net::bundle::{BundleElementWriter, TopElementReader, BundleElement, BundleResult};
use crate::util::io::*;
use super::{SimpleElement, TopElement, NoopElement, ElementLength, ElementIdRange};
use super::entity::{MethodCall, MethodCallWrapper, MethodCallExt};
pub mod id {
use super::ElementIdRange;
pub const CLIENT_AUTH: u8 = 0x00;
pub const CLIENT_SESSION_KEY: u8 = 0x01;
pub const CELL_ENTITY_METHOD: ElementIdRange = ElementIdRange::new(0x0F, 0x87);
pub const BASE_ENTITY_METHOD: ElementIdRange = ElementIdRange::new(0x88, 0xFE);
}
#[derive(Debug, Clone)]
pub struct ClientAuth {
pub login_key: u32,
pub attempts_count: u8,
pub unk: u16,
}
impl SimpleElement for ClientAuth {
fn encode(&self, write: &mut impl Write) -> io::Result<()> {
write.write_u32(self.login_key)?;
write.write_u8(self.attempts_count)?;
write.write_u16(self.unk)
}
fn decode(read: &mut impl Read, _len: usize) -> io::Result<Self> {
Ok(Self {
login_key: read.read_u32()?,
attempts_count: read.read_u8()?,
unk: read.read_u16()?,
})
}
}
impl TopElement for ClientAuth {
const LEN: ElementLength = ElementLength::Fixed(7);
}
#[derive(Debug, Clone)]
pub struct ServerSessionKey {
pub session_key: u32,
}
impl SimpleElement for ServerSessionKey {
fn encode(&self, write: &mut impl Write) -> io::Result<()> {
write.write_u32(self.session_key)
}
fn decode(read: &mut impl Read, _len: usize) -> io::Result<Self> {
Ok(Self { session_key: read.read_u32()? })
}
}
#[derive(Debug, Clone)]
pub struct ClientSessionKey {
pub session_key: u32,
}
impl ClientSessionKey {
pub const ID: u8 = 0x01;
}
impl SimpleElement for ClientSessionKey {
fn encode(&self, write: &mut impl Write) -> io::Result<()> {
write.write_u32(self.session_key)
}
fn decode(read: &mut impl Read, _len: usize) -> io::Result<Self> {
Ok(Self { session_key: read.read_u32()? })
}
}
impl TopElement for ClientSessionKey {
const LEN: ElementLength = ElementLength::Fixed(4);
}
#[derive(Debug, Clone)]
pub struct CellEntityMethod<M: MethodCall> {
pub entity_id: u32,
pub method: M,
}
impl<M: MethodCall> CellEntityMethod<M> {
pub fn write(self, writer: BundleElementWriter) {
MethodCallWrapper::new(self.method, CellEntityMethodExt {
entity_id: self.entity_id,
}).write(writer);
}
pub fn read(reader: TopElementReader) -> BundleResult<BundleElement<Self>> {
MethodCallWrapper::<M, CellEntityMethodExt>::read(reader).map(|res| {
res.map(|wrapper| Self {
entity_id: wrapper.ext.entity_id,
method: wrapper.method,
})
})
}
}
struct CellEntityMethodExt {
entity_id: u32,
}
impl MethodCallExt for CellEntityMethodExt {
const ID_RANGE: ElementIdRange = id::CELL_ENTITY_METHOD;
}
impl SimpleElement for CellEntityMethodExt {
fn encode(&self, write: &mut impl Write) -> io::Result<()> {
write.write_u32(self.entity_id)
}
fn decode(read: &mut impl Read, _len: usize) -> io::Result<Self> {
Ok(Self { entity_id: read.read_u32()? })
}
}
impl TopElement for CellEntityMethodExt {
const LEN: ElementLength = ElementLength::Variable16;
}
#[derive(Debug, Clone)]
pub struct BaseEntityMethod<M: MethodCall> {
pub method: M,
}
impl<M: MethodCall> BaseEntityMethod<M> {
pub fn write(self, writer: BundleElementWriter) {
MethodCallWrapper::new(self.method, BaseEntityMethodExt).write(writer);
}
pub fn read(reader: TopElementReader) -> BundleResult<BundleElement<Self>> {
MethodCallWrapper::<M, BaseEntityMethodExt>::read(reader).map(|res| {
res.map(|wrapper| Self {
method: wrapper.method,
})
})
}
}
#[derive(Default)]
struct BaseEntityMethodExt;
impl MethodCallExt for BaseEntityMethodExt {
const ID_RANGE: ElementIdRange = id::BASE_ENTITY_METHOD;
}
impl NoopElement for BaseEntityMethodExt {}
impl TopElement for BaseEntityMethodExt {
const LEN: ElementLength = ElementLength::Variable16;
}