diff options
| author | 1992414357@qq.com <1992414357@qq.com> | 2025-06-09 01:44:36 +0800 |
|---|---|---|
| committer | 1992414357@qq.com <1992414357@qq.com> | 2025-06-09 01:44:36 +0800 |
| commit | 49192dbb98e0ab1f2a66b4786fac86d63f69be64 (patch) | |
| tree | 7cdf27c7cab5fb6b1aabc2ac7c44b7b492558945 | |
| parent | c9dbba0d288becb7f05cebe526be25c76e5a850a (diff) | |
重构所有部分
180 files changed, 3181 insertions, 6093 deletions
diff --git a/.cargo/config.toml b/.cargo/config.toml index b4690fc..cabad87 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -4,7 +4,7 @@ target-dir = "./.cargo/shared/target" [env] PROJECT_VERSION = { value = "0.1.0" } -TEST_PLAYER_ACCOUNT = { value = "Juliet_Smile" } -TEST_PLAYER_PASSWORD = { value = "juliet09881652@@__" } +TEST_PLAYER_ACCOUNT = { value = "Ame.Na.LISA" } +TEST_PLAYER_PASSWORD = { value = "amenalisa@@:P_QWQ" } -TEST_PLAYER_NICKNAME = { value = "juliet" }
\ No newline at end of file +TEST_PLAYER_NICKNAME = { value = "ame_na_lisa" }
\ No newline at end of file diff --git a/.idea/runConfigurations/Export_Project.xml b/.idea/runConfigurations/Export_Project.xml index 8a06dae..c0beea1 100644 --- a/.idea/runConfigurations/Export_Project.xml +++ b/.idea/runConfigurations/Export_Project.xml @@ -1,7 +1,7 @@ <component name="ProjectRunConfigurationManager"> <configuration default="false" name="Export Project" type="CargoCommandRunConfiguration" factoryName="Cargo Command" folderName="Export"> <option name="buildProfileId" value="dev" /> - <option name="command" value="run --manifest-path .\export\Cargo.toml --bin export_project" /> + <option name="command" value="run --manifest-path ./export/Cargo.toml --bin export_project" /> <option name="workingDirectory" value="file://$PROJECT_DIR$" /> <envs /> <option name="emulateTerminal" value="true" /> diff --git a/.idea/runConfigurations/Run_Client_Console.xml b/.idea/runConfigurations/Run_Client_Console.xml index 01b3f83..171319c 100644 --- a/.idea/runConfigurations/Run_Client_Console.xml +++ b/.idea/runConfigurations/Run_Client_Console.xml @@ -12,8 +12,6 @@ <option name="backtrace" value="SHORT" /> <option name="isRedirectInput" value="false" /> <option name="redirectInputPath" value="" /> - <method v="2"> - <option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" /> - </method> + <method v="2" /> </configuration> </component>
\ No newline at end of file diff --git a/.idea/runConfigurations/Run_NoGamepads_Client__Win_.xml b/.idea/runConfigurations/Run_NoGamepads_Client__Win_.xml deleted file mode 100644 index 943b3ad..0000000 --- a/.idea/runConfigurations/Run_NoGamepads_Client__Win_.xml +++ /dev/null @@ -1,19 +0,0 @@ -<component name="ProjectRunConfigurationManager"> - <configuration default="false" name="Run NoGamepads Client (Win)" type="CargoCommandRunConfiguration" factoryName="Cargo Command" folderName="Run"> - <option name="command" value="run --package nogamepads-client --bin nogamepads-client" /> - <option name="workingDirectory" value="file://$PROJECT_DIR$" /> - <envs /> - <option name="emulateTerminal" value="true" /> - <option name="channel" value="DEFAULT" /> - <option name="requiredFeatures" value="true" /> - <option name="allFeatures" value="false" /> - <option name="withSudo" value="false" /> - <option name="buildTarget" value="REMOTE" /> - <option name="backtrace" value="SHORT" /> - <option name="isRedirectInput" value="false" /> - <option name="redirectInputPath" value="" /> - <method v="2"> - <option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" /> - </method> - </configuration> -</component>
\ No newline at end of file diff --git a/.idea/runConfigurations/Run_Server_Console.xml b/.idea/runConfigurations/Run_Server_Console.xml index ed24c68..3d7bde8 100644 --- a/.idea/runConfigurations/Run_Server_Console.xml +++ b/.idea/runConfigurations/Run_Server_Console.xml @@ -12,8 +12,6 @@ <option name="backtrace" value="SHORT" /> <option name="isRedirectInput" value="false" /> <option name="redirectInputPath" value="" /> - <method v="2"> - <option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" /> - </method> + <method v="2" /> </configuration> </component>
\ No newline at end of file @@ -427,7 +427,7 @@ dependencies = [ "bevy_transform", "bevy_utils", "blake3", - "derive_more", + "derive_more 1.0.0", "downcast-rs", "either", "petgraph", @@ -484,7 +484,7 @@ dependencies = [ "bitflags 2.9.1", "blake3", "crossbeam-channel", - "derive_more", + "derive_more 1.0.0", "disqualified", "downcast-rs", "either", @@ -542,7 +542,7 @@ dependencies = [ "bevy_math", "bevy_reflect", "bytemuck", - "derive_more", + "derive_more 1.0.0", "encase", "serde", "thiserror 2.0.12", @@ -624,7 +624,7 @@ dependencies = [ "bitflags 2.9.1", "bumpalo", "concurrent-queue", - "derive_more", + "derive_more 1.0.0", "disqualified", "fixedbitset", "indexmap", @@ -787,7 +787,7 @@ dependencies = [ "bevy_platform", "bevy_reflect", "bevy_utils", - "derive_more", + "derive_more 1.0.0", "log", "smol_str", "thiserror 2.0.12", @@ -890,7 +890,7 @@ checksum = "f1a3a926d02dc501c6156a047510bdb538dcb1fa744eeba13c824b73ba88de55" dependencies = [ "approx", "bevy_reflect", - "derive_more", + "derive_more 1.0.0", "glam", "itertools 0.14.0", "libm", @@ -959,7 +959,7 @@ dependencies = [ "bevy_window", "bitflags 2.9.1", "bytemuck", - "derive_more", + "derive_more 1.0.0", "fixedbitset", "nonmax", "offset-allocator", @@ -1030,7 +1030,7 @@ dependencies = [ "bevy_ptr", "bevy_reflect_derive", "bevy_utils", - "derive_more", + "derive_more 1.0.0", "disqualified", "downcast-rs", "erased-serde", @@ -1087,7 +1087,7 @@ dependencies = [ "bitflags 2.9.1", "bytemuck", "codespan-reporting", - "derive_more", + "derive_more 1.0.0", "downcast-rs", "encase", "fixedbitset", @@ -1138,7 +1138,7 @@ dependencies = [ "bevy_render", "bevy_transform", "bevy_utils", - "derive_more", + "derive_more 1.0.0", "serde", "thiserror 2.0.12", "uuid", @@ -1167,7 +1167,7 @@ dependencies = [ "bevy_window", "bitflags 2.9.1", "bytemuck", - "derive_more", + "derive_more 1.0.0", "fixedbitset", "nonmax", "radsort", @@ -1216,7 +1216,7 @@ dependencies = [ "cfg-if", "concurrent-queue", "crossbeam-queue", - "derive_more", + "derive_more 1.0.0", "futures-channel", "futures-lite", "heapless", @@ -1282,7 +1282,7 @@ dependencies = [ "bevy_reflect", "bevy_tasks", "bevy_utils", - "derive_more", + "derive_more 1.0.0", "serde", "thiserror 2.0.12", ] @@ -1314,7 +1314,7 @@ dependencies = [ "bevy_utils", "bevy_window", "bytemuck", - "derive_more", + "derive_more 1.0.0", "nonmax", "smallvec", "taffy", @@ -1581,25 +1581,6 @@ dependencies = [ ] [[package]] -name = "cbindgen" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "975982cdb7ad6a142be15bdf84aea7ec6a9e5d4d797c004d43185b24cfe4e684" -dependencies = [ - "clap", - "heck", - "indexmap", - "log", - "proc-macro2", - "quote", - "serde", - "serde_json", - "syn", - "tempfile", - "toml 0.8.22", -] - -[[package]] name = "cc" version = "1.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1795,6 +1776,15 @@ dependencies = [ ] [[package]] +name = "convert_case" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" +dependencies = [ + "unicode-segmentation", +] + +[[package]] name = "core-foundation" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1959,6 +1949,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] +name = "crossterm" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" +dependencies = [ + "bitflags 2.9.1", + "crossterm_winapi", + "derive_more 2.0.1", + "document-features", + "mio", + "parking_lot", + "rustix 1.0.7", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + +[[package]] name = "crunchy" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2029,7 +2046,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "derive_more-impl", + "derive_more-impl 1.0.0", +] + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl 2.0.1", ] [[package]] @@ -2045,6 +2071,18 @@ dependencies = [ ] [[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3067,6 +3105,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", + "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] @@ -3204,14 +3243,6 @@ dependencies = [ ] [[package]] -name = "nogamepads-c" -version = "0.1.0" -dependencies = [ - "cbindgen", - "nogamepads-core", -] - -[[package]] name = "nogamepads-client" version = "0.1.0" dependencies = [ @@ -3226,12 +3257,15 @@ name = "nogamepads-console" version = "0.1.0" dependencies = [ "clap", + "crossterm", + "log", + "nogamepads", "nogamepads-core", "prettytable-rs", "rand 0.9.1", - "rpassword", "serde", "serde_yaml", + "tokio", ] [[package]] @@ -3247,6 +3281,7 @@ dependencies = [ "prettytable-rs", "serde", "sha1", + "shell-words", "tokio", ] @@ -3255,7 +3290,7 @@ name = "nogamepads-export" version = "0.0.0" dependencies = [ "serde", - "toml 0.7.8", + "toml", ] [[package]] @@ -4124,27 +4159,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" [[package]] -name = "rpassword" -version = "7.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d4c8b64f049c6721ec8ccec37ddfc3d641c4a7fca57e8f2a89de509c73df39" -dependencies = [ - "libc", - "rtoolbox", - "windows-sys 0.59.0", -] - -[[package]] -name = "rtoolbox" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cc970b249fbe527d6e02e0a227762c9108b2f49d81094fe357ffc6d14d7f6f" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4334,6 +4348,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[package]] name = "signal-hook-registry" version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4534,19 +4569,6 @@ dependencies = [ ] [[package]] -name = "tempfile" -version = "3.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" -dependencies = [ - "fastrand", - "getrandom 0.3.3", - "once_cell", - "rustix 1.0.7", - "windows-sys 0.59.0", -] - -[[package]] name = "term" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4685,18 +4707,6 @@ dependencies = [ ] [[package]] -name = "toml" -version = "0.8.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.22.26", -] - -[[package]] name = "toml_datetime" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4725,20 +4735,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" dependencies = [ "indexmap", - "serde", - "serde_spanned", "toml_datetime", - "toml_write", "winnow 0.7.10", ] [[package]] -name = "toml_write" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" - -[[package]] name = "tracing" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -15,7 +15,6 @@ edition = "2024" members = [ "core", "console", - "bindings/c", "client", "export" ] diff --git a/Config_Export.toml b/Config_Export.toml index 502cc11..310b7f6 100644 --- a/Config_Export.toml +++ b/Config_Export.toml @@ -6,4 +6,4 @@ license = { raw = "./", target = "./", files = ["LICENSE-LGPL-2", "LICENSE-THIRD [release.deps] header = { raw = "./", target = "./bridge", files = ["nogamepads_cpp.h", "nogamepads.h"] } dll = { raw = "./", target = "./bridge", files = ["nogamepads_lib_c.dll"] } -binaries = { raw = "./", target = "./bin", files = ["nogpadc.exe", "nogpads.exe"] }
\ No newline at end of file +binaries = { raw = "./", target = "./bin", files = ["padc.exe"] }
\ No newline at end of file diff --git a/LICENSE-THIRD-PARTY b/LICENSE-THIRD-PARTY index e516064..eb99fb1 100644 --- a/LICENSE-THIRD-PARTY +++ b/LICENSE-THIRD-PARTY @@ -6,6 +6,7 @@ This project uses third-party components with the following licenses: [MIT License Dependencies] ----------------------------------------------------------------------- * bincode +* crossterm * tokio * bevy (original license: Apache-2.0 OR MIT) * chrono (original license: Apache-2.0 OR MIT) @@ -31,6 +32,7 @@ Copyright (c) 2013-2014 The Rust Project Developers. * chrono - Copyright (c) 2014, Kang Seonghoon. * clap - Copyright (c) The clap Project Developer(s). * clearscreen - Copyright (c) The clearscreen Project Developer(s). +* crossterm - Copyright (c) 2019 Timon. * env_logger - Copyright (c) The env_logger Project Developer(s). * hex - Copyright (c) 2015-2020 The rust-hex Developers. * log - Copyright (c) The log Project Developer(s). @@ -62,188 +64,6 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -[Apache-2.0 License Dependencies] ------------------------------------------------------------------------ -* rpassword - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - [BSD-3-Clause License Dependencies] ----------------------------------------------------------------------- * prettytable-rs diff --git a/bindings/c/Cargo.toml b/bindings/c/Cargo.toml deleted file mode 100644 index 81bde85..0000000 --- a/bindings/c/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "nogamepads-c" -edition = "2024" -version.workspace = true - -[dependencies] -nogamepads-core = { path = "../../core" } - -[build-dependencies] -cbindgen = "0.29.0" - -[lib] -name = "nogamepads_lib_c" -crate-type = [ "cdylib", "staticlib"]
\ No newline at end of file diff --git a/bindings/c/build.rs b/bindings/c/build.rs deleted file mode 100644 index b5770a0..0000000 --- a/bindings/c/build.rs +++ /dev/null @@ -1,47 +0,0 @@ -use cbindgen::{generate_with_config, Config, ExportConfig, Language, ParseConfig, ParseExpandConfig}; -use std::env; - -fn main() { - let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); - - let config_c = Config { - language: Language::C, - header: Some("/* NoGamepads C Bindings. */".to_string()), - - parse: ParseConfig { - include: Some(vec!["*".to_string()]), - expand: ParseExpandConfig { - all_features: true, - ..Default::default() - }, - ..Default::default() - }, - - export: ExportConfig { - include: vec![ - "ConnectionMessageC".to_string(), - "ConnectionCallbackMessageC".to_string(), - "ControlMessageC".to_string(), - "GameMessageC".to_string(), - - "GameProfileC".to_string(), - "PlayerInfoC".to_string(), - ], - ..Default::default() - }, - ..Config::default() - }; - - let mut config_cpp = config_c.clone(); - config_cpp.language = Language::Cxx; - config_cpp.include_version = true; - config_cpp.header = Some("/* NoGamepads C++ Bindings. */".to_string()); - config_cpp.namespace = Some("nogamepads".to_string()); - - generate_with_config(&crate_dir, config_c) - .expect("Could not generate nogamepads.h") - .write_to_file("../../.cargo/shared/target/export/deps/nogamepads.h"); - generate_with_config(&crate_dir, config_cpp) - .expect("Could not generate nogamepads_cpp.h") - .write_to_file("../../.cargo/shared/target/export/deps/nogamepads_cpp.h"); -}
\ No newline at end of file diff --git a/bindings/c/src/data_c/common.rs b/bindings/c/src/data_c/common.rs deleted file mode 100644 index 58c34c4..0000000 --- a/bindings/c/src/data_c/common.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[repr(C)] -#[allow(unused_imports)] -#[derive(Copy, Clone)] -pub struct KeyData { - pub(crate) key: u8 -}
\ No newline at end of file diff --git a/bindings/c/src/data_c/connection_callback_message_c.rs b/bindings/c/src/data_c/connection_callback_message_c.rs deleted file mode 100644 index 9ded18b..0000000 --- a/bindings/c/src/data_c/connection_callback_message_c.rs +++ /dev/null @@ -1,129 +0,0 @@ -use crate::data_c::game_profile_c::GameProfileC; -use nogamepads_lib_rs::pad_data::pad_messages::nogamepads_messages::{ConnectionCallbackMessage, ConnectionErrorType}; -use std::ffi::c_void; -use std::mem::ManuallyDrop; -use std::ptr::null_mut; - -#[repr(C)] -#[allow(unused_imports)] -pub struct ConnectionCallbackMessageC { - pub tag: ConnCallbackMsgCTag, - pub data: ConnCallbackMsgCUnion, -} - -#[repr(C)] -#[allow(unused_imports)] -pub enum ConnCallbackMsgCTag { - Profile, Deny, Fail, Ok, Welcome, Err -} - -#[repr(C)] -#[allow(unused_imports)] -pub union ConnCallbackMsgCUnion { - nul: *mut c_void, - profile: ManuallyDrop<GameProfileC>, - conn_err: ConnErrTypeC -} - -#[repr(C)] -#[allow(unused_imports)] -#[derive(Copy, Clone)] -pub enum ConnErrTypeC { - ContainSamePlayer, PlayerBanned, Timeout, GameLocked, WhatTheHell -} - -impl From<ConnErrTypeC> for ConnectionErrorType { - fn from(value: ConnErrTypeC) -> Self { - match value { - ConnErrTypeC::ContainSamePlayer => { ConnectionErrorType::ContainSamePlayer } - ConnErrTypeC::PlayerBanned => { ConnectionErrorType::PlayerBanned } - ConnErrTypeC::Timeout => { ConnectionErrorType::Timeout } - ConnErrTypeC::GameLocked => { ConnectionErrorType::GameLocked } - ConnErrTypeC::WhatTheHell => { ConnectionErrorType::WhatTheHell } - } - } -} - -impl From<ConnectionErrorType> for ConnErrTypeC { - fn from(value: ConnectionErrorType) -> Self { - match value { - ConnectionErrorType::ContainSamePlayer => { ConnErrTypeC::ContainSamePlayer } - ConnectionErrorType::PlayerBanned => { ConnErrTypeC::PlayerBanned } - ConnectionErrorType::Timeout => { ConnErrTypeC::Timeout } - ConnectionErrorType::GameLocked => { ConnErrTypeC::GameLocked } - ConnectionErrorType::WhatTheHell => { ConnErrTypeC::WhatTheHell } - } - } -} - -impl From<ConnectionCallbackMessageC> for ConnectionCallbackMessage { - fn from(mut value: ConnectionCallbackMessageC) -> Self { - match value.tag { - ConnCallbackMsgCTag::Profile => unsafe { - let profile = ManuallyDrop::take(&mut value.data.profile); - ConnectionCallbackMessage::Profile(profile.into()) - } - ConnCallbackMsgCTag::Deny => unsafe { - ConnectionCallbackMessage::Deny(value.data.conn_err.into()) - } - ConnCallbackMsgCTag::Fail => unsafe { - ConnectionCallbackMessage::Fail(value.data.conn_err.into()) - } - ConnCallbackMsgCTag::Ok => { - ConnectionCallbackMessage::Ok - - } - ConnCallbackMsgCTag::Welcome => { - ConnectionCallbackMessage::Welcome - } - ConnCallbackMsgCTag::Err => { - ConnectionCallbackMessage::Err - } - } - } -} - -impl From<ConnectionCallbackMessage> for ConnectionCallbackMessageC { - fn from(value: ConnectionCallbackMessage) -> Self { - match value { - ConnectionCallbackMessage::Profile(profile) => { - ConnectionCallbackMessageC { - tag: ConnCallbackMsgCTag::Profile, - data: ConnCallbackMsgCUnion { - profile: ManuallyDrop::new(profile.into()) - } - } - } - ConnectionCallbackMessage::Deny(conn_err) => { - ConnectionCallbackMessageC { - tag: ConnCallbackMsgCTag::Deny, - data: ConnCallbackMsgCUnion { conn_err: conn_err.into() } - } - } - ConnectionCallbackMessage::Fail(conn_err) => { - ConnectionCallbackMessageC { - tag: ConnCallbackMsgCTag::Fail, - data: ConnCallbackMsgCUnion { conn_err: conn_err.into() } - } - } - ConnectionCallbackMessage::Ok => { - ConnectionCallbackMessageC { - tag: ConnCallbackMsgCTag::Ok, - data: ConnCallbackMsgCUnion { nul: null_mut() } - } - } - ConnectionCallbackMessage::Welcome => { - ConnectionCallbackMessageC { - tag: ConnCallbackMsgCTag::Welcome, - data: ConnCallbackMsgCUnion { nul: null_mut() } - } - } - ConnectionCallbackMessage::Err => { - ConnectionCallbackMessageC { - tag: ConnCallbackMsgCTag::Err, - data: ConnCallbackMsgCUnion { nul: null_mut() } - } - } - } - } -}
\ No newline at end of file diff --git a/bindings/c/src/data_c/connection_message_c.rs b/bindings/c/src/data_c/connection_message_c.rs deleted file mode 100644 index b3b54d4..0000000 --- a/bindings/c/src/data_c/connection_message_c.rs +++ /dev/null @@ -1,95 +0,0 @@ -use crate::data_c::connection_message_c::ConnMsgCTag::{Connection, Ready, RequestLayoutConfigure, RequestProfile, RequestSkinPackage}; -use std::ffi::c_void; -use std::mem::ManuallyDrop; -use std::ptr::null_mut; -use nogamepads_lib_rs::pad_data::pad_messages::nogamepads_messages::ConnectionMessage; -use nogamepads_lib_rs::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; - -#[repr(C)] -#[allow(unused_imports)] -pub struct ConnectionMessageC { - pub tag: ConnMsgCTag, - pub data: ConnMsgCUnion -} - -#[repr(C)] -#[allow(unused_imports)] -pub enum ConnMsgCTag { - Connection, RequestProfile, RequestLayoutConfigure, RequestSkinPackage, Ready, Err -} - -#[repr(C)] -#[allow(unused_imports)] -pub union ConnMsgCUnion { - nul: *mut c_void, - info: ManuallyDrop<PlayerInfo> -} - -impl From<ConnectionMessageC> for ConnectionMessage { - fn from(mut value: ConnectionMessageC) -> Self { - match value.tag { - Connection => unsafe { - let info = ManuallyDrop::take(&mut value.data.info); - ConnectionMessage::Connection(info) - } - RequestProfile => { - ConnectionMessage::RequestProfile - } - RequestLayoutConfigure => { - ConnectionMessage::RequestLayoutConfigure - } - RequestSkinPackage => { - ConnectionMessage::RequestSkinPackage - } - Ready => { - ConnectionMessage::Ready - } - ConnMsgCTag::Err => { - ConnectionMessage::Err - } - } - } -} - -impl From<ConnectionMessage> for ConnectionMessageC { - fn from(value: ConnectionMessage) -> Self { - match value { - ConnectionMessage::Connection(info) => { - ConnectionMessageC { - tag: Connection, - data: ConnMsgCUnion { info: ManuallyDrop::new(info) } - } - } - ConnectionMessage::RequestProfile => { - ConnectionMessageC { - tag: RequestProfile, - data: ConnMsgCUnion { nul: null_mut() } - } - } - ConnectionMessage::RequestLayoutConfigure => { - ConnectionMessageC { - tag: RequestLayoutConfigure, - data: ConnMsgCUnion { nul: null_mut() } - } - } - ConnectionMessage::RequestSkinPackage => { - ConnectionMessageC { - tag: RequestSkinPackage, - data: ConnMsgCUnion { nul: null_mut() } - } - } - ConnectionMessage::Ready => { - ConnectionMessageC { - tag: Ready, - data: ConnMsgCUnion { nul: null_mut() } - } - } - ConnectionMessage::Err => { - ConnectionMessageC { - tag: ConnMsgCTag::Err, - data: ConnMsgCUnion { nul: null_mut() } - } - } - } - } -}
\ No newline at end of file diff --git a/bindings/c/src/data_c/control_message_c.rs b/bindings/c/src/data_c/control_message_c.rs deleted file mode 100644 index 6868459..0000000 --- a/bindings/c/src/data_c/control_message_c.rs +++ /dev/null @@ -1,150 +0,0 @@ -use crate::data_c::common::KeyData; -use crate::{str_c_to_rs, str_rs_to_c}; -use nogamepads_lib_rs::pad_data::pad_messages::nogamepads_messages::ControlMessage; -use std::ffi::{c_char, c_void}; -use std::ptr::null_mut; - -#[repr(C)] -#[allow(unused_imports)] -pub struct ControlMessageC { - pub tag: CtrlMsgCTag, - pub data: CtrlMsgCUnion -} - -#[repr(C)] -#[allow(unused_imports)] -pub enum CtrlMsgCTag { - Msg, Pressed, Released, Axis, Dir, Exit, Err -} - -#[repr(C)] -#[allow(unused_imports)] -pub union CtrlMsgCUnion { - nul: *mut c_void, - key: KeyData, - axis: AxisData, - dir: DirData, - str: StrData -} - -#[repr(C)] -#[allow(unused_imports)] -#[derive(Copy, Clone)] -pub struct AxisData { - key: u8, - ax: f64 -} - -#[repr(C)] -#[allow(unused_imports)] -#[derive(Copy, Clone)] -pub struct DirData { - key: u8, - x: f64, - y: f64 -} - -#[repr(C)] -#[allow(unused_imports)] -#[derive(Copy, Clone)] -pub struct StrData { - str: *const c_char -} - -impl From<ControlMessageC> for ControlMessage { - fn from(msg_c: ControlMessageC) -> Self { - match msg_c.tag { - CtrlMsgCTag::Msg => unsafe { - let str = str_c_to_rs(msg_c.data.str.str); - if str.is_some() { - ControlMessage::Msg(str.unwrap()) - } else { - ControlMessage::Err - } - } - CtrlMsgCTag::Pressed => unsafe { - ControlMessage::Pressed(msg_c.data.key.key) - } - CtrlMsgCTag::Released => unsafe { - ControlMessage::Released(msg_c.data.key.key) - } - CtrlMsgCTag::Axis => unsafe { - let data = msg_c.data.axis; - ControlMessage::Axis(data.key, data.ax) - } - CtrlMsgCTag::Dir => unsafe { - let data = msg_c.data.dir; - ControlMessage::Dir(data.key, (data.x, data.y)) - } - CtrlMsgCTag::Exit => { - ControlMessage::Exit - } - CtrlMsgCTag::Err => { - ControlMessage::Err - } - } - } -} - -impl From<ControlMessage> for ControlMessageC { - fn from(msg_rs: ControlMessage) -> Self { - match msg_rs { - ControlMessage::Msg(str_msg) => { - ControlMessageC { - tag: CtrlMsgCTag::Msg, - data: CtrlMsgCUnion { - str: StrData { str: str_rs_to_c(str_msg).1 }, - } - } - } - ControlMessage::Pressed(key) => { - ControlMessageC { - tag: CtrlMsgCTag::Pressed, - data: CtrlMsgCUnion { - key: KeyData { key }, - } - } - } - ControlMessage::Released(key) => { - ControlMessageC { - tag: CtrlMsgCTag::Released, - data: CtrlMsgCUnion { - key: KeyData { key }, - } - } - } - ControlMessage::Axis(key, ax) => { - ControlMessageC { - tag: CtrlMsgCTag::Axis, - data: CtrlMsgCUnion { - axis: AxisData { key, ax } - } - } - } - ControlMessage::Dir(key, (x, y)) => { - ControlMessageC { - tag: CtrlMsgCTag::Dir, - data: CtrlMsgCUnion { - dir: DirData { key, x, y } - } - } - } - ControlMessage::Exit => { - ControlMessageC { - tag: CtrlMsgCTag::Exit, - data: CtrlMsgCUnion { - nul: null_mut(), - } - } - } - ControlMessage::Err => { - ControlMessageC { - tag: CtrlMsgCTag::Err, - data: CtrlMsgCUnion { - nul: null_mut(), - } - } - } - } - } -}
\ No newline at end of file diff --git a/bindings/c/src/data_c/game_message_c.rs b/bindings/c/src/data_c/game_message_c.rs deleted file mode 100644 index 946ce60..0000000 --- a/bindings/c/src/data_c/game_message_c.rs +++ /dev/null @@ -1,114 +0,0 @@ -use std::ffi::c_void; -use std::ptr::null_mut; -use nogamepads_lib_rs::pad_data::pad_messages::nogamepads_messages::{GameMessage, LeaveReason}; -use crate::data_c::common::KeyData; - -#[repr(C)] -#[allow(unused_imports)] -pub struct GameMessageC { - pub tag: GameMsgCTag, - pub data: GameMsgCUnion -} - - -#[repr(C)] -#[allow(unused_imports)] -pub enum GameMsgCTag { - SkinEventTrigger, DisableKey, EnableKey, Leave, Err -} - -#[repr(C)] -#[allow(unused_imports)] -pub union GameMsgCUnion { - nul: *mut c_void, - key: KeyData, - reason: LeaveReasonData -} - -#[repr(C)] -#[allow(unused_imports)] -#[derive(Copy, Clone)] -pub enum LeaveReasonData { - GameOver, ServerClosed, YouAreKicked, YouAreBanned -} - -impl From<LeaveReasonData> for LeaveReason { - fn from(value: LeaveReasonData) -> Self { - match value { - LeaveReasonData::GameOver => { LeaveReason::GameOver } - LeaveReasonData::ServerClosed => { LeaveReason::ServerClosed } - LeaveReasonData::YouAreKicked => { LeaveReason::YouAreKicked } - LeaveReasonData::YouAreBanned => { LeaveReason::YouAreBanned } - } - } -} - -impl From<LeaveReason> for LeaveReasonData { - fn from(value: LeaveReason) -> Self { - match value { - LeaveReason::GameOver => { LeaveReasonData::GameOver } - LeaveReason::ServerClosed => { LeaveReasonData::ServerClosed } - LeaveReason::YouAreKicked => { LeaveReasonData::YouAreKicked } - LeaveReason::YouAreBanned => { LeaveReasonData::YouAreBanned } - } - } -} - -impl From<GameMessageC> for GameMessage { - fn from(msg: GameMessageC) -> Self { - match msg.tag { - GameMsgCTag::SkinEventTrigger => unsafe { - GameMessage::SkinEventTrigger(msg.data.key.key) - } - GameMsgCTag::DisableKey => unsafe { - GameMessage::DisableKey(msg.data.key.key) - } - GameMsgCTag::EnableKey => unsafe { - GameMessage::EnableKey(msg.data.key.key) - } - GameMsgCTag::Leave => unsafe { - GameMessage::Leave(msg.data.reason.into()) - } - GameMsgCTag::Err => { - GameMessage::Err - } - } - } -} - -impl From<GameMessage> for GameMessageC { - fn from(msg: GameMessage) -> Self { - match msg { - GameMessage::SkinEventTrigger(key) => { - GameMessageC { - tag: GameMsgCTag::SkinEventTrigger, - data: GameMsgCUnion { key: KeyData { key } } - } - } - GameMessage::DisableKey(key) => { - GameMessageC { - tag: GameMsgCTag::DisableKey, - data: GameMsgCUnion { key: KeyData { key } } - } - } - GameMessage::EnableKey(key) => { - GameMessageC { - tag: GameMsgCTag::EnableKey, - data: GameMsgCUnion { key: KeyData { key } } - } - } - GameMessage::Leave(reason) => { - GameMessageC { - tag: GameMsgCTag::Leave, - data: GameMsgCUnion { reason: reason.into() } - } - } - GameMessage::Err => { - GameMessageC { - tag: GameMsgCTag::Err, - data: GameMsgCUnion { nul: null_mut() } - } - } - } - } -}
\ No newline at end of file diff --git a/bindings/c/src/data_c/game_profile_c.rs b/bindings/c/src/data_c/game_profile_c.rs deleted file mode 100644 index 1dd11f7..0000000 --- a/bindings/c/src/data_c/game_profile_c.rs +++ /dev/null @@ -1,101 +0,0 @@ -use crate::{str_c_to_rs, str_rs_to_c}; -use nogamepads_lib_rs::pad_data::game_profile::game_profile::GameProfile; -use std::ffi::c_char; - -#[repr(C)] -#[derive(Copy, Clone)] -#[allow(unused_imports)] -pub struct GameProfileC { - pub game_name: *const c_char, - pub game_description: *const c_char, - pub organization: *const c_char, - pub version: *const c_char, - pub website: *const c_char, - pub email: *const c_char -} - -impl From<GameProfileC> for GameProfile { - fn from(value: GameProfileC) -> Self { - let unknown = "".to_string(); - GameProfile { - game_name: str_c_to_rs(value.game_name).unwrap_or(unknown.clone()), - game_description: str_c_to_rs(value.game_description).unwrap_or(unknown.clone()), - organization: str_c_to_rs(value.organization).unwrap_or(unknown.clone()), - version: str_c_to_rs(value.version).unwrap_or(unknown.clone()), - website: str_c_to_rs(value.website).unwrap_or(unknown.clone()), - email: str_c_to_rs(value.email).unwrap_or(unknown.clone()) - } - } -} - -impl From<GameProfile> for GameProfileC { - fn from(value: GameProfile) -> Self { - GameProfileC { - game_name: str_rs_to_c(value.game_name).1, - game_description: str_rs_to_c(value.game_description).1, - organization: str_rs_to_c(value.organization).1, - version: str_rs_to_c(value.version).1, - website: str_rs_to_c(value.website).1, - email: str_rs_to_c(value.email).1 - } - } -} - -impl From<&GameProfileC> for &GameProfile { - fn from(value: &GameProfileC) -> Self { - value.into() - } -} - -impl From<&GameProfile> for &GameProfileC { - fn from(value: &GameProfile) -> Self { - value.into() - } -} - -#[unsafe(no_mangle)] -pub extern "C" fn init_game_profile() -> GameProfileC { - GameProfile::default().into() -} - -#[unsafe(no_mangle)] -pub extern "C" fn set_game_profile_name(game_profile: GameProfileC, value: *const c_char) -> GameProfileC { - let value = str_c_to_rs(value).unwrap_or_default(); - let mut raw = GameProfile::from(game_profile); - raw.game_name(value.as_str()).to_owned().into() -} - -#[unsafe(no_mangle)] -pub extern "C" fn set_game_profile_description(game_profile: GameProfileC, value: *const c_char) -> GameProfileC { - let value = str_c_to_rs(value).unwrap_or_default(); - let mut raw = GameProfile::from(game_profile); - raw.game_description(value.as_str()).to_owned().into() -} - -#[unsafe(no_mangle)] -pub extern "C" fn set_game_profile_organization(game_profile: GameProfileC, value: *const c_char) -> GameProfileC { - let value = str_c_to_rs(value).unwrap_or_default(); - let mut raw = GameProfile::from(game_profile); - raw.organization(value.as_str()).to_owned().into() -} - -#[unsafe(no_mangle)] -pub extern "C" fn set_game_profile_version(game_profile: GameProfileC, value: *const c_char) -> GameProfileC { - let value = str_c_to_rs(value).unwrap_or_default(); - let mut raw = GameProfile::from(game_profile); - raw.version(value.as_str()).to_owned().into() -} - -#[unsafe(no_mangle)] -pub extern "C" fn set_game_profile_website(game_profile: GameProfileC, value: *const c_char) -> GameProfileC { - let value = str_c_to_rs(value).unwrap_or_default(); - let mut raw = GameProfile::from(game_profile); - raw.website(value.as_str()).to_owned().into() -} - -#[unsafe(no_mangle)] -pub extern "C" fn set_game_profile_email(game_profile: GameProfileC, value: *const c_char) -> GameProfileC { - let value = str_c_to_rs(value).unwrap_or_default(); - let mut raw = GameProfile::from(game_profile); - raw.email(value.as_str()).to_owned().into() -}
\ No newline at end of file diff --git a/bindings/c/src/data_c/mod.rs b/bindings/c/src/data_c/mod.rs deleted file mode 100644 index afe8728..0000000 --- a/bindings/c/src/data_c/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -pub mod common; - -pub mod control_message_c; -pub mod game_message_c; -pub mod connection_message_c; -pub mod connection_callback_message_c; - - -pub mod game_profile_c; -pub mod player_info_c; -pub mod player_info_list_c;
\ No newline at end of file diff --git a/bindings/c/src/data_c/player_info_c.rs b/bindings/c/src/data_c/player_info_c.rs deleted file mode 100644 index b8a54e6..0000000 --- a/bindings/c/src/data_c/player_info_c.rs +++ /dev/null @@ -1,95 +0,0 @@ -use crate::{str_c_to_rs, str_rs_to_c}; -use nogamepads_lib_rs::pad_data::pad_player_info::nogamepads_player_info::{PlayerAccountInfo, PlayerCustomizeInfo, PlayerInfo}; -use std::ffi::c_char; - -#[repr(C)] -#[derive(Copy, Clone)] -#[allow(unused_imports)] -pub struct PlayerInfoC { - pub account_id: *const c_char, - pub account_hash: *const c_char, - - pub customize_nickname: *const c_char, - pub customize_color_hue: i32, - pub customize_color_saturation: f64, - pub customize_color_value: f64, -} - -impl From<PlayerInfoC> for PlayerInfo { - fn from(value: PlayerInfoC) -> Self { - let unknown = "unknown".to_string(); - PlayerInfo { - account : PlayerAccountInfo { - id: str_c_to_rs(value.account_id).unwrap_or(unknown.clone()), - player_hash: str_c_to_rs(value.account_hash).unwrap_or(unknown.clone()), - }, - customize: PlayerCustomizeInfo { - nickname: str_c_to_rs(value.customize_nickname).unwrap_or(unknown.clone()), - color_hue: value.customize_color_hue, - color_saturation: value.customize_color_saturation, - color_value: value.customize_color_value, - } - } - } -} - -impl From<PlayerInfo> for PlayerInfoC { - fn from(value: PlayerInfo) -> Self { - PlayerInfoC { - account_id: str_rs_to_c(value.account.id).1, - account_hash: str_rs_to_c(value.account.player_hash).1, - customize_nickname: str_rs_to_c(value.customize.nickname).1, - customize_color_hue: value.customize.color_hue, - customize_color_saturation: value.customize.color_saturation, - customize_color_value: value.customize.color_value, - } - } -} - -impl From<&PlayerInfoC> for &PlayerInfo { - fn from(value: &PlayerInfoC) -> Self { - value.into() - } -} - -impl From<&PlayerInfo> for &PlayerInfoC { - fn from(value: &PlayerInfo) -> Self { - value.into() - } -} - -#[unsafe(no_mangle)] -pub extern "C" fn init_player_info() -> PlayerInfoC { - PlayerInfo::new().into() -} - -#[unsafe(no_mangle)] -pub extern "C" fn set_player_info_account( - info: PlayerInfoC, id: *const c_char, password: *const c_char) -> PlayerInfoC { - - let id = str_c_to_rs(id).unwrap_or("".to_string()); - let password = str_c_to_rs(password).unwrap_or("".to_string()); - - let mut raw_info = PlayerInfo::from(info); - raw_info.setup_account_info(id.as_str(), password.as_str()); - raw_info.into() -} - -#[unsafe(no_mangle)] -pub extern "C" fn set_player_info_color( - info: PlayerInfoC, h: i32, s: f64, v: f64) -> PlayerInfoC { - - let mut raw_info = PlayerInfo::from(info); - raw_info.set_customize_color_hsv(h, s, v); - raw_info.into() -} - -#[unsafe(no_mangle)] -pub extern "C" fn set_player_info_nickname( - info: PlayerInfoC, nickname: *const c_char) -> PlayerInfoC { - let nickname = str_c_to_rs(nickname).unwrap_or("".to_string()); - - let mut raw_info = PlayerInfo::from(info); - raw_info.set_nickname(nickname.as_str()); - raw_info.into() -}
\ No newline at end of file diff --git a/bindings/c/src/data_c/player_info_list_c.rs b/bindings/c/src/data_c/player_info_list_c.rs deleted file mode 100644 index 99d5c35..0000000 --- a/bindings/c/src/data_c/player_info_list_c.rs +++ /dev/null @@ -1,8 +0,0 @@ -use crate::data_c::player_info_c::PlayerInfoC; - -#[repr(C)] -pub struct PlayerList { - pub(crate) players: *mut PlayerInfoC, - pub(crate) len: usize, - pub(crate) capacity: usize, -}
\ No newline at end of file diff --git a/bindings/c/src/lib.rs b/bindings/c/src/lib.rs deleted file mode 100644 index 6efd0e9..0000000 --- a/bindings/c/src/lib.rs +++ /dev/null @@ -1,41 +0,0 @@ -use std::ffi::{c_char, CStr, CString}; - -pub mod data_c; -pub mod service_c; - -pub fn str_rs_to_c(s: String) -> (CString, *const c_char) { - let c_string = CString::new(s).expect(""); - let ptr = c_string.as_ptr(); - (c_string, ptr) -} - -pub fn str_c_to_rs(ptr: *const c_char) -> Option<String> { - if ptr.is_null() { - return None; - } - unsafe { - CStr::from_ptr(ptr) - .to_str() - .ok() - .map(|s| s.to_owned()) - } -} - -#[macro_export] -macro_rules! box_into_raw { - ($expr:expr) => { - $crate::box_into_raw!(@inner $expr) - }; - - ($expr:expr => $t:ty) => { - $crate::box_into_raw!(@inner ($expr) as $t) - }; - - (@inner $expr:expr) => { - ::std::boxed::Box::into_raw(::std::boxed::Box::new($expr)) - }; - - (@inner ($expr:expr) as $t:ty) => { - ::std::boxed::Box::into_raw(::std::boxed::Box::new($expr) as ::std::boxed::Box<$t>) - }; -}
\ No newline at end of file diff --git a/bindings/c/src/service_c/common.rs b/bindings/c/src/service_c/common.rs deleted file mode 100644 index 8b13da0..0000000 --- a/bindings/c/src/service_c/common.rs +++ /dev/null @@ -1,4 +0,0 @@ -use nogamepads_lib_rs::DEFAULT_PORT; - -#[unsafe(no_mangle)] -pub extern "C" fn get_default_port() -> u16 { DEFAULT_PORT }
\ No newline at end of file diff --git a/bindings/c/src/service_c/mod.rs b/bindings/c/src/service_c/mod.rs deleted file mode 100644 index 674baf7..0000000 --- a/bindings/c/src/service_c/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod common; - -pub mod padclient; -pub mod padserver;
\ No newline at end of file diff --git a/bindings/c/src/service_c/padclient.rs b/bindings/c/src/service_c/padclient.rs deleted file mode 100644 index b7bac43..0000000 --- a/bindings/c/src/service_c/padclient.rs +++ /dev/null @@ -1,126 +0,0 @@ -use crate::data_c::control_message_c::ControlMessageC; -use crate::data_c::game_message_c::GameMessageC; -use crate::data_c::player_info_c::PlayerInfoC; -use crate::{box_into_raw, str_c_to_rs, str_rs_to_c}; -use nogamepads_lib_rs::pad_data::pad_messages::nogamepads_messages::GameMessage; -use nogamepads_lib_rs::pad_service::client::nogamepads_client::PadClient; -use nogamepads_lib_rs::DEFAULT_PORT; -use std::ffi::c_char; -use std::net::{IpAddr, Ipv4Addr}; -use std::str::FromStr; - -#[repr(C)] -#[derive(Copy, Clone)] -#[allow(unused_imports)] -pub struct PadClientC { - pub target_address: *const c_char, - pub target_port: u16, - pub bind_player: PlayerInfoC, - pub enable_console: bool, - pub quiet: bool -} - -impl From<PadClientC> for PadClient { - fn from(value: PadClientC) -> Self { - let address = IpAddr::from_str(str_c_to_rs(value.target_address).unwrap_or("".to_string()).as_str()).unwrap_or( - IpAddr::from(Ipv4Addr::new(127, 0, 0, 1)) - ); - let port = value.target_port; - let mut client = PadClient::bind_addr_with_port(address, port); - client.bind_player(value.bind_player.into()); - if value.enable_console { client.enable_console(); } - if value.quiet { client.quiet(); } - client - } -} - -impl From<PadClient> for PadClientC { - fn from(mut value: PadClient) -> Self { - let (addr, port) = value.clone_addr(); - - PadClientC { - target_address: str_rs_to_c(addr.to_string()).1, - target_port: port, - bind_player: value.unbind_player().into(), - enable_console: value.is_enable_console(), - quiet: value.is_quiet(), - } - } -} -impl From<&mut PadClient> for PadClientC { - fn from(value: &mut PadClient) -> Self { - value.into() - } -} - -// 构建 - -#[unsafe(no_mangle)] -pub extern "C" fn init_client(address: *const c_char) -> PadClientC { - let addr_str = str_c_to_rs(address).unwrap_or("127.0.0.1".to_string()); - let addr_v4 = Ipv4Addr::from_str(addr_str.as_str()).unwrap_or( - Ipv4Addr::new(127, 0, 0, 1)); - PadClient::bind_addr_with_port(IpAddr::from(addr_v4), DEFAULT_PORT).into() -} - -#[unsafe(no_mangle)] -pub unsafe extern "C" fn init_client_with_port(address: *const c_char, port: u16) -> PadClientC { - let addr_str = str_c_to_rs(address).unwrap_or("127.0.0.1".to_string()); - let addr_v4 = Ipv4Addr::from_str(addr_str.as_str()).unwrap_or( - Ipv4Addr::new(127, 0, 0, 1)); - PadClient::bind_addr_with_port(IpAddr::from(addr_v4), port).into() -} - -#[unsafe(no_mangle)] -pub extern "C" fn set_client_quiet(client: PadClientC) -> PadClientC { - let mut raw: PadClient = client.into(); - raw.quiet().into() -} - -#[unsafe(no_mangle)] -pub extern "C" fn enable_client_console(client: PadClientC) -> PadClientC { - let mut raw: PadClient = client.into(); - raw.enable_console().into() -} - -#[unsafe(no_mangle)] -pub extern "C" fn bind_player_to_client(client: PadClientC, info: PlayerInfoC) -> PadClientC { - let mut raw: PadClient = client.into(); - raw.bind_player(info.into()).into() -} - -#[unsafe(no_mangle)] -pub extern "C" fn complete(client: PadClientC) -> *mut PadClient { - let client: PadClient = client.into(); - box_into_raw!(client) -} - -// 状态控制 - -#[unsafe(no_mangle)] -pub extern "C" fn connect_client_to_server(client: &mut PadClient) { - let client = unsafe { Box::from_raw(client) }; - client.connect(); -} - -#[unsafe(no_mangle)] -pub extern "C" fn exit_client_from_server(client: &PadClient) { - client.exit_server(); -} - -// 消息管理 - -#[unsafe(no_mangle)] -pub extern "C" fn put_a_msg_to_server(client: &PadClient, msg: ControlMessageC) { - client.put_msg(msg.into()) -} - -#[unsafe(no_mangle)] -pub extern "C" fn pop_a_msg_from_server(client: &PadClient) -> GameMessageC { - client.pop_a_msg().unwrap_or(GameMessage::Err).into() -} - -#[unsafe(no_mangle)] -pub extern "C" fn pop_msg_from_server_or(client: &PadClient, or: GameMessageC) -> GameMessageC { - client.pop_msg_or(or.into()).into() -}
\ No newline at end of file diff --git a/bindings/c/src/service_c/padserver.rs b/bindings/c/src/service_c/padserver.rs deleted file mode 100644 index 98c5792..0000000 --- a/bindings/c/src/service_c/padserver.rs +++ /dev/null @@ -1,174 +0,0 @@ -use crate::data_c::game_message_c::GameMessageC; -use crate::data_c::game_profile_c::GameProfileC; -use crate::data_c::player_info_c::PlayerInfoC; -use crate::data_c::player_info_list_c::PlayerList; -use crate::{box_into_raw, str_c_to_rs}; -use nogamepads_lib_rs::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; -use nogamepads_lib_rs::pad_service::server::nogamepads_server::PadServer; -use nogamepads_lib_rs::DEFAULT_PORT; -use std::collections::HashMap; -use std::ffi::c_char; -use std::net::{IpAddr, Ipv4Addr}; -use std::str::FromStr; -use std::sync::{Arc, MutexGuard, PoisonError}; - -// 构建 - -#[unsafe(no_mangle)] -pub extern "C" fn init_server(address: *const c_char) -> *mut PadServer { - let addr_str = str_c_to_rs(address).unwrap_or("127.0.0.1".to_string()); - let addr_v4 = Ipv4Addr::from_str(addr_str.as_str()).unwrap_or( - Ipv4Addr::new(127, 0, 0, 1)); - let mut server = PadServer::default(); - server.addr(IpAddr::from(addr_v4), DEFAULT_PORT); - box_into_raw!(server) -} - -#[unsafe(no_mangle)] -pub extern "C" fn init_server_with_port(address: *const c_char, port: u16) -> *mut PadServer { - let addr_str = str_c_to_rs(address).unwrap_or("127.0.0.1".to_string()); - let addr_v4 = Ipv4Addr::from_str(addr_str.as_str()).unwrap_or( - Ipv4Addr::new(127, 0, 0, 1)); - let mut server = PadServer::default(); - server.addr(IpAddr::from(addr_v4), port); - box_into_raw!(server) -} - -#[unsafe(no_mangle)] -pub extern "C" fn set_server_quiet(server: &mut PadServer) { - server.quiet(); -} - -#[unsafe(no_mangle)] -pub extern "C" fn enable_server_console(server: &mut PadServer) { - server.enable_console(); -} - -#[unsafe(no_mangle)] -pub extern "C" fn bind_profile_to_server(server: &mut PadServer, profile: &GameProfileC) { - server.put_profile(profile.clone().into()); -} - -// 状态控制 - -#[unsafe(no_mangle)] -pub extern "C" fn start_server(server: *mut PadServer) { - let server = unsafe { Box::from_raw(server) }; - let arc = Arc::new(server.as_ref().clone()); - PadServer::start_server(arc); -} - -#[unsafe(no_mangle)] -pub extern "C" fn stop_server(server: *mut PadServer) { - let server = unsafe { Box::from_raw(server) }; - server.stop_server(); -} - -#[unsafe(no_mangle)] -pub extern "C" fn lock_game_on_server(server: *mut PadServer) { - let server = unsafe { Box::from_raw(server) }; - server.lock_game(); -} - -#[unsafe(no_mangle)] -pub extern "C" fn unlock_game_on_server(server: *mut PadServer) { - let server = unsafe { Box::from_raw(server) }; - server.unlock_game(); -} - -#[unsafe(no_mangle)] -pub extern "C" fn is_server_game_locked(server: *mut PadServer) -> bool { - let server = unsafe { Box::from_raw(server) }; - server.is_game_locked() -} - -// 消息管理 -#[unsafe(no_mangle)] -pub extern "C" fn put_a_msg_to_player(server: *mut PadServer, msg: GameMessageC, player: &PlayerInfoC) { - let server = unsafe { Box::from_raw(server) }; - server.put_msg_to(msg.into(), player.into()); -} - -#[unsafe(no_mangle)] -pub extern "C" fn put_msg_to_all_players(server: *mut PadServer, msg: GameMessageC) { - let server = unsafe { Box::from_raw(server) }; - server.put_msg_to_all(&msg.into()); -} - -// #[unsafe(no_mangle)] -// pub extern "C" fn pop_a_msg(server: *mut PadServer) -> ControlMessageC { -// let server = unsafe { Box::from_raw(server) }; -// let msg = server.pop_a_msg(); -// if msg.is_some() { -// let (player, msg) = msg.unwrap(); -// } -// } - -// 玩家管理 -#[unsafe(no_mangle)] -pub extern "C" fn is_player_online(server: *mut PadServer, player: &PlayerInfoC) -> bool { - let server = unsafe { Box::from_raw(server) }; - server.is_player_online(player.into()) -} - -#[unsafe(no_mangle)] -pub extern "C" fn is_player_banned(server: *mut PadServer, player: &PlayerInfoC) -> bool { - let server = unsafe { Box::from_raw(server) }; - server.is_player_banned(player.into()) -} - -#[unsafe(no_mangle)] -pub extern "C" fn kick_player(server: *mut PadServer, player: &PlayerInfoC) { - let server = unsafe { Box::from_raw(server) }; - server.kick_player(player.into()); -} - -#[unsafe(no_mangle)] -pub extern "C" fn ban_player(server: *mut PadServer, player: &PlayerInfoC) { - let server = unsafe { Box::from_raw(server) }; - server.ban_player(player.into()); -} - -#[unsafe(no_mangle)] -pub extern "C" fn pardon_player(server: *mut PadServer, player: &PlayerInfoC) { - let server = unsafe { Box::from_raw(server) }; - server.pardon_player(player.into()); -} - -#[unsafe(no_mangle)] -pub extern "C" fn list_online_players(server: *mut PadServer) -> PlayerList { - let server = unsafe { Box::from_raw(server) }; - let list = server.list_players(); - process_list_result(list) -} - -#[unsafe(no_mangle)] -pub extern "C" fn list_banned_players(server: *mut PadServer) -> PlayerList { - let server = unsafe { Box::from_raw(server) }; - let list = server.list_players_banned(); - process_list_result(list) -} - -fn process_list_result(list: Result<Vec<PlayerInfo>, PoisonError<MutexGuard<HashMap<String, PlayerInfo>>>>) -> PlayerList { - let result : Vec<PlayerInfo>; - if list.is_ok() { - result = list.unwrap(); - } else { - result = vec![]; - } - let mut result_c: Vec<PlayerInfoC> = Vec::new(); - for item in result { - result_c.push(item.into()); - } - - let mut vec = result_c.into_boxed_slice(); - let ptr = vec.as_mut_ptr(); - let len = vec.len(); - let capacity = vec.len(); - - PlayerList { - players: ptr, - len, - capacity - } -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/.idea/.idea.NoGamepadsSharp/.idea/.gitignore b/bindings/csharp/NoGamepadsSharp/.idea/.idea.NoGamepadsSharp/.idea/.gitignore deleted file mode 100644 index 7d29992..0000000 --- a/bindings/csharp/NoGamepadsSharp/.idea/.idea.NoGamepadsSharp/.idea/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Rider ignored files -/modules.xml -/contentModel.xml -/projectSettingsUpdater.xml -/.idea.NoGamepadsSharp.iml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/bindings/csharp/NoGamepadsSharp/.idea/.idea.NoGamepadsSharp/.idea/indexLayout.xml b/bindings/csharp/NoGamepadsSharp/.idea/.idea.NoGamepadsSharp/.idea/indexLayout.xml deleted file mode 100644 index 7b08163..0000000 --- a/bindings/csharp/NoGamepadsSharp/.idea/.idea.NoGamepadsSharp/.idea/indexLayout.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="4"> - <component name="UserContentModel"> - <attachedFolders /> - <explicitIncludes /> - <explicitExcludes /> - </component> -</project>
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/.idea/.idea.NoGamepadsSharp/.idea/vcs.xml b/bindings/csharp/NoGamepadsSharp/.idea/.idea.NoGamepadsSharp/.idea/vcs.xml deleted file mode 100644 index b2bdec2..0000000 --- a/bindings/csharp/NoGamepadsSharp/.idea/.idea.NoGamepadsSharp/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="4"> - <component name="VcsDirectoryMappings"> - <mapping directory="$PROJECT_DIR$/../.." vcs="Git" /> - </component> -</project>
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/.run/Run Example.run.xml b/bindings/csharp/NoGamepadsSharp/.run/Run Example.run.xml deleted file mode 100644 index 52006c3..0000000 --- a/bindings/csharp/NoGamepadsSharp/.run/Run Example.run.xml +++ /dev/null @@ -1,20 +0,0 @@ -<component name="ProjectRunConfigurationManager"> - <configuration default="false" name="Run Example" type="DotNetProject" factoryName=".NET Project"> - <option name="EXE_PATH" value="$PROJECT_DIR$/NoGamepadsSharp_Execute/bin/Debug/net8.0/NoGamepadsSharp_Execute.exe" /> - <option name="PROGRAM_PARAMETERS" value="" /> - <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/NoGamepadsSharp_Execute/bin/Debug/net8.0" /> - <option name="PASS_PARENT_ENVS" value="1" /> - <option name="USE_EXTERNAL_CONSOLE" value="0" /> - <option name="USE_MONO" value="0" /> - <option name="RUNTIME_ARGUMENTS" value="" /> - <option name="PROJECT_PATH" value="$PROJECT_DIR$/NoGamepadsSharp_Execute/NoGamepadsSharp_Execute.csproj" /> - <option name="PROJECT_EXE_PATH_TRACKING" value="1" /> - <option name="PROJECT_ARGUMENTS_TRACKING" value="1" /> - <option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" /> - <option name="PROJECT_KIND" value="DotNetCore" /> - <option name="PROJECT_TFM" value="net8.0" /> - <method v="2"> - <option name="Build" /> - </method> - </configuration> -</component>
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp.sln b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp.sln deleted file mode 100644 index d9ec2f5..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp.sln +++ /dev/null @@ -1,22 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NoGamepadsSharp_Core", "NoGamepadsSharp_Core\NoGamepadsSharp_Core.csproj", "{18F3ABA3-0B44-4BE2-8F81-624DD57AE5B8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NoGamepadsSharp_Execute", "NoGamepadsSharp_Execute\NoGamepadsSharp_Execute.csproj", "{88ECEC25-6071-4F1B-8C5F-C8A3C66D43A4}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {18F3ABA3-0B44-4BE2-8F81-624DD57AE5B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {18F3ABA3-0B44-4BE2-8F81-624DD57AE5B8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {18F3ABA3-0B44-4BE2-8F81-624DD57AE5B8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {18F3ABA3-0B44-4BE2-8F81-624DD57AE5B8}.Release|Any CPU.Build.0 = Release|Any CPU - {88ECEC25-6071-4F1B-8C5F-C8A3C66D43A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {88ECEC25-6071-4F1B-8C5F-C8A3C66D43A4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {88ECEC25-6071-4F1B-8C5F-C8A3C66D43A4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {88ECEC25-6071-4F1B-8C5F-C8A3C66D43A4}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/Data/GameProfile.cs b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/Data/GameProfile.cs deleted file mode 100644 index c92a934..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/Data/GameProfile.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace NoGamepadsSharp_Data.Data; - -public class GameProfile -{ - -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/Data/HsvColor.cs b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/Data/HsvColor.cs deleted file mode 100644 index a534be6..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/Data/HsvColor.cs +++ /dev/null @@ -1,158 +0,0 @@ -namespace NoGamepadsSharp_Data.Data; - -public struct HsvColor -{ - private int _h; - private float _s; - private float _v; - - public HsvColor(int h, float s, float v) - { - _h = h; - _s = s; - _v = v; - } - - public HsvColor(float r, float g, float b) - { - Converter.ToHsv(r, g, b, out int h, out float s, out float v); - _h = h; - _s = s; - _v = v; - } - - public int hue - { - get => _h; - set => _h = int.Clamp(value, 0, 360); - } - - public float saturation - { - get => _s; - set => _s = float.Clamp(value, 0, 1); - } - - public float value - { - get => _v; - set => _v = float.Clamp(value, 0, 1); - } - - public float red - { - get - { - Converter.ToRgb(_h, _s, _v, out float f, out _, out _); - return f; - } - set - { - Converter.ToRgb(_h, _s, _v, out float r, out float g, out float b); - r = float.Clamp(value, 0, 1); - Converter.ToHsv(r, g, b, out int h, out float s, out float v); - _h = h; - _s = s; - _v = v; - } - } - - public float green - { - get - { - Converter.ToRgb(_h, _s, _v, out _, out float f, out _); - return f; - } - set - { - Converter.ToRgb(_h, _s, _v, out float r, out float g, out float b); - g = float.Clamp(value, 0, 1); - Converter.ToHsv(r, g, b, out int h, out float s, out float v); - _h = h; - _s = s; - _v = v; - } - } - - public float blue - { - get - { - Converter.ToRgb(_h, _s, _v, out _, out _, out float f); - return f; - } - set - { - Converter.ToRgb(_h, _s, _v, out float r, out float g, out float b); - b = float.Clamp(value, 0, 1); - Converter.ToHsv(r, g, b, out int h, out float s, out float v); - _h = h; - _s = s; - _v = v; - } - } - - public class Converter - { - public static void ToRgb(int h, float s, float v, out float r, out float g, out float b) - { - h = (h % 360 + 360) % 360; - - if (s <= 0.0f) - { - r = g = b = v; - return; - } - - float hh = h / 60.0f; - int i = (int)hh; - float ff = hh - i; - float p = v * (1.0f - s); - float q = v * (1.0f - s * ff); - float t = v * (1.0f - s * (1.0f - ff)); - - switch (i) - { - case 0: r = v; g = t; b = p; break; - case 1: r = q; g = v; b = p; break; - case 2: r = p; g = v; b = t; break; - case 3: r = p; g = q; b = v; break; - case 4: r = t; g = p; b = v; break; - default: r = v; g = p; b = q; break; - } - } - - public static void ToHsv(float r, float g, float b, out int h, out float s, out float v) - { - float min = Math.Min(Math.Min(r, g), b); - float max = Math.Max(Math.Max(r, g), b); - float delta = max - min; - - v = max; - - if (delta <= 1e-6f) - { - h = 0; - s = 0.0f; - return; - } - - s = delta / max; - float hh; - - if (Math.Abs(r - max) < 0.001f) - hh = (g - b) / delta; - else if (Math.Abs(g - max) < 0.001f) - hh = (b - r) / delta + 2.0f; - else - hh = (r - g) / delta + 4.0f; - - hh *= 60.0f; - if (hh < 0.0f) hh += 360.0f; - - h = (int)Math.Round(hh); - h = (h % 360 + 360) % 360; - } - } -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/Data/PlayerInfo.cs b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/Data/PlayerInfo.cs deleted file mode 100644 index 44ab51b..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/Data/PlayerInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace NoGamepadsSharp_Data.Data; - -public struct PlayerInfo -{ - public PlayerAccount Account; - public PlayerCustomize Customize; - - public struct PlayerCustomize - { - public String Nickname; - public HsvColor Color; - } - - public struct PlayerAccount - { - public String Id; - public String Hash; - } -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/NoGamepadsSharp_Core.csproj b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/NoGamepadsSharp_Core.csproj deleted file mode 100644 index d289ab2..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/NoGamepadsSharp_Core.csproj +++ /dev/null @@ -1,14 +0,0 @@ -<Project Sdk="Microsoft.NET.Sdk"> - - <PropertyGroup> - <TargetFramework>net8.0</TargetFramework> - <ImplicitUsings>enable</ImplicitUsings> - <Nullable>enable</Nullable> - <RootNamespace>NoGamepadsSharp_Data</RootNamespace> - </PropertyGroup> - - <ItemGroup> - <Folder Include="Data\Messages\" /> - </ItemGroup> - -</Project> diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/Service/PadClient.cs b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/Service/PadClient.cs deleted file mode 100644 index 3cbc403..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/Service/PadClient.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace NoGamepadsSharp_Data.Service; - -public class PadClient -{ - -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/Service/PadServer.cs b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/Service/PadServer.cs deleted file mode 100644 index 215437e..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/Service/PadServer.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace NoGamepadsSharp_Data.Service; - -public class PadServer -{ - -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/bin/Debug/net8.0/NoGamepadsSharp_Core.dll b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/bin/Debug/net8.0/NoGamepadsSharp_Core.dll Binary files differdeleted file mode 100644 index 6c507ae..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/bin/Debug/net8.0/NoGamepadsSharp_Core.dll +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/bin/Debug/net8.0/NoGamepadsSharp_Core.pdb b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/bin/Debug/net8.0/NoGamepadsSharp_Core.pdb Binary files differdeleted file mode 100644 index 2249b25..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/bin/Debug/net8.0/NoGamepadsSharp_Core.pdb +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/bin/Debug/net8.0/NoGamepadsSharp_Data.deps.json b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/bin/Debug/net8.0/NoGamepadsSharp_Data.deps.json deleted file mode 100644 index 8bbf5eb..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/bin/Debug/net8.0/NoGamepadsSharp_Data.deps.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "runtimeTarget": { - "name": ".NETCoreApp,Version=v8.0", - "signature": "" - }, - "compilationOptions": {}, - "targets": { - ".NETCoreApp,Version=v8.0": { - "NoGamepadsSharp_Data/1.0.0": { - "runtime": { - "NoGamepadsSharp_Data.dll": {} - } - } - } - }, - "libraries": { - "NoGamepadsSharp_Data/1.0.0": { - "type": "project", - "serviceable": false, - "sha512": "" - } - } -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/bin/Debug/net8.0/nogamepads_lib_c.dll b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/bin/Debug/net8.0/nogamepads_lib_c.dll Binary files differdeleted file mode 100644 index f9fa81d..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/bin/Debug/net8.0/nogamepads_lib_c.dll +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs deleted file mode 100644 index 2217181..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs +++ /dev/null @@ -1,4 +0,0 @@ -// <autogenerated /> -using System; -using System.Reflection; -[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")] diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Core.AssemblyInfo.cs b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Core.AssemblyInfo.cs deleted file mode 100644 index 9a403d4..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Core.AssemblyInfo.cs +++ /dev/null @@ -1,22 +0,0 @@ -//------------------------------------------------------------------------------ -// <auto-generated> -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// </auto-generated> -//------------------------------------------------------------------------------ - -using System; -using System.Reflection; - -[assembly: System.Reflection.AssemblyCompanyAttribute("NoGamepadsSharp_Core")] -[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] -[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+7bf8e1f24f95d87e1a30765b1904473cf75b435b")] -[assembly: System.Reflection.AssemblyProductAttribute("NoGamepadsSharp_Core")] -[assembly: System.Reflection.AssemblyTitleAttribute("NoGamepadsSharp_Core")] -[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] - -// 由 MSBuild WriteCodeFragment 类生成。 - diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Core.AssemblyInfoInputs.cache b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Core.AssemblyInfoInputs.cache deleted file mode 100644 index b65f543..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Core.AssemblyInfoInputs.cache +++ /dev/null @@ -1 +0,0 @@ -a6b869bd9da6a1765cbae4ac831af005406c2755ca688e375f929ab2317f8c28 diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Core.GeneratedMSBuildEditorConfig.editorconfig b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Core.GeneratedMSBuildEditorConfig.editorconfig deleted file mode 100644 index 5ca075c..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Core.GeneratedMSBuildEditorConfig.editorconfig +++ /dev/null @@ -1,13 +0,0 @@ -is_global = true -build_property.TargetFramework = net8.0 -build_property.TargetPlatformMinVersion = -build_property.UsingMicrosoftNETSdkWeb = -build_property.ProjectTypeGuids = -build_property.InvariantGlobalization = -build_property.PlatformNeutralAssembly = -build_property.EnforceExtendedAnalyzerRules = -build_property._SupportedPlatformList = Linux,macOS,Windows -build_property.RootNamespace = NoGamepadsSharp_Data -build_property.ProjectDir = D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Core\ -build_property.EnableComHosting = -build_property.EnableGeneratedComInterfaceComImportInterop = diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Core.GlobalUsings.g.cs b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Core.GlobalUsings.g.cs deleted file mode 100644 index 8578f3d..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Core.GlobalUsings.g.cs +++ /dev/null @@ -1,8 +0,0 @@ -// <auto-generated/> -global using global::System; -global using global::System.Collections.Generic; -global using global::System.IO; -global using global::System.Linq; -global using global::System.Net.Http; -global using global::System.Threading; -global using global::System.Threading.Tasks; diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Core.assets.cache b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Core.assets.cache Binary files differdeleted file mode 100644 index f039f0a..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Core.assets.cache +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.AssemblyInfo.cs b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.AssemblyInfo.cs deleted file mode 100644 index 116d7ca..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.AssemblyInfo.cs +++ /dev/null @@ -1,22 +0,0 @@ -//------------------------------------------------------------------------------ -// <auto-generated> -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// </auto-generated> -//------------------------------------------------------------------------------ - -using System; -using System.Reflection; - -[assembly: System.Reflection.AssemblyCompanyAttribute("NoGamepadsSharp_Data")] -[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] -[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+5a244311d5c9c42b33a49f3cafa7f20017d10305")] -[assembly: System.Reflection.AssemblyProductAttribute("NoGamepadsSharp_Data")] -[assembly: System.Reflection.AssemblyTitleAttribute("NoGamepadsSharp_Data")] -[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] - -// 由 MSBuild WriteCodeFragment 类生成。 - diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.AssemblyInfoInputs.cache b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.AssemblyInfoInputs.cache deleted file mode 100644 index 883b42c..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.AssemblyInfoInputs.cache +++ /dev/null @@ -1 +0,0 @@ -51f4886343a683d8f2a181ebd299d171750154161d19d908016790b79db7e699 diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.GeneratedMSBuildEditorConfig.editorconfig b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.GeneratedMSBuildEditorConfig.editorconfig deleted file mode 100644 index 123eb1c..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.GeneratedMSBuildEditorConfig.editorconfig +++ /dev/null @@ -1,13 +0,0 @@ -is_global = true -build_property.TargetFramework = net8.0 -build_property.TargetPlatformMinVersion = -build_property.UsingMicrosoftNETSdkWeb = -build_property.ProjectTypeGuids = -build_property.InvariantGlobalization = -build_property.PlatformNeutralAssembly = -build_property.EnforceExtendedAnalyzerRules = -build_property._SupportedPlatformList = Linux,macOS,Windows -build_property.RootNamespace = NoGamepadsSharp_Data -build_property.ProjectDir = D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Data\ -build_property.EnableComHosting = -build_property.EnableGeneratedComInterfaceComImportInterop = diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.GlobalUsings.g.cs b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.GlobalUsings.g.cs deleted file mode 100644 index 8578f3d..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.GlobalUsings.g.cs +++ /dev/null @@ -1,8 +0,0 @@ -// <auto-generated/> -global using global::System; -global using global::System.Collections.Generic; -global using global::System.IO; -global using global::System.Linq; -global using global::System.Net.Http; -global using global::System.Threading; -global using global::System.Threading.Tasks; diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.assets.cache b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.assets.cache Binary files differdeleted file mode 100644 index 3f0d1f1..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.assets.cache +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.csproj.CoreCompileInputs.cache b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.csproj.CoreCompileInputs.cache deleted file mode 100644 index fdbba54..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.csproj.CoreCompileInputs.cache +++ /dev/null @@ -1 +0,0 @@ -0803e9ca17c5d9a2228864ae9f1e28ef4bb203288db0ab9ca52fc11229959850 diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.csproj.FileListAbsolute.txt b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.csproj.FileListAbsolute.txt deleted file mode 100644 index 66fd1fc..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.csproj.FileListAbsolute.txt +++ /dev/null @@ -1,12 +0,0 @@ -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Data\bin\Debug\net8.0\NoGamepadsSharp_Data.deps.json -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Data\bin\Debug\net8.0\NoGamepadsSharp_Data.dll -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Data\bin\Debug\net8.0\NoGamepadsSharp_Data.pdb -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Data\obj\Debug\net8.0\NoGamepadsSharp_Data.GeneratedMSBuildEditorConfig.editorconfig -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Data\obj\Debug\net8.0\NoGamepadsSharp_Data.AssemblyInfoInputs.cache -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Data\obj\Debug\net8.0\NoGamepadsSharp_Data.AssemblyInfo.cs -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Data\obj\Debug\net8.0\NoGamepadsSharp_Data.csproj.CoreCompileInputs.cache -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Data\obj\Debug\net8.0\NoGamepadsSharp_Data.sourcelink.json -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Data\obj\Debug\net8.0\NoGamepadsSharp_Data.dll -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Data\obj\Debug\net8.0\refint\NoGamepadsSharp_Data.dll -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Data\obj\Debug\net8.0\NoGamepadsSharp_Data.pdb -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Data\obj\Debug\net8.0\ref\NoGamepadsSharp_Data.dll diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.dll b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.dll Binary files differdeleted file mode 100644 index 6c507ae..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.dll +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.pdb b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.pdb Binary files differdeleted file mode 100644 index 2249b25..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.pdb +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.sourcelink.json b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.sourcelink.json deleted file mode 100644 index 55ad6d0..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/NoGamepadsSharp_Data.sourcelink.json +++ /dev/null @@ -1 +0,0 @@ -{"documents":{"D:\\TINP\\NoGamepads\\*":"https://raw.githubusercontent.com/CatilGrass/NoGamepads/5a244311d5c9c42b33a49f3cafa7f20017d10305/*"}}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/ref/NoGamepadsSharp_Data.dll b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/ref/NoGamepadsSharp_Data.dll Binary files differdeleted file mode 100644 index f284434..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/ref/NoGamepadsSharp_Data.dll +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/refint/NoGamepadsSharp_Data.dll b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/refint/NoGamepadsSharp_Data.dll Binary files differdeleted file mode 100644 index f284434..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/Debug/net8.0/refint/NoGamepadsSharp_Data.dll +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Core.csproj.nuget.dgspec.json b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Core.csproj.nuget.dgspec.json deleted file mode 100644 index 2ec1ff3..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Core.csproj.nuget.dgspec.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "format": 1, - "restore": { - "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Core\\NoGamepadsSharp_Core.csproj": {} - }, - "projects": { - "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Core\\NoGamepadsSharp_Core.csproj": { - "version": "1.0.0", - "restore": { - "projectUniqueName": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Core\\NoGamepadsSharp_Core.csproj", - "projectName": "NoGamepadsSharp_Core", - "projectPath": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Core\\NoGamepadsSharp_Core.csproj", - "packagesPath": "C:\\Users\\CatilGrass\\.nuget\\packages\\", - "outputPath": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Core\\obj\\", - "projectStyle": "PackageReference", - "configFilePaths": [ - "C:\\Users\\CatilGrass\\AppData\\Roaming\\NuGet\\NuGet.Config", - "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" - ], - "originalTargetFrameworks": [ - "net8.0" - ], - "sources": { - "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, - "https://api.nuget.org/v3/index.json": {} - }, - "frameworks": { - "net8.0": { - "targetAlias": "net8.0", - "projectReferences": {} - } - }, - "warningProperties": { - "warnAsError": [ - "NU1605" - ] - }, - "restoreAuditProperties": { - "enableAudit": "true", - "auditLevel": "low", - "auditMode": "direct" - } - }, - "frameworks": { - "net8.0": { - "targetAlias": "net8.0", - "imports": [ - "net461", - "net462", - "net47", - "net471", - "net472", - "net48", - "net481" - ], - "assetTargetFallback": true, - "warn": true, - "frameworkReferences": { - "Microsoft.NETCore.App": { - "privateAssets": "all" - } - }, - "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\8.0.406/PortableRuntimeIdentifierGraph.json" - } - } - } - } -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Core.csproj.nuget.g.props b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Core.csproj.nuget.g.props deleted file mode 100644 index 23d8bdd..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Core.csproj.nuget.g.props +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?> -<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> - <RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess> - <RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool> - <ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile> - <NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot> - <NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\CatilGrass\.nuget\packages\</NuGetPackageFolders> - <NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle> - <NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.12.2</NuGetToolVersion> - </PropertyGroup> - <ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> - <SourceRoot Include="C:\Users\CatilGrass\.nuget\packages\" /> - </ItemGroup> -</Project>
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Core.csproj.nuget.g.targets b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Core.csproj.nuget.g.targets deleted file mode 100644 index 3dc06ef..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Core.csproj.nuget.g.targets +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?> -<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Data.csproj.nuget.dgspec.json b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Data.csproj.nuget.dgspec.json deleted file mode 100644 index 1b99a0b..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Data.csproj.nuget.dgspec.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "format": 1, - "restore": { - "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Data\\NoGamepadsSharp_Data.csproj": {} - }, - "projects": { - "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Data\\NoGamepadsSharp_Data.csproj": { - "version": "1.0.0", - "restore": { - "projectUniqueName": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Data\\NoGamepadsSharp_Data.csproj", - "projectName": "NoGamepadsSharp_Data", - "projectPath": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Data\\NoGamepadsSharp_Data.csproj", - "packagesPath": "C:\\Users\\CatilGrass\\.nuget\\packages\\", - "outputPath": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Data\\obj\\", - "projectStyle": "PackageReference", - "configFilePaths": [ - "C:\\Users\\CatilGrass\\AppData\\Roaming\\NuGet\\NuGet.Config", - "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" - ], - "originalTargetFrameworks": [ - "net8.0" - ], - "sources": { - "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, - "https://api.nuget.org/v3/index.json": {} - }, - "frameworks": { - "net8.0": { - "targetAlias": "net8.0", - "projectReferences": {} - } - }, - "warningProperties": { - "warnAsError": [ - "NU1605" - ] - }, - "restoreAuditProperties": { - "enableAudit": "true", - "auditLevel": "low", - "auditMode": "direct" - } - }, - "frameworks": { - "net8.0": { - "targetAlias": "net8.0", - "imports": [ - "net461", - "net462", - "net47", - "net471", - "net472", - "net48", - "net481" - ], - "assetTargetFallback": true, - "warn": true, - "frameworkReferences": { - "Microsoft.NETCore.App": { - "privateAssets": "all" - } - }, - "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\8.0.406/PortableRuntimeIdentifierGraph.json" - } - } - } - } -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Data.csproj.nuget.g.props b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Data.csproj.nuget.g.props deleted file mode 100644 index 23d8bdd..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Data.csproj.nuget.g.props +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?> -<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> - <RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess> - <RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool> - <ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile> - <NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot> - <NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\CatilGrass\.nuget\packages\</NuGetPackageFolders> - <NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle> - <NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.12.2</NuGetToolVersion> - </PropertyGroup> - <ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> - <SourceRoot Include="C:\Users\CatilGrass\.nuget\packages\" /> - </ItemGroup> -</Project>
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Data.csproj.nuget.g.targets b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Data.csproj.nuget.g.targets deleted file mode 100644 index 3dc06ef..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/NoGamepadsSharp_Data.csproj.nuget.g.targets +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?> -<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/project.assets.json b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/project.assets.json deleted file mode 100644 index b1dd5ac..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/project.assets.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "version": 3, - "targets": { - "net8.0": {} - }, - "libraries": {}, - "projectFileDependencyGroups": { - "net8.0": [] - }, - "packageFolders": { - "C:\\Users\\CatilGrass\\.nuget\\packages\\": {} - }, - "project": { - "version": "1.0.0", - "restore": { - "projectUniqueName": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Core\\NoGamepadsSharp_Core.csproj", - "projectName": "NoGamepadsSharp_Core", - "projectPath": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Core\\NoGamepadsSharp_Core.csproj", - "packagesPath": "C:\\Users\\CatilGrass\\.nuget\\packages\\", - "outputPath": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Core\\obj\\", - "projectStyle": "PackageReference", - "configFilePaths": [ - "C:\\Users\\CatilGrass\\AppData\\Roaming\\NuGet\\NuGet.Config", - "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" - ], - "originalTargetFrameworks": [ - "net8.0" - ], - "sources": { - "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, - "https://api.nuget.org/v3/index.json": {} - }, - "frameworks": { - "net8.0": { - "targetAlias": "net8.0", - "projectReferences": {} - } - }, - "warningProperties": { - "warnAsError": [ - "NU1605" - ] - }, - "restoreAuditProperties": { - "enableAudit": "true", - "auditLevel": "low", - "auditMode": "direct" - } - }, - "frameworks": { - "net8.0": { - "targetAlias": "net8.0", - "imports": [ - "net461", - "net462", - "net47", - "net471", - "net472", - "net48", - "net481" - ], - "assetTargetFallback": true, - "warn": true, - "frameworkReferences": { - "Microsoft.NETCore.App": { - "privateAssets": "all" - } - }, - "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\8.0.406/PortableRuntimeIdentifierGraph.json" - } - } - } -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/project.nuget.cache b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/project.nuget.cache deleted file mode 100644 index 30a67f3..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/project.nuget.cache +++ /dev/null @@ -1,8 +0,0 @@ -{ - "version": 2, - "dgSpecHash": "Q6iJ8uE2jE4=", - "success": true, - "projectFilePath": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Core\\NoGamepadsSharp_Core.csproj", - "expectedPackageFiles": [], - "logs": [] -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/project.packagespec.json b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/project.packagespec.json deleted file mode 100644 index 6409f09..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/project.packagespec.json +++ /dev/null @@ -1 +0,0 @@ -"restore":{"projectUniqueName":"D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Core\\NoGamepadsSharp_Core.csproj","projectName":"NoGamepadsSharp_Core","projectPath":"D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Core\\NoGamepadsSharp_Core.csproj","outputPath":"D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Core\\obj\\","projectStyle":"PackageReference","originalTargetFrameworks":["net8.0"],"sources":{"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\":{},"https://api.nuget.org/v3/index.json":{}},"frameworks":{"net8.0":{"targetAlias":"net8.0","projectReferences":{}}},"warningProperties":{"warnAsError":["NU1605"]},"restoreAuditProperties":{"enableAudit":"true","auditLevel":"low","auditMode":"direct"}}"frameworks":{"net8.0":{"targetAlias":"net8.0","imports":["net461","net462","net47","net471","net472","net48","net481"],"assetTargetFallback":true,"warn":true,"frameworkReferences":{"Microsoft.NETCore.App":{"privateAssets":"all"}},"runtimeIdentifierGraphPath":"C:\\Program Files\\dotnet\\sdk\\8.0.406/PortableRuntimeIdentifierGraph.json"}}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/rider.project.model.nuget.info b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/rider.project.model.nuget.info deleted file mode 100644 index 8e81be6..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/rider.project.model.nuget.info +++ /dev/null @@ -1 +0,0 @@ -17483963567493999
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/rider.project.restore.info b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/rider.project.restore.info deleted file mode 100644 index 8e81be6..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Core/obj/rider.project.restore.info +++ /dev/null @@ -1 +0,0 @@ -17483963567493999
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/NoGamepadsSharp_Execute.csproj b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/NoGamepadsSharp_Execute.csproj deleted file mode 100644 index 2f4fc77..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/NoGamepadsSharp_Execute.csproj +++ /dev/null @@ -1,10 +0,0 @@ -<Project Sdk="Microsoft.NET.Sdk"> - - <PropertyGroup> - <OutputType>Exe</OutputType> - <TargetFramework>net8.0</TargetFramework> - <ImplicitUsings>enable</ImplicitUsings> - <Nullable>enable</Nullable> - </PropertyGroup> - -</Project> diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/Program.cs b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/Program.cs deleted file mode 100644 index 4f9a31c..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/Program.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Runtime.InteropServices; - -namespace NoGamepadsSharp_Execute -{ - public class Program - { - public static void Main(string[] args) - { - - } - } -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/NoGamepadsSharp_Execute.deps.json b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/NoGamepadsSharp_Execute.deps.json deleted file mode 100644 index 7ec60d1..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/NoGamepadsSharp_Execute.deps.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "runtimeTarget": { - "name": ".NETCoreApp,Version=v8.0", - "signature": "" - }, - "compilationOptions": {}, - "targets": { - ".NETCoreApp,Version=v8.0": { - "NoGamepadsSharp_Execute/1.0.0": { - "runtime": { - "NoGamepadsSharp_Execute.dll": {} - } - } - } - }, - "libraries": { - "NoGamepadsSharp_Execute/1.0.0": { - "type": "project", - "serviceable": false, - "sha512": "" - } - } -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/NoGamepadsSharp_Execute.dll b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/NoGamepadsSharp_Execute.dll Binary files differdeleted file mode 100644 index 7304713..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/NoGamepadsSharp_Execute.dll +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/NoGamepadsSharp_Execute.exe b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/NoGamepadsSharp_Execute.exe Binary files differdeleted file mode 100644 index 1aed8a6..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/NoGamepadsSharp_Execute.exe +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/NoGamepadsSharp_Execute.pdb b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/NoGamepadsSharp_Execute.pdb Binary files differdeleted file mode 100644 index f0bffa1..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/NoGamepadsSharp_Execute.pdb +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/NoGamepadsSharp_Execute.runtimeconfig.json b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/NoGamepadsSharp_Execute.runtimeconfig.json deleted file mode 100644 index becfaea..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/NoGamepadsSharp_Execute.runtimeconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "runtimeOptions": { - "tfm": "net8.0", - "framework": { - "name": "Microsoft.NETCore.App", - "version": "8.0.0" - }, - "configProperties": { - "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false - } - } -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/nogamepads_lib_c.dll b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/nogamepads_lib_c.dll Binary files differdeleted file mode 100644 index 1dcd807..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/bin/Debug/net8.0/nogamepads_lib_c.dll +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs deleted file mode 100644 index 2217181..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs +++ /dev/null @@ -1,4 +0,0 @@ -// <autogenerated /> -using System; -using System.Reflection; -[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")] diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.AssemblyInfo.cs b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.AssemblyInfo.cs deleted file mode 100644 index 1cd6707..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.AssemblyInfo.cs +++ /dev/null @@ -1,22 +0,0 @@ -//------------------------------------------------------------------------------ -// <auto-generated> -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// </auto-generated> -//------------------------------------------------------------------------------ - -using System; -using System.Reflection; - -[assembly: System.Reflection.AssemblyCompanyAttribute("NoGamepadsSharp_Execute")] -[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] -[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+7bf8e1f24f95d87e1a30765b1904473cf75b435b")] -[assembly: System.Reflection.AssemblyProductAttribute("NoGamepadsSharp_Execute")] -[assembly: System.Reflection.AssemblyTitleAttribute("NoGamepadsSharp_Execute")] -[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] - -// 由 MSBuild WriteCodeFragment 类生成。 - diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.AssemblyInfoInputs.cache b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.AssemblyInfoInputs.cache deleted file mode 100644 index 9d55bff..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.AssemblyInfoInputs.cache +++ /dev/null @@ -1 +0,0 @@ -04ec6d515d7009e3fadb88848dbf20ac4996198345493ab6f51b427aa75bafe7 diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.GeneratedMSBuildEditorConfig.editorconfig b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.GeneratedMSBuildEditorConfig.editorconfig deleted file mode 100644 index a70a292..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.GeneratedMSBuildEditorConfig.editorconfig +++ /dev/null @@ -1,13 +0,0 @@ -is_global = true -build_property.TargetFramework = net8.0 -build_property.TargetPlatformMinVersion = -build_property.UsingMicrosoftNETSdkWeb = -build_property.ProjectTypeGuids = -build_property.InvariantGlobalization = -build_property.PlatformNeutralAssembly = -build_property.EnforceExtendedAnalyzerRules = -build_property._SupportedPlatformList = Linux,macOS,Windows -build_property.RootNamespace = NoGamepadsSharp_Execute -build_property.ProjectDir = D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Execute\ -build_property.EnableComHosting = -build_property.EnableGeneratedComInterfaceComImportInterop = diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.GlobalUsings.g.cs b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.GlobalUsings.g.cs deleted file mode 100644 index 8578f3d..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.GlobalUsings.g.cs +++ /dev/null @@ -1,8 +0,0 @@ -// <auto-generated/> -global using global::System; -global using global::System.Collections.Generic; -global using global::System.IO; -global using global::System.Linq; -global using global::System.Net.Http; -global using global::System.Threading; -global using global::System.Threading.Tasks; diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.assets.cache b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.assets.cache Binary files differdeleted file mode 100644 index 6e38352..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.assets.cache +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.csproj.CoreCompileInputs.cache b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.csproj.CoreCompileInputs.cache deleted file mode 100644 index b8d2bb6..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.csproj.CoreCompileInputs.cache +++ /dev/null @@ -1 +0,0 @@ -08b6a6e0c0f5c70b73eb166c3425ecd1b8254db5cb3da53ddf331a4e9ececa64 diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.csproj.FileListAbsolute.txt b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.csproj.FileListAbsolute.txt deleted file mode 100644 index 60ba01a..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.csproj.FileListAbsolute.txt +++ /dev/null @@ -1,15 +0,0 @@ -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Execute\bin\Debug\net8.0\NoGamepadsSharp_Execute.exe -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Execute\bin\Debug\net8.0\NoGamepadsSharp_Execute.deps.json -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Execute\bin\Debug\net8.0\NoGamepadsSharp_Execute.runtimeconfig.json -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Execute\bin\Debug\net8.0\NoGamepadsSharp_Execute.dll -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Execute\bin\Debug\net8.0\NoGamepadsSharp_Execute.pdb -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Execute\obj\Debug\net8.0\NoGamepadsSharp_Execute.GeneratedMSBuildEditorConfig.editorconfig -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Execute\obj\Debug\net8.0\NoGamepadsSharp_Execute.AssemblyInfoInputs.cache -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Execute\obj\Debug\net8.0\NoGamepadsSharp_Execute.AssemblyInfo.cs -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Execute\obj\Debug\net8.0\NoGamepadsSharp_Execute.csproj.CoreCompileInputs.cache -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Execute\obj\Debug\net8.0\NoGamepadsSharp_Execute.sourcelink.json -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Execute\obj\Debug\net8.0\NoGamepadsSharp_Execute.dll -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Execute\obj\Debug\net8.0\refint\NoGamepadsSharp_Execute.dll -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Execute\obj\Debug\net8.0\NoGamepadsSharp_Execute.pdb -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Execute\obj\Debug\net8.0\NoGamepadsSharp_Execute.genruntimeconfig.cache -D:\TINP\NoGamepads\core_csharp\NoGamepadsSharp\NoGamepadsSharp_Execute\obj\Debug\net8.0\ref\NoGamepadsSharp_Execute.dll diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.dll b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.dll Binary files differdeleted file mode 100644 index 7304713..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.dll +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.genruntimeconfig.cache b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.genruntimeconfig.cache deleted file mode 100644 index d1d6363..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.genruntimeconfig.cache +++ /dev/null @@ -1 +0,0 @@ -747af723e27e441c874613b2ee11f095ebffaa1343df438ff5c28c1abeefb1b1 diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.pdb b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.pdb Binary files differdeleted file mode 100644 index f0bffa1..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.pdb +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.sourcelink.json b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.sourcelink.json deleted file mode 100644 index 9ab27c4..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/NoGamepadsSharp_Execute.sourcelink.json +++ /dev/null @@ -1 +0,0 @@ -{"documents":{"D:\\TINP\\NoGamepads\\*":"https://raw.githubusercontent.com/CatilGrass/NoGamepads/7bf8e1f24f95d87e1a30765b1904473cf75b435b/*"}}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/apphost.exe b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/apphost.exe Binary files differdeleted file mode 100644 index 1aed8a6..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/apphost.exe +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/ref/NoGamepadsSharp_Execute.dll b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/ref/NoGamepadsSharp_Execute.dll Binary files differdeleted file mode 100644 index 1a99951..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/ref/NoGamepadsSharp_Execute.dll +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/refint/NoGamepadsSharp_Execute.dll b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/refint/NoGamepadsSharp_Execute.dll Binary files differdeleted file mode 100644 index 1a99951..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/Debug/net8.0/refint/NoGamepadsSharp_Execute.dll +++ /dev/null diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/NoGamepadsSharp_Execute.csproj.nuget.dgspec.json b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/NoGamepadsSharp_Execute.csproj.nuget.dgspec.json deleted file mode 100644 index fd5cb69..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/NoGamepadsSharp_Execute.csproj.nuget.dgspec.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "format": 1, - "restore": { - "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Execute\\NoGamepadsSharp_Execute.csproj": {} - }, - "projects": { - "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Execute\\NoGamepadsSharp_Execute.csproj": { - "version": "1.0.0", - "restore": { - "projectUniqueName": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Execute\\NoGamepadsSharp_Execute.csproj", - "projectName": "NoGamepadsSharp_Execute", - "projectPath": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Execute\\NoGamepadsSharp_Execute.csproj", - "packagesPath": "C:\\Users\\CatilGrass\\.nuget\\packages\\", - "outputPath": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Execute\\obj\\", - "projectStyle": "PackageReference", - "configFilePaths": [ - "C:\\Users\\CatilGrass\\AppData\\Roaming\\NuGet\\NuGet.Config", - "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" - ], - "originalTargetFrameworks": [ - "net8.0" - ], - "sources": { - "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, - "https://api.nuget.org/v3/index.json": {} - }, - "frameworks": { - "net8.0": { - "targetAlias": "net8.0", - "projectReferences": {} - } - }, - "warningProperties": { - "warnAsError": [ - "NU1605" - ] - }, - "restoreAuditProperties": { - "enableAudit": "true", - "auditLevel": "low", - "auditMode": "direct" - } - }, - "frameworks": { - "net8.0": { - "targetAlias": "net8.0", - "imports": [ - "net461", - "net462", - "net47", - "net471", - "net472", - "net48", - "net481" - ], - "assetTargetFallback": true, - "warn": true, - "frameworkReferences": { - "Microsoft.NETCore.App": { - "privateAssets": "all" - } - }, - "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\8.0.406/PortableRuntimeIdentifierGraph.json" - } - } - } - } -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/NoGamepadsSharp_Execute.csproj.nuget.g.props b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/NoGamepadsSharp_Execute.csproj.nuget.g.props deleted file mode 100644 index 23d8bdd..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/NoGamepadsSharp_Execute.csproj.nuget.g.props +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?> -<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> - <RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess> - <RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool> - <ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile> - <NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot> - <NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\CatilGrass\.nuget\packages\</NuGetPackageFolders> - <NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle> - <NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.12.2</NuGetToolVersion> - </PropertyGroup> - <ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> - <SourceRoot Include="C:\Users\CatilGrass\.nuget\packages\" /> - </ItemGroup> -</Project>
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/NoGamepadsSharp_Execute.csproj.nuget.g.targets b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/NoGamepadsSharp_Execute.csproj.nuget.g.targets deleted file mode 100644 index 3dc06ef..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/NoGamepadsSharp_Execute.csproj.nuget.g.targets +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?> -<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/project.assets.json b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/project.assets.json deleted file mode 100644 index d719216..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/project.assets.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "version": 3, - "targets": { - "net8.0": {} - }, - "libraries": {}, - "projectFileDependencyGroups": { - "net8.0": [] - }, - "packageFolders": { - "C:\\Users\\CatilGrass\\.nuget\\packages\\": {} - }, - "project": { - "version": "1.0.0", - "restore": { - "projectUniqueName": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Execute\\NoGamepadsSharp_Execute.csproj", - "projectName": "NoGamepadsSharp_Execute", - "projectPath": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Execute\\NoGamepadsSharp_Execute.csproj", - "packagesPath": "C:\\Users\\CatilGrass\\.nuget\\packages\\", - "outputPath": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Execute\\obj\\", - "projectStyle": "PackageReference", - "configFilePaths": [ - "C:\\Users\\CatilGrass\\AppData\\Roaming\\NuGet\\NuGet.Config", - "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" - ], - "originalTargetFrameworks": [ - "net8.0" - ], - "sources": { - "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, - "https://api.nuget.org/v3/index.json": {} - }, - "frameworks": { - "net8.0": { - "targetAlias": "net8.0", - "projectReferences": {} - } - }, - "warningProperties": { - "warnAsError": [ - "NU1605" - ] - }, - "restoreAuditProperties": { - "enableAudit": "true", - "auditLevel": "low", - "auditMode": "direct" - } - }, - "frameworks": { - "net8.0": { - "targetAlias": "net8.0", - "imports": [ - "net461", - "net462", - "net47", - "net471", - "net472", - "net48", - "net481" - ], - "assetTargetFallback": true, - "warn": true, - "frameworkReferences": { - "Microsoft.NETCore.App": { - "privateAssets": "all" - } - }, - "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\8.0.406/PortableRuntimeIdentifierGraph.json" - } - } - } -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/project.nuget.cache b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/project.nuget.cache deleted file mode 100644 index 1840ead..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/project.nuget.cache +++ /dev/null @@ -1,8 +0,0 @@ -{ - "version": 2, - "dgSpecHash": "7zQApaEoWYM=", - "success": true, - "projectFilePath": "D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Execute\\NoGamepadsSharp_Execute.csproj", - "expectedPackageFiles": [], - "logs": [] -}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/project.packagespec.json b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/project.packagespec.json deleted file mode 100644 index 1fa2ff6..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/project.packagespec.json +++ /dev/null @@ -1 +0,0 @@ -"restore":{"projectUniqueName":"D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Execute\\NoGamepadsSharp_Execute.csproj","projectName":"NoGamepadsSharp_Execute","projectPath":"D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Execute\\NoGamepadsSharp_Execute.csproj","outputPath":"D:\\TINP\\NoGamepads\\core_csharp\\NoGamepadsSharp\\NoGamepadsSharp_Execute\\obj\\","projectStyle":"PackageReference","originalTargetFrameworks":["net8.0"],"sources":{"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\":{},"https://api.nuget.org/v3/index.json":{}},"frameworks":{"net8.0":{"targetAlias":"net8.0","projectReferences":{}}},"warningProperties":{"warnAsError":["NU1605"]},"restoreAuditProperties":{"enableAudit":"true","auditLevel":"low","auditMode":"direct"}}"frameworks":{"net8.0":{"targetAlias":"net8.0","imports":["net461","net462","net47","net471","net472","net48","net481"],"assetTargetFallback":true,"warn":true,"frameworkReferences":{"Microsoft.NETCore.App":{"privateAssets":"all"}},"runtimeIdentifierGraphPath":"C:\\Program Files\\dotnet\\sdk\\8.0.406/PortableRuntimeIdentifierGraph.json"}}
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/rider.project.model.nuget.info b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/rider.project.model.nuget.info deleted file mode 100644 index 91b84e6..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/rider.project.model.nuget.info +++ /dev/null @@ -1 +0,0 @@ -17483964212879694
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/rider.project.restore.info b/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/rider.project.restore.info deleted file mode 100644 index 91b84e6..0000000 --- a/bindings/csharp/NoGamepadsSharp/NoGamepadsSharp_Execute/obj/rider.project.restore.info +++ /dev/null @@ -1 +0,0 @@ -17483964212879694
\ No newline at end of file diff --git a/bindings/csharp/NoGamepadsSharp/global.json b/bindings/csharp/NoGamepadsSharp/global.json deleted file mode 100644 index 2ddda36..0000000 --- a/bindings/csharp/NoGamepadsSharp/global.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "sdk": { - "version": "8.0.0", - "rollForward": "latestMinor", - "allowPrerelease": false - } -}
\ No newline at end of file diff --git a/client/src/main.rs b/client/src/main.rs index 178122f..39d3dba 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -1,12 +1,9 @@ -use bevy::prelude::App; -use bevy::prelude::ResMut; -use bevy::prelude::Startup; -use bevy::tasks::block_on; +mod plugin_client; + +use crate::plugin_client::PadClientPlugin; +use bevy::prelude::{App}; use bevy::DefaultPlugins; -use bevy_tokio_tasks::{TokioTasksPlugin, TokioTasksRuntime}; -use nogamepads_lib_rs::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; -use nogamepads_lib_rs::pad_service::client::nogamepads_client::PadClient; -use std::net::{IpAddr, Ipv4Addr}; +use bevy_tokio_tasks::TokioTasksPlugin; use tokio::runtime::Builder; fn main() { @@ -16,36 +13,14 @@ fn main() { app.add_plugins(DefaultPlugins); app.add_plugins(TokioTasksPlugin { make_runtime: Box::new(|| { - Builder::new_multi_thread() - .enable_all() - .build().unwrap() + Builder::new_multi_thread().enable_all().build().unwrap() }), ..TokioTasksPlugin::default() }); - // 系统 - app.add_systems(Startup, client_init); + // 自定义插件 + app.add_plugins(PadClientPlugin); + // 启动 app.run(); } - -fn client_init( - runtime: ResMut<TokioTasksRuntime> -) { - let mut client = - PadClient::bind_addr(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); - - let mut player_info = PlayerInfo::new(); - player_info.setup_account_info( - env!("TEST_PLAYER_ACCOUNT"), - env!("TEST_PLAYER_PASSWORD")); - player_info.set_nickname(env!("TEST_PLAYER_NICKNAME")); - player_info.set_customize_color_hsv(320, 0.5, 1.0); // PINK - - client.bind_player(player_info); // 绑定玩家 - - runtime.spawn_background_task(|context| async move { - let entry = client.get_connect_entry(); - block_on(entry); - }); -} diff --git a/client/src/plugin_client.rs b/client/src/plugin_client.rs new file mode 100644 index 0000000..2449f3a --- /dev/null +++ b/client/src/plugin_client.rs @@ -0,0 +1,66 @@ + + +// #[derive(Component)] +// struct ClientComponent { +// pad_client: Arc<PadClient>, +// } + +use bevy::prelude::{App, Plugin}; + +pub struct PadClientPlugin; +impl Plugin for PadClientPlugin { + fn build(&self, app: &mut App) { + // app.add_systems(PreStartup, client_init); + // app.add_systems(Startup, client_start); + // app.add_systems(Update, client_exit.run_if(input_just_pressed(KeyCode::Escape))); + } +} +// +// fn client_init( +// mut commands: Commands +// ) { +// // 构建玩家信息 +// let mut player_info = PlayerInfo::new(); +// player_info.setup_account_info( +// env!("TEST_PLAYER_ACCOUNT"), +// env!("TEST_PLAYER_PASSWORD")); +// player_info.set_nickname(env!("TEST_PLAYER_NICKNAME")); +// player_info.set_customize_color_hsv(320, 0.5, 1.0); // PINK +// +// // 构建客户端 +// let mut pad_client = PadClient::default(); +// pad_client.bind_player(player_info); +// pad_client.quiet(); +// +// // 将客户端放入实体 +// commands.spawn( +// ClientComponent { +// pad_client: pad_client.build(), +// } +// ); +// } +// +// fn client_start( +// client_components: Query<&mut ClientComponent>, +// runtime: ResMut<TokioTasksRuntime> +// ) { +// for client_component in client_components.iter() { +// let pad_client = Arc::clone(&client_component.pad_client); +// +// // 启动服务器 +// runtime.spawn_background_task(|_ctx|async move { +// let entry = pad_client.get_connect_entry(); +// block_on(entry); +// info!("Finished"); +// }); +// } +// } +// +// fn client_exit( +// client_components: Query<&mut ClientComponent> +// ){ +// for client_component in client_components.iter() { +// let pad_client = Arc::clone(&client_component.pad_client); +// pad_client.request_disconnect(); +// } +// }
\ No newline at end of file diff --git a/console/Cargo.toml b/console/Cargo.toml index 4751571..b241b6b 100644 --- a/console/Cargo.toml +++ b/console/Cargo.toml @@ -5,10 +5,13 @@ edition = "2024" version.workspace = true [dependencies] +nogamepads = { path = "../../NoGamepads" } nogamepads-core = { path = "../core" } clap = { version = "4.5.38", features = ["derive"] } rand = { version = "0.9.1", features = [] } -rpassword = "7.4.0" serde = { version = "1.0.219", features = ["derive"] } serde_yaml = "0.9.34" -prettytable-rs = "0.10.0"
\ No newline at end of file +prettytable-rs = "0.10.0" +tokio = { version = "1.45.0", features = ["full"] } +crossterm = "0.29.0" +log = "0.4.27"
\ No newline at end of file diff --git a/console/src/bin/nogpadc.rs b/console/src/bin/nogpadc.rs deleted file mode 100644 index 9a5418e..0000000 --- a/console/src/bin/nogpadc.rs +++ /dev/null @@ -1,387 +0,0 @@ -use crate::AccountCommands::{Add, Customize, List, Remove}; -use crate::Commands::{Account, Connect}; -use clap::{Args, Parser, Subcommand}; -use prettytable::{row, Table}; -use rand::Rng; -use std::env::current_dir; -use std::fs::{create_dir_all, remove_file, File}; -use std::io::{BufReader, Write}; -use std::net::{IpAddr, Ipv4Addr}; -use std::path::PathBuf; -use std::process::exit; -use std::str::FromStr; -use nogamepads_lib_rs::DEFAULT_PORT; -use nogamepads_lib_rs::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; -use nogamepads_lib_rs::pad_service::client::nogamepads_client::PadClient; - -/// NoGamePads Console - Client Cli -#[derive(Parser, Debug)] -#[command(author, version, about, long_about = None)] -struct NoGamepadClientCli { - #[command(subcommand)] - command: Commands, -} - -/// 主要命令 -#[derive(Subcommand, Debug)] -enum Commands { - - // 账户设置 - #[command(subcommand, about = "Operation of player account")] - Account(AccountCommands), - - // 连接到服务器 - #[command(about = "Connect a player to server")] - Connect(ConnectArgs) -} - -/// 账户设置 命令 -#[derive(Subcommand, Debug)] -enum AccountCommands { - - // 列出所有账号 - #[command(about = "List all local players")] - List(ListAccountArgs), - - // 添加账号 - #[command(about = "Add a local player")] - Add(AddAccountArgs), - - // 移除账号 - #[command(about = "Remove a local player")] - Remove(RemoveAccountArgs), - - // 自定义账号显示信息 - #[command(about = "Customize how the player appears")] - Customize(CustomizeAccountArgs) -} - -/// 列出所有账号 参数 -#[derive(Args, Debug)] -struct ListAccountArgs { } - -/// 添加账号 参数 -#[derive(Args, Debug)] -struct AddAccountArgs { - - // 注册的角色 ID - #[arg(value_name = "NAME")] - id: String -} - -/// 移除账号 参数 -#[derive(Args, Debug)] -struct RemoveAccountArgs { - - // 删除的角色 ID - #[arg(value_name = "NAME")] - id: String -} - -/// 自定义账号显示信息 参数 -#[derive(Args, Debug)] -struct CustomizeAccountArgs { - - // 定制的角色 ID - #[arg(value_name = "WHO")] - id: String, - - // 昵称 - #[arg(short, long, help = "Nickname")] - name: Option<String>, - - // 颜色 - #[arg(short = 'H', long = "hsv", num_args = 3, value_names = ["H", "S", "V"], help = "Player color, h(0 - 360), s(0 - 1), v(0 - 1)")] - hsv: Option<Vec<f64>> -} - -/// 连接到服务器 -#[derive(Args, Debug)] -struct ConnectArgs { - - // 连接的玩家 - #[arg(value_name = "WHO")] - id: String, - - // 目标服务器 - #[arg(value_name = "WHERE", default_value = "127.0.0.1")] - target: String, - - // 目标端口 - #[arg(short, long, default_value = "5989")] // <---- DEFAULT_PORT - port: Option<u16>, - - // 启用调试 - #[arg(long)] - debug: bool, -} - -/// 配置文件后缀名称 -const EXTENSION_NAME : &str = "yaml"; - -fn main() { - - // 初始化 - let root = get_config_folder_path(); - if ! root.exists() { - create_dir_all(root.as_path()).unwrap(); - } - - // 命令行 - let cli = NoGamepadClientCli::parse(); - match cli.command { - - // 账户设置部分 - Account(commands) => { - match commands { - - // 添加账号 - Add(args) => { - if is_account_exist(&args.id) { - println!("Account already exists!"); - } else { - // 账号 ID 和 配置路径 - let account_id = process_inputted_text(args.id); - let account_config_path = get_account_config_path(&account_id); - - // 为新号准备的配置文件 - let mut new_info = PlayerInfo::new(); - - // 密码输入和密码验证 - let password = rpassword::prompt_password("Type password: ").unwrap(); - let password_confirm = rpassword::prompt_password("Confirm password: ").unwrap(); - if ! password_confirm.eq(&password) { - println!("Password does not match!"); - exit(1); - } - - // 随机生成 色调 值 - let mut rng = rand::rng(); - let random_hue: i32 = rng.random_range(0..=360); - - // 建立账号信息并预填入信息 - new_info.setup_account_info(account_id.as_str(), password.as_str()); - new_info.set_nickname(account_id.as_str()); - new_info.set_customize_color_hsv(random_hue, 0.8, 0.8); - - // 新配置信息的文本 - let new_info_yaml = serde_yaml::to_string(&new_info); - - // 将信息写入文件系统 - let mut buffer = File::create(account_config_path).unwrap(); - buffer.write_all(new_info_yaml.unwrap().as_bytes()).unwrap(); - - println!("Account created."); - } - }, - - // 移除账号 - Remove(args) => { - if ! is_account_exist(&args.id) { - println!("Account not found!"); - } else { - // 账号 ID 和 配置路径 - let account_id = process_inputted_text(args.id); - let account_config_path = get_account_config_path(&account_id); - - // 删除文件 - remove_file(account_config_path).unwrap(); - - println!("Account removed."); - } - }, - - // 列出所有账号 - List(_args) => { - // 账号信息文件夹 - let folder_path = get_config_folder_path(); - - // 输出表格 - let mut info_table = Table::new(); - - // 表头 - info_table.add_row(row!["ACCOUNT_ID", "NICKNAME", "COLOR", "HASH"]); - - // 遍历目录下文件,将信息逐一填入表格 - for item in folder_path.read_dir().unwrap() { - if let Ok(path) = item { - // 文件名 - let file_name = path.file_name().into_string().unwrap(); - let ext = format!(".{}", EXTENSION_NAME); - - // 判断是否为指定后缀 - if file_name.contains(ext.as_str()) { - - // 去除后缀内容,截取为 ID - let id = file_name.replace(ext.as_str(), ""); - - // 读取并加载其中的玩家信息 - let file = File::open(get_account_config_path(&id)).unwrap(); - let reader = BufReader::new(file); - let info: PlayerInfo = serde_yaml::from_reader(reader).unwrap(); - - // 填入表格 - info_table.add_row(row![ - &id, // ACCOUNT_ID - info.customize.nickname, // NICKNAME - hsv_to_hex( // COLOR - info.customize.color_hue, - info.customize.color_saturation, - info.customize.color_value), - info.account.player_hash // HASH - ]); - } - } - } - println!("{}", info_table.to_string()) - }, - - // 自定义账号显示信息 - Customize(args) => { - - // 加载配置文件 - let file = File::open(get_account_config_path(&args.id)).unwrap(); - let reader = BufReader::new(file); - let mut info: PlayerInfo = serde_yaml::from_reader(reader).unwrap(); - - // HSV 参数 - if args.hsv.is_some() { - let hsv = args.hsv.unwrap(); - let hue = hsv[0].round().clamp(0.0, 360.0); - let sat = hsv[1].clamp(0.0, 1.0); - let val = hsv[2].clamp(0.0, 1.0); - - info.customize.color_hue = hue as i32; - info.customize.color_saturation = sat; - info.customize.color_value = val; - - println!("Set {}'s HSV color to: {}, {}, {}.", &args.id, hue, sat, val); - } - - // 昵称 参数 - if args.name.is_some() { - let name = args.name.unwrap(); - info.customize.nickname = name.clone(); - - println!("Set {}'s display name to: {}.", &args.id, name); - } - - // 写入配置文件 - let yaml_content = serde_yaml::to_string(&info); - let mut buffer = File::create(get_account_config_path(&args.id)).unwrap(); - buffer.write_all(yaml_content.unwrap().as_bytes()).unwrap(); - }, - } - }, - - // 连接到服务器 - Connect(args) => { - if ! is_account_exist(&args.id) { - println!("Player not found!"); - exit(1); - } - - // 加载配置文件 - let file = File::open(get_account_config_path(&args.id)).unwrap(); - let reader = BufReader::new(file); - let info: PlayerInfo = serde_yaml::from_reader(reader).unwrap(); - - // 从参数获得 Ip 地址 (或默认) - let addr : IpAddr; - match IpAddr::from_str(&args.target) { - Ok(result) => { addr = result; } - Err(_err) => { - addr = IpAddr::from(Ipv4Addr::new(127, 0, 0, 1)); - } - } - - // 从参数获得端口地址 (或默认) - let port : u16 = if args.port.is_some() { args.port.unwrap() } else { DEFAULT_PORT } - .clamp(0, 65535); - - // 绑定目标地址 - let mut client = PadClient::bind_addr_with_port(addr, port); - - // 启动调试模式 ? - if args.debug { - println!("- DEBUG MODE -"); - client.enable_console(); - } - - // 写入玩家信息 - client.bind_player(info); - - // 连接 - client.connect(); - println!("Connected {} to {}:{}", args.id, addr.to_string(), port.to_string()); - } - } -} - -fn process_inputted_text(input: String) -> String { - // 截取前后文本,并转换为小写 - let s = input.trim().to_lowercase(); - let mut result = String::new(); - - // 处理其中的特殊符号,部分用于分割的符号需要转换为下划线 - for c in s.chars() { - match c { - '\n' | '_' => continue, - '-' | '.' | ',' | ' ' => result.push('_'), - _ => result.push(c), - } - } - - // 仅保留 ASCII 字符 - result.chars() - .filter(|&c| c.is_ascii_alphanumeric() || c == '_') - .collect() -} - -fn hsv_to_hex(h: i32, s: f64, v: f64) -> String { - let h = (h as f64).clamp(0.0, 360.0); - let s = s.clamp(0.0, 1.0); - let v = v.clamp(0.0, 1.0); - - let c = v * s; - let x = c * (1.0 - ((h / 60.0) % 2.0 - 1.0).abs()); - let m = v - c; - - let (r, g, b) = match (h / 60.0) as usize { - 0 => (c, x, 0.0), - 1 => (x, c, 0.0), - 2 => (0.0, c, x), - 3 => (0.0, x, c), - 4 => (x, 0.0, c), - 5 => (c, 0.0, x), - _ => (0.0, 0.0, 0.0), - }; - - let r = ((r + m) * 255.0).round() as u8; - let g = ((g + m) * 255.0).round() as u8; - let b = ((b + m) * 255.0).round() as u8; - format!("#{:02X}{:02X}{:02X}", r, g, b) -} - -fn get_config_folder_path() -> PathBuf { - current_dir().unwrap().join(".nogpadc") -} - -fn get_account_config_path(id: &str) -> PathBuf { - get_config_folder_path().join(format!("{}.{}", process_inputted_text(id.to_string()), EXTENSION_NAME)) -} - -fn is_account_exist(id: &str) -> bool { - let id = process_inputted_text(id.to_string()); - let path = get_config_folder_path(); - let dir = path.as_path().read_dir().unwrap(); - let mut found = false; - for item in dir { - if let Ok(path) = item { - if path.file_name().eq(format!("{}.{}", id, EXTENSION_NAME).as_str()) { - found = true; - } - } - } - found -}
\ No newline at end of file diff --git a/console/src/bin/nogpads.rs b/console/src/bin/nogpads.rs deleted file mode 100644 index 14df488..0000000 --- a/console/src/bin/nogpads.rs +++ /dev/null @@ -1,299 +0,0 @@ -use std::collections::HashMap; -use clap::{arg, Args, Parser, Subcommand}; -use serde::{Deserialize, Serialize}; -use std::env::current_dir; -use std::fs::{create_dir, File}; -use std::io::{BufReader, Write}; -use std::net::{IpAddr, Ipv4Addr}; -use std::path::PathBuf; -use nogamepads_lib_rs::DEFAULT_PORT; -use nogamepads_lib_rs::pad_data::game_profile::game_profile::GameProfile; -use nogamepads_lib_rs::pad_data::layout::layout_data::LayoutKeyRegisters; -use nogamepads_lib_rs::pad_service::server::nogamepads_server::PadServer; - -/// NoGamePads Console - Server Cli -#[derive(Parser, Debug)] -#[command(author, version, about, long_about = None)] -struct NoGamepadServerCli { - #[command(subcommand)] - command: Commands, -} - -/// 主要命令 -#[derive(Subcommand, Debug)] -enum Commands { - - #[command(subcommand, about = "Manage buttons")] - Button(ManageCommands), - - #[command(subcommand, about = "Manage directions")] - Direction(ManageCommands), - - #[command(subcommand, about = "Manage axes")] - Axis(ManageCommands), - - // 服务端配置 - #[command(about = "Configure the server")] - Config(ConfigArgs), - - // 运行服务端 - #[command(about = "Run the server")] - Run(RunArgs) -} - -/// 服务端配置 参数 -#[derive(Args, Debug)] -struct ConfigArgs { - - // 绑定的端口号 - #[arg(short, long, help = "Server port (0 = Default)")] // <---- DEFAULT_PORT - port: Option<u16>, - - // 游戏名称 - #[arg(short ='n', long = "name")] - game_name: Option<String>, - - // 游戏描述 - #[arg(short = 'd', long = "description")] - game_description: Option<String>, - - // 游戏组织 - #[arg(short = 'o', long = "organization")] - organization: Option<String>, - - // 游戏版本 - #[arg(short = 'v', long = "version")] - version: Option<String>, - - // 工作室 & 游戏 主页 - #[arg(short = 'w', long = "website")] - website: Option<String>, - - // 交流邮箱 - #[arg(short = 'e', long = "email")] - email: Option<String> -} - -/// 运行服务端 参数 -#[derive(Args, Debug)] -struct RunArgs { - - // 调试模式 - #[arg(long)] - debug: bool, -} - -/// 管理键 -#[derive(Subcommand, Debug)] -enum ManageCommands { - - #[command(about = "Add or rename a key")] - Add(AddKeyArgs), - - #[command(about = "Remove a key")] - Remove(RemoveKeyArgs), - - #[command(about = "List all")] - List -} - -/// 添加键 -#[derive(Args, Debug)] -struct AddKeyArgs{ - - // 添加的键 - #[arg(value_name = "KEY")] - key: u8, - - // 事件编号 - #[arg(value_name = "NAME")] - name: String -} - -/// 移除键 -#[derive(Args, Debug)] -struct RemoveKeyArgs{ - - // 删除的键 - #[arg(value_name = "KEY")] - key: u8, -} - -/// 本地存储的配置信息 -#[derive(Serialize, Deserialize, PartialEq, Debug)] -struct ServerConfig { - port: u16, - registered_keys: LayoutKeyRegisters, - profile: GameProfile, -} - -impl Default for ServerConfig { - fn default() -> Self { - ServerConfig { - port: DEFAULT_PORT, - registered_keys: Default::default(), - profile: GameProfile::default(), - } - } -} - -/// # 快速生成 更新服务端信息 的宏 -macro_rules! update_config { - ($config:expr, $args:expr, $($field:ident),+) => { - $( - if let Some(ref value) = $args.$field { - $config.profile.$field = value.clone(); - println!("Changed profile \"{}\" to \"{}\"", - stringify!($field), - value - ); - } - )+ - }; -} - -fn main () { - - // 命令行 - let cli = NoGamepadServerCli::parse(); - - // 读取服务端配置 - let mut config = read_config(); - - match cli.command { - - // 服务端配置 - Commands::Config(args) => { - - // 端口信息配置: - // 端口数值被限定在 0 - 65535,但是若端口参数为 0,则会被设置为默认端口 - if args.port.is_some() { - let port = args.port.unwrap_or(DEFAULT_PORT).clamp(0, 65535); - config.port = if port == 0 { DEFAULT_PORT } else { port }; - } - - // 其他信息配置 - update_config!( - config, args, - game_name, - game_description, - organization, - version, - website, - email - ); - }, - - // 运行服务端 - Commands::Run(args) => { - // 读取服务端配置 - let config = read_config(); - - // 根据调试选项启动服务端 - if args.debug { - println!("- DEBUG MODE -"); - println!("Server started!"); - PadServer::default() - .addr(IpAddr::from(Ipv4Addr::new(127, 0, 0, 1)), config.port) - .put_profile(config.profile) - .register_keys(config.registered_keys) - .enable_console() - .build() - .start_server(); - } else { - println!("Server started!"); - PadServer::default() - .addr(IpAddr::from(Ipv4Addr::new(127, 0, 0, 1)), config.port) - .put_profile(config.profile) - .register_keys(config.registered_keys) - .build() - .start_server(); - } - } - - Commands::Button(manage) => { - process_manage_command("btn", manage, &mut config.registered_keys.button_keys); - } - - Commands::Direction(manage) => { - process_manage_command("dir", manage, &mut config.registered_keys.direction_keys); - } - - Commands::Axis(manage) => { - process_manage_command("ax", manage, &mut config.registered_keys.axis_keys); - } - } - - // 写入配置 - write_config(config); -} - -fn process_manage_command(prefix: &str, manage: ManageCommands, map: &mut HashMap<u8, String>) { - match manage { - ManageCommands::Add(args) => { - map.entry(args.key) - .or_insert_with(|| args.name.clone()); - println!("Added(Renamed) key {}_{} : \"{}\".", prefix, args.key, args.name); - } - ManageCommands::Remove(args) => { - let removed = map.remove(&args.key); - if removed.is_some() { - println!("Removed key {}_{}.", prefix, removed.is_some()) - } else { - println!("Removed key failed: Cannot found key {}", args.key); - } - } - ManageCommands::List => { - for button_key in map { - println!("{}_{} : \"{}\"", prefix, button_key.0, button_key.1) - } - } - } -} - -#[allow(dead_code)] -fn get_config_folder_path () -> PathBuf { - current_dir().unwrap().join(".nogpads") -} - -#[allow(dead_code)] -fn get_config_file_path () -> PathBuf { - get_config_folder_path().join("config.yaml") -} - -#[allow(dead_code)] -fn get_layout_file_path () -> PathBuf { - get_config_folder_path().join("layout.yaml") -} - -#[allow(dead_code)] -fn get_assets_package_path () -> PathBuf { - get_config_folder_path().join("assets.zip") -} - -fn read_config () -> ServerConfig { - let config_folder_path = get_config_folder_path(); - let config_file_path = get_config_file_path(); - - if ! config_folder_path.exists() { - create_dir(&config_folder_path).unwrap(); - } - - if ! config_file_path.exists() { - let config = ServerConfig::default(); - let config_text = serde_yaml::to_string(&config).unwrap(); - File::create(&config_file_path).unwrap().write_all(config_text.as_bytes()).unwrap(); - config - } else { - let config_file = File::open(&config_file_path).unwrap(); - let config_reader = BufReader::new(config_file); - serde_yaml::from_reader(config_reader).unwrap() - } -} - -fn write_config (config: ServerConfig) { - let config_file_path = get_config_file_path(); - - let config_text = serde_yaml::to_string(&config).unwrap(); - File::create(config_file_path).unwrap().write_all(config_text.as_bytes()).unwrap(); -}
\ No newline at end of file diff --git a/console/src/bin/padc.rs b/console/src/bin/padc.rs new file mode 100644 index 0000000..742b6c2 --- /dev/null +++ b/console/src/bin/padc.rs @@ -0,0 +1,684 @@ +use clap::{Args, CommandFactory, Parser, Subcommand}; +use nogamepads::string_utils::process_id_text; +use nogamepads_console::utils::{confirm, read_password, read_password_and_confirm}; +use nogamepads_core::data::game::structs::GameData; +use nogamepads_core::data::player::structs::Player; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::env::current_dir; +use std::fs::File; +use std::io::{BufReader, Write}; +use std::net::SocketAddr; +use std::path::PathBuf; +use std::process::exit; +use std::str::FromStr; +use std::sync::Arc; +use log::LevelFilter; +use nogamepads::logger_utils::logger_build; +use nogamepads_core::data::controller::cli::cli_command::{process_controller_cli, ControllerCli}; +use nogamepads_core::data::controller::structs::ControllerData; +use nogamepads_core::data::game::cli::cli_command::{process_game_cli, GameCli}; +use nogamepads_core::run_services; +use nogamepads_core::service::cli_addition::runtime_consoles::RuntimeConsole; +use nogamepads_core::service::service_runner::{NoGamepadsService, ServiceRunner}; +use nogamepads_core::service::tcp_network::DEFAULT_PORT; +use nogamepads_core::service::tcp_network::pad_client::structs::PadClientNetwork; +use nogamepads_core::service::tcp_network::pad_server::structs::PadServerNetwork; + +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct ConsoleCli { + #[command(subcommand)] + command: Commands, +} + +#[derive(Subcommand, Debug)] +enum Commands { + + #[command(subcommand, about = "Manage accounts")] + Account(AccountCommands), + + #[command(about = "List accounts")] + Accounts, + + #[command(subcommand, about = "Manage game infos")] + Game(GameCommands), + + #[command(about = "List all games")] + Games, + + #[command(about = "Connect to a service")] + Connect(ConnectArgs), + + #[command(about = "Start a service")] + Listen(ListenArgs) +} + +#[derive(Subcommand, Debug)] +enum AccountCommands { + + #[command(about = "Add a account")] + Add(AccountArgs), + + #[command(about = "Remove a account")] + Remove(AccountArgs), + + #[command(about = "Edit the profile of account")] + Edit(EditAccountArgs) +} + +#[derive(Args, Debug)] +struct AccountArgs{ + + #[arg(value_name = "Account")] + account: String, + + #[arg(short, long, value_name = "Password")] + password: Option<String> +} + +#[derive(Args, Debug)] +struct EditAccountArgs{ + + #[arg(value_name = "Account")] + account: String, + + #[arg(short, long, help = "Nickname")] + nickname: Option<String>, + + #[arg(short = 'c', long = "color", num_args = 3, value_names = ["H", "S", "V"], help = "Player color, h(0 - 360), s(0 - 1), v(0 - 1)")] + color: Option<Vec<f64>> +} + +#[derive(Subcommand, Debug)] +enum GameCommands { + + #[command(about = "Add a game")] + Add(GameArgs), + + #[command(about = "Remove a game")] + Remove(GameArgs), + + #[command(about = "Edit the profile of game")] + Edit(EditGameArgs), + + #[command(subcommand, about = "Register keys to game")] + Register(RegisterKeysCommands) +} + +#[derive(Args, Debug)] +struct GameArgs { + + #[arg(value_name = "Game Name")] + name: String, + + #[arg(short, long)] + confirm: bool +} + +#[derive(Args, Debug)] +struct EditGameArgs { + + #[arg(value_name = "Game Name")] + name: String, + + #[arg(value_name = "Key")] + key: String, + + #[arg(value_name = "Value")] + value: String, +} + +#[derive(Subcommand, Debug)] +enum RegisterKeysCommands { + + #[command(subcommand, about = "Register a button")] + Button(KeyManageCommands), + + #[command(subcommand, about = "Register a axis")] + Axis(KeyManageCommands), + + #[command(subcommand, about = "Register a direction")] + Direction(KeyManageCommands) +} + +#[derive(Subcommand, Debug)] +enum KeyManageCommands { + + #[command(about = "Add or rename a key")] + Add(AddKeyArgs), + + #[command(about = "Remove a key")] + Remove(RemoveKeyArgs), + + #[command(about = "List all")] + List(ListKeyArgs) +} + +#[derive(Args, Debug)] +struct AddKeyArgs{ + + #[arg(value_name = "Game Name")] + name: String, + + #[arg(value_name = "Key")] + key: u8, + + #[arg(value_name = "Name")] + key_name: String +} + +#[derive(Args, Debug)] +struct RemoveKeyArgs{ + + #[arg(value_name = "Game Name")] + name: String, + + #[arg(value_name = "Key")] + key: u8, +} + +#[derive(Args, Debug)] +struct ListKeyArgs{ + + #[arg(value_name = "Game Name")] + name: String +} + +#[derive(Args, Debug)] +struct ConnectArgs { + + #[arg(short, long, value_name = "Account")] + account: Option<String>, + + #[arg(short, long, value_name = "Address")] + tcp_addr: Option<String>, + + #[arg(short, long, value_name = "Methods")] + method: Option<String>, + + #[arg(long)] + cmd: bool, + + #[arg(long)] + gui: bool, + + #[arg(long)] + debug: bool, +} + +#[derive(Args, Debug)] +struct ListenArgs { + + #[arg(value_name = "Game")] + game: String, + + #[arg(short = 'a', long, value_name = "Address")] + tcp_addr: Option<String>, + + #[arg(long)] + cmd: bool, + + #[arg(long)] + gui: bool, + + #[arg(long)] + tcp: bool, + + #[arg(long)] + bluetooth: bool, + + #[arg(long)] + usb: bool, + + #[arg(long)] + debug: bool, +} + +#[derive(Default, Serialize, Deserialize, PartialEq, Debug)] +struct LocalData { + game_data: LocalGameData, + controller_data: LocalControllerData, +} + +#[derive(Default, Serialize, Deserialize, PartialEq, Debug)] +struct LocalGameData { + games: HashMap<String, GameData> +} + +#[derive(Default, Serialize, Deserialize, PartialEq, Debug)] +struct LocalControllerData { + players: HashMap<String, Player> +} + +fn main () { + let cli = ConsoleCli::parse(); + let mut data = read(); + + match cli.command { + Commands::Account(cmds) => { + match cmds { + AccountCommands::Add(args) => { + add_player(&mut data, args.account, args.password); + } + + AccountCommands::Remove(args) => { + remove_player(&mut data, args.account, args.password); + } + + AccountCommands::Edit(args) => { + edit_player(&mut data, args); + } + } + } + + Commands::Accounts => { + for player in data.controller_data.players.values() { + let id = &player.account.id; + if player.customize.is_some() { + let nickname = &player.clone().customize.unwrap().nickname; + println!("{}({})", id, nickname); + } else { + println!("{}", id); + } + } + } + + Commands::Game(cmds) => { + match cmds { + GameCommands::Add(args) => { + let name = process_id_text(args.name); + data.game_data.games.entry(name.clone()) + .or_insert_with(GameData::default); + println!("Game configuration added or reset: \"{}\"", name.clone()); + } + + GameCommands::Remove(args) => { + if ! args.confirm { + if ! confirm("Confirm ") { + exit(1); + } + } + + let name = process_id_text(args.name); + let game = data.game_data.games.remove(&name); + if game.is_none() { + eprintln!("Removal of the game \"{}\" failed: game not found.", name.clone()); + } else { + println!("The game \"{}\" has been removed.", name.clone()); + } + } + + GameCommands::Edit(args) => { + let name = process_id_text(args.name); + let game = data.game_data.games.get_mut(&name); + if game.is_none() { + eprintln!("Edit the game \"{}\" failed: game not found.", name.clone()); + } else { + let mut game = game.unwrap(); + game.info(args.key.clone(), args.value.clone()); + println!("Set the game info \"{}\" to \"{}\".", args.key, args.value); + } + } + + GameCommands::Register(cmds) => { + match cmds { + RegisterKeysCommands::Button(cmds) => { + manage_keys(&mut data, cmds, + |game| &mut game.control.button_keys); + } + + RegisterKeysCommands::Axis(cmds) => { + manage_keys(&mut data, cmds, + |game| &mut game.control.axis_keys); + } + + RegisterKeysCommands::Direction(cmds) => { + manage_keys(&mut data, cmds, + |game| &mut game.control.direction_keys); + } + } + } + } + } + + Commands::Games => { + for (key, _) in data.game_data.games.iter() { + println!("{}", key); + } + } + + Commands::Connect(args) => { + connect(&mut data, args); + } + + Commands::Listen(args) => { + listen(&mut data, args); + } + } + + write(data); +} + +fn connect(data: &mut LocalData, args: ConnectArgs) { + + let mut result: Option<&Player> = None; + if args.account.is_some() { + // Account specified + let id = &args.account.unwrap(); + let player = data.controller_data.players.get(id); + + // Account not found + if player.is_none() { + eprintln!("Account not found: \"{}\"", id); + exit(1); + } else { + // Account exists + result = Some(player.unwrap()); + } + } else { + // Account not specified + for found in data.controller_data.players.values() { + // Found a replaceable account + result = Some(found); + println!("Account not specified! Using account \"{}\" instead!", found.account.id); + break; + } + // No replaceable account found + if result.is_none() { + eprintln!("Cannot find any replaceable account! Please ensure at least one account exists locally!"); + exit(1); + } + } + + let player = result.unwrap().clone(); + + let mut controller = ControllerData::default(); + controller.bind_player(player); + + let runtime = controller.runtime(); + + let method = args.method.unwrap_or("tcp".to_string()); + let mut entry: Option<NoGamepadsService> = None; + match method.as_str() { + "tcp" => { + let mut client = PadClientNetwork::build(Arc::clone(&runtime)); + let addr = args.tcp_addr.unwrap_or(format!("127.0.0.1:{}", DEFAULT_PORT)); + client.bind_addr(SocketAddr::from_str(&addr).unwrap_or( + SocketAddr::from(([127, 0, 0, 1], DEFAULT_PORT)), + )); + + entry = Some(client.build_entry()); + }, + + "bluetooth" => { + // TODO :: BLUETOOTH METHOD + }, + + "usb" => { + // TODO :: USB METHOD + }, + + _ => { + eprintln!("Unknown connection method: {}", method); + exit(1); + } + } + + if let Some(entry) = entry { + let mut services = Vec::new(); + services.push(entry); + + if args.cmd { + services.push(RuntimeConsole::build( + ControllerCli::command(), + "ControllerCli".to_string(), + Arc::clone(&runtime), + |runtime, cmd| { + process_controller_cli(runtime, cmd); + } + ).build_entry()); + } + + if args.gui { + + } + + if args.debug { + logger_build(LevelFilter::Trace); + } else { + logger_build(LevelFilter::Info); + } + + ServiceRunner::run(services); + } +} + +fn listen(data: &mut LocalData, args: ListenArgs) { + let id = process_id_text(args.game); + let game = data.game_data.games.get(&id); + if game.is_none() { + eprintln!("Game not found: \"{}\"", id); + exit(1); + } + + let game_data = game.unwrap().clone(); + + let runtime = game_data.runtime(); + + let mut services = Vec::new(); + + if args.tcp { + let mut server = PadServerNetwork::build(Arc::clone(&runtime)); + if args.tcp_addr.is_some() { + let addr = SocketAddr::from_str(&args.tcp_addr.unwrap()) + .unwrap_or(SocketAddr::from(([127, 0, 0, 1], DEFAULT_PORT))); + server.bind_ip(addr.ip()); + server.bind_port(addr.port()); + } + services.push(server.build_entry()); + println!("Setup TCP Service!") + } + + if args.bluetooth { + + } + + if args.usb { + + } + + if args.cmd { + services.push(RuntimeConsole::build( + GameCli::command(), + "GameCli".to_string(), + Arc::clone(&runtime), + |runtime, cmd| { + process_game_cli(runtime, cmd); + } + ).build_entry()); + println!("Setup Command Line!") + } + + if args.gui { + + } + + if args.debug { + logger_build(LevelFilter::Trace); + } else { + logger_build(LevelFilter::Info); + } + + ServiceRunner::run(services); +} + +fn add_player(data: &mut LocalData, account_args: String, password_args: Option<String>) { + if data.controller_data.players.contains_key(process_id_text(account_args.clone()).as_str()) { + eprintln!("This account already exists. Please do not create it again."); + exit(1); + } else { + // Read password + let mut password = "".to_string(); + if password_args.is_none() { + let input = read_password_and_confirm("Enter password: ", "Confirm: "); + if input.is_some() { + password = input.unwrap(); + } + } else if password_args.is_some() { + password = password_args.unwrap(); + } + + // Create player + let player = Player::register(account_args, password); + let player_key = player.clone().account.id; + + data.controller_data.players.insert(player_key, player.clone()); + } +} + +fn remove_player(data: &mut LocalData, account_args: String, password_args: Option<String>) { + // Read password + let mut password = "".to_string(); + if password_args.is_none() { + password = read_password("Enter password: ").unwrap_or("".to_string()); + } else if password_args.is_some() { + password = password_args.unwrap(); + } + + // Remove + let player_id = process_id_text(account_args.clone()); + + let player = data.controller_data.players.get(&player_id); + if player.is_none() { + eprintln!("Failed to remove account \"{}\": Account not found.", account_args.clone()); + exit(1); + } + let player = player.unwrap(); + + if player.check(password.clone()) { + data.controller_data.players.remove(player_id.as_str()); + println!("The account \"{}\" has been removed!", player_id); + } else { + eprintln!("Failed to remove account \"{}\": Password is incorrect!", player_id) + } +} + +fn edit_player(data: &mut LocalData, args: EditAccountArgs) { + let account_id = process_id_text(args.account); + if ! data.controller_data.players.contains_key(&account_id) { + eprintln!("Edit failed: Account \"{}\" not found!", account_id); + exit(1); + } + + let player = data.controller_data.players.get_mut(&account_id).unwrap(); + + if args.nickname.is_some() { + let nickname = args.nickname.unwrap(); + player.nickname(&nickname); + println!("Change the nickname of account \"{}\" to \"{}\"", account_id, &nickname); + } + + if args.color.is_some() { + let color = args.color.unwrap(); + let hue = color[0].round().clamp(0.0, 360.0); + let sat = color[1].clamp(0.0, 1.0); + let val = color[2].clamp(0.0, 1.0); + player.hsv(hue as i32, sat, val); + println!("Change the color of account \"{}\" to \"{}\"", account_id, hsv_to_hex(hue as i32, sat, val)); + } +} + +macro_rules! check_game { + ($data:expr, $args:expr, |$game:ident| $code:block) => { + let name = process_id_text($args.name); + let mut game = $data.game_data.games.get_mut(&name); + if game.is_none() { + eprintln!("Edit the game \"{}\" failed: game not found.", name.clone()); + exit(1); + } else { + let mut $game = game.unwrap(); + $code + } + }; +} + +fn manage_keys(data: &mut LocalData, cmds: KeyManageCommands, get_map: fn(game: &mut GameData) -> &mut HashMap<u8, String>) { + match cmds { + KeyManageCommands::Add(args) => { + check_game!(data, args, |game| { + get_map(game).entry(args.key) + .or_insert_with(|| args.key_name.clone()); + println!("Registered key \"{}\"", args.key_name); + }); + } + + KeyManageCommands::Remove(args) => { + check_game!(data, args, |game| { + let result = get_map(game).remove(&args.key); + if result.is_some() { + println!("Removed key \"{}\"", result.unwrap()); + } + }); + } + + KeyManageCommands::List(args) => { + check_game!(data, args, |game| { + for (key, key_name) in get_map(game).iter() { + println!("{} - \"{}\"", key, key_name); + } + }); + } + } +} + +fn local_config() -> PathBuf { + current_dir().unwrap().join("nogamepads.yaml") +} + +fn read() -> LocalData { + let file_path = local_config(); + + if ! file_path.exists() { + let data = LocalData::default(); + let content = serde_yaml::to_string(&data).unwrap(); + File::create(&file_path).unwrap().write_all(content.as_bytes()).unwrap(); + data + } else { + let file = File::open(&file_path).unwrap(); + let reader = BufReader::new(file); + serde_yaml::from_reader(reader).unwrap() + } +} + +fn write(config: LocalData) { + let file_path = local_config(); + let content = serde_yaml::to_string(&config).unwrap(); + + File::create(file_path).unwrap().write_all(content.as_bytes()).unwrap(); +} + +fn hsv_to_hex(h: i32, s: f64, v: f64) -> String { + let h = (h as f64).clamp(0.0, 360.0); + let s = s.clamp(0.0, 1.0); + let v = v.clamp(0.0, 1.0); + + let c = v * s; + let x = c * (1.0 - ((h / 60.0) % 2.0 - 1.0).abs()); + let m = v - c; + + let (r, g, b) = match (h / 60.0) as usize { + 0 => (c, x, 0.0), + 1 => (x, c, 0.0), + 2 => (0.0, c, x), + 3 => (0.0, x, c), + 4 => (x, 0.0, c), + 5 => (c, 0.0, x), + _ => (0.0, 0.0, 0.0), + }; + + let r = ((r + m) * 255.0).round() as u8; + let g = ((g + m) * 255.0).round() as u8; + let b = ((b + m) * 255.0).round() as u8; + format!("#{:02X}{:02X}{:02X}", r, g, b) +} diff --git a/console/src/lib.rs b/console/src/lib.rs index e69de29..fab870e 100644 --- a/console/src/lib.rs +++ b/console/src/lib.rs @@ -0,0 +1 @@ +pub mod utils;
\ No newline at end of file diff --git a/console/src/utils.rs b/console/src/utils.rs new file mode 100644 index 0000000..1e65f0e --- /dev/null +++ b/console/src/utils.rs @@ -0,0 +1,107 @@ +use std::io::{self, Read, Write}; +use crossterm::terminal; +use tokio::task; + +pub fn read_password(prompt: &str) -> Option<String> { + print!("{}", prompt); + io::stdout().flush().unwrap(); + + let raw_mode_enabled = terminal::enable_raw_mode().is_ok(); + if !raw_mode_enabled { + eprintln!("Warning: Password will be displayed in plain text"); + } + + let mut buffer = Vec::new(); + loop { + let mut byte = [0]; + if io::stdin().read(&mut byte).is_err() || byte[0] == b'\n' || byte[0] == b'\r' { + break; + } + + match byte[0] { + 8 | 127 => { + if buffer.pop().is_some() { + print!("\x08 \x08"); + io::stdout().flush().unwrap(); + } + } + 3 => { + println!(); + return None; + } + _ => { + buffer.push(byte[0]); + print!("*"); + io::stdout().flush().unwrap(); + } + } + } + + if raw_mode_enabled { + terminal::disable_raw_mode().unwrap(); + } + println!(); + + Some(String::from_utf8_lossy(&buffer).into_owned()) +} + +pub fn read_password_and_confirm( + prompt: &str, + confirm_prompt: &str +) -> Option<String> { + loop { + let pw1 = read_password(prompt).unwrap(); + let pw2 = read_password(confirm_prompt).unwrap(); + + if pw1 == pw2 { + return Some(pw1); + } + eprintln!("The passwords entered twice do not match, please try again."); + } +} + +pub fn confirm(prompt: &str) -> bool { + let prompt = format!("{} [Y/n]: ", prompt); + loop { + let input = read_password(&prompt).unwrap_or_default(); + match input.to_lowercase().as_str() { + "y" | "yes" | "" => return true, + "n" | "no" => return false, + _ => eprintln!("Invalid input, please enter Y or n."), + } + } +} + +pub async fn read_password_async(prompt: &str) -> Option<String> { + let prompt = prompt.to_owned(); + task::spawn_blocking(move || read_password(&prompt)) + .await + .unwrap_or_else(|_| None) +} + +pub async fn read_password_and_confirm_async( + prompt: &str, + confirm_prompt: &str +) -> Option<String> { + loop { + let pw1 = read_password_async(prompt).await.unwrap(); + let pw2 = read_password_async(confirm_prompt).await.unwrap(); + + if pw1 == pw2 { + return Some(pw1); + } + eprintln!("The passwords entered twice do not match, please try again."); + } +} + +pub async fn confirm_async(prompt: &str) -> bool { + let prompt = format!("{} [Y/n]: ", prompt); + loop { + let input = read_password_async(&prompt).await.unwrap_or_default(); + match input.to_lowercase().as_str() { + "y" | "yes" | "" => return true, + "n" | "no" => return false, + _ => eprintln!("Invalid input, please enter Y or n."), + } + } +}
\ No newline at end of file diff --git a/core/Cargo.toml b/core/Cargo.toml index 29f612c..f943cb7 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -14,7 +14,8 @@ clap = { version = "4.5.38", features = ["derive"] } sha1 = "0.10.6" log = "0.4.27" prettytable-rs = "0.10.0" +shell-words = "1.1.0" [lib] -name = "nogamepads_lib_rs" +name = "nogamepads_core" crate-type = [ "rlib"]
\ No newline at end of file diff --git a/core/examples/connect.rs b/core/examples/connect.rs new file mode 100644 index 0000000..c367787 --- /dev/null +++ b/core/examples/connect.rs @@ -0,0 +1,25 @@ +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; + +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)); + client.connect(); +}
\ No newline at end of file diff --git a/core/examples/start_client_console.rs b/core/examples/start_client_console.rs deleted file mode 100644 index c4e0126..0000000 --- a/core/examples/start_client_console.rs +++ /dev/null @@ -1,24 +0,0 @@ -use std::net::{IpAddr, Ipv4Addr}; -use nogamepads_lib_rs::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; -use nogamepads_lib_rs::pad_service::client::nogamepads_client::PadClient; - -fn main() { - - // 构建玩家信息 - let mut player_info = PlayerInfo::new(); - player_info.setup_account_info( - env!("TEST_PLAYER_ACCOUNT"), - env!("TEST_PLAYER_PASSWORD")); - player_info.set_nickname(env!("TEST_PLAYER_NICKNAME")); - player_info.set_customize_color_hsv(320, 0.5, 1.0); // PINK - - // 构建客户端 - let mut client = PadClient::bind_addr( - IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)) - ); - client.bind_player(player_info); // 绑定玩家 - client.enable_console(); // 启用控制台 - - // 连接至目标地址 - client.connect(); -}
\ No newline at end of file diff --git a/core/examples/start_server_console.rs b/core/examples/start_server_console.rs deleted file mode 100644 index cbe081f..0000000 --- a/core/examples/start_server_console.rs +++ /dev/null @@ -1,40 +0,0 @@ -use std::net::{IpAddr, Ipv4Addr}; -use nogamepads_lib_rs::DEFAULT_PORT; -use nogamepads_lib_rs::pad_data::game_profile::game_profile::GameProfile; -use nogamepads_lib_rs::pad_service::server::nogamepads_server::PadServer; - -fn main() { - - // 简易构建服务端 - // let server = PadServer::build_simple(); - // server.start_listening_debug() - - // 构建服务端 - let server = PadServer::default() - - // 地址 - .addr(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), DEFAULT_PORT) - - // 配置信息 - .put_profile( - GameProfile::default() - .game_name("My Multiplayer Game") - .game_description("My Game Description") - .version("0.1 alpha") - .to_owned() - ) - - // 键位注册 - .register_button(0, "Shoot") - .register_button(1, "Jump") - .register_direction(0, "Walk") - .register_axis(0, "View Yaw") - - // 控制台 - .enable_console() - // .quiet() - .build(); - - // 运行服务端 - server.start_server(); -}
\ No newline at end of file diff --git a/core/examples/tcp_server.rs b/core/examples/tcp_server.rs new file mode 100644 index 0000000..6c0e60b --- /dev/null +++ b/core/examples/tcp_server.rs @@ -0,0 +1,43 @@ +use clap::CommandFactory; +use nogamepads::logger_utils::logger_build; +use nogamepads_core::data::game::cli::cli_command::{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 diff --git a/core/examples/tetris_multicmd_game.rs b/core/examples/tetris_multicmd_game.rs deleted file mode 100644 index 356a1cf..0000000 --- a/core/examples/tetris_multicmd_game.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - // env!("CARGO") -}
\ No newline at end of file diff --git a/core/src/data/controller/cli/cli_command.rs b/core/src/data/controller/cli/cli_command.rs new file mode 100644 index 0000000..b5c0414 --- /dev/null +++ b/core/src/data/controller/cli/cli_command.rs @@ -0,0 +1,48 @@ +use std::sync::{Arc, Mutex}; +use clap::{Parser, Subcommand}; +use nogamepads::entry_mutex; +use crate::data::controller::runtime::structs::ControllerRuntime; +use crate::data::message::enums::ControlMessage; +use crate::data::message::traits::MessageManager; +use crate::service::service_types::ServiceType::TCPConnection; + +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +pub struct ControllerCli { + #[command(subcommand)] + command: Commands, +} + +#[derive(Subcommand, Debug)] +enum Commands { + + #[command(about = "Clean the screen")] + Clear, + + #[command(about = "Send a message")] + Message, + + #[command(about = "Close the controller")] + Close +} + +pub fn process_controller_cli(runtime: Arc<Mutex<ControllerRuntime>>, cmd: ControllerCli) { + + match cmd.command { + Commands::Clear => { + + } + + Commands::Message => { + entry_mutex!(runtime, |guard| { + guard.send(ControlMessage::Msg("fuck".to_string()), 0, TCPConnection); + }); + } + + Commands::Close => { + entry_mutex!(runtime, |guard| { + guard.close(); + }); + } + } +}
\ No newline at end of file diff --git a/core/src/data/controller/cli/mod.rs b/core/src/data/controller/cli/mod.rs new file mode 100644 index 0000000..043f7b8 --- /dev/null +++ b/core/src/data/controller/cli/mod.rs @@ -0,0 +1 @@ +pub mod cli_command;
\ No newline at end of file diff --git a/core/src/data/controller/implements.rs b/core/src/data/controller/implements.rs new file mode 100644 index 0000000..86a19de --- /dev/null +++ b/core/src/data/controller/implements.rs @@ -0,0 +1,21 @@ +use std::sync::{Arc, Mutex}; +use crate::data::controller::runtime::structs::ControllerRuntime; +use crate::data::controller::structs::ControllerData; +use crate::data::player::structs::Player; + +impl ControllerData { + + pub fn bind_player(&mut self, player: Player) -> &mut ControllerData { + self.player = player; + self + } + + /// Build the controller-side runtime using controller data + pub fn runtime(self) -> Arc<Mutex<ControllerRuntime>> { + let runtime = ControllerRuntime { + player: self.player, + ..Default::default() + }; + Arc::new(Mutex::new(runtime)) + } +}
\ No newline at end of file diff --git a/core/src/data/controller/mod.rs b/core/src/data/controller/mod.rs new file mode 100644 index 0000000..019ebcf --- /dev/null +++ b/core/src/data/controller/mod.rs @@ -0,0 +1,4 @@ +pub mod cli; +pub mod runtime; +pub mod implements; +pub mod structs;
\ No newline at end of file diff --git a/core/src/data/controller/runtime/implements.rs b/core/src/data/controller/runtime/implements.rs new file mode 100644 index 0000000..b79890e --- /dev/null +++ b/core/src/data/controller/runtime/implements.rs @@ -0,0 +1,29 @@ +use std::collections::{HashMap, VecDeque}; +use std::sync::atomic::Ordering::SeqCst; +use log::trace; +use crate::data::controller::runtime::structs::ControllerRuntime; +use crate::data::message::enums::{ControlMessage, GameMessage}; +use crate::data::message::traits::MessageManager; +use crate::service::service_types::ServiceType; + +/// Message manager for controller-side runtime +/// After the service starts, it can be accessed or relevant messages can be stored. +impl MessageManager<GameMessage, ControlMessage, u8> for ControllerRuntime { + fn borrow_received_list_mut(&mut self) -> &mut HashMap<(ServiceType, u8), VecDeque<GameMessage>> { + &mut self.received + } + + fn borrow_send_list_mut(&mut self) -> &mut HashMap<(ServiceType, u8), VecDeque<ControlMessage>> { + &mut self.send + } +} + +impl ControllerRuntime { + + pub fn close(&mut self) { + if !self.close.load(SeqCst) { + self.close.store(true, SeqCst); + trace!("[Controller Runtime] Closed."); + } + } +}
\ No newline at end of file diff --git a/core/src/data/controller/runtime/mod.rs b/core/src/data/controller/runtime/mod.rs new file mode 100644 index 0000000..0ff870f --- /dev/null +++ b/core/src/data/controller/runtime/mod.rs @@ -0,0 +1,2 @@ +pub mod implements; +pub mod structs;
\ No newline at end of file diff --git a/core/src/data/controller/runtime/structs.rs b/core/src/data/controller/runtime/structs.rs new file mode 100644 index 0000000..7be2cd6 --- /dev/null +++ b/core/src/data/controller/runtime/structs.rs @@ -0,0 +1,20 @@ +use std::collections::{HashMap, VecDeque}; +use std::sync::atomic::AtomicBool; +use crate::data::game::types::GameInfo; +use crate::data::message::enums::{ControlMessage, GameMessage}; +use crate::data::player::structs::Player; +use crate::service::service_types::ServiceType; + +/// Controller-side runtime +/// Stores all data involved in game pad_client interactions during runtime +#[derive(Default)] +pub struct ControllerRuntime { + + pub(crate) received: HashMap<(ServiceType, u8), VecDeque<GameMessage>>, + pub(crate) send: HashMap<(ServiceType, u8), VecDeque<ControlMessage>>, + + pub(crate) player: Player, + + pub game_info: GameInfo, + pub close: AtomicBool +}
\ No newline at end of file diff --git a/core/src/data/controller/structs.rs b/core/src/data/controller/structs.rs new file mode 100644 index 0000000..c6fdd31 --- /dev/null +++ b/core/src/data/controller/structs.rs @@ -0,0 +1,10 @@ +use crate::data::player::structs::Player; + +/// Controller-side Data +/// Describes the basic information of the controller side +#[derive(Default)] +pub struct ControllerData { + + /// Player bound to the controller side + pub(crate) player: Player +}
\ No newline at end of file diff --git a/core/src/data/game/cli/cli_command.rs b/core/src/data/game/cli/cli_command.rs new file mode 100644 index 0000000..1d79515 --- /dev/null +++ b/core/src/data/game/cli/cli_command.rs @@ -0,0 +1,35 @@ +use std::sync::{Arc, Mutex}; +use clap::{Parser, Subcommand}; +use nogamepads::entry_mutex; +use crate::data::game::runtime::structs::GameRuntime; + +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +pub struct GameCli { + #[command(subcommand)] + command: Commands, +} + +#[derive(Subcommand, Debug)] +enum Commands { + + #[command(about = "Clean the screen")] + Clear, + + #[command(about = "Close the game")] + Close +} + +pub fn process_game_cli(runtime: Arc<Mutex<GameRuntime>>, cmd: GameCli) { + match cmd.command { + Commands::Clear => { + + } + + Commands::Close => { + entry_mutex!(runtime, |guard| { + guard.close_game(); + }) + } + } +}
\ No newline at end of file diff --git a/core/src/data/game/cli/mod.rs b/core/src/data/game/cli/mod.rs new file mode 100644 index 0000000..043f7b8 --- /dev/null +++ b/core/src/data/game/cli/mod.rs @@ -0,0 +1 @@ +pub mod cli_command;
\ No newline at end of file diff --git a/core/src/data/game/implements.rs b/core/src/data/game/implements.rs new file mode 100644 index 0000000..ad86572 --- /dev/null +++ b/core/src/data/game/implements.rs @@ -0,0 +1,99 @@ +use std::sync::{Arc, Mutex}; +use nogamepads::entry_mutex; +use crate::data::game::runtime::structs::{GameControlRuntime, GameRuntime, GameRuntimeData}; +use crate::data::game::structs::{GameControlData, GameData, GameRuntimeDataArchive}; +use crate::data::game::types::{GameInfo, Players}; +use crate::data::player::structs::Player; + +impl Default for GameData { + fn default() -> Self { + GameData::new() + } +} + +impl GameData { + + /// Create new game data + pub fn new() -> GameData { + let mut game = GameData { + info: GameInfo::default(), + control: GameControlData::default(), + archive: GameRuntimeDataArchive::default(), + }; + + game.name("Mini Hero".to_string()); + game.version(env!("PROJECT_VERSION").to_string()); + game + } + + /// Add or modify game name information + pub fn name(&mut self, name: String) -> &mut GameData { + self.info("Game_Name".to_string(), name); + self + } + + /// Add or modify game version information + pub fn version(&mut self, version: String) -> &mut GameData { + self.info("Version".to_string(), version); + self + } + + /// Add or modify information for a specific entry + pub fn info(&mut self, name: String, value: String) -> &mut GameData { + self.info.insert(name, value); + self + } + + /// Read game runtime archive data + pub fn load_data(&mut self, storage: GameRuntimeDataArchive) -> &mut GameData { + self.archive = storage; + self + } + + /// Build the game-side runtime using game data + pub fn runtime(self) -> Arc<Mutex<GameRuntime>> { + let runtime = GameRuntime { + info: self.info, + data: self.archive.into(), + control: GameControlRuntime { + keys: self.control, + ..Default::default() + }, + + writer_count: 0, + reader_count: 0, + }; + Arc::new(Mutex::new(runtime)) + } +} + +impl From<GameRuntimeDataArchive> for GameRuntimeData { + fn from(archive: GameRuntimeDataArchive) -> Self { + let banned_mutex = Players::default(); + entry_mutex!(banned_mutex, |guard| { + for account in archive.banned { + let player_info = Player::from(account.clone()); + guard.entry(account).or_insert_with(|| player_info); + } + }); + GameRuntimeData { + players_banned : banned_mutex, + ..Self::default() + } + } +} + +impl From<GameRuntimeData> for GameRuntimeDataArchive { + fn from(data: GameRuntimeData) -> Self { + let mut banned = Vec::new(); + entry_mutex!(data.players_online, |guard| { + for account in guard.keys().into_iter() { + banned.push(account.to_owned()); + } + }); + + GameRuntimeDataArchive { + banned + } + } +}
\ No newline at end of file diff --git a/core/src/data/game/mod.rs b/core/src/data/game/mod.rs new file mode 100644 index 0000000..4a0a3d4 --- /dev/null +++ b/core/src/data/game/mod.rs @@ -0,0 +1,6 @@ +pub mod cli; +pub mod runtime; + +pub mod implements; +pub mod structs; +pub mod types;
\ No newline at end of file diff --git a/core/src/data/game/runtime/implements.rs b/core/src/data/game/runtime/implements.rs new file mode 100644 index 0000000..62038ba --- /dev/null +++ b/core/src/data/game/runtime/implements.rs @@ -0,0 +1,324 @@ +use std::collections::{HashMap, VecDeque}; +use std::sync::atomic::AtomicBool; +use std::sync::atomic::Ordering::SeqCst; +use log::{info, trace, warn}; +use nogamepads::entry_mutex; +use crate::data::game::runtime::structs::{GameControlRuntime, GameRuntime, GameRuntimeData}; +use crate::data::game::types::Players; +use crate::data::message::enums::{JoinFailedMessage, ControlMessage, ExitReason, GameMessage}; +use crate::data::message::enums::JoinFailedMessage::{ContainIdenticalPlayer, GameLocked, PlayerBanned}; +use crate::data::message::enums::ControlMessage::{Axis, Dir, Msg, Pressed, Released}; +use crate::data::message::enums::GameMessage::LetExit; +use crate::data::message::traits::MessageManager; +use crate::data::player::structs::{Account, Player}; +use crate::service::service_types::ServiceType; +use crate::service::service_types::ServiceType::TCPConnection; + +impl GameRuntime { + + /// Attempt to have the specified player join the game + pub fn try_join_player(&mut self, player: Player) -> Result<(), JoinFailedMessage> { + let join = self.can_join_game(&player.account); + match join { + Ok(_) => { + self.data.sign_player_online_status(&player, TCPConnection, true); + trace!("[Game Runtime] Player \"{}\" joined", player.account); + Ok(()) + } + Err(why) => { + warn!("[Game Runtime] Player \"{}\" join failed: {:?}", player.account, why); + Err(why) + } + } + } + + fn can_join_game(&self, account: &Account) -> Result<bool, JoinFailedMessage> { + + if self.is_game_locked() { + Err(GameLocked) + } else if self.data.is_account_banned(account) { + Err(PlayerBanned) + } else if self.data.is_account_online(account) { + Err(ContainIdenticalPlayer) + } else { + Ok(true) + } + } + + /// Request an account to exit + pub fn let_account_exit(&mut self, account: &Account, reason: ExitReason, service_type: ServiceType) { + // Send a leave message to the pad_client and wait for it to actively disconnect + if self.data.is_account_online(account) { + self.send((account.clone(), LetExit(reason)), account.clone(), service_type); + } + } + + /// Check if the game is locked + pub fn is_game_locked(&self) -> bool { + self.data.locked.load(SeqCst) + } + + /// Lock the game + pub fn lock_game(&self) { + if !self.data.locked.load(SeqCst) { + self.data.locked.store(true, SeqCst); + info!("[Game Runtime] Game locked!"); + } + } + + /// Unlock the game + pub fn unlock_game(&self) { + if self.data.locked.load(SeqCst) { + self.data.locked.store(false, SeqCst); + info!("[Game Runtime] Game unlocked!"); + } + } + + /// Close the Game + pub fn close_game(&self) { + if !self.data.close.load(SeqCst) { + self.data.close.store(true, SeqCst); + info!("[Game Runtime] Game closed!"); + } + } +} + +/// Message manager for game pad_client runtime +/// After the service starts, it can be accessed or relevant messages can be stored. +impl MessageManager<(Account, ControlMessage), (Account, GameMessage), Account> for GameRuntime { + fn borrow_received_list_mut(&mut self) -> &mut HashMap<(ServiceType, Account), VecDeque<(Account, ControlMessage)>> { + &mut self.data.received + } + + fn borrow_send_list_mut(&mut self) -> &mut HashMap<(ServiceType, Account), VecDeque<(Account, GameMessage)>> { + &mut self.data.send + } + + fn pop_from_send_list(&mut self, key: Account, service: ServiceType) -> Option<(Account, GameMessage)> { + let key = (service, key); + self.borrow_send_list_mut() + .entry(key) + .or_insert_with(VecDeque::new) + .pop_front() + } + + fn put_into_receive_list(&mut self, message: (Account, ControlMessage), _key: Account, _service: ServiceType) { + let result = self.control.process_control_message(&message.0, message.1); + if result.is_err() { + let result = result.unwrap_err(); + warn!("[Game Runtime] Can't process message: {:?}", result); + drop(result); + } + } +} + +impl Default for GameRuntimeData { + fn default() -> Self { + Self { + received: Default::default(), + send: Default::default(), + players_online: Players::default(), + players_banned: Players::default(), + + locked: AtomicBool::new(false), + close: AtomicBool::new(false) + } + } +} + +impl GameRuntimeData { + + /// Mark a player as online + pub fn sign_player_online_status(&mut self, player: &Player, service_type: ServiceType, value: bool) { + let online = self.is_account_online(&player.account); + if online && !value { + + // Remove player + entry_mutex!(self.players_online, |guard| { + guard.remove_entry(&player.account); + }); + + info!("[Game Runtime] Signed player \"{}\" is [OFFLINE]!", player.account); + + // Reset runtime + let key = (service_type, player.account.clone()); + let get_received = self.received.get_mut(&key); + let get_send = self.send.get_mut(&key); + if let Some(mut list) = get_received { + list.clear(); + } + if let Some(mut list) = get_send { + list.clear(); + } + + } else if !online & value { + + // Insert player + entry_mutex!(self.players_online, |guard| { + guard.entry(player.account.clone()) + .or_insert_with(|| player.clone()); + }); + + info!("[Game Runtime] Signed player \"{}\" is [ONLINE]!", player.account); + } + } + + /// Returns all online accounts + pub fn online_accounts(&self) -> Vec<Account> { + let mut vec = Vec::new(); + entry_mutex!(self.players_online, |guard| { + for account in guard.keys().into_iter() { + vec.push(account.clone()); + } + }); + vec + } + + /// Check if specified account is online + pub fn is_account_online(&self, account: &Account) -> bool { + entry_mutex!(self.players_online, |guard| { + if guard.contains_key(account) { + return true; + } + }); + false + } + + /// Returns all banned accounts + pub fn banned_accounts(&self) -> Vec<Account> { + let mut vec = Vec::new(); + entry_mutex!(self.players_banned, |guard| { + for account in guard.keys().into_iter() { + vec.push(account.clone()); + } + }); + vec + } + + /// Check if account is banned + pub fn is_account_banned(&self, account: &Account) -> bool { + entry_mutex!(self.players_banned, |guard| { + if guard.contains_key(account) { + true; + } + }); + false + } +} + +impl GameControlRuntime { + + /// Process a control message + fn process_control_message(&mut self, who: &Account, msg: ControlMessage) -> Result<(), ControlMessage> { + match msg { + Msg(_) => { + self.send_event(who, msg); + Ok(()) + } + + Pressed(button_key) => { + let key_valid = self.check_key(&self.keys.button_keys, &button_key); + if key_valid { + Self::change_value(&mut self.button, button_key, who, true); + self.send_event(who, msg); + trace!("[Control Runtime] Player \"{}\" pressed btn_{}", &who.id, button_key); + } else { + warn!("[Control Runtime] Key btn_{} not registered!", button_key); + } + Ok(()) + } + + Released(button_key) => { + if self.check_key(&self.keys.button_keys, &button_key) { + Self::change_value(&mut self.button, button_key, who, false); + self.send_event(who, msg); + trace!("[Control Runtime] Player \"{}\" released btn_{}", &who.id, button_key); + } else { + warn!("[Control Runtime] Key btn_{} not registered!", button_key); + } + Ok(()) + } + + Axis(axis_key, axis) => { + if self.check_key(&self.keys.button_keys, &axis_key) { + Self::change_value(&mut self.axes, axis_key, who, axis); + trace!("[Control Runtime] Player \"{}\" changed ax_{} to ({})", &who.id, axis_key, axis); + } else { + warn!("[Control Runtime] Key ax_{} not registered!", axis_key); + } + Ok(()) + } + + Dir(dir_key, dir) => { + if self.check_key(&self.keys.button_keys, &dir_key) { + Self::change_value(&mut self.directions, dir_key, who, dir); + trace!("[Control Runtime] Player \"{}\" changed dir_{} to ({}, {})", &who.id, dir_key, dir.0, dir.1); + } else { + warn!("[Control Runtime] Key dir_{} not registered!", dir_key); + } + Ok(()) + } + + _ => { + Err(msg) + } + } + } + + /// Pop an event message + pub fn pop_event(&mut self, game_runtime: &GameRuntime) -> Option<(Account, ControlMessage)> { + let pop = self.events.pop_front(); + if pop.is_some() { + let (account, msg) = pop.unwrap(); + if game_runtime.data.is_account_online(&account) { + trace!("[Control Runtime] Message: {:?} from \"{}\" ", &msg, account); + Some((account, msg)) + } else { + warn!("[Control Runtime] Invalid message: Player \"{}\" is not online!", account); + None + } + } else { + None + } + } + + /// Get specified player's direction value + pub fn get_direction(&self, who: &Account, key: &u8) -> Option<(f64, f64)> { + Self::get(&self.directions, who, key) + } + + /// Get specified player's axis value + pub fn get_axis(&self, who: &Account, key: &u8) -> Option<f64> { + Self::get(&self.axes, who, key) + } + + /// Get specified player's button status + pub fn get_button_status(&self, who: &Account, key: &u8) -> Option<bool> { + Self::get(&self.button, who, key) + } + + fn check_key(&self, map: &HashMap<u8, String>, key: &u8) -> bool { + map.contains_key(key) + } + + fn get<V: Clone>(map: &HashMap<u8, HashMap<Account, V>>, who: &Account, key: &u8) -> Option<V> { + let key = map.get(key); + if key.is_some() { + let value = key.unwrap().get(who); + if value.is_some() { + let result = value.unwrap(); + Some(result.clone()) + } else { None } + } else { None } + } + + fn change_value<T>(map: &mut HashMap<u8, HashMap<Account, T>>, key: u8, who: &Account, msg: T) { + map.entry(key) + .or_insert_with(HashMap::new) + .insert(who.clone(), msg); + } + + fn send_event(&mut self, who: &Account, msg: ControlMessage) { + self.events.push_back((who.clone(), msg)); + } +}
\ No newline at end of file diff --git a/core/src/data/game/runtime/mod.rs b/core/src/data/game/runtime/mod.rs new file mode 100644 index 0000000..0ff870f --- /dev/null +++ b/core/src/data/game/runtime/mod.rs @@ -0,0 +1,2 @@ +pub mod implements; +pub mod structs;
\ No newline at end of file diff --git a/core/src/data/game/runtime/structs.rs b/core/src/data/game/runtime/structs.rs new file mode 100644 index 0000000..bf68424 --- /dev/null +++ b/core/src/data/game/runtime/structs.rs @@ -0,0 +1,40 @@ +use std::collections::{HashMap, VecDeque}; +use std::sync::atomic::AtomicBool; +use crate::data::game::structs::GameControlData; +use crate::data::game::types::{GameInfo, Players}; +use crate::data::message::enums::{ControlMessage, GameMessage}; +use crate::data::player::structs::Account; +use crate::service::service_types::ServiceType; + +/// Game pad_client runtime +/// Stores the game state, player information, and all data involved in controller-side interactions during runtime +pub struct GameRuntime { + + pub info: GameInfo, + pub data: GameRuntimeData, + pub control: GameControlRuntime, + + pub writer_count: i32, + pub reader_count: i32, +} + +pub struct GameRuntimeData { + + pub(crate) received: HashMap<(ServiceType, Account), VecDeque<(Account, ControlMessage)>>, + pub(crate) send: HashMap<(ServiceType, Account), VecDeque<(Account, GameMessage)>>, + + pub(crate) players_online: Players, + pub(crate) players_banned: Players, + + pub locked: AtomicBool, + pub close: AtomicBool, +} + +#[derive(Default)] +pub struct GameControlRuntime { + pub(crate) keys: GameControlData, + pub(crate) directions : HashMap<u8, HashMap<Account, (f64, f64)>>, + pub(crate) axes : HashMap<u8, HashMap<Account, f64>>, + pub(crate) button : HashMap<u8, HashMap<Account, bool>>, + pub(crate) events : VecDeque<(Account, ControlMessage)> +}
\ No newline at end of file diff --git a/core/src/data/game/structs.rs b/core/src/data/game/structs.rs new file mode 100644 index 0000000..52fc0f1 --- /dev/null +++ b/core/src/data/game/structs.rs @@ -0,0 +1,29 @@ +use std::collections::HashMap; +use serde::{Deserialize, Serialize}; +use crate::data::game::types::GameInfo; +use crate::data::player::structs::Account; + +/// Game pad_client data +/// Describes the basic information of the game pad_client +#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)] +pub struct GameData { + pub info: GameInfo, + pub control: GameControlData, + pub archive: GameRuntimeDataArchive +} + +/// Game control information +/// Describes the buttons, axes, and directions that can be controlled. +#[derive(Default, Clone, Serialize, Deserialize, PartialEq, Debug)] +pub struct GameControlData { + pub direction_keys : HashMap<u8, String>, + pub axis_keys : HashMap<u8, String>, + pub button_keys : HashMap<u8, String>, +} + +/// Archive of game runtime data +/// The game pad_client can convert data into this structure for persistence. +#[derive(Default, Clone, Serialize, Deserialize, PartialEq, Debug)] +pub struct GameRuntimeDataArchive { + pub banned: Vec<Account> +}
\ No newline at end of file diff --git a/core/src/data/game/types.rs b/core/src/data/game/types.rs new file mode 100644 index 0000000..8af17d3 --- /dev/null +++ b/core/src/data/game/types.rs @@ -0,0 +1,7 @@ +use std::collections::HashMap; +use std::sync::Mutex; +use crate::data::player::structs::{Account, Player}; + +pub(crate) type GameInfo = HashMap<String, String>; + +pub(crate) type Players = Mutex<HashMap<Account, Player>>;
\ No newline at end of file diff --git a/core/src/data/message/enums.rs b/core/src/data/message/enums.rs new file mode 100644 index 0000000..4150b63 --- /dev/null +++ b/core/src/data/message/enums.rs @@ -0,0 +1,154 @@ +use crate::data::player::structs::Player; +use bincode::{Decode, Encode}; +use crate::data::game::types::GameInfo; + +/// Control messages. +/// Messages sent from controller to game pad_client after establishing persistent connection +#[derive(Default, Encode, Decode, PartialEq, Debug, Clone)] +pub enum ControlMessage { + /// Plain message containing a string + /// The message will be handed over to the game for its own processing + Msg(String), + + /// Press event + /// Indicates that a button has been pressed + Pressed(u8), + + /// Release event + /// Indicates that a button has been released + Released(u8), + + /// Axis input + /// Indicates that the value of an axis has been changed + Axis(u8, f64), + + /// Directional input + /// Indicates that the value of a direction has been changed + Dir(u8, (f64, f64)), + + /// Exit command + /// Sends a disconnect request to the pad_server + Exit, + + #[default] + /// Error state + Err, + + /// Indicates the termination message, which is the final message in a long-lived connection. + End +} + +/// Game messages. +/// Messages sent from game pad_client to controller after establishing persistent connection +#[derive(Default, Encode, Decode, PartialEq, Debug, Clone)] +pub enum GameMessage { + /// Event trigger + /// Sends an event to the controller; if skins are enabled, this will trigger corresponding animations, sounds, vibrations, etc. + EventTrigger(u8), + + /// Plain message containing a string + /// The message will be handed over to the controller for its own processing + Msg(String), + + /// Disconnect request + /// Notifies the pad_client that the connection will be terminated + LetExit(ExitReason), + + /// Error state + #[default] + Err, + + /// Indicates the termination message, which is the final message in a long-lived connection. + End +} + +/// Exit reasons. +/// Reason provided when requesting disconnection +#[derive(Default, Encode, Decode, PartialEq, Debug, Clone)] +pub enum ExitReason { + /// Normal exit + /// No specific reason, simply requesting to disconnect + Exit, + + /// Game has ended + GameOver, + + /// Server shutdown (normal) + ServerClosed, + + /// Kicked by pad_server + YouAreKicked, + + /// Account banned + YouAreBanned, + + /// Error state + #[default] + Err +} + +/// Connection messages. +/// Messages sent by pad_client when requesting pad_server connection +#[derive(Default, Encode, Decode, PartialEq, Debug, Clone)] +pub enum ConnectionMessage { + /// Requests to join the game + Join(Player), + + /// Request for game information + RequestGameInfos, + + /// Request for game layout configuration file + RequestLayoutConfigure, + + /// Request to download game skin assets + RequestSkinPackage, + + /// Ready state to establish persistent connection + Ready, + + /// Error state + #[default] + Err +} + +/// Connection Response. +/// Messages from pad_server responding to pad_client connection requests +#[derive(Default, Encode, Decode, PartialEq, Debug, Clone)] +pub enum ConnectionResponseMessage { + /// Game information data + GameInfos(GameInfo), + + /// Rejection with reason + Deny(JoinFailedMessage), + + /// Failure with reason + Fail(JoinFailedMessage), + + /// Approval confirmation + Ok, + + /// Welcome acknowledgment + Welcome, + + /// Error state + #[default] + Err +} + +/// Game Join Failure Information. +/// Reason provided when pad_client fails to join +#[derive(Default, Encode, Decode, PartialEq, Debug, Clone)] +pub enum JoinFailedMessage { + /// Game already contains identical player + ContainIdenticalPlayer, + + /// Player is banned + PlayerBanned, + + /// Game is locked, no further joins allowed + GameLocked, + + /// Unknown error + #[default] + UnknownError +}
\ No newline at end of file diff --git a/core/src/data/message/implements.rs b/core/src/data/message/implements.rs new file mode 100644 index 0000000..2d5bae8 --- /dev/null +++ b/core/src/data/message/implements.rs @@ -0,0 +1,15 @@ +use crate::data::message::enums::{ConnectionResponseMessage, JoinFailedMessage, ConnectionMessage, ControlMessage, ExitReason, GameMessage}; +use crate::data::message::traits::MessageEncoder; + +#[macro_export] +macro_rules! encoder { + ($($msg:ident),+) => { + $( + impl MessageEncoder<$msg> for $msg {} + )+ + }; +} + +encoder!( + ControlMessage, GameMessage, ExitReason, ConnectionMessage, ConnectionResponseMessage, JoinFailedMessage +);
\ No newline at end of file diff --git a/core/src/data/message/mod.rs b/core/src/data/message/mod.rs new file mode 100644 index 0000000..96fdd73 --- /dev/null +++ b/core/src/data/message/mod.rs @@ -0,0 +1,3 @@ +pub mod enums; +pub mod implements; +pub mod traits;
\ No newline at end of file diff --git a/core/src/data/message/traits.rs b/core/src/data/message/traits.rs new file mode 100644 index 0000000..c4b3af4 --- /dev/null +++ b/core/src/data/message/traits.rs @@ -0,0 +1,67 @@ +use std::collections::{HashMap, VecDeque}; +use std::fmt::Debug; +use std::hash::Hash; +use bincode::{Decode, Encode}; +use crate::data::{BINCODE_CONFIG, BINCODE_CONVERT_FAILED}; +use crate::service::service_types::ServiceType; + +/// Message Manager +/// Provides the ability to store and retrieve messages from a VecDeque +pub trait MessageManager<In, Out, Key> +where Key: Eq + Hash { + fn borrow_received_list_mut(&mut self) -> &mut HashMap<(ServiceType, Key), VecDeque<In>>; + + fn borrow_send_list_mut(&mut self) -> &mut HashMap<(ServiceType, Key), VecDeque<Out>>; + + fn send(&mut self, message: Out, key: Key, service: ServiceType) { + self.borrow_send_list_mut() + .entry((service, key)) + .or_insert_with(VecDeque::new) + .push_back(message); + } + + fn receive(&mut self, key: Key, service: ServiceType) -> Option<In> { + self.borrow_received_list_mut() + .entry((service, key)) + .or_insert_with(VecDeque::new) + .pop_front() + } + + fn pop_from_send_list(&mut self, key: Key, service: ServiceType) -> Option<Out> { + self.borrow_send_list_mut() + .entry((service, key)) + .or_insert_with(VecDeque::new) + .pop_front() + } + + fn put_into_receive_list(&mut self, message: In, key: Key, service: ServiceType) { + self.borrow_received_list_mut() + .entry((service, key)) + .or_insert_with(VecDeque::new) + .push_back(message); + } +} + +/// Message Encoder +/// Provides the ability to encode messages into binary data or decode them from binary data +pub trait MessageEncoder<M: Encode + Decode<()> + Default + Debug> { + fn err_result_decode () -> M { + M::default() + } + + fn err_result_encode () -> Vec<u8> { + BINCODE_CONVERT_FAILED + } + + fn en(&self) -> Vec<u8> where Self : Encode { + bincode::encode_to_vec(self, BINCODE_CONFIG) + .unwrap_or_else(|_| Self::err_result_encode()) + } + + fn de(encoded : Vec<u8>) -> M { + match bincode::decode_from_slice(&encoded[..], BINCODE_CONFIG) { + Ok((decoded, _)) => decoded, + Err(_) => Self::err_result_decode() + } + } +}
\ No newline at end of file diff --git a/core/src/data/mod.rs b/core/src/data/mod.rs new file mode 100644 index 0000000..19589a2 --- /dev/null +++ b/core/src/data/mod.rs @@ -0,0 +1,10 @@ +use bincode::config; +use bincode::config::Configuration; + +pub const BINCODE_CONVERT_FAILED : Vec<u8> = Vec::new(); +pub const BINCODE_CONFIG : Configuration = config::standard(); + +pub mod controller; +pub mod game; +pub mod message; +pub mod player;
\ No newline at end of file diff --git a/core/src/data/player/implements.rs b/core/src/data/player/implements.rs new file mode 100644 index 0000000..bbaefc4 --- /dev/null +++ b/core/src/data/player/implements.rs @@ -0,0 +1,119 @@ +use crate::data::player::structs::{Account, Customize, Player}; +use crate::data::player::ACCOUNT_HASH_SALT; +use hex::encode; +use sha1::{Digest, Sha1}; +use std::fmt::{Display, Formatter}; +use std::hash::{Hash, Hasher}; +use nogamepads::string_utils::process_id_text; + +impl Player { + + /// Create new player information using a username and password + pub fn register(id: String, password: String) -> Player { + let mut player = Player { + customize: None, + account: Account::default() + }; + + let processed_id = process_id_text(id); + + player.account.id = processed_id.clone(); + player.account.player_hash = Self::gen_hash(processed_id, password); + player + } + + pub fn check(&self, password: String) -> bool { + let hash = Self::gen_hash(self.account.id.clone(), password); + hash == self.account.player_hash + } + + fn gen_hash(processed_id: String, password: String) -> String { + let combined = format!("{}{}{}", processed_id, password, ACCOUNT_HASH_SALT); + let mut hasher = Sha1::new(); + hasher.update(combined); + let result = hasher.finalize(); + encode(&result[..]) + } +} + +// Customize implements +impl Player { + + /// Set player nickname + pub fn nickname(&mut self, name: &String) -> &mut Player { + self.change(|custom| { + custom.nickname = name.clone(); + custom + }) + } + + /// Set the hue of the player's color + pub fn hue(&mut self, mut hue: i32) -> &mut Player { + hue = hue.clamp(0, 360); + self.change(|custom| { + custom.color_hue = hue.clone(); + custom + }) + } + + /// Set the player's HSV values + pub fn hsv(&mut self, mut hue: i32, mut saturation: f64, mut value: f64) -> &mut Player { + hue = hue.clamp(0, 360); + saturation = saturation.clamp(0.0, 1.0); + value = value.clamp(0.0, 1.0); + self.change(|custom| { + custom.color_hue = hue.clone(); + custom.color_saturation = saturation.clone(); + custom.color_value = value.clone(); + custom + }) + } + + fn init(&mut self) { + if self.customize.is_none() { + self.customize = Some(Customize::default()); + } + } + + fn change<F>(&mut self, f: F) -> &mut Player + where F: FnOnce(&mut Customize) -> &mut Customize { + self.init(); + let mut customize = self.customize.clone().unwrap(); + f(&mut customize); + self.customize = Some(customize); + self + } +} + +impl PartialEq for Player { + fn eq(&self, other: &Self) -> bool { + self.account == other.account + } +} + +impl Hash for Player { + fn hash<H: Hasher>(&self, state: &mut H) { + self.account.hash(state); + } +} + +impl Display for Player { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_str(self.account.id.as_str()) + } +} + +impl From<Account> for Player { + fn from(account: Account) -> Self { + Player { + account, + customize: None + } + } +} + +impl Display for Account { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_str(self.id.as_str()) + } +}
\ No newline at end of file diff --git a/core/src/data/player/mod.rs b/core/src/data/player/mod.rs new file mode 100644 index 0000000..7e8fe28 --- /dev/null +++ b/core/src/data/player/mod.rs @@ -0,0 +1,4 @@ +pub mod implements; +pub mod structs; + +pub const ACCOUNT_HASH_SALT : &str = env!("TEST_PLAYER_ACCOUNT");
\ No newline at end of file diff --git a/core/src/data/player/structs.rs b/core/src/data/player/structs.rs new file mode 100644 index 0000000..cc3d7c9 --- /dev/null +++ b/core/src/data/player/structs.rs @@ -0,0 +1,45 @@ +use bincode::{Decode, Encode}; +use serde::{Deserialize, Serialize}; +use std::hash::{Hash}; + +/// Player information +/// Describes a player's specific details, which are frequently exchanged between the controller and game pad_client. +#[derive(Default, Clone, Encode, Decode, Serialize, Deserialize, Debug)] +pub struct Player { + + /// Account information + pub account: Account, + + /// Custom information (Optional) + pub customize: Option<Customize> +} + +/// Account information +/// Essential data for verifying player uniqueness, including the player's hash value and account ID. +#[derive(Default, Clone, Encode, Decode, Serialize, Deserialize, Eq, Hash, PartialEq, Debug)] +pub struct Account { + + /// Player name stored in data, allowing only lowercase letters and underscores + pub id: String, + + /// Player hash value proving player uniqueness + pub player_hash: String +} + +/// Custom information +/// Describes personalized player details displayed in-game, such as name, color, or other customizations. +#[derive(Default, Clone, Encode, Decode, Serialize, Deserialize, PartialEq, Debug)] +pub struct Customize { + + /// Player name displayed in the game + pub nickname: String, + + /// HSV Color - Hue (Range: 0 - 360) + pub color_hue: i32, + + /// HSV Color - Saturation (Range: 0 - 1) + pub color_saturation: f64, + + /// HSV Color - Value (Range: 0 - 1) + pub color_value: f64 +}
\ No newline at end of file diff --git a/core/src/lib.rs b/core/src/lib.rs index 0c8cf83..49db429 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,9 +1,8 @@ use bincode::config; use bincode::config::Configuration; -pub mod pad_service; -pub mod pad_data; +pub mod data; +pub mod service; -pub const DEFAULT_PORT : u16 = 5989; pub const BINCODE_CONVERT_FAILED : Vec<u8> = Vec::new(); -pub const BINCODE_CONFIG : Configuration = config::standard();
\ No newline at end of file +pub const BINCODE_CONFIG : Configuration = config::standard(); diff --git a/core/src/pad_data/game_profile.rs b/core/src/pad_data/game_profile.rs deleted file mode 100644 index cd2a175..0000000 --- a/core/src/pad_data/game_profile.rs +++ /dev/null @@ -1,100 +0,0 @@ -pub mod game_profile { - use std::fmt::Display; - use bincode::{Decode, Encode}; - use serde::{Deserialize, Serialize}; - - #[repr(C)] - #[derive(Encode, Decode, Serialize, Deserialize, PartialEq, Debug)] - pub struct GameProfile { - - // 游戏名称 - pub game_name: String, - - // 游戏描述 - pub game_description: String, - - // 游戏组织 - pub organization: String, - - // 游戏版本 - pub version: String, - - // 工作室 & 游戏 主页 - pub website: String, - - // 交流邮箱 - pub email: String - } - - impl Default for GameProfile { - fn default() -> Self { - GameProfile { - game_name: "Unnamed Game".to_string(), - game_description: "".to_string(), - organization: "".to_string(), - version: "0.1".to_string(), - website: "".to_string(), - email: "".to_string() - } - } - } - - impl Clone for GameProfile { - fn clone(&self) -> Self { - GameProfile { - game_name: self.game_name.clone(), - game_description: self.game_description.clone(), - organization: self.organization.clone(), - version: self.version.clone(), - website: self.website.clone(), - email: self.email.clone() - } - } - } - - impl Display for GameProfile { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut string = String::new(); - string += format!("Game Name: {}\n", self.game_name).as_str(); - if !self.game_description.eq("") { string += format!("Description: {}\n", self.game_description).as_str(); } - if !self.organization.eq("") { string += format!("Org: {}\n", self.organization).as_str(); } - if !self.website.eq("") { string += format!("- Web: {}\n", self.website).as_str(); } - if !self.version.eq("") { string += format!("Version: {}\n", self.version).as_str(); } - if !self.email.eq("") { string += format!("- E-mail: {}\n", self.email).as_str(); } - - write!(f, "{}", string) - } - } - - impl GameProfile { - pub fn game_name(&mut self, game_name: &str) -> &mut GameProfile { - self.game_name = game_name.to_string(); - self - } - - pub fn game_description(&mut self, game_description: &str) -> &mut GameProfile { - self.game_description = game_description.to_string(); - self - } - - pub fn organization(&mut self, organization: &str) -> &mut GameProfile { - self.organization = organization.to_string(); - self - } - - pub fn version(&mut self, version: &str) -> &mut GameProfile { - self.version = version.to_string(); - self - } - - pub fn website(&mut self, website: &str) -> &mut GameProfile { - self.website = website.to_string(); - self - } - - pub fn email(&mut self, email: &str) -> &mut GameProfile { - self.email = email.to_string(); - self - } - } -}
\ No newline at end of file diff --git a/core/src/pad_data/layout.rs b/core/src/pad_data/layout.rs deleted file mode 100644 index 4c5f53f..0000000 --- a/core/src/pad_data/layout.rs +++ /dev/null @@ -1,137 +0,0 @@ -pub mod layout_data { - use std::collections::{HashMap, VecDeque}; - use bincode::{Decode, Encode}; - use serde::{Deserialize, Serialize}; - use crate::pad_data::pad_messages::nogamepads_messages::ControlMessage; - use crate::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; - use crate::pad_service::server::nogamepads_server::PadServer; - - - #[derive(Encode, Decode, Serialize, Deserialize, PartialEq, Debug, Clone)] - pub struct LayoutKeyRegisters { - pub direction_keys : HashMap<u8, String>, // 注册方向键 - pub axis_keys : HashMap<u8, String>, // 注册轴向键 - pub button_keys : HashMap<u8, String>, // 注册按钮 - } - - impl Default for LayoutKeyRegisters { - fn default() -> LayoutKeyRegisters { - LayoutKeyRegisters { - direction_keys: Default::default(), - axis_keys: Default::default(), - button_keys: Default::default(), - } - } - } - - pub struct LayoutKeyRuntimeData { - directions : HashMap<u8, HashMap<String, (f64, f64)>>, // <键, <玩家Hash, (x, y)>> - axes : HashMap<u8, HashMap<String, f64>>, // <键, <玩家Hash, 轴向>> - button : HashMap<u8, HashMap<String, bool>>, // <键, <玩家Hash, 是否按下>> - - events : VecDeque<(String, ControlMessage)>, // (玩家Hash, 信息) - } - - impl Default for LayoutKeyRuntimeData { - fn default() -> Self { - LayoutKeyRuntimeData { - directions: Default::default(), - axes: Default::default(), - button: Default::default(), - events: Default::default(), - } - } - } - - impl LayoutKeyRuntimeData { - - // 输入控制信息到数据 - pub fn insert_control(&mut self, who: PlayerInfo, msg: ControlMessage) { - match msg { - // 消息放入信息队列待读取 - ControlMessage::Msg(_) => { - self.events.push_back((who.account.player_hash, msg)) - } - - // 按钮更新对应玩家的状态,并且放入信息队列待读取 - ControlMessage::Pressed(button_key) => { - self.button.entry(button_key) - .or_insert_with(HashMap::new) - .insert(who.account.player_hash.clone(), true); - self.events.push_back((who.account.player_hash, msg)) - } - ControlMessage::Released(button_key) => { - self.button.entry(button_key) - .or_insert_with(HashMap::new) - .insert(who.account.player_hash.clone(), false); - self.events.push_back((who.account.player_hash, msg)) - } - - // 轴向更新直接传入玩家状态 - ControlMessage::Axis(axis_key, axis) => { - self.axes.entry(axis_key) - .or_insert_with(HashMap::new) - .insert(who.account.player_hash.clone(), axis); - } - ControlMessage::Dir(dir_key, (x, y)) => { - self.directions.entry(dir_key) - .or_insert_with(HashMap::new) - .insert(who.account.player_hash.clone(), (x, y)); - } - _ => { } - } - } - - pub fn pop_control_event(&mut self, server: &PadServer) -> Option<(PlayerInfo, ControlMessage)> { - let pop = self.events.pop_front(); - if pop.is_some() { - let (hash, msg) = pop.unwrap(); - let info = server.find_online_player(hash); - if info.is_some() { - Some((info.unwrap(), msg)) - } else { - None - } - } else { - None - } - } - - pub fn get_direction(&self, who: &PlayerInfo, key: &u8) -> Option<(f64, f64)> { - Self::get(&self.directions, who, key) - } - - pub fn get_axis(&self, who: &PlayerInfo, key: &u8) -> Option<f64> { - Self::get(&self.axes, who, key) - } - - pub fn get_button_status(&self, who: &PlayerInfo, key: &u8) -> Option<bool> { - Self::get(&self.button, who, key) - } - - fn get<V: Clone>(map: &HashMap<u8, HashMap<String, V>>, who: &PlayerInfo, key: &u8) -> Option<V> { - let key = map.get(key); - if key.is_some() { - let value = key.unwrap().get(&who.account.player_hash); - if value.is_some() { - let result = value.unwrap(); - Some(result.clone()) - } else { None } - } else { None } - } - } -} - -pub mod layout_gamepad { - use bincode::{Decode, Encode}; - use serde::{Deserialize, Serialize}; - - #[derive(Encode, Decode, Serialize, Deserialize, PartialEq, Debug)] - pub struct PadLayout { - - } - - pub trait ButtonArea { - - } -}
\ No newline at end of file diff --git a/core/src/pad_data/mod.rs b/core/src/pad_data/mod.rs deleted file mode 100644 index e041524..0000000 --- a/core/src/pad_data/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod pad_messages; -pub mod pad_player_info; -pub mod game_profile; -pub mod layout;
\ No newline at end of file diff --git a/core/src/pad_data/pad_messages.rs b/core/src/pad_data/pad_messages.rs deleted file mode 100644 index f081e5d..0000000 --- a/core/src/pad_data/pad_messages.rs +++ /dev/null @@ -1,176 +0,0 @@ -pub mod nogamepads_messages { - use bincode::{Decode, Encode}; - use crate::pad_data::game_profile::game_profile::GameProfile; - use crate::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; - - #[derive(Encode, Decode, PartialEq, Debug, Clone)] - pub enum ControlMessage { - - Msg(String), - - Pressed(u8), - - Released(u8), - - Axis(u8, f64), - - Dir(u8, (f64, f64)), - - Exit, - - Err - } - - #[derive(Encode, Decode, PartialEq, Debug, Clone)] - pub enum GameMessage { - - SkinEventTrigger(u8), - - DisableKey(u8), - - EnableKey(u8), - - Leave(LeaveReason), - - Err - } - - #[derive(Encode, Decode, PartialEq, Debug, Clone)] - pub enum LeaveReason { - - GameOver, - - ServerClosed, - - YouAreKicked, - - YouAreBanned - } - - #[derive(Encode, Decode, PartialEq, Debug, Clone)] - pub enum ConnectionMessage { - - Connection(PlayerInfo), - - RequestProfile, - - RequestLayoutConfigure, - - RequestSkinPackage, - - Ready, - - Err - } - - #[derive(Encode, Decode, PartialEq, Debug, Clone)] - pub enum ConnectionCallbackMessage { - - Profile(GameProfile), - - Deny(ConnectionErrorType), - - Fail(ConnectionErrorType), - - Ok, - - Welcome, - - Err - } - - #[derive(Encode, Decode, PartialEq, Debug, Clone)] - pub enum ConnectionErrorType { - - ContainSamePlayer, - - PlayerBanned, - - Timeout, - - GameLocked, - - WhatTheHell - } -} - -pub mod nogamepads_message_encoder { - use bincode::{Decode, Encode}; - use crate::{BINCODE_CONFIG, BINCODE_CONVERT_FAILED}; - use crate::pad_data::pad_messages::nogamepads_messages::{ConnectionCallbackMessage, ConnectionMessage, ControlMessage, GameMessage}; - - pub trait NgpdMessageEncoder<Message: Encode + Decode<()>> { - fn err_result_decode () -> Message; - fn err_result_encode () -> Vec<u8> { - BINCODE_CONVERT_FAILED - } - - fn en(&self) -> Vec<u8> where Self : Encode { - bincode::encode_to_vec(self, BINCODE_CONFIG) - .unwrap_or_else(|_| Self::err_result_encode()) - } - - fn de(encoded : Vec<u8>) -> Message { - match bincode::decode_from_slice(&encoded[..], BINCODE_CONFIG) { - Ok((decoded, _)) => decoded, - Err(_) => Self::err_result_decode() - } - } - } - - impl NgpdMessageEncoder<ControlMessage> for ControlMessage { - fn err_result_decode() -> ControlMessage { - ControlMessage::Err - } - } - - impl NgpdMessageEncoder<GameMessage> for GameMessage { - fn err_result_decode() -> GameMessage { - GameMessage::Err - } - } - - impl NgpdMessageEncoder<ConnectionMessage> for ConnectionMessage { - fn err_result_decode() -> ConnectionMessage { - ConnectionMessage::Err - } - } - - impl NgpdMessageEncoder<ConnectionCallbackMessage> for ConnectionCallbackMessage { - fn err_result_decode() -> ConnectionCallbackMessage { - ConnectionCallbackMessage::Err - } - } -} - -pub mod nogamepads_message_transfer { - use bincode::{Decode, Encode}; - use log::error; - use tokio::io::{AsyncReadExt, AsyncWriteExt}; - use tokio::net::TcpStream; - use crate::pad_data::pad_messages::nogamepads_message_encoder::NgpdMessageEncoder; - - pub async fn send_msg <Message>(stream: &mut TcpStream, msg: impl NgpdMessageEncoder<Message> + Decode<()> + Encode) - where Message: NgpdMessageEncoder<Message> + Decode<()> + Encode { - match stream.write_all(NgpdMessageEncoder::en(&msg).as_slice()).await { - Ok(_) => {} - Err(_) => { - error!("Failed to send message."); - } - } - } - - pub async fn read_msg<Message>(buffer: &mut [u8], stream: &mut TcpStream) -> Message - where Message: NgpdMessageEncoder<Message> + Decode<()> + Encode { - match stream.read(buffer).await { - Ok(read) => { - let received = &buffer[..read]; - <Message as NgpdMessageEncoder<Message>>::de(Vec::from(received)) - } - Err(err) => { - error!("Error reading from socket: {}", err); - <Message as NgpdMessageEncoder<Message>>::err_result_decode() - } - } - } -}
\ No newline at end of file diff --git a/core/src/pad_data/pad_player_info.rs b/core/src/pad_data/pad_player_info.rs deleted file mode 100644 index 1c8b7e0..0000000 --- a/core/src/pad_data/pad_player_info.rs +++ /dev/null @@ -1,127 +0,0 @@ -pub mod nogamepads_player_info { - - use bincode::{Decode, Encode}; - use hex::encode; - use sha1::{Digest, Sha1}; - use serde::{Deserialize, Serialize}; - - pub const ACCOUNT_HASH_SALT : &str = "Mr.Weicao"; - - #[repr(C)] - #[derive(Encode, Decode, - Serialize, Deserialize, - PartialEq, Debug)] - pub struct PlayerInfo { - pub account: PlayerAccountInfo, - pub customize: PlayerCustomizeInfo - } - - #[derive(Encode, Decode, - Serialize, Deserialize, - PartialEq, Debug)] - pub struct PlayerAccountInfo { - pub id: String, - pub player_hash: String - } - - #[derive(Encode, Decode, - Serialize, Deserialize, - PartialEq, Debug)] - pub struct PlayerCustomizeInfo { - pub nickname: String, - - pub color_hue: i32, // 0 - 360 - pub color_saturation: f64, // 0 - 1 - pub color_value: f64 // 0 - 1 - } - - impl PlayerInfo { - - pub fn new() -> PlayerInfo { - PlayerInfo { - customize: PlayerCustomizeInfo::default(), - account: PlayerAccountInfo::default() - } - } - - pub fn set_nickname(&mut self, name: &str) -> &mut PlayerInfo { - self.customize.nickname = String::from(name); - self - } - - pub fn set_customize_color_hue(&mut self, mut hue: i32) -> &mut PlayerInfo { - hue = hue.clamp(0, 360); - self.customize.color_hue = hue; - self - } - - pub fn set_customize_color_hsv(&mut self, mut hue: i32, mut saturation: f64, mut value: f64) -> &mut PlayerInfo { - hue = hue.clamp(0, 360); - saturation = saturation.clamp(0.0, 1.0); - value = value.clamp(0.0, 1.0); - - self.customize.color_hue = hue; - self.customize.color_saturation = saturation; - self.customize.color_value = value; - self - } - - pub fn setup_account_info(&mut self, id: &str, password: &str) -> &mut PlayerInfo { - - let combined = format!("{}{}{}", id, password, ACCOUNT_HASH_SALT); - let mut hasher = Sha1::new(); - hasher.update(combined); - let result = hasher.finalize(); - - self.account.id = String::from(id); - self.account.player_hash = encode(&result[..]); - self - } - } - - impl Clone for PlayerInfo { - fn clone(&self) -> PlayerInfo { - PlayerInfo { - account: PlayerAccountInfo { - id: String::from(self.account.id.clone()), - player_hash: String::from(self.account.player_hash.clone()) - }, - customize: PlayerCustomizeInfo { - nickname: self.customize.nickname.clone(), - color_hue: self.customize.color_hue.clone(), - color_saturation: self.customize.color_saturation.clone(), - color_value: self.customize.color_value.clone() - } - } - } - } - - impl Default for PlayerCustomizeInfo { - fn default() -> Self { - PlayerCustomizeInfo { - nickname: String::from("unnamed"), - - color_hue: 120, - color_saturation: 1.0, - color_value: 1.0 - } - } - } - - impl Default for PlayerAccountInfo { - fn default() -> Self { - PlayerAccountInfo { - id: String::from("empty"), - player_hash: String::from("") - } - } - } -} - -#[cfg(test)] -mod player_info_test { - #[test] - fn test_player_info_setup() { - - } -}
\ No newline at end of file diff --git a/core/src/pad_service/client.rs b/core/src/pad_service/client.rs deleted file mode 100644 index b0b05a2..0000000 --- a/core/src/pad_service/client.rs +++ /dev/null @@ -1,520 +0,0 @@ -pub mod nogamepads_client { - use std::collections::VecDeque; - use crate::pad_data::pad_messages::nogamepads_message_transfer::{read_msg, send_msg}; - use crate::pad_data::pad_messages::nogamepads_messages::{ConnectionCallbackMessage, ConnectionErrorType, ConnectionMessage, ControlMessage, GameMessage, LeaveReason}; - use crate::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; - use log::{error, info}; - use std::net::{IpAddr, Ipv4Addr}; - use std::process::exit; - use std::sync::atomic::AtomicBool; - use std::sync::atomic::Ordering::SeqCst; - use std::sync::{Arc, Mutex}; - use std::time::Duration; - use clap::CommandFactory; - use tokio::io::{AsyncReadExt, AsyncWriteExt, ReadHalf, WriteHalf}; - use tokio::net::TcpStream; - use tokio::{io, spawn}; - use tokio::runtime::Runtime; - use nogamepads::console_utils::debug_console::read_cli; - use nogamepads::convert_utils::convert_deque_to_vec; - use nogamepads::logger_utils::logger_build; - use crate::pad_service::client_debug_cli::{process_debug_cmd, Pcc}; - use crate::DEFAULT_PORT; - use crate::pad_data::game_profile::game_profile::GameProfile; - use crate::pad_data::pad_messages::nogamepads_message_encoder::NgpdMessageEncoder; - use crate::pad_data::pad_messages::nogamepads_messages::ControlMessage::{Axis, Dir, Msg, Pressed, Released}; - - type WriteList = Arc<Mutex<VecDeque<ControlMessage>>>; - type ReadList = Arc<Mutex<VecDeque<GameMessage>>>; - - #[repr(C)] - pub struct PadClient { - - // --- 主要参数 --- - - // 目标地址 - target_address: IpAddr, - - // 目标端口 - #[allow(dead_code)] - target_port: u16, - - // 绑定的玩家 - bind_player: PlayerInfo, - - // 调试模式 - enable_console: bool, - - // 保持安静,不初始化 env_logger - quiet: bool, - - // --- 运行时参数 --- - - // 发送信息列表 - write_list: WriteList, - - // 读取信息列表 - read_list: ReadList, - - // 是否退出 - exit: AtomicBool, - } - - impl Clone for PadClient { - fn clone(&self) -> Self { - PadClient { - enable_console: self.enable_console.clone(), - target_address: self.target_address.clone(), - target_port: self.target_port.clone(), - bind_player: self.bind_player.clone(), - quiet: self.quiet.clone(), - - write_list: self.write_list.clone(), - read_list: self.read_list.clone(), - exit: AtomicBool::new(self.exit.load(SeqCst)), - } - } - } - - impl Default for PadClient { - fn default() -> Self { - PadClient { - enable_console: false, - target_address: IpAddr::from(Ipv4Addr::new(127, 0, 0, 1)), - target_port: DEFAULT_PORT, - bind_player: PlayerInfo::new(), - quiet: false, - - write_list: WriteList::default(), - read_list: ReadList::default(), - exit: AtomicBool::new(false) - } - } - } - - // 客户端构建部分 - impl PadClient { - - pub fn bind_addr(address: IpAddr) -> PadClient { - PadClient { - target_address: address, - ..PadClient::default() - } - } - - pub fn bind_addr_with_port(address: IpAddr, port: u16) -> PadClient { - PadClient { - target_address: address, - target_port: port, - ..PadClient::default() - } - } - - pub fn enable_console(&mut self) -> &mut PadClient { - self.enable_console = true; - self - } - - pub fn quiet(&mut self) -> &mut PadClient { - self.quiet = true; - self - } - - pub fn bind_player(&mut self, player: PlayerInfo) -> &mut PadClient { - self.bind_player = player; - self - } - - pub fn clone_addr(&self) -> (IpAddr, u16) { - (self.target_address, self.target_port) - } - - pub fn is_quiet(&self) -> bool { - self.quiet - } - - pub fn is_enable_console(&self) -> bool { - self.enable_console - } - - pub fn unbind_player(&mut self) -> PlayerInfo { - let player = self.bind_player.clone(); - self.bind_player = PlayerInfo::new(); - player - } - } - - // 客户端消息管理 - impl PadClient { - - pub fn key_press(&self, key_id: u8) { - self.put_msg(Pressed(key_id)); - } - - pub fn key_release(&self, key_id: u8) { - self.put_msg(Released(key_id)); - } - - pub fn change_axis(&self, axis_id: u8, axis: f64) { - self.put_msg(Axis(axis_id, axis)); - } - - pub fn change_direction(&self, direction_id: u8, x: f64, y: f64) { - self.put_msg(Dir(direction_id, (x.clamp(0.0, 1.0), y.clamp(0.0, 1.0)))); - } - - pub fn say_str(&self, msg: &str) { - self.put_msg(Msg(msg.to_owned())); - } - - pub fn say(&self, msg: String) { - self.put_msg(Msg(msg)); - } - - pub fn put_msg(&self, msg: ControlMessage) { - let mut guard = self.write_list.lock().unwrap(); - guard.push_back(msg); - } - - pub fn pop_a_msg(&self) -> Option<GameMessage> { - let mut guard = self.read_list.lock().unwrap(); - if !guard.is_empty() { - guard.pop_front() - } else { - None - } - } - - pub fn pop_msg_or(&self, or: GameMessage) -> GameMessage { - self.pop_a_msg().unwrap_or(or) - } - - pub fn list_received(&self) -> Vec<GameMessage> { - match self.read_list.lock() { - Ok(guard) => { - convert_deque_to_vec(&guard.to_owned()) - } - Err(_) => { Vec::new() } - } - } - } - - // 客户端状态控制 - impl PadClient { - - pub fn connect(self) { - self.connect_in_runtime(None); - } - - pub fn connect_in_runtime(self, tokio_runtime: Option<Runtime>) { - - self.exit.store(false, SeqCst); - - // 构建 Logger - if !self.quiet { - logger_build(); - } - - info!("Starting \"NoGamepads Client\"."); - - // 入口 - let entry = self.get_connect_entry(); - - // 阻塞运行 - if tokio_runtime.is_some() { - tokio_runtime.unwrap().block_on(entry); - } else { - let runtime = tokio::runtime::Builder::new_multi_thread() - .thread_name("nogpad-pad_service") - .thread_stack_size(32 * 1024 * 1024) - .enable_time() - .enable_io() - .build() - .unwrap(); - runtime.block_on(entry); - } - } - - pub fn get_connect_entry(self) -> impl Future<Output = ()> + Send + 'static { - - // 调试模式 - let debug = self.enable_console; - - // Arc - let arc_client = Arc::new(self); - - async move { - let main_thread = spawn({ - let client = Arc::clone(&arc_client); - async move { - Self::main_client_thread(client).await - } - }); - - let background_thread = spawn({ - let client = Arc::clone(&arc_client); - async move { - Self::background_thread(client).await - } - }); - - if debug { - let debug_cli = spawn({ - let client = Arc::clone(&arc_client); - async move { - Self::process_debug_cli(client).await - } - }); - let _ = tokio::join!(debug_cli, main_thread, background_thread); - } else { - let _ = tokio::join!(main_thread, background_thread); - } - } - } - - pub fn exit_server(&self) { - self.exit.store(true, SeqCst); - } - - async fn main_client_thread(self: Arc<Self>) { - let mut buffer : [u8; 1024] = [0; 1024]; - let addr_str = format!("{}:{}", self.target_address.to_string(), DEFAULT_PORT); - - info!("Connected to {}", &addr_str); - - // 下载服务端配置文件 - { - info!("Check: Downloaded game profile."); - let profile = self.check_server_profile(&mut buffer, addr_str.clone()).await; - if profile.is_some() { - info!("Success: Downloaded."); - let profile = profile.unwrap_or(GameProfile::default()); - for line in profile.to_string().split('\n') { - info!("{}", line); - } - } - else { - error!("Failed: Can't download profile!"); - self.exit_server(); - } - } - - // 尝试加入服务端,并建立长连接 - { - if !self.try_join_game(&mut buffer, addr_str.clone()).await { - error!("Failed: Can't join the game!"); - self.exit_server(); - return; - } - } - } - - async fn check_server_profile(self: &Arc<Self>, buffer: &mut [u8], addr_str: String) -> Option<GameProfile> { - match TcpStream::connect(&addr_str).await { - Ok(mut stream) => { - send_msg(&mut stream, ConnectionMessage::RequestProfile).await; - let callback : ConnectionCallbackMessage = read_msg(buffer, &mut stream).await; - match callback { - ConnectionCallbackMessage::Profile(profile) => { - Some(profile) - } - ConnectionCallbackMessage::Deny(err_type) => { - error!("Request failed: Server denied your request! ({:?})", err_type); - None - } - ConnectionCallbackMessage::Err => { - error!("Connection failed: Can't connect to server!"); - None - } - _ => { None } - } - } - Err(_err) => { - None - } - } - } - - async fn try_join_game(self: &Arc<Self>, buffer: &mut [u8], addr_str: String) -> bool { - - match TcpStream::connect(&addr_str).await { - Ok(mut stream) => { - - // 发送连接请求 - let info = self.bind_player.clone(); - send_msg(&mut stream, ConnectionMessage::Connection(info)).await; - - // 读取回调 - let callback : ConnectionCallbackMessage = read_msg(buffer, &mut stream).await; - match callback { - ConnectionCallbackMessage::Deny(error) => { - match error { - ConnectionErrorType::ContainSamePlayer => { - error!("Connection failed: Contains same player!"); - false - } - ConnectionErrorType::PlayerBanned => { - error!("Connection failed: You are banned!"); - false - } - ConnectionErrorType::Timeout => { - error!("Connection failed: Timeout!"); - false - } - ConnectionErrorType::GameLocked => { - error!("Connection failed: Game was locked!"); - false - } - _ => { false } - } - } - ConnectionCallbackMessage::Ok => { - - // 服务端检查完毕,发送 Ready 以示加入游戏 - send_msg(&mut stream, ConnectionMessage::Ready).await; - let callback : ConnectionCallbackMessage = read_msg(buffer, &mut stream).await; - match callback { - ConnectionCallbackMessage::Welcome => { - info!("Welcome!"); - Self::long_connection(Arc::clone(&self), stream).await; - } - ConnectionCallbackMessage::Deny(_error) => { - error!("Request failed: Server denied your request",); - } - _ => {} - } - true - } - _ => { false } - } - } - Err(err) => { - error!("Failed to connect to server: {}", err); - false - } - } - } - - async fn long_connection(self: Arc<Self>, stream: TcpStream) { - let (reader, writer) = io::split(stream); - spawn(Self::read_task(Arc::clone(&self), reader)); - spawn(Self::write_task(Arc::clone(&self), writer)); - } - - async fn read_task(self: Arc<Self>, mut reader: ReadHalf<TcpStream>) { - let mut buf = [0u8; 1024]; - loop { - match reader.read(&mut buf).await { - Ok(0) => break, - Ok(n) => { - let msg = GameMessage::de(buf[0..n].to_vec()); - { - match self.read_list.lock() { - Ok(mut guard) => { - match &msg { - GameMessage::Leave(reason) => { - match reason { - LeaveReason::GameOver => { - info!("Leave Game: Game Over!"); - self.exit_server(); - } - LeaveReason::ServerClosed => { - info!("Leave Game: Server closed!"); - self.exit_server(); - } - LeaveReason::YouAreKicked => { - error!("Kick Game: You are kicked!"); - self.exit_server(); - } - LeaveReason::YouAreBanned => { - error!("Kick Game: You are banned!"); - self.exit_server(); - } - } - } - _ => { - info!("{:?}", &msg); - guard.push_back(msg); - } - } - } - Err(_) => {} - } - } - } - Err(e) => { - error!("Error reading from stream: {}", e); - self.exit_server(); - break; - } - } - } - } - - async fn write_task(self: Arc<Self>, mut writer: WriteHalf<TcpStream>) { - loop { - let msg : Option<ControlMessage>; - { - let lock = self.write_list.lock(); - match lock { - Ok(mut guard) => { - if ! guard.is_empty() { - msg = guard.pop_front(); - } else { - msg = None; - } - } - Err(_) => { - msg = None; - } - } - } - if msg.is_some() { - let msg = msg.unwrap(); - match &writer.write_all(NgpdMessageEncoder::en(&msg).as_slice()).await { - Ok(_) => { - info!("Sent {:?}", msg); - } - Err(_error) => { - error!("Sent {:?} failed!", msg); - } - } - } - } - } - - async fn background_thread(self: Arc<Self>) { - loop { - // 退出程序的监听 - if self.exit.load(SeqCst) { - tokio::time::sleep(Duration::from_secs(1)).await; - info!("Main thread exited."); - exit(0); - } - } - } - - async fn process_debug_cli(self: Arc<Self>) { - loop { - if self.exit.load(SeqCst) { - info!("Debug console exited"); - break - } - tokio::time::sleep(Duration::from_secs_f64(0.2)).await; - let option: Option<Pcc> = read_cli( - format!("CLIENT {}/{}> ", - self.target_address.to_string(), - self.bind_player.account.id).as_str(), - "pcc".to_string(), - Pcc::command() - ).await; - match option { - None => {} - Some(cmd) => { - process_debug_cmd(cmd, Arc::clone(&self)); - } - } - } - } - } -}
\ No newline at end of file diff --git a/core/src/pad_service/client_debug_cli.rs b/core/src/pad_service/client_debug_cli.rs deleted file mode 100644 index 988bf39..0000000 --- a/core/src/pad_service/client_debug_cli.rs +++ /dev/null @@ -1,92 +0,0 @@ -use crate::pad_service::client::nogamepads_client::PadClient; -use crate::pad_data::pad_messages::nogamepads_messages::{ControlMessage, GameMessage}; -use clap::{Args, Parser, Subcommand}; -use std::sync::Arc; -use log::info; - -/// NoGamePads Client - Cli -#[derive(Parser, Debug)] -#[command(author, version, about, long_about = None)] -pub struct Pcc { - #[command(subcommand)] - command: Commands, -} - -/// 主要命令 -#[derive(Subcommand, Debug)] -enum Commands { - - // 清屏 - #[command(about = "Clean the screen")] - Clear, - - // 断开当前连接 - #[command(about = "Exit from server")] - Exit, - - // 检查收到的消息 - #[command(about = "Check received")] - Received(ReceivedArgs), - - // 取出一条消息 - #[command(about = "Pop a message")] - Pop(PopArgs), - - // 发送消息 - #[command(about = "Send Message")] - Msg(MsgArgs), -} - -#[derive(Args, Debug)] -struct ReceivedArgs { - - #[arg(long)] - list: bool -} - -/// 发送消息 参数 -#[derive(Args, Debug)] -struct MsgArgs { - - // 消息内容 - #[arg(value_name = "CONTENT")] - message: String, -} - -#[derive(Args, Debug)] -struct PopArgs { } - -pub fn process_debug_cmd (cmd: Pcc, client: Arc<PadClient>) { - match cmd.command { - Commands::Clear => { - clearscreen::clear().expect("Failed to clear screen"); - } - - Commands::Exit => { - client.exit_server(); - } - - Commands::Received(args) => { - if args.list { - for msg in client.list_received() { - info!("{:?}", msg); - } - } else { - info!("Total {} messsage(s)!", client.list_received().iter().count()); - } - } - - Commands::Pop(_args) => { - info!("{:?}", client.pop_msg_or(GameMessage::Err)); - } - - Commands::Msg(args) => { - client.put_msg(ControlMessage::Msg(args.message)); - } - } -} - -#[allow(dead_code)] -fn put_to_list(client: Arc<PadClient>, message: ControlMessage) { - client.put_msg(message); -}
\ No newline at end of file diff --git a/core/src/pad_service/mod.rs b/core/src/pad_service/mod.rs deleted file mode 100644 index ae10f2d..0000000 --- a/core/src/pad_service/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod client; -pub mod client_debug_cli; - -pub mod server; -pub mod server_debug_cli;
\ No newline at end of file diff --git a/core/src/pad_service/server.rs b/core/src/pad_service/server.rs deleted file mode 100644 index eeadb01..0000000 --- a/core/src/pad_service/server.rs +++ /dev/null @@ -1,819 +0,0 @@ -pub mod nogamepads_server { - use std::collections::{HashMap, VecDeque}; - use crate::pad_data::pad_messages::nogamepads_message_encoder::NgpdMessageEncoder; - use crate::pad_data::pad_messages::nogamepads_message_transfer::{read_msg, send_msg}; - use crate::pad_data::pad_messages::nogamepads_messages::{ConnectionCallbackMessage, ConnectionMessage, ControlMessage, GameMessage, LeaveReason}; - use log::{error, info, warn}; - use std::net::{IpAddr, Ipv4Addr, SocketAddr}; - use std::ops::Deref; - use std::process::exit; - use std::sync::atomic::AtomicBool; - use std::sync::atomic::Ordering::SeqCst; - use std::sync::{Arc, Mutex, MutexGuard, PoisonError}; - use std::time::Duration; - use clap::CommandFactory; - use clearscreen::clear; - use prettytable::{Row, Table}; - use tokio::io::{AsyncReadExt, AsyncWriteExt, ReadHalf, WriteHalf}; - use tokio::net::{TcpListener, TcpStream}; - use tokio::{io, signal, spawn}; - use tokio::runtime::Runtime; - use nogamepads::console_utils::debug_console::read_cli; - use nogamepads::logger_utils::logger_build; - use crate::DEFAULT_PORT; - use crate::pad_data::game_profile::game_profile::GameProfile; - use crate::pad_data::layout::layout_data::{LayoutKeyRegisters, LayoutKeyRuntimeData}; - use crate::pad_data::pad_messages::nogamepads_messages::ConnectionErrorType::{ContainSamePlayer, GameLocked, PlayerBanned, WhatTheHell}; - use crate::pad_data::pad_messages::nogamepads_messages::GameMessage::Leave; - use crate::pad_data::pad_messages::nogamepads_messages::LeaveReason::ServerClosed; - use crate::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; - use crate::pad_service::server_debug_cli::{process_debug_cmd, Psc}; - - type PlayerMap = Arc<Mutex<HashMap<String, PlayerInfo>>>; - type WriteList = Arc<Mutex<HashMap<String, VecDeque<GameMessage>>>>; - - #[repr(C)] - pub struct PadServer { - - // --- 主要参数 --- - - // 本地监听地址 - address: IpAddr, - - // 游戏信息 - game_profile: GameProfile, - - // 绑定端口 - port: u16, - - // 调试模式 - enable_console: bool, - - // 保持安静,不初始化 env_logger - quiet: bool, - - // 键位表 - keys: LayoutKeyRegisters, - - // --- 运行时参数 --- - - - // 发送信息列表 - write_list: WriteList, - - // 运行环境信息 - control_data: Arc<Mutex<LayoutKeyRuntimeData>>, - - // 在线玩家 - online_players: PlayerMap, - - // 被封禁的玩家 - banned_players: PlayerMap, - - // 是否锁定该游戏:禁止后续玩家加入 - game_locked: AtomicBool, - - // 是否停止服务器 - stop: AtomicBool, - - // 调试模式 - 实时信息显示模式 - monitor_view: AtomicBool, - } - - impl Clone for PadServer { - fn clone(&self) -> Self { - PadServer { - address: self.address.clone(), - game_profile: self.game_profile.clone(), - port: self.port.clone(), - enable_console: self.enable_console, - quiet: self.quiet, - keys: self.keys.clone(), - - write_list: self.write_list.clone(), - control_data: self.control_data.clone(), - online_players: self.online_players.clone(), - banned_players: self.banned_players.clone(), - game_locked: AtomicBool::new((&self.game_locked.load(SeqCst)).clone()), - stop: AtomicBool::new((&self.stop.load(SeqCst)).clone()), - monitor_view: AtomicBool::new((&self.monitor_view.load(SeqCst)).clone()) - } - } - } - - impl Default for PadServer { - fn default() -> Self { - PadServer { - address: IpAddr::from(Ipv4Addr::new(127, 0, 0, 1)), - game_profile: GameProfile::default(), - port: DEFAULT_PORT, - enable_console: false, - quiet: false, - keys: LayoutKeyRegisters::default(), - - write_list: WriteList::default(), - control_data: Arc::new(Mutex::new(LayoutKeyRuntimeData::default())), - online_players: PlayerMap::default(), - banned_players: PlayerMap::default(), - game_locked: AtomicBool::new(false), - stop: AtomicBool::new(false), - monitor_view: AtomicBool::new(false), - } - } - } - - // 服务端构建部分 - impl PadServer { - - pub fn build_simple() -> Arc<PadServer> { - Arc::new(Self::default() - .addr(IpAddr::from(Ipv4Addr::new(127, 0, 0, 1)), DEFAULT_PORT) - .put_profile(GameProfile::default()).to_owned()) - } - - pub fn addr(&mut self, ip_addr: IpAddr, port: u16) -> &mut PadServer { - self.ip_addr(ip_addr).port(port) - } - - pub fn socket_addr(&mut self, socket_addr: SocketAddr) -> &mut PadServer { - self.ip_addr(socket_addr.ip()).port(socket_addr.port()) - } - - pub fn port(&mut self, port: u16) -> &mut PadServer { - self.port = port; - self - } - - pub fn ip_addr(&mut self, ip_addr: IpAddr) -> &mut PadServer { - self.address = ip_addr; - self - } - - pub fn put_profile(&mut self, profile: GameProfile) -> &mut PadServer { - self.game_profile = profile; - self - } - - pub fn enable_console(&mut self) -> &mut PadServer { - self.enable_console = true; - self - } - - pub fn quiet(&mut self) -> &mut PadServer { - self.quiet = true; - self - } - - pub fn register_keys(&mut self, keys: LayoutKeyRegisters) -> &mut PadServer { - self.keys = keys; - self - } - - pub fn register_button(&mut self, key: u8, name: &str) -> &mut PadServer { - self.keys.button_keys.insert(key, name.to_string()); - self - } - - pub fn register_axis(&mut self, key: u8, name: &str) -> &mut PadServer { - self.keys.axis_keys.insert(key, name.to_string()); - self - } - - pub fn register_direction(&mut self, key: u8, name: &str) -> &mut PadServer { - self.keys.direction_keys.insert(key, name.to_string()); - self - } - - pub fn build(&self) -> Arc<PadServer> { - Arc::new(self.clone()) - } - } - - // 服务端消息管理 - impl PadServer { - - pub fn put_msg_to(&self, msg: GameMessage, player: &PlayerInfo) { - match self.write_list.lock() { - Ok(mut guard) => { - let hash = &player.account.player_hash.clone(); - if ! guard.contains_key(hash.as_str()) { - guard.entry(player.account.player_hash.clone()) - .or_insert_with(VecDeque::new) - .push_back(msg); - } - } - Err(_) => { - error!("Cannot lock \"{:?}\" in write_list", player.account.player_hash); - } - } - } - - pub fn put_msg_to_all(&self, msg: &GameMessage) { - match self.list_players() { - Ok(list) => { - for player in list { - self.put_msg_to(msg.clone(), &player); - } - } - Err(_) => { - error!("Cannot put GameMessage with no players."); - } - } - } - - pub fn pop_a_msg(&self) -> Option<(PlayerInfo, ControlMessage)> { - match self.control_data.lock() { - Ok(mut guard) => { - guard.pop_control_event(self) - } - Err(_) => { - None - } - } - } - } - - // 操控信息管理 - impl PadServer { - pub fn get_player_direction(&self, player: &PlayerInfo, key: &u8) -> Option<(f64, f64)> { - match self.control_data.lock() { - Ok(guard) => { - guard.get_direction(player, &key) - } - Err(_) => { - None - } - } - } - - pub fn get_player_axis(&self, player: &PlayerInfo, key: &u8) -> Option<f64> { - match self.control_data.lock() { - Ok(guard) => { - guard.get_axis(player, &key) - } - Err(_) => { - None - } - } - } - - pub fn get_player_button_status(&self, player: &PlayerInfo, key: &u8) -> Option<bool> { - match self.control_data.lock() { - Ok(guard) => { - guard.get_button_status(player, &key) - } - Err(_) => { - None - } - } - } - } - - // 服务端玩家管理 - impl PadServer { - - pub fn is_player_online (&self, player: &PlayerInfo) -> bool { - let guard = self.online_players.lock().unwrap(); - guard.contains_key(&player.account.player_hash) - } - - fn set_player_online (&self, player: &PlayerInfo, online: bool) { - let online_current = self.is_player_online(player); - if online_current && !online { - let mut guard = self.online_players.lock().unwrap(); - guard.remove(&player.account.player_hash); - info!("{} is OFFLINE!", player.account.id); - } else if !online_current && online { - let mut guard = self.online_players.lock().unwrap(); - guard.insert(player.account.player_hash.clone(), player.clone()); - info!("{} is ONLINE!", player.account.id); - } - } - - pub fn is_player_banned (&self, player: &PlayerInfo) -> bool { - let guard = self.banned_players.lock().unwrap(); - guard.contains_key(&player.account.player_hash) - } - - pub fn kick_player(&self, player: &PlayerInfo) { - if self.is_player_online(player) { - self.put_msg_to(Leave(LeaveReason::YouAreKicked), player); - } - } - - pub fn ban_player(&self, player: &PlayerInfo) { - self.set_player_banned(player, true); - if self.is_player_online(player) { - self.put_msg_to(Leave(LeaveReason::YouAreBanned), player); - } - } - - pub fn pardon_player(&self, player: &PlayerInfo) { - self.set_player_banned(player, false); - } - - fn set_player_banned (&self, player: &PlayerInfo, banned: bool) { - let banned_current = self.is_player_banned(player); - if banned_current && !banned { - let mut guard = self.banned_players.lock().unwrap(); - guard.remove(&player.account.player_hash); - info!("Pardoned player {}", player.account.id); - } else if !banned_current && banned { - let mut guard = self.banned_players.lock().unwrap(); - guard.insert(player.account.player_hash.clone(), player.clone()); - info!("Banned player {}!", player.account.id); - } - } - - pub fn list_players(&self) -> Result<Vec<PlayerInfo>, PoisonError<MutexGuard<HashMap<String, PlayerInfo>>>> { - match self.online_players.lock() { - Ok(guard) => { - Ok(guard.values().cloned().collect()) - } - Err(err) => Err(err) - } - } - - pub fn list_players_banned(&self) -> Result<Vec<PlayerInfo>, PoisonError<MutexGuard<HashMap<String, PlayerInfo>>>> { - match self.banned_players.lock() { - Ok(guard) => { - Ok(guard.values().cloned().collect()) - } - Err(err) => Err(err) - } - } - - pub fn find_online_player(&self, hash: String) -> Option<PlayerInfo> { - match self.online_players.lock() { - Ok(guard) => { - guard.get(&hash).cloned() - } - Err(_) => None - } - } - } - - // 服务端状态控制 - #[allow(dead_code)] - impl PadServer { - - pub fn stop_server(&self) { - self.put_msg_to_all(&Leave(ServerClosed)); - self.stop.store(true, SeqCst); - } - - pub fn start_server(self: Arc<Self>) { - - // 构建 Logger - if ! self.quiet { - logger_build(); - } - - // 运行时 - let runtime = Self::get_runtime(); - - info!("Starting \"NoGamepads Server\"."); - - // 入口 - let console = self.enable_console; - let entry = self.get_entry(console); - - // 阻塞运行 - runtime.block_on(entry); - } - - fn get_runtime() -> Runtime { - tokio::runtime::Builder::new_multi_thread() - .thread_name("nogpad-server") - .thread_stack_size(32 * 1024 * 1024) - .enable_time() - .enable_io() - .build() - .unwrap() - } - - fn get_entry(self: Arc<Self>, debug: bool) -> impl Future<Output = ()> + Send + 'static { - async move { - let main_thread = spawn({ - let client = Arc::clone(&self); - async move { - Self::main_request_thread(client).await - } - }); - - let background_thread = spawn({ - let client = Arc::clone(&self); - async move { - Self::background_thread(client).await - } - }); - - let ctrl_c_thread = spawn({ - let client = Arc::clone(&self); - async move { - Self::process_ctrl_c(client).await - } - }); - - if debug { - let debug_cli = spawn({ - let client = Arc::clone(&self); - async move { - Self::process_debug_cli(client).await - } - }); - - let _ = tokio::join!(ctrl_c_thread, debug_cli, main_thread, background_thread); - } else { - let _ = tokio::join!(ctrl_c_thread, main_thread, background_thread); - } - } - } - - pub fn lock_game(&self) { - self.game_locked.store(true, SeqCst); - } - - pub fn unlock_game(&self) { - self.game_locked.store(false, SeqCst); - } - - pub fn is_game_locked(&self) -> bool { - self.game_locked.load(SeqCst) - } - - pub fn enter_monitor(&self) { - self.monitor_view.store(true, SeqCst); - } - - pub fn exit_monitor(&self) { - self.monitor_view.store(false, SeqCst); - } - - async fn main_request_thread(self: Arc<Self>) { - - let addr_str = format!("{}:{}", self.address.to_string(), self.port); - info!("Server listening at {}", addr_str); - - // Tcp 监听器 - let listener : TcpListener; - match TcpListener::bind(&addr_str).await { - Ok(result) => { - info!("Listener created."); - listener = result; - } - Err(_) => { - error!("Server listening at {} failed!", addr_str); - exit(1); - } - } - - // 请求信息循环 - loop { - match listener.accept().await { - Ok((stream, _)) => { - spawn(Self::process_request(Arc::clone(&self), stream)); - } - Err(error) => { - error!("Error: {}", error); - } - } - } - } - - async fn process_request(self: Arc<Self>, mut stream: TcpStream) { - let mut buffer = [0; 1024]; - let connection_msg : ConnectionMessage = read_msg(&mut buffer, &mut stream).await; - match connection_msg { - - // 客户端请求加入游戏,并建立长连接 - ConnectionMessage::Connection(info) => { - - // 加入游戏资格检测 - info!("Account {} trying to connect.", info.account.player_hash); - - // 0. 当前游戏是否已经锁定? - if self.is_game_locked() { - // 当前游戏已经锁定,禁止加入玩家,发送失败信息,并断开连接 - send_msg(&mut stream, ConnectionCallbackMessage::Deny(GameLocked)).await; - return; - } - - // 1. 是否存在重复玩家? - let online = self.is_player_online(&info); - if online { - // 当前玩家已在线,发送失败信息,并断开连接 - send_msg(&mut stream, ConnectionCallbackMessage::Deny(ContainSamePlayer)).await; - return; - } - - // 2. 该玩家是否被封禁? - let banned = self.is_player_banned(&info); - if banned { - // 当前玩家已被封禁,发送失败信息,并断开连接 - send_msg(&mut stream, ConnectionCallbackMessage::Deny(PlayerBanned)).await; - return; - } - - // OK!若执行到此处,说明该玩家具有加入资格,Welcome! - - send_msg(&mut stream, ConnectionCallbackMessage::Ok).await; - let callback : ConnectionMessage = read_msg(&mut buffer, &mut stream).await; - - match callback { - // 玩家已就绪,发送 Welcome 信息以邀请该玩家加入游戏 - ConnectionMessage::Ready => { - info!("Player \"{}\" is ready!", info.account.id); - - // 发送 Welcome - send_msg(&mut stream, ConnectionCallbackMessage::Welcome).await; - - // 注册该玩家到在线列表 - self.set_player_online(&info, true); - - // 启动控制循环 - - spawn(Self::long_connection(Arc::clone(&self), stream, info)); - }, - _ => { - send_msg(&mut stream, ConnectionCallbackMessage::Deny(WhatTheHell)).await; // WTH ? - } - } - } - - // 客户端请求获得游戏信息 - ConnectionMessage::RequestProfile => { - // 发送游戏信息到客户端 - send_msg(&mut stream, ConnectionCallbackMessage::Profile(self.game_profile.clone())).await; - } - - // 客户端发来了错误信息 - ConnectionMessage::Err => { - match stream.peer_addr() { - Ok(addr) => { - warn!("Received an error message from {}.", addr.to_string()); - } - Err(_) => { - warn!("Received an error message from unknown pad_service."); - } - } - } - - // 客户端发来了不相干的信息 - _ => { - match stream.peer_addr() { - Ok(addr) => { - warn!("Received unknown connection message from {}.", addr.to_string()); - } - Err(_) => { - warn!("Received unknown connection message from unknown pad_service."); - } - } - } - } - } - - async fn long_connection(self: Arc<Self>, stream: TcpStream, player_info: PlayerInfo) { - let player_info_arc = Arc::new(player_info); - let (reader, writer) = io::split(stream); - spawn(Self::read_task(Arc::clone(&self), reader, Arc::clone(&player_info_arc))); - spawn(Self::write_task(Arc::clone(&self), writer, Arc::clone(&player_info_arc))); - } - - async fn read_task(self: Arc<Self>, - mut reader: ReadHalf<TcpStream>, - player_info: Arc<PlayerInfo>) { - let player_hash = player_info.account.player_hash.clone(); - let mut buf = [0u8; 1024]; - loop { - match reader.read(&mut buf).await { - Ok(0) => break, - Ok(n) => { - let msg = ControlMessage::de(buf[0..n].to_vec()); - match self.control_data.lock() { - Ok(mut guard) => { - info!("{:?} from {}({})", &msg, player_info.customize.nickname, player_info.account.id); - let player_info = self.find_online_player(player_hash.clone()); - if player_info.is_some() { - let player_info = player_info.unwrap(); - guard.insert_control(player_info, msg); - } else { - warn!("Player \"{}\" not found!", player_hash); - } - } - Err(_) => { - } - } - } - Err(e) => { - warn!("Error reading from stream: {}", e); - - self.set_player_online(&player_info, false); - - // 放入一条错误信息到队列,使 write_task 及时发现该玩家离开 - self.put_msg_to(GameMessage::Err, &player_info); - - break; - } - } - } - } - - async fn write_task(self: Arc<Self>, - mut writer: WriteHalf<TcpStream>, - player_info: Arc<PlayerInfo>) { - let player_hash = player_info.account.player_hash.clone(); - let mut exit = false; - loop { - let msg : Option<GameMessage>; - match self.write_list.lock() { - Ok(mut hash_map) => { - if ! hash_map.is_empty() { - match hash_map.get_mut(&player_hash) { - None => { - msg = None; - } - Some(queue) => { - if ! queue.is_empty() { - msg = queue.pop_front(); - } else { - msg = None; - hash_map.remove(&player_hash); - } - } - } - } - else { msg = None; } - } - Err(_) => { - msg = None; - } - } - if msg.is_some() { - let msg = msg.unwrap(); - match &writer.write_all(NgpdMessageEncoder::en(&msg).as_slice()).await { - Ok(_) => { - - info!("Sent {:?} to {}", msg, &player_info.account.id); - } - Err(error) => { - warn!("Sent {:?} to {} failed!", msg, &player_info.account.id); - warn!("{:?}", error); - - exit = true; - } - } - } - if exit { - warn!("Long connection between \"{}\" closed.", &player_info.account.id); - break - } - } - } - - async fn background_thread(self: Arc<Self>) { - loop { - // 退出程序的监听 - if self.stop.load(SeqCst) { - tokio::time::sleep(Duration::from_secs(1)).await; - - info!("Main thread exited."); - exit(0); - } - } - } - - async fn process_ctrl_c(self: Arc<Self>) { - loop { - signal::ctrl_c().await.unwrap(); - if self.monitor_view.load(SeqCst) { - self.exit_monitor(); - } else { - self.stop_server(); - info!("Stopping server..."); - break; - } - } - } - - async fn process_debug_cli(self: Arc<Self>) { - loop { - if self.stop.load(SeqCst) { - info!("Debug console exited"); - return; - } - - if ! self.monitor_view.load(SeqCst) { - tokio::time::sleep(Duration::from_secs_f64(0.2)).await; - - // 控制台模式 - let option: Option<Psc> = read_cli( - format!("SERVER {}> ", self.address.to_string()).as_str(), - "psc".to_string(), - Psc::command() - ).await; - match option { - None => {} - Some(cmd) => { - process_debug_cmd(cmd, Arc::clone(&self)); - } - } - } else { - tokio::time::sleep(Duration::from_secs_f64(0.2)).await; - - // 实时信息模式 - - // 表头文本 - let mut header : Vec<String> = Vec::new(); - header.push("PLAYER \\ KEYS".to_string()); - self.all_keys(|key, name, i|{ - if i == 0 { - header.push(format!("{}(btn:{})", name, key)); - } else if i == 1 { - header.push(format!("{}(dir:{})", name, key)); - } else if i == 2 { - header.push(format!("{}(ax:{})", name, key)); - } - }); - - let mut info_table = Table::new(); - - // 添加表头 - info_table.add_row(Row::from_iter(header)); - - // 玩家 - let players = &self.deref().online_players; - match players.lock() { - Ok(guard) => { - for (_player_hash, player) in guard.iter() { - - // 行 - let mut line = Vec::new(); - line.push(player.account.id.to_string()); - self.all_keys(|key, _, i|{ - if i == 0 { - // 按钮 - let r = self.get_player_button_status(player, key); - if r.is_some() { - let r = r.unwrap(); - if r { - line.push("TRUE".to_string()); - } else { - line.push("FALSE".to_string()); - } - } else { - line.push("UNKNOWN".to_string()); - } - - } else if i == 1 { - // 方向 - let r = self.get_player_direction(player, key); - if r.is_some() { - let r = r.unwrap(); - line.push(format!("{}, {}", r.0, r.1)); - } else { - line.push("UNKNOWN".to_string()); - } - - } else if i == 2 { - // 轴向 - let r = self.get_player_axis(player, key); - if r.is_some() { - let r = r.unwrap(); - line.push(format!("{}", r)); - } else { - line.push("UNKNOWN".to_string()); - } - } - }); - - // 添加行文本 - info_table.add_row(Row::from_iter(line)); - } - } - Err(_) => {} - } - - let result = info_table.to_string(); - let _ = clear(); - println!("[HELP] Ctrl + C to exit monitor.\n{}", result); - } - } - } - - fn all_keys<F>(self: &Arc<Self>, mut f: F) - where F: FnMut(&u8, &String, i32){ - let mut i = 0; - for iter in [ - self.keys.button_keys.iter(), - self.keys.direction_keys.iter(), - self.keys.axis_keys.iter(), - ] { - for (key, name) in iter { - f(key, name, i); - } - i += 1; - } - } - } -}
\ No newline at end of file diff --git a/core/src/pad_service/server_debug_cli.rs b/core/src/pad_service/server_debug_cli.rs deleted file mode 100644 index ac52253..0000000 --- a/core/src/pad_service/server_debug_cli.rs +++ /dev/null @@ -1,212 +0,0 @@ -use std::collections::HashMap; -use crate::pad_data::pad_messages::nogamepads_messages::{GameMessage}; -use crate::pad_service::server::nogamepads_server::PadServer; -use clap::{Args, Parser, Subcommand}; -use std::sync::{Arc, MutexGuard, PoisonError}; -use log::{error, info}; -use crate::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; - -/// NoGamePads Server - Cli -#[derive(Parser, Debug)] -#[command(author, version, about, long_about = None)] -pub struct Psc { - #[command(subcommand)] - command: Commands, -} - -#[derive(Subcommand, Debug)] -enum Commands { - - // 清屏 - #[command(about = "Clean the screen")] - Clear, - - #[command(about = "Enter monitor")] - Monitor, - - // 关闭服务器 - #[command(about = "Close the server")] - Stop, - - // 展示所有玩家 - #[command(about = "List all online players")] - List, - - // 展示所有封禁的玩家 - #[command(about = "List all banned players")] - Banned, - - // 取出一条消息 - #[command(about = "Pop a message")] - Pop, - - // 踢出玩家 - #[command(about = "Kick a player")] - Kick(PlayerArgs), - - // 封禁玩家 - #[command(about = "Ban a player")] - Ban(PlayerArgs), - - // 解封(赦免)玩家 - #[command(about = "Pardon a player")] - Pardon(PlayerArgs), - - // 锁定游戏 - #[command(about = "Lock this game")] - Lock, - - // 解锁游戏 - #[command(about = "Unlock this game")] - Unlock, - - // 激活事件触发器 - #[command(about = "Send SkinEventTrigger")] - Event(EventArgs) -} - -// 检查收到的消息 -#[derive(Args, Debug)] -struct ReceivedArgs { - - #[arg(default_value = "0")] - player: usize, - - #[arg(long)] - list: bool, -} - -/// 激活事件触发器 参数 -#[derive(Args, Debug)] -struct EventArgs { - - // 玩家序号 - #[arg(value_name = "PLAYER_INDEX")] - index: usize, - - // 事件编号 - #[arg(value_name = "CONTENT")] - message: u8, -} - -#[derive(Args, Debug)] -struct PlayerArgs { - - // 玩家序号 - #[arg(value_name = "PLAYER_INDEX")] - index: usize -} - -pub fn process_debug_cmd (cmd: Psc, server: Arc<PadServer>) { - match cmd.command { - - Commands::Clear => { - clearscreen::clear().expect("Failed to clear screen"); - } - - Commands::Monitor => { - server.enter_monitor(); - } - - Commands::Stop => { - server.stop_server(); - } - - Commands::List => { - print_player_list(server.list_players()); - } - - Commands::Banned => { - print_player_list(server.list_players_banned()); - } - - Commands::Pop => { - let message = server.pop_a_msg(); - if message.is_some() { - let (player, msg) = message.unwrap(); - info!("{:?} from \"{}\"({})", msg, player.customize.nickname, player.account.id); - } - } - - Commands::Kick(args) => { - let player = get_player_by_index(&server, args.index); - if player.is_some() { - let player = player.unwrap(); - server.kick_player(&player); - } - } - - Commands::Ban(args) => { - let player = get_player_by_index(&server, args.index); - if player.is_some() { - let player = player.unwrap(); - server.ban_player(&player); - } - } - - Commands::Pardon(args) => { - let player = get_player_by_ban_index(&server, args.index); - if player.is_some() { - let player = player.unwrap(); - server.pardon_player(&player); - } - } - - Commands::Lock => { - if ! server.is_game_locked() { - server.lock_game(); - info!("Game locked"); - } - } - - Commands::Unlock => { - if server.is_game_locked() { - server.unlock_game(); - info!("Game unlocked"); - } - } - - Commands::Event(args) => { - put_to_list(server, args.index, GameMessage::SkinEventTrigger(args.message)); - } - } -} - -fn put_to_list(server: Arc<PadServer>, player_index: usize, message: GameMessage) { - match get_player_by_index(&server, player_index) { - None => { - error!("Put message failed : Player index \"{}\" not found!", player_index); - } - Some(player) => { - server.put_msg_to(message, &player); - } - } -} - -fn get_player_by_index(server: &Arc<PadServer>, index: usize) -> Option<PlayerInfo> { - let list = server.list_players().unwrap_or(Vec::new()); - let max = list.iter().count(); - let index = if max > 0 { index.clamp(0, max - 1) } else { 0 }; - - let result = list.get(index).cloned(); - result -} - -fn get_player_by_ban_index(server: &Arc<PadServer>, index: usize) -> Option<PlayerInfo> { - let list = server.list_players_banned().unwrap_or(Vec::new()); - let max = list.iter().count(); - let index = if max > 0 { index.clamp(0, max - 1) } else { 0 }; - - let result = list.get(index).cloned(); - result -} - -fn print_player_list(list: Result<Vec<PlayerInfo>, PoisonError<MutexGuard<HashMap<String, PlayerInfo>>>>) { - let list = list.unwrap_or(Vec::new()); - let mut i = 0; - for player in list { - let n = player.customize.nickname; - info!("({}){} ", i, n); - i += 1; - } -}
\ No newline at end of file diff --git a/core/src/service/cli_addition/mod.rs b/core/src/service/cli_addition/mod.rs new file mode 100644 index 0000000..ced68da --- /dev/null +++ b/core/src/service/cli_addition/mod.rs @@ -0,0 +1,2 @@ +pub mod runtime_consoles; +mod utils; diff --git a/core/src/service/cli_addition/runtime_consoles.rs b/core/src/service/cli_addition/runtime_consoles.rs new file mode 100644 index 0000000..76ff20c --- /dev/null +++ b/core/src/service/cli_addition/runtime_consoles.rs @@ -0,0 +1,60 @@ +use crate::service::cli_addition::utils::read_cli; +use clap::{Command, FromArgMatches}; +use std::sync::{Arc, Mutex}; +use tokio::{join, spawn}; +use crate::service::service_runner::NoGamepadsService; + +pub struct RuntimeConsole<PadService, Cmd> +where Cmd: FromArgMatches { + command: Command, + prefix: String, + service: Arc<Mutex<PadService>>, + process_command: fn(Arc<Mutex<PadService>>, Cmd), +} + +impl<PadService: Send + 'static, Cmd: FromArgMatches + 'static> RuntimeConsole<PadService, Cmd> { + pub fn build(command: Command, + prefix: String, + service: Arc<Mutex<PadService>>, + process_command: fn(Arc<Mutex<PadService>>, Cmd), + ) -> RuntimeConsole<PadService, Cmd> { + RuntimeConsole { command, prefix, service, process_command } + } + + pub fn build_entry(self) -> NoGamepadsService { + let arc = Arc::new(self); + + let entry = async move { + let console_main = spawn({ + let console = Arc::clone(&arc); + async move { + Self::console_main(console).await + } + }); + + // Join + let _ = join!(console_main); + }; + + Box::pin(entry) + } + + async fn console_main(self: Arc<RuntimeConsole<PadService, Cmd>>) { + let prefix_uppercase = self.prefix.to_uppercase(); + let prefix_lowercase = self.prefix.to_lowercase(); + + loop { + let option : Option<Cmd> = read_cli( + format!("{}> ", prefix_uppercase), + &prefix_lowercase, + self.command.clone() + ).await; + match option { + None => {} + Some(cmd) => { + (self.process_command)(Arc::clone(&self.service), cmd); + } + } + } + } +}
\ No newline at end of file diff --git a/core/src/service/cli_addition/utils.rs b/core/src/service/cli_addition/utils.rs new file mode 100644 index 0000000..05969a5 --- /dev/null +++ b/core/src/service/cli_addition/utils.rs @@ -0,0 +1,58 @@ +use clap::{Command, FromArgMatches}; +use clap::ColorChoice::Auto; +use tokio::io::{AsyncBufReadExt, AsyncWriteExt}; + +pub async fn read_cli<Cmd>(prefix: String, entry: &String, cmd: Command) -> Option<Cmd> +where Cmd: FromArgMatches { + let input: String = { + let mut buffer = String::new(); + let mut stdin = tokio::io::BufReader::new(tokio::io::stdin()); + let mut stdout = tokio::io::stdout(); + + stdout.write_all(prefix.as_bytes()).await.ok().unwrap(); + stdout.flush().await.ok().unwrap(); + + stdin.read_line(&mut buffer).await.ok().unwrap(); + buffer.trim().to_string() + }; + + process_debug_cli(entry, input, cmd).await +} + +async fn process_debug_cli<Cmd>(entry: &String, input: String, cmd: Command) -> Option<Cmd> +where Cmd: FromArgMatches { + if input.trim().is_empty() { + return None; + } + + let cmd = cmd + .color(Auto) + .help_template( + "{subcommands}{options}" + ) + .disable_help_flag(true) + .disable_version_flag(true); + + let args = shell_words::split(input.as_str()).unwrap_or_else(|_e| { + ["".to_string()].to_vec() + }); + + let full_args = std::iter::once(entry.into()).chain(args); + + match cmd.try_get_matches_from(full_args) { + Ok(matches) => { + match Cmd::from_arg_matches(&matches) { + Ok(cmd) => { + Some(cmd) + } + Err(_err) => { + None + } + } + } + Err(err) => { + println!("{}", err); + None + } + } +}
\ No newline at end of file diff --git a/core/src/service/mod.rs b/core/src/service/mod.rs new file mode 100644 index 0000000..2631af8 --- /dev/null +++ b/core/src/service/mod.rs @@ -0,0 +1,4 @@ +pub mod cli_addition; +pub mod tcp_network; +pub mod service_types; +pub mod service_runner; diff --git a/core/src/service/service_runner.rs b/core/src/service/service_runner.rs new file mode 100644 index 0000000..bd2d1d9 --- /dev/null +++ b/core/src/service/service_runner.rs @@ -0,0 +1,31 @@ +use std::pin::Pin; +use crate::service::tcp_network::utils::tokio_utils::build_tokio_runtime; +use tokio::spawn; + +#[macro_export] +#[allow(unused_macros)] +macro_rules! run_services { + ($($service:expr),+ $(,)?) => { + nogamepads_core::service::service_runner::ServiceRunner::run(Vec::from([$($service),+])); + }; +} + +pub type NoGamepadsService = Pin<Box<dyn Future<Output = ()> + Send>>; + +pub struct ServiceRunner; + +impl ServiceRunner { + pub fn run(futures: Vec<NoGamepadsService>) { + let runtime = build_tokio_runtime("nogamepads".to_string()); + runtime.block_on(async { + let mut handles = Vec::new(); + for fut in futures { + handles.push(spawn(fut)); + } + + for handle in handles { + handle.await.expect("Task panicked"); + } + }); + } +}
\ No newline at end of file diff --git a/core/src/service/service_types.rs b/core/src/service/service_types.rs new file mode 100644 index 0000000..dda18bd --- /dev/null +++ b/core/src/service/service_types.rs @@ -0,0 +1,13 @@ +use bincode::{Decode, Encode}; +use crate::data::message::traits::MessageEncoder; +use crate::encoder; + +#[derive(Default, Encode, Decode, PartialEq, Debug, Clone, Eq, Hash)] +pub enum ServiceType { + #[default] + TCPConnection, + BlueTooth, + USB, +} + +encoder!(ServiceType);
\ No newline at end of file diff --git a/core/src/service/tcp_network/long_connection.rs b/core/src/service/tcp_network/long_connection.rs new file mode 100644 index 0000000..ada9751 --- /dev/null +++ b/core/src/service/tcp_network/long_connection.rs @@ -0,0 +1,272 @@ +use crate::data::player::structs::Player; +use crate::service::tcp_network::pad_client::structs::PadClientNetwork; +use crate::service::tcp_network::pad_server::structs::PadServerNetwork; +use std::sync::Arc; +use std::sync::atomic::Ordering::SeqCst; +use log::{error, info, trace, warn}; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf}; +use tokio::net::TcpStream; +use tokio::spawn; +use nogamepads::entry_mutex; +use crate::data::message::enums::{ControlMessage, GameMessage}; +use crate::data::message::enums::ExitReason::GameOver; +use crate::data::message::enums::GameMessage::{End, LetExit}; +use crate::data::message::traits::{MessageEncoder, MessageManager}; +use crate::service::service_types::ServiceType; +use crate::service::service_types::ServiceType::TCPConnection; + +impl PadServerNetwork { + + pub async fn start_long_connection(self: Arc<Self>, player: Player, stream: TcpStream) { + let (reader, writer) = stream.into_split(); + spawn(Self::read_task(Arc::clone(&self), player.clone(), reader)); + spawn(Self::write_task(Arc::clone(&self), player.clone(), writer)); + } + + async fn read_task(self: Arc<Self>, player: Player, mut reader: OwnedReadHalf) { + info!("[TCP Server] [Runtime] Reader started."); + entry_mutex!(self.runtime, |guard| { + guard.reader_count += 1; + }); + + let mut buffer = [0u8; 1024]; + let mut err_message_counter = 0; + + loop { + let read = reader.read(&mut buffer).await; + match read { + Ok(size) => { + let message : ControlMessage = ControlMessage::de(buffer[0..size].to_vec()); + + // Preprocess messages: handle exit messages. + match message { + ControlMessage::Exit => { + info!("[TCP Server] [Runtime] Player {} exited.", player.account.id); + entry_mutex!(self.runtime, |guard| { + guard.send((player.account.clone(), End), player.account.clone(), ServiceType::TCPConnection); + }); + break; + } + + ControlMessage::Err => { + info!("[TCP Server] [Runtime] Received error message from {}.", player.account.id); + if err_message_counter < 16 { + err_message_counter += 1; + } else { + warn!("[TCP Server] [Runtime] Too many error messages! Connection closed."); + entry_mutex!(self.runtime, |guard| { + guard.send((player.account.clone(), End), player.account.clone(), ServiceType::TCPConnection); + }); + break; + } + } + + _ => {} + } + + // Process messages + entry_mutex!(self.runtime, |guard| { + trace!("[TCP Server] [Runtime] Received: {:?}", &message); + guard.put_into_receive_list((player.account.clone(), message), player.account.clone(), ServiceType::TCPConnection); + }); + } + + Err(error) => { + warn!("[TCP Server] [Runtime] Error reading from socket: {:?}", error); + break; + } + } + + // Check close + entry_mutex!(self.runtime, |guard| { + if guard.data.close.load(SeqCst) { + break; + } + }); + } + + info!("[TCP Server] [Runtime] Reader between {} closed.", player.account.id); + entry_mutex!(self.runtime, |guard| { + guard.send((player.account.clone(), End), player.account.clone(), TCPConnection); + guard.reader_count -= 1; + }) + } + + async fn write_task(self: Arc<Self>, player: Player, mut writer: OwnedWriteHalf) { + info!("[TCP Server] [Runtime] Writer started."); + entry_mutex!(self.runtime, |guard| { + guard.writer_count += 1; + }); + + let mut closed = false; + + loop { + // Check close + entry_mutex!(self.runtime, |guard| { + if guard.data.close.load(SeqCst) && !closed { + guard.send((player.account.clone(), LetExit(GameOver)), player.account.clone(), ServiceType::TCPConnection); + closed = true; + } + }); + + let mut message = None; + entry_mutex!(self.runtime, |guard| { + message = guard.pop_from_send_list(player.account.clone(), ServiceType::TCPConnection); + }); + + if let Some(message) = message { + + // Preprocess messages: handle end messages. + match message.1 { + End => { + break; + } + GameMessage::Err => { + continue; + } + _ => {} + } + + // Process messages + match writer.write_all(GameMessage::en(&message.1).as_slice()).await { + Ok(_) => { + trace!("[TCP Server] [Runtime] Sent {:?} to {}", &message.1, player.account.id); + writer.flush().await.expect("[TCP Client] [Runtime] Writer encountered an error"); + } + Err(error) => { + warn!("[TCP Server] [Runtime] Sent {:?} to {} failed: {}", &message.1, player.account.id, error); + break; + } + } + } + } + + info!("[TCP Server] [Runtime] Writer between {} closed.", player.account.id); + entry_mutex!(self.runtime, |guard| { + guard.data.sign_player_online_status(&player, TCPConnection, false); + guard.writer_count -= 1; + }) + } +} + +impl PadClientNetwork { + + pub async fn start_long_connection(self: Arc<Self>, stream: TcpStream) { + let (reader, writer) = stream.into_split(); + spawn(Self::read_task(Arc::clone(&self), reader)); + spawn(Self::write_task(Arc::clone(&self), writer)); + } + + async fn read_task(self: Arc<Self>, mut reader: OwnedReadHalf) { + info!("[TCP Client] [Runtime] Reader started."); + + let mut buffer = [0u8; 1024]; + let mut err_message_counter = 0; + loop { + // Check close + entry_mutex!(self.runtime, |guard| { + if guard.close.load(SeqCst) { + break; + } + }); + + let read = reader.read(&mut buffer).await; + match read { + Ok(size) => { + let message : GameMessage = GameMessage::de(buffer[0..size].to_vec()); + + // Preprocess messages: handle exit messages. + match message { + LetExit(reason) => { + info!("[TCP Client] [Runtime] Server let you exit: {:?}", reason); + entry_mutex!(self.runtime, |guard| { + guard.send(ControlMessage::End, 0, ServiceType::TCPConnection); + }); + break; + } + + GameMessage::Err => { + info!("[TCP Client] [Runtime] Received error message from server."); + if err_message_counter < 16 { + err_message_counter += 1; + } else { + warn!("[TCP Client] [Runtime] Too many error messages! Connection closed."); + entry_mutex!(self.runtime, |guard| { + guard.send(ControlMessage::End, 0, ServiceType::TCPConnection); + }); + break; + } + } + + _ => {} + } + + // Process messages + entry_mutex!(self.runtime, |guard| { + trace!("[TCP Client] [Runtime] Received: {:?}", &message); + guard.put_into_receive_list(message, 0, ServiceType::TCPConnection); + }); + } + Err(err) => { + error!("[TCP Client] [Runtime] Reader encountered an error: {}", err); + break; + } + } + } + + info!("[TCP Client] [Runtime] Reader closed."); + } + + async fn write_task(self: Arc<Self>, mut writer: OwnedWriteHalf) { + info!("[TCP Client] [Runtime] Writer started."); + + let mut closed = false; + + loop { + // Check close + if !closed { + entry_mutex!(self.runtime, |guard| { + if guard.close.load(SeqCst) { + guard.send(ControlMessage::Exit, 0, ServiceType::TCPConnection); + closed = true; + } + }); + } + + let mut message = None; + entry_mutex!(self.runtime, |guard| { + message = guard.pop_from_send_list(0, ServiceType::TCPConnection); + }); + + if let Some(message) = message { + + // Preprocess messages: handle exit messages. + match message { + ControlMessage::End => { break; } + ControlMessage::Err => { + continue; + } + _ => {} + } + + // Process messages + match writer.write_all(ControlMessage::en(&message).as_slice()).await { + Ok(_) => { + trace!("[TCP Client] [Runtime] Sent {:?}.", &message); + writer.flush().await.expect("[TCP Client] [Runtime] Writer encountered an error"); + } + Err(error) => { + warn!("[TCP Client] [Runtime] Sent {:?} failed: {}", &message, error); + break; + } + } + } + } + + info!("[TCP Client] [Runtime] Writer closed."); + entry_mutex!(self.runtime, |guard| { + guard.close(); + }) + } +}
\ No newline at end of file diff --git a/core/src/service/tcp_network/mod.rs b/core/src/service/tcp_network/mod.rs new file mode 100644 index 0000000..4954c1c --- /dev/null +++ b/core/src/service/tcp_network/mod.rs @@ -0,0 +1,6 @@ +pub mod utils; +pub mod pad_client; +pub mod pad_server; +pub mod long_connection; + +pub const DEFAULT_PORT : u16 = 5989;
\ No newline at end of file diff --git a/core/src/service/tcp_network/pad_client/implements.rs b/core/src/service/tcp_network/pad_client/implements.rs new file mode 100644 index 0000000..584bc83 --- /dev/null +++ b/core/src/service/tcp_network/pad_client/implements.rs @@ -0,0 +1,156 @@ +use std::net::{IpAddr, SocketAddr}; +use std::sync::{Arc, Mutex}; +use std::sync::atomic::Ordering::SeqCst; +use std::time::Duration; +use log::{error, info, warn}; +use tokio::{join, spawn}; +use tokio::time::sleep; +use nogamepads::entry_mutex; +use crate::data::controller::runtime::structs::ControllerRuntime; +use crate::data::message::enums::ConnectionMessage::{Join, RequestGameInfos}; +use crate::data::message::enums::ConnectionResponseMessage; +use crate::service::service_runner::NoGamepadsService; +use crate::service::tcp_network::pad_client::structs::PadClientNetwork; +use crate::service::tcp_network::DEFAULT_PORT; +use crate::service::tcp_network::utils::stream_utils::{read_msg, send_msg}; +use crate::service::tcp_network::utils::tokio_utils::build_tokio_runtime; + +macro_rules! connect_once { + ($addr:expr, |$conn:ident| $code:block) => {{ + use tokio::net::TcpStream; + match TcpStream::connect($addr).await { + Ok(mut $conn) => { + $code + true + }, + Err(e) => { + error!("[TCP Client] [Main] Connection failed {:?}", e); + false + } + } + }} +} + +impl PadClientNetwork { + + pub fn build(runtime: Arc<Mutex<ControllerRuntime>>) -> PadClientNetwork { + PadClientNetwork { + addr: SocketAddr::from(([127, 0, 0, 1], DEFAULT_PORT)), + runtime + } + } + + pub fn bind_addr(&mut self, addr: SocketAddr) -> &mut PadClientNetwork { + self.addr = addr; + self + } + + pub fn bind_ip(&mut self, addr: IpAddr) -> &mut PadClientNetwork { + self.addr.set_ip(addr); + self + } + + pub fn bind_port(&mut self, port: u16) -> &mut PadClientNetwork { + self.addr.set_port(port); + self + } + + pub fn build_entry(self) -> NoGamepadsService { + let arc = Arc::new(self); + + let entry = async move { + // Connection thread: Download the relevant resources, verify connection eligibility, and attempt to join the game. + let connection_thread = spawn({ + let client = Arc::clone(&arc); + async move { + Self::connection_thread(client).await + } + }); + + // Join + let _ = join!(connection_thread); + }; + + Box::pin(entry) + } + + pub fn connect(self) { + let runtime = build_tokio_runtime("padclient_tcp".to_string()); + + info!("[TCP Client] Connecting to {}:{}", self.addr.ip().to_string(), self.addr.port()); + runtime.block_on(self.build_entry()); + } +} + +impl PadClientNetwork { + + async fn connection_thread(self: Arc<PadClientNetwork>) { + let mut buffer = [0; 1024]; + + // Requests game infos + if !connect_once!(self.addr, |stream| { + info!("[TCP Client] [Main] Requesting game infos."); + send_msg(&mut stream, RequestGameInfos).await; + let response : ConnectionResponseMessage = read_msg(&mut buffer, &mut stream).await; + match response { + ConnectionResponseMessage::GameInfos(infos) => { + entry_mutex!(self.runtime, |guard| { + guard.game_info = infos; + }); + info!("[TCP Client] [Main] Download game infos successfully."); + } + ConnectionResponseMessage::Err => { + warn!("[TCP Client] [Main] Download game infos failed."); + } + _ => { + warn!("[TCP Client] [Main] Not found game infos."); + } + } + }) { + return; + } + + // TODO :: Download game layouts + + // TODO :: Download skin assets + + // Try to join game + let _ = connect_once!(self.addr, |connection| { + let mut player = None; + entry_mutex!(self.runtime, |guard| { + player = Some(guard.player.clone()); + }); + if player.is_some() { + info!("[TCP Client] [Main] Trying to join game."); + send_msg(&mut connection, Join(player.unwrap())).await; + let response : ConnectionResponseMessage = read_msg(&mut buffer, &mut connection).await; + match response { + ConnectionResponseMessage::Welcome => { + + // Long Connection + info!("[TCP Client] [Main] Welcome"); + spawn(Self::start_long_connection(Arc::clone(&self), connection)); + } + ConnectionResponseMessage::Deny(why) => { + error!("[TCP Client] [Main] Connection denied: {:?}", why); + } + _ => { } + } + } else { + error!("[TCP Client] [Main] No player found."); + return; + } + }); + + loop { + sleep(Duration::from_millis(1000)).await; + entry_mutex!(self.runtime, |guard| { + if guard.close.load(SeqCst) { + break; + } + }) + } + + info!("[TCP Client] [Main] Main thread closed."); + } +}
\ No newline at end of file diff --git a/core/src/service/tcp_network/pad_client/mod.rs b/core/src/service/tcp_network/pad_client/mod.rs new file mode 100644 index 0000000..0ff870f --- /dev/null +++ b/core/src/service/tcp_network/pad_client/mod.rs @@ -0,0 +1,2 @@ +pub mod implements; +pub mod structs;
\ No newline at end of file diff --git a/core/src/service/tcp_network/pad_client/structs.rs b/core/src/service/tcp_network/pad_client/structs.rs new file mode 100644 index 0000000..10c93c4 --- /dev/null +++ b/core/src/service/tcp_network/pad_client/structs.rs @@ -0,0 +1,8 @@ +use std::net::SocketAddr; +use std::sync::{Arc, Mutex}; +use crate::data::controller::runtime::structs::ControllerRuntime; + +pub struct PadClientNetwork { + pub(crate) addr: SocketAddr, + pub(crate) runtime: Arc<Mutex<ControllerRuntime>> +}
\ No newline at end of file diff --git a/core/src/service/tcp_network/pad_server/implements.rs b/core/src/service/tcp_network/pad_server/implements.rs new file mode 100644 index 0000000..c4d8cfc --- /dev/null +++ b/core/src/service/tcp_network/pad_server/implements.rs @@ -0,0 +1,186 @@ +use std::net::{IpAddr, SocketAddr}; +use std::sync::{Arc, Mutex}; +use std::sync::atomic::Ordering::SeqCst; +use std::time::Duration; +use log::{error, info, trace, warn}; +use tokio::{join, select, spawn}; +use tokio::net::{TcpListener, TcpStream}; +use tokio::sync::watch::{channel, Receiver, Sender}; +use tokio::time::sleep; +use nogamepads::entry_mutex; +use crate::data::game::runtime::structs::GameRuntime; +use crate::data::message::enums::ConnectionMessage; +use crate::data::message::enums::ConnectionMessage::{Join, RequestGameInfos, RequestLayoutConfigure, RequestSkinPackage, Ready}; +use crate::data::message::enums::ConnectionResponseMessage::{Deny, GameInfos, Welcome}; +use crate::service::service_runner::NoGamepadsService; +use crate::service::tcp_network::DEFAULT_PORT; +use crate::service::tcp_network::pad_server::structs::PadServerNetwork; +use crate::service::tcp_network::utils::stream_utils::{get_target_address, read_msg, send_msg}; +use crate::service::tcp_network::utils::tokio_utils::build_tokio_runtime; + +impl PadServerNetwork { + + pub fn build(runtime: Arc<Mutex<GameRuntime>>) -> PadServerNetwork { + let (close_tx, close_rx) = channel(false); + PadServerNetwork { + addr: SocketAddr::from(([127, 0, 0, 1], DEFAULT_PORT)), + runtime, + close_tx, + close_rx + } + } + + pub fn bind_ip(&mut self, ip: IpAddr) -> &mut PadServerNetwork { + self.addr.set_ip(ip); + self + } + + pub fn bind_port(&mut self, port: u16) -> &mut PadServerNetwork { + self.addr.set_port(port); + self + } + + pub fn build_entry(self) -> NoGamepadsService { + let arc = Arc::new(self); + + let entry = async move { + // Main thread: Used to handle connection requests, data requests, and transfer skin assets + let main_thread = spawn({ + let server = Arc::clone(&arc); + async move { + Self::main_thread(server).await + } + }); + + let close_checker = { + let server = Arc::clone(&arc); + async move { + Self::close_checker(server).await + } + }; + + // Join + let _ = join!(close_checker, main_thread); + }; + + Box::pin(entry) + } + + pub fn listening_block_on(self) { + let runtime = build_tokio_runtime("padserver_tcp".to_string()); + + info!("[TCP Server] Server start."); + runtime.block_on(self.build_entry()); + info!("[TCP Server] Finished."); + } +} + +impl PadServerNetwork { + + async fn main_thread(self: Arc<PadServerNetwork>) { + + info!("[TCP Server] [Main] Server listening at {}", self.addr.to_string()); + + let listener = TcpListener::bind(self.addr).await; + if listener.is_err() { + error!("[TCP Server] [Main] Failed to bind to {}", self.addr.to_string()); + return; + } + + let listener = listener.unwrap(); + info!("[TCP Server] [Main] Listener created, start listening."); + + let mut local_close_rx = self.close_rx.clone(); + + loop { + select! { + _ = local_close_rx.changed() => { + if *local_close_rx.borrow() { + break; + } + } + + accept = listener.accept() => { + match accept { + Ok((stream, _)) => { + spawn(Self::process_connection(Arc::clone(&self), stream)); + } + Err(error) => { + warn!("[TCP Server] [Main] Failed to accept TCP connections: {}", error); + } + } + } + } + } + + info!("[TCP Server] [Main] Main thread closed."); + } + + async fn process_connection(self: Arc<Self>, mut stream: TcpStream) { + let mut buffer = [0; 1024]; + let message: ConnectionMessage = read_msg(&mut buffer, &mut stream).await; + let from_address = get_target_address(&stream); + + match message { + + Join(player) => { + trace!("[TCP Server] [Main] Trying to join Player \"{}\"", &player.account.id); + let mut result = Ok(()); + entry_mutex!(self.runtime, |guard| { + match guard.try_join_player(player.clone()) { + Ok(_) => { result = Ok(()); } + Err(why) => { result = Err(why); } + } + }); + if result.is_err() { + let fail_message = result.unwrap_err(); + error!("[TCP Server] [Main] Player join failed: {:?}", &fail_message); + send_msg(&mut stream, Deny(fail_message)).await; + } else { + + // Long Connection + info!("[TCP Server] [Main] Player joined, begin long connection."); + send_msg(&mut stream, Welcome).await; + spawn(Self::start_long_connection(Arc::clone(&self), player, stream)); + } + } + + RequestGameInfos => { + info!("[TCP Server] [Main] Client({}) requests game infos.", from_address); + let mut info = Default::default(); + entry_mutex!(self.runtime, |guard| { + info = guard.info.clone(); + }); + send_msg(&mut stream, GameInfos(info)).await; + info!("[TCP Server] [Main] Game infos sent."); + } + + RequestLayoutConfigure => { + info!("[TCP Server] [Main] Client({}) requests layout configures.", from_address); + } + + RequestSkinPackage => { + info!("[TCP Server] [Main] Client({}) requests to download skin package.", from_address); + } + + Ready => { + info!("[TCP Server] [Main] Client({}) is ready!", from_address); + warn!("[TCP Server] [Main] But I don't know who he is.....") + } + + _ => { } + } + } + + async fn close_checker(self: Arc<Self>) { + loop { + sleep(Duration::from_millis(1000)).await; + entry_mutex!(self.runtime, |guard| { + if guard.data.close.load(SeqCst) { + let _ = self.close_tx.send(true); + break; + } + }) + } + } +}
\ No newline at end of file diff --git a/core/src/service/tcp_network/pad_server/mod.rs b/core/src/service/tcp_network/pad_server/mod.rs new file mode 100644 index 0000000..b37b320 --- /dev/null +++ b/core/src/service/tcp_network/pad_server/mod.rs @@ -0,0 +1,2 @@ +pub mod implements; +pub mod structs; diff --git a/core/src/service/tcp_network/pad_server/structs.rs b/core/src/service/tcp_network/pad_server/structs.rs new file mode 100644 index 0000000..f46608a --- /dev/null +++ b/core/src/service/tcp_network/pad_server/structs.rs @@ -0,0 +1,12 @@ +use crate::data::game::runtime::structs::GameRuntime; +use std::net::SocketAddr; +use std::sync::{Arc, Mutex}; +use tokio::sync::watch::{Receiver, Sender}; + +pub struct PadServerNetwork { + pub(crate) addr: SocketAddr, + pub(crate) runtime: Arc<Mutex<GameRuntime>>, + + pub(crate) close_tx: Sender<bool>, + pub(crate) close_rx: Receiver<bool>, +}
\ No newline at end of file diff --git a/core/src/service/tcp_network/utils/mod.rs b/core/src/service/tcp_network/utils/mod.rs new file mode 100644 index 0000000..ad06dac --- /dev/null +++ b/core/src/service/tcp_network/utils/mod.rs @@ -0,0 +1,2 @@ +pub mod stream_utils; +pub mod tokio_utils;
\ No newline at end of file diff --git a/core/src/service/tcp_network/utils/stream_utils.rs b/core/src/service/tcp_network/utils/stream_utils.rs new file mode 100644 index 0000000..9ccff3b --- /dev/null +++ b/core/src/service/tcp_network/utils/stream_utils.rs @@ -0,0 +1,44 @@ +use std::fmt::Debug; +use bincode::{Decode, Encode}; +use log::{error, trace}; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::net::TcpStream; +use crate::data::message::traits::MessageEncoder; + +pub async fn send_msg<Message>( + stream: &mut TcpStream, + msg: impl MessageEncoder<Message> + Encode + Decode<()> + Default + Debug +) +where Message: MessageEncoder<Message> + Encode + Decode<()> + Default + Debug { + match stream.write_all(MessageEncoder::en(&msg).as_slice()).await { + Ok(_) => { trace!("[Message Sender] Sent {:?} to {}", msg, get_target_address(stream)); } + Err(err) => { error!("[Message Sender] Failed to send message: {}", err); } + } +} + +pub async fn read_msg<Message>( + buffer: &mut [u8], + stream: &mut TcpStream +) -> Message +where Message: MessageEncoder<Message> + Encode + Decode<()> + Default + Debug { + match stream.read(buffer).await { + Ok(read) => { + let received = Message::de(Vec::from(&buffer[..read])); + trace!("[Message Reader] Received {:?} from {}", received, get_target_address(stream)); + received + } + Err(err) => { + error!("[Message Reader] Error reading from stream: {}", err); + Message::err_result_decode() + } + } +} + +pub fn get_target_address(stream: &TcpStream) -> String { + let p = stream.peer_addr(); + if p.is_ok() { + p.unwrap().to_string() + } else { + "Unknown".to_string() + } +}
\ No newline at end of file diff --git a/core/src/service/tcp_network/utils/tokio_utils.rs b/core/src/service/tcp_network/utils/tokio_utils.rs new file mode 100644 index 0000000..efa68c3 --- /dev/null +++ b/core/src/service/tcp_network/utils/tokio_utils.rs @@ -0,0 +1,10 @@ +use tokio::runtime::{Builder, Runtime}; + +pub fn build_tokio_runtime(name: String) -> Runtime { + Builder::new_multi_thread() + .thread_name(name) + .thread_stack_size(32 * 1024 * 1024) + .enable_all() + .build() + .unwrap() +}
\ No newline at end of file diff --git a/documents/临时/About Toolchain - 关于 Rust 工具链.md b/documents/临时/About Toolchain - 关于 Rust 工具链.md deleted file mode 100644 index f3e947b..0000000 --- a/documents/临时/About Toolchain - 关于 Rust 工具链.md +++ /dev/null @@ -1,17 +0,0 @@ -# 关于工具链的使用 - -## Core - -| 平台 | 工具链名称 | -| ------- | ----------------------------- | -| Windows | stable-x86_64-pc-windows-msvc | -| Linux | NONE | -| Mac OS | NONE | - -## Console - -| 平台 | 工具链名称 | -| ------- | ----------------------------- | -| Windows | stable-x86_64-pc-windows-msvc | -| Linux | NONE | -| Mac OS | NONE | diff --git a/documents/临时/路线.md b/documents/临时/路线.md deleted file mode 100644 index 6f4481c..0000000 --- a/documents/临时/路线.md +++ /dev/null @@ -1,4 +0,0 @@ -1. 使用 Bevy 完成客户端图形界面的制作 -2. 完善核心层的事件逻辑处理 -3. 完善Csharp的绑定 -4. ...
\ No newline at end of file diff --git a/export/dev/LICENSE-THIRD-PARTY b/export/dev/LICENSE-THIRD-PARTY index a607e52..eb99fb1 100644 --- a/export/dev/LICENSE-THIRD-PARTY +++ b/export/dev/LICENSE-THIRD-PARTY @@ -6,7 +6,9 @@ This project uses third-party components with the following licenses: [MIT License Dependencies] ----------------------------------------------------------------------- * bincode +* crossterm * tokio +* bevy (original license: Apache-2.0 OR MIT) * chrono (original license: Apache-2.0 OR MIT) * clap (original license: Apache-2.0 OR MIT) * clearscreen (original license: Apache-2.0 OR MIT) @@ -25,10 +27,12 @@ MIT License Copyright (c) 2009-2014 Mozilla Foundation Copyright (c) 2013-2014 The Rust Project Developers. +* bevy - Copyright (c) The Bevy Team. * tokio - Copyright (c) Tokio Contributors. * chrono - Copyright (c) 2014, Kang Seonghoon. * clap - Copyright (c) The clap Project Developer(s). * clearscreen - Copyright (c) The clearscreen Project Developer(s). +* crossterm - Copyright (c) 2019 Timon. * env_logger - Copyright (c) The env_logger Project Developer(s). * hex - Copyright (c) 2015-2020 The rust-hex Developers. * log - Copyright (c) The log Project Developer(s). @@ -60,188 +64,6 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -[Apache-2.0 License Dependencies] ------------------------------------------------------------------------ -* rpassword - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - [BSD-3-Clause License Dependencies] ----------------------------------------------------------------------- * prettytable-rs @@ -647,3 +469,131 @@ Exhibit B - "Incompatible With Secondary Licenses" Notice This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. + + + +[Creative Commons Legal Code Dependencies] +----------------------------------------------------------------------- +* bevy-tokio-tasks + +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work.
\ No newline at end of file diff --git a/export/dev/bin/nogpadc.exe b/export/dev/bin/nogpadc.exe Binary files differdeleted file mode 100644 index 7795720..0000000 --- a/export/dev/bin/nogpadc.exe +++ /dev/null diff --git a/export/dev/bin/nogpads.exe b/export/dev/bin/nogpads.exe Binary files differdeleted file mode 100644 index 314c59d..0000000 --- a/export/dev/bin/nogpads.exe +++ /dev/null diff --git a/export/dev/bridge/nogamepads.h b/export/dev/bridge/nogamepads.h deleted file mode 100644 index f8b58cf..0000000 --- a/export/dev/bridge/nogamepads.h +++ /dev/null @@ -1,249 +0,0 @@ -/* NoGamepads C Bindings. */ - -#include <stdarg.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> - -typedef enum ConnCallbackMsgCTag { - Profile, - Deny, - Fail, - Ok, - Welcome, - Err, -} ConnCallbackMsgCTag; - -typedef enum ConnErrTypeC { - ContainSamePlayer, - PlayerBanned, - Timeout, - GameLocked, - WhatTheHell, -} ConnErrTypeC; - -typedef enum ConnMsgCTag { - Connection, - RequestProfile, - RequestLayoutConfigure, - RequestSkinPackage, - Ready, - Err, -} ConnMsgCTag; - -typedef enum CtrlMsgCTag { - Msg, - Pressed, - Released, - Axis, - Dir, - Exit, - Err, -} CtrlMsgCTag; - -typedef enum GameMsgCTag { - SkinEventTrigger, - DisableKey, - EnableKey, - Leave, - Err, -} GameMsgCTag; - -typedef enum LeaveReasonData { - GameOver, - ServerClosed, - YouAreKicked, - YouAreBanned, -} LeaveReasonData; - -typedef struct GameProfileC { - const char *game_name; - const char *game_description; - const char *organization; - const char *version; - const char *website; - const char *email; -} GameProfileC; - -typedef struct PlayerInfoC { - const char *account_id; - const char *account_hash; - const char *customize_nickname; - int32_t customize_color_hue; - double customize_color_saturation; - double customize_color_value; -} PlayerInfoC; - -typedef struct PadClientC { - const char *target_address; - uint16_t target_port; - struct PlayerInfoC bind_player; - bool enable_console; - bool quiet; -} PadClientC; - -typedef struct KeyData { - uint8_t key; -} KeyData; - -typedef struct AxisData { - uint8_t key; - double ax; -} AxisData; - -typedef struct DirData { - uint8_t key; - double x; - double y; -} DirData; - -typedef struct StrData { - const char *str; -} StrData; - -typedef union CtrlMsgCUnion { - void *nul; - struct KeyData key; - struct AxisData axis; - struct DirData dir; - struct StrData str; -} CtrlMsgCUnion; - -typedef struct ControlMessageC { - enum CtrlMsgCTag tag; - union CtrlMsgCUnion data; -} ControlMessageC; - -typedef union GameMsgCUnion { - void *nul; - struct KeyData key; - enum LeaveReasonData reason; -} GameMsgCUnion; - -typedef struct GameMessageC { - enum GameMsgCTag tag; - union GameMsgCUnion data; -} GameMessageC; - -typedef struct PlayerList { - struct PlayerInfoC *players; - uintptr_t len; - uintptr_t capacity; -} PlayerList; - -typedef union ConnMsgCUnion { - void *nul; - PlayerInfo info; -} ConnMsgCUnion; - -typedef struct ConnectionMessageC { - enum ConnMsgCTag tag; - union ConnMsgCUnion data; -} ConnectionMessageC; - -typedef union ConnCallbackMsgCUnion { - void *nul; - struct GameProfileC profile; - enum ConnErrTypeC conn_err; -} ConnCallbackMsgCUnion; - -typedef struct ConnectionCallbackMessageC { - enum ConnCallbackMsgCTag tag; - union ConnCallbackMsgCUnion data; -} ConnectionCallbackMessageC; - -struct GameProfileC init_game_profile(void); - -struct GameProfileC set_game_profile_name(struct GameProfileC game_profile, const char *value); - -struct GameProfileC set_game_profile_description(struct GameProfileC game_profile, - const char *value); - -struct GameProfileC set_game_profile_organization(struct GameProfileC game_profile, - const char *value); - -struct GameProfileC set_game_profile_version(struct GameProfileC game_profile, const char *value); - -struct GameProfileC set_game_profile_website(struct GameProfileC game_profile, const char *value); - -struct GameProfileC set_game_profile_email(struct GameProfileC game_profile, const char *value); - -struct PlayerInfoC init_player_info(void); - -struct PlayerInfoC set_player_info_account(struct PlayerInfoC info, - const char *id, - const char *password); - -struct PlayerInfoC set_player_info_color(struct PlayerInfoC info, int32_t h, double s, double v); - -struct PlayerInfoC set_player_info_nickname(struct PlayerInfoC info, const char *nickname); - -uint16_t get_default_port(void); - -struct PadClientC init_client(const char *address); - -struct PadClientC init_client_with_port(const char *address, uint16_t port); - -struct PadClientC set_client_quiet(struct PadClientC client); - -struct PadClientC enable_client_console(struct PadClientC client); - -struct PadClientC bind_player_to_client(struct PadClientC client, struct PlayerInfoC info); - -PadClient *complete(struct PadClientC client); - -void connect_client_to_server(PadClient *client); - -void exit_client_from_server(const PadClient *client); - -void put_a_msg_to_server(const PadClient *client, struct ControlMessageC msg); - -struct GameMessageC pop_a_msg_from_server(const PadClient *client); - -struct GameMessageC pop_msg_from_server_or(const PadClient *client, struct GameMessageC or); - -PadServer *init_server(const char *address); - -PadServer *init_server_with_port(const char *address, uint16_t port); - -void set_server_quiet(PadServer *server); - -void enable_server_console(PadServer *server); - -void bind_profile_to_server(PadServer *server, const struct GameProfileC *profile); - -void start_server(PadServer *server); - -void stop_server(PadServer *server); - -void lock_game_on_server(PadServer *server); - -void unlock_game_on_server(PadServer *server); - -bool is_server_game_locked(PadServer *server); - -void put_a_msg_to_player(PadServer *server, - struct GameMessageC msg, - const struct PlayerInfoC *player); - -void put_msg_to_all_players(PadServer *server, struct GameMessageC msg); - -struct ControlMessageC pop_a_msg_from_player(PadServer *server, const struct PlayerInfoC *player); - -struct ControlMessageC pop_msg_from_player_or(PadServer *server, - const struct PlayerInfoC *player, - struct ControlMessageC or); - -bool is_player_online(PadServer *server, const struct PlayerInfoC *player); - -bool is_player_banned(PadServer *server, const struct PlayerInfoC *player); - -void kick_player(PadServer *server, const struct PlayerInfoC *player); - -void ban_player(PadServer *server, const struct PlayerInfoC *player); - -void pardon_player(PadServer *server, const struct PlayerInfoC *player); - -struct PlayerList list_online_players(PadServer *server); - -struct PlayerList list_banned_players(PadServer *server); diff --git a/export/dev/bridge/nogamepads_cpp.h b/export/dev/bridge/nogamepads_cpp.h deleted file mode 100644 index cd31b65..0000000 --- a/export/dev/bridge/nogamepads_cpp.h +++ /dev/null @@ -1,257 +0,0 @@ -/* NoGamepads C++ Bindings. */ - -/* Generated with cbindgen:0.29.0 */ - -#include <cstdarg> -#include <cstdint> -#include <cstdlib> -#include <ostream> -#include <new> - -namespace nogamepads { - -enum class ConnCallbackMsgCTag { - Profile, - Deny, - Fail, - Ok, - Welcome, - Err, -}; - -enum class ConnErrTypeC { - ContainSamePlayer, - PlayerBanned, - Timeout, - GameLocked, - WhatTheHell, -}; - -enum class ConnMsgCTag { - Connection, - RequestProfile, - RequestLayoutConfigure, - RequestSkinPackage, - Ready, - Err, -}; - -enum class CtrlMsgCTag { - Msg, - Pressed, - Released, - Axis, - Dir, - Exit, - Err, -}; - -enum class GameMsgCTag { - SkinEventTrigger, - DisableKey, - EnableKey, - Leave, - Err, -}; - -enum class LeaveReasonData { - GameOver, - ServerClosed, - YouAreKicked, - YouAreBanned, -}; - -template<typename T = void> -struct ManuallyDrop; - -struct GameProfileC { - const char *game_name; - const char *game_description; - const char *organization; - const char *version; - const char *website; - const char *email; -}; - -struct PlayerInfoC { - const char *account_id; - const char *account_hash; - const char *customize_nickname; - int32_t customize_color_hue; - double customize_color_saturation; - double customize_color_value; -}; - -struct PadClientC { - const char *target_address; - uint16_t target_port; - PlayerInfoC bind_player; - bool enable_console; - bool quiet; -}; - -struct KeyData { - uint8_t key; -}; - -struct AxisData { - uint8_t key; - double ax; -}; - -struct DirData { - uint8_t key; - double x; - double y; -}; - -struct StrData { - const char *str; -}; - -union CtrlMsgCUnion { - void *nul; - KeyData key; - AxisData axis; - DirData dir; - StrData str; -}; - -struct ControlMessageC { - CtrlMsgCTag tag; - CtrlMsgCUnion data; -}; - -union GameMsgCUnion { - void *nul; - KeyData key; - LeaveReasonData reason; -}; - -struct GameMessageC { - GameMsgCTag tag; - GameMsgCUnion data; -}; - -struct PlayerList { - PlayerInfoC *players; - uintptr_t len; - uintptr_t capacity; -}; - -union ConnMsgCUnion { - void *nul; - ManuallyDrop<PlayerInfo> info; -}; - -struct ConnectionMessageC { - ConnMsgCTag tag; - ConnMsgCUnion data; -}; - -union ConnCallbackMsgCUnion { - void *nul; - ManuallyDrop<GameProfileC> profile; - ConnErrTypeC conn_err; -}; - -struct ConnectionCallbackMessageC { - ConnCallbackMsgCTag tag; - ConnCallbackMsgCUnion data; -}; - -extern "C" { - -GameProfileC init_game_profile(); - -GameProfileC set_game_profile_name(GameProfileC game_profile, const char *value); - -GameProfileC set_game_profile_description(GameProfileC game_profile, const char *value); - -GameProfileC set_game_profile_organization(GameProfileC game_profile, const char *value); - -GameProfileC set_game_profile_version(GameProfileC game_profile, const char *value); - -GameProfileC set_game_profile_website(GameProfileC game_profile, const char *value); - -GameProfileC set_game_profile_email(GameProfileC game_profile, const char *value); - -PlayerInfoC init_player_info(); - -PlayerInfoC set_player_info_account(PlayerInfoC info, const char *id, const char *password); - -PlayerInfoC set_player_info_color(PlayerInfoC info, int32_t h, double s, double v); - -PlayerInfoC set_player_info_nickname(PlayerInfoC info, const char *nickname); - -uint16_t get_default_port(); - -PadClientC init_client(const char *address); - -PadClientC init_client_with_port(const char *address, uint16_t port); - -PadClientC set_client_quiet(PadClientC client); - -PadClientC enable_client_console(PadClientC client); - -PadClientC bind_player_to_client(PadClientC client, PlayerInfoC info); - -PadClient *complete(PadClientC client); - -void connect_client_to_server(PadClient *client); - -void exit_client_from_server(const PadClient *client); - -void put_a_msg_to_server(const PadClient *client, ControlMessageC msg); - -GameMessageC pop_a_msg_from_server(const PadClient *client); - -GameMessageC pop_msg_from_server_or(const PadClient *client, GameMessageC or); - -PadServer *init_server(const char *address); - -PadServer *init_server_with_port(const char *address, uint16_t port); - -void set_server_quiet(PadServer *server); - -void enable_server_console(PadServer *server); - -void bind_profile_to_server(PadServer *server, const GameProfileC *profile); - -void start_server(PadServer *server); - -void stop_server(PadServer *server); - -void lock_game_on_server(PadServer *server); - -void unlock_game_on_server(PadServer *server); - -bool is_server_game_locked(PadServer *server); - -void put_a_msg_to_player(PadServer *server, GameMessageC msg, const PlayerInfoC *player); - -void put_msg_to_all_players(PadServer *server, GameMessageC msg); - -ControlMessageC pop_a_msg_from_player(PadServer *server, const PlayerInfoC *player); - -ControlMessageC pop_msg_from_player_or(PadServer *server, - const PlayerInfoC *player, - ControlMessageC or); - -bool is_player_online(PadServer *server, const PlayerInfoC *player); - -bool is_player_banned(PadServer *server, const PlayerInfoC *player); - -void kick_player(PadServer *server, const PlayerInfoC *player); - -void ban_player(PadServer *server, const PlayerInfoC *player); - -void pardon_player(PadServer *server, const PlayerInfoC *player); - -PlayerList list_online_players(PadServer *server); - -PlayerList list_banned_players(PadServer *server); - -} // extern "C" - -} // namespace nogamepads diff --git a/export/dev/bridge/nogamepads_lib_c.dll b/export/dev/bridge/nogamepads_lib_c.dll Binary files differdeleted file mode 100644 index 733d0d4..0000000 --- a/export/dev/bridge/nogamepads_lib_c.dll +++ /dev/null @@ -1,3 +1,5 @@ pub mod console_utils; pub mod logger_utils; -pub mod convert_utils;
\ No newline at end of file +pub mod convert_utils; +pub mod macros; +pub mod string_utils;
\ No newline at end of file diff --git a/src/logger_utils.rs b/src/logger_utils.rs index 77b136e..543b706 100644 --- a/src/logger_utils.rs +++ b/src/logger_utils.rs @@ -1,7 +1,7 @@ use env_logger::Builder; -use log::{info, LevelFilter}; +use log::LevelFilter; -pub fn logger_build () { +pub fn logger_build(level: LevelFilter) { Builder::new() .format(|buf, record| { use std::io::Write; @@ -15,8 +15,6 @@ pub fn logger_build () { record.args() ) }) - .filter(None, LevelFilter::Info) + .filter(None, level) .init(); - info!("Logger Built.") -} - +}
\ No newline at end of file diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..a7f9dd4 --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,9 @@ +#[macro_export] +macro_rules! entry_mutex { + ($mutex:expr, |$guard:ident| $code:expr) => { + if let Ok(mut $guard) = $mutex.lock() { + let $guard = &mut $guard; + $code + } + }; +}
\ No newline at end of file diff --git a/src/string_utils.rs b/src/string_utils.rs new file mode 100644 index 0000000..7a02f25 --- /dev/null +++ b/src/string_utils.rs @@ -0,0 +1,16 @@ +pub fn process_id_text(input: String) -> String { + let s = input.trim().to_lowercase(); + let mut result = String::new(); + + for c in s.chars() { + match c { + '\n' | '_' => continue, + '-' | '.' | ',' | ' ' => result.push('_'), + _ => result.push(c), + } + } + + result.chars() + .filter(|&c| c.is_ascii_alphanumeric() || c == '_') + .collect() +}
\ No newline at end of file |
