diff options
| author | 1992414357@qq.com <1992414357@qq.com> | 2025-06-18 02:52:12 +0800 |
|---|---|---|
| committer | 1992414357@qq.com <1992414357@qq.com> | 2025-06-18 02:52:12 +0800 |
| commit | 768e2d50fdbf8a2de8b57e7363cf26d95dbdc015 (patch) | |
| tree | ea4c3f8f5d2683765642dd53c133b859bd280ac3 /core | |
| parent | 37f6816105f165610eca06432b798f99f9d4325a (diff) | |
Finished CBindings
Diffstat (limited to 'core')
| -rw-r--r-- | core/bindings/lang/clang/Cargo.toml | 1 | ||||
| -rw-r--r-- | core/bindings/lang/clang/binding_example/.idea/misc.xml | 1 | ||||
| -rw-r--r-- | core/bindings/lang/clang/binding_example/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | core/bindings/lang/clang/binding_example/tcp_client.c | 68 | ||||
| -rw-r--r-- | core/bindings/lang/clang/binding_example/tcp_server.c | 64 | ||||
| -rw-r--r-- | core/bindings/lang/clang/configures/nogamepads_utils.toml | 10 | ||||
| -rw-r--r-- | core/bindings/lang/clang/headers/nogamepads_data.h | 40 | ||||
| -rw-r--r-- | core/bindings/lang/clang/headers/nogamepads_utils.h | 671 | ||||
| -rw-r--r-- | core/bindings/lang/clang/src/data/ngpd_controller.rs | 121 | ||||
| -rw-r--r-- | core/bindings/lang/clang/src/data/ngpd_game.rs | 355 | ||||
| -rw-r--r-- | core/bindings/lang/clang/src/lib.rs | 1 | ||||
| -rw-r--r-- | core/bindings/lang/clang/src/logger_utils.rs | 13 | ||||
| -rw-r--r-- | core/bindings/lang/clang/src/service/ngpd_service_types.rs | 4 | ||||
| -rw-r--r-- | core/bindings/lang/clang/src/service/ngpd_tcp_service.rs | 68 | ||||
| -rw-r--r-- | core/src/data/controller/controller_data.rs | 11 | ||||
| -rw-r--r-- | core/src/data/game/game_data.rs | 6 |
16 files changed, 1177 insertions, 263 deletions
diff --git a/core/bindings/lang/clang/Cargo.toml b/core/bindings/lang/clang/Cargo.toml index 7eae084..a0c8283 100644 --- a/core/bindings/lang/clang/Cargo.toml +++ b/core/bindings/lang/clang/Cargo.toml @@ -8,6 +8,7 @@ build = "build.rs" [dependencies] nogamepads = { path = "./../../../../../NoGamepads" } nogamepads-core = { path = "./../../../../core" } +log = "0.4.27" [build-dependencies] cbindgen = "0.29.0" diff --git a/core/bindings/lang/clang/binding_example/.idea/misc.xml b/core/bindings/lang/clang/binding_example/.idea/misc.xml index 0b76fe5..e479d63 100644 --- a/core/bindings/lang/clang/binding_example/.idea/misc.xml +++ b/core/bindings/lang/clang/binding_example/.idea/misc.xml @@ -4,4 +4,5 @@ <option name="pythonIntegrationState" value="YES" /> </component> <component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" /> + <component name="WestSettings"><![CDATA[{}]]></component> </project>
\ No newline at end of file diff --git a/core/bindings/lang/clang/binding_example/CMakeLists.txt b/core/bindings/lang/clang/binding_example/CMakeLists.txt index 29b5fda..02185bf 100644 --- a/core/bindings/lang/clang/binding_example/CMakeLists.txt +++ b/core/bindings/lang/clang/binding_example/CMakeLists.txt @@ -3,12 +3,18 @@ project(binding_example C) set(CMAKE_C_STANDARD 99) +# Executables + add_executable(example_server_listening tcp_server.c) add_executable(example_connect_server tcp_client.c) +# Includes + include_directories(${PROJECT_SOURCE_DIR}/include) link_directories(${PROJECT_SOURCE_DIR}/libs) +# Libraries + target_link_libraries(example_server_listening ${PROJECT_SOURCE_DIR}/libs/nogamepads_c.dll.lib ) diff --git a/core/bindings/lang/clang/binding_example/tcp_client.c b/core/bindings/lang/clang/binding_example/tcp_client.c index ba219a9..7caa647 100644 --- a/core/bindings/lang/clang/binding_example/tcp_client.c +++ b/core/bindings/lang/clang/binding_example/tcp_client.c @@ -1,35 +1,67 @@ -#include <stdio.h> #include "include/nogamepads_data.h" +#include <stdio.h> +#include <stdlib.h> + +#define USERNAME "juliet" +#define PASSWORD "12345678" +#define DISPLAY_NAME "IM JULIET" +#define SERVER_IP {127, 0, 0, 1} +#define SERVER_PORT 5989 int main(void) { - printf("//////////////////////////////////////// \n"); - printf("///// NoGamepads C Binding ///////////// \n"); - printf("///// Example: Connect to a server ///// \n"); - printf("//////////////////////////////////////// \n"); - printf("\n"); + // Create player + FfiPlayer *player = player_register(USERNAME, PASSWORD); + if (!player) { + fprintf(stderr, "Failed to register player\n"); + return EXIT_FAILURE; + } - FfiPlayer *player = player_register("juliet", "12345678"); + // Configure player attributes player_set_hsv(player, 120, 0.5, 0.9); - player_set_nickname(player, "IM JULIET"); - printf("Player created. \n"); + player_set_nickname(player, DISPLAY_NAME); + // Initialize controller FfiControllerData *controller = controller_data_new(); - controller_data_bind_player(controller, player); - printf("Controller data created. \n"); + if (!controller) { + fprintf(stderr, "Failed to create controller\n"); + free_player(player); + return EXIT_FAILURE; + } else { + controller_data_bind_player(controller, player); + } + // Create runtime FfiControllerRuntime *rt = controller_data_build_runtime(controller); - printf("Runtime created. \n"); + if (!rt) { + fprintf(stderr, "Failed to create runtime\n"); + free_player(player); + free_controller_data(controller); + return EXIT_FAILURE; + } + // Create TcpNetwork client FfiTcpClientService *client = tcp_client_build(rt); - printf("Tcp client built. \n"); + if (!client) { + fprintf(stderr, "Failed to create client\n"); + free_controller_runtime(rt); + free_controller_data(controller); + free_player(player); + return EXIT_FAILURE; + } else { + uint8_t ip[4] = SERVER_IP; + tcp_client_bind_address_v4(client, ip[0], ip[1], ip[2], ip[3], SERVER_PORT); + } - tcp_client_bind_address_v4(client, 127, 0, 0, 1, 5989); - printf("Address bind. \n"); + enable_logger(0); - printf("Connecting \n"); + // Connect to server and block tcp_client_connect(client); - printf("Disconnected \n"); + + // Release memory + free_controller_runtime(rt); + free_controller_data(controller); + free_player(player); return 0; -} +}
\ No newline at end of file diff --git a/core/bindings/lang/clang/binding_example/tcp_server.c b/core/bindings/lang/clang/binding_example/tcp_server.c index b0ff629..dd02a4a 100644 --- a/core/bindings/lang/clang/binding_example/tcp_server.c +++ b/core/bindings/lang/clang/binding_example/tcp_server.c @@ -1,43 +1,57 @@ -#include <stdio.h> -#include <pthread.h> #include "include/nogamepads_data.h" +#include <stdio.h> +#include <stdlib.h> -void* server_thread(void* arg) { - FfiTcpServerService *server = arg; - tcp_server_listening_block_on(server); - - printf("Server stopped. \n"); - return NULL; -} +#define GAME_NAME "My Hero" +#define GAME_VERSION "0.1.0" +#define SERVER_IP {127, 0, 0, 1} +#define SERVER_PORT 5989 int main(void) { - printf("//////////////////////////////////// \n"); - printf("///// NoGamepads C Binding ///////// \n"); - printf("///// Example: Start a server. ///// \n"); - printf("//////////////////////////////////// \n"); - printf("\n"); - + // Game data initialization FfiGameData *data = game_data_new(); - printf("Data created. \n"); + if (!data) { + fprintf(stderr, "Failed to create game data\n"); + return EXIT_FAILURE; + } + + // Configure game information + game_data_set_name_info(data, GAME_NAME); + game_data_set_version_info(data, GAME_VERSION); + // Create runtime FfiGameRuntime *rt = game_data_build_runtime(data); - printf("Runtime created. \n"); + if (!rt) { + fprintf(stderr, "Failed to create runtime\n"); + free_game_data(data); + return EXIT_FAILURE; + } + // Start the server FfiTcpServerService *server = tcp_server_build(rt); - printf("Tcp services created. \n"); + if (!server) { + fprintf(stderr, "Failed to create server\n"); + free_game_runtime(rt); + free_game_data(data); + return EXIT_FAILURE; + } - tcp_server_bind_address_v4(server, 127, 0, 0, 1, 5989); - printf("Address bind. \n"); + // Bind address + uint8_t ip[4] = SERVER_IP; + tcp_server_bind_address_v4(server, ip[0], ip[1], ip[2], ip[3], SERVER_PORT); - pthread_t thread; - pthread_create(&thread, NULL, server_thread, server); + printf("Server started at %d.%d.%d.%d:%d\n", ip[0], ip[1], ip[2], ip[3], SERVER_PORT); - printf("Server started. Press Enter to stop...\n"); + enable_logger(2); - getchar(); + // Start server listening + tcp_server_listening_block_on(server); - printf("Process stopped. \n"); + printf("Server closed\n"); + // Release memory + free_game_runtime(rt); + free_game_data(data); return 0; }
\ No newline at end of file diff --git a/core/bindings/lang/clang/configures/nogamepads_utils.toml b/core/bindings/lang/clang/configures/nogamepads_utils.toml new file mode 100644 index 0000000..4d1c271 --- /dev/null +++ b/core/bindings/lang/clang/configures/nogamepads_utils.toml @@ -0,0 +1,10 @@ +language = "C" +include_guard = "NOGAMEPADS_UTILS_H" +header = "// Auto generated by cbindgen 0.29.0" +cpp_compat = true + +[parse] +parse_deps = true +include = [ + "logger_utils" +]
\ 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 91a07d9..d0fc002 100644 --- a/core/bindings/lang/clang/headers/nogamepads_data.h +++ b/core/bindings/lang/clang/headers/nogamepads_data.h @@ -62,6 +62,7 @@ typedef enum FfiJoinFailedMessage { } FfiJoinFailedMessage; typedef enum FfiServiceType { + Unknown, TCPConnection, BlueTooth, USB, @@ -308,7 +309,7 @@ struct FfiControllerRuntime *controller_data_build_runtime(struct FfiControllerD /** * Free ControllerData memory */ -void controller_data_free(struct FfiControllerData *controller); +void free_controller_data(struct FfiControllerData *controller); /** * Close runtime and exit game @@ -366,6 +367,23 @@ void free_controller_runtime(struct FfiControllerRuntime *runtime); struct FfiGameData *game_data_new(void); /** + * Add info + */ +struct FfiGameData *game_data_add_info(struct FfiGameData *data, + const char *key, + const char *value); + +/** + * Set name info + */ +struct FfiGameData *game_data_set_name_info(struct FfiGameData *data, const char *name); + +/** + * Set version info + */ +struct FfiGameData *game_data_set_version_info(struct FfiGameData *data, const char *version); + +/** * Load data archive */ struct FfiGameData *game_data_load_archive(struct FfiGameData *data, @@ -403,14 +421,14 @@ void free_game_archive_data(struct FfiGameRuntimeArchive *data); void game_runtime_send_message_to(struct FfiGameRuntime *runtime, const struct FfiPlayer *player, struct FfiGameMessage *message, - enum FfiServiceType *service_type); + 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, + enum FfiServiceType service_type, const char *text); /** @@ -418,7 +436,7 @@ void game_runtime_send_text_message(struct FfiGameRuntime *runtime, */ void game_runtime_send_event(struct FfiGameRuntime *runtime, const struct FfiPlayer *player, - enum FfiServiceType *service_type, + enum FfiServiceType service_type, uint8_t key); /** @@ -431,22 +449,22 @@ struct FfiControlEvent *game_runtime_pop_control_event(struct FfiGameRuntime *ru */ void game_runtime_let_exit(struct FfiGameRuntime *runtime, const struct FfiPlayer *player, - enum FfiServiceType *service_type, - enum FfiExitReason *reason); + 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); + 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); + enum FfiServiceType service_type); /** * Pardon a player @@ -497,8 +515,8 @@ struct FfiDirection game_runtime_get_direction(struct FfiGameRuntime *runtime, /** * Get service type of player */ -const enum FfiServiceType *game_runtime_get_service_type(struct FfiGameRuntime *runtime, - const struct FfiPlayer *player); +enum FfiServiceType game_runtime_get_service_type(struct FfiGameRuntime *runtime, + const struct FfiPlayer *player); /** * Is player banned @@ -644,6 +662,8 @@ void tcp_server_listening_block_on(struct FfiTcpServerService *service); */ void free_tcp_server(struct FfiTcpServerService *service); +void enable_logger(uint8_t level); + #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/core/bindings/lang/clang/headers/nogamepads_utils.h b/core/bindings/lang/clang/headers/nogamepads_utils.h new file mode 100644 index 0000000..df8628e --- /dev/null +++ b/core/bindings/lang/clang/headers/nogamepads_utils.h @@ -0,0 +1,671 @@ +// Auto generated by cbindgen 0.29.0 + +#ifndef NOGAMEPADS_UTILS_H +#define NOGAMEPADS_UTILS_H + +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> + +typedef enum FfiConnectionMessageTag { + ConnectionJoin, + ConnectionRequestGameInfos, + ConnectionRequestLayoutConfigure, + ConnectionRequestSkinPackage, + ConnectionReady, + ConnectionError, +} FfiConnectionMessageTag; + +typedef enum FfiConnectionResponseMessageTag { + GameInfosResponse, + DenyResponse, + FailResponse, + OkResponse, + WelcomeResponse, + ErrorResponse, +} FfiConnectionResponseMessageTag; + +typedef enum FfiControlMessageTag { + CtrlMsg, + CtrlPressed, + CtrlReleased, + CtrlAxis, + CtrlDir, + CtrlExit, + CtrlError, + CtrlEnd, +} FfiControlMessageTag; + +typedef enum FfiExitReason { + ExitReason, + GameOverReason, + ServerClosedReason, + YouAreKickedReason, + YouAreBannedReason, + ErrorReason, +} FfiExitReason; + +typedef enum FfiGameMessageTag { + GameEventTrigger, + GameMsg, + GameLetExit, + GameError, + GameEnd, +} FfiGameMessageTag; + +typedef enum FfiJoinFailedMessage { + ContainIdenticalPlayer, + PlayerBanned, + GameLocked, + UnknownError, +} FfiJoinFailedMessage; + +typedef enum FfiServiceType { + Unknown, + TCPConnection, + BlueTooth, + USB, +} FfiServiceType; + +typedef struct FfiAccount { + char *id; + char *player_hash; +} FfiAccount; + +typedef struct FfiCustomize { + char *nickname; + int color_hue; + double color_saturation; + double color_value; +} FfiCustomize; + +typedef struct FfiPlayer { + struct FfiAccount account; + struct FfiCustomize *customize; +} FfiPlayer; + +typedef struct FfiKeyAndAxis { + uint8_t key; + double axis; +} FfiKeyAndAxis; + +typedef struct FfiKeyAndDirection { + uint8_t key; + double x; + double y; +} FfiKeyAndDirection; + +typedef union FfiControlMessageUnion { + char *message; + uint8_t key; + struct FfiKeyAndAxis key_and_axis; + struct FfiKeyAndDirection key_and_direction; +} FfiControlMessageUnion; + +typedef struct FfiControlMessage { + enum FfiControlMessageTag tag; + union FfiControlMessageUnion data; +} FfiControlMessage; + +typedef union FfiGameMessageUnion { + uint8_t key; + char *message; + enum FfiExitReason exit_reason; +} FfiGameMessageUnion; + +typedef struct FfiGameMessage { + enum FfiGameMessageTag tag; + union FfiGameMessageUnion data; +} FfiGameMessage; + +typedef union FfiConnectionMessageUnion { + struct FfiPlayer player; +} FfiConnectionMessageUnion; + +typedef struct FfiConnectionMessage { + enum FfiConnectionMessageTag tag; + union FfiConnectionMessageUnion data; +} FfiConnectionMessage; + +typedef struct KeyValuePair { + char *key; + char *value; +} KeyValuePair; + +typedef struct FfiGameInfo { + struct KeyValuePair *data; + uintptr_t len; + uintptr_t cap; +} FfiGameInfo; + +typedef union FfiConnectionResponseMessageUnion { + struct FfiGameInfo game_info; + enum FfiJoinFailedMessage failed_message; +} FfiConnectionResponseMessageUnion; + +typedef struct FfiConnectionResponseMessage { + enum FfiConnectionResponseMessageTag tag; + union FfiConnectionResponseMessageUnion data; +} FfiConnectionResponseMessage; + +typedef struct FfiControllerData { + void *_0; +} FfiControllerData; + +typedef struct FfiControllerRuntime { + void *inner; + 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; + +typedef struct FfiTcpClientService { + void *_0; +} FfiTcpClientService; + +typedef struct FfiTcpServerService { + void *_0; +} FfiTcpServerService; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void free_c_string(char *ptr); + +/** + * Register a player + */ +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); + +/** + * Set the player's nickname + */ +void player_set_nickname(struct FfiPlayer *player, const char *nickname); + +/** + * Set the player's hue + */ +void player_set_hue(struct FfiPlayer *player, int hue); + +/** + * Set the player's HSV color + */ +void player_set_hsv(struct FfiPlayer *player, int hue, double saturation, double value); + +/** + * Free the player + */ +void free_player(struct FfiPlayer *player); + +/** + * Free ControlMessage + */ +void free_control_message(struct FfiControlMessage *msg); + +/** + * Free GameMessage + */ +void free_game_message(struct FfiGameMessage *msg); + +/** + * Free ExitReason + */ +void free_exit_reason(enum FfiExitReason *msg); + +/** + * Free ConnectionMessage + */ +void free_connection_message(struct FfiConnectionMessage *msg); + +/** + * Free ConnectionResponseMessage + */ +void free_connection_response_message(struct FfiConnectionResponseMessage *msg); + +/** + * Free JoinFailedMessage + */ +void free_join_failed_message(enum FfiJoinFailedMessage *msg); + +void free_game_info(struct FfiGameInfo map); + +/** + * Create controller data + */ +struct FfiControllerData *controller_data_new(void); + +/** + * Bind player to controller + */ +void controller_data_bind_player(struct FfiControllerData *controller, + struct FfiPlayer *ffi_player); + +/** + * Build runtime + */ +struct FfiControllerRuntime *controller_data_build_runtime(struct FfiControllerData *controller); + +/** + * Free ControllerData memory + */ +void free_controller_data(struct FfiControllerData *controller); + +/** + * Close runtime and exit game + */ +void controller_runtime_close(struct FfiControllerRuntime *runtime); + +/** + * Send control message + */ +void controller_runtime_send_message(struct FfiControllerRuntime *runtime, + struct FfiControlMessage *control_message); + +/** + * Send text message + */ +void controller_runtime_send_text_message(struct FfiControllerRuntime *runtime, + const char *message_ptr); + +/** + * Press a button + */ +void controller_runtime_press_a_button(struct FfiControllerRuntime *runtime, uint8_t key); + +/** + * Release a button + */ +void controller_runtime_release_a_button(struct FfiControllerRuntime *runtime, uint8_t key); + +/** + * Change axis value + */ +void controller_runtime_change_axis(struct FfiControllerRuntime *runtime, uint8_t key, double axis); + +/** + * Change direction value + */ +void controller_runtime_change_direction(struct FfiControllerRuntime *runtime, + uint8_t key, + double x, + double y); + +/** + * Pop a message from the queue + */ +struct FfiGameMessage *controller_runtime_pop(struct FfiControllerRuntime *runtime); + +/** + * Free runtime memory + */ +void free_controller_runtime(struct FfiControllerRuntime *runtime); + +/** + * Create game data + */ +struct FfiGameData *game_data_new(void); + +/** + * Add info + */ +struct FfiGameData *game_data_add_info(struct FfiGameData *data, + const char *key, + const char *value); + +/** + * Set name info + */ +struct FfiGameData *game_data_set_name_info(struct FfiGameData *data, const char *name); + +/** + * Set version info + */ +struct FfiGameData *game_data_set_version_info(struct FfiGameData *data, const char *version); + +/** + * 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 + */ +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 game runtime + */ +void free_game_runtime(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); + +/** + * Build tcp client + */ +struct FfiTcpClientService *tcp_client_build(struct FfiControllerRuntime *runtime); + +/** + * Bind ipv4 address + */ +void tcp_client_bind_ipv4(struct FfiTcpClientService *service, + uint8_t a0, + uint8_t a1, + uint8_t a2, + uint8_t a3); + +/** + * Bind ipv6 address + */ +bool tcp_client_bind_ipv6(struct FfiTcpClientService *service, const char *ip_str); + +/** + * Bind port + */ +void tcp_client_bind_port(struct FfiTcpClientService *service, uint16_t port); + +/** + * Bind address with ipv4 + */ +void tcp_client_bind_address_v4(struct FfiTcpClientService *service, + uint8_t a0, + uint8_t a1, + uint8_t a2, + uint8_t a3, + uint16_t port); + +/** + * Bind address with ipv6 + */ +bool tcp_client_bind_address_v6(struct FfiTcpClientService *service, + const char *ip_str, + uint16_t port); + +/** + * Connect + */ +void tcp_client_connect(struct FfiTcpClientService *service); + +/** + * Free tcp client + */ +void free_tcp_client(struct FfiTcpClientService *service); + +/** + * Build tcp server + */ +struct FfiTcpServerService *tcp_server_build(struct FfiGameRuntime *runtime); + +/** + * Bind ipv4 address + */ +void tcp_server_bind_ipv4(struct FfiTcpServerService *service, + uint8_t a0, + uint8_t a1, + uint8_t a2, + uint8_t a3); + +/** + * Bind ipv6 address + */ +bool tcp_server_bind_ipv6(struct FfiTcpServerService *service, const char *ip_str); + +/** + * Bind port + */ +void tcp_server_bind_port(struct FfiTcpServerService *service, uint16_t port); + +/** + * Bind address with ipv4 + */ +void tcp_server_bind_address_v4(struct FfiTcpServerService *service, + uint8_t a0, + uint8_t a1, + uint8_t a2, + uint8_t a3, + uint16_t port); + +/** + * Bind address with ipv6 + */ +bool tcp_server_bind_address_v6(struct FfiTcpServerService *service, + const char *ip_str, + uint16_t port); + +/** + * Start listening + */ +void tcp_server_listening_block_on(struct FfiTcpServerService *service); + +/** + * Free tcp server + */ +void free_tcp_server(struct FfiTcpServerService *service); + +void enable_logger(uint8_t level); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif /* NOGAMEPADS_UTILS_H */ diff --git a/core/bindings/lang/clang/src/data/ngpd_controller.rs b/core/bindings/lang/clang/src/data/ngpd_controller.rs index d7f7b96..3c710fb 100644 --- a/core/bindings/lang/clang/src/data/ngpd_controller.rs +++ b/core/bindings/lang/clang/src/data/ngpd_controller.rs @@ -6,7 +6,8 @@ use nogamepads_core::data::controller::controller_runtime::ControllerRuntime; use nogamepads_core::data::message::message_enums::ControlMessage; use nogamepads_core::data::player::player_data::Player; use std::ffi::{c_char, c_double, c_void, CStr}; -use std::sync::{Arc, Mutex}; +use std::ptr::null_mut; +use std::sync::{Arc, Mutex, MutexGuard}; #[repr(C)] pub struct FfiControllerData(*mut c_void); @@ -29,13 +30,11 @@ impl FfiControllerData { /// Bind player to controller #[unsafe(no_mangle)] - #[allow(unsafe_op_in_unsafe_fn)] pub extern "C" fn controller_data_bind_player( controller: *mut FfiControllerData, ffi_player: *mut FfiPlayer ) { - assert!(!controller.is_null(), "ControllerData pointer is null"); - assert!(!ffi_player.is_null(), "FfiPlayer pointer is null"); + if controller.is_null() || ffi_player.is_null() { return; } let ffi_player_ref = unsafe { &*ffi_player }; @@ -52,39 +51,32 @@ impl FfiControllerData { /// Build runtime #[unsafe(no_mangle)] - #[allow(unsafe_op_in_unsafe_fn)] pub extern "C" fn controller_data_build_runtime( controller: *mut FfiControllerData ) -> *mut FfiControllerRuntime { - assert!(!controller.is_null(), "ControllerData pointer is null"); + let controller_inner = unsafe { &mut *((*controller).0 as *mut ControllerData) }; + let arc = controller_inner.runtime_with_borrowed_data(); + let ptr = Arc::into_raw(arc) as *mut c_void; - // Take ownership - let controller_box = unsafe { Box::from_raw(controller) }; - let raw_data = controller_box.0; + let ffi_runtime = Box::new(FfiControllerRuntime { + inner: ptr, + drop_fn: Self::drop_controller_runtime, + }); - // Convert ControllerData - let controller_data: Box<ControllerData> = unsafe { Box::from_raw(raw_data as *mut ControllerData) }; + Box::into_raw(ffi_runtime) + } - // Define custom drop function - extern "C" fn drop_runtime(raw: *mut c_void) { + extern "C" fn drop_controller_runtime(ptr: *mut c_void) { + if !ptr.is_null() { unsafe { - let arc_ptr = raw as *const Arc<Mutex<ControllerRuntime>>; - drop(Arc::from_raw(arc_ptr)); + let _ = Arc::<Mutex<ControllerRuntime>>::from_raw(ptr as *mut _); } } - - // Convert to an FFI-safe structure - let arc_raw = Arc::into_raw(controller_data.runtime()) as *mut c_void; - - Box::into_raw(Box::new(FfiControllerRuntime { - inner: arc_raw, - drop_fn: drop_runtime, - })) } /// Free ControllerData memory #[unsafe(no_mangle)] - pub extern "C" fn controller_data_free(controller: *mut FfiControllerData) { + pub extern "C" fn free_controller_data(controller: *mut FfiControllerData) { if controller.is_null() { return; } @@ -103,6 +95,43 @@ impl FfiControllerData { // ControllerRuntime implementation impl FfiControllerRuntime { + fn operate_controller_runtime( + runtime: *mut FfiControllerRuntime, + callback: fn(guard: &mut MutexGuard<ControllerRuntime>) + ) { + unsafe { + let ffi_runtime = &*runtime; + Arc::increment_strong_count(ffi_runtime.inner); + let arc = Arc::<Mutex<ControllerRuntime>>::from_raw(ffi_runtime.inner as *mut _); + let arc_clone = Arc::clone(&arc); + let _ = Arc::into_raw(arc); + entry_mutex!(arc_clone, |guard| { + callback(guard); + }); + Arc::decrement_strong_count(ffi_runtime.inner); + } + } + + fn operate_controller_runtime_with_return<Input, Result>( + runtime: *mut FfiControllerRuntime, + input: Input, + callback: fn(guard: &mut MutexGuard<ControllerRuntime>, input: Input) -> Option<Result> + ) -> Option<Result> { + unsafe { + let ffi_runtime = &*runtime; + Arc::increment_strong_count(ffi_runtime.inner); + let arc = Arc::<Mutex<ControllerRuntime>>::from_raw(ffi_runtime.inner as *mut _); + let arc_clone = Arc::clone(&arc); + let _ = Arc::into_raw(arc); + let mut result = None; + entry_mutex!(arc_clone, |guard| { + result = callback(guard, input); + }); + Arc::decrement_strong_count(ffi_runtime.inner); + result + } + } + /// Close runtime and exit game #[unsafe(no_mangle)] pub extern "C" fn controller_runtime_close( @@ -112,15 +141,9 @@ impl FfiControllerRuntime { return; } - let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<ControllerRuntime>> }; - let arc_ref = unsafe { Arc::from_raw(arc_ptr) }; - - entry_mutex!(arc_ref, |mutex_guard| { - mutex_guard.close(); + Self::operate_controller_runtime(runtime, |guard| { + guard.close(); }); - - // Reconstruct Arc - let _ = Arc::into_raw(arc_ref); } /// Send control message @@ -133,19 +156,12 @@ impl FfiControllerRuntime { return; } - let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<ControllerRuntime>> }; - let arc_ref = unsafe { Arc::from_raw(arc_ptr) }; + let msg = unsafe { ControlMessage::from(control_message.read()) }; - let msg = unsafe { - let boxed_msg = Box::from_raw(control_message); - ControlMessage::from(*boxed_msg) - }; - - entry_mutex!(arc_ref, |mutex_guard| { - mutex_guard.send_message(msg); + Self::operate_controller_runtime_with_return(runtime, msg, |guard, input| { + guard.send_message(input); + Some(()) }); - - let _ = Arc::into_raw(arc_ref); } /// Send text message @@ -257,20 +273,19 @@ impl FfiControllerRuntime { runtime: *mut FfiControllerRuntime ) -> *mut FfiGameMessage { if runtime.is_null() { - return std::ptr::null_mut(); + return null_mut(); } let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<ControllerRuntime>> }; - let arc_ref = unsafe { Arc::from_raw(arc_ptr) }; + let arc_ref = unsafe { Arc::from_raw(arc_ptr).clone() }; let result = { - let mut pop_result = None; - - entry_mutex!(arc_ref, |mutex_guard| { - pop_result = mutex_guard.pop(); - }); - - pop_result + Self::operate_controller_runtime_with_return(runtime, (), |guard, _| { + match guard.pop() { + None => { None } + Some(msg) => { Some(msg) } + } + }) }; // Reconstruct Arc @@ -281,7 +296,7 @@ impl FfiControllerRuntime { let ffi_msg = Box::new(FfiGameMessage::from(msg)); Box::into_raw(ffi_msg) } else { - std::ptr::null_mut() + null_mut() } } diff --git a/core/bindings/lang/clang/src/data/ngpd_game.rs b/core/bindings/lang/clang/src/data/ngpd_game.rs index 829c5ed..2892ecc 100644 --- a/core/bindings/lang/clang/src/data/ngpd_game.rs +++ b/core/bindings/lang/clang/src/data/ngpd_game.rs @@ -8,7 +8,6 @@ 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)] @@ -72,6 +71,68 @@ impl FfiGameData { raw } + /// Add info + #[unsafe(no_mangle)] + pub extern "C" fn game_data_add_info( + data: *mut FfiGameData, + key: *const c_char, + value: *const c_char, + ) -> *mut FfiGameData { + + if data.is_null() || key.is_null() || value.is_null() { + return std::ptr::null_mut(); + } + + let key_str = unsafe { CStr::from_ptr(key) }.to_string_lossy().into_owned(); + let value_str = unsafe { CStr::from_ptr(value) }.to_string_lossy().into_owned(); + + let data_inner = unsafe { &mut *((*data).0 as *mut GameData) }; + data_inner.info(key_str, value_str); + + let raw = Box::into_raw(Box::new(FfiGameData(Box::into_raw(Box::new(data)) as *mut _))); + raw + } + + /// Set name info + #[unsafe(no_mangle)] + pub extern "C" fn game_data_set_name_info( + data: *mut FfiGameData, + name: *const c_char, + ) -> *mut FfiGameData { + + if data.is_null() || name.is_null() { + return std::ptr::null_mut(); + } + + let name_str = unsafe { CStr::from_ptr(name) }.to_string_lossy().into_owned(); + + let data_inner = unsafe { &mut *((*data).0 as *mut GameData) }; + data_inner.name(name_str); + + let raw = Box::into_raw(Box::new(FfiGameData(Box::into_raw(Box::new(data)) as *mut _))); + raw + } + + /// Set version info + #[unsafe(no_mangle)] + pub extern "C" fn game_data_set_version_info( + data: *mut FfiGameData, + version: *const c_char, + ) -> *mut FfiGameData { + + if data.is_null() || version.is_null() { + return std::ptr::null_mut(); + } + + let version_str = unsafe { CStr::from_ptr(version) }.to_string_lossy().into_owned(); + + let data_inner = unsafe { &mut *((*data).0 as *mut GameData) }; + data_inner.version(version_str); + + let raw = Box::into_raw(Box::new(FfiGameData(Box::into_raw(Box::new(data)) as *mut _))); + raw + } + /// Load data archive #[unsafe(no_mangle)] pub extern "C" fn game_data_load_archive( @@ -104,24 +165,25 @@ impl FfiGameData { return std::ptr::null_mut(); } - let data_inner = unsafe { data.read() }; - let raw_data = data_inner.0; + let data_inner = unsafe { &mut *((*data).0 as *mut GameData) }; - let game_data: Box<GameData> = unsafe { Box::from_raw(raw_data as *mut GameData) }; + let arc = data_inner.runtime_with_borrowed_data(); + let ptr = Arc::into_raw(arc) as *mut c_void; - extern "C" fn drop_runtime(raw: *mut c_void) { + let ffi_runtime = Box::new(FfiGameRuntime { + inner: ptr, + drop_fn: Self::drop_game_runtime, + }); + + Box::into_raw(ffi_runtime) + } + + extern "C" fn drop_game_runtime(ptr: *mut c_void) { + if !ptr.is_null() { unsafe { - let arc_ptr = raw as *const Arc<Mutex<GameRuntime>>; - drop(Arc::from_raw(arc_ptr)); + let _ = Arc::<Mutex<GameRuntime>>::from_raw(ptr as *mut _); } } - - let arc_raw = Arc::into_raw(game_data.runtime()) as *mut c_void; - - Box::into_raw(Box::new(FfiGameRuntime { - inner: arc_raw, - drop_fn: drop_runtime, - })) } /// Free data @@ -183,34 +245,62 @@ impl FfiGameRuntimeArchive { impl FfiGameRuntime { + fn operate_game_runtime( + runtime: *mut FfiGameRuntime, + callback: fn(guard: &mut MutexGuard<GameRuntime>) + ) { + unsafe { + let ffi_runtime = &*runtime; + Arc::increment_strong_count(ffi_runtime.inner); + let arc = Arc::<Mutex<GameRuntime>>::from_raw(ffi_runtime.inner as *mut _); + let arc_clone = Arc::clone(&arc); + let _ = Arc::into_raw(arc); + entry_mutex!(arc_clone, |guard| { + callback(guard); + }); + Arc::decrement_strong_count(ffi_runtime.inner); + } + } + + fn operate_game_runtime_with_return<Input, Result>( + runtime: *mut FfiGameRuntime, + input: Input, + callback: fn(guard: &mut MutexGuard<GameRuntime>, input: Input) -> Option<Result> + ) -> Option<Result> { + unsafe { + let ffi_runtime = &*runtime; + Arc::increment_strong_count(ffi_runtime.inner); + let arc = Arc::<Mutex<GameRuntime>>::from_raw(ffi_runtime.inner as *mut _); + let arc_clone = Arc::clone(&arc); + let _ = Arc::into_raw(arc); + let mut result = None; + entry_mutex!(arc_clone, |guard| { + result = callback(guard, input); + }); + Arc::decrement_strong_count(ffi_runtime.inner); + result + } + } + fn send_message_to( runtime: *mut FfiGameRuntime, player: *const FfiPlayer, - service_type: *mut FfiServiceType, + service_type: 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) }; + let service = ServiceType::from(&service_type); - entry_mutex!(arc_ref, |mutex_guard| { - do_on(mutex_guard); + Self::operate_game_runtime_with_return( + runtime, + (&player.account, message, service), + |guard, (account, message, service)| { + guard.send_game_message(account, message, service); + Some(()) }); } @@ -220,7 +310,7 @@ impl FfiGameRuntime { runtime: *mut FfiGameRuntime, player: *const FfiPlayer, message: *mut FfiGameMessage, - service_type: *mut FfiServiceType + service_type: FfiServiceType ) { if message.is_null() { return; } let msg = unsafe { GameMessage::from(message.read()) }; @@ -232,7 +322,7 @@ impl FfiGameRuntime { pub extern "C" fn game_runtime_send_text_message( runtime: *mut FfiGameRuntime, player: *const FfiPlayer, - service_type: *mut FfiServiceType, + service_type: FfiServiceType, text: *const c_char ) { let text_str = unsafe { CStr::from_ptr(text) }.to_string_lossy().into_owned().to_string(); @@ -244,7 +334,7 @@ impl FfiGameRuntime { pub extern "C" fn game_runtime_send_event( runtime: *mut FfiGameRuntime, player: *const FfiPlayer, - service_type: *mut FfiServiceType, + service_type: FfiServiceType, key: u8 ) { Self::send_message_to(runtime, player, service_type, GameMessage::EventTrigger(key)); @@ -254,12 +344,13 @@ impl FfiGameRuntime { #[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(); - }); + + let control_event = Self::operate_game_runtime_with_return( + runtime, + (), |guard, _| { + guard.pop_control_event() + }); + match control_event { None => { std::ptr::null_mut() } Some((account, message)) => { @@ -276,13 +367,21 @@ impl FfiGameRuntime { pub extern "C" fn game_runtime_let_exit( runtime: *mut FfiGameRuntime, player: *const FfiPlayer, - service_type: *mut FfiServiceType, - reason: *mut FfiExitReason + service_type: FfiServiceType, + reason: 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); + 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(); + + Self::operate_game_runtime_with_return( + runtime, (&player.account, ExitReason::from(&reason), ServiceType::from(&service_type)), + |guard, (account, reason, service)| { + guard.let_account_exit(account, reason, service); + Some(()) + } + ); } /// Kick a player @@ -290,20 +389,20 @@ impl FfiGameRuntime { pub extern "C" fn game_runtime_kick_player( runtime: *mut FfiGameRuntime, player: *const FfiPlayer, - service_type: *mut FfiServiceType + service_type: FfiServiceType ) { - if runtime.is_null() || player.is_null() || service_type.is_null() { return; } + 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(); - 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); - }); + Self::operate_game_runtime_with_return( + runtime, (&player, ServiceType::from(&service_type)), + |guard, (player, service)| { + guard.kick_player(player, service); + Some(()) + } + ); } /// Ban a player (And kick) @@ -311,20 +410,20 @@ impl FfiGameRuntime { pub extern "C" fn game_runtime_ban_player( runtime: *mut FfiGameRuntime, player: *const FfiPlayer, - service_type: *mut FfiServiceType + service_type: FfiServiceType ) { - if runtime.is_null() || player.is_null() || service_type.is_null() { return; } + 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(); - 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); - }); + Self::operate_game_runtime_with_return( + runtime, (&player, ServiceType::from(&service_type)), + |guard, (player, service)| { + guard.ban_player(player, service); + Some(()) + } + ); } /// Pardon a player @@ -338,19 +437,20 @@ impl FfiGameRuntime { 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); - }); + Self::operate_game_runtime_with_return( + runtime, &player, + |guard, player| { + guard.pardon_player(player); + Some(()) + } + ); } /// 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| { + Self::operate_game_runtime(runtime, |guard| { guard.close_game(); }) } @@ -359,7 +459,7 @@ impl FfiGameRuntime { #[unsafe(no_mangle)] pub extern "C" fn game_runtime_lock(runtime: *mut FfiGameRuntime) { if runtime.is_null() { return; } - Self::do_on_rt(runtime, |guard| { + Self::operate_game_runtime(runtime, |guard| { guard.lock_game(); }) } @@ -368,7 +468,7 @@ impl FfiGameRuntime { #[unsafe(no_mangle)] pub extern "C" fn game_runtime_unlock(runtime: *mut FfiGameRuntime) { if runtime.is_null() { return; } - Self::do_on_rt(runtime, |guard| { + Self::operate_game_runtime(runtime, |guard| { guard.unlock_game(); }) } @@ -377,15 +477,12 @@ impl FfiGameRuntime { #[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(); + let result = Self::operate_game_runtime_with_return( + runtime, (), + |guard, _| { + Some(guard.is_game_locked()) }); - - locked + result.unwrap_or(false) } /// Get button status of player @@ -400,12 +497,11 @@ impl FfiGameRuntime { 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); - }); + let status = Self::operate_game_runtime_with_return( + runtime, (account, key), |guard, (account, key)| { + guard.control.get_button_status(&account, &key) + } + ); match status { None => { FfiButtonStatus { found: false, pressed: false, released: false } } @@ -427,12 +523,11 @@ impl FfiGameRuntime { 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); - }); + let status = Self::operate_game_runtime_with_return( + runtime, (account, key), |guard, (account, key)| { + guard.control.get_axis(&account, &key) + } + ); match status { None => { FfiAxis { found: false, axis: 0.0 } } @@ -454,12 +549,11 @@ impl FfiGameRuntime { 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); - }); + let status = Self::operate_game_runtime_with_return( + runtime, (account, key), |guard, (account, key)| { + guard.control.get_direction(&account, &key) + } + ); match status { None => { FfiDirection { found: false, x: 0.0, y: 0.0 } } @@ -474,23 +568,22 @@ impl FfiGameRuntime { pub extern "C" fn game_runtime_get_service_type( runtime: *mut FfiGameRuntime, player: *const FfiPlayer - ) -> *const FfiServiceType { + ) -> 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); - }); + let service_type = Self::operate_game_runtime_with_return( + runtime, account, |guard, account| { + guard.data.get_service_type(&account) + } + ); match service_type { - None => { null() } + None => { FfiServiceType::BlueTooth } Some(r) => { - Box::into_raw(Box::new(FfiServiceType::from(&r))) + FfiServiceType::from(&r) } } } @@ -506,12 +599,11 @@ impl FfiGameRuntime { 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)); - }); + let banned = Self::operate_game_runtime_with_return( + runtime, account, |guard, account| { + Some(guard.data.is_account_banned(&account)) + } + ); match banned { None => { FfiBooleanResult { found: false, result: false } } @@ -532,12 +624,11 @@ impl FfiGameRuntime { 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)); - }); + let online = Self::operate_game_runtime_with_return( + runtime, account, |guard, account| { + Some(guard.data.is_account_online(&account)) + } + ); match online { None => { FfiBooleanResult { found: false, result: false } } @@ -551,12 +642,11 @@ impl FfiGameRuntime { #[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 online_list = Self::operate_game_runtime_with_return( + runtime, (), |guard, _| { + Some(guard.data.online_accounts()) + } + ); let mut result : Vec<FfiPlayer> = vec![]; if online_list.is_some() { @@ -579,12 +669,11 @@ impl FfiGameRuntime { #[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 banned_list = Self::operate_game_runtime_with_return( + runtime, (), |guard, _| { + Some(guard.data.banned_accounts()) + } + ); let mut result : Vec<FfiPlayer> = vec![]; if banned_list.is_none() { diff --git a/core/bindings/lang/clang/src/lib.rs b/core/bindings/lang/clang/src/lib.rs index f939758..08da79e 100644 --- a/core/bindings/lang/clang/src/lib.rs +++ b/core/bindings/lang/clang/src/lib.rs @@ -1,3 +1,4 @@ pub mod converter; pub mod data; pub mod service; +pub mod logger_utils; diff --git a/core/bindings/lang/clang/src/logger_utils.rs b/core/bindings/lang/clang/src/logger_utils.rs new file mode 100644 index 0000000..96bd0dc --- /dev/null +++ b/core/bindings/lang/clang/src/logger_utils.rs @@ -0,0 +1,13 @@ +use nogamepads::logger_utils::logger_build; + +#[unsafe(no_mangle)] +pub extern "C" fn enable_logger(level: u8) { + let level_filter = match level { + 0 => log::LevelFilter::Info, + 1 => log::LevelFilter::Debug, + 2 => log::LevelFilter::Trace, + _ => { log::LevelFilter::Info } + }; + + logger_build(level_filter); +}
\ 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 index 8701284..a11c2f1 100644 --- a/core/bindings/lang/clang/src/service/ngpd_service_types.rs +++ b/core/bindings/lang/clang/src/service/ngpd_service_types.rs @@ -2,6 +2,7 @@ use nogamepads_core::service::service_types::ServiceType; #[repr(C)] pub enum FfiServiceType { + Unknown, TCPConnection, BlueTooth, USB, @@ -23,6 +24,9 @@ impl From<&FfiServiceType> for ServiceType { FfiServiceType::TCPConnection => { ServiceType::TCPConnection } FfiServiceType::BlueTooth => { ServiceType::BlueTooth } FfiServiceType::USB => { ServiceType::USB } + _ => { + ServiceType::default() + } } } } diff --git a/core/bindings/lang/clang/src/service/ngpd_tcp_service.rs b/core/bindings/lang/clang/src/service/ngpd_tcp_service.rs index 2c8995c..6e706b5 100644 --- a/core/bindings/lang/clang/src/service/ngpd_tcp_service.rs +++ b/core/bindings/lang/clang/src/service/ngpd_tcp_service.rs @@ -1,13 +1,14 @@ use crate::data::ngpd_controller::FfiControllerRuntime; use crate::data::ngpd_game::FfiGameRuntime; -use nogamepads_core::data::controller::controller_runtime::ControllerRuntime; -use nogamepads_core::data::game::game_runtime::GameRuntime; use nogamepads_core::service::tcp_network::pad_client::pad_client_service::PadClientNetwork; use nogamepads_core::service::tcp_network::pad_server::pad_server_service::PadServerNetwork; +use nogamepads_core::service::tcp_network::utils::tokio_utils::build_tokio_runtime; use std::ffi::{c_char, c_void, CStr}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; +use std::ptr::null_mut; use std::sync::{Arc, Mutex}; -use nogamepads_core::service::tcp_network::utils::tokio_utils::build_tokio_runtime; +use nogamepads_core::data::controller::controller_runtime::ControllerRuntime; +use nogamepads_core::data::game::game_runtime::GameRuntime; #[repr(C)] pub struct FfiTcpClientService(*mut c_void); @@ -24,16 +25,22 @@ impl FfiTcpClientService { ) -> *mut FfiTcpClientService { if runtime.is_null() { - return std::ptr::null_mut(); + return null_mut(); } - let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<ControllerRuntime>> }; - let arc_ref = unsafe { Arc::clone(&*arc_ptr) }; + let runtime_ref = unsafe { &*runtime }; + let data_ptr = runtime_ref.inner as *const Mutex<ControllerRuntime>; + + let arc = unsafe { + let atomic_arc = Arc::from_raw(data_ptr); + Arc::clone(&atomic_arc) + }; - let service = PadClientNetwork::build(Arc::clone(&arc_ref)); - let raw = Box::into_raw(Box::new(FfiTcpClientService(Box::into_raw(Box::new(service)) as *mut _))); + let client = PadClientNetwork::build(arc.clone()); - raw + let client_box = Box::new(client); + let service = FfiTcpClientService(Box::into_raw(client_box) as *mut _); + Box::into_raw(Box::new(service)) } /// Bind ipv4 address @@ -160,12 +167,17 @@ impl FfiTcpClientService { pub extern "C" fn free_tcp_client( service: *mut FfiTcpClientService ) { - if service.is_null() { return; } + if service.is_null() { + return; + } - let service_ptr = service as *mut PadClientNetwork; + let wrapper = unsafe { Box::from_raw(service) }; + let client_ptr = wrapper.0; unsafe { - let _ = Box::from_raw(service_ptr); + if !client_ptr.is_null() { + let _ = Box::from_raw(client_ptr as *mut PadClientNetwork); + } } } } @@ -178,15 +190,23 @@ impl FfiTcpServerService { runtime: *mut FfiGameRuntime, ) -> *mut FfiTcpServerService { - if runtime.is_null() { return std::ptr::null_mut(); } + if runtime.is_null() { + return null_mut(); + } + + let runtime_ref = unsafe { &*runtime }; + let data_ptr = runtime_ref.inner as *const Mutex<GameRuntime>; - let arc_ptr = unsafe { (*runtime).inner as *const Arc<Mutex<GameRuntime>> }; - let arc_ref = unsafe { Arc::clone(&*arc_ptr) }; + let arc = unsafe { + let atomic_arc = Arc::from_raw(data_ptr); + Arc::clone(&atomic_arc) + }; - let service = PadServerNetwork::build(Arc::clone(&arc_ref)); - let raw = Box::into_raw(Box::new(FfiTcpServerService(Box::into_raw(Box::new(service)) as *mut _))); + let server = PadServerNetwork::build(arc.clone()); - raw + let server_box = Box::new(server); + let service = FfiTcpServerService(Box::into_raw(server_box) as *mut _); + Box::into_raw(Box::new(service)) } /// Bind ipv4 address @@ -305,12 +325,14 @@ impl FfiTcpServerService { pub extern "C" fn free_tcp_server( service: *mut FfiTcpServerService ) { - if service.is_null() { return; } - - let service_ptr = service as *mut PadServerNetwork; + if !service.is_null() { + unsafe { + let service = Box::from_raw(service); - unsafe { - let _ = Box::from_raw(service_ptr); + if !service.0.is_null() { + Arc::from_raw(service.0 as *mut _); + } + } } } }
\ No newline at end of file diff --git a/core/src/data/controller/controller_data.rs b/core/src/data/controller/controller_data.rs index a3f1c02..a40f49c 100644 --- a/core/src/data/controller/controller_data.rs +++ b/core/src/data/controller/controller_data.rs @@ -4,7 +4,7 @@ use crate::data::player::player_data::Player; /// Controller-side Data /// Describes the basic information of the controller side -#[derive(Default)] +#[derive(Default, Clone)] pub struct ControllerData { /// Player bound to the controller side @@ -26,4 +26,13 @@ impl ControllerData { }; Arc::new(Mutex::new(runtime)) } + + /// Build the controller-side runtime using controller data (borrowed) + pub fn runtime_with_borrowed_data(&self) -> Arc<Mutex<ControllerRuntime>> { + let runtime = ControllerRuntime { + player: self.player.clone(), + ..Default::default() + }; + Arc::new(Mutex::new(runtime)) + } }
\ No newline at end of file diff --git a/core/src/data/game/game_data.rs b/core/src/data/game/game_data.rs index 35a5c0e..bc198df 100644 --- a/core/src/data/game/game_data.rs +++ b/core/src/data/game/game_data.rs @@ -91,6 +91,12 @@ impl GameData { }; Arc::new(Mutex::new(runtime)) } + + /// Build the game-side runtime using game data (borrowed) + pub fn runtime_with_borrowed_data(&self) -> Arc<Mutex<GameRuntime>> { + let runtime = self.clone().runtime(); + runtime + } } impl From<GameRuntimeDataArchive> for GameRuntimeData { |
