use dll::RLBotCoreInterface;
use error::RLBotError;
use ffi;
use flatbuffers;
use inject;
use packeteer::Packeteer;
use rlbot_generated::rlbot::flat;
use std::cell::Cell;
use std::error::Error;
use std::marker::PhantomData;
use std::os::raw::{c_int, c_void};
use std::ptr::null_mut;
use std::slice;
pub fn init() -> Result<RLBot, Box<Error>> {
inject::inject_dll()?;
let interface = RLBotCoreInterface::load()?;
interface.wait_for_initialized()?;
Ok(RLBot::new(interface))
}
pub struct RLBot {
interface: RLBotCoreInterface,
not_sync: PhantomData<Cell<()>>,
}
impl RLBot {
pub(crate) fn new(interface: RLBotCoreInterface) -> RLBot {
RLBot {
interface,
not_sync: PhantomData,
}
}
pub fn packeteer(&self) -> Packeteer {
Packeteer::new(self)
}
pub fn update_player_input(
&self,
player_input: ffi::PlayerInput,
player_index: c_int,
) -> Result<(), RLBotError> {
let status = (self.interface.update_player_input)(player_input, player_index);
core_result(status)
}
pub fn update_player_input_flatbuffer(
&self,
player_input_buffer: &[u8],
) -> Result<(), RLBotError> {
let status = (self.interface.update_player_input_flatbuffer)(
player_input_buffer.as_ptr() as *mut c_void,
player_input_buffer.len() as c_int,
);
core_result(status)
}
pub fn update_live_data_packet(
&self,
packet: &mut ffi::LiveDataPacket,
) -> Result<(), RLBotError> {
let status = (self.interface.update_live_data_packet)(packet);
core_result(status)
}
pub fn update_live_data_packet_flatbuffer(&self) -> Option<flat::GameTickPacket> {
let byte_buffer = (self.interface.update_live_data_packet_flatbuffer)();
if byte_buffer.size == 0 {
None
} else {
let slice: &[u8] = unsafe {
slice::from_raw_parts(byte_buffer.ptr as *const u8, byte_buffer.size as usize)
};
Some(flatbuffers::get_root::<flat::GameTickPacket>(&slice))
}
}
pub fn update_field_info(&self, field_info: &mut ffi::FieldInfo) -> Result<(), RLBotError> {
let status = (self.interface.update_field_info)(field_info);
core_result(status)
}
pub fn update_field_info_flatbuffer(&self) -> Option<flat::FieldInfo> {
let byte_buffer = (self.interface.update_field_info_flatbuffer)();
if byte_buffer.size == 0 {
None
} else {
let slice: &[u8] = unsafe {
slice::from_raw_parts(byte_buffer.ptr as *const u8, byte_buffer.size as usize)
};
Some(flatbuffers::get_root::<flat::FieldInfo>(&slice))
}
}
pub fn set_game_state(&self, desired_game_state_buffer: &[u8]) -> Result<(), RLBotError> {
let status = (self.interface.set_game_state)(
desired_game_state_buffer.as_ptr() as *mut c_void,
desired_game_state_buffer.len() as c_int,
);
core_result(status)
}
pub fn render_group(&self, render_group_buffer: &[u8]) -> Result<(), RLBotError> {
let status = (self.interface.render_group)(
render_group_buffer.as_ptr() as *mut c_void,
render_group_buffer.len() as c_int,
);
core_result(status)
}
pub fn send_quick_chat(&self, quick_chat_buffer: &[u8]) -> Result<(), RLBotError> {
let status = (self.interface.send_quick_chat)(
quick_chat_buffer.as_ptr() as *mut c_void,
quick_chat_buffer.len() as c_int,
);
core_result(status)
}
pub fn start_match(&self, match_settings: ffi::MatchSettings) -> Result<(), RLBotError> {
let status = (self.interface.start_match)(match_settings, None, null_mut());
core_result(status)
}
}
fn core_result(status: ffi::RLBotCoreStatus) -> Result<(), RLBotError> {
match status {
ffi::RLBotCoreStatus::Success => Ok(()),
_ => Err(RLBotError { status }),
}
}