12 Commits

Author SHA1 Message Date
neru 9f5abefb34 docs: add images and sources
Build / build (push) Successful in 9m28s
2026-06-20 09:18:59 -03:00
neru f6ac12962d fix: remove unneeded def 2026-06-20 09:18:29 -03:00
neru 6d176c2020 build: fix weird compile bug
Build / build (push) Successful in 9m23s
2026-06-20 08:25:13 -03:00
neru 83c1fba265 build: bring back minsizerel
Build / build (push) Failing after 6m7s
2026-06-20 08:17:03 -03:00
neru e46a60f95f feat: randomize console title
Build / build (push) Successful in 8m20s
2026-06-20 08:06:34 -03:00
neru 6c086b5307 feat: add additional logging and write to file 2026-06-20 08:05:23 -03:00
neru 064f1701ee chore: rename log-sink to log-sink-cout 2026-06-20 08:04:55 -03:00
neru df9ad4fc70 feat: add file log sink 2026-06-20 08:04:36 -03:00
neru c0b710d6f7 fix: misc building warnings
Build / build (push) Successful in 8m29s
2026-06-20 07:33:18 -03:00
neru e27fb6d73a docs: add readme
Build / build (push) Failing after 5m23s
2026-06-20 07:24:17 -03:00
neru e95308605b build: attempt to fix wolfssl build error 2026-06-20 07:15:44 -03:00
neru 205ee06c27 build: remove zip 2026-06-20 07:11:18 -03:00
12 changed files with 142 additions and 25 deletions
+4 -5
View File
@@ -15,7 +15,7 @@ jobs:
- name: Install Dependencies
run: |
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
with:
@@ -74,6 +74,7 @@ jobs:
- name: Configure CMake
run: |
cmake -B build -S . -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_SYSTEM_NAME=Windows \
-DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc \
-DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ \
@@ -90,14 +91,12 @@ jobs:
echo "Found EXE: $EXE"
mkdir -p release
cp "$EXE" release/
if [ -d "res" ]; then cp res/*.json release/; fi
cd release && zip -j ../hex-unlocked.zip *
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: runner-build
path: hex-unlocked.zip
path: release/
- name: Finalize Version and Push Tag
if: ${{ github.event_name == 'push' && success() }}
@@ -109,7 +108,7 @@ jobs:
if: ${{ github.event_name == 'push' && success() }}
uses: akkuman/gitea-release-action@v1
with:
files: hex-unlocked.zip
files: release/*
tag_name: ${{ steps.calculate-version.outputs.new-tag }}
name: Release ${{ steps.calculate-version.outputs.new-tag }}
body: ${{ steps.calculate-version.outputs.changelog }}
+4 -1
View File
@@ -6,7 +6,6 @@ cmake_minimum_required(VERSION 3.25.0)
set(CMAKE_CXX_STANDARD 20)
add_compile_definitions(WIN32_LEAN_AND_MEAN NOMINMAX)
project(hex-unlocked LANGUAGES CXX)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
@@ -138,6 +137,7 @@ endif()
file(GLOB_RECURSE UNLOCKER_SOURCES CONFIGURE_DEPENDS "src/unlocker/*.cpp" "src/unlocker/*.h")
add_executable(hex-unlocked WIN32 ${UNLOCKER_SOURCES} "res/resources.rc")
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
@@ -147,6 +147,9 @@ set_target_properties(hex-unlocked PROPERTIES OUTPUT_NAME "${RANDOM_EXE_NAME}")
# compiler / IDE config
if(NOT MSVC)
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()
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT hex-unlocked)
endif()
+56
View File
@@ -0,0 +1,56 @@
<h1 align="center">
<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
```
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 607 KiB

BIN
View File
Binary file not shown.
@@ -11,6 +11,9 @@ class ConOutSink : public ILogSink
public:
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) << "["
<< seallib::getLogTypeName(type) << "]"
<< "\x1b[0m " << msg << std::endl;
+48
View File
@@ -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;
};
+5 -6
View File
@@ -2,7 +2,8 @@
#include "tray-icon.h"
#include "utils.h"
#include "spoofer.h"
#include "log-sink.h"
#include "log-sink-cout.h"
#include "log-sink-file.h"
#include "proxy-configurator.h"
#include "cache-cleaner.h"
@@ -16,11 +17,6 @@
#include <processthreadsapi.h>
#include <handleapi.h>
#ifndef CREATE_NO_WINDOW
// from: WinBase.h
#define CREATE_NO_WINDOW 0x08000000
#endif
bool running = true;
TinyMITMProxy* proxy = nullptr;
ProxyConfigurator* conf = nullptr;
@@ -88,6 +84,7 @@ bool run()
*/
seallib::Logger mainLog("Main");
mainLog.addSink(std::make_shared<ConOutSink>());
mainLog.addSink(FileSink::getSharedInstance());
mainLog.info("Init");
@@ -141,6 +138,7 @@ bool run()
}
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)
{
tray.processMessages();
@@ -166,6 +164,7 @@ bool run()
int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nShowCmd*/)
{
AllocConsole();
SetConsoleTitleA(utils::randomizeString(32).c_str());
/*
ansi seequences
+3 -1
View File
@@ -1,7 +1,8 @@
#include "proxy-configurator.h"
#include "win-platform.h"
#include "log-sink.h"
#include "log-sink-cout.h"
#include "log-sink-file.h"
#include <minwinbase.h>
#include <wininet.h>
@@ -13,6 +14,7 @@ ProxyConfigurator::ProxyConfigurator()
{
_log = new seallib::Logger("ProxyConfigurator");
_log->addSink(std::make_shared<ConOutSink>());
_log->addSink(FileSink::getSharedInstance());
_log->verbose("ProxyConfigurator instantiated");
}
+15 -8
View File
@@ -1,6 +1,7 @@
#include "spoofer.h"
#include "utils.h"
#include "log-sink.h"
#include "log-sink-cout.h"
#include "log-sink-file.h"
#include <regex>
#include <map>
@@ -35,18 +36,19 @@ Spoofer::Spoofer()
{
_log = new seallib::Logger("Spoofer");
_log->addSink(std::make_shared<ConOutSink>());
_log->addSink(FileSink::getSharedInstance());
_log->info("Spoofer init");
_log->verbose("Spoofer init");
loadConfig();
_log->info("Starting WebSocket server");
_log->verbose("Starting WebSocket server");
initServer();
}
Spoofer::~Spoofer()
{
_log->info("Stopping WebSocket server");
_log->verbose("Stopping WebSocket server");
stopServer();
delete _log;
@@ -133,6 +135,7 @@ void Spoofer::saveConfig()
std::string 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);
_log->verbose("Saved config @ config.json");
}
/*
@@ -175,7 +178,7 @@ void Spoofer::wsMessageCallback(std::shared_ptr<ix::ConnectionState> /*connectio
{
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;
initMsg.profile.camperItems = _camperItems;
initMsg.profile.camperAddons = _camperAddons;
@@ -203,7 +206,7 @@ void Spoofer::wsMessageCallback(std::shared_ptr<ix::ConnectionState> /*connectio
break;
}
case ix::WebSocketMessageType::Close:
_log->verbose("Websocket connection close");
_log->verbose("WebSocket connection close");
break;
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);
if (err.ec != glz::error_code::none)
{
_log->error("Failed to parse websocket message");
_log->error("Failed to parse WebSocket message");
break;
}
switch (req.action)
@@ -330,13 +333,15 @@ void Spoofer::modifyCharacterInventory(glz::generic& js)
appendPerks(_slasherPerks);
}
appendItems(_globalOfferings);
_log->verbose("Modified inventory for character {}", js["characterName"].get_string());
}
void Spoofer::modifyCharacterData(glz::generic& js)
{
if (!js.contains("characterName") || !js["characterName"].is_string())
{
_log->verbose("attempted to modify invalid char");
_log->warning("Attempted to modify invalid character");
return;
}
@@ -371,6 +376,8 @@ void Spoofer::modifyCharacterData(glz::generic& js)
}
if (_spoofItems || _spoofPerks) modifyCharacterInventory(js);
_log->verbose("Modified data for character {}", js["characterName"].get_string());
}
void Spoofer::generateBloodweb(glz::generic& js)
+4 -4
View File
@@ -63,9 +63,9 @@ void* TrayIcon::windowProc(void* h, unsigned int msg, unsigned long long wParam,
bool TrayIcon::init()
{
WNDCLASSEXA wc = {0};
WNDCLASSEXA wc = {};
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = (WNDPROC)windowProc;
wc.lpfnWndProc = reinterpret_cast<WNDPROC>(reinterpret_cast<void*>(windowProc));
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = "HexUnlockedTrayIconClass";
@@ -77,7 +77,7 @@ bool TrayIcon::init()
this->_hwnd = window;
NOTIFYICONDATAA nid = {0};
NOTIFYICONDATAA nid = {};
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = window;
nid.uID = ID_TRAY_APP_ICON;
@@ -97,7 +97,7 @@ void TrayIcon::shutdown()
{
if (_hwnd)
{
NOTIFYICONDATAA nid = {0};
NOTIFYICONDATAA nid = {};
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = reinterpret_cast<HWND>(_hwnd);
nid.uID = ID_TRAY_APP_ICON;