pub mod events;
pub mod functions;
use std::ffi::c_void;
use crate::{
players::Player,
runtime::queue_api_call,
types::{colour::Colour, vector::Vector3},
vehicles::Vehicle,
};
pub use functions::load_functions;
pub struct Object {
handle: *const c_void,
}
impl Object {
pub fn get_handle(&self) -> *const c_void {
self.handle
}
pub fn new(handle: *const c_void) -> Self {
Self { handle }
}
pub fn create(
modelid: i32,
position: Vector3,
rotation: Vector3,
draw_distance: f32,
) -> Option<Object> {
let mut _id = 0;
functions::Object_Create(
modelid,
position.x,
position.y,
position.z,
rotation.x,
rotation.y,
rotation.z,
draw_distance,
&mut _id,
)
}
pub fn destroy(&self) {
self.defer_api_call(Box::new(move |object| {
functions::Object_Destroy(&object);
}));
}
pub fn attach_to_vehicle(&self, vehicle: &Vehicle, offset: Vector3, rotation: Vector3) -> bool {
functions::Object_AttachToVehicle(
self, vehicle, offset.x, offset.y, offset.z, rotation.x, rotation.y, rotation.z,
)
}
pub fn attach_to_object(
&self,
obj_attached_to: &Object,
offset: Vector3,
rotation: Vector3,
sync_rotation: bool,
) -> bool {
functions::Object_AttachToObject(
self,
obj_attached_to,
offset.x,
offset.y,
offset.z,
rotation.x,
rotation.y,
rotation.z,
sync_rotation,
)
}
pub fn attach_to_player(&self, player: &Player, offset: Vector3, rotation: Vector3) -> bool {
functions::Object_AttachToPlayer(
self, player, offset.x, offset.y, offset.z, rotation.x, rotation.y, rotation.z,
)
}
pub fn set_pos(&self, position: Vector3) -> bool {
functions::Object_SetPos(self, position.x, position.y, position.z)
}
pub fn get_pos(&self) -> Vector3 {
let mut pos = Vector3::default();
functions::Object_GetPos(self, &mut pos.x, &mut pos.y, &mut pos.z);
pos
}
pub fn set_rotation(&self, rotation: Vector3) -> bool {
functions::Object_SetRot(self, rotation.x, rotation.y, rotation.z)
}
pub fn get_rotation(&self) -> Vector3 {
let mut rotation = Vector3::default();
functions::Object_GetRot(self, &mut rotation.x, &mut rotation.y, &mut rotation.z);
rotation
}
pub fn get_model(&self) -> i32 {
functions::Object_GetModel(self)
}
pub fn set_no_camera_collision(&self) -> bool {
functions::Object_SetNoCameraCollision(self)
}
pub fn move_object(&self, data: ObjectMoveData) -> i32 {
self.defer_api_call(Box::new(move |object| {
functions::Object_Move(
&object,
data.targetPos.x,
data.targetPos.y,
data.targetPos.z,
data.speed,
data.targetRot.x,
data.targetRot.y,
data.targetRot.z,
);
}));
if data.speed <= 0.0 {
return 0; }
let distance = (data.targetPos - self.get_pos()).length();
let time_ms = (distance / data.speed) * 1000.0;
time_ms as i32
}
pub fn stop(&self) -> bool {
functions::Object_Stop(self)
}
pub fn is_moving(&self) -> bool {
functions::Object_IsMoving(self)
}
pub fn set_material(
&self,
material_index: i32,
model_id: i32,
texture_library: &str,
texture_name: &str,
material_colour: Colour,
) -> bool {
functions::Object_SetMaterial(
self,
material_index,
model_id,
texture_library,
texture_name,
material_colour.argb(),
)
}
pub fn set_material_text(
&self,
text: &str,
material_index: i32,
material_size: ObjectMaterialSize,
fontface: &str,
fontsize: i32,
bold: bool,
font_colour: Colour,
background_colour: Colour,
textalignment: ObjectMaterialTextAlign,
) -> bool {
functions::Object_SetMaterialText(
self,
text,
material_index,
material_size as i32,
fontface,
fontsize,
bold,
font_colour.argb(),
background_colour.argb(),
textalignment as i32,
)
}
pub fn set_objects_default_camera_collision(disable: bool) -> bool {
functions::Object_SetDefaultCameraCollision(disable)
}
pub fn get_draw_distance(&self) -> f32 {
functions::Object_GetDrawDistance(self)
}
pub fn get_move_speed(&self) -> f32 {
functions::Object_GetMoveSpeed(self)
}
pub fn get_move_data(&self) -> ObjectMoveData {
let mut data = ObjectMoveData {
speed: functions::Object_GetMoveSpeed(self),
..Default::default()
};
functions::Object_GetMovingTargetPos(
self,
&mut data.targetPos.x,
&mut data.targetPos.y,
&mut data.targetPos.z,
);
functions::Object_GetMovingTargetPos(
self,
&mut data.targetRot.x,
&mut data.targetRot.y,
&mut data.targetRot.z,
);
data
}
pub fn get_attached_data(&self) -> ObjectAttachmentData {
let mut data = ObjectAttachmentData::default();
let (mut pid, mut oid, mut vid): (i32, i32, i32) = (-1, -1, -1);
functions::Object_GetAttachedData(self, &mut pid, &mut oid, &mut vid);
if pid != 65535 {
data.ID = pid;
data.attachment_type = ObjectAttachmentType::Player;
} else if oid != 65535 {
data.ID = oid;
data.attachment_type = ObjectAttachmentType::Object;
} else if vid != 65535 {
data.ID = vid;
data.attachment_type = ObjectAttachmentType::Vehicle;
} else {
data.attachment_type = ObjectAttachmentType::None;
}
data.syncRotation = functions::Object_GetSyncRotation(self);
functions::Object_GetAttachedOffset(
self,
&mut data.offset.x,
&mut data.offset.y,
&mut data.offset.z,
&mut data.rotation.x,
&mut data.rotation.y,
&mut data.rotation.z,
);
data
}
pub fn is_material_slot_used(&self, material_index: i32) -> bool {
functions::Object_IsMaterialSlotUsed(self, material_index)
}
pub fn get_material_data(&self, material_index: i32) -> ObjectMaterialData {
let (
mut modelid,
mut texture_library,
mut texture_name,
mut material_colour,
mut text,
mut material_size,
mut font_face,
mut font_size,
mut bold,
mut font_colour,
mut background_colour,
mut text_alignment,
): (
i32,
String,
String,
i32,
String,
i32,
String,
i32,
bool,
i32,
i32,
i32,
) = Default::default();
functions::Object_GetMaterial(
self,
material_index,
&mut modelid,
&mut texture_library,
16,
&mut texture_name,
16,
&mut material_colour,
);
functions::Object_GetMaterialText(
self,
material_index,
&mut text,
16,
&mut material_size,
&mut font_face,
16,
&mut font_size,
&mut bold,
&mut font_colour,
&mut background_colour,
&mut text_alignment,
);
ObjectMaterialData::new(
modelid,
texture_library,
texture_name,
Colour::from_argb(material_colour as u32),
text,
material_size,
font_face,
font_size,
bold,
Colour::from_argb(font_colour as u32),
Colour::from_argb(background_colour as u32),
text_alignment,
)
}
pub fn is_no_camera_collision(&self) -> bool {
functions::Object_IsObjectNoCameraCollision(self)
}
pub fn get_id(&self) -> i32 {
functions::Object_GetID(self)
}
pub fn from_id(id: i32) -> Option<Object> {
functions::Object_FromID(id)
}
fn defer_api_call(&self, callback: Box<dyn FnOnce(Self)>) {
let object_id = self.get_id();
queue_api_call(Box::new(move || {
let object = match Self::from_id(object_id) {
Some(object) => object,
None => {
log::error!("object with id={object_id} not found");
return;
}
};
callback(object);
}));
}
}
pub struct PlayerObject {
handle: *const c_void,
pub player: Player,
}
impl PlayerObject {
pub fn get_handle(&self) -> *const c_void {
self.handle
}
pub fn new(handle: *const c_void, player: Player) -> Self {
Self { handle, player }
}
pub fn attach_player_object_to_vehicle(
&self,
vehicle: &Vehicle,
offset: Vector3,
rotation: Vector3,
) -> bool {
functions::PlayerObject_AttachToVehicle(
&self.player,
self,
vehicle,
offset.x,
offset.y,
offset.z,
rotation.x,
rotation.y,
rotation.z,
)
}
pub fn attach_player_object_to_player(
&self,
player_attached_to: &Player,
offset: Vector3,
rotation: Vector3,
) -> bool {
functions::PlayerObject_AttachToPlayer(
&self.player,
self,
player_attached_to,
offset.x,
offset.y,
offset.z,
rotation.x,
rotation.y,
rotation.z,
)
}
pub fn attach_player_object_to_object(
&self,
attached_to: &PlayerObject,
offset: Vector3,
rotation: Vector3,
) -> bool {
functions::PlayerObject_AttachToObject(
&self.player,
self,
attached_to,
offset.x,
offset.y,
offset.z,
rotation.x,
rotation.y,
rotation.z,
)
}
pub fn set_player_object_pos(&self, position: Vector3) -> bool {
functions::PlayerObject_SetPos(&self.player, self, position.x, position.y, position.z)
}
pub fn get_player_object_pos(&self) -> Vector3 {
let mut position = Vector3::default();
functions::PlayerObject_GetPos(
&self.player,
self,
&mut position.x,
&mut position.y,
&mut position.z,
);
position
}
pub fn set_player_object_rotation(&self, rotation: Vector3) -> bool {
functions::PlayerObject_SetRot(&self.player, self, rotation.x, rotation.y, rotation.z)
}
pub fn get_player_object_rotation(&self) -> Vector3 {
let mut rotation = Vector3::default();
functions::PlayerObject_GetRot(
&self.player,
self,
&mut rotation.x,
&mut rotation.y,
&mut rotation.z,
);
rotation
}
pub fn get_player_object_model(&self) -> i32 {
functions::PlayerObject_GetModel(&self.player, self)
}
pub fn set_player_object_no_camera_collision(&self) -> bool {
functions::PlayerObject_SetNoCameraCollision(&self.player, self)
}
pub fn move_player_object(&self, data: ObjectMoveData) -> i32 {
functions::PlayerObject_Move(
&self.player,
self,
data.targetPos.x,
data.targetPos.y,
data.targetPos.z,
data.speed,
data.targetRot.x,
data.targetRot.y,
data.targetRot.z,
)
}
pub fn stop_player_object(&self) -> bool {
functions::PlayerObject_Stop(&self.player, self)
}
pub fn is_player_object_moving(&self) -> bool {
functions::PlayerObject_IsMoving(&self.player, self)
}
pub fn set_player_object_material(
&self,
material_index: i32,
model_id: i32,
texture_library: &str,
texture_name: &str,
material_colour: Colour,
) -> bool {
functions::PlayerObject_SetMaterial(
&self.player,
self,
material_index,
model_id,
texture_library,
texture_name,
material_colour.argb(),
)
}
pub fn set_player_object_material_text(
&self,
text: &str,
material_index: i32,
material_size: i32,
fontface: &str,
fontsize: i32,
bold: bool,
font_colour: Colour,
background_colour: Colour,
textalignment: ObjectMaterialTextAlign,
) -> bool {
functions::PlayerObject_SetMaterialText(
&self.player,
self,
text,
material_index,
material_size,
fontface,
fontsize,
bold,
font_colour.argb(),
background_colour.argb(),
textalignment as i32,
)
}
pub fn get_player_object_draw_distance(&self) -> f32 {
functions::PlayerObject_GetDrawDistance(&self.player, self)
}
pub fn get_player_object_move_speed(&self) -> f32 {
functions::PlayerObject_GetMoveSpeed(&self.player, self)
}
pub fn get_player_object_moving_data(&self) -> ObjectMoveData {
let mut data = ObjectMoveData {
speed: functions::PlayerObject_GetMoveSpeed(&self.player, self),
..Default::default()
};
functions::PlayerObject_GetMovingTargetPos(
&self.player,
self,
&mut data.targetPos.x,
&mut data.targetPos.y,
&mut data.targetPos.z,
);
functions::PlayerObject_GetMovingTargetRot(
&self.player,
self,
&mut data.targetRot.x,
&mut data.targetRot.y,
&mut data.targetRot.z,
);
data
}
pub fn get_player_object_attached_data(&self) -> ObjectAttachmentData {
let mut data = ObjectAttachmentData::default();
let (mut pid, mut oid, mut vid): (i32, i32, i32) = (-1, -1, -1);
functions::PlayerObject_GetAttachedData(&self.player, self, &mut pid, &mut oid, &mut vid);
if pid != 65535 {
data.ID = pid;
data.attachment_type = ObjectAttachmentType::Player;
} else if oid != 65535 {
data.ID = oid;
data.attachment_type = ObjectAttachmentType::Object;
} else if vid != 65535 {
data.ID = vid;
data.attachment_type = ObjectAttachmentType::Vehicle;
} else {
data.attachment_type = ObjectAttachmentType::None;
}
data.syncRotation = functions::PlayerObject_GetSyncRotation(&self.player, self);
functions::PlayerObject_GetAttachedOffset(
&self.player,
self,
&mut data.offset.x,
&mut data.offset.y,
&mut data.offset.z,
&mut data.rotation.x,
&mut data.rotation.y,
&mut data.rotation.z,
);
data
}
pub fn is_player_object_material_slot_used(&self, material_index: i32) -> bool {
functions::PlayerObject_IsMaterialSlotUsed(&self.player, self, material_index)
}
pub fn get_player_object_material_data(&self, material_index: i32) -> ObjectMaterialData {
let (
mut modelid,
mut texture_library,
mut texture_name,
mut material_colour,
mut text,
mut material_size,
mut font_face,
mut font_size,
mut bold,
mut font_colour,
mut background_colour,
mut text_alignment,
): (
i32,
String,
String,
i32,
String,
i32,
String,
i32,
bool,
i32,
i32,
i32,
) = Default::default();
functions::PlayerObject_GetMaterial(
&self.player,
self,
material_index,
&mut modelid,
&mut texture_library,
16,
&mut texture_name,
16,
&mut material_colour,
);
functions::PlayerObject_GetMaterialText(
&self.player,
self,
material_index,
&mut text,
16,
&mut material_size,
&mut font_face,
16,
&mut font_size,
&mut bold,
&mut font_colour,
&mut background_colour,
&mut text_alignment,
);
ObjectMaterialData::new(
modelid,
texture_library,
texture_name,
Colour::from_argb(material_colour as u32),
text,
material_size,
font_face,
font_size,
bold,
Colour::from_argb(font_colour as u32),
Colour::from_argb(background_colour as u32),
text_alignment,
)
}
pub fn is_player_object_no_camera_collision(&self) -> bool {
functions::PlayerObject_IsNoCameraCollision(&self.player, self)
}
pub fn get_id(&self) -> i32 {
functions::PlayerObject_GetID(&self.player, self)
}
}
#[repr(C)]
#[derive(Default, Clone, Copy, Debug)]
pub struct ObjectMoveData {
pub targetPos: Vector3,
pub targetRot: Vector3,
pub speed: f32,
}
#[repr(C)]
#[derive(Default, PartialEq, Clone, Copy, Debug)]
pub enum ObjectAttachmentType {
#[default]
None,
Vehicle,
Object,
Player,
}
#[repr(C)]
#[derive(Default, Clone, Copy, Debug)]
pub struct ObjectAttachmentData {
pub attachment_type: ObjectAttachmentType,
pub syncRotation: bool,
pub ID: i32,
pub offset: Vector3,
pub rotation: Vector3,
}
#[repr(C)]
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum ObjectMaterialTextAlign {
Left,
Center,
Right,
}
#[repr(C)]
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum ObjectMaterialSize {
Size32x32 = 10,
Size64x32 = 20,
Size64x64 = 30,
Size128x32 = 40,
Size128x64 = 50,
Size128x128 = 60,
Size256x32 = 70,
Size256x64 = 80,
Size256x128 = 90,
Size256x256 = 100,
Size512x64 = 110,
Size512x128 = 120,
Size512x256 = 130,
Size512x512 = 140,
}
#[repr(C)]
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum ObjectMaterialType {
None,
Default,
Text,
}
#[derive(PartialEq, Clone, Debug)]
pub struct ObjectMaterialData {
pub modelid: i32,
pub textureLibrary: String,
pub textureName: String,
pub materialColour: Colour,
pub text: String,
pub materialSize: i32,
pub fontFace: String,
pub fontSize: i32,
pub bold: bool,
pub fontColour: Colour,
pub backgroundColour: Colour,
pub textAlignment: i32,
}
impl ObjectMaterialData {
pub fn new(
modelid: i32,
textureLibrary: String,
textureName: String,
materialColour: Colour,
text: String,
materialSize: i32,
fontFace: String,
fontSize: i32,
bold: bool,
fontColour: Colour,
backgroundColour: Colour,
textAlignment: i32,
) -> Self {
Self {
modelid,
textureLibrary,
textureName,
materialColour,
text,
materialSize,
fontFace,
fontSize,
bold,
fontColour,
backgroundColour,
textAlignment,
}
}
}
#[repr(C)]
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum ObjectEditResponse {
Cancel,
Final,
Update,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct ObjectAttachmentSlotData {
pub model: i32,
pub bone: i32,
pub offset: Vector3,
pub rotation: Vector3,
pub scale: Vector3,
pub colour1: Colour,
pub colour2: Colour,
}