diff options
| author | Weicao Mao <1992414357@qq.com> | 2025-06-16 05:00:08 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-16 05:00:08 +0800 |
| commit | f5072499d9241b22e7a259267cc0315841b7589d (patch) | |
| tree | da0ef21a88131b6e495bf6ec0dc03092e2815a76 | |
| parent | bb7a31c753df0a7663cdcc89aff840384b16564e (diff) | |
| parent | b44b687c3c90642bbe609593b301cd248745dfc6 (diff) | |
Merge pull request #5 from CatilGrass/c_bindings
Add CBindings of GameData, GameRuntime
| -rw-r--r-- | core/bindings/lang/clang/configures/nogamepads_data.toml | 3 | ||||
| -rw-r--r-- | core/bindings/lang/clang/configures/nogamepads_data_cpp.toml | 15 | ||||
| -rw-r--r-- | core/bindings/lang/clang/headers/nogamepads_data.h | 253 | ||||
| -rw-r--r-- | core/bindings/lang/clang/headers/nogamepads_data_cpp.h | 245 | ||||
| -rw-r--r-- | core/bindings/lang/clang/src/data/mod.rs | 5 | ||||
| -rw-r--r-- | core/bindings/lang/clang/src/data/ngpd_controller.rs | 76 | ||||
| -rw-r--r-- | core/bindings/lang/clang/src/data/ngpd_game.rs | 641 | ||||
| -rw-r--r-- | core/bindings/lang/clang/src/data/ngpd_game_info.rs | 2 | ||||
| -rw-r--r-- | core/bindings/lang/clang/src/data/ngpd_message.rs | 109 | ||||
| -rw-r--r-- | core/bindings/lang/clang/src/data/ngpd_player.rs | 24 | ||||
| -rw-r--r-- | core/bindings/lang/clang/src/lib.rs | 1 | ||||
| -rw-r--r-- | core/bindings/lang/clang/src/service/mod.rs | 1 | ||||
| -rw-r--r-- | core/bindings/lang/clang/src/service/ngpd_service_types.rs | 36 | ||||
| -rw-r--r-- | core/src/data/game/game_cli.rs | 4 | ||||
| -rw-r--r-- | core/src/data/game/game_data.rs | 4 | ||||
| -rw-r--r-- | core/src/data/game/game_runtime.rs | 2 | ||||
| -rw-r--r-- | core/src/data/player/player_data.rs | 11 |
17 files changed, 1062 insertions, 370 deletions
diff --git a/core/bindings/lang/clang/configures/nogamepads_data.toml b/core/bindings/lang/clang/configures/nogamepads_data.toml index 5c7e91b..a408296 100644 --- a/core/bindings/lang/clang/configures/nogamepads_data.toml +++ b/core/bindings/lang/clang/configures/nogamepads_data.toml @@ -12,4 +12,7 @@ include = [ "ngpd_message", "ngpd_player", "ngpd_controller", + "ngpd_game", + + "ngpd_service_types", ]
\ No newline at end of file diff --git a/core/bindings/lang/clang/configures/nogamepads_data_cpp.toml b/core/bindings/lang/clang/configures/nogamepads_data_cpp.toml deleted file mode 100644 index 82afbf4..0000000 --- a/core/bindings/lang/clang/configures/nogamepads_data_cpp.toml +++ /dev/null @@ -1,15 +0,0 @@ -language = "C++" -include_guard = "NOGAMEPADS_DATA_H" -header = "// Auto generated by cbindgen 0.29.0" -cpp_compat = true - -[parse] -parse_deps = true -include = [ - "string_converter", - - "ngpd_game_info", - "ngpd_message", - "ngpd_player", - "ngpd_controller", -]
\ No newline at end of file diff --git a/core/bindings/lang/clang/headers/nogamepads_data.h b/core/bindings/lang/clang/headers/nogamepads_data.h index 81dca74..8340bdd 100644 --- a/core/bindings/lang/clang/headers/nogamepads_data.h +++ b/core/bindings/lang/clang/headers/nogamepads_data.h @@ -61,6 +61,12 @@ typedef enum FfiJoinFailedMessage { UnknownError, } FfiJoinFailedMessage; +typedef enum FfiServiceType { + TCPConnection, + BlueTooth, + USB, +} FfiServiceType; + typedef struct FfiAccount { char *id; char *player_hash; @@ -151,6 +157,52 @@ typedef struct FfiControllerRuntime { void (*drop_fn)(void*); } FfiControllerRuntime; +typedef struct FfiGameData { + void *_0; +} FfiGameData; + +typedef struct FfiGameRuntimeArchive { + void *_0; +} FfiGameRuntimeArchive; + +typedef struct FfiGameRuntime { + void *inner; + void (*drop_fn)(void*); +} FfiGameRuntime; + +typedef struct FfiControlEvent { + struct FfiPlayer player; + struct FfiControlMessage message; +} FfiControlEvent; + +typedef struct FfiButtonStatus { + bool found; + bool pressed; + bool released; +} FfiButtonStatus; + +typedef struct FfiAxis { + bool found; + double axis; +} FfiAxis; + +typedef struct FfiDirection { + bool found; + double x; + double y; +} FfiDirection; + +typedef struct FfiBooleanResult { + bool found; + bool result; +} FfiBooleanResult; + +typedef struct FfiPlayerList { + struct FfiPlayer *players; + uintptr_t len; + uintptr_t cap; +} FfiPlayerList; + #ifdef __cplusplus extern "C" { #endif // __cplusplus @@ -163,6 +215,16 @@ void free_c_string(char *ptr); struct FfiPlayer *player_register(const char *id, const char *password); /** + * Register a player from hash + */ +struct FfiPlayer *player_from_hash(const char *hash); + +/** + * Get a hash from player + */ +const char *player_get_hash(struct FfiPlayer *player); + +/** * Check if the player's password is correct */ bool player_check(const struct FfiPlayer *player, const char *password); @@ -190,32 +252,32 @@ void free_player(struct FfiPlayer *player); /** * Free ControlMessage */ -void free_control_message(struct FfiControlMessage msg); +void free_control_message(struct FfiControlMessage *msg); /** * Free GameMessage */ -void free_game_message(struct FfiGameMessage msg); +void free_game_message(struct FfiGameMessage *msg); /** * Free ExitReason */ -void free_exit_reason(enum FfiExitReason msg); +void free_exit_reason(enum FfiExitReason *msg); /** * Free ConnectionMessage */ -void free_connection_message(struct FfiConnectionMessage msg); +void free_connection_message(struct FfiConnectionMessage *msg); /** * Free ConnectionResponseMessage */ -void free_connection_response_message(struct FfiConnectionResponseMessage msg); +void free_connection_response_message(struct FfiConnectionResponseMessage *msg); /** * Free JoinFailedMessage */ -void free_join_failed_message(enum FfiJoinFailedMessage msg); +void free_join_failed_message(enum FfiJoinFailedMessage *msg); void free_game_info(struct FfiGameInfo map); @@ -288,7 +350,184 @@ struct FfiGameMessage *controller_runtime_pop(struct FfiControllerRuntime *runti /** * Free runtime memory */ -void controller_runtime_free(struct FfiControllerRuntime *runtime); +void free_controller_runtime(struct FfiControllerRuntime *runtime); + +/** + * Create game data + */ +struct FfiGameData *game_data_new(void); + +/** + * Load data archive + */ +struct FfiGameData *game_data_load_archive(struct FfiGameData *data, + struct FfiGameRuntimeArchive *archive); + +/** + * Build runtime by data + */ +struct FfiGameRuntime *game_data_build_runtime(struct FfiGameData *data); + +/** + * Free data + */ +void free_game_data(struct FfiGameData *data); + +/** + * Create game archive data + */ +struct FfiGameRuntimeArchive *game_archive_data_new(void); + +/** + * Add ban player + */ +struct FfiGameRuntimeArchive *game_archive_data_add_ban_player(struct FfiGameRuntimeArchive *data, + struct FfiPlayer *ffi_player); + +/** + * Free data + */ +void free_game_archive_data(struct FfiGameRuntimeArchive *data); + +/** + * Send a message to + */ +void game_runtime_send_message_to(struct FfiGameRuntime *runtime, + const struct FfiPlayer *player, + struct FfiGameMessage *message, + enum FfiServiceType *service_type); + +/** + * Send a text message + */ +void game_runtime_send_text_message(struct FfiGameRuntime *runtime, + const struct FfiPlayer *player, + enum FfiServiceType *service_type, + const char *text); + +/** + * Send a event message + */ +void game_runtime_send_event(struct FfiGameRuntime *runtime, + const struct FfiPlayer *player, + enum FfiServiceType *service_type, + uint8_t key); + +/** + * Pop a control event + */ +struct FfiControlEvent *game_runtime_pop_control_event(struct FfiGameRuntime *runtime); + +/** + * Let player exit + */ +void game_runtime_let_exit(struct FfiGameRuntime *runtime, + const struct FfiPlayer *player, + enum FfiServiceType *service_type, + enum FfiExitReason *reason); + +/** + * Kick a player + */ +void game_runtime_kick_player(struct FfiGameRuntime *runtime, + const struct FfiPlayer *player, + enum FfiServiceType *service_type); + +/** + * Ban a player (And kick) + */ +void game_runtime_ban_player(struct FfiGameRuntime *runtime, + const struct FfiPlayer *player, + enum FfiServiceType *service_type); + +/** + * Pardon a player + */ +void game_runtime_pardon_player(struct FfiGameRuntime *runtime, const struct FfiPlayer *player); + +/** + * Close runtime + */ +void game_runtime_close(struct FfiGameRuntime *runtime); + +/** + * Lock game + */ +void game_runtime_lock(struct FfiGameRuntime *runtime); + +/** + * Unlock game + */ +void game_runtime_unlock(struct FfiGameRuntime *runtime); + +/** + * Get game lock status + */ +bool game_runtime_get_lock_status(struct FfiGameRuntime *runtime); + +/** + * Get button status of player + */ +struct FfiButtonStatus game_runtime_get_button_status(struct FfiGameRuntime *runtime, + const struct FfiPlayer *player, + uint8_t key); + +/** + * Get axis value of player + */ +struct FfiAxis game_runtime_get_axis(struct FfiGameRuntime *runtime, + const struct FfiPlayer *player, + uint8_t key); + +/** + * Get direction value of player + */ +struct FfiDirection game_runtime_get_direction(struct FfiGameRuntime *runtime, + const struct FfiPlayer *player, + uint8_t key); + +/** + * Get service type of player + */ +const enum FfiServiceType *game_runtime_get_service_type(struct FfiGameRuntime *runtime, + const struct FfiPlayer *player); + +/** + * Is player banned + */ +struct FfiBooleanResult game_runtime_is_player_banned(struct FfiGameRuntime *runtime, + const struct FfiPlayer *player); + +/** + * Is player online + */ +struct FfiBooleanResult game_runtime_is_player_online(struct FfiGameRuntime *runtime, + const struct FfiPlayer *player); + +/** + * Get online list + */ +struct FfiPlayerList game_runtime_get_online_list(struct FfiGameRuntime *runtime); + +/** + * Get banned list + */ +struct FfiPlayerList game_runtime_get_banned_list(struct FfiGameRuntime *runtime); + +/** + * Free control event + */ +void free_control_event(struct FfiControlEvent *event); + +/** + * Free player list + */ +void free_player_list(struct FfiPlayerList list); + +/** + * Free service type tag + */ +void free_ffi_service_type(enum FfiServiceType *ptr); #ifdef __cplusplus } // extern "C" diff --git a/core/bindings/lang/clang/headers/nogamepads_data_cpp.h b/core/bindings/lang/clang/headers/nogamepads_data_cpp.h deleted file mode 100644 index 2c128bb..0000000 --- a/core/bindings/lang/clang/headers/nogamepads_data_cpp.h +++ /dev/null @@ -1,245 +0,0 @@ -// Auto generated by cbindgen 0.29.0 - -#ifndef NOGAMEPADS_DATA_H -#define NOGAMEPADS_DATA_H - -#include <cstdarg> -#include <cstdint> -#include <cstdlib> -#include <ostream> -#include <new> - -enum class FfiConnectionMessageTag { - ConnectionJoin, - ConnectionRequestGameInfos, - ConnectionRequestLayoutConfigure, - ConnectionRequestSkinPackage, - ConnectionReady, - ConnectionError, -}; - -enum class FfiConnectionResponseMessageTag { - GameInfosResponse, - DenyResponse, - FailResponse, - OkResponse, - WelcomeResponse, - ErrorResponse, -}; - -enum class FfiControlMessageTag { - CtrlMsg, - CtrlPressed, - CtrlReleased, - CtrlAxis, - CtrlDir, - CtrlExit, - CtrlError, - CtrlEnd, -}; - -enum class FfiExitReason { - ExitReason, - GameOverReason, - ServerClosedReason, - YouAreKickedReason, - YouAreBannedReason, - ErrorReason, -}; - -enum class FfiGameMessageTag { - GameEventTrigger, - GameMsg, - GameLetExit, - GameError, - GameEnd, -}; - -enum class FfiJoinFailedMessage { - ContainIdenticalPlayer, - PlayerBanned, - GameLocked, - UnknownError, -}; - -template<typename T = void> -struct ManuallyDrop; - -struct FfiAccount { - char *id; - char *player_hash; -}; - -struct FfiCustomize { - char *nickname; - int color_hue; - double color_saturation; - double color_value; -}; - -struct FfiPlayer { - FfiAccount account; - FfiCustomize *customize; -}; - -struct FfiKeyAndAxis { - uint8_t key; - double axis; -}; - -struct FfiKeyAndDirection { - uint8_t key; - double x; - double y; -}; - -union FfiControlMessageUnion { - char *message; - uint8_t key; - ManuallyDrop<FfiKeyAndAxis> key_and_axis; - ManuallyDrop<FfiKeyAndDirection> key_and_direction; -}; - -struct FfiControlMessage { - FfiControlMessageTag tag; - FfiControlMessageUnion data; -}; - -union FfiGameMessageUnion { - uint8_t key; - char *message; - ManuallyDrop<FfiExitReason> exit_reason; -}; - -struct FfiGameMessage { - FfiGameMessageTag tag; - FfiGameMessageUnion data; -}; - -union FfiConnectionMessageUnion { - ManuallyDrop<FfiPlayer> player; -}; - -struct FfiConnectionMessage { - FfiConnectionMessageTag tag; - FfiConnectionMessageUnion data; -}; - -struct KeyValuePair { - char *key; - char *value; -}; - -struct FfiGameInfo { - KeyValuePair *data; - uintptr_t len; - uintptr_t cap; -}; - -union FfiConnectionResponseMessageUnion { - ManuallyDrop<FfiGameInfo> game_info; - ManuallyDrop<FfiJoinFailedMessage> failed_message; -}; - -struct FfiConnectionResponseMessage { - FfiConnectionResponseMessageTag tag; - FfiConnectionResponseMessageUnion data; -}; - -struct FfiControllerData { - void *_0; -}; - -struct FfiControllerRuntime { - void *inner; - void (*drop_fn)(void*); -}; - -extern "C" { - -void free_c_string(char *ptr); - -/// Register a player -FfiPlayer *player_register(const char *id, const char *password); - -/// Check if the player's password is correct -bool player_check(const FfiPlayer *player, const char *password); - -/// Set the player's nickname -void player_set_nickname(FfiPlayer *player, const char *nickname); - -/// Set the player's hue -void player_set_hue(FfiPlayer *player, int hue); - -/// Set the player's HSV color -void player_set_hsv(FfiPlayer *player, int hue, double saturation, double value); - -/// Free the player -void free_player(FfiPlayer *player); - -/// Free ControlMessage -void free_control_message(FfiControlMessage msg); - -/// Free GameMessage -void free_game_message(FfiGameMessage msg); - -/// Free ExitReason -void free_exit_reason(FfiExitReason msg); - -/// Free ConnectionMessage -void free_connection_message(FfiConnectionMessage msg); - -/// Free ConnectionResponseMessage -void free_connection_response_message(FfiConnectionResponseMessage msg); - -/// Free JoinFailedMessage -void free_join_failed_message(FfiJoinFailedMessage msg); - -void free_game_info(FfiGameInfo map); - -/// Create controller data -FfiControllerData *controller_data_new(); - -/// Bind player to controller -void controller_data_bind_player(FfiControllerData *controller, FfiPlayer *ffi_player); - -/// Build runtime -FfiControllerRuntime *controller_data_build_runtime(FfiControllerData *controller); - -/// Free ControllerData memory -void controller_data_free(FfiControllerData *controller); - -/// Close runtime and exit game -void controller_runtime_close(FfiControllerRuntime *runtime); - -/// Send control message -void controller_runtime_send_message(FfiControllerRuntime *runtime, - FfiControlMessage *control_message); - -/// Send text message -void controller_runtime_send_text_message(FfiControllerRuntime *runtime, const char *message_ptr); - -/// Press a button -void controller_runtime_press_a_button(FfiControllerRuntime *runtime, uint8_t key); - -/// Release a button -void controller_runtime_release_a_button(FfiControllerRuntime *runtime, uint8_t key); - -/// Change axis value -void controller_runtime_change_axis(FfiControllerRuntime *runtime, uint8_t key, double axis); - -/// Change direction value -void controller_runtime_change_direction(FfiControllerRuntime *runtime, - uint8_t key, - double x, - double y); - -/// Pop a message from the queue -FfiGameMessage *controller_runtime_pop(FfiControllerRuntime *runtime); - -/// Free runtime memory -void controller_runtime_free(FfiControllerRuntime *runtime); - -} // extern "C" - -#endif // NOGAMEPADS_DATA_H 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 diff --git a/core/src/data/game/game_cli.rs b/core/src/data/game/game_cli.rs index 521de3f..fd71556 100644 --- a/core/src/data/game/game_cli.rs +++ b/core/src/data/game/game_cli.rs @@ -172,7 +172,7 @@ pub fn process_game_cli(runtime: Arc<Mutex<GameRuntime>>, cmd: GameCli) -> bool Commands::Pop => { entry_mutex!(runtime, |guard| { - if let Some((account, message)) = guard.pop_event() { + if let Some((account, message)) = guard.pop_control_event() { info!("{}: {:?}", account.id, message); } else { info!("None") @@ -182,7 +182,7 @@ pub fn process_game_cli(runtime: Arc<Mutex<GameRuntime>>, cmd: GameCli) -> bool Commands::PopAll => { entry_mutex!(runtime, |guard| { - while let Some((account, message)) = guard.pop_event() { + while let Some((account, message)) = guard.pop_control_event() { info!("{}: {:?}", account.id, message); } }); diff --git a/core/src/data/game/game_data.rs b/core/src/data/game/game_data.rs index 3bdf28b..35a5c0e 100644 --- a/core/src/data/game/game_data.rs +++ b/core/src/data/game/game_data.rs @@ -71,8 +71,8 @@ impl GameData { } /// Read game runtime archive data - pub fn load_data(&mut self, storage: GameRuntimeDataArchive) -> &mut GameData { - self.archive = storage; + pub fn load_data(&mut self, archive: GameRuntimeDataArchive) -> &mut GameData { + self.archive = archive; self } diff --git a/core/src/data/game/game_runtime.rs b/core/src/data/game/game_runtime.rs index 1c5a548..7ce1991 100644 --- a/core/src/data/game/game_runtime.rs +++ b/core/src/data/game/game_runtime.rs @@ -154,7 +154,7 @@ impl GameRuntime { } /// Pop an event message - pub fn pop_event(&mut self) -> Option<(Account, ControlMessage)> { + pub fn pop_control_event(&mut self) -> Option<(Account, ControlMessage)> { let pop = self.control.events.pop_front(); if pop.is_some() { let (account, msg) = pop.unwrap(); diff --git a/core/src/data/player/player_data.rs b/core/src/data/player/player_data.rs index 1fe5ff0..9b1ab71 100644 --- a/core/src/data/player/player_data.rs +++ b/core/src/data/player/player_data.rs @@ -65,6 +65,17 @@ impl Player { player } + pub fn register_from_hash(hash: String) -> Player { + let mut player = Player { + customize: None, + account: Account::default() + }; + + player.account.id = "$only_hash$".to_string(); + player.account.player_hash = hash; + player + } + pub fn check(&self, password: String) -> bool { let hash = Self::gen_hash(self.account.id.clone(), password); hash == self.account.player_hash |
