define_api_id!(0xbb0f_0e2f_ff53_2a51, "behavior-v0");
use crate::ErrorCode;
use bytemuck::Pod;
use bytemuck::Zeroable;
pub type ActorId = u32;
pub const CONTROLLER_SENTINEL_ACTOR_ID: ActorId = !0u32;
pub const INCOMING_MESSAGE_NO_INSTANCE_SENTINEL: u64 = 0xffff_ffff_ffff;
pub type Guid = u128;
pub type LocalBehaviorTypeId = u16;
pub type ForeignBehaviorInstanceId = u64;
pub const INVALID_GUID_COMPONENT: u64 = !0u64;
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Pod, Zeroable)]
pub struct OutgoingMessageAddr {
pub to_actor_id: ActorId,
_pad: u32,
behavior_guid_hi: u64,
behavior_guid_lo: u64,
}
impl OutgoingMessageAddr {
pub fn new(to_actor_id: ActorId) -> Self {
Self {
to_actor_id,
_pad: 0,
behavior_guid_hi: INVALID_GUID_COMPONENT,
behavior_guid_lo: INVALID_GUID_COMPONENT,
}
}
pub fn new_to_behavior(to_actor_id: ActorId, behavior_guid: Guid) -> Result<Self, ErrorCode> {
let behavior_guid_hi = (behavior_guid >> 64) as u64;
let behavior_guid_lo = behavior_guid as u64;
if behavior_guid_hi != INVALID_GUID_COMPONENT || behavior_guid_lo != INVALID_GUID_COMPONENT
{
Ok(Self {
to_actor_id,
_pad: 0,
behavior_guid_hi,
behavior_guid_lo,
})
} else {
Err(ErrorCode::InvalidArguments)
}
}
pub fn new_to_controller() -> Self {
Self {
to_actor_id: CONTROLLER_SENTINEL_ACTOR_ID,
_pad: 0,
behavior_guid_hi: INVALID_GUID_COMPONENT,
behavior_guid_lo: INVALID_GUID_COMPONENT,
}
}
pub fn guid(&self) -> Option<Guid> {
if self.behavior_guid_hi == INVALID_GUID_COMPONENT
&& self.behavior_guid_lo == INVALID_GUID_COMPONENT
{
None
} else {
Some((u128::from(self.behavior_guid_hi) << 64) | u128::from(self.behavior_guid_lo))
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Pod, Zeroable)]
pub struct OutgoingMessage {
pub addr: OutgoingMessageAddr,
serialized_message_ptr: u32,
serialized_message_len: u32,
}
impl OutgoingMessage {
pub fn new(addr: OutgoingMessageAddr, serialized_message: &[u8]) -> Self {
Self {
addr,
serialized_message_ptr: serialized_message.as_ptr() as _,
serialized_message_len: serialized_message.len() as _,
}
}
pub fn msg_ptr(&self) -> u32 {
self.serialized_message_ptr
}
pub fn msg_len(&self) -> u32 {
self.serialized_message_len
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Pod, Zeroable)]
pub struct IncomingMessage {
pub instance_id: ForeignBehaviorInstanceId,
pub actor_id: ActorId,
pub serialized_message_ptr: u32,
pub serialized_message_len: u32,
pub _pad: u32,
}
#[cfg_attr(feature = "with_serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LocalBehaviorRegistration {
pub type_id: LocalBehaviorTypeId,
pub name: String,
}
#[cfg_attr(feature = "with_serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LocalModuleRegistration {
pub behavior_infos: Vec<LocalBehaviorRegistration>,
}
#[ark_api_macros::ark_bindgen(imports = "ark-behavior-v0")]
mod behavior {
use super::ActorId;
use super::OutgoingMessage;
use crate::pod_helpers::Align16U128;
use crate::FFIResult;
extern "C" {
pub fn aspect_get(
aspect_guid_hi: u64,
aspect_guid_lo: u64,
actor_id: ActorId,
) -> FFIResult<Vec<u8>>;
#[with_memory]
pub fn send_outgoing_messages(outgoing_messages: &[OutgoingMessage]) -> FFIResult<()>;
pub fn actors_with_aspect(aspect_guid_hi: u64, aspect_guid_lo: u64) -> FFIResult<Vec<u8>>;
pub fn random_seed_value() -> Align16U128;
}
}
pub use behavior::*;