Skip to content

Commit 4738b06

Browse files
committed
selaura proxy
1 parent 9776360 commit 4738b06

12 files changed

Lines changed: 180 additions & 119 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ add_compile_definitions(
4949
5050
add_subdirectory(include)
5151
add_subdirectory(src)
52+
add_subdirectory(src-proxy)
5253
add_subdirectory(test)
5354
5455
if (MSVC)

src-proxy/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
cmake_minimum_required(VERSION 3.28)
2+
project(selaura_proxy LANGUAGES CXX)
3+
4+
add_library(selaura_proxy SHARED
5+
main_win_uwp.cpp
6+
)
7+
8+
target_include_directories(selaura_proxy PRIVATE
9+
${CMAKE_SOURCE_DIR}/src
10+
)
11+
12+
target_link_libraries(selaura_proxy PRIVATE
13+
runtimeobject.lib
14+
)

src-proxy/main_win_uwp.cpp

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#include "main_win_uwp.hpp"
2+
3+
#include <filesystem>
4+
#include <functional>
5+
#include <print>
6+
#include <thread>
7+
8+
#include <winrt/windows.applicationmodel.h>
9+
#include <winrt/windows.foundation.h>
10+
#include <winrt/windows.storage.h>
11+
12+
#include <runtime.hpp>
13+
14+
std::thread::id mc_thread_id;
15+
HANDLE mc_thread_handle = nullptr;
16+
17+
DWORD WINAPI SelauraRuntimeLoaderProc() {
18+
AllocConsole();
19+
20+
AttachConsole(GetCurrentProcessId());
21+
SetConsoleTitleA("Selaura Client Console");
22+
23+
FILE* fp;
24+
freopen_s(&fp, "CONOUT$", "w", stdout);
25+
freopen_s(&fp, "CONOUT$", "w", stderr);
26+
freopen_s(&fp, "CONIN$", "r", stdin);
27+
28+
std::println("[Selaura Runtime Loader] Thread ID: {}, Thread Handle: {}", mc_thread_id, mc_thread_handle);
29+
std::println("[Selaura Runtime Loader] Press Numpad1 to End");
30+
31+
auto winrt_folder = winrt::Windows::Storage::ApplicationData::Current().RoamingFolder();
32+
auto folder = std::filesystem::path(winrt::to_string(winrt_folder.Path())) / "Selaura";
33+
34+
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
35+
if (hOut != INVALID_HANDLE_VALUE) {
36+
DWORD mode = 0;
37+
if (GetConsoleMode(hOut, &mode)) {
38+
SetConsoleMode(hOut, mode | 0x0004);
39+
}
40+
}
41+
42+
const auto runtime_path = folder / "selaura_runtime.dll";
43+
if (!std::filesystem::exists(runtime_path)) {
44+
std::println("\x1b[91m[Selaura Runtime Loader] ERROR: '{}' not found. The runtime is required.\x1b[0m",
45+
runtime_path.string());
46+
} else {
47+
std::function<void(selaura::runtime*)> load_mods = [=](selaura::runtime* rt) {
48+
// To load mods we need LoadLibrary, and other Windows-specific
49+
// functions, and this will be called in the runtime. However,
50+
// due to the goal of cross-platform, the function must be
51+
// created here, and then further passed to the runtime as an
52+
// argument in the Init function.
53+
std::filesystem::path mods_folder = folder/ "mods";
54+
55+
if (!std::filesystem::exists(mods_folder)) {
56+
std::filesystem::create_directory(mods_folder);
57+
return;
58+
}
59+
60+
int plugins_loaded = 0;
61+
62+
using init_fn = void(*)(selaura::runtime*);
63+
std::vector<init_fn> init_fn_list = {};
64+
65+
for (const auto& entry : std::filesystem::directory_iterator(mods_folder)) {
66+
if (!entry.is_regular_file()) continue;
67+
const auto& path = entry.path();
68+
if (path.extension() == ".dll") {
69+
HMODULE mod = LoadLibraryExW(entry.path().c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES);
70+
if (mod) {
71+
FreeLibrary(mod);
72+
mod = LoadLibraryW(entry.path().c_str());
73+
}
74+
75+
auto init = reinterpret_cast<init_fn>(GetProcAddress(mod, "SelauraPluginInit"));
76+
init_fn_list.push_back(init);
77+
78+
if (mod) {
79+
plugins_loaded++;
80+
std::println("[Selaura Plugin Loader] Loaded: {}", path.filename().string());
81+
} else {
82+
std::println("[Selaura Plugin Loader] Failed to load: {} (Error {})",
83+
path.filename().string(), GetLastError());
84+
}
85+
}
86+
}
87+
88+
std::println("[Selaura Plugin Loader] Loaded {} plugin(s).", plugins_loaded);
89+
90+
for (auto fn : init_fn_list) {
91+
fn(rt);
92+
}
93+
};
94+
95+
SuspendThread(mc_thread_handle);
96+
97+
auto* ctx = new selaura::runtime_context;
98+
ctx->thread_id = mc_thread_id;
99+
100+
const winrt::Windows::ApplicationModel::Package pkg = winrt::Windows::ApplicationModel::Package::Current();
101+
ctx->version_major = pkg.Id().Version().Major;
102+
ctx->version_minor = pkg.Id().Version().Minor;
103+
ctx->version_build = pkg.Id().Version().Build;
104+
ctx->version_revision = pkg.Id().Version().Revision;
105+
106+
HMODULE mod = LoadLibraryExW((folder / "selaura_runtime.dll").c_str(), nullptr, 0);
107+
using runtime_init_fn = void(*)(selaura::runtime_context*, std::function<void(selaura::runtime*)>);
108+
auto runtime_init = reinterpret_cast<runtime_init_fn>(GetProcAddress(mod, "SelauraRuntimeInit"));
109+
runtime_init(ctx, load_mods);
110+
111+
ResumeThread(mc_thread_handle);
112+
}
113+
114+
while (true) {
115+
Sleep(10);
116+
if (GetAsyncKeyState(VK_NUMPAD1)) break;
117+
}
118+
119+
fclose(fp);
120+
FreeConsole();
121+
122+
ExitProcess(0);
123+
124+
return 0;
125+
}
126+
127+
BOOL APIENTRY DllMain(HINSTANCE, DWORD fdwReason, LPVOID) {
128+
// This DLL is the Selaura Runtime Loader, which is injected
129+
// immediately as the game loads by replacing the dxgi.dll.
130+
// This is why in the headers it exports the necessary
131+
// functions used in that library, so it can be loaded as it
132+
// is essential to the game's startup.
133+
134+
if (fdwReason == DLL_PROCESS_ATTACH) {
135+
mc_thread_id = std::this_thread::get_id();
136+
mc_thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId());
137+
138+
CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)SelauraRuntimeLoaderProc, nullptr, 0, nullptr);
139+
}
140+
141+
return TRUE;
142+
}
Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
#pragma once
22
#include <Windows.h>
33

4-
// this is because selaura_client.dll is embedded into minecraft as dxgi.dll
5-
// therefore, it needs to still have the necessary inside of dxgi
6-
// or the game will not open.
74
#pragma comment(linker, "/export:ApplyCompatResolutionQuirking=c:\\windows\\system32\\dxgi.ApplyCompatResolutionQuirking,@1")
85
#pragma comment(linker, "/export:CompatString=c:\\windows\\system32\\dxgi.CompatString,@2")
96
#pragma comment(linker, "/export:CompatValue=c:\\windows\\system32\\dxgi.CompatValue,@3")
@@ -24,4 +21,4 @@
2421
#pragma comment(linker, "/export:SetAppCompatStringPointer=c:\\windows\\system32\\dxgi.SetAppCompatStringPointer,@8")
2522
#pragma comment(linker, "/export:UpdateHMDEmulationStatus=c:\\windows\\system32\\dxgi.UpdateHMDEmulationStatus,@9")
2623

27-
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID);
24+
BOOL APIENTRY DllMain(HINSTANCE, DWORD fdwReason, LPVOID);

src/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.28)
22
project(selaura_client LANGUAGES CXX)
33

44
add_library(selaura_client SHARED
5-
loader/main_win.cpp
6-
loader/runtime.cpp
5+
main.cpp
6+
runtime.cpp
77
hooks/hooks.cpp
88
)
99

File renamed without changes.

src/hooks/hooks.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include <libhat/scanner.hpp>
44
#include <print>
55

6-
#include <loader/runtime.hpp>
6+
#include <../runtime.hpp>
77

88

99
#include <api/mc/world/Minecraft.hpp>

src/loader/main_win.cpp

Lines changed: 0 additions & 111 deletions
This file was deleted.

src/main.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifdef _WIN32
2+
#include <Windows.h>
3+
4+
BOOL APIENTRY DllMain(HINSTANCE, DWORD, LPVOID) {
5+
return TRUE;
6+
}
7+
#endif
8+
9+
#include <api/imports.hpp>
10+
#include <print>
11+
#include "runtime.hpp"
12+
13+
SELAURA_API void SelauraRuntimeInit(selaura::runtime_context* ctx, std::function<void(selaura::runtime*)> load_mods) {
14+
selaura::runtime_instance = std::make_unique<selaura::runtime>(*ctx);
15+
selaura::runtime_instance->start();
16+
17+
load_mods(selaura::runtime_instance.get());
18+
}
File renamed without changes.

0 commit comments

Comments
 (0)