aboutsummaryrefslogtreecommitdiff
path: root/core/bindings/lang/clang/src
diff options
context:
space:
mode:
author1992414357@qq.com <1992414357@qq.com>2025-06-16 04:57:50 +0800
committer1992414357@qq.com <1992414357@qq.com>2025-06-16 05:00:40 +0800
commit05f078b19471d2d05c71613afd42bab8df522b00 (patch)
treeda0ef21a88131b6e495bf6ec0dc03092e2815a76 /core/bindings/lang/clang/src
parent4a00dc20114401aee3d09539c265ae0f4369dfd6 (diff)
Add CBindings of GameData, GameRuntime
Diffstat (limited to 'core/bindings/lang/clang/src')
-rw-r--r--core/bindings/lang/clang/src/data/mod.rs5
-rw-r--r--core/bindings/lang/clang/src/data/ngpd_controller.rs76
-rw-r--r--core/bindings/lang/clang/src/data/ngpd_game.rs641
-rw-r--r--core/bindings/lang/clang/src/data/ngpd_game_info.rs2
-rw-r--r--core/bindings/lang/clang/src/data/ngpd_message.rs109
-rw-r--r--core/bindings/lang/clang/src/data/ngpd_player.rs24
-rw-r--r--core/bindings/lang/clang/src/lib.rs1
-rw-r--r--core/bindings/lang/clang/src/service/mod.rs1
-rw-r--r--core/bindings/lang/clang/src/service/ngpd_service_types.rs36
9 files changed, 797 insertions, 98 deletions
diff --git a/core/bindings/lang/clang/src/data/mod.rs b/core/bindings/lang/clang/src/data/mod.rs
index ca432f9..67e630a 100644
--- a/core/bindings/lang/clang/src/data/mod.rs
+++ b/core/bindings/lang/clang/src/data/mod.rs
@@ -1,4 +1,5 @@
pub mod ngpd_player;
pub mod ngpd_message;
-mod ngpd_game_info;
-mod ngpd_controller; \ No newline at end of file
+pub mod ngpd_game_info;
+pub mod ngpd_controller;
+pub mod ngpd_game; \ No newline at end of file
diff --git a/core/bindings/lang/clang/src/data/ngpd_controller.rs b/core/bindings/lang/clang/src/data/ngpd_controller.rs
index 923218b..c954df4 100644
--- a/core/bindings/lang/clang/src/data/ngpd_controller.rs
+++ b/core/bindings/lang/clang/src/data/ngpd_controller.rs
@@ -30,7 +30,7 @@ impl FfiControllerData {
/// Bind player to controller
#[unsafe(no_mangle)]
#[allow(unsafe_op_in_unsafe_fn)]
- pub unsafe extern "C" fn controller_data_bind_player(
+ pub extern "C" fn controller_data_bind_player(
controller: *mut FfiControllerData,
ffi_player: *mut FfiPlayer
) {
@@ -47,13 +47,13 @@ impl FfiControllerData {
controller_inner.bind_player(player);
// Release the FFI Player
- drop(Box::from_raw(ffi_player));
+ drop(unsafe { Box::from_raw(ffi_player) });
}
/// Build runtime
#[unsafe(no_mangle)]
#[allow(unsafe_op_in_unsafe_fn)]
- pub unsafe extern "C" fn controller_data_build_runtime(
+ pub extern "C" fn controller_data_build_runtime(
controller: *mut FfiControllerData
) -> *mut FfiControllerRuntime {
assert!(!controller.is_null(), "ControllerData pointer is null");
@@ -85,7 +85,7 @@ impl FfiControllerData {
/// Free ControllerData memory
#[unsafe(no_mangle)]
- pub unsafe extern "C" fn controller_data_free(controller: *mut FfiControllerData) {
+ pub extern "C" fn controller_data_free(controller: *mut FfiControllerData) {
if controller.is_null() {
return;
}
@@ -106,7 +106,7 @@ impl FfiControllerRuntime {
/// Close runtime and exit game
#[unsafe(no_mangle)]
- pub unsafe extern "C" fn controller_runtime_close(
+ pub extern "C" fn controller_runtime_close(
runtime: *mut FfiControllerRuntime
) {
if runtime.is_null() {
@@ -126,7 +126,7 @@ impl FfiControllerRuntime {
/// Send control message
#[unsafe(no_mangle)]
- pub unsafe extern "C" fn controller_runtime_send_message(
+ pub extern "C" fn controller_runtime_send_message(
runtime: *mut FfiControllerRuntime,
control_message: *mut FfiControlMessage
) {
@@ -147,7 +147,7 @@ impl FfiControllerRuntime {
/// Send text message
#[unsafe(no_mangle)]
- pub unsafe extern "C" fn controller_runtime_send_text_message(
+ pub extern "C" fn controller_runtime_send_text_message(
runtime: *mut FfiControllerRuntime,
message_ptr: *const c_char
) {
@@ -159,17 +159,15 @@ impl FfiControllerRuntime {
let text = c_str.to_string_lossy().into_owned();
let message = FfiControlMessage::from(ControlMessage::Msg(text));
- unsafe {
- Self::controller_runtime_send_message(
- runtime,
- Box::into_raw(Box::new(message))
- )
- }
+ Self::controller_runtime_send_message(
+ runtime,
+ Box::into_raw(Box::new(message))
+ )
}
/// Press a button
#[unsafe(no_mangle)]
- pub unsafe extern "C" fn controller_runtime_press_a_button(
+ pub extern "C" fn controller_runtime_press_a_button(
runtime: *mut FfiControllerRuntime,
key: u8
) {
@@ -181,17 +179,15 @@ impl FfiControllerRuntime {
ControlMessage::Pressed(key)
);
- unsafe {
- Self::controller_runtime_send_message(
- runtime,
- Box::into_raw(Box::new(message))
- )
- }
+ Self::controller_runtime_send_message(
+ runtime,
+ Box::into_raw(Box::new(message))
+ )
}
/// Release a button
#[unsafe(no_mangle)]
- pub unsafe extern "C" fn controller_runtime_release_a_button(
+ pub extern "C" fn controller_runtime_release_a_button(
runtime: *mut FfiControllerRuntime,
key: u8
) {
@@ -203,17 +199,15 @@ impl FfiControllerRuntime {
ControlMessage::Released(key)
);
- unsafe {
- Self::controller_runtime_send_message(
- runtime,
- Box::into_raw(Box::new(message))
- )
- }
+ Self::controller_runtime_send_message(
+ runtime,
+ Box::into_raw(Box::new(message))
+ )
}
/// Change axis value
#[unsafe(no_mangle)]
- pub unsafe extern "C" fn controller_runtime_change_axis(
+ pub extern "C" fn controller_runtime_change_axis(
runtime: *mut FfiControllerRuntime,
key: u8,
axis: c_double
@@ -226,17 +220,15 @@ impl FfiControllerRuntime {
ControlMessage::Axis(key, axis)
);
- unsafe {
- Self::controller_runtime_send_message(
- runtime,
- Box::into_raw(Box::new(message))
- )
- }
+ Self::controller_runtime_send_message(
+ runtime,
+ Box::into_raw(Box::new(message))
+ )
}
/// Change direction value
#[unsafe(no_mangle)]
- pub unsafe extern "C" fn controller_runtime_change_direction(
+ pub extern "C" fn controller_runtime_change_direction(
runtime: *mut FfiControllerRuntime,
key: u8,
x: c_double,
@@ -250,17 +242,15 @@ impl FfiControllerRuntime {
ControlMessage::Dir(key, (x, y))
);
- unsafe {
- Self::controller_runtime_send_message(
- runtime,
- Box::into_raw(Box::new(message))
- )
- }
+ Self::controller_runtime_send_message(
+ runtime,
+ Box::into_raw(Box::new(message))
+ )
}
/// Pop a message from the queue
#[unsafe(no_mangle)]
- pub unsafe extern "C" fn controller_runtime_pop(
+ pub extern "C" fn controller_runtime_pop(
runtime: *mut FfiControllerRuntime
) -> *mut FfiGameMessage {
if runtime.is_null() {
@@ -294,7 +284,7 @@ impl FfiControllerRuntime {
/// Free runtime memory
#[unsafe(no_mangle)]
- pub unsafe extern "C" fn controller_runtime_free(runtime: *mut FfiControllerRuntime) {
+ pub extern "C" fn free_controller_runtime(runtime: *mut FfiControllerRuntime) {
if runtime.is_null() {
return;
}
diff --git a/core/bindings/lang/clang/src/data/ngpd_game.rs b/core/bindings/lang/clang/src/data/ngpd_game.rs
new file mode 100644
index 0000000..dc82822
--- /dev/null
+++ b/core/bindings/lang/clang/src/data/ngpd_game.rs
@@ -0,0 +1,641 @@
+use crate::data::ngpd_message::{free_control_message, FfiControlMessage, FfiExitReason, FfiGameMessage};
+use crate::data::ngpd_player::{free_player, FfiPlayer};
+use crate::service::ngpd_service_types::FfiServiceType;
+use nogamepads::entry_mutex;
+use nogamepads_core::data::game::game_data::{GameData, GameRuntimeDataArchive};
+use nogamepads_core::data::game::game_runtime::GameRuntime;
+use nogamepads_core::data::message::message_enums::{ExitReason, GameMessage};
+use nogamepads_core::data::player::player_data::Player;
+use nogamepads_core::service::service_types::ServiceType;
+use std::ffi::{c_char, c_double, c_void, CStr};
+use std::ptr::null;
+use std::sync::{Arc, Mutex, MutexGuard};
+
+#[repr(C)]
+pub struct FfiGameData(*mut c_void);
+
+#[repr(C)]
+pub struct FfiGameRuntimeArchive(*mut c_void);
+
+#[repr(C)]
+pub struct FfiControlEvent {
+ player: FfiPlayer,
+ message: FfiControlMessage
+}
+
+#[repr(C)]
+pub struct FfiGameRuntime {
+ inner: *mut c_void,
+ drop_fn: extern "C" fn(*mut c_void),
+}
+
+#[repr(C)]
+pub struct FfiButtonStatus {
+ found: bool,
+ pressed: bool,
+ released: bool
+}
+
+#[repr(C)]
+pub struct FfiAxis {
+ found: bool,
+ axis: c_double
+}
+
+#[repr(C)]
+pub struct FfiDirection {
+ found: bool,
+ x: c_double,
+ y: c_double,
+}
+
+#[repr(C)]
+pub struct FfiBooleanResult {
+ found: bool,
+ result: bool
+}
+
+#[repr(C)]
+pub struct FfiPlayerList {
+ players: *mut FfiPlayer,
+ len: usize,
+ cap: usize,
+}
+
+impl FfiGameData {
+
+ /// Create game data
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_data_new() -> *mut FfiGameData {
+ let game_data = GameData::default();
+ let raw = Box::into_raw(Box::new(FfiGameData(Box::into_raw(Box::new(game_data)) as *mut _)));
+ raw
+ }
+
+ /// Load data archive
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_data_load_archive(
+ data: *mut FfiGameData,
+ archive: *mut FfiGameRuntimeArchive,
+ ) -> *mut FfiGameData {
+ if data.is_null() {
+ return std::ptr::null_mut();
+ }
+
+ if archive.is_null() {
+ return std::ptr::null_mut();
+ }
+
+ let data_inner = unsafe { &mut *((*data).0 as *mut GameData) };
+ let archive_inner = unsafe { &mut *((*archive).0 as *mut GameRuntimeDataArchive) };
+ let archive = *unsafe { Box::from_raw(archive_inner) };
+ data_inner.load_data(archive);
+
+ let raw = Box::into_raw(Box::new(FfiGameData(Box::into_raw(Box::new(data)) as *mut _)));
+ raw
+ }
+
+ /// Build runtime by data
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_data_build_runtime(
+ data: *mut FfiGameData
+ ) -> *mut FfiGameRuntime {
+ if data.is_null() {
+ return std::ptr::null_mut();
+ }
+
+ let data_inner = unsafe { &mut *((*data).0 as *mut GameData) };
+ let game_data = *unsafe { Box::from_raw(data_inner) };
+
+ let runtime = game_data.runtime();
+
+ extern "C" fn drop_runtime(raw: *mut c_void) {
+ unsafe {
+ let arc_ptr = raw as *const Arc<Mutex<GameRuntime>>;
+ drop(Arc::from_raw(arc_ptr));
+ }
+ }
+
+ let arc_raw = Arc::into_raw(runtime.clone()) as *mut c_void;
+
+ Box::into_raw(Box::new(FfiGameRuntime {
+ inner: arc_raw,
+ drop_fn: drop_runtime,
+ }))
+ }
+
+ /// Free data
+ #[unsafe(no_mangle)]
+ pub extern "C" fn free_game_data(data: *mut FfiGameData) {
+ if data.is_null() {
+ return;
+ }
+ let ffi_wrapper = unsafe { Box::from_raw(data) };
+ let inner_ptr = ffi_wrapper.0 as *mut GameData;
+ let _ = unsafe { Box::from_raw(inner_ptr) };
+ }
+}
+
+impl FfiGameRuntimeArchive {
+
+ /// Create game archive data
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_archive_data_new() -> *mut FfiGameRuntimeArchive {
+ let archive_data = GameRuntimeDataArchive::default();
+ let raw = Box::into_raw(Box::new(FfiGameRuntimeArchive(Box::into_raw(Box::new(archive_data)) as *mut _)));
+ raw
+ }
+
+ /// Add ban player
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_archive_data_add_ban_player(
+ data: *mut FfiGameRuntimeArchive,
+ ffi_player: *mut FfiPlayer
+ ) -> *mut FfiGameRuntimeArchive {
+ if data.is_null() {
+ return std::ptr::null_mut();
+ }
+
+ if ffi_player.is_null() {
+ return std::ptr::null_mut();
+ }
+
+ let data_inner = unsafe { &mut *((*data).0 as *mut GameRuntimeDataArchive) };
+ let ffi_player_ref = unsafe { &*ffi_player };
+ let player = Player::try_from(&*ffi_player_ref).unwrap_or_default();
+
+ data_inner.banned.push(player.account);
+
+ Box::into_raw(Box::new(FfiGameRuntimeArchive(Box::into_raw(Box::new(data_inner)) as *mut _)))
+ }
+
+ /// Free data
+ #[unsafe(no_mangle)]
+ pub extern "C" fn free_game_archive_data(data: *mut FfiGameRuntimeArchive) {
+ if data.is_null() {
+ return;
+ }
+ let ffi_wrapper = unsafe { Box::from_raw(data) };
+ let inner_ptr = ffi_wrapper.0 as *mut GameRuntimeDataArchive;
+ let _ = unsafe { Box::from_raw(inner_ptr) };
+ }
+}
+
+impl FfiGameRuntime {
+
+ fn send_message_to(
+ runtime: *mut FfiGameRuntime,
+ player: *const FfiPlayer,
+ service_type: *mut FfiServiceType,
+ message: GameMessage,
+ ) {
+ if runtime.is_null() || player.is_null() { return; }
+ let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<GameRuntime>> };
+ let arc_ref = unsafe { Arc::from_raw(arc_ptr) };
+ let ffi_player_ref = unsafe { &*player };
+ let player = Player::try_from(&*ffi_player_ref).unwrap_or_default();
+ let service = unsafe { ServiceType::from(&service_type.read()) };
+
+ entry_mutex!(*arc_ref, |mutex_guard| {
+ mutex_guard.send_game_message(&player.account, message, service);
+ });
+ }
+
+ fn do_on_rt(
+ runtime: *mut FfiGameRuntime,
+ do_on: fn(guard: &mut MutexGuard<GameRuntime>)
+ ) {
+ if runtime.is_null() { return; }
+ let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<GameRuntime>> };
+ let arc_ref = unsafe { Arc::from_raw(arc_ptr) };
+
+ entry_mutex!(*arc_ref, |mutex_guard| {
+ do_on(mutex_guard);
+ });
+ }
+
+ /// Send a message to
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_send_message_to(
+ runtime: *mut FfiGameRuntime,
+ player: *const FfiPlayer,
+ message: *mut FfiGameMessage,
+ service_type: *mut FfiServiceType
+ ) {
+ if message.is_null() { return; }
+ let msg = unsafe { GameMessage::from(message.read()) };
+ Self::send_message_to(runtime, player, service_type, msg);
+ }
+
+ /// Send a text message
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_send_text_message(
+ runtime: *mut FfiGameRuntime,
+ player: *const FfiPlayer,
+ service_type: *mut FfiServiceType,
+ text: *const c_char
+ ) {
+ let text_str = unsafe { CStr::from_ptr(text) }.to_string_lossy().into_owned().to_string();
+ Self::send_message_to(runtime, player, service_type, GameMessage::Msg(text_str));
+ }
+
+ /// Send a event message
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_send_event(
+ runtime: *mut FfiGameRuntime,
+ player: *const FfiPlayer,
+ service_type: *mut FfiServiceType,
+ key: u8
+ ) {
+ Self::send_message_to(runtime, player, service_type, GameMessage::EventTrigger(key));
+ }
+
+ /// Pop a control event
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_pop_control_event(runtime: *mut FfiGameRuntime) -> *mut FfiControlEvent {
+ if runtime.is_null() { return std::ptr::null_mut(); }
+ let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<GameRuntime>> };
+ let arc_ref = unsafe { Arc::from_raw(arc_ptr) };
+ let mut control_event = None;
+ entry_mutex!(*arc_ref, |mutex_guard| {
+ control_event = mutex_guard.pop_control_event();
+ });
+ match control_event {
+ None => { std::ptr::null_mut() }
+ Some((account, message)) => {
+ let hash = account.player_hash;
+ let player = FfiPlayer::from(&Player::register_from_hash(hash));
+ let message = FfiControlMessage::from(message);
+ Box::into_raw(Box::new(FfiControlEvent { player, message }))
+ }
+ }
+ }
+
+ /// Let player exit
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_let_exit(
+ runtime: *mut FfiGameRuntime,
+ player: *const FfiPlayer,
+ service_type: *mut FfiServiceType,
+ reason: *mut FfiExitReason
+ ) {
+ if reason.is_null() { return; }
+ let reason = unsafe { reason.read() };
+ let reason_msg = GameMessage::LetExit(ExitReason::from(&reason));
+ Self::send_message_to(runtime, player, service_type, reason_msg);
+ }
+
+ /// Kick a player
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_kick_player(
+ runtime: *mut FfiGameRuntime,
+ player: *const FfiPlayer,
+ service_type: *mut FfiServiceType
+ ) {
+ if runtime.is_null() || player.is_null() || service_type.is_null() { return; }
+
+ let ffi_player_ref = unsafe { &*player };
+ let player = Player::try_from(&*ffi_player_ref).unwrap_or_default();
+ let service = unsafe { ServiceType::from(&service_type.read()) };
+
+ if runtime.is_null() { return; }
+ let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<GameRuntime>> };
+ let arc_ref = unsafe { Arc::from_raw(arc_ptr) };
+ entry_mutex!(*arc_ref, |mutex_guard| {
+ mutex_guard.kick_player(&player, service);
+ });
+ }
+
+ /// Ban a player (And kick)
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_ban_player(
+ runtime: *mut FfiGameRuntime,
+ player: *const FfiPlayer,
+ service_type: *mut FfiServiceType
+ ) {
+ if runtime.is_null() || player.is_null() || service_type.is_null() { return; }
+
+ let ffi_player_ref = unsafe { &*player };
+ let player = Player::try_from(&*ffi_player_ref).unwrap_or_default();
+ let service = unsafe { ServiceType::from(&service_type.read()) };
+
+ if runtime.is_null() { return; }
+ let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<GameRuntime>> };
+ let arc_ref = unsafe { Arc::from_raw(arc_ptr) };
+ entry_mutex!(*arc_ref, |mutex_guard| {
+ mutex_guard.ban_player(&player, service);
+ });
+ }
+
+ /// Pardon a player
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_pardon_player(
+ runtime: *mut FfiGameRuntime,
+ player: *const FfiPlayer
+ ) {
+ if runtime.is_null() || player.is_null() { return; }
+
+ let ffi_player_ref = unsafe { &*player };
+ let player = Player::try_from(&*ffi_player_ref).unwrap_or_default();
+
+ if runtime.is_null() { return; }
+ let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<GameRuntime>> };
+ let arc_ref = unsafe { Arc::from_raw(arc_ptr) };
+ entry_mutex!(*arc_ref, |mutex_guard| {
+ mutex_guard.pardon_player(&player);
+ });
+ }
+
+ /// Close runtime
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_close(runtime: *mut FfiGameRuntime) {
+ if runtime.is_null() { return; }
+ Self::do_on_rt(runtime, |guard| {
+ guard.close_game();
+ })
+ }
+
+ /// Lock game
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_lock(runtime: *mut FfiGameRuntime) {
+ if runtime.is_null() { return; }
+ Self::do_on_rt(runtime, |guard| {
+ guard.lock_game();
+ })
+ }
+
+ /// Unlock game
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_unlock(runtime: *mut FfiGameRuntime) {
+ if runtime.is_null() { return; }
+ Self::do_on_rt(runtime, |guard| {
+ guard.unlock_game();
+ })
+ }
+
+ /// Get game lock status
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_get_lock_status(runtime: *mut FfiGameRuntime) -> bool {
+ if runtime.is_null() { return false; }
+
+ let mut locked = false;
+ let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<GameRuntime>> };
+ let arc_ref = unsafe { Arc::from_raw(arc_ptr) };
+ entry_mutex!(*arc_ref, |mutex_guard| {
+ locked = mutex_guard.is_game_locked();
+ });
+
+ locked
+ }
+
+ /// Get button status of player
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_get_button_status(
+ runtime: *mut FfiGameRuntime,
+ player: *const FfiPlayer,
+ key: u8
+ ) -> FfiButtonStatus {
+
+ let ffi_player_ref = unsafe { &*player };
+ let player = Player::try_from(&*ffi_player_ref).unwrap_or_default();
+ let account = player.account;
+
+ let mut status = None;
+ let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<GameRuntime>> };
+ let arc_ref = unsafe { Arc::from_raw(arc_ptr) };
+ entry_mutex!(*arc_ref, |mutex_guard| {
+ status = mutex_guard.control.get_button_status(&account, &key);
+ });
+
+ match status {
+ None => { FfiButtonStatus { found: false, pressed: false, released: false } }
+ Some(status) => {
+ FfiButtonStatus { found: true, pressed: status, released: !status }
+ }
+ }
+ }
+
+ /// Get axis value of player
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_get_axis(
+ runtime: *mut FfiGameRuntime,
+ player: *const FfiPlayer,
+ key: u8
+ ) -> FfiAxis {
+
+ let ffi_player_ref = unsafe { &*player };
+ let player = Player::try_from(&*ffi_player_ref).unwrap_or_default();
+ let account = player.account;
+
+ let mut status = None;
+ let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<GameRuntime>> };
+ let arc_ref = unsafe { Arc::from_raw(arc_ptr) };
+ entry_mutex!(*arc_ref, |mutex_guard| {
+ status = mutex_guard.control.get_axis(&account, &key);
+ });
+
+ match status {
+ None => { FfiAxis { found: false, axis: 0.0 } }
+ Some(status) => {
+ FfiAxis { found: true, axis: status }
+ }
+ }
+ }
+
+ /// Get direction value of player
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_get_direction(
+ runtime: *mut FfiGameRuntime,
+ player: *const FfiPlayer,
+ key: u8
+ ) -> FfiDirection {
+
+ let ffi_player_ref = unsafe { &*player };
+ let player = Player::try_from(&*ffi_player_ref).unwrap_or_default();
+ let account = player.account;
+
+ let mut status = None;
+ let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<GameRuntime>> };
+ let arc_ref = unsafe { Arc::from_raw(arc_ptr) };
+ entry_mutex!(*arc_ref, |mutex_guard| {
+ status = mutex_guard.control.get_direction(&account, &key);
+ });
+
+ match status {
+ None => { FfiDirection { found: false, x: 0.0, y: 0.0 } }
+ Some(status) => {
+ FfiDirection { found: true, x: status.0, y: status.1 }
+ }
+ }
+ }
+
+ /// Get service type of player
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_get_service_type(
+ runtime: *mut FfiGameRuntime,
+ player: *const FfiPlayer
+ ) -> *const FfiServiceType {
+
+ let ffi_player_ref = unsafe { &*player };
+ let player = Player::try_from(&*ffi_player_ref).unwrap_or_default();
+ let account = player.account;
+
+ let mut service_type = None;
+ let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<GameRuntime>> };
+ let arc_ref = unsafe { Arc::from_raw(arc_ptr) };
+ entry_mutex!(*arc_ref, |mutex_guard| {
+ service_type = mutex_guard.data.get_service_type(&account);
+ });
+
+ match service_type {
+ None => { null() }
+ Some(r) => {
+ Box::into_raw(Box::new(FfiServiceType::from(&r)))
+ }
+ }
+ }
+
+ /// Is player banned
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_is_player_banned(
+ runtime: *mut FfiGameRuntime,
+ player: *const FfiPlayer
+ ) -> FfiBooleanResult {
+
+ let ffi_player_ref = unsafe { &*player };
+ let player = Player::try_from(&*ffi_player_ref).unwrap_or_default();
+ let account = player.account;
+
+ let mut banned = None;
+ let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<GameRuntime>> };
+ let arc_ref = unsafe { Arc::from_raw(arc_ptr) };
+ entry_mutex!(*arc_ref, |mutex_guard| {
+ banned = Some(mutex_guard.data.is_account_banned(&account));
+ });
+
+ match banned {
+ None => { FfiBooleanResult { found: false, result: false } }
+ Some(r) => {
+ FfiBooleanResult { found: false, result: r }
+ }
+ }
+ }
+
+ /// Is player online
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_is_player_online(
+ runtime: *mut FfiGameRuntime,
+ player: *const FfiPlayer
+ ) -> FfiBooleanResult {
+
+ let ffi_player_ref = unsafe { &*player };
+ let player = Player::try_from(&*ffi_player_ref).unwrap_or_default();
+ let account = player.account;
+
+ let mut online = None;
+ let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<GameRuntime>> };
+ let arc_ref = unsafe { Arc::from_raw(arc_ptr) };
+ entry_mutex!(*arc_ref, |mutex_guard| {
+ online = Some(mutex_guard.data.is_account_online(&account));
+ });
+
+ match online {
+ None => { FfiBooleanResult { found: false, result: false } }
+ Some(r) => {
+ FfiBooleanResult { found: false, result: r }
+ }
+ }
+ }
+
+ /// Get online list
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_get_online_list(runtime: *mut FfiGameRuntime) -> FfiPlayerList {
+
+ let mut online_list = None;
+ let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<GameRuntime>> };
+ let arc_ref = unsafe { Arc::from_raw(arc_ptr) };
+ entry_mutex!(*arc_ref, |mutex_guard| {
+ online_list = Some(mutex_guard.data.online_accounts());
+ });
+
+ let mut result : Vec<FfiPlayer> = vec![];
+ if online_list.is_some() {
+ for online in online_list.unwrap() {
+ result.push(FfiPlayer::from(&Player::register_from_hash(online.player_hash)));
+ }
+ }
+
+ let len = result.len();
+ let cap = result.capacity();
+ let ptr = result.as_mut_ptr();
+ FfiPlayerList {
+ players: ptr,
+ len,
+ cap,
+ }
+ }
+
+ /// Get banned list
+ #[unsafe(no_mangle)]
+ pub extern "C" fn game_runtime_get_banned_list(runtime: *mut FfiGameRuntime) -> FfiPlayerList {
+
+ let mut banned_list = None;
+ let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<GameRuntime>> };
+ let arc_ref = unsafe { Arc::from_raw(arc_ptr) };
+ entry_mutex!(*arc_ref, |mutex_guard| {
+ banned_list = Some(mutex_guard.data.banned_accounts());
+ });
+
+ let mut result : Vec<FfiPlayer> = vec![];
+ if banned_list.is_none() {
+ for online in banned_list.unwrap() {
+ result.push(FfiPlayer::from(&Player::register_from_hash(online.player_hash)));
+ }
+ }
+
+ let len = result.len();
+ let cap = result.capacity();
+ let ptr = result.as_mut_ptr();
+ FfiPlayerList {
+ players: ptr,
+ len,
+ cap,
+ }
+ }
+}
+
+impl FfiControlEvent {
+
+ /// Free control event
+ #[unsafe(no_mangle)]
+ pub extern "C" fn free_control_event(event: *mut FfiControlEvent) {
+ if event.is_null() {
+ return;
+ }
+
+ let event_box = unsafe { Box::from_raw(event) };
+
+ let player_ptr = Box::into_raw(Box::new(event_box.player));
+ free_player(player_ptr);
+
+ let message_ptr = Box::into_raw(Box::new(event_box.message));
+ free_control_message(message_ptr);
+ }
+}
+
+impl FfiPlayerList {
+
+ /// Free player list
+ #[unsafe(no_mangle)]
+ pub extern "C" fn free_player_list(list: FfiPlayerList) {
+ if !list.players.is_null() {
+ let _ = unsafe {
+ Vec::from_raw_parts(
+ list.players,
+ list.len,
+ list.cap,
+ )
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/core/bindings/lang/clang/src/data/ngpd_game_info.rs b/core/bindings/lang/clang/src/data/ngpd_game_info.rs
index b83d0f7..c85d2f3 100644
--- a/core/bindings/lang/clang/src/data/ngpd_game_info.rs
+++ b/core/bindings/lang/clang/src/data/ngpd_game_info.rs
@@ -96,7 +96,7 @@ impl From<&FfiGameInfo> for Option<HashMap<String, String>> {
}
#[unsafe(no_mangle)]
-pub unsafe extern "C" fn free_game_info(map: FfiGameInfo) {
+pub extern "C" fn free_game_info(map: FfiGameInfo) {
let kv_pairs = unsafe { Vec::from_raw_parts(map.data, map.len, map.cap) };
for pair in kv_pairs {
diff --git a/core/bindings/lang/clang/src/data/ngpd_message.rs b/core/bindings/lang/clang/src/data/ngpd_message.rs
index 624d0b8..58635c3 100644
--- a/core/bindings/lang/clang/src/data/ngpd_message.rs
+++ b/core/bindings/lang/clang/src/data/ngpd_message.rs
@@ -483,96 +483,105 @@ impl From<&FfiJoinFailedMessage> for JoinFailedMessage {
/// Free ControlMessage
#[unsafe(no_mangle)]
-pub unsafe extern "C" fn free_control_message(msg: *mut FfiControlMessage) {
+pub extern "C" fn free_control_message(msg: *mut FfiControlMessage) {
if msg.is_null() { return; }
- let msg = Box::from_raw(msg);
+ let msg = unsafe { Box::from_raw(msg) };
- match msg.tag {
- FfiControlMessageTag::CtrlMsg => {
- if !msg.data.message.is_null() {
- drop(CString::from_raw(msg.data.message));
+ unsafe {
+ match msg.tag {
+ FfiControlMessageTag::CtrlMsg => {
+ if !msg.data.message.is_null() {
+ drop(CString::from_raw(msg.data.message));
+ }
}
+ FfiControlMessageTag::CtrlAxis => {
+ let ptr = ManuallyDrop::into_inner(msg.data.key_and_axis);
+ drop(ptr);
+ }
+ FfiControlMessageTag::CtrlDir => {
+ let ptr = ManuallyDrop::into_inner(msg.data.key_and_direction);
+ drop(ptr);
+ }
+ _ => {}
}
- FfiControlMessageTag::CtrlAxis => {
- let ptr = ManuallyDrop::into_inner(msg.data.key_and_axis);
- drop(ptr);
- }
- FfiControlMessageTag::CtrlDir => {
- let ptr = ManuallyDrop::into_inner(msg.data.key_and_direction);
- drop(ptr);
- }
- _ => {}
}
}
/// Free GameMessage
#[unsafe(no_mangle)]
-pub unsafe extern "C" fn free_game_message(msg: *mut FfiGameMessage) {
+pub extern "C" fn free_game_message(msg: *mut FfiGameMessage) {
if msg.is_null() { return; }
- let msg = Box::from_raw(msg);
+ let msg = unsafe { Box::from_raw(msg) };
- match msg.tag {
- FfiGameMessageTag::GameMsg => {
- if !msg.data.message.is_null() {
- drop(CString::from_raw(msg.data.message));
+ unsafe {
+ match msg.tag {
+ FfiGameMessageTag::GameMsg => {
+ if !msg.data.message.is_null() {
+ drop(CString::from_raw(msg.data.message));
+ }
}
+ FfiGameMessageTag::GameLetExit => {
+ let reason = ManuallyDrop::into_inner(msg.data.exit_reason);
+ drop(reason);
+ }
+ _ => {}
}
- FfiGameMessageTag::GameLetExit => {
- let reason = ManuallyDrop::into_inner(msg.data.exit_reason);
- drop(reason);
- }
- _ => {}
}
}
/// Free ExitReason
#[unsafe(no_mangle)]
-pub unsafe extern "C" fn free_exit_reason(msg: *mut FfiExitReason) {
+pub extern "C" fn free_exit_reason(msg: *mut FfiExitReason) {
if !msg.is_null() {
- drop(Box::from_raw(msg));
+ drop(unsafe { Box::from_raw(msg) });
}
}
+
/// Free ConnectionMessage
#[unsafe(no_mangle)]
-pub unsafe extern "C" fn free_connection_message(msg: *mut FfiConnectionMessage) {
+pub extern "C" fn free_connection_message(msg: *mut FfiConnectionMessage) {
if msg.is_null() { return; }
- let msg = Box::from_raw(msg);
+ let msg = unsafe { Box::from_raw(msg) };
- match msg.tag {
- FfiConnectionMessageTag::ConnectionJoin => {
- let player = ManuallyDrop::into_inner(msg.data.player);
- let player_ptr = Box::into_raw(Box::new(player));
+ unsafe {
+ match msg.tag {
+ FfiConnectionMessageTag::ConnectionJoin => {
+ let player = ManuallyDrop::into_inner(msg.data.player);
+ let player_ptr = Box::into_raw(Box::new(player));
- free_player(player_ptr);
+ free_player(player_ptr);
+ }
+ _ => {}
}
- _ => {}
}
}
/// Free ConnectionResponseMessage
#[unsafe(no_mangle)]
-pub unsafe extern "C" fn free_connection_response_message(msg: *mut FfiConnectionResponseMessage) {
+pub extern "C" fn free_connection_response_message(msg: *mut FfiConnectionResponseMessage) {
if msg.is_null() { return; }
- let msg = Box::from_raw(msg);
+ let msg = unsafe { Box::from_raw(msg) };
- match msg.tag {
- FfiConnectionResponseMessageTag::GameInfosResponse => {
- let game_info = ManuallyDrop::into_inner(msg.data.game_info);
- free_game_info(game_info);
- }
- FfiConnectionResponseMessageTag::DenyResponse |
- FfiConnectionResponseMessageTag::FailResponse => {
- let failed_msg = ManuallyDrop::into_inner(msg.data.failed_message);
- drop(failed_msg);
+ unsafe {
+ match msg.tag {
+ FfiConnectionResponseMessageTag::GameInfosResponse => {
+ let game_info = ManuallyDrop::into_inner(msg.data.game_info);
+ free_game_info(game_info);
+ }
+ FfiConnectionResponseMessageTag::DenyResponse |
+ FfiConnectionResponseMessageTag::FailResponse => {
+ let failed_msg = ManuallyDrop::into_inner(msg.data.failed_message);
+ drop(failed_msg);
+ }
+ _ => {}
}
- _ => {}
}
}
/// Free JoinFailedMessage
#[unsafe(no_mangle)]
-pub unsafe extern "C" fn free_join_failed_message(msg: *mut FfiJoinFailedMessage) {
+pub extern "C" fn free_join_failed_message(msg: *mut FfiJoinFailedMessage) {
if !msg.is_null() {
- drop(Box::from_raw(msg));
+ drop(unsafe { Box::from_raw(msg) });
}
} \ No newline at end of file
diff --git a/core/bindings/lang/clang/src/data/ngpd_player.rs b/core/bindings/lang/clang/src/data/ngpd_player.rs
index c2c3378..0c4710b 100644
--- a/core/bindings/lang/clang/src/data/ngpd_player.rs
+++ b/core/bindings/lang/clang/src/data/ngpd_player.rs
@@ -1,11 +1,12 @@
use std::ffi::{c_char, c_double, c_int, CStr, CString};
use std::ptr;
use nogamepads_core::data::player::player_data::{Account, Customize, Player};
+use crate::converter::string_converter::str_rs_to_c;
#[repr(C)]
pub struct FfiAccount {
- id: *mut c_char,
- player_hash: *mut c_char,
+ pub(crate) id: *mut c_char,
+ pub(crate) player_hash: *mut c_char,
}
#[repr(C)]
@@ -82,6 +83,25 @@ pub extern "C" fn player_register(id: *const c_char, password: *const c_char) ->
Box::into_raw(Box::new(FfiPlayer::from(&player)))
}
+/// Register a player from hash
+#[unsafe(no_mangle)]
+pub extern "C" fn player_from_hash(hash: *const c_char) -> *mut FfiPlayer {
+ let hash_str = unsafe { CStr::from_ptr(hash) }.to_string_lossy();
+
+ let player = Player::register_from_hash(hash_str.into_owned());
+ Box::into_raw(Box::new(FfiPlayer::from(&player)))
+}
+
+/// Get a hash from player
+#[unsafe(no_mangle)]
+pub extern "C" fn player_get_hash(player: *mut FfiPlayer) -> *const c_char {
+ let rust_player : Player = unsafe { (&*player).try_into().unwrap() };
+
+ let hash = rust_player.account.player_hash.clone();
+ *unsafe { &mut *player } = FfiPlayer::from(&rust_player);
+ unsafe { str_rs_to_c(hash) }
+}
+
/// Check if the player's password is correct
#[unsafe(no_mangle)]
pub extern "C" fn player_check(player: *const FfiPlayer, password: *const c_char) -> bool {
diff --git a/core/bindings/lang/clang/src/lib.rs b/core/bindings/lang/clang/src/lib.rs
index 9a8fe37..f939758 100644
--- a/core/bindings/lang/clang/src/lib.rs
+++ b/core/bindings/lang/clang/src/lib.rs
@@ -1,2 +1,3 @@
pub mod converter;
pub mod data;
+pub mod service;
diff --git a/core/bindings/lang/clang/src/service/mod.rs b/core/bindings/lang/clang/src/service/mod.rs
new file mode 100644
index 0000000..464cfba
--- /dev/null
+++ b/core/bindings/lang/clang/src/service/mod.rs
@@ -0,0 +1 @@
+pub mod ngpd_service_types; \ No newline at end of file
diff --git a/core/bindings/lang/clang/src/service/ngpd_service_types.rs b/core/bindings/lang/clang/src/service/ngpd_service_types.rs
new file mode 100644
index 0000000..8701284
--- /dev/null
+++ b/core/bindings/lang/clang/src/service/ngpd_service_types.rs
@@ -0,0 +1,36 @@
+use nogamepads_core::service::service_types::ServiceType;
+
+#[repr(C)]
+pub enum FfiServiceType {
+ TCPConnection,
+ BlueTooth,
+ USB,
+}
+
+impl From<&ServiceType> for FfiServiceType {
+ fn from(value: &ServiceType) -> Self {
+ match value {
+ ServiceType::TCPConnection => { FfiServiceType::TCPConnection }
+ ServiceType::BlueTooth => { FfiServiceType::BlueTooth }
+ ServiceType::USB => { FfiServiceType::USB }
+ }
+ }
+}
+
+impl From<&FfiServiceType> for ServiceType {
+ fn from(value: &FfiServiceType) -> Self {
+ match value {
+ FfiServiceType::TCPConnection => { ServiceType::TCPConnection }
+ FfiServiceType::BlueTooth => { ServiceType::BlueTooth }
+ FfiServiceType::USB => { ServiceType::USB }
+ }
+ }
+}
+
+/// Free service type tag
+#[unsafe(no_mangle)]
+pub extern "C" fn free_ffi_service_type(ptr: *mut FfiServiceType) {
+ if !ptr.is_null() {
+ unsafe { let _ = Box::from_raw(ptr); }
+ }
+} \ No newline at end of file