Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8830d1abdb | |||
| 71fe1c6549 | |||
| e70323c86b | |||
| 9f5abefb34 | |||
| f6ac12962d | |||
| 6d176c2020 | |||
| 83c1fba265 | |||
| e46a60f95f | |||
| 6c086b5307 | |||
| 064f1701ee | |||
| df9ad4fc70 | |||
| c0b710d6f7 | |||
| e27fb6d73a | |||
| e95308605b | |||
| 205ee06c27 | |||
| d390304577 | |||
| 037260acd5 | |||
| f30a76fe18 | |||
| 579e0d1352 | |||
| 26a4406c88 | |||
| 385cfe147d | |||
| 98be88b346 | |||
| bf83ae571d | |||
| c1bc1023eb |
@@ -15,7 +15,7 @@ jobs:
|
|||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: |
|
run: |
|
||||||
pacman -Syu --noconfirm
|
pacman -Syu --noconfirm
|
||||||
pacman -S --noconfirm nodejs mingw-w64-gcc cmake ninja ccache zip git base-devel
|
pacman -S --noconfirm nodejs mingw-w64-gcc cmake ninja ccache git base-devel
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
@@ -56,7 +56,7 @@ jobs:
|
|||||||
} >> $GITHUB_OUTPUT
|
} >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Cache FetchContent & ccache
|
- name: Cache FetchContent & ccache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
build/_deps
|
build/_deps
|
||||||
@@ -74,6 +74,7 @@ jobs:
|
|||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
run: |
|
run: |
|
||||||
cmake -B build -S . -G Ninja \
|
cmake -B build -S . -G Ninja \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
-DCMAKE_SYSTEM_NAME=Windows \
|
-DCMAKE_SYSTEM_NAME=Windows \
|
||||||
-DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc \
|
-DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc \
|
||||||
-DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ \
|
-DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ \
|
||||||
@@ -90,14 +91,12 @@ jobs:
|
|||||||
echo "Found EXE: $EXE"
|
echo "Found EXE: $EXE"
|
||||||
mkdir -p release
|
mkdir -p release
|
||||||
cp "$EXE" release/
|
cp "$EXE" release/
|
||||||
if [ -d "res" ]; then cp res/*.json release/; fi
|
|
||||||
cd release && zip -j ../hex-unlocked.zip *
|
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: runner-build
|
name: runner-build
|
||||||
path: hex-unlocked.zip
|
path: release/
|
||||||
|
|
||||||
- name: Finalize Version and Push Tag
|
- name: Finalize Version and Push Tag
|
||||||
if: ${{ github.event_name == 'push' && success() }}
|
if: ${{ github.event_name == 'push' && success() }}
|
||||||
@@ -109,7 +108,7 @@ jobs:
|
|||||||
if: ${{ github.event_name == 'push' && success() }}
|
if: ${{ github.event_name == 'push' && success() }}
|
||||||
uses: akkuman/gitea-release-action@v1
|
uses: akkuman/gitea-release-action@v1
|
||||||
with:
|
with:
|
||||||
files: hex-unlocked.zip
|
files: release/*
|
||||||
tag_name: ${{ steps.calculate-version.outputs.new-tag }}
|
tag_name: ${{ steps.calculate-version.outputs.new-tag }}
|
||||||
name: Release ${{ steps.calculate-version.outputs.new-tag }}
|
name: Release ${{ steps.calculate-version.outputs.new-tag }}
|
||||||
body: ${{ steps.calculate-version.outputs.changelog }}
|
body: ${{ steps.calculate-version.outputs.changelog }}
|
||||||
+15
-13
@@ -6,20 +6,19 @@ cmake_minimum_required(VERSION 3.25.0)
|
|||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
add_compile_definitions(WIN32_LEAN_AND_MEAN NOMINMAX)
|
|
||||||
|
|
||||||
if(MSVC)
|
|
||||||
add_compile_options(/EHsc /utf-8 /Zc:char8_t)
|
|
||||||
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
|
|
||||||
add_compile_definitions(_AMD64_)
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
add_compile_options(-m64)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
project(hex-unlocked LANGUAGES CXX)
|
project(hex-unlocked LANGUAGES CXX)
|
||||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
|
||||||
|
enable_language(RC)
|
||||||
|
|
||||||
|
if(CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||||
|
add_compile_options(/EHsc /utf-8 /Zc:char8_t)
|
||||||
|
else()
|
||||||
|
add_compile_options(-m64)
|
||||||
|
add_link_options(-static -static-libgcc -static-libstdc++)
|
||||||
|
endif()
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# options
|
# options
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
@@ -37,7 +36,6 @@ endif()
|
|||||||
# msvc stuff
|
# msvc stuff
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
if(CMAKE_GENERATOR MATCHES "Visual Studio")
|
if(CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||||
string(APPEND CMAKE_CXX_FLAGS " /EHsc /DWIN32_LEAN_AND_MEAN /utf-8 /Zc:char8_t")
|
|
||||||
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
|
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
|
||||||
string(APPEND CMAKE_CXX_FLAGS " /D_AMD64_")
|
string(APPEND CMAKE_CXX_FLAGS " /D_AMD64_")
|
||||||
elseif(CMAKE_GENERATOR_PLATFORM STREQUAL "Win32")
|
elseif(CMAKE_GENERATOR_PLATFORM STREQUAL "Win32")
|
||||||
@@ -138,8 +136,9 @@ endif()
|
|||||||
# ------------------------------
|
# ------------------------------
|
||||||
file(GLOB_RECURSE UNLOCKER_SOURCES CONFIGURE_DEPENDS "src/unlocker/*.cpp" "src/unlocker/*.h")
|
file(GLOB_RECURSE UNLOCKER_SOURCES CONFIGURE_DEPENDS "src/unlocker/*.cpp" "src/unlocker/*.h")
|
||||||
|
|
||||||
add_executable(hex-unlocked ${UNLOCKER_SOURCES})
|
add_executable(hex-unlocked WIN32 ${UNLOCKER_SOURCES} "res/resources.rc")
|
||||||
target_link_libraries(hex-unlocked PRIVATE hex-warned seallib glaze::glaze tinymitm wininet ixwebsocket crypt32)
|
target_compile_definitions(hex-unlocked PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX)
|
||||||
|
target_link_libraries(hex-unlocked PRIVATE hex-warned seallib glaze::glaze tinymitm wininet ixwebsocket crypt32 user32 shell32)
|
||||||
|
|
||||||
# rnd exe name
|
# rnd exe name
|
||||||
string(RANDOM LENGTH 12 ALPHABET "abcdefghijklmnopqrstuvwxyz0123456789" RANDOM_EXE_NAME)
|
string(RANDOM LENGTH 12 ALPHABET "abcdefghijklmnopqrstuvwxyz0123456789" RANDOM_EXE_NAME)
|
||||||
@@ -148,6 +147,9 @@ set_target_properties(hex-unlocked PROPERTIES OUTPUT_NAME "${RANDOM_EXE_NAME}")
|
|||||||
# compiler / IDE config
|
# compiler / IDE config
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
target_link_options(hex-unlocked PRIVATE -static -static-libgcc -static-libstdc++)
|
target_link_options(hex-unlocked PRIVATE -static -static-libgcc -static-libstdc++)
|
||||||
|
if(CMAKE_BUILD_TYPE MATCHES "Release|MinSizeRel")
|
||||||
|
target_link_options(hex-unlocked PRIVATE -s)
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT hex-unlocked)
|
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT hex-unlocked)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
<h1 align="center">
|
||||||
|
<img src="img/favicon.ico" height="64">
|
||||||
|
<br/>
|
||||||
|
<b>Hex: Unlocked</b>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
A Dead By Daylight inventory manager <b> for educational purposes</b>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
---
|
||||||
|
## Table of Contents
|
||||||
|
* [Installation & usage](#installation--usage)
|
||||||
|
* [Building](#building)
|
||||||
|
|
||||||
|
## Installation & usage
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> This goes against the Behaviour's Terms of Service. Although unlikely, there is a definite risk of ban.
|
||||||
|
|
||||||
|
### 1. Requirements
|
||||||
|
* **Dead By Daylight**: Xbox PC version or *Epic Games version **(untested)***
|
||||||
|
* **Operating System**: Windows 10 or 11 (64-bit)
|
||||||
|
|
||||||
|
### 2. Usage
|
||||||
|
1. Download the latest `hex-unlocked.exe` from the [Releases](../../releases) tab.
|
||||||
|
2. Run the exe before the game is running.
|
||||||
|
3. Configure your profile using the [site](https://dbd.neru.rip/).
|
||||||
|
4. Run the game.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> If you're missing items, open the Bloodweb, wait for it to load, and the inventory should be applied once again.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
This project uses CMake and requires a C++20 compatible compiler.
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
* CMake 3.25.0 or higher
|
||||||
|
* Visual Studio 2022 or higher (with C++ desktop development) OR MinGW-w64
|
||||||
|
* .NET SDK (if building with the optional Dumper enabled)
|
||||||
|
|
||||||
|
### Visual Studio (Recommended for Windows)
|
||||||
|
The easiest way to get started on Windows is to run the included PowerShell script. It will generate the Visual Studio solution and open it automatically:
|
||||||
|
```powershell
|
||||||
|
.\create-project.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
### MinGW (Linux Cross-Compile)
|
||||||
|
If you want to cross-compile using MinGW on Linux, you can configure and build using Ninja:
|
||||||
|
```bash
|
||||||
|
cmake -B proj -S . -G Ninja \
|
||||||
|
-DCMAKE_SYSTEM_NAME=Windows \
|
||||||
|
-DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc \
|
||||||
|
-DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ \
|
||||||
|
-DCMAKE_RC_COMPILER=x86_64-w64-mingw32-windres
|
||||||
|
|
||||||
|
cmake --build proj --target hex-unlocked
|
||||||
|
```
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 156 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 607 KiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 156 KiB |
@@ -0,0 +1 @@
|
|||||||
|
IDI_ICON1 ICON DISCARDABLE "icon.ico"
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "cache-cleaner.h"
|
#include "cache-cleaner.h"
|
||||||
|
|
||||||
#include "win-platform.h"
|
#include "win-platform.h"
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ class ConOutSink : public ILogSink
|
|||||||
public:
|
public:
|
||||||
virtual void receiveLog(LogType type, std::string_view loggerName, std::string_view msg) override
|
virtual void receiveLog(LogType type, std::string_view loggerName, std::string_view msg) override
|
||||||
{
|
{
|
||||||
|
#ifndef _DEBUG
|
||||||
|
if (type == LogType::VERBOSE) return;
|
||||||
|
#endif
|
||||||
std::cout << "[" << loggerName << "] " << seallib::getLogTypeColor(type) << "["
|
std::cout << "[" << loggerName << "] " << seallib::getLogTypeColor(type) << "["
|
||||||
<< seallib::getLogTypeName(type) << "]"
|
<< seallib::getLogTypeName(type) << "]"
|
||||||
<< "\x1b[0m " << msg << std::endl;
|
<< "\x1b[0m " << msg << std::endl;
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <seallib/log.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <mutex>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
using namespace seallib;
|
||||||
|
|
||||||
|
class FileSink : public ILogSink
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FileSink(const std::string& filename)
|
||||||
|
{
|
||||||
|
_file.open(utils::getExePath() + filename, std::ios::out | std::ios::app);
|
||||||
|
}
|
||||||
|
|
||||||
|
~FileSink()
|
||||||
|
{
|
||||||
|
if (_file.is_open())
|
||||||
|
_file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void receiveLog(LogType type, std::string_view loggerName, std::string_view msg) override
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
|
if (_file.is_open())
|
||||||
|
{
|
||||||
|
_file << "[" << loggerName << "] ["
|
||||||
|
<< seallib::getLogTypeName(type) << "] "
|
||||||
|
<< msg << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::shared_ptr<FileSink> getSharedInstance()
|
||||||
|
{
|
||||||
|
static std::shared_ptr<FileSink> instance = std::make_shared<FileSink>("hex-unlocked.log");
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::ofstream _file;
|
||||||
|
std::mutex _mutex;
|
||||||
|
};
|
||||||
+79
-16
@@ -1,26 +1,22 @@
|
|||||||
|
#include "win-platform.h"
|
||||||
|
#include "tray-icon.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "spoofer.h"
|
||||||
|
#include "log-sink-cout.h"
|
||||||
|
#include "log-sink-file.h"
|
||||||
|
#include "proxy-configurator.h"
|
||||||
|
#include "cache-cleaner.h"
|
||||||
|
|
||||||
#include <seallib/log.h>
|
#include <seallib/log.h>
|
||||||
#include <tinymitm/proxy.h>
|
#include <tinymitm/proxy.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
#include "spoofer.h"
|
|
||||||
#include "log-sink.h"
|
|
||||||
#include "proxy-configurator.h"
|
|
||||||
#include "cache-cleaner.h"
|
|
||||||
|
|
||||||
#include "win-platform.h"
|
|
||||||
|
|
||||||
#include <processenv.h>
|
#include <processenv.h>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <processthreadsapi.h>
|
#include <processthreadsapi.h>
|
||||||
#include <handleapi.h>
|
#include <handleapi.h>
|
||||||
|
|
||||||
#ifndef CREATE_NO_WINDOW
|
|
||||||
// from: WinBase.h
|
|
||||||
#define CREATE_NO_WINDOW 0x08000000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool running = true;
|
bool running = true;
|
||||||
TinyMITMProxy* proxy = nullptr;
|
TinyMITMProxy* proxy = nullptr;
|
||||||
ProxyConfigurator* conf = nullptr;
|
ProxyConfigurator* conf = nullptr;
|
||||||
@@ -71,8 +67,24 @@ void StartWatchdog()
|
|||||||
|
|
||||||
bool run()
|
bool run()
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
mutex check before running
|
||||||
|
*/
|
||||||
|
HANDLE mtx = CreateMutexA(NULL, TRUE, "Global\\HexUnlocked");
|
||||||
|
if (mtx == NULL) return false;
|
||||||
|
if (GetLastError() == ERROR_ALREADY_EXISTS)
|
||||||
|
{
|
||||||
|
MessageBoxA(NULL, "Program is already running", "Hex: Unlocked", MB_OK | MB_ICONERROR | MB_ICONINFORMATION);
|
||||||
|
CloseHandle(mtx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
init
|
||||||
|
*/
|
||||||
seallib::Logger mainLog("Main");
|
seallib::Logger mainLog("Main");
|
||||||
mainLog.addSink(std::make_shared<ConOutSink>());
|
mainLog.addSink(std::make_shared<ConOutSink>());
|
||||||
|
mainLog.addSink(FileSink::getSharedInstance());
|
||||||
|
|
||||||
mainLog.info("Init");
|
mainLog.info("Init");
|
||||||
|
|
||||||
@@ -104,11 +116,37 @@ bool run()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mainLog.info("Proxy running, Ctrl+C to stop.");
|
mainLog.info("Setting up system tray icon");
|
||||||
|
|
||||||
|
TrayIcon tray;
|
||||||
|
tray.setExitCallback([&]() {
|
||||||
|
running = false;
|
||||||
|
mainLog.info("Exit requested from system tray.");
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!tray.init())
|
||||||
|
{
|
||||||
|
mainLog.error("Failed to initialize system tray icon.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND consoleWnd = GetConsoleWindow();
|
||||||
|
if (consoleWnd)
|
||||||
|
{
|
||||||
|
HMENU menuHandle = GetSystemMenu(consoleWnd, FALSE);
|
||||||
|
if (menuHandle) RemoveMenu(menuHandle, SC_CLOSE, MF_BYCOMMAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
mainLog.info("Proxy running, Ctrl+C to stop. Check system tray for options.");
|
||||||
|
mainLog.info("Go to https://dbd.neru.rip/ for settings.");
|
||||||
while (running)
|
while (running)
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
{
|
||||||
|
tray.processMessages();
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||||
|
}
|
||||||
|
|
||||||
mainLog.info("Shutting down...");
|
mainLog.info("Shutting down...");
|
||||||
|
tray.shutdown();
|
||||||
proxy->shutdown();
|
proxy->shutdown();
|
||||||
cleaner->shutdown();
|
cleaner->shutdown();
|
||||||
|
|
||||||
@@ -117,11 +155,36 @@ bool run()
|
|||||||
delete conf;
|
delete conf;
|
||||||
conf = nullptr;
|
conf = nullptr;
|
||||||
|
|
||||||
|
ReleaseMutex(mtx);
|
||||||
|
CloseHandle(mtx);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nShowCmd*/)
|
||||||
{
|
{
|
||||||
|
AllocConsole();
|
||||||
|
SetConsoleTitleA(utils::randomizeString(32).c_str());
|
||||||
|
|
||||||
|
/*
|
||||||
|
ansi seequences
|
||||||
|
*/
|
||||||
|
HANDLE outHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
if (outHandle == INVALID_HANDLE_VALUE) return 1;
|
||||||
|
|
||||||
|
DWORD conMode = 0;
|
||||||
|
if (!GetConsoleMode(outHandle, &conMode)) return 1;
|
||||||
|
|
||||||
|
conMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
|
SetConsoleMode(outHandle, conMode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
io
|
||||||
|
*/
|
||||||
|
FILE* dummy;
|
||||||
|
freopen_s(&dummy, "CONIN$", "r", stdin);
|
||||||
|
freopen_s(&dummy, "CONOUT$", "w", stdout);
|
||||||
|
freopen_s(&dummy, "CONOUT$", "w", stderr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
handlers for cleaning proxy conf on exit / crash / taskkill / whatever
|
handlers for cleaning proxy conf on exit / crash / taskkill / whatever
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
#include "proxy-configurator.h"
|
#include "proxy-configurator.h"
|
||||||
|
|
||||||
#include "log-sink.h"
|
|
||||||
|
|
||||||
#include "win-platform.h"
|
#include "win-platform.h"
|
||||||
|
#include "log-sink-cout.h"
|
||||||
|
#include "log-sink-file.h"
|
||||||
|
|
||||||
#include <minwinbase.h>
|
#include <minwinbase.h>
|
||||||
#include <wininet.h>
|
#include <wininet.h>
|
||||||
#include <errhandlingapi.h>
|
#include <errhandlingapi.h>
|
||||||
|
|
||||||
|
#include <seallib/log.h>
|
||||||
|
|
||||||
ProxyConfigurator::ProxyConfigurator()
|
ProxyConfigurator::ProxyConfigurator()
|
||||||
{
|
{
|
||||||
_log = new seallib::Logger("ProxyConfigurator");
|
_log = new seallib::Logger("ProxyConfigurator");
|
||||||
_log->addSink(std::make_shared<ConOutSink>());
|
_log->addSink(std::make_shared<ConOutSink>());
|
||||||
|
_log->addSink(FileSink::getSharedInstance());
|
||||||
|
|
||||||
_log->verbose("ProxyConfigurator instantiated");
|
_log->verbose("ProxyConfigurator instantiated");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "spoofer.h"
|
#include "spoofer.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "log-sink.h"
|
#include "log-sink-cout.h"
|
||||||
|
#include "log-sink-file.h"
|
||||||
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -35,18 +36,19 @@ Spoofer::Spoofer()
|
|||||||
{
|
{
|
||||||
_log = new seallib::Logger("Spoofer");
|
_log = new seallib::Logger("Spoofer");
|
||||||
_log->addSink(std::make_shared<ConOutSink>());
|
_log->addSink(std::make_shared<ConOutSink>());
|
||||||
|
_log->addSink(FileSink::getSharedInstance());
|
||||||
|
|
||||||
_log->info("Spoofer init");
|
_log->verbose("Spoofer init");
|
||||||
|
|
||||||
loadConfig();
|
loadConfig();
|
||||||
|
|
||||||
_log->info("Starting WebSocket server");
|
_log->verbose("Starting WebSocket server");
|
||||||
initServer();
|
initServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
Spoofer::~Spoofer()
|
Spoofer::~Spoofer()
|
||||||
{
|
{
|
||||||
_log->info("Stopping WebSocket server");
|
_log->verbose("Stopping WebSocket server");
|
||||||
stopServer();
|
stopServer();
|
||||||
|
|
||||||
delete _log;
|
delete _log;
|
||||||
@@ -133,6 +135,7 @@ void Spoofer::saveConfig()
|
|||||||
std::string buffer;
|
std::string buffer;
|
||||||
auto errCtx = glz::write_file_json(conf, configPath, buffer);
|
auto errCtx = glz::write_file_json(conf, configPath, buffer);
|
||||||
if (errCtx.ec != glz::error_code::none) _log->error("Failed to save config to {}", configPath);
|
if (errCtx.ec != glz::error_code::none) _log->error("Failed to save config to {}", configPath);
|
||||||
|
_log->verbose("Saved config @ config.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -175,7 +178,7 @@ void Spoofer::wsMessageCallback(std::shared_ptr<ix::ConnectionState> /*connectio
|
|||||||
{
|
{
|
||||||
case ix::WebSocketMessageType::Open:
|
case ix::WebSocketMessageType::Open:
|
||||||
{
|
{
|
||||||
_log->verbose("Websocket connection open, URI: {}", msg->openInfo.uri);
|
_log->verbose("WebSocket connection open, URI: {}", msg->openInfo.uri);
|
||||||
WSMessages::Init initMsg;
|
WSMessages::Init initMsg;
|
||||||
initMsg.profile.camperItems = _camperItems;
|
initMsg.profile.camperItems = _camperItems;
|
||||||
initMsg.profile.camperAddons = _camperAddons;
|
initMsg.profile.camperAddons = _camperAddons;
|
||||||
@@ -203,7 +206,7 @@ void Spoofer::wsMessageCallback(std::shared_ptr<ix::ConnectionState> /*connectio
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ix::WebSocketMessageType::Close:
|
case ix::WebSocketMessageType::Close:
|
||||||
_log->verbose("Websocket connection close");
|
_log->verbose("WebSocket connection close");
|
||||||
break;
|
break;
|
||||||
case ix::WebSocketMessageType::Message:
|
case ix::WebSocketMessageType::Message:
|
||||||
{
|
{
|
||||||
@@ -211,7 +214,7 @@ void Spoofer::wsMessageCallback(std::shared_ptr<ix::ConnectionState> /*connectio
|
|||||||
auto err = glz::read_json(req, msg->str);
|
auto err = glz::read_json(req, msg->str);
|
||||||
if (err.ec != glz::error_code::none)
|
if (err.ec != glz::error_code::none)
|
||||||
{
|
{
|
||||||
_log->error("Failed to parse websocket message");
|
_log->error("Failed to parse WebSocket message");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (req.action)
|
switch (req.action)
|
||||||
@@ -330,13 +333,15 @@ void Spoofer::modifyCharacterInventory(glz::generic& js)
|
|||||||
appendPerks(_slasherPerks);
|
appendPerks(_slasherPerks);
|
||||||
}
|
}
|
||||||
appendItems(_globalOfferings);
|
appendItems(_globalOfferings);
|
||||||
|
|
||||||
|
_log->verbose("Modified inventory for character {}", js["characterName"].get_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Spoofer::modifyCharacterData(glz::generic& js)
|
void Spoofer::modifyCharacterData(glz::generic& js)
|
||||||
{
|
{
|
||||||
if (!js.contains("characterName") || !js["characterName"].is_string())
|
if (!js.contains("characterName") || !js["characterName"].is_string())
|
||||||
{
|
{
|
||||||
_log->verbose("attempted to modify invalid char");
|
_log->warning("Attempted to modify invalid character");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,6 +376,8 @@ void Spoofer::modifyCharacterData(glz::generic& js)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_spoofItems || _spoofPerks) modifyCharacterInventory(js);
|
if (_spoofItems || _spoofPerks) modifyCharacterInventory(js);
|
||||||
|
|
||||||
|
_log->verbose("Modified data for character {}", js["characterName"].get_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Spoofer::generateBloodweb(glz::generic& js)
|
void Spoofer::generateBloodweb(glz::generic& js)
|
||||||
|
|||||||
@@ -0,0 +1,175 @@
|
|||||||
|
#include "tray-icon.h"
|
||||||
|
#include "win-platform.h"
|
||||||
|
|
||||||
|
#include <shellapi.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define WM_TRAYICON (WM_USER + 1)
|
||||||
|
#define ID_TRAY_APP_ICON 1001
|
||||||
|
#define ID_TRAY_EXIT 1002
|
||||||
|
#define ID_TRAY_CONTROL_PANEL 1003
|
||||||
|
|
||||||
|
TrayIcon* TrayIcon::instance = nullptr;
|
||||||
|
|
||||||
|
TrayIcon::TrayIcon() : _hwnd(nullptr), _isConsoleVisible(true)
|
||||||
|
{
|
||||||
|
instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrayIcon::~TrayIcon()
|
||||||
|
{
|
||||||
|
shutdown();
|
||||||
|
instance = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* TrayIcon::windowProc(void* h, unsigned int msg, unsigned long long wParam, long long lParam)
|
||||||
|
{
|
||||||
|
HWND hwnd = reinterpret_cast<HWND>(h);
|
||||||
|
|
||||||
|
if (msg == WM_DESTROY)
|
||||||
|
{
|
||||||
|
PostQuitMessage(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg == WM_TRAYICON)
|
||||||
|
{
|
||||||
|
if (lParam == WM_LBUTTONUP && instance)
|
||||||
|
instance->onToggleConsole();
|
||||||
|
else if (lParam == WM_RBUTTONUP)
|
||||||
|
{
|
||||||
|
POINT curPoint;
|
||||||
|
GetCursorPos(&curPoint);
|
||||||
|
|
||||||
|
HMENU popupHandle = CreatePopupMenu();
|
||||||
|
InsertMenuA(popupHandle, 0, MF_BYPOSITION | MF_STRING, ID_TRAY_CONTROL_PANEL, "Open Control Panel");
|
||||||
|
InsertMenuA(popupHandle, 1, MF_BYPOSITION | MF_STRING, ID_TRAY_EXIT, "Exit");
|
||||||
|
|
||||||
|
SetForegroundWindow(hwnd);
|
||||||
|
|
||||||
|
UINT clicked =
|
||||||
|
TrackPopupMenu(popupHandle, TPM_RETURNCMD | TPM_NONOTIFY, curPoint.x, curPoint.y, 0, hwnd, NULL);
|
||||||
|
|
||||||
|
if (clicked == ID_TRAY_CONTROL_PANEL && instance)
|
||||||
|
instance->onOpenControlPanel();
|
||||||
|
else if (clicked == ID_TRAY_EXIT && instance)
|
||||||
|
instance->onExit();
|
||||||
|
|
||||||
|
DestroyMenu(popupHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reinterpret_cast<void*>(DefWindowProcA(hwnd, msg, wParam, lParam));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TrayIcon::init()
|
||||||
|
{
|
||||||
|
WNDCLASSEXA wc = {};
|
||||||
|
wc.cbSize = sizeof(WNDCLASSEX);
|
||||||
|
wc.lpfnWndProc = reinterpret_cast<WNDPROC>(reinterpret_cast<void*>(windowProc));
|
||||||
|
wc.hInstance = GetModuleHandle(NULL);
|
||||||
|
wc.lpszClassName = "HexUnlockedTrayIconClass";
|
||||||
|
|
||||||
|
if (!RegisterClassExA(&wc)) return false;
|
||||||
|
|
||||||
|
HWND window = CreateWindowExA(0, "HexUnlockedTrayIconClass", "HexUnlocked", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL,
|
||||||
|
wc.hInstance, NULL);
|
||||||
|
if (!window) return false;
|
||||||
|
|
||||||
|
this->_hwnd = window;
|
||||||
|
|
||||||
|
NOTIFYICONDATAA nid = {};
|
||||||
|
nid.cbSize = sizeof(NOTIFYICONDATA);
|
||||||
|
nid.hWnd = window;
|
||||||
|
nid.uID = ID_TRAY_APP_ICON;
|
||||||
|
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
|
||||||
|
nid.uCallbackMessage = WM_TRAYICON;
|
||||||
|
|
||||||
|
nid.hIcon = LoadIconA(GetModuleHandle(NULL), "IDI_ICON1");
|
||||||
|
strncpy_s(nid.szTip, "HexUnlocked", sizeof(nid.szTip) - 1);
|
||||||
|
nid.szTip[sizeof(nid.szTip) - 1] = '\0';
|
||||||
|
|
||||||
|
Shell_NotifyIconA(NIM_ADD, &nid);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrayIcon::shutdown()
|
||||||
|
{
|
||||||
|
if (_hwnd)
|
||||||
|
{
|
||||||
|
NOTIFYICONDATAA nid = {};
|
||||||
|
nid.cbSize = sizeof(NOTIFYICONDATA);
|
||||||
|
nid.hWnd = reinterpret_cast<HWND>(_hwnd);
|
||||||
|
nid.uID = ID_TRAY_APP_ICON;
|
||||||
|
Shell_NotifyIconA(NIM_DELETE, &nid);
|
||||||
|
|
||||||
|
DestroyWindow(reinterpret_cast<HWND>(_hwnd));
|
||||||
|
UnregisterClassA("HexUnlockedTrayIconClass", GetModuleHandle(NULL));
|
||||||
|
_hwnd = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrayIcon::processMessages()
|
||||||
|
{
|
||||||
|
MSG msg;
|
||||||
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||||
|
{
|
||||||
|
if (msg.message == WM_QUIT)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND consoleWnd = GetConsoleWindow();
|
||||||
|
if (consoleWnd && IsIconic(consoleWnd))
|
||||||
|
{
|
||||||
|
ShowWindow(consoleWnd, SW_HIDE);
|
||||||
|
_isConsoleVisible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrayIcon::onToggleConsole()
|
||||||
|
{
|
||||||
|
HWND consoleWnd = GetConsoleWindow();
|
||||||
|
if (!consoleWnd) return;
|
||||||
|
|
||||||
|
if (_isConsoleVisible)
|
||||||
|
{
|
||||||
|
ShowWindow(consoleWnd, SW_HIDE);
|
||||||
|
_isConsoleVisible = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ShowWindow(consoleWnd, SW_RESTORE);
|
||||||
|
|
||||||
|
HWND hCurWnd = GetForegroundWindow();
|
||||||
|
DWORD dwMyID = GetCurrentThreadId();
|
||||||
|
DWORD dwCurID = GetWindowThreadProcessId(hCurWnd, NULL);
|
||||||
|
AttachThreadInput(dwCurID, dwMyID, TRUE);
|
||||||
|
SetWindowPos(consoleWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
|
||||||
|
SetWindowPos(consoleWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
|
||||||
|
SetForegroundWindow(consoleWnd);
|
||||||
|
SetFocus(consoleWnd);
|
||||||
|
SetActiveWindow(consoleWnd);
|
||||||
|
AttachThreadInput(dwCurID, dwMyID, FALSE);
|
||||||
|
|
||||||
|
_isConsoleVisible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrayIcon::onOpenControlPanel()
|
||||||
|
{
|
||||||
|
ShellExecuteA(NULL, "open", "https://dbd.neru.rip", NULL, NULL, SW_SHOWNORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrayIcon::onExit()
|
||||||
|
{
|
||||||
|
if (_exitCallback) _exitCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrayIcon::setExitCallback(std::function<void()> callback)
|
||||||
|
{
|
||||||
|
_exitCallback = callback;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
class TrayIcon
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TrayIcon();
|
||||||
|
~TrayIcon();
|
||||||
|
|
||||||
|
bool init();
|
||||||
|
void shutdown();
|
||||||
|
void processMessages();
|
||||||
|
|
||||||
|
void onToggleConsole();
|
||||||
|
void onOpenControlPanel();
|
||||||
|
void onExit();
|
||||||
|
|
||||||
|
void setExitCallback(std::function<void()> callback);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void* windowProc(void* hwnd, unsigned int msg, unsigned long long wParam, long long lParam);
|
||||||
|
static TrayIcon* instance;
|
||||||
|
|
||||||
|
void* _hwnd;
|
||||||
|
bool _isConsoleVisible;
|
||||||
|
std::function<void()> _exitCallback;
|
||||||
|
};
|
||||||
@@ -6,4 +6,4 @@ namespace utils
|
|||||||
{
|
{
|
||||||
std::string getExePath();
|
std::string getExePath();
|
||||||
std::string randomizeString(size_t length);
|
std::string randomizeString(size_t length);
|
||||||
}
|
} // namespace utils
|
||||||
|
|||||||
@@ -3,10 +3,16 @@
|
|||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NOMINMAX
|
#ifndef NOMINMAX
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#include <windows.h>
|
#include <minwindef.h>
|
||||||
|
#include <wtypes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ERROR
|
||||||
|
#undef ERROR
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user