-
Автор темы
- #1
Перед прочтением основного контента ниже, пожалуйста, обратите внимание на обновление внутри секции Майна на нашем форуме. У нас появились:
- бесплатные читы для Майнкрафт — любое использование на свой страх и риск;
- маркетплейс Майнкрафт — абсолютно любая коммерция, связанная с игрой, за исключением продажи читов (аккаунты, предоставления услуг, поиск кодеров читов и так далее);
- приватные читы для Minecraft — в этом разделе только платные хаки для игры, покупайте группу "Продавец" и выставляйте на продажу свой софт;
- обсуждения и гайды — всё тот же раздел с вопросами, но теперь модернизированный: поиск нужных хаков, пати с игроками-читерами и другая полезная информация.
Спасибо!
Привет. Прошу помочь с отрисовкой 2D ESP на entity (как пример, хотел отрисовывать на овцах). Координаты овец получаю. Свои тоже получаю. Скорее всего проблема в WorldToScreen, но я не понимаю что тут фиксить нужно. Пытался через ChatGPT платный сделать, она мне хуйню всякую советует. Вот пришёл сюда. Скриншот прилагаю.
[Minecraft 1.7.10 Forge]
Возможно этот WorldToScreen сработает, но я не знаю как его вставить в свой код, так как я просто паcтер.
[Minecraft 1.7.10 Forge]
#define NOMINMAX
#include <Windows.h>
#include <thread>
#include <chrono>
#include <limits>
#include <mutex>
#include "MinHook.h"
#pragma comment(lib, "libMinHook.x64.lib")
#include <jni.h>
#include <vector>
#include <string>
#include <unordered_map>
#include <functional>
#include "imgui/imgui.h"
#include "imgui/imgui_impl_win32.h"
#include "imgui/imgui_impl_opengl2.h"
#include "imgui/imgui_internal.h"
#define _CAST(t,v) reinterpret_cast<t>(v)
#define _VOID_1(v) std::function<void(v)>
#define _VOID_2(v) _VOID_1(_VOID_1(v))
typedef LRESULT(CALLBACK* WNDPROC) (IN HWND hwnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam);
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
static WNDPROC o_WndProc;
static HGLRC g_WglContext;
static bool initImGui = false;
static _VOID_1() RenderMains;
HWND hWnd = nullptr;
bool menu = false;
// Глобальные переменные
JNIEnv* g_env = nullptr;
jobject g_loader = nullptr;
JavaVM* g_jvm = nullptr;
typedef jint(JNICALL* JNI_GetCreatedJavaVMs_t)(JavaVM*, jsize, jsize);
JNI_GetCreatedJavaVMs_t original_JNI_GetCreatedJavaVMs = nullptr;
typedef BOOL(__stdcall* T_SwapBuffers)(HDC);
T_SwapBuffers pSwapBuffers = nullptr;
bool showSheep = true;
void RenderMain();
// Структура для овец
struct Entity {
float x, y, z; // Координаты в мире
};
// Глобальные переменные для координат игрока и овец
std::unordered_map<jlong, Entity> sheepEntities;
float playerX = 0.0f, playerY = 0.0f, playerZ = 0.0f;
std::mutex entitiesMutex; // Для синхронизации доступа к sheepEntities
LRESULT CALLBACK h_WndProc(const HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (menu) {
ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam);
}
return CallWindowProc(o_WndProc, hWnd, uMsg, wParam, lParam);
}
void ExitStatus(bool* status, bool value)
{
if (status) *status = value;
}
void InitOpenGL2(IN HDC hDc, OUT bool* init, OUT bool* status)
{
if (WindowFromDC(hDc) == hWnd && *init) return;
auto tStatus = true;
hWnd = WindowFromDC(hDc);
auto wLPTR = SetWindowLongPtr(hWnd, GWLP_WNDPROC, _CAST(LONG_PTR, h_WndProc));
if (*init)
{
ImGui_ImplWin32_Init(hWnd);
ImGui_ImplOpenGL2_Init();
return;
}
if (!wLPTR) return ExitStatus(status, false);
o_WndProc = _CAST(WNDPROC, wLPTR);
g_WglContext = wglCreateContext(hDc);
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
/*
ImFontConfig config;
config.MergeMode = true;
config.GlyphMinAdvanceX = 13.0f;
static const ImWchar icon_ranges[] = { ICON_MIN, ICON_MAX, 0 };
io.Fonts->AddFontFromMemoryTTF(icons, 13.0f, &config, icon_ranges);
*/
tStatus &= ImGui_ImplWin32_Init(hWnd);
tStatus &= ImGui_ImplOpenGL2_Init();
*init = true;
return ExitStatus(status, tStatus);
}
void RenderWin32(IN std::function<void()> render)
{
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
render();
ImGui::EndFrame();
ImGui::Render();
}
void RenderOpenGL2(IN HGLRC WglContext, IN HDC hDc, IN _VOID_2() render, IN _VOID_1() render_inner, OUT bool* status)
{
auto tStatus = true;
auto o_WglContext = wglGetCurrentContext();
tStatus &= wglMakeCurrent(hDc, WglContext);
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
ImGui_ImplOpenGL2_NewFrame();
render(render_inner);
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
tStatus &= wglMakeCurrent(hDc, o_WglContext);
return ExitStatus(status, tStatus);
}
BOOL __stdcall mySwapBuffers(HDC hDC)
{
InitOpenGL2(hDC, &initImGui, nullptr);
RenderOpenGL2(g_WglContext, hDC, RenderWin32, RenderMain, nullptr);
return pSwapBuffers(hDC);
}
// Получаем координаты игрока и овец (вызывается в MainThread)
void UpdateEntities(JNIEnv* env, jobject loader) {
if (!env || !loader) return;
// Получаем класс Minecraft
jclass minecraftClass = getJVMFindClass(env, "net/minecraft/client/Minecraft", JNI_TRUE, loader, JNI_FALSE);
if (!minecraftClass) return;
// Получаем экземпляр Minecraft
jfieldID minecraftInstanceField = env->GetStaticFieldID(minecraftClass, "field_71432_P", "Lnet/minecraft/client/Minecraft;");
if (!minecraftInstanceField) return;
jobject minecraftInstance = env->GetStaticObjectField(minecraftClass, minecraftInstanceField);
if (!minecraftInstance) return;
// Пытаемся получить игрока (EntityClientPlayerMP для 1.7.10)
jfieldID playerField = env->GetFieldID(minecraftClass, "field_71439_g", "Lnet/minecraft/client/entity/EntityClientPlayerMP;");
if (!playerField) return;
jobject player = env->GetObjectField(minecraftInstance, playerField);
if (!player) return;
// Получаем координаты игрока
jclass entityClass = getJVMFindClass(env, "net/minecraft/entity/Entity", JNI_TRUE, loader, JNI_FALSE);
if (!entityClass) return;
jfieldID posXField = env->GetFieldID(entityClass, "field_70165_t", "D"); // posX
jfieldID posYField = env->GetFieldID(entityClass, "field_70163_u", "D"); // posY
jfieldID posZField = env->GetFieldID(entityClass, "field_70161_v", "D"); // posZ
if (!posXField || !posYField || !posZField) return;
playerX = (float)env->GetDoubleField(player, posXField);
playerY = (float)env->GetDoubleField(player, posYField);
playerZ = (float)env->GetDoubleField(player, posZField);
// Получаем мир
jfieldID worldField = env->GetFieldID(minecraftClass, "field_71441_e", "Lnet/minecraft/client/multiplayer/WorldClient;");
if (!worldField) return;
jobject world = env->GetObjectField(minecraftInstance, worldField);
if (!world) return;
// Получаем список сущностей
jclass worldClass = env->GetObjectClass(world);
jfieldID entityListField = env->GetFieldID(worldClass, "field_72996_f", "Ljava/util/List;");
if (!entityListField) return;
jobject entityList = env->GetObjectField(world, entityListField);
if (!entityList) return;
// Работаем со списком сущностей
jclass listClass = env->FindClass("java/util/List");
if (!listClass) return;
jmethodID sizeMethod = env->GetMethodID(listClass, "size", "()I");
jmethodID getMethod = env->GetMethodID(listClass, "get", "(I)Ljava/lang/Object;");
if (!sizeMethod || !getMethod) return;
jint entityCount = env->CallIntMethod(entityList, sizeMethod);
jclass sheepClass = getJVMFindClass(env, "net/minecraft/entity/passive/EntitySheep", JNI_TRUE, loader, JNI_FALSE);
if (!sheepClass) return;
jmethodID getEntityIdMethod = env->GetMethodID(entityClass, "func_145782_y", "()I"); // getEntityId
if (!getEntityIdMethod) return;
std::unordered_map<jlong, Entity> tempEntities;
for (jint i = 0; i < entityCount; i++) {
jobject entity = env->CallObjectMethod(entityList, getMethod, i);
if (!entity) continue;
// Проверяем, является ли сущность овцой
jboolean isSheep = env->IsInstanceOf(entity, sheepClass);
if (!isSheep) continue;
// Получаем координаты
jdouble x = env->GetDoubleField(entity, posXField);
jdouble y = env->GetDoubleField(entity, posYField);
jdouble z = env->GetDoubleField(entity, posZField);
jint entityId = env->CallIntMethod(entity, getEntityIdMethod);
tempEntities[entityId] = { (float)x, (float)y, (float)z };
}
// Безопасно обновляем глобальную переменную
std::lock_guard<std::mutex> lock(entitiesMutex);
sheepEntities = std::move(tempEntities);
}
// Упрощённая проекция координат овец в экранное пространство
ImVec2 WorldToScreenSimple(float entityX, float entityY, float entityZ, float playerX, float playerY, float playerZ, float screenWidth, float screenHeight) {
float dx = entityX - playerX;
float dz = entityZ - playerZ;
float distance = sqrt(dx * dx + dz * dz);
if (distance < 1.0f) return ImVec2(-1, -1); // Слишком близко
float screenX = (dx / distance) * screenWidth * 0.5f + screenWidth * 0.5f;
float screenY = screenHeight * 0.5f - (entityY - playerY) * 50.0f / distance; // Масштаб по высоте
return ImVec2(screenX, screenY);
}
// Отрисовка 2D боксов на овцах
void Render2DESP() {
if (!showSheep) return;
ImGuiIO& io = ImGui::GetIO();
float screenWidth = io.DisplaySize.x;
float screenHeight = io.DisplaySize.y;
ImDrawList* drawList = ImGui::GetBackgroundDrawList();
std::lock_guard<std::mutex> lock(entitiesMutex);
for (std::unordered_map<jlong, Entity>::const_iterator it = sheepEntities.begin(); it != sheepEntities.end(); ++it) {
const Entity& sheep = it->second;
// Преобразуем координаты овцы в экранные (верх и низ)
ImVec2 screenPos = WorldToScreenSimple(sheep.x, sheep.y + 1.0f, sheep.z, playerX, playerY, playerZ, screenWidth, screenHeight);
if (screenPos.x < 0 || screenPos.x > screenWidth || screenPos.y < 0 || screenPos.y > screenHeight) continue;
ImVec2 bottomPos = WorldToScreenSimple(sheep.x, sheep.y - 0.5f, sheep.z, playerX, playerY, playerZ, screenWidth, screenHeight);
float height = bottomPos.y - screenPos.y;
float width = height * 0.5f;
// Ограничиваем размеры
if (width < 10.0f) width = 10.0f;
if (height < 20.0f) height = 20.0f;
ImVec2 topLeft(screenPos.x - width / 2, screenPos.y);
ImVec2 bottomRight(screenPos.x + width / 2, screenPos.y + height);
// Рисуем красный прямоугольник
drawList->AddRect(topLeft, bottomRight, IM_COL32(255, 0, 0, 255), 0.0f, 0, 2.0f);
}
}
void ShowError(const char* message) {
MessageBoxA(NULL, message, "Error", MB_OK | MB_ICONERROR);
}
jobject getLaunchClassLoader(JNIEnv* env) {
// Получаю Форджовский класс лоадер
}
jint JNICALL Hooked_JNI_GetCreatedJavaVMs(JavaVM** vmBuf, jsize bufLen, jsize* nVMs) {
jint result = original_JNI_GetCreatedJavaVMs(vmBuf, bufLen, nVMs);
if (result == JNI_OK && nVMs && *nVMs > 0) {
g_jvm = vmBuf[0];
}
return result;
}
void initHooks() {
MH_Initialize();
HMODULE jvmModule = GetModuleHandleA("jvm.dll");
HMODULE openglModule = GetModuleHandleW(L"opengl32.dll");
FARPROC target = GetProcAddress(jvmModule, "JNI_GetCreatedJavaVMs");
pSwapBuffers = reinterpret_cast<T_SwapBuffers>(GetProcAddress(openglModule, "wglSwapBuffers"));
MH_CreateHook(target, &Hooked_JNI_GetCreatedJavaVMs, (LPVOID*)&original_JNI_GetCreatedJavaVMs);
MH_CreateHook(pSwapBuffers, mySwapBuffers, reinterpret_cast<void**>(&pSwapBuffers));
MH_EnableHook(MH_ALL_HOOKS);
}
DWORD WINAPI MainThread(LPVOID) {
initHooks();
if (!g_jvm) {
HMODULE jvmModule = GetModuleHandleA("jvm.dll");
if (!jvmModule) return 0;
auto pGetCreatedJavaVMs = (JNI_GetCreatedJavaVMs_t)GetProcAddress(jvmModule, "JNI_GetCreatedJavaVMs");
if (!pGetCreatedJavaVMs) return 0;
JavaVM* tmp[1];
jsize count = 0;
jint res = pGetCreatedJavaVMs(tmp, 1, &count);
if (res == JNI_OK && count > 0) g_jvm = tmp[0];
else return 0;
}
bool attached = false;
jint ret = g_jvm->GetEnv((void**)&g_env, JNI_VERSION_1_6);
if (ret == JNI_EDETACHED) {
if (g_jvm->AttachCurrentThread((void**)&g_env, nullptr) != JNI_OK) {
ShowError("Failed to attach thread to JVM!");
return 0;
}
attached = true;
}
else if (ret != JNI_OK) {
ShowError("Failed to get JNI environment!");
return 0;
}
g_loader = getLaunchClassLoader(g_env);
if (!g_loader) {
ShowError("Failed to get ClassLoader!");
if (attached) g_jvm->DetachCurrentThread();
return 0;
}
// Цикл обновления данных об овцах
while (true) {
UpdateEntities(g_env, g_loader);
Sleep(50); // Обновляем примерно 20 раз в секунду
}
if (attached) g_jvm->DetachCurrentThread();
return 0;
}
void RenderMain() {
if (ImGui::Begin("ESP Settings")) {
ImGui::Checkbox("ESP Sheep", &showSheep);
}
ImGui::End();
if (showSheep) {
Render2DESP();
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls(hModule);
HANDLE hThread = CreateThread(nullptr, 0, MainThread, nullptr, 0, nullptr);
if (hThread) CloseHandle(hThread);
}
else if (ul_reason_for_call == DLL_PROCESS_DETACH) {
MH_Uninitialize();
}
return TRUE;
}
#include <Windows.h>
#include <thread>
#include <chrono>
#include <limits>
#include <mutex>
#include "MinHook.h"
#pragma comment(lib, "libMinHook.x64.lib")
#include <jni.h>
#include <vector>
#include <string>
#include <unordered_map>
#include <functional>
#include "imgui/imgui.h"
#include "imgui/imgui_impl_win32.h"
#include "imgui/imgui_impl_opengl2.h"
#include "imgui/imgui_internal.h"
#define _CAST(t,v) reinterpret_cast<t>(v)
#define _VOID_1(v) std::function<void(v)>
#define _VOID_2(v) _VOID_1(_VOID_1(v))
typedef LRESULT(CALLBACK* WNDPROC) (IN HWND hwnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam);
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
static WNDPROC o_WndProc;
static HGLRC g_WglContext;
static bool initImGui = false;
static _VOID_1() RenderMains;
HWND hWnd = nullptr;
bool menu = false;
// Глобальные переменные
JNIEnv* g_env = nullptr;
jobject g_loader = nullptr;
JavaVM* g_jvm = nullptr;
typedef jint(JNICALL* JNI_GetCreatedJavaVMs_t)(JavaVM*, jsize, jsize);
JNI_GetCreatedJavaVMs_t original_JNI_GetCreatedJavaVMs = nullptr;
typedef BOOL(__stdcall* T_SwapBuffers)(HDC);
T_SwapBuffers pSwapBuffers = nullptr;
bool showSheep = true;
void RenderMain();
// Структура для овец
struct Entity {
float x, y, z; // Координаты в мире
};
// Глобальные переменные для координат игрока и овец
std::unordered_map<jlong, Entity> sheepEntities;
float playerX = 0.0f, playerY = 0.0f, playerZ = 0.0f;
std::mutex entitiesMutex; // Для синхронизации доступа к sheepEntities
LRESULT CALLBACK h_WndProc(const HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (menu) {
ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam);
}
return CallWindowProc(o_WndProc, hWnd, uMsg, wParam, lParam);
}
void ExitStatus(bool* status, bool value)
{
if (status) *status = value;
}
void InitOpenGL2(IN HDC hDc, OUT bool* init, OUT bool* status)
{
if (WindowFromDC(hDc) == hWnd && *init) return;
auto tStatus = true;
hWnd = WindowFromDC(hDc);
auto wLPTR = SetWindowLongPtr(hWnd, GWLP_WNDPROC, _CAST(LONG_PTR, h_WndProc));
if (*init)
{
ImGui_ImplWin32_Init(hWnd);
ImGui_ImplOpenGL2_Init();
return;
}
if (!wLPTR) return ExitStatus(status, false);
o_WndProc = _CAST(WNDPROC, wLPTR);
g_WglContext = wglCreateContext(hDc);
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
/*
ImFontConfig config;
config.MergeMode = true;
config.GlyphMinAdvanceX = 13.0f;
static const ImWchar icon_ranges[] = { ICON_MIN, ICON_MAX, 0 };
io.Fonts->AddFontFromMemoryTTF(icons, 13.0f, &config, icon_ranges);
*/
tStatus &= ImGui_ImplWin32_Init(hWnd);
tStatus &= ImGui_ImplOpenGL2_Init();
*init = true;
return ExitStatus(status, tStatus);
}
void RenderWin32(IN std::function<void()> render)
{
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
render();
ImGui::EndFrame();
ImGui::Render();
}
void RenderOpenGL2(IN HGLRC WglContext, IN HDC hDc, IN _VOID_2() render, IN _VOID_1() render_inner, OUT bool* status)
{
auto tStatus = true;
auto o_WglContext = wglGetCurrentContext();
tStatus &= wglMakeCurrent(hDc, WglContext);
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
ImGui_ImplOpenGL2_NewFrame();
render(render_inner);
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
tStatus &= wglMakeCurrent(hDc, o_WglContext);
return ExitStatus(status, tStatus);
}
BOOL __stdcall mySwapBuffers(HDC hDC)
{
InitOpenGL2(hDC, &initImGui, nullptr);
RenderOpenGL2(g_WglContext, hDC, RenderWin32, RenderMain, nullptr);
return pSwapBuffers(hDC);
}
// Получаем координаты игрока и овец (вызывается в MainThread)
void UpdateEntities(JNIEnv* env, jobject loader) {
if (!env || !loader) return;
// Получаем класс Minecraft
jclass minecraftClass = getJVMFindClass(env, "net/minecraft/client/Minecraft", JNI_TRUE, loader, JNI_FALSE);
if (!minecraftClass) return;
// Получаем экземпляр Minecraft
jfieldID minecraftInstanceField = env->GetStaticFieldID(minecraftClass, "field_71432_P", "Lnet/minecraft/client/Minecraft;");
if (!minecraftInstanceField) return;
jobject minecraftInstance = env->GetStaticObjectField(minecraftClass, minecraftInstanceField);
if (!minecraftInstance) return;
// Пытаемся получить игрока (EntityClientPlayerMP для 1.7.10)
jfieldID playerField = env->GetFieldID(minecraftClass, "field_71439_g", "Lnet/minecraft/client/entity/EntityClientPlayerMP;");
if (!playerField) return;
jobject player = env->GetObjectField(minecraftInstance, playerField);
if (!player) return;
// Получаем координаты игрока
jclass entityClass = getJVMFindClass(env, "net/minecraft/entity/Entity", JNI_TRUE, loader, JNI_FALSE);
if (!entityClass) return;
jfieldID posXField = env->GetFieldID(entityClass, "field_70165_t", "D"); // posX
jfieldID posYField = env->GetFieldID(entityClass, "field_70163_u", "D"); // posY
jfieldID posZField = env->GetFieldID(entityClass, "field_70161_v", "D"); // posZ
if (!posXField || !posYField || !posZField) return;
playerX = (float)env->GetDoubleField(player, posXField);
playerY = (float)env->GetDoubleField(player, posYField);
playerZ = (float)env->GetDoubleField(player, posZField);
// Получаем мир
jfieldID worldField = env->GetFieldID(minecraftClass, "field_71441_e", "Lnet/minecraft/client/multiplayer/WorldClient;");
if (!worldField) return;
jobject world = env->GetObjectField(minecraftInstance, worldField);
if (!world) return;
// Получаем список сущностей
jclass worldClass = env->GetObjectClass(world);
jfieldID entityListField = env->GetFieldID(worldClass, "field_72996_f", "Ljava/util/List;");
if (!entityListField) return;
jobject entityList = env->GetObjectField(world, entityListField);
if (!entityList) return;
// Работаем со списком сущностей
jclass listClass = env->FindClass("java/util/List");
if (!listClass) return;
jmethodID sizeMethod = env->GetMethodID(listClass, "size", "()I");
jmethodID getMethod = env->GetMethodID(listClass, "get", "(I)Ljava/lang/Object;");
if (!sizeMethod || !getMethod) return;
jint entityCount = env->CallIntMethod(entityList, sizeMethod);
jclass sheepClass = getJVMFindClass(env, "net/minecraft/entity/passive/EntitySheep", JNI_TRUE, loader, JNI_FALSE);
if (!sheepClass) return;
jmethodID getEntityIdMethod = env->GetMethodID(entityClass, "func_145782_y", "()I"); // getEntityId
if (!getEntityIdMethod) return;
std::unordered_map<jlong, Entity> tempEntities;
for (jint i = 0; i < entityCount; i++) {
jobject entity = env->CallObjectMethod(entityList, getMethod, i);
if (!entity) continue;
// Проверяем, является ли сущность овцой
jboolean isSheep = env->IsInstanceOf(entity, sheepClass);
if (!isSheep) continue;
// Получаем координаты
jdouble x = env->GetDoubleField(entity, posXField);
jdouble y = env->GetDoubleField(entity, posYField);
jdouble z = env->GetDoubleField(entity, posZField);
jint entityId = env->CallIntMethod(entity, getEntityIdMethod);
tempEntities[entityId] = { (float)x, (float)y, (float)z };
}
// Безопасно обновляем глобальную переменную
std::lock_guard<std::mutex> lock(entitiesMutex);
sheepEntities = std::move(tempEntities);
}
// Упрощённая проекция координат овец в экранное пространство
ImVec2 WorldToScreenSimple(float entityX, float entityY, float entityZ, float playerX, float playerY, float playerZ, float screenWidth, float screenHeight) {
float dx = entityX - playerX;
float dz = entityZ - playerZ;
float distance = sqrt(dx * dx + dz * dz);
if (distance < 1.0f) return ImVec2(-1, -1); // Слишком близко
float screenX = (dx / distance) * screenWidth * 0.5f + screenWidth * 0.5f;
float screenY = screenHeight * 0.5f - (entityY - playerY) * 50.0f / distance; // Масштаб по высоте
return ImVec2(screenX, screenY);
}
// Отрисовка 2D боксов на овцах
void Render2DESP() {
if (!showSheep) return;
ImGuiIO& io = ImGui::GetIO();
float screenWidth = io.DisplaySize.x;
float screenHeight = io.DisplaySize.y;
ImDrawList* drawList = ImGui::GetBackgroundDrawList();
std::lock_guard<std::mutex> lock(entitiesMutex);
for (std::unordered_map<jlong, Entity>::const_iterator it = sheepEntities.begin(); it != sheepEntities.end(); ++it) {
const Entity& sheep = it->second;
// Преобразуем координаты овцы в экранные (верх и низ)
ImVec2 screenPos = WorldToScreenSimple(sheep.x, sheep.y + 1.0f, sheep.z, playerX, playerY, playerZ, screenWidth, screenHeight);
if (screenPos.x < 0 || screenPos.x > screenWidth || screenPos.y < 0 || screenPos.y > screenHeight) continue;
ImVec2 bottomPos = WorldToScreenSimple(sheep.x, sheep.y - 0.5f, sheep.z, playerX, playerY, playerZ, screenWidth, screenHeight);
float height = bottomPos.y - screenPos.y;
float width = height * 0.5f;
// Ограничиваем размеры
if (width < 10.0f) width = 10.0f;
if (height < 20.0f) height = 20.0f;
ImVec2 topLeft(screenPos.x - width / 2, screenPos.y);
ImVec2 bottomRight(screenPos.x + width / 2, screenPos.y + height);
// Рисуем красный прямоугольник
drawList->AddRect(topLeft, bottomRight, IM_COL32(255, 0, 0, 255), 0.0f, 0, 2.0f);
}
}
void ShowError(const char* message) {
MessageBoxA(NULL, message, "Error", MB_OK | MB_ICONERROR);
}
jobject getLaunchClassLoader(JNIEnv* env) {
// Получаю Форджовский класс лоадер
}
jint JNICALL Hooked_JNI_GetCreatedJavaVMs(JavaVM** vmBuf, jsize bufLen, jsize* nVMs) {
jint result = original_JNI_GetCreatedJavaVMs(vmBuf, bufLen, nVMs);
if (result == JNI_OK && nVMs && *nVMs > 0) {
g_jvm = vmBuf[0];
}
return result;
}
void initHooks() {
MH_Initialize();
HMODULE jvmModule = GetModuleHandleA("jvm.dll");
HMODULE openglModule = GetModuleHandleW(L"opengl32.dll");
FARPROC target = GetProcAddress(jvmModule, "JNI_GetCreatedJavaVMs");
pSwapBuffers = reinterpret_cast<T_SwapBuffers>(GetProcAddress(openglModule, "wglSwapBuffers"));
MH_CreateHook(target, &Hooked_JNI_GetCreatedJavaVMs, (LPVOID*)&original_JNI_GetCreatedJavaVMs);
MH_CreateHook(pSwapBuffers, mySwapBuffers, reinterpret_cast<void**>(&pSwapBuffers));
MH_EnableHook(MH_ALL_HOOKS);
}
DWORD WINAPI MainThread(LPVOID) {
initHooks();
if (!g_jvm) {
HMODULE jvmModule = GetModuleHandleA("jvm.dll");
if (!jvmModule) return 0;
auto pGetCreatedJavaVMs = (JNI_GetCreatedJavaVMs_t)GetProcAddress(jvmModule, "JNI_GetCreatedJavaVMs");
if (!pGetCreatedJavaVMs) return 0;
JavaVM* tmp[1];
jsize count = 0;
jint res = pGetCreatedJavaVMs(tmp, 1, &count);
if (res == JNI_OK && count > 0) g_jvm = tmp[0];
else return 0;
}
bool attached = false;
jint ret = g_jvm->GetEnv((void**)&g_env, JNI_VERSION_1_6);
if (ret == JNI_EDETACHED) {
if (g_jvm->AttachCurrentThread((void**)&g_env, nullptr) != JNI_OK) {
ShowError("Failed to attach thread to JVM!");
return 0;
}
attached = true;
}
else if (ret != JNI_OK) {
ShowError("Failed to get JNI environment!");
return 0;
}
g_loader = getLaunchClassLoader(g_env);
if (!g_loader) {
ShowError("Failed to get ClassLoader!");
if (attached) g_jvm->DetachCurrentThread();
return 0;
}
// Цикл обновления данных об овцах
while (true) {
UpdateEntities(g_env, g_loader);
Sleep(50); // Обновляем примерно 20 раз в секунду
}
if (attached) g_jvm->DetachCurrentThread();
return 0;
}
void RenderMain() {
if (ImGui::Begin("ESP Settings")) {
ImGui::Checkbox("ESP Sheep", &showSheep);
}
ImGui::End();
if (showSheep) {
Render2DESP();
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls(hModule);
HANDLE hThread = CreateThread(nullptr, 0, MainThread, nullptr, 0, nullptr);
if (hThread) CloseHandle(hThread);
}
else if (ul_reason_for_call == DLL_PROCESS_DETACH) {
MH_Uninitialize();
}
return TRUE;
}
bool WorldToScreen(const float* modelview, const float* projection, int viewportWidth, int viewportHeight, const ImVec3& worldPos, ImVec2& screenPos) {
// 4D гомогенные координаты
float clipCoords[4];
// Умножаем точку на матрицу modelview
clipCoords[0] = modelview[0] * worldPos.x + modelview[4] * worldPos.y + modelview[8] * worldPos.z + modelview[12];
clipCoords[1] = modelview[1] * worldPos.x + modelview[5] * worldPos.y + modelview[9] * worldPos.z + modelview[13];
clipCoords[2] = modelview[2] * worldPos.x + modelview[6] * worldPos.y + modelview[10] * worldPos.z + modelview[14];
clipCoords[3] = modelview[3] * worldPos.x + modelview[7] * worldPos.y + modelview[11] * worldPos.z + modelview[15];
// Умножаем на матрицу проекции
float clipCoordsProjected[4];
clipCoordsProjected[0] = projection[0] * clipCoords[0] + projection[4] * clipCoords[1] + projection[8] * clipCoords[2] + projection[12] * clipCoords[3];
clipCoordsProjected[1] = projection[1] * clipCoords[0] + projection[5] * clipCoords[1] + projection[9] * clipCoords[2] + projection[13] * clipCoords[3];
clipCoordsProjected[2] = projection[2] * clipCoords[0] + projection[6] * clipCoords[1] + projection[10] * clipCoords[2] + projection[14] * clipCoords[3];
clipCoordsProjected[3] = -clipCoords[2]; // Перспективное деление
if (clipCoordsProjected[3] < 0.1f) {
return false; // Объект позади камеры или слишком близко
}
// Перспективное деление, преобразование координат в нормализованные координаты устройства
float ndcX = clipCoordsProjected[0] / clipCoordsProjected[3];
float ndcY = clipCoordsProjected[1] / clipCoordsProjected[3];
// Преобразование координат устройства в экранные координаты
screenPos.x = (ndcX + 1.0f) * 0.5f * viewportWidth;
screenPos.y = (1.0f - ndcY) * 0.5f * viewportHeight;
return true;
}
// 4D гомогенные координаты
float clipCoords[4];
// Умножаем точку на матрицу modelview
clipCoords[0] = modelview[0] * worldPos.x + modelview[4] * worldPos.y + modelview[8] * worldPos.z + modelview[12];
clipCoords[1] = modelview[1] * worldPos.x + modelview[5] * worldPos.y + modelview[9] * worldPos.z + modelview[13];
clipCoords[2] = modelview[2] * worldPos.x + modelview[6] * worldPos.y + modelview[10] * worldPos.z + modelview[14];
clipCoords[3] = modelview[3] * worldPos.x + modelview[7] * worldPos.y + modelview[11] * worldPos.z + modelview[15];
// Умножаем на матрицу проекции
float clipCoordsProjected[4];
clipCoordsProjected[0] = projection[0] * clipCoords[0] + projection[4] * clipCoords[1] + projection[8] * clipCoords[2] + projection[12] * clipCoords[3];
clipCoordsProjected[1] = projection[1] * clipCoords[0] + projection[5] * clipCoords[1] + projection[9] * clipCoords[2] + projection[13] * clipCoords[3];
clipCoordsProjected[2] = projection[2] * clipCoords[0] + projection[6] * clipCoords[1] + projection[10] * clipCoords[2] + projection[14] * clipCoords[3];
clipCoordsProjected[3] = -clipCoords[2]; // Перспективное деление
if (clipCoordsProjected[3] < 0.1f) {
return false; // Объект позади камеры или слишком близко
}
// Перспективное деление, преобразование координат в нормализованные координаты устройства
float ndcX = clipCoordsProjected[0] / clipCoordsProjected[3];
float ndcY = clipCoordsProjected[1] / clipCoordsProjected[3];
// Преобразование координат устройства в экранные координаты
screenPos.x = (ndcX + 1.0f) * 0.5f * viewportWidth;
screenPos.y = (1.0f - ndcY) * 0.5f * viewportHeight;
return true;
}
Последнее редактирование: