aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock8
-rw-r--r--Cargo.toml4
-rw-r--r--Project_Export.toml10
-rw-r--r--apps/client/src/bevy_plugins/plugin_client_app.rs6
-rw-r--r--apps/client/src/data/layout_data.rs2
-rw-r--r--apps/console/src/bin/padc.rs7
-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/data/ngpd_player.rs139
-rw-r--r--core/bindings/c_lang/src/lib.rs1
-rw-r--r--core/src/service/cli_addition/runtime_consoles.rs3
-rw-r--r--export/src/bin/export_project.rs6
13 files changed, 221 insertions, 17 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d982dc1..459802c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3204,6 +3204,14 @@ dependencies = [
]
[[package]]
+name = "nogamepads-c-bindings"
+version = "0.1.0"
+dependencies = [
+ "libc",
+ "nogamepads-core",
+]
+
+[[package]]
name = "nogamepads-client"
version = "0.1.0"
dependencies = [
diff --git a/Cargo.toml b/Cargo.toml
index 58161da..10b8c93 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,7 +16,9 @@ members = [
"core",
"apps/console",
"apps/client",
- "export"
+ "export",
+
+ "core/bindings/c_lang"
]
[workspace.package]
diff --git a/Project_Export.toml b/Project_Export.toml
index d07bc31..50896b1 100644
--- a/Project_Export.toml
+++ b/Project_Export.toml
@@ -15,6 +15,11 @@ powershell_complete = { raw = "./.cargo/resources/scripts/", target = "./bin/com
"install_completion_powershell.ps1"
] }
+# Headers
+headers = { raw = "./core/bindings/c_lang/headers/", target = "./lib", files = [
+ "ngpd_player.h"
+] }
+
# Items defined in [release.deps]
# It will search starting from the build directory and copy to the specified location in the target directory.
[release.deps]
@@ -22,4 +27,9 @@ powershell_complete = { raw = "./.cargo/resources/scripts/", target = "./bin/com
# Windows executables
win_exes = { raw = "./", target = "./bin", files = [
"padc.exe", "pad.exe"
+] }
+
+# Windows dynamic link libraries
+dlls = { raw = "./", target = "./lib", files = [
+ "nogamepads_c.dll"
] } \ No newline at end of file
diff --git a/apps/client/src/bevy_plugins/plugin_client_app.rs b/apps/client/src/bevy_plugins/plugin_client_app.rs
index e7d60d2..c95d0a4 100644
--- a/apps/client/src/bevy_plugins/plugin_client_app.rs
+++ b/apps/client/src/bevy_plugins/plugin_client_app.rs
@@ -1,9 +1,6 @@
use std::sync::{Arc, Mutex};
-use bevy::app::FixedLast;
-use bevy::input::common_conditions::input_just_pressed;
use bevy::log::info;
-use bevy::log::tracing::Instrument;
-use bevy::prelude::{App, AppExit, Commands, Component, EventReader, IntoScheduleConfigs, KeyCode, NextState, OnEnter, OnExit, Plugin, PreStartup, Query, ResMut, Startup, State, States, Update};
+use bevy::prelude::{App, Commands, Component, OnEnter, Plugin, PreStartup, Query, ResMut, Startup, States};
use bevy_tokio_tasks::TokioTasksRuntime;
use nogamepads::entry_mutex;
use nogamepads_core::data::controller::controller_data::ControllerData;
@@ -12,6 +9,7 @@ use nogamepads_core::data::player::player_data::Player;
use nogamepads_core::service::tcp_network::pad_client::pad_client_service::PadClientNetwork;
use crate::bevy_plugins::plugin_client_app::GameState::Exiting;
+#[allow(dead_code)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States)]
enum GameState {
#[default]
diff --git a/apps/client/src/data/layout_data.rs b/apps/client/src/data/layout_data.rs
index f960b41..9c283e5 100644
--- a/apps/client/src/data/layout_data.rs
+++ b/apps/client/src/data/layout_data.rs
@@ -13,7 +13,7 @@ pub struct LayoutXml {
}
#[derive(Debug, Deserialize)]
-struct Preload {
+pub struct Preload {
#[serde(rename = "sound", default)]
pub sounds: Vec<Asset>,
diff --git a/apps/console/src/bin/padc.rs b/apps/console/src/bin/padc.rs
index e44f0f9..e34fee1 100644
--- a/apps/console/src/bin/padc.rs
+++ b/apps/console/src/bin/padc.rs
@@ -11,14 +11,10 @@ use std::net::SocketAddr;
use std::path::PathBuf;
use std::process::exit;
use std::str::FromStr;
-use std::sync::{Arc, Mutex};
+use std::sync::{Arc};
use std::sync::atomic::Ordering::SeqCst;
-use std::time::Duration;
use clap_complete::{generate, Shell};
use log::{info, LevelFilter};
-use tokio::{select, spawn};
-use tokio::signal::ctrl_c;
-use tokio::time::sleep;
use nogamepads::entry_mutex;
use nogamepads::logger_utils::logger_build;
use nogamepads_core::data::controller::controller_cli::{process_controller_cli, ControllerCli};
@@ -31,7 +27,6 @@ use nogamepads_core::service::service_runner::{NoGamepadsService, ServiceRunner}
use nogamepads_core::service::tcp_network::DEFAULT_PORT;
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;
#[derive(Parser, Debug)]
#[command(version, color = ColorChoice::Auto)]
diff --git a/core/bindings/c_lang/Cargo.toml b/core/bindings/c_lang/Cargo.toml
new file mode 100644
index 0000000..a0ee61f
--- /dev/null
+++ b/core/bindings/c_lang/Cargo.toml
@@ -0,0 +1,12 @@
+[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
new file mode 100644
index 0000000..00fbe5b
--- /dev/null
+++ b/core/bindings/c_lang/headers/ngpd_player.h
@@ -0,0 +1,39 @@
+#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
new file mode 100644
index 0000000..32af6d8
--- /dev/null
+++ b/core/bindings/c_lang/src/data/mod.rs
@@ -0,0 +1 @@
+pub mod ngpd_player; \ No newline at end of file
diff --git a/core/bindings/c_lang/src/data/ngpd_player.rs b/core/bindings/c_lang/src/data/ngpd_player.rs
new file mode 100644
index 0000000..2ab615c
--- /dev/null
+++ b/core/bindings/c_lang/src/data/ngpd_player.rs
@@ -0,0 +1,139 @@
+use std::ffi::{CStr, CString};
+use std::os::raw::{c_char, c_double, c_int};
+use std::ptr;
+use nogamepads_core::data::player::player_data::{Account, Customize, Player};
+
+#[repr(C)]
+pub struct FfiAccount {
+ id: *mut c_char,
+ player_hash: *mut c_char,
+}
+
+#[repr(C)]
+pub struct FfiCustomize {
+ nickname: *mut c_char,
+ color_hue: c_int,
+ color_saturation: c_double,
+ color_value: c_double,
+}
+
+#[repr(C)]
+pub struct FfiPlayer {
+ account: FfiAccount,
+ customize: *mut FfiCustomize,
+}
+
+impl From<Account> for FfiAccount {
+ fn from(acc: Account) -> Self {
+ FfiAccount {
+ id: CString::new(acc.id).unwrap().into_raw(),
+ player_hash: CString::new(acc.player_hash).unwrap().into_raw(),
+ }
+ }
+}
+
+impl From<Player> for FfiPlayer {
+ fn from(player: Player) -> Self {
+ let account = FfiAccount::from(player.account);
+ let customize = player.customize.map(|c| {
+ Box::into_raw(Box::new(FfiCustomize {
+ nickname: CString::new(c.nickname).unwrap().into_raw(),
+ color_hue: c.color_hue,
+ color_saturation: c.color_saturation,
+ color_value: c.color_value,
+ }))
+ }).unwrap_or(ptr::null_mut());
+
+ FfiPlayer { account, customize }
+ }
+}
+
+impl TryFrom<&FfiPlayer> for Player {
+ type Error = ();
+
+ fn try_from(ffi: &FfiPlayer) -> Result<Self, Self::Error> {
+ let account = Account {
+ id: unsafe { CStr::from_ptr(ffi.account.id) }.to_str().map_err(|_| ())?.to_owned(),
+ player_hash: unsafe { CStr::from_ptr(ffi.account.player_hash) }.to_str().map_err(|_| ())?.to_owned(),
+ };
+
+ let customize = if !ffi.customize.is_null() {
+ let c = unsafe { &*ffi.customize };
+ Some(Customize {
+ nickname: unsafe { CStr::from_ptr(c.nickname) }.to_str().map_err(|_| ())?.to_owned(),
+ color_hue: c.color_hue,
+ color_saturation: c.color_saturation,
+ color_value: c.color_value,
+ })
+ } else {
+ None
+ };
+
+ Ok(Player { account, customize })
+ }
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn player_register(id: *const c_char, password: *const c_char) -> *mut FfiPlayer {
+ let id_str = unsafe { CStr::from_ptr(id) }.to_string_lossy();
+ 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)))
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn player_check(player: *const FfiPlayer, password: *const c_char) -> bool {
+ let player = unsafe { &*player };
+ let pass_str = unsafe { CStr::from_ptr(password) }.to_string_lossy();
+
+ Player::try_from(player)
+ .map(|p| p.check(pass_str.into_owned()))
+ .unwrap_or(false)
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn player_set_nickname(player: *mut FfiPlayer, nickname: *const c_char) {
+ let nickname_str = unsafe { CStr::from_ptr(nickname) }.to_string_lossy().into_owned();
+ let mut rust_player : Player = unsafe { (&*player).try_into().unwrap() };
+
+ rust_player.nickname(&nickname_str);
+ *unsafe { &mut *player } = FfiPlayer::from(rust_player);
+}
+
+#[unsafe(no_mangle)]
+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(no_mangle)]
+pub extern "C" fn player_set_hsv(
+ player: *mut FfiPlayer, hue: c_int, saturation: c_double, value: c_double
+) {
+ let mut rust_player : Player = unsafe { (&*player).try_into().unwrap() };
+
+ rust_player.hsv(hue, saturation, value);
+ *unsafe { &mut *player } = FfiPlayer::from(rust_player);
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn player_free(player: *mut FfiPlayer) {
+ if player.is_null() { return; }
+
+ let ffi_player = unsafe { Box::from_raw(player) };
+
+ // Free account strings
+ unsafe {
+ let _ = CString::from_raw(ffi_player.account.id);
+ let _ = CString::from_raw(ffi_player.account.player_hash);
+ }
+
+ // Free customize if present
+ if !ffi_player.customize.is_null() {
+ let ffi_custom = unsafe { Box::from_raw(ffi_player.customize) };
+ unsafe { let _ = CString::from_raw(ffi_custom.nickname); };
+ }
+} \ No newline at end of file
diff --git a/core/bindings/c_lang/src/lib.rs b/core/bindings/c_lang/src/lib.rs
new file mode 100644
index 0000000..12e35bb
--- /dev/null
+++ b/core/bindings/c_lang/src/lib.rs
@@ -0,0 +1 @@
+pub mod data; \ No newline at end of file
diff --git a/core/src/service/cli_addition/runtime_consoles.rs b/core/src/service/cli_addition/runtime_consoles.rs
index c96c0f2..2b2984b 100644
--- a/core/src/service/cli_addition/runtime_consoles.rs
+++ b/core/src/service/cli_addition/runtime_consoles.rs
@@ -1,10 +1,9 @@
-use std::process::exit;
use crate::service::cli_addition::utils::read_cli;
use clap::{Command, FromArgMatches};
use std::sync::{Arc, Mutex};
use std::time::Duration;
use log::{info, warn};
-use tokio::{count, join, select, spawn};
+use tokio::{join, select, spawn};
use tokio::signal::ctrl_c;
use tokio::time::sleep;
use crate::service::service_runner::NoGamepadsService;
diff --git a/export/src/bin/export_project.rs b/export/src/bin/export_project.rs
index 6c6eaaf..b83e54b 100644
--- a/export/src/bin/export_project.rs
+++ b/export/src/bin/export_project.rs
@@ -29,7 +29,7 @@ pub fn main() {
let version = if let Some(v) = args.get(1) { v.to_string() } else { env!("PROJECT_VERSION").to_string() };
let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).parent().unwrap().to_path_buf();
- let toml_config = root.join("../../../Project_Export.toml");
+ let toml_config = root.join("./Project_Export.toml");
let config: Config = toml::from_str(fs::read_to_string(toml_config).unwrap().as_str())
.expect("Failed to parse TOML");
@@ -48,14 +48,14 @@ pub fn main() {
let _ = remove_dir_all(&export_version_dir);
for data in config.release.root {
- println!("Releasing \"{}\" files", data.0);
+ println!("Releasing \"{}\"", data.0);
let raw_path = root.join(data.1.raw);
let target_path = export_version_dir.join(data.1.target);
copy_files(&raw_path, &target_path, data.1.files);
}
for data in config.release.deps {
- println!("Releasing \"{}\" files", data.0);
+ println!("Releasing \"{}\"", data.0);
let raw_path = target_dir.join(data.1.raw);
let target_path = export_version_dir.join(data.1.target);
copy_files(&raw_path, &target_path, data.1.files);