Skip to content

Commit aa8f6d7

Browse files
committed
platform
1 parent 964395c commit aa8f6d7

8 files changed

Lines changed: 147 additions & 58 deletions

File tree

src-proxy/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ project(selaura_proxy LANGUAGES CXX)
44
add_library(selaura_proxy SHARED
55
main_win.cpp
66
vcruntime.cpp
7+
../src/platform/windows.cpp
78
)
89

910
target_include_directories(selaura_proxy PRIVATE

src-proxy/main_win.cpp

Lines changed: 22 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,52 +6,29 @@
66
#include <iostream>
77
#include <print>
88
#include <thread>
9-
#include <shlobj_core.h>
109

1110
#include <winrt/windows.applicationmodel.h>
1211
#include <winrt/windows.foundation.h>
1312
#include <winrt/windows.storage.h>
1413

1514
#include <runtime.hpp>
1615

17-
std::thread::id mc_thread_id;
18-
HANDLE mc_thread_handle = nullptr;
16+
#include <platform/windows.hpp>
1917

20-
DWORD WINAPI SelauraRuntimeLoaderProc() {
21-
AllocConsole();
18+
std::thread::id mcThreadId;
19+
HANDLE mcThreadHandle = nullptr;
2220

23-
AttachConsole(GetCurrentProcessId());
24-
SetConsoleTitleA("Selaura Runtime Console");
21+
DWORD WINAPI SelauraRuntimeLoaderProc() {
22+
auto platform = std::make_unique<Selaura::WindowsPlatform>(mcThreadHandle);
23+
auto* ctx = new Selaura::RuntimeContext;
24+
ctx->mPlatform = std::move(platform);
2525

26-
FILE* fp;
27-
freopen_s(&fp, "CONOUT$", "w", stdout);
28-
freopen_s(&fp, "CONOUT$", "w", stderr);
29-
freopen_s(&fp, "CONIN$", "r", stdin);
26+
ctx->mPlatform->InitConsole();
3027

31-
std::println("[Selaura Runtime Loader] Thread ID: {}, Thread Handle: {}", mc_thread_id, mc_thread_handle);
28+
std::println("[Selaura Runtime Loader] Thread ID: {}, Thread Handle: {}", mcThreadId, mcThreadHandle);
3229
std::println("[Selaura Runtime Loader] Press Numpad1 to End");
3330

34-
PWSTR appDataPath = nullptr;
35-
if (FAILED(SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, &appDataPath))) {
36-
throw std::runtime_error("Failed to get AppData path");
37-
}
38-
39-
std::filesystem::path folder = appDataPath;
40-
CoTaskMemFree(appDataPath);
41-
42-
folder /= R"(Minecraft Bedrock\Users\Shared\games\com.mojang\Selaura)";
43-
44-
45-
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
46-
if (hOut != INVALID_HANDLE_VALUE) {
47-
DWORD mode = 0;
48-
if (GetConsoleMode(hOut, &mode)) {
49-
SetConsoleMode(hOut, mode | 0x0004);
50-
}
51-
}
52-
53-
54-
auto* ctx = new Selaura::RuntimeContext;
31+
auto folder = ctx->mPlatform->GetSelauraFolder();
5532

5633
const auto runtime_path = folder / "selaura_runtime.dll";
5734
if (!std::filesystem::exists(runtime_path)) {
@@ -106,9 +83,9 @@ DWORD WINAPI SelauraRuntimeLoaderProc() {
10683
}
10784
};
10885

109-
SuspendThread(mc_thread_handle);
86+
SuspendThread(mcThreadHandle);
11087

111-
ctx->thread_id = mc_thread_id;
88+
ctx->mThreadId = mcThreadId;
11289

11390
DWORD handle = 0;
11491
wchar_t path[MAX_PATH];
@@ -121,10 +98,10 @@ DWORD WINAPI SelauraRuntimeLoaderProc() {
12198
VS_FIXEDFILEINFO* file_info = nullptr;
12299
UINT len = 0;
123100
if (VerQueryValueW(buffer.data(), L"\\", reinterpret_cast<LPVOID*>(&file_info), &len) && file_info) {
124-
ctx->version_major = HIWORD(file_info->dwFileVersionMS);
125-
ctx->version_minor = LOWORD(file_info->dwFileVersionMS);
126-
ctx->version_build = HIWORD(file_info->dwFileVersionLS);
127-
ctx->version_revision = LOWORD(file_info->dwFileVersionLS);
101+
ctx->mVersionMajor = HIWORD(file_info->dwFileVersionMS);
102+
ctx->mVersionMinor = LOWORD(file_info->dwFileVersionMS);
103+
ctx->mVersionBuild = HIWORD(file_info->dwFileVersionLS);
104+
ctx->mVersionRevision = LOWORD(file_info->dwFileVersionLS);
128105
}
129106
}
130107
}
@@ -134,7 +111,7 @@ DWORD WINAPI SelauraRuntimeLoaderProc() {
134111
auto runtime_init = reinterpret_cast<runtime_init_fn>(GetProcAddress(mod, "SelauraRuntimeInit"));
135112
runtime_init(ctx, load_mods);
136113

137-
ResumeThread(mc_thread_handle);
114+
ResumeThread(mcThreadHandle);
138115
}
139116

140117
HWND hwnd = nullptr;
@@ -196,9 +173,9 @@ DWORD WINAPI SelauraRuntimeLoaderProc() {
196173
(void)DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &value_true, sizeof(value_true));
197174

198175
std::string title = std::format("Selaura Runtime ({}.{}.{}/{}-{})",
199-
ctx->version_major,
200-
ctx->version_minor,
201-
ctx->version_build,
176+
ctx->mVersionMajor,
177+
ctx->mVersionMinor,
178+
ctx->mVersionBuild,
202179
RUNTIME_VERSION,
203180
GIT_BRANCH
204181
);
@@ -218,7 +195,6 @@ DWORD WINAPI SelauraRuntimeLoaderProc() {
218195
if (GetAsyncKeyState(VK_NUMPAD1)) break;
219196
}
220197

221-
fclose(fp);
222198
FreeConsole();
223199

224200
ExitProcess(0);
@@ -229,8 +205,8 @@ DWORD WINAPI SelauraRuntimeLoaderProc() {
229205
BOOL APIENTRY DllMain(HINSTANCE, DWORD fdwReason, LPVOID) {
230206
if (fdwReason == DLL_PROCESS_ATTACH) {
231207
proxy::init_runtime();
232-
mc_thread_id = std::this_thread::get_id();
233-
mc_thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId());
208+
mcThreadId = std::this_thread::get_id();
209+
mcThreadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId());
234210

235211
CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)SelauraRuntimeLoaderProc, nullptr, 0, nullptr);
236212
}

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ project(selaura_runtime LANGUAGES CXX)
33

44
add_library(selaura_runtime SHARED
55
main.cpp
6+
platform/windows.cpp
67
runtime.cpp
78
hooks/hooks.cpp
89
)

src/context.hpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <api/mc/world/Minecraft.hpp>
55
#include <api/mc/client/ClientInstance.hpp>
6+
#include <platform/platform.hpp>
67

78
namespace Selaura {
89
struct SharedContext {
@@ -16,13 +17,14 @@ namespace Selaura {
1617
struct ServerContext : SharedContext {};
1718

1819
struct RuntimeContext {
19-
std::thread::id thread_id;
20-
int version_major;
21-
int version_minor;
22-
int version_build;
23-
int version_revision;
20+
std::thread::id mThreadId;
21+
int mVersionMajor;
22+
int mVersionMinor;
23+
int mVersionBuild;
24+
int mVersionRevision;
2425

25-
ClientContext* client_ctx;
26-
ServerContext* server_ctx;
26+
ClientContext* mClientCtx;
27+
ServerContext* mServerCtx;
28+
std::unique_ptr<Platform> mPlatform;
2729
};
2830
};

src/platform/platform.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
#include <filesystem>
3+
#include <span>
4+
5+
namespace Selaura {
6+
enum class PlatformType : int {
7+
Windows = 0
8+
};
9+
10+
struct Platform {
11+
virtual ~Platform() = default;
12+
virtual PlatformType GetPlatformType() const = 0;
13+
14+
virtual void PauseGameThread() const = 0;
15+
virtual void ResumeGameThread() const = 0;
16+
17+
virtual std::filesystem::path GetSelauraFolder() const = 0;
18+
19+
virtual void InitConsole() const = 0;
20+
21+
virtual std::span<std::byte> GetMinecraftModule() const = 0;
22+
};
23+
};

src/platform/windows.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#include "windows.hpp"
2+
3+
namespace Selaura {
4+
WindowsPlatform::WindowsPlatform(HANDLE mcThreadHandle) {
5+
this->mcThreadHandle = mcThreadHandle;
6+
}
7+
8+
PlatformType WindowsPlatform::GetPlatformType() const {
9+
return PlatformType::Windows;
10+
}
11+
12+
void WindowsPlatform::PauseGameThread() const {
13+
SuspendThread(this->mcThreadHandle);
14+
}
15+
16+
void WindowsPlatform::ResumeGameThread() const {
17+
ResumeThread(this->mcThreadHandle);
18+
}
19+
20+
std::filesystem::path WindowsPlatform::GetSelauraFolder() const {
21+
PWSTR appDataPath = nullptr;
22+
if (FAILED(SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, &appDataPath))) {
23+
throw std::runtime_error("Failed to get AppData path");
24+
}
25+
26+
std::filesystem::path folder = appDataPath;
27+
CoTaskMemFree(appDataPath);
28+
29+
folder /= R"(Minecraft Bedrock\Users\Shared\games\com.mojang\Selaura)";
30+
31+
return folder;
32+
}
33+
34+
void WindowsPlatform::InitConsole() const {
35+
AllocConsole();
36+
37+
AttachConsole(GetCurrentProcessId());
38+
SetConsoleTitleA("Selaura Runtime Console");
39+
40+
FILE* fp;
41+
freopen_s(&fp, "CONOUT$", "w", stdout);
42+
freopen_s(&fp, "CONOUT$", "w", stderr);
43+
freopen_s(&fp, "CONIN$", "r", stdin);
44+
45+
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
46+
if (hOut != INVALID_HANDLE_VALUE) {
47+
DWORD mode = 0;
48+
if (GetConsoleMode(hOut, &mode)) {
49+
SetConsoleMode(hOut, mode | 0x0004);
50+
}
51+
}
52+
}
53+
54+
std::span<std::byte> WindowsPlatform::GetMinecraftModule() const {
55+
const HMODULE handle = GetModuleHandleA("Minecraft.Windows.exe");
56+
if (!handle) return {};
57+
58+
MODULEINFO moduleInfo;
59+
if (!GetModuleInformation(GetCurrentProcess(), handle, &moduleInfo, sizeof(moduleInfo))) return {};
60+
return std::span<std::byte>{static_cast<std::byte*>(moduleInfo.lpBaseOfDll), moduleInfo.SizeOfImage};
61+
}
62+
};

src/platform/windows.hpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
3+
#ifdef WIN32
4+
#include <Windows.h>
5+
#include <Psapi.h>
6+
#include <shlobj_core.h>
7+
8+
#include "platform.hpp"
9+
10+
namespace Selaura {
11+
struct WindowsPlatform : public Platform {
12+
explicit WindowsPlatform(HANDLE mcThreadHandle);
13+
14+
[[nodiscard]] PlatformType GetPlatformType() const override;
15+
void PauseGameThread() const override;
16+
void ResumeGameThread() const override;
17+
[[nodiscard]] std::filesystem::path GetSelauraFolder() const override;
18+
void InitConsole() const override;
19+
[[nodiscard]] std::span<std::byte> GetMinecraftModule() const override;
20+
private:
21+
HANDLE mcThreadHandle;
22+
};
23+
};
24+
#endif

src/runtime.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ namespace Selaura {
88
Runtime::Runtime(const RuntimeContext& ctx) {
99
std::println("[Selaura Runtime] Created runtime.");
1010
std::println("[Selaura Runtime] Running on Minecraft Version: {}.{}.{}.{}",
11-
ctx.version_major,
12-
ctx.version_minor,
13-
ctx.version_build,
14-
ctx.version_revision);
11+
ctx.mVersionMajor,
12+
ctx.mVersionMinor,
13+
ctx.mVersionBuild,
14+
ctx.mVersionRevision);
1515

16-
this->mThreadId = ctx.thread_id;
16+
this->mThreadId = ctx.mThreadId;
1717

1818
this->mClientCtx = std::make_unique<ClientContext>();
1919
this->mServerCtx = std::make_unique<ServerContext>();

0 commit comments

Comments
 (0)