use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use crate::message::{Coupling, MessageMeta, MessageType};
#[derive(Debug, thiserror::Error)]
pub enum VehicleError {
#[error("vehicle not found")]
VehicleNotFound = 256,
#[error("bogie not found")]
BogieNotFound = 512,
#[error("axle not found")]
AxleNotFound = 1024,
#[error("coupling not found")]
CouplingNotFound = 2048,
#[error("pantograph not found")]
PantographNotFound = 4096,
#[error("road axle not found")]
RoadAxleNotFound = 8192,
#[error("road wheel not found")]
RoadWheelNotFound = 16384,
#[error("unknown error")]
Unknown = 0,
}
impl From<u32> for VehicleError {
fn from(value: u32) -> Self {
match value {
256 => VehicleError::VehicleNotFound,
512 => VehicleError::BogieNotFound,
1024 => VehicleError::AxleNotFound,
2048 => VehicleError::CouplingNotFound,
4096 => VehicleError::PantographNotFound,
8192 => VehicleError::RoadAxleNotFound,
16384 => VehicleError::RoadWheelNotFound,
_ => VehicleError::Unknown,
}
}
}
#[cfg(feature = "ffi")]
pub fn spawned_inverted_to_train() -> bool {
unsafe { lotus_script_sys::vehicle::spawned_inverted_to_train() == 1 }
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TrainVehicleConfiguration {
pub number: String,
pub reversed_to_train: bool,
}
pub type TrainConfiguration = Vec<TrainVehicleConfiguration>;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TrainConfigurationChanged {
pub entity_id: u64,
pub reversed_to_train: bool,
pub index_in_train: usize,
pub train_vehicle_count: usize,
#[serde(default)]
pub train_configuration: Option<TrainConfiguration>,
}
impl MessageType for TrainConfigurationChanged {
const MESSAGE_META: MessageMeta = MessageMeta::new("builtin", "vehicle_in_train_changed", None);
}
impl TrainConfigurationChanged {
pub fn neighbour_vehicle_count(&self, coupling: Coupling) -> usize {
if (coupling == Coupling::Rear) ^ self.reversed_to_train {
self.train_vehicle_count - self.index_in_train - 1
} else {
self.index_in_train
}
}
}
#[cfg(feature = "ffi")]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Bogie {
index: usize,
}
#[cfg(feature = "ffi")]
impl Bogie {
pub fn get(index: usize) -> Result<Self, VehicleError> {
match unsafe { lotus_script_sys::vehicle::bogie_is_valid(index as u32) } {
0 => Ok(Self { index }),
e => Err(e.into()),
}
}
pub fn set_rail_brake_force_newton(self, value: f32) {
unsafe { lotus_script_sys::vehicle::set_rail_brake_force_newton(self.index as u32, value) };
}
}
#[cfg(feature = "ffi")]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Axle {
bogie_index: usize,
axle_index: usize,
}
#[cfg(feature = "ffi")]
impl Axle {
pub fn get(bogie_index: usize, axle_index: usize) -> Result<Self, VehicleError> {
match unsafe {
lotus_script_sys::vehicle::axle_is_valid(bogie_index as u32, axle_index as u32)
} {
0 => Ok(Self {
bogie_index,
axle_index,
}),
e => Err(e.into()),
}
}
pub fn velocity_var_name(self) -> String {
format!("v_Axle_mps_{}_{}", self.bogie_index, self.axle_index)
}
pub fn bogie(self) -> Bogie {
Bogie {
index: self.bogie_index,
}
}
pub fn axle_index(self) -> usize {
self.axle_index
}
pub fn bogie_index(self) -> usize {
self.bogie_index
}
pub fn inverse_radius(self) -> f32 {
let inverse_radius = unsafe {
lotus_script_sys::vehicle::inverse_radius(
self.bogie_index as u32,
self.axle_index as u32,
)
};
assert!(!inverse_radius.is_nan());
assert_ne!(inverse_radius, f32::NEG_INFINITY);
assert_ne!(inverse_radius, f32::INFINITY);
inverse_radius
}
pub fn surface_type(self) -> SurfaceType {
let surface_type = unsafe {
lotus_script_sys::vehicle::surface_type(self.bogie_index as u32, self.axle_index as u32)
};
SurfaceType::try_from(surface_type).unwrap()
}
pub fn rail_quality(self) -> RailQuality {
let quality = unsafe {
lotus_script_sys::vehicle::rail_quality(self.bogie_index as u32, self.axle_index as u32)
};
RailQuality::try_from(quality).unwrap()
}
pub fn set_traction_force_newton(self, value: f32) {
unsafe {
lotus_script_sys::vehicle::set_traction_force_newton(
self.bogie_index as u32,
self.axle_index as u32,
value,
)
};
}
pub fn set_brake_force_newton(self, value: f32) {
unsafe {
lotus_script_sys::vehicle::set_brake_force_newton(
self.bogie_index as u32,
self.axle_index as u32,
value,
)
};
}
}
#[cfg(feature = "ffi")]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct RoadAxle {
index: usize,
}
#[cfg(feature = "ffi")]
impl RoadAxle {
pub fn get(index: usize) -> Result<Self, VehicleError> {
match unsafe { lotus_script_sys::vehicle::road_axle_is_valid(index as u32) } {
0 => Ok(Self { index }),
e => Err(e.into()),
}
}
}
#[cfg(feature = "ffi")]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct RoadWheel {
axle_index: usize,
wheel_index: usize,
}
#[cfg(feature = "ffi")]
impl RoadWheel {
pub fn get(axle_index: usize, wheel_index: usize) -> Result<Self, VehicleError> {
match unsafe {
lotus_script_sys::vehicle::road_wheel_is_valid(axle_index as u32, wheel_index as u32)
} {
0 => Ok(Self {
axle_index,
wheel_index,
}),
e => Err(e.into()),
}
}
pub fn velocity_var_name(self) -> String {
format!("v_wheel_mps_{}_{}", self.axle_index, self.wheel_index)
}
pub fn wheel_index(self) -> usize {
self.wheel_index
}
pub fn axle_index(self) -> usize {
self.axle_index
}
pub fn set_traction_force_newton(self, value: f32) {
unsafe {
lotus_script_sys::vehicle::set_wheel_traction_force_newton(
self.axle_index as u32,
self.wheel_index as u32,
value,
)
};
}
pub fn set_brake_force_newton(self, value: f32) {
unsafe {
lotus_script_sys::vehicle::set_wheel_brake_force_newton(
self.axle_index as u32,
self.wheel_index as u32,
value,
)
};
}
pub fn set_spring_factor(self, value: f32) {
unsafe {
lotus_script_sys::vehicle::set_wheel_spring_factor(
self.axle_index as u32,
self.wheel_index as u32,
value,
)
};
}
}
#[cfg(feature = "ffi")]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Pantograph {
index: usize,
}
#[cfg(feature = "ffi")]
impl Pantograph {
pub fn get(index: usize) -> Result<Self, VehicleError> {
match unsafe { lotus_script_sys::vehicle::pantograph_is_valid(index as u32) } {
0 => Ok(Self { index }),
e => Err(e.into()),
}
}
pub fn height(self) -> f32 {
let height = unsafe { lotus_script_sys::vehicle::pantograph_height(self.index as u32) };
assert!(!height.is_nan());
assert_ne!(height, f32::INFINITY);
height
}
pub fn voltage(self) -> f32 {
let voltage = unsafe { lotus_script_sys::vehicle::pantograph_voltage(self.index as u32) };
assert!(!voltage.is_nan());
assert_ne!(voltage, f32::INFINITY);
voltage
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize_repr, Deserialize_repr)]
#[repr(u8)]
pub enum RailQuality {
Smooth = 0,
Rough = 1,
FroggySmooth = 2,
FroggyRough = 3,
FlatGroove = 4,
HighSpeedSmooth = 5,
SmoothDirt = 6,
RoughDirt = 7,
Deraileur = 8,
}
impl TryFrom<u32> for RailQuality {
type Error = VehicleError;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
0 => Ok(RailQuality::Smooth),
1 => Ok(RailQuality::Rough),
2 => Ok(RailQuality::FroggySmooth),
3 => Ok(RailQuality::FroggyRough),
4 => Ok(RailQuality::FlatGroove),
5 => Ok(RailQuality::HighSpeedSmooth),
6 => Ok(RailQuality::SmoothDirt),
7 => Ok(RailQuality::RoughDirt),
8 => Ok(RailQuality::Deraileur),
value => Err(value.into()),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize_repr, Deserialize_repr)]
#[repr(u8)]
pub enum SurfaceType {
Gravel = 0,
Street = 1,
Grass = 2,
}
impl TryFrom<u32> for SurfaceType {
type Error = VehicleError;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
0 => Ok(SurfaceType::Gravel),
1 => Ok(SurfaceType::Street),
2 => Ok(SurfaceType::Grass),
value => Err(value.into()),
}
}
}
#[derive(Clone, Copy)]
pub struct RoadSteeringSpringDamperManipulator {
pub stiffness_add: f32,
pub stiffness_mult: f32,
pub damping_add: f32,
pub damping_mult: f32,
}
impl Default for RoadSteeringSpringDamperManipulator {
fn default() -> Self {
Self {
stiffness_add: 0.0,
stiffness_mult: 1.0,
damping_add: 0.0,
damping_mult: 1.0,
}
}
}
impl RoadSteeringSpringDamperManipulator {
pub fn new(
stiffness_add: f32,
stiffness_mult: f32,
damping_add: f32,
damping_mult: f32,
) -> Self {
Self {
stiffness_add,
stiffness_mult,
damping_add,
damping_mult,
}
}
}