aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorWeicao Mao <1992414357@qq.com>2025-06-14 04:35:18 +0800
committerGitHub <noreply@github.com>2025-06-14 04:35:18 +0800
commitf0929789d5e3957082c41534eecd2ebf5dd38163 (patch)
tree00692a012dde9ca06ffc725066228157e0e83ec8 /core
parent8a87a67ac7eaed22b3d925b8a2d66e60c3847007 (diff)
parentf657a9c2056d4e5692ddbc19217b654277300c75 (diff)
Merge pull request #1 from CatilGrass/c_bindings
Merge to main
Diffstat (limited to 'core')
-rw-r--r--core/bindings/c_lang/Cargo.toml12
-rw-r--r--core/bindings/c_lang/headers/ngpd_player.h39
-rw-r--r--core/bindings/c_lang/src/data/mod.rs1
-rw-r--r--core/bindings/c_lang/src/lib.rs1
-rw-r--r--core/bindings/lang/clang/Cargo.toml16
-rw-r--r--core/bindings/lang/clang/build.rs61
-rw-r--r--core/bindings/lang/clang/configures/nogamepads_data.toml17
-rw-r--r--core/bindings/lang/clang/headers/nogamepads_data.h181
-rw-r--r--core/bindings/lang/clang/src/converter/mod.rs1
-rw-r--r--core/bindings/lang/clang/src/converter/string_converter.rs24
-rw-r--r--core/bindings/lang/clang/src/data/mod.rs3
-rw-r--r--core/bindings/lang/clang/src/data/ngpd_game_info.rs109
-rw-r--r--core/bindings/lang/clang/src/data/ngpd_message.rs486
-rw-r--r--core/bindings/lang/clang/src/data/ngpd_player.rs (renamed from core/bindings/c_lang/src/data/ngpd_player.rs)16
-rw-r--r--core/bindings/lang/clang/src/lib.rs2
-rw-r--r--core/examples/connect.rs27
-rw-r--r--core/examples/tcp_server.rs43
17 files changed, 908 insertions, 131 deletions
diff --git a/core/bindings/c_lang/Cargo.toml b/core/bindings/c_lang/Cargo.toml
deleted file mode 100644
index a0ee61f..0000000
--- a/core/bindings/c_lang/Cargo.toml
+++ /dev/null
@@ -1,12 +0,0 @@
-[package]
-name = "nogamepads-c-bindings"
-edition = "2024"
-version.workspace = true
-
-[dependencies]
-nogamepads-core = { path = "../../../core" }
-libc = "0.2.172"
-
-[lib]
-name = "nogamepads_c"
-crate-type = ["cdylib"]
diff --git a/core/bindings/c_lang/headers/ngpd_player.h b/core/bindings/c_lang/headers/ngpd_player.h
deleted file mode 100644
index 00fbe5b..0000000
--- a/core/bindings/c_lang/headers/ngpd_player.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef PLAYER_FFI_H
-#define PLAYER_FFI_H
-
-#include <stdbool.h>
-#include <stdint.h>
-
-typedef struct FfiAccount {
- char* id;
- char* player_hash;
-} FfiAccount;
-
-typedef struct FfiCustomize {
- char* nickname;
- int32_t color_hue;
- double color_saturation;
- double color_value;
-} FfiCustomize;
-
-typedef struct FfiPlayer {
- FfiAccount account;
- FfiCustomize* customize;
-} FfiPlayer;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-FfiPlayer* player_register(const char* id, const char* password);
-bool player_check(const FfiPlayer* player, const char* password);
-void player_set_nickname(FfiPlayer* player, const char* nickname);
-void player_set_hue(FfiPlayer* player, int hue);
-void player_set_hsv(FfiPlayer* player, int hue, double saturation, double value);
-void player_free(FfiPlayer* player);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif \ No newline at end of file
diff --git a/core/bindings/c_lang/src/data/mod.rs b/core/bindings/c_lang/src/data/mod.rs
deleted file mode 100644
index 32af6d8..0000000
--- a/core/bindings/c_lang/src/data/mod.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub mod ngpd_player; \ No newline at end of file
diff --git a/core/bindings/c_lang/src/lib.rs b/core/bindings/c_lang/src/lib.rs
deleted file mode 100644
index 12e35bb..0000000
--- a/core/bindings/c_lang/src/lib.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub mod data; \ No newline at end of file
diff --git a/core/bindings/lang/clang/Cargo.toml b/core/bindings/lang/clang/Cargo.toml
new file mode 100644
index 0000000..7359db0
--- /dev/null
+++ b/core/bindings/lang/clang/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "nogamepads-c-bindings"
+edition = "2024"
+version.workspace = true
+
+build = "build.rs"
+
+[dependencies]
+nogamepads-core = { path = "./../../../../core" }
+
+[build-dependencies]
+cbindgen = "0.29.0"
+
+[lib]
+name = "nogamepads_c"
+crate-type = ["cdylib", "rlib"]
diff --git a/core/bindings/lang/clang/build.rs b/core/bindings/lang/clang/build.rs
new file mode 100644
index 0000000..190501e
--- /dev/null
+++ b/core/bindings/lang/clang/build.rs
@@ -0,0 +1,61 @@
+fn main() {
+ // Get the project root directory
+ let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
+ let root_path = std::path::Path::new(&manifest_dir);
+
+ // Input configuration directory path
+ let config_dir = root_path.join("configures");
+
+ // Output directory path (headers folder in the crate directory)
+ let headers_dir = root_path.join("headers");
+
+ // Clear existing headers directory (if it exists)
+ if headers_dir.exists() {
+ std::fs::remove_dir_all(&headers_dir).expect("Failed to remove headers directory");
+ }
+
+ // Create a new headers directory
+ std::fs::create_dir_all(&headers_dir).expect("Failed to create headers directory");
+
+ // Find all TOML files in configures directory
+ let config_files = std::fs::read_dir(&config_dir)
+ .expect("Failed to read configures directory")
+ .filter_map(|entry| {
+ let entry = entry.expect("Failed to read directory entry");
+ let path = entry.path();
+ if path.is_file() && path.extension().map_or(false, |ext| ext == "toml") {
+ Some(path)
+ } else {
+ None
+ }
+ });
+
+ // Process each configuration file
+ for config_path in config_files {
+ // Extract filename without extension
+ let file_stem = config_path.file_stem()
+ .and_then(|s| s.to_str())
+ .expect("Invalid filename")
+ .to_string();
+
+ // Set output file path
+ let output_file = headers_dir.join(format!("{}.h", file_stem));
+
+ // Load configuration from current TOML file
+ let config = cbindgen::Config::from_file(&config_path)
+ .expect(&format!("Failed to parse configuration: {}", config_path.display()));
+
+ // Generate header file
+ cbindgen::Builder::new()
+ .with_crate(&manifest_dir)
+ .with_config(config)
+ .generate()
+ .expect(&format!("Failed to generate header for: {}", config_path.display()))
+ .write_to_file(&output_file);
+ }
+
+ // Print rerun instructions
+ println!("cargo:rerun-if-changed={}", config_dir.display());
+ println!("cargo:rerun-if-changed=src/mycode.rs");
+ println!("cargo:rerun-if-changed=build.rs");
+} \ No newline at end of file
diff --git a/core/bindings/lang/clang/configures/nogamepads_data.toml b/core/bindings/lang/clang/configures/nogamepads_data.toml
new file mode 100644
index 0000000..56d645d
--- /dev/null
+++ b/core/bindings/lang/clang/configures/nogamepads_data.toml
@@ -0,0 +1,17 @@
+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"
+]
+
+[fn]
+prefix = "ngpd_data_" \ 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
new file mode 100644
index 0000000..6d9f1ad
--- /dev/null
+++ b/core/bindings/lang/clang/headers/nogamepads_data.h
@@ -0,0 +1,181 @@
+// Auto generated by cbindgen 0.29.0
+
+#ifndef NOGAMEPADS_DATA_H
+#define NOGAMEPADS_DATA_H
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+typedef enum FfiConnectionMessageTag {
+ Join,
+ RequestGameInfos,
+ RequestLayoutConfigure,
+ RequestSkinPackage,
+ Ready,
+ Err,
+} FfiConnectionMessageTag;
+
+typedef enum FfiConnectionResponseMessageTag {
+ GameInfos,
+ Deny,
+ Fail,
+ Ok,
+ Welcome,
+ Err,
+} FfiConnectionResponseMessageTag;
+
+typedef enum FfiControlMessageTag {
+ Msg,
+ Pressed,
+ Released,
+ Axis,
+ Dir,
+ Exit,
+ Err,
+ End,
+} FfiControlMessageTag;
+
+typedef enum FfiExitReason {
+ Exit,
+ GameOver,
+ ServerClosed,
+ YouAreKicked,
+ YouAreBanned,
+ Err,
+} FfiExitReason;
+
+typedef enum FfiGameMessageTag {
+ EventTrigger,
+ Msg,
+ LetExit,
+ Err,
+ End,
+} FfiGameMessageTag;
+
+typedef enum FfiJoinFailedMessage {
+ ContainIdenticalPlayer,
+ PlayerBanned,
+ GameLocked,
+ UnknownError,
+} FfiJoinFailedMessage;
+
+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;
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+ngpd_data_ void free_c_string(char *ptr);
+
+ngpd_data_ struct FfiPlayer *player_register(const char *id, const char *password);
+
+ngpd_data_ bool player_check(const struct FfiPlayer *player, const char *password);
+
+ngpd_data_ void player_set_nickname(struct FfiPlayer *player, const char *nickname);
+
+ngpd_data_ void player_set_hue(struct FfiPlayer *player, int hue);
+
+ngpd_data_ void player_set_hsv(struct FfiPlayer *player, int hue, double saturation, double value);
+
+ngpd_data_ void player_free(struct FfiPlayer *player);
+
+ngpd_data_ void free_control_message(struct FfiControlMessage msg);
+
+ngpd_data_ void free_game_message(struct FfiGameMessage msg);
+
+ngpd_data_ void free_exit_reason(enum FfiExitReason msg);
+
+ngpd_data_ void free_connection_message(struct FfiConnectionMessage msg);
+
+ngpd_data_ void free_connection_response_message(struct FfiConnectionResponseMessage msg);
+
+ngpd_data_ void free_join_failed_message(enum FfiJoinFailedMessage msg);
+
+ngpd_data_ void free_game_info(struct FfiGameInfo map);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif /* NOGAMEPADS_DATA_H */
diff --git a/core/bindings/lang/clang/src/converter/mod.rs b/core/bindings/lang/clang/src/converter/mod.rs
new file mode 100644
index 0000000..86708b0
--- /dev/null
+++ b/core/bindings/lang/clang/src/converter/mod.rs
@@ -0,0 +1 @@
+pub mod string_converter; \ No newline at end of file
diff --git a/core/bindings/lang/clang/src/converter/string_converter.rs b/core/bindings/lang/clang/src/converter/string_converter.rs
new file mode 100644
index 0000000..7345f5a
--- /dev/null
+++ b/core/bindings/lang/clang/src/converter/string_converter.rs
@@ -0,0 +1,24 @@
+use std::ffi::{c_char, CStr, CString};
+
+pub unsafe fn str_rs_to_c(content: String) -> *mut c_char {
+ let c_str = CString::new(content).expect("CString::new failed");
+
+ c_str.into_raw()
+}
+
+pub unsafe fn str_c_to_rs(content_ptr: *mut c_char) -> String {
+ let c_str = unsafe { CStr::from_ptr(content_ptr) };
+
+ c_str.to_str()
+ .expect("Invalid UTF-8 sequence")
+ .to_owned()
+}
+
+#[unsafe(no_mangle)]
+pub unsafe extern "C" fn free_c_string(ptr: *mut c_char) {
+ if ptr.is_null() {
+ return;
+ }
+
+ let _ = unsafe { CString::from_raw(ptr) };
+} \ No newline at end of file
diff --git a/core/bindings/lang/clang/src/data/mod.rs b/core/bindings/lang/clang/src/data/mod.rs
new file mode 100644
index 0000000..c93e7f0
--- /dev/null
+++ b/core/bindings/lang/clang/src/data/mod.rs
@@ -0,0 +1,3 @@
+pub mod ngpd_player;
+pub mod ngpd_message;
+mod ngpd_game_info; \ 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
new file mode 100644
index 0000000..af45758
--- /dev/null
+++ b/core/bindings/lang/clang/src/data/ngpd_game_info.rs
@@ -0,0 +1,109 @@
+use std::collections::HashMap;
+use std::ffi::{CStr, CString};
+use std::os::raw::c_char;
+
+#[repr(C)]
+pub struct KeyValuePair {
+ key: *mut c_char,
+ value: *mut c_char,
+}
+
+#[repr(C)]
+pub struct FfiGameInfo {
+ data: *mut KeyValuePair,
+ len: usize,
+ cap: usize,
+}
+
+impl From<&HashMap<String, String>> for FfiGameInfo {
+ fn from(map: &HashMap<String, String>) -> Self {
+ let mut kv_pairs: Vec<KeyValuePair> = map
+ .into_iter()
+ .map(|(k, v)| {
+ KeyValuePair {
+ key: CString::new(k.clone()).unwrap().into_raw(),
+ value: CString::new(v.clone()).unwrap().into_raw(),
+ }
+ })
+ .collect();
+
+ let cap = kv_pairs.capacity();
+ let len = kv_pairs.len();
+ let data_ptr = kv_pairs.as_mut_ptr();
+
+ std::mem::forget(kv_pairs);
+
+ FfiGameInfo {
+ data: data_ptr,
+ len,
+ cap,
+ }
+ }
+}
+
+impl TryFrom<&FfiGameInfo> for HashMap<String, String> {
+ type Error = String;
+
+ fn try_from(ffi_info: &FfiGameInfo) -> Result<Self, Self::Error> {
+ if ffi_info.len == 0 {
+ return Ok(HashMap::new());
+ }
+
+ if ffi_info.data.is_null() {
+ return Err("FfiGameInfo data pointer is null".to_string());
+ }
+
+ let kv_slice = unsafe {
+ std::slice::from_raw_parts(ffi_info.data, ffi_info.len)
+ };
+
+ let mut map = HashMap::with_capacity(ffi_info.len);
+
+ for (i, pair) in kv_slice.iter().enumerate() {
+ if pair.key.is_null() {
+ return Err(format!("Key pointer is null at index {}", i));
+ }
+
+ if pair.value.is_null() {
+ return Err(format!("Value pointer is null at index {}", i));
+ }
+
+ let key_str = unsafe {
+ CStr::from_ptr(pair.key)
+ .to_str()
+ .map_err(|_| "Invalid UTF-8 in key")?
+ };
+
+ let value_str = unsafe {
+ CStr::from_ptr(pair.value)
+ .to_str()
+ .map_err(|_| "Invalid UTF-8 in value")?
+ };
+
+ map.insert(key_str.to_owned(), value_str.to_owned());
+ }
+
+ Ok(map)
+ }
+}
+
+impl From<&FfiGameInfo> for Option<HashMap<String, String>> {
+ fn from(ffi_info: &FfiGameInfo) -> Self {
+ match HashMap::try_from(ffi_info) {
+ Ok(map) => Some(map),
+ Err(_) => None,
+ }
+ }
+}
+
+#[unsafe(no_mangle)]
+pub unsafe 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 {
+ unsafe {
+ let _ = CString::from_raw(pair.key);
+ let _ = CString::from_raw(pair.value);
+ }
+ }
+} \ No newline at end of file
diff --git a/core/bindings/lang/clang/src/data/ngpd_message.rs b/core/bindings/lang/clang/src/data/ngpd_message.rs
new file mode 100644
index 0000000..c669299
--- /dev/null
+++ b/core/bindings/lang/clang/src/data/ngpd_message.rs
@@ -0,0 +1,486 @@
+use crate::converter::string_converter::{str_c_to_rs, str_rs_to_c};
+use crate::data::ngpd_game_info::FfiGameInfo;
+use crate::data::ngpd_player::FfiPlayer;
+use nogamepads_core::data::message::message_enums::{ConnectionMessage, ConnectionResponseMessage, ControlMessage, ExitReason, GameMessage, JoinFailedMessage};
+use std::mem::ManuallyDrop;
+use std::ops::Deref;
+use std::os::raw::{c_char, c_double};
+
+#[repr(C)]
+pub struct FfiControlMessage {
+ pub tag: FfiControlMessageTag,
+ pub data: FfiControlMessageUnion
+}
+
+#[repr(C)]
+pub enum FfiControlMessageTag {
+ Msg, Pressed, Released, Axis, Dir, Exit, Err, End
+}
+
+#[repr(C)]
+pub union FfiControlMessageUnion {
+ pub none: (),
+ pub message: *mut c_char,
+ pub key: u8,
+ pub key_and_axis: ManuallyDrop<FfiKeyAndAxis>,
+ pub key_and_direction: ManuallyDrop<FfiKeyAndDirection>,
+}
+
+#[repr(C)]
+pub struct FfiKeyAndAxis {
+ pub key: u8,
+ pub axis: c_double
+}
+
+#[repr(C)]
+pub struct FfiKeyAndDirection {
+ pub key: u8,
+ pub x: c_double,
+ pub y: c_double
+}
+
+#[repr(C)]
+pub struct FfiGameMessage {
+ pub tag: FfiGameMessageTag,
+ pub data: FfiGameMessageUnion
+}
+
+#[repr(C)]
+pub enum FfiGameMessageTag {
+ EventTrigger, Msg, LetExit, Err, End
+}
+
+#[repr(C)]
+pub union FfiGameMessageUnion {
+ pub none: (),
+ pub key: u8,
+ pub message: *mut c_char,
+ pub exit_reason: ManuallyDrop<FfiExitReason>,
+}
+
+#[repr(C)]
+pub enum FfiExitReason {
+ Exit, GameOver, ServerClosed, YouAreKicked, YouAreBanned, Err
+}
+
+#[repr(C)]
+pub struct FfiConnectionMessage {
+ pub tag: FfiConnectionMessageTag,
+ pub data: FfiConnectionMessageUnion
+}
+
+#[repr(C)]
+pub enum FfiConnectionMessageTag {
+ Join, RequestGameInfos, RequestLayoutConfigure, RequestSkinPackage, Ready, Err
+}
+
+#[repr(C)]
+pub union FfiConnectionMessageUnion {
+ pub none: (),
+ pub player: ManuallyDrop<FfiPlayer>
+}
+
+#[repr(C)]
+pub struct FfiConnectionResponseMessage {
+ pub tag: FfiConnectionResponseMessageTag,
+ pub data: FfiConnectionResponseMessageUnion
+}
+
+#[repr(C)]
+pub enum FfiConnectionResponseMessageTag {
+ GameInfos, Deny, Fail, Ok, Welcome, Err
+}
+
+#[repr(C)]
+pub union FfiConnectionResponseMessageUnion {
+ pub none: (),
+ pub game_info: ManuallyDrop<FfiGameInfo>,
+ pub failed_message: ManuallyDrop<FfiJoinFailedMessage>
+}
+
+#[repr(C)]
+pub enum FfiJoinFailedMessage {
+ ContainIdenticalPlayer, PlayerBanned, GameLocked, UnknownError
+}
+
+impl From<ControlMessage> for FfiControlMessage {
+ fn from(value: ControlMessage) -> Self {
+ match value {
+ ControlMessage::Msg(msg) => unsafe {
+ FfiControlMessage {
+ tag: FfiControlMessageTag::Msg,
+ data: FfiControlMessageUnion {
+ message: str_rs_to_c(msg),
+ }
+ }
+ }
+ ControlMessage::Pressed(key) => {
+ FfiControlMessage {
+ tag: FfiControlMessageTag::Pressed,
+ data: FfiControlMessageUnion {
+ key: key.into()
+ }
+ }
+ }
+ ControlMessage::Released(key) => {
+ FfiControlMessage {
+ tag: FfiControlMessageTag::Released,
+ data: FfiControlMessageUnion {
+ key: key.into()
+ }
+ }
+ }
+ ControlMessage::Axis(key, axis) => {
+ FfiControlMessage {
+ tag: FfiControlMessageTag::Axis,
+ data: FfiControlMessageUnion {
+ key_and_axis: ManuallyDrop::new(FfiKeyAndAxis {
+ key: key.into(),
+ axis: axis.into()
+ })
+ }
+ }
+ }
+ ControlMessage::Dir(key, (x, y)) => {
+ FfiControlMessage {
+ tag: FfiControlMessageTag::Axis,
+ data: FfiControlMessageUnion {
+ key_and_direction: ManuallyDrop::new(FfiKeyAndDirection {
+ key: key.into(),
+ x, y
+ })
+ }
+ }
+ }
+ ControlMessage::Exit => {
+ FfiControlMessage {
+ tag: FfiControlMessageTag::Axis,
+ data: FfiControlMessageUnion { none: () }
+ }
+ }
+ ControlMessage::Err => {
+ FfiControlMessage {
+ tag: FfiControlMessageTag::Axis,
+ data: FfiControlMessageUnion { none: () }
+ }
+ }
+ ControlMessage::End => {
+ FfiControlMessage {
+ tag: FfiControlMessageTag::Axis,
+ data: FfiControlMessageUnion { none: () }
+ }
+ }
+ }
+ }
+}
+
+impl From<FfiControlMessage> for ControlMessage {
+ fn from(value: FfiControlMessage) -> Self {
+ match value.tag {
+ FfiControlMessageTag::Msg => unsafe {
+ ControlMessage::Msg(str_c_to_rs(value.data.message))
+ }
+ FfiControlMessageTag::Pressed => unsafe {
+ ControlMessage::Pressed(value.data.key.into())
+ }
+ FfiControlMessageTag::Released => unsafe {
+ ControlMessage::Released(value.data.key.into())
+ }
+ FfiControlMessageTag::Axis => {
+ let value = unsafe { value.data.key_and_axis };
+ ControlMessage::Axis(value.key.into(), value.axis.into())
+ }
+ FfiControlMessageTag::Dir => {
+ let value = unsafe { value.data.key_and_direction };
+ ControlMessage::Dir(value.key.into(), (value.x.into(), value.y.into()))
+ }
+ FfiControlMessageTag::Exit => {
+ ControlMessage::Exit
+ }
+ FfiControlMessageTag::Err => {
+ ControlMessage::Err
+ }
+ FfiControlMessageTag::End => {
+ ControlMessage::End
+ }
+ }
+ }
+}
+
+impl From<GameMessage> for FfiGameMessage {
+ fn from(value: GameMessage) -> Self {
+ match value {
+ GameMessage::EventTrigger(key) => {
+ FfiGameMessage {
+ tag: FfiGameMessageTag::EventTrigger,
+ data: FfiGameMessageUnion {
+ key: key.into()
+ }
+ }
+ }
+ GameMessage::Msg(msg) => unsafe {
+ FfiGameMessage {
+ tag: FfiGameMessageTag::Msg,
+ data: FfiGameMessageUnion {
+ message: str_rs_to_c(msg)
+ }
+ }
+ }
+ GameMessage::LetExit(reason) => {
+ FfiGameMessage {
+ tag: FfiGameMessageTag::LetExit,
+ data: FfiGameMessageUnion {
+ exit_reason: ManuallyDrop::new(FfiExitReason::from(&reason))
+ }
+ }
+ }
+ GameMessage::Err => {
+ FfiGameMessage {
+ tag: FfiGameMessageTag::Err,
+ data: FfiGameMessageUnion { none: () }
+ }
+ }
+ GameMessage::End => {
+ FfiGameMessage {
+ tag: FfiGameMessageTag::End,
+ data: FfiGameMessageUnion { none: () }
+ }
+ }
+ }
+ }
+}
+
+impl From<FfiGameMessage> for GameMessage {
+ fn from(value: FfiGameMessage) -> Self {
+ match value.tag {
+ FfiGameMessageTag::EventTrigger => unsafe {
+ GameMessage::EventTrigger(value.data.key.into())
+ }
+ FfiGameMessageTag::Msg => unsafe {
+ GameMessage::Msg(str_c_to_rs(value.data.message))
+ }
+ FfiGameMessageTag::LetExit => unsafe {
+ GameMessage::LetExit(value.data.exit_reason.deref().into())
+ }
+ FfiGameMessageTag::Err => {
+ GameMessage::Err
+ }
+ FfiGameMessageTag::End => {
+ GameMessage::End
+ }
+ }
+ }
+}
+
+impl From<&ExitReason> for FfiExitReason {
+ fn from(value: &ExitReason) -> Self {
+ match value {
+ ExitReason::Exit => { FfiExitReason::Exit }
+ ExitReason::GameOver => { FfiExitReason::GameOver }
+ ExitReason::ServerClosed => { FfiExitReason::ServerClosed }
+ ExitReason::YouAreKicked => { FfiExitReason::YouAreKicked }
+ ExitReason::YouAreBanned => { FfiExitReason::YouAreBanned }
+ ExitReason::Err => { FfiExitReason::Err }
+ }
+ }
+}
+
+impl From<&FfiExitReason> for ExitReason {
+ fn from(value: &FfiExitReason) -> Self {
+ match value {
+ FfiExitReason::Exit => { ExitReason::Exit }
+ FfiExitReason::GameOver => { ExitReason::GameOver }
+ FfiExitReason::ServerClosed => { ExitReason::ServerClosed }
+ FfiExitReason::YouAreKicked => { ExitReason::YouAreKicked }
+ FfiExitReason::YouAreBanned => { ExitReason::YouAreBanned }
+ FfiExitReason::Err => { ExitReason::Err }
+ }
+ }
+}
+
+impl From<ConnectionMessage> for FfiConnectionMessage {
+ fn from(value: ConnectionMessage) -> Self {
+ match value {
+ ConnectionMessage::Join(player) => {
+ let c_player : FfiPlayer = (&player).into();
+ FfiConnectionMessage {
+ tag: FfiConnectionMessageTag::Join,
+ data: FfiConnectionMessageUnion {
+ player: ManuallyDrop::new(c_player),
+ }
+ }
+ }
+ ConnectionMessage::RequestGameInfos => {
+ FfiConnectionMessage {
+ tag: FfiConnectionMessageTag::RequestGameInfos,
+ data: FfiConnectionMessageUnion { none: () }
+ }
+ }
+ ConnectionMessage::RequestLayoutConfigure => {
+ FfiConnectionMessage {
+ tag: FfiConnectionMessageTag::RequestLayoutConfigure,
+ data: FfiConnectionMessageUnion { none: () }
+ }
+ }
+ ConnectionMessage::RequestSkinPackage => {
+ FfiConnectionMessage {
+ tag: FfiConnectionMessageTag::RequestSkinPackage,
+ data: FfiConnectionMessageUnion { none: () }
+ }
+ }
+ ConnectionMessage::Ready => {
+ FfiConnectionMessage {
+ tag: FfiConnectionMessageTag::Ready,
+ data: FfiConnectionMessageUnion { none: () }
+ }
+ }
+ ConnectionMessage::Err => {
+ FfiConnectionMessage {
+ tag: FfiConnectionMessageTag::Err,
+ data: FfiConnectionMessageUnion { none: () }
+ }
+ }
+ }
+ }
+}
+
+impl From<FfiConnectionMessage> for ConnectionMessage {
+ fn from(value: FfiConnectionMessage) -> Self {
+ match value.tag {
+ FfiConnectionMessageTag::Join => unsafe {
+ ConnectionMessage::Join(value.data.player.deref().try_into().unwrap_or_default())
+ }
+ FfiConnectionMessageTag::RequestGameInfos => { ConnectionMessage::RequestGameInfos }
+ FfiConnectionMessageTag::RequestLayoutConfigure => { ConnectionMessage::RequestLayoutConfigure }
+ FfiConnectionMessageTag::RequestSkinPackage => { ConnectionMessage::RequestSkinPackage }
+ FfiConnectionMessageTag::Ready => { ConnectionMessage::Ready }
+ FfiConnectionMessageTag::Err => { ConnectionMessage::Err }
+ }
+ }
+}
+
+impl From<ConnectionResponseMessage> for FfiConnectionResponseMessage {
+ fn from(value: ConnectionResponseMessage) -> Self {
+ match value {
+ ConnectionResponseMessage::GameInfos(info) => {
+ FfiConnectionResponseMessage {
+ tag: FfiConnectionResponseMessageTag::GameInfos,
+ data: FfiConnectionResponseMessageUnion {
+ game_info: ManuallyDrop::new((&info).into())
+ }
+ }
+ }
+ ConnectionResponseMessage::Deny(fail) => {
+ FfiConnectionResponseMessage {
+ tag: FfiConnectionResponseMessageTag::Deny,
+ data: FfiConnectionResponseMessageUnion {
+ failed_message: ManuallyDrop::new((&fail).into())
+ }
+ }
+ }
+ ConnectionResponseMessage::Fail(fail) => {
+ FfiConnectionResponseMessage {
+ tag: FfiConnectionResponseMessageTag::Fail,
+ data: FfiConnectionResponseMessageUnion {
+ failed_message: ManuallyDrop::new((&fail).into())
+ }
+ }
+ }
+ ConnectionResponseMessage::Ok => {
+ FfiConnectionResponseMessage {
+ tag: FfiConnectionResponseMessageTag::Ok,
+ data: FfiConnectionResponseMessageUnion { none: () }
+ }
+ }
+ ConnectionResponseMessage::Welcome => {
+ FfiConnectionResponseMessage {
+ tag: FfiConnectionResponseMessageTag::Welcome,
+ data: FfiConnectionResponseMessageUnion { none: () }
+ }
+ }
+ ConnectionResponseMessage::Err => {
+ FfiConnectionResponseMessage {
+ tag: FfiConnectionResponseMessageTag::Err,
+ data: FfiConnectionResponseMessageUnion { none: () }
+ }
+ }
+ }
+ }
+}
+
+impl From<FfiConnectionResponseMessage> for ConnectionResponseMessage {
+ fn from(value: FfiConnectionResponseMessage) -> Self {
+ match value.tag {
+ FfiConnectionResponseMessageTag::GameInfos => unsafe {
+ ConnectionResponseMessage::GameInfos(value.data.game_info.deref().try_into().unwrap_or_default())
+ }
+ FfiConnectionResponseMessageTag::Deny => unsafe {
+ ConnectionResponseMessage::Deny(value.data.failed_message.deref().try_into().unwrap_or_default())
+ }
+ FfiConnectionResponseMessageTag::Fail => unsafe {
+ ConnectionResponseMessage::Fail(value.data.failed_message.deref().try_into().unwrap_or_default())
+ }
+ FfiConnectionResponseMessageTag::Ok => {
+ ConnectionResponseMessage::Ok
+ }
+ FfiConnectionResponseMessageTag::Welcome => {
+ ConnectionResponseMessage::Welcome
+ }
+ FfiConnectionResponseMessageTag::Err => {
+ ConnectionResponseMessage::Err
+ }
+ }
+ }
+}
+
+impl From<&JoinFailedMessage> for FfiJoinFailedMessage {
+ fn from(value: &JoinFailedMessage) -> Self {
+ match value {
+ JoinFailedMessage::ContainIdenticalPlayer => { FfiJoinFailedMessage::ContainIdenticalPlayer }
+ JoinFailedMessage::PlayerBanned => { FfiJoinFailedMessage::PlayerBanned }
+ JoinFailedMessage::GameLocked => { FfiJoinFailedMessage::GameLocked }
+ JoinFailedMessage::UnknownError => { FfiJoinFailedMessage::UnknownError }
+ }
+ }
+}
+
+impl From<&FfiJoinFailedMessage> for JoinFailedMessage {
+ fn from(value: &FfiJoinFailedMessage) -> Self {
+ match value {
+ FfiJoinFailedMessage::ContainIdenticalPlayer => { JoinFailedMessage::ContainIdenticalPlayer }
+ FfiJoinFailedMessage::PlayerBanned => { JoinFailedMessage::PlayerBanned }
+ FfiJoinFailedMessage::GameLocked => { JoinFailedMessage::GameLocked }
+ FfiJoinFailedMessage::UnknownError => { JoinFailedMessage::UnknownError }
+ }
+ }
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn free_control_message(msg: FfiControlMessage) {
+ let _ = msg;
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn free_game_message(msg: FfiGameMessage) {
+ let _ = msg;
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn free_exit_reason(msg: FfiExitReason) {
+ let _ = msg;
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn free_connection_message(msg: FfiConnectionMessage) {
+ let _ = msg;
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn free_connection_response_message(msg: FfiConnectionResponseMessage) {
+ let _ = msg;
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn free_join_failed_message(msg: FfiJoinFailedMessage) {
+ let _ = msg;
+} \ No newline at end of file
diff --git a/core/bindings/c_lang/src/data/ngpd_player.rs b/core/bindings/lang/clang/src/data/ngpd_player.rs
index 2ab615c..a1a8370 100644
--- a/core/bindings/c_lang/src/data/ngpd_player.rs
+++ b/core/bindings/lang/clang/src/data/ngpd_player.rs
@@ -32,10 +32,10 @@ impl From<Account> for FfiAccount {
}
}
-impl From<Player> for FfiPlayer {
- fn from(player: Player) -> Self {
- let account = FfiAccount::from(player.account);
- let customize = player.customize.map(|c| {
+impl From<&Player> for FfiPlayer {
+ fn from(player: &Player) -> Self {
+ let account = FfiAccount::from(player.account.clone());
+ let customize = player.clone().customize.map(|c| {
Box::into_raw(Box::new(FfiCustomize {
nickname: CString::new(c.nickname).unwrap().into_raw(),
color_hue: c.color_hue,
@@ -79,7 +79,7 @@ pub extern "C" fn player_register(id: *const c_char, password: *const c_char) ->
let pass_str = unsafe { CStr::from_ptr(password) }.to_string_lossy();
let player = Player::register(id_str.into_owned(), pass_str.into_owned());
- Box::into_raw(Box::new(FfiPlayer::from(player)))
+ Box::into_raw(Box::new(FfiPlayer::from(&player)))
}
#[unsafe(no_mangle)]
@@ -98,7 +98,7 @@ pub extern "C" fn player_set_nickname(player: *mut FfiPlayer, nickname: *const c
let mut rust_player : Player = unsafe { (&*player).try_into().unwrap() };
rust_player.nickname(&nickname_str);
- *unsafe { &mut *player } = FfiPlayer::from(rust_player);
+ *unsafe { &mut *player } = FfiPlayer::from(&rust_player);
}
#[unsafe(no_mangle)]
@@ -106,7 +106,7 @@ pub extern "C" fn player_set_hue(player: *mut FfiPlayer, hue: c_int) {
let mut rust_player : Player = unsafe { (&*player).try_into().unwrap() };
rust_player.hue(hue);
- *unsafe { &mut *player } = FfiPlayer::from(rust_player);
+ *unsafe { &mut *player } = FfiPlayer::from(&rust_player);
}
#[unsafe(no_mangle)]
@@ -116,7 +116,7 @@ pub extern "C" fn player_set_hsv(
let mut rust_player : Player = unsafe { (&*player).try_into().unwrap() };
rust_player.hsv(hue, saturation, value);
- *unsafe { &mut *player } = FfiPlayer::from(rust_player);
+ *unsafe { &mut *player } = FfiPlayer::from(&rust_player);
}
#[unsafe(no_mangle)]
diff --git a/core/bindings/lang/clang/src/lib.rs b/core/bindings/lang/clang/src/lib.rs
new file mode 100644
index 0000000..9a8fe37
--- /dev/null
+++ b/core/bindings/lang/clang/src/lib.rs
@@ -0,0 +1,2 @@
+pub mod converter;
+pub mod data;
diff --git a/core/examples/connect.rs b/core/examples/connect.rs
deleted file mode 100644
index e6f70c4..0000000
--- a/core/examples/connect.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-use std::sync::Arc;
-use log::LevelFilter::Trace;
-use nogamepads::logger_utils::logger_build;
-use nogamepads_core::data::controller::structs::ControllerData;
-use nogamepads_core::data::player::structs::Player;
-use nogamepads_core::service::tcp_network::pad_client::structs::PadClientNetwork;
-use nogamepads_core::service::tcp_network::utils::tokio_utils::build_tokio_runtime;
-
-fn main () {
- logger_build(Trace);
-
- let mut player = Player::register(
- env!("TEST_PLAYER_ACCOUNT").to_string(),
- env!("TEST_PLAYER_PASSWORD").to_string()
- );
-
- player.nickname(&env!("TEST_PLAYER_NICKNAME").to_string());
-
- let mut controller = ControllerData::default();
- controller.bind_player(player);
-
- let runtime = controller.runtime();
-
- let client = PadClientNetwork::build(Arc::clone(&runtime));
-
- build_tokio_runtime("Tokio Runtime".to_string()).block_on(client.build_entry())
-} \ No newline at end of file
diff --git a/core/examples/tcp_server.rs b/core/examples/tcp_server.rs
deleted file mode 100644
index 87e63c8..0000000
--- a/core/examples/tcp_server.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-use clap::CommandFactory;
-use nogamepads::logger_utils::logger_build;
-use nogamepads_core::data::game::game_cli::{process_game_cli, GameCli};
-use nogamepads_core::data::game::structs::{GameData, GameRuntimeDataArchive};
-use nogamepads_core::run_services;
-use nogamepads_core::service::cli_addition::runtime_consoles::RuntimeConsole;
-use nogamepads_core::service::tcp_network::pad_server::structs::PadServerNetwork;
-use std::sync::Arc;
-use log::LevelFilter::Trace;
-
-fn main () {
- logger_build(Trace);
-
- // Initialize game data
- let mut game = GameData::new();
- game.name("My Game".to_string());
- game.version("0.1".to_string());
- game.load_data(
- GameRuntimeDataArchive {
- banned: vec![],
- }
- );
-
- // Generate runtime from game data
- let runtime = game.runtime();
-
- // Establish TCP pad_server using runtime
- let tcp_server = PadServerNetwork::build(Arc::clone(&runtime));
-
- let server = tcp_server.build_entry();
-
- // Cmd
- let cmd = RuntimeConsole::build(
- GameCli::command(),
- "gamecli".to_string(),
- Arc::clone(&runtime),
- |runtime, cmd: GameCli| {
- process_game_cli(runtime, cmd)
- }
- ).build_entry();
-
- run_services!(server, cmd);
-} \ No newline at end of file