build: test format #1
							
								
								
									
										33
									
								
								.gitea/workflows/check-formatting.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								.gitea/workflows/check-formatting.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | name: check-formatting | ||||||
|  |  | ||||||
|  | on: | ||||||
|  |   push: | ||||||
|  |     branches: | ||||||
|  |       - "*" | ||||||
|  |   pull_request: | ||||||
|  |     branches: | ||||||
|  |       - "*" | ||||||
|  |     types: [opened, synchronize, reopened] | ||||||
|  |  | ||||||
|  | jobs: | ||||||
|  |   check-formatting: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - name: Checkout repository | ||||||
|  |         uses: actions/checkout@v4 | ||||||
|  |  | ||||||
|  |       - name: Install LLVM | ||||||
|  |         uses: KyleMayes/install-llvm-action@v2.0.5 | ||||||
|  |         with: | ||||||
|  |           version: "17.0" | ||||||
|  |  | ||||||
|  |       - name: Install dependencies (x64) | ||||||
|  |         run: | | ||||||
|  |           apt-get update | ||||||
|  |           apt-get install libtinfo5 -y | ||||||
|  |  | ||||||
|  |       - name: Test formatting for all files | ||||||
|  |         working-directory: ${{ github.workspace }} | ||||||
|  |         run: | | ||||||
|  |           export CLANG_FORMAT_BIN="${LLVM_PATH}/bin/clang-format" | ||||||
|  |           ./scripts/check-format.sh | ||||||
							
								
								
									
										8
									
								
								scripts/check-format.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										8
									
								
								scripts/check-format.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | #!/bin/bash | ||||||
|  |  | ||||||
|  | # Go to repository root | ||||||
|  | cd "$(dirname "$0")/.." || exit 2 | ||||||
|  |  | ||||||
|  | CLANG_FORMAT_BIN="${CLANG_FORMAT_BIN:-clang-format}" | ||||||
|  |  | ||||||
|  | find ./src -iname '*.hpp' -o -iname '*.cpp' | xargs $CLANG_FORMAT_BIN -Werror -ferror-limit=1 --dry-run | ||||||
| @@ -12,8 +12,19 @@ | |||||||
|  |  | ||||||
| #include "scheduler.hpp" | #include "scheduler.hpp" | ||||||
|  |  | ||||||
|  | #include <xorstr.hpp> | ||||||
|  |  | ||||||
| namespace { | namespace { | ||||||
| utils::binary_resource runner_file(RUNNER, "iw4sp-runner.exe"); | enum class ownership_state { | ||||||
|  |   success, | ||||||
|  |   unowned, | ||||||
|  |   nosteam, | ||||||
|  |   error, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | ownership_state state_; | ||||||
|  |  | ||||||
|  | utils::binary_resource runner_file(RUNNER, xorstr_("iw4sp-runner.exe")); | ||||||
| } // namespace | } // namespace | ||||||
|  |  | ||||||
| class steam_proxy final : public component_interface { | class steam_proxy final : public component_interface { | ||||||
| @@ -23,22 +34,35 @@ public: | |||||||
|     this->clean_up_on_error(); |     this->clean_up_on_error(); | ||||||
|  |  | ||||||
|     try { |     try { | ||||||
|       this->start_mod("iw4x-sp singleplayer", 10180); |       state_ = this->start_mod(xorstr_("iw4x-sp singleplayer"), 10180); | ||||||
|     } catch (const std::exception& ex) { |     } catch (const std::exception& ex) { | ||||||
|       printf("Steam: %s\n", ex.what()); |       state_ = ownership_state::error; | ||||||
|  |       printf(xorstr_("Steam: %s\n"), ex.what()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | #ifdef STEAM_OWNERSHIP_CHECK | ||||||
|  |     if (utils::nt::is_wine()) { | ||||||
|  |       state_ = ownership_state::success; | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef STEAM_OWNERSHIP_CHECK | ||||||
|  |     evaluate_ownership_state(state_); | ||||||
|  | #endif | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void pre_destroy() override { |   void pre_destroy() override { | ||||||
|     if (this->steam_client_module_) { |     if (this->steam_client_module_) { | ||||||
|       if (this->steam_pipe_) { |       if (this->steam_pipe_) { | ||||||
|         if (this->global_user_) { |         if (this->global_user_) { | ||||||
|           this->steam_client_module_.invoke<void>( |           this->steam_client_module_.invoke<void>(xorstr_("Steam_ReleaseUser"), | ||||||
|               "Steam_ReleaseUser", this->steam_pipe_, this->global_user_); |                                                   this->steam_pipe_, | ||||||
|  |                                                   this->global_user_); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         this->steam_client_module_.invoke<bool>("Steam_BReleaseSteamPipe", |         this->steam_client_module_.invoke<bool>( | ||||||
|                                                 this->steam_pipe_); |             xorstr_("Steam_BReleaseSteamPipe"), this->steam_pipe_); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -59,10 +83,10 @@ private: | |||||||
|  |  | ||||||
|     for (auto i = 1; i < 1000; ++i) { |     for (auto i = 1; i < 1000; ++i) { | ||||||
|       const auto* name = |       const auto* name = | ||||||
|           utils::string::va("CLIENTENGINE_INTERFACE_VERSION{0:03}", i); |           utils::string::va(xorstr_("CLIENTENGINE_INTERFACE_VERSION{0:03}"), i); | ||||||
|  |  | ||||||
|       auto* const client_engine = this->steam_client_module_.invoke<void*>( |       auto* const client_engine = this->steam_client_module_.invoke<void*>( | ||||||
|           "CreateInterface", name, nullptr); |           xorstr_("CreateInterface"), name, nullptr); | ||||||
|       if (client_engine) |       if (client_engine) | ||||||
|         return client_engine; |         return client_engine; | ||||||
|     } |     } | ||||||
| @@ -75,10 +99,10 @@ private: | |||||||
|     if (steam_path.empty()) |     if (steam_path.empty()) | ||||||
|       return; |       return; | ||||||
|  |  | ||||||
|     utils::nt::library::load(steam_path / "tier0_s.dll"); |     utils::nt::library::load(steam_path / xorstr_("tier0_s.dll")); | ||||||
|     utils::nt::library::load(steam_path / "vstdlib_s.dll"); |     utils::nt::library::load(steam_path / xorstr_("vstdlib_s.dll")); | ||||||
|     this->steam_client_module_ = |     this->steam_client_module_ = | ||||||
|         utils::nt::library::load(steam_path / "steamclient.dll"); |         utils::nt::library::load(steam_path / xorstr_("steamclient.dll")); | ||||||
|     if (!this->steam_client_module_) |     if (!this->steam_client_module_) | ||||||
|       return; |       return; | ||||||
|  |  | ||||||
| @@ -86,52 +110,62 @@ private: | |||||||
|     if (!this->client_engine_) |     if (!this->client_engine_) | ||||||
|       return; |       return; | ||||||
|  |  | ||||||
|     this->steam_pipe_ = |     this->steam_pipe_ = this->steam_client_module_.invoke<void*>( | ||||||
|         this->steam_client_module_.invoke<void*>("Steam_CreateSteamPipe"); |         xorstr_("Steam_CreateSteamPipe")); | ||||||
|     this->global_user_ = this->steam_client_module_.invoke<void*>( |     this->global_user_ = this->steam_client_module_.invoke<void*>( | ||||||
|         "Steam_ConnectToGlobalUser", this->steam_pipe_); |         xorstr_("Steam_ConnectToGlobalUser"), this->steam_pipe_); | ||||||
|     this->client_user_ = this->client_engine_.invoke<void*>( |     this->client_user_ = this->client_engine_.invoke<void*>( | ||||||
|         8, this->steam_pipe_, this->global_user_); // GetIClientUser |         8, this->steam_pipe_, this->global_user_); // GetIClientUser | ||||||
|     this->client_utils_ = this->client_engine_.invoke<void*>( |     this->client_utils_ = this->client_engine_.invoke<void*>( | ||||||
|         14, this->steam_pipe_); // GetIClientUtils |         14, this->steam_pipe_); // GetIClientUtils | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void start_mod(const std::string& title, const std::size_t app_id) { |   ownership_state start_mod(const std::string& title, | ||||||
|  |                             const std::size_t app_id) { | ||||||
|     __try { |     __try { | ||||||
|       this->start_mod_unsafe(title, app_id); |       return this->start_mod_unsafe(title, app_id); | ||||||
|     } __except (EXCEPTION_EXECUTE_HANDLER) { |     } __except (EXCEPTION_EXECUTE_HANDLER) { | ||||||
|       this->do_cleanup(); |       this->do_cleanup(); | ||||||
|  |       return ownership_state::error; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void start_mod_unsafe(const std::string& title, std::size_t app_id) { |   ownership_state start_mod_unsafe(const std::string& title, | ||||||
|  |                                    std::size_t app_id) { | ||||||
|     if (!this->client_utils_ || !this->client_user_) |     if (!this->client_utils_ || !this->client_user_) | ||||||
|       return; |       return ownership_state::nosteam; | ||||||
|  |  | ||||||
|     if (!this->client_user_.invoke<bool>("BIsSubscribedApp", app_id)) { |     if (!this->client_user_.invoke<bool>(xorstr_("BIsSubscribedApp"), app_id)) { | ||||||
|  | #ifdef _DEBUG | ||||||
|       app_id = 480; // Spacewar |       app_id = 480; // Spacewar | ||||||
|  | #else | ||||||
|  |       return ownership_state::unowned; | ||||||
|  | #endif | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     this->client_utils_.invoke<void>("SetAppIDForCurrentPipe", app_id, false); |     this->client_utils_.invoke<void>(xorstr_("SetAppIDForCurrentPipe"), app_id, | ||||||
|  |                                      false); | ||||||
|  |  | ||||||
|     char our_directory[MAX_PATH]{}; |     char our_directory[MAX_PATH]{}; | ||||||
|     GetCurrentDirectoryA(sizeof(our_directory), our_directory); |     GetCurrentDirectoryA(sizeof(our_directory), our_directory); | ||||||
|  |  | ||||||
|     const auto path = runner_file.get_extracted_file(); |     const auto path = runner_file.get_extracted_file(); | ||||||
|     const auto* cmd_line = |     const auto* cmd_line = utils::string::va(xorstr_("\"{0}\" -proc {1}"), path, | ||||||
|         utils::string::va("\"{0}\" -proc {1}", path, GetCurrentProcessId()); |                                              GetCurrentProcessId()); | ||||||
|  |  | ||||||
|     game_id game_id; |     game_id game_id; | ||||||
|     game_id.raw.type = 1; // k_EGameIDTypeGameMod |     game_id.raw.type = 1; // k_EGameIDTypeGameMod | ||||||
|     game_id.raw.app_id = app_id & 0xFFFFFF; |     game_id.raw.app_id = app_id & 0xFFFFFF; | ||||||
|  |  | ||||||
|     const auto* mod_id = "IW4"; |     const auto* mod_id = "IW4x-SP"; | ||||||
|     game_id.raw.mod_id = |     game_id.raw.mod_id = | ||||||
|         *reinterpret_cast<const unsigned int*>(mod_id) | 0x80000000; |         *reinterpret_cast<const unsigned int*>(mod_id) | 0x80000000; | ||||||
|  |  | ||||||
|     this->client_user_.invoke<bool>("SpawnProcess", path.data(), cmd_line, |     this->client_user_.invoke<bool>(xorstr_("SpawnProcess"), path.c_str(), | ||||||
|                                     our_directory, game_id.bits, title.data(), |                                     cmd_line, our_directory, game_id.bits, | ||||||
|                                     app_id, 0, 0, 0); |                                     title.c_str(), app_id, 0, 0, 0); | ||||||
|  |  | ||||||
|  |     return ownership_state::success; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void do_cleanup() { |   void do_cleanup() { | ||||||
| @@ -151,9 +185,11 @@ private: | |||||||
|           if (this->steam_client_module_ && this->steam_pipe_ && |           if (this->steam_client_module_ && this->steam_pipe_ && | ||||||
|               this->global_user_ && |               this->global_user_ && | ||||||
|               this->steam_client_module_.invoke<bool>( |               this->steam_client_module_.invoke<bool>( | ||||||
|                   "Steam_BConnected", this->global_user_, this->steam_pipe_) && |                   xorstr_("Steam_BConnected"), this->global_user_, | ||||||
|  |                   this->steam_pipe_) && | ||||||
|               this->steam_client_module_.invoke<bool>( |               this->steam_client_module_.invoke<bool>( | ||||||
|                   "Steam_BLoggedOn", this->global_user_, this->steam_pipe_)) { |                   xorstr_("Steam_BLoggedOn"), this->global_user_, | ||||||
|  |                   this->steam_pipe_)) { | ||||||
|             return scheduler::cond_continue; |             return scheduler::cond_continue; | ||||||
|           } |           } | ||||||
|  |  | ||||||
| @@ -162,6 +198,24 @@ private: | |||||||
|         }, |         }, | ||||||
|         scheduler::pipeline::async); |         scheduler::pipeline::async); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | #ifdef STEAM_OWNERSHIP_CHECK | ||||||
|  |   void evaluate_ownership_state(const ownership_state state) { | ||||||
|  |     switch (state) { | ||||||
|  |     case ownership_state::nosteam: | ||||||
|  |       throw std::runtime_error( | ||||||
|  |           xorstr_("Steam must be running to play this game!")); | ||||||
|  |     case ownership_state::unowned: | ||||||
|  |       throw std::runtime_error( | ||||||
|  |           xorstr_("You must own the game on Steam to play this mod!")); | ||||||
|  |     case ownership_state::error: | ||||||
|  |       throw std::runtime_error( | ||||||
|  |           xorstr_("Failed to verify ownership of the game!")); | ||||||
|  |     case ownership_state::success: | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
| REGISTER_COMPONENT(steam_proxy) | REGISTER_COMPONENT(steam_proxy) | ||||||
|   | |||||||
| @@ -1,5 +1,7 @@ | |||||||
| #include "nt.hpp" | #include "nt.hpp" | ||||||
|  |  | ||||||
|  | #include <xorstr.hpp> | ||||||
|  |  | ||||||
| namespace utils::nt { | namespace utils::nt { | ||||||
| library library::load(const std::string& name) { | library library::load(const std::string& name) { | ||||||
|   return library(LoadLibraryA(name.c_str())); |   return library(LoadLibraryA(name.c_str())); | ||||||
| @@ -206,8 +208,8 @@ std::string library::get_dll_directory() { | |||||||
|  |  | ||||||
| bool is_wine() { | bool is_wine() { | ||||||
|   static const auto has_wine_export = []() -> bool { |   static const auto has_wine_export = []() -> bool { | ||||||
|     const library ntdll("ntdll.dll"); |     const library ntdll(xorstr_("ntdll.dll")); | ||||||
|     return ntdll.get_proc<void*>("wine_get_version"); |     return ntdll.get_proc<void*>(xorstr_("wine_get_version")); | ||||||
|   }(); |   }(); | ||||||
|  |  | ||||||
|   return has_wine_export; |   return has_wine_export; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user