define_api_id!(0xbb0f_0abc_ff53_2c51, "behavior-controller-v0");
use crate::ErrorCode;
use bytemuck::Pod;
use bytemuck::Zeroable;
use std::ops::Deref;
pub type ActorId = u32;
pub type Guid = u128;
pub type BehaviorInstanceId = u64;
pub type BehaviorTypeIdInner = u32;
pub const INVALID_GUID_COMPONENT: u64 = !0u64;
pub const CONTROLLER_SENTINEL_ACTOR_ID: ActorId = !0u32;
pub const INCOMING_MESSAGE_NO_INSTANCE_SENTINEL: u64 = 0xffff_ffff_ffff;
#[cfg_attr(feature = "with_serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct BehaviorTypeId(pub BehaviorTypeIdInner);
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Pod, Zeroable)]
pub struct AspectAddr {
aspect_guid_hi: u64,
aspect_guid_lo: u64,
actor_id: ActorId,
_pad: u32,
}
impl AspectAddr {
pub fn new(aspect_guid: Guid, actor_id: ActorId) -> Result<Self, ErrorCode> {
let aspect_guid_hi = (aspect_guid >> 64) as u64;
let aspect_guid_lo = aspect_guid as u64;
if aspect_guid_hi != INVALID_GUID_COMPONENT || aspect_guid_lo != INVALID_GUID_COMPONENT {
Ok(Self {
actor_id,
aspect_guid_hi,
aspect_guid_lo,
_pad: 0,
})
} else {
Err(ErrorCode::InvalidArguments)
}
}
pub fn guid(&self) -> Guid {
(u128::from(self.aspect_guid_hi) << 64) | u128::from(self.aspect_guid_lo)
}
pub fn actor_id(&self) -> ActorId {
self.actor_id
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Pod, Zeroable)]
pub struct AspectUpsert {
pub addr: AspectAddr,
serialized_aspect_ptr: u32,
serialized_aspect_len: u32,
}
impl AspectUpsert {
pub fn new(addr: AspectAddr, serialized_aspect_data: &[u8]) -> Self {
Self {
addr,
serialized_aspect_ptr: serialized_aspect_data.as_ptr() as _,
serialized_aspect_len: serialized_aspect_data.len() as _,
}
}
pub fn aspect_ptr(&self) -> u32 {
self.serialized_aspect_ptr
}
pub fn aspect_len(&self) -> u32 {
self.serialized_aspect_len
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Pod, Zeroable)]
pub struct IncomingMessage {
pub instance_id: BehaviorInstanceId,
pub actor_id: ActorId,
serialized_message_ptr: u32,
serialized_message_len: u32,
_pad: u32,
}
impl IncomingMessage {
pub fn new(
instance_id: BehaviorInstanceId,
actor_id: ActorId,
serialized_message: &[u8],
) -> Self {
Self {
instance_id,
actor_id,
serialized_message_ptr: serialized_message.as_ptr() as _,
serialized_message_len: serialized_message.len() as _,
_pad: 0,
}
}
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 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, behavior_guid: Option<Guid>) -> Result<Self, ErrorCode> {
let (behavior_guid_hi, behavior_guid_lo) = match behavior_guid {
Some(guid) => {
let hi = (guid >> 64) as u64;
let lo = guid as u64;
if hi == INVALID_GUID_COMPONENT || lo == INVALID_GUID_COMPONENT {
return Err(ErrorCode::InvalidArguments);
}
(hi, lo)
}
None => (INVALID_GUID_COMPONENT, INVALID_GUID_COMPONENT),
};
Ok(Self {
to_actor_id,
_pad: 0,
behavior_guid_hi,
behavior_guid_lo,
})
}
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,
pub serialized_message_len: u32,
pub _pad: u32,
}
#[cfg_attr(feature = "with_serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub struct BehaviorModuleId(String);
impl BehaviorModuleId {
pub fn new(id: String) -> Self {
Self(id)
}
}
impl Deref for BehaviorModuleId {
type Target = str;
fn deref(&self) -> &Self::Target {
self.0.as_str()
}
}
#[cfg_attr(feature = "with_serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BehaviorRegistration {
pub type_id: BehaviorTypeId,
pub name: String,
}
#[cfg_attr(feature = "with_serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BehaviorModuleRegistration {
pub name: String,
pub id: Option<BehaviorModuleId>,
pub behavior_infos: Vec<BehaviorRegistration>,
}
#[ark_api_macros::ark_bindgen(imports = "ark-behavior-controller-v0")]
mod behavior_controller {
use super::*;
use crate::FFIResult;
extern "C" {
fn list_modules() -> Vec<u8>;
fn instance_create(type_id: BehaviorTypeIdInner, ron_params: &str) -> BehaviorInstanceId;
fn instance_destroy(instance_id: BehaviorInstanceId);
fn instance_clone(instance_id: BehaviorInstanceId) -> BehaviorInstanceId;
fn instance_persist(instance_id: BehaviorInstanceId) -> Vec<u8>;
fn instance_restore(type_id: BehaviorTypeIdInner, bytes: &[u8]) -> BehaviorInstanceId;
#[with_memory]
fn instances_handle_messages(messages: &[IncomingMessage]) -> Vec<u8>;
#[with_memory]
fn aspect_upsert(upserts: &[AspectUpsert]);
fn aspect_remove(removes: &[AspectAddr]);
fn aspect_reset_all();
fn publish(id: &str) -> FFIResult<String>;
fn load_behavior_module(id: &str) -> FFIResult<Vec<u8>>;
}
}
pub use behavior_controller::*;