Вопрос [Решено] 2D ESP на JNI. Рисовка ImGui

Пользователь
Статус
Оффлайн
Регистрация
26 Май 2019
Сообщения
151
Реакции[?]
35
Поинты[?]
17K

Перед прочтением основного контента ниже, пожалуйста, обратите внимание на обновление внутри секции Майна на нашем форуме. У нас появились:

  • бесплатные читы для Майнкрафт — любое использование на свой страх и риск;
  • маркетплейс Майнкрафт — абсолютно любая коммерция, связанная с игрой, за исключением продажи читов (аккаунты, предоставления услуг, поиск кодеров читов и так далее);
  • приватные читы для Minecraft — в этом разделе только платные хаки для игры, покупайте группу "Продавец" и выставляйте на продажу свой софт;
  • обсуждения и гайды — всё тот же раздел с вопросами, но теперь модернизированный: поиск нужных хаков, пати с игроками-читерами и другая полезная информация.

Спасибо!

Привет. Прошу помочь с отрисовкой 2D ESP на entity (как пример, хотел отрисовывать на овцах). Координаты овец получаю. Свои тоже получаю. Скорее всего проблема в WorldToScreen, но я не понимаю что тут фиксить нужно. Пытался через ChatGPT платный сделать, она мне хуйню всякую советует. Вот пришёл сюда. Скриншот прилагаю.

[Minecraft 1.7.10 Forge]

1742409692023.png
#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;
}
Возможно этот WorldToScreen сработает, но я не знаю как его вставить в свой код, так как я просто паcтер.
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;
}
 
Последнее редактирование:
Начинающий
Статус
Оффлайн
Регистрация
29 Июл 2023
Сообщения
44
Реакции[?]
2
Поинты[?]
2K
привет я в душе не знаю эти плюсы если не ошибаюсь

но вот что мне выдал другой ии хз попробуй этот полный код


Попробуй это:
#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;

// Структура для 3D координат
struct ImVec3 {
    float x, y, z;
    ImVec3(float _x = 0.0f, float _y = 0.0f, float _z = 0.0f) : x(_x), y(_y), z(_z) {}
};

// Глобальные переменные
JNIEnv* g_env = nullptr;
jobject g_loader = nullptr;
JavaVM* g_jvm = nullptr;

// Матрицы и состояние для ESP
float g_modelViewMatrix[16] = {0};
float g_projectionMatrix[16] = {0};
bool g_matricesInitialized = false;
int g_viewportWidth = 0;
int g_viewportHeight = 0;

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;
bool showDistance = true;
ImColor espColor = ImColor(255, 0, 0, 255); // Красный

void RenderMain();

// Структура для овец
struct Entity {
    float x, y, z; // Координаты в мире
    float yaw, pitch; // Угол поворота
    float width, height; // Размеры
};

// Глобальные переменные для координат игрока и овец
std::unordered_map<jlong, Entity> sheepEntities;
float playerX = 0.0f, playerY = 0.0f, playerZ = 0.0f;
float playerYaw = 0.0f, playerPitch = 0.0f;
std::mutex entitiesMutex; // Для синхронизации доступа к sheepEntities

// Глобальная переменная для хранения getJVMFindClass
typedef jclass ([I]getJVMFindClass_t)(JNIEnv[/I], const char*, jboolean, jobject, jboolean);
getJVMFindClass_t getJVMFindClass = nullptr;

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);
}

// Получение матриц из LWJGL
bool GetMinecraftMatrices(JNIEnv* env, jobject loader) {
    if (!env || !loader || !getJVMFindClass) return false;
    
    // Найдем класс LWJGL GL11
    jclass gl11Class = getJVMFindClass(env, "org/lwjgl/opengl/GL11", JNI_TRUE, loader, JNI_FALSE);
    if (!gl11Class) return false;
    
    // Находим bufferutils для создания буферов
    jclass bufferUtilsClass = getJVMFindClass(env, "org/lwjgl/BufferUtils", JNI_TRUE, loader, JNI_FALSE);
    if (!bufferUtilsClass) return false;
    
    // Находим класс FloatBuffer
    jclass floatBufferClass = env->FindClass("java/nio/FloatBuffer");
    if (!floatBufferClass) return false;
    
    // Получаем размеры viewport
    jmethodID glGetIntegerMethod = env->GetStaticMethodID(gl11Class, "glGetInteger", "(I)I");
    if (!glGetIntegerMethod) return false;
    
    // GL_VIEWPORT = 0x0BA2
    jint GL_VIEWPORT = 0x0BA2;
    
    // Создаем буфер для viewport
    jmethodID createIntBufferMethod = env->GetStaticMethodID(bufferUtilsClass, "createIntBuffer", "(I)Ljava/nio/IntBuffer;");
    if (!createIntBufferMethod) return false;
    jobject viewportBuffer = env->CallStaticObjectMethod(bufferUtilsClass, createIntBufferMethod, 16);
    
    // Получаем viewport
    jmethodID glGetIntegervMethod = env->GetStaticMethodID(gl11Class, "glGetIntegerv", "(ILjava/nio/IntBuffer;)V");
    if (!glGetIntegervMethod) return false;
    env->CallStaticVoidMethod(gl11Class, glGetIntegervMethod, GL_VIEWPORT, viewportBuffer);
    
    // Получаем размеры viewport
    jclass intBufferClass = env->FindClass("java/nio/IntBuffer");
    if (!intBufferClass) return false;
    jmethodID getMethod = env->GetMethodID(intBufferClass, "get", "(I)I");
    if (!getMethod) return false;
    
    g_viewportWidth = env->CallIntMethod(viewportBuffer, getMethod, 2);
    g_viewportHeight = env->CallIntMethod(viewportBuffer, getMethod, 3);
    
    // Методы для получения матриц
    jmethodID createFloatBufferMethod = env->GetStaticMethodID(bufferUtilsClass, "createFloatBuffer", "(I)Ljava/nio/FloatBuffer;");
    if (!createFloatBufferMethod) return false;
    
    // Создаем буферы для матриц
    jobject modelViewBuffer = env->CallStaticObjectMethod(bufferUtilsClass, createFloatBufferMethod, 16);
    jobject projectionBuffer = env->CallStaticObjectMethod(bufferUtilsClass, createFloatBufferMethod, 16);
    
    // Получаем метод для glGetFloat
    jmethodID glGetFloatMethod = env->GetStaticMethodID(gl11Class, "glGetFloat", "(ILjava/nio/FloatBuffer;)V");
    if (!glGetFloatMethod) return false;
    
    // Константы для матриц в OpenGL
    jint GL_MODELVIEW_MATRIX = 0x0BA6;
    jint GL_PROJECTION_MATRIX = 0x0BA7;
    
    // Получаем матрицы
    env->CallStaticVoidMethod(gl11Class, glGetFloatMethod, GL_MODELVIEW_MATRIX, modelViewBuffer);
    env->CallStaticVoidMethod(gl11Class, glGetFloatMethod, GL_PROJECTION_MATRIX, projectionBuffer);
    
    // Получаем метод get для FloatBuffer
    jmethodID getFloatMethod = env->GetMethodID(floatBufferClass, "get", "(I)F");
    if (!getFloatMethod) return false;
    
    // Извлекаем матрицы
    for (int i = 0; i < 16; i++) {
        g_modelViewMatrix[i] = env->CallFloatMethod(modelViewBuffer, getFloatMethod, i);
        g_projectionMatrix[i] = env->CallFloatMethod(projectionBuffer, getFloatMethod, i);
    }
    
    g_matricesInitialized = true;
    return true;
}

BOOL __stdcall mySwapBuffers(HDC hDC)
{
    InitOpenGL2(hDC, &initImGui, nullptr);
    RenderOpenGL2(g_WglContext, hDC, RenderWin32, RenderMain, nullptr);
    return pSwapBuffers(hDC);
}

// Улучшенная функция WorldToScreen
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] = projection[3] * clipCoords[0] + projection[7] * clipCoords[1] + projection[11] * clipCoords[2] + projection[15] * clipCoords[3];
    
    // Проверка, находится ли объект перед камерой
    if (clipCoordsProjected[3] < 0.1f) {
        return false; // Объект позади камеры или слишком близко
    }
    
    // Перспективное деление
    float ndcX = clipCoordsProjected[0] / clipCoordsProjected[3];
    float ndcY = clipCoordsProjected[1] / clipCoordsProjected[3];
    float ndcZ = clipCoordsProjected[2] / clipCoordsProjected[3];
    
    // Проверка, находится ли объект в пределах видимой области
    if (ndcX < -1.0f || ndcX > 1.0f || ndcY < -1.0f || ndcY > 1.0f) {
        return false; // Объект вне видимой области
    }
    
    // Преобразование в экранные координаты
    screenPos.x = (ndcX + 1.0f) * 0.5f * viewportWidth;
    screenPos.y = (1.0f - (ndcY + 1.0f) * 0.5f) * viewportHeight;
    
    return true;
}

// Получаем координаты игрока и овец (вызывается в 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
    jfieldID rotYawField = env->GetFieldID(entityClass, "field_70177_z", "F"); // rotationYaw
    jfieldID rotPitchField = env->GetFieldID(entityClass, "field_70125_A", "F"); // rotationPitch
    if (!posXField || !posYField || !posZField || !rotYawField || !rotPitchField) return;
    
    playerX = (float)env->GetDoubleField(player, posXField);
    playerY = (float)env->GetDoubleField(player, posYField);
    playerZ = (float)env->GetDoubleField(player, posZField);
    playerYaw = env->GetFloatField(player, rotYawField);
    playerPitch = env->GetFloatField(player, rotPitchField);

    // Получаем мир
    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;

    // Получаем ширину и высоту сущности
    jfieldID widthField = env->GetFieldID(entityClass, "field_70130_N", "F"); // width
    jfieldID heightField = env->GetFieldID(entityClass, "field_70131_O", "F"); // height
    if (!widthField || !heightField) 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);
        jfloat yaw = env->GetFloatField(entity, rotYawField);
        jfloat pitch = env->GetFloatField(entity, rotPitchField);
        jfloat width = env->GetFloatField(entity, widthField);
        jfloat height = env->GetFloatField(entity, heightField);
        jint entityId = env->CallIntMethod(entity, getEntityIdMethod);

        Entity entityInfo;
        entityInfo.x = (float)x;
        entityInfo.y = (float)y;
        entityInfo.z = (float)z;
        entityInfo.yaw = yaw;
        entityInfo.pitch = pitch;
        entityInfo.width = width;
        entityInfo.height = height;

        tempEntities[entityId] = entityInfo;
    }

    // Безопасно обновляем глобальную переменную
    std::lock_guard<std::mutex> lock(entitiesMutex);
    sheepEntities = std::move(tempEntities);
    
    // Обновляем матрицы, если нужно отображать ESP
    if (showSheep) {
        GetMinecraftMatrices(env, loader);
    }
}

// Обновленная функция отрисовки ESP
void Render2DESP() {
    if (!showSheep || !g_matricesInitialized) return;

    ImGuiIO& io = ImGui::GetIO();
    float screenWidth = io.DisplaySize.x;
    float screenHeight = io.DisplaySize.y;

    // Если размеры viewport'а не получены, используем размеры ImGui окна
    if (g_viewportWidth <= 0 || g_viewportHeight <= 0) {
        g_viewportWidth = (int)screenWidth;
        g_viewportHeight = (int)screenHeight;
    }

    ImDrawList* drawList = ImGui::GetBackgroundDrawList();

    std::lock_guard<std::mutex> lock(entitiesMutex);
    for (const auto& pair : sheepEntities) {
        const Entity& sheep = pair.second;
        
        // Создаем точки верха и низа овцы (с учетом её высоты)
        ImVec3 topPos(sheep.x, sheep.y + sheep.height, sheep.z);
        ImVec3 bottomPos(sheep.x, sheep.y, sheep.z);
        
        // Преобразуем в экранные координаты
        ImVec2 screenTop, screenBottom;
        bool topVisible = WorldToScreen(g_modelViewMatrix, g_projectionMatrix, g_viewportWidth, g_viewportHeight, topPos, screenTop);
        bool bottomVisible = WorldToScreen(g_modelViewMatrix, g_projectionMatrix, g_viewportWidth, g_viewportHeight, bottomPos, screenBottom);
        
        // Если хотя бы одна из точек видима, рисуем ESP
        if (topVisible || bottomVisible) {
            // Если верхняя точка не видна, предполагаем, что она выше экрана
            if (!topVisible) {
                screenTop.x = screenBottom.x;
                screenTop.y = 0;
            }
            
            // Если нижняя точка не видна, предполагаем, что она ниже экрана
            if (!bottomVisible) {
                screenBottom.x = screenTop.x;
                screenBottom.y = screenHeight;
            }
            
            float height = screenBottom.y - screenTop.y;
            float width = height * 0.5f;
            
            // Ограничиваем минимальные размеры бокса
            if (width < 10.0f) width = 10.0f;
            if (height < 20.0f) height = 20.0f;
            
            // Рассчитываем позицию и размеры бокса
            ImVec2 boxTopLeft(screenTop.x - width * 0.5f, screenTop.y);
            ImVec2 boxBottomRight(screenTop.x + width * 0.5f, screenBottom.y);
            
            // Рисуем прямоугольник с выбранным цветом
            drawList->AddRect(boxTopLeft, boxBottomRight, espColor, 0.0f, 0, 2.0f);
            
            // Опционально отображаем расстояние
            if (showDistance) {
                float distance = sqrt(
                    (sheep.x - playerX) * (sheep.x - playerX) +
                    (sheep.y - playerY) * (sheep.y - playerY) +
                    (sheep.z - playerZ) * (sheep.z - playerZ)
                );
                
                char distText[32];
                sprintf_s(distText, "%.1fm", distance);
                ImVec2 textPos(boxTopLeft.x, boxTopLeft.y - 15);
                drawList->AddText(textPos, IM_COL32(255, 255, 255, 255), distText);
            }
        }
    }
}

void ShowError(const char* message) {
    MessageBoxA(NULL, message, "Error", MB_OK | MB_ICONERROR);
}

// Функция для получения LaunchClassLoader
jobject getLaunchClassLoader(JNIEnv* env) {
    // Сначала пытаемся найти класс Launch
    jclass launchClass = env->FindClass("net/minecraft/launchwrapper/Launch");
    if (!launchClass) {
        // Если не нашли, возможно, мы не на правильном classpath
        return nullptr;
    }
    
    // Получаем статическое поле classLoader
    jfieldID classLoaderField = env->GetStaticFieldID(launchClass, "classLoader", "Lnet/minecraft/launchwrapper/LaunchClassLoader;");
    if (!classLoaderField) {
        return nullptr;
    }
    
    // Получаем объект classLoader
    jobject classLoader = env->GetStaticObjectField(launchClass, classLoaderField);
    return classLoader;
}

// Ищем класс для Forge Minecraft
jclass findForgeClass(JNIEnv* env, const char* name) {
    jclass clazz = env->FindClass(name);
    if (clazz) return clazz;
    
    // Если не нашли напрямую, пытаемся через classLoader
    jobject classLoader = getLaunchClassLoader(env);
    if (!classLoader) return nullptr;
    
    // Получаем метод findClass в LaunchClassLoader
    jclass classLoaderClass = env->GetObjectClass(classLoader);
    jmethodID findClassMethod = env->GetMethodID(classLoaderClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
    if (!findClassMethod) return nullptr;
    
    // Вызываем findClass
    jstring className = env->NewStringUTF(name);
    jclass result = (jclass)env->CallObjectMethod(classLoader, findClassMethod, className);
    env->DeleteLocalRef(className);
    
    return result;
}

// Обертка для поиска класса через Forge LaunchClassLoader
jclass getJVMFindClass(JNIEnv* env, const char* name, jboolean initialize, jobject loader, jboolean ignoreError) {
    return findForgeClass(env, name);
}

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");
    
    if (!jvmModule || !openglModule) {
        ShowError("Не удалось найти необходимые модули");
        return;
    }
    
    FARPROC target = GetProcAddress(jvmModule, "JNI_GetCreatedJavaVMs");
    pSwapBuffers = reinterpret_cast<T_SwapBuffers>(GetProcAddress(openglModule, "wglSwapBuffers"));
    
    if (!target || !pSwapBuffers) {
        ShowError("Не удалось найти необходимые функции");
        return;
    }
    
    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) {
    // Инициализируем функцию поиска классов
    getJVMFindClass = &::getJVMFindClass;
    
    initHooks();

    if (!g_jvm) {
        HMODULE jvmModule = GetModuleHandleA("jvm.dll");
        if (!jvmModule) {
            ShowError("Не удалось получить jvm.dll");
            return 0;
        }
        
        auto pGetCreatedJavaVMs = (JNI_GetCreatedJavaVMs_t)GetProcAddress(jvmModule, "JNI_GetCreatedJavaVMs");
        if (!pGetCreatedJavaVMs) {
            ShowError("Не удалось найти JNI_GetCreatedJavaVMs");
            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 {
            ShowError("Не удалось получить JavaVM");
            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;
    }
    
    // Делаем g_loader глобальной ссылкой, чтобы она не была освобождена сборщиком мусора
    g_loader = g_env->NewGlobalRef(g_loader);

    // Цикл обновления данных об овцах
    while (true) {
        UpdateEntities(g_env, g_loader);
        Sleep(50); // Обновляем примерно 20 раз в секунду
    }

    if (g_loader) {
        g_env->DeleteGlobalRef(g_loader);
        g_loader = nullptr;
    }
    
    if (attached) g_jvm->DetachCurrentThread();
    return 0;
}

void RenderMain() {
    // Обработка нажатия клавиши Insert для открытия/закрытия меню
    if (GetAsyncKeyState(VK_INSERT) & 1) {
        menu = !menu;
    }
    
    // Отрисовка ESP в любом случае, даже если меню закрыто
    if (showSheep) {
        Render2DESP();
    }
    
    // Отрисовка меню только если оно открыто
    if (menu) {
        ImGui::Begin("ESP Settings", &menu);
        
        // Чекбокс для включения/выключения ESP
        ImGui::Checkbox("ESP Sheep", &showSheep);
        
        // Чекбокс для отображения расстояния
        ImGui::Checkbox("Show Distance", &showDistance);
        
        // Выбор цвета для ESP
        ImGui::ColorEdit4("ESP Color", (float*)&espColor);
        
        // Дополнительная информация
        ImGui::Separator();
        ImGui::Text("Game Info:");
        ImGui::Text("Player Pos: %.1f, %.1f, %.1f", playerX, playerY, playerZ);
        ImGui::Text("Player Rotation: %.1f, %.1f", playerYaw, playerPitch);
        ImGui::Text("Sheep Count: %d", (int)sheepEntities.size());
        ImGui::Text("Matrices Initialized: %s", g_matricesInitialized ? "Yes" : "No");
        
        ImGui::End();
    }
}

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;
}
 
Начинающий
Статус
Онлайн
Регистрация
22 Окт 2022
Сообщения
12
Реакции[?]
0
Поинты[?]
0
привет я в душе не знаю эти плюсы если не ошибаюсь

но вот что мне выдал другой ии хз попробуй этот полный код


Попробуй это:
#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;

// Структура для 3D координат
struct ImVec3 {
    float x, y, z;
    ImVec3(float _x = 0.0f, float _y = 0.0f, float _z = 0.0f) : x(_x), y(_y), z(_z) {}
};

// Глобальные переменные
JNIEnv* g_env = nullptr;
jobject g_loader = nullptr;
JavaVM* g_jvm = nullptr;

// Матрицы и состояние для ESP
float g_modelViewMatrix[16] = {0};
float g_projectionMatrix[16] = {0};
bool g_matricesInitialized = false;
int g_viewportWidth = 0;
int g_viewportHeight = 0;

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;
bool showDistance = true;
ImColor espColor = ImColor(255, 0, 0, 255); // Красный

void RenderMain();

// Структура для овец
struct Entity {
    float x, y, z; // Координаты в мире
    float yaw, pitch; // Угол поворота
    float width, height; // Размеры
};

// Глобальные переменные для координат игрока и овец
std::unordered_map<jlong, Entity> sheepEntities;
float playerX = 0.0f, playerY = 0.0f, playerZ = 0.0f;
float playerYaw = 0.0f, playerPitch = 0.0f;
std::mutex entitiesMutex; // Для синхронизации доступа к sheepEntities

// Глобальная переменная для хранения getJVMFindClass
typedef jclass ([I]getJVMFindClass_t)(JNIEnv[/I], const char*, jboolean, jobject, jboolean);
getJVMFindClass_t getJVMFindClass = nullptr;

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);
}

// Получение матриц из LWJGL
bool GetMinecraftMatrices(JNIEnv* env, jobject loader) {
    if (!env || !loader || !getJVMFindClass) return false;
   
    // Найдем класс LWJGL GL11
    jclass gl11Class = getJVMFindClass(env, "org/lwjgl/opengl/GL11", JNI_TRUE, loader, JNI_FALSE);
    if (!gl11Class) return false;
   
    // Находим bufferutils для создания буферов
    jclass bufferUtilsClass = getJVMFindClass(env, "org/lwjgl/BufferUtils", JNI_TRUE, loader, JNI_FALSE);
    if (!bufferUtilsClass) return false;
   
    // Находим класс FloatBuffer
    jclass floatBufferClass = env->FindClass("java/nio/FloatBuffer");
    if (!floatBufferClass) return false;
   
    // Получаем размеры viewport
    jmethodID glGetIntegerMethod = env->GetStaticMethodID(gl11Class, "glGetInteger", "(I)I");
    if (!glGetIntegerMethod) return false;
   
    // GL_VIEWPORT = 0x0BA2
    jint GL_VIEWPORT = 0x0BA2;
   
    // Создаем буфер для viewport
    jmethodID createIntBufferMethod = env->GetStaticMethodID(bufferUtilsClass, "createIntBuffer", "(I)Ljava/nio/IntBuffer;");
    if (!createIntBufferMethod) return false;
    jobject viewportBuffer = env->CallStaticObjectMethod(bufferUtilsClass, createIntBufferMethod, 16);
   
    // Получаем viewport
    jmethodID glGetIntegervMethod = env->GetStaticMethodID(gl11Class, "glGetIntegerv", "(ILjava/nio/IntBuffer;)V");
    if (!glGetIntegervMethod) return false;
    env->CallStaticVoidMethod(gl11Class, glGetIntegervMethod, GL_VIEWPORT, viewportBuffer);
   
    // Получаем размеры viewport
    jclass intBufferClass = env->FindClass("java/nio/IntBuffer");
    if (!intBufferClass) return false;
    jmethodID getMethod = env->GetMethodID(intBufferClass, "get", "(I)I");
    if (!getMethod) return false;
   
    g_viewportWidth = env->CallIntMethod(viewportBuffer, getMethod, 2);
    g_viewportHeight = env->CallIntMethod(viewportBuffer, getMethod, 3);
   
    // Методы для получения матриц
    jmethodID createFloatBufferMethod = env->GetStaticMethodID(bufferUtilsClass, "createFloatBuffer", "(I)Ljava/nio/FloatBuffer;");
    if (!createFloatBufferMethod) return false;
   
    // Создаем буферы для матриц
    jobject modelViewBuffer = env->CallStaticObjectMethod(bufferUtilsClass, createFloatBufferMethod, 16);
    jobject projectionBuffer = env->CallStaticObjectMethod(bufferUtilsClass, createFloatBufferMethod, 16);
   
    // Получаем метод для glGetFloat
    jmethodID glGetFloatMethod = env->GetStaticMethodID(gl11Class, "glGetFloat", "(ILjava/nio/FloatBuffer;)V");
    if (!glGetFloatMethod) return false;
   
    // Константы для матриц в OpenGL
    jint GL_MODELVIEW_MATRIX = 0x0BA6;
    jint GL_PROJECTION_MATRIX = 0x0BA7;
   
    // Получаем матрицы
    env->CallStaticVoidMethod(gl11Class, glGetFloatMethod, GL_MODELVIEW_MATRIX, modelViewBuffer);
    env->CallStaticVoidMethod(gl11Class, glGetFloatMethod, GL_PROJECTION_MATRIX, projectionBuffer);
   
    // Получаем метод get для FloatBuffer
    jmethodID getFloatMethod = env->GetMethodID(floatBufferClass, "get", "(I)F");
    if (!getFloatMethod) return false;
   
    // Извлекаем матрицы
    for (int i = 0; i < 16; i++) {
        g_modelViewMatrix[i] = env->CallFloatMethod(modelViewBuffer, getFloatMethod, i);
        g_projectionMatrix[i] = env->CallFloatMethod(projectionBuffer, getFloatMethod, i);
    }
   
    g_matricesInitialized = true;
    return true;
}

BOOL __stdcall mySwapBuffers(HDC hDC)
{
    InitOpenGL2(hDC, &initImGui, nullptr);
    RenderOpenGL2(g_WglContext, hDC, RenderWin32, RenderMain, nullptr);
    return pSwapBuffers(hDC);
}

// Улучшенная функция WorldToScreen
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] = projection[3] * clipCoords[0] + projection[7] * clipCoords[1] + projection[11] * clipCoords[2] + projection[15] * clipCoords[3];
   
    // Проверка, находится ли объект перед камерой
    if (clipCoordsProjected[3] < 0.1f) {
        return false; // Объект позади камеры или слишком близко
    }
   
    // Перспективное деление
    float ndcX = clipCoordsProjected[0] / clipCoordsProjected[3];
    float ndcY = clipCoordsProjected[1] / clipCoordsProjected[3];
    float ndcZ = clipCoordsProjected[2] / clipCoordsProjected[3];
   
    // Проверка, находится ли объект в пределах видимой области
    if (ndcX < -1.0f || ndcX > 1.0f || ndcY < -1.0f || ndcY > 1.0f) {
        return false; // Объект вне видимой области
    }
   
    // Преобразование в экранные координаты
    screenPos.x = (ndcX + 1.0f) * 0.5f * viewportWidth;
    screenPos.y = (1.0f - (ndcY + 1.0f) * 0.5f) * viewportHeight;
   
    return true;
}

// Получаем координаты игрока и овец (вызывается в 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
    jfieldID rotYawField = env->GetFieldID(entityClass, "field_70177_z", "F"); // rotationYaw
    jfieldID rotPitchField = env->GetFieldID(entityClass, "field_70125_A", "F"); // rotationPitch
    if (!posXField || !posYField || !posZField || !rotYawField || !rotPitchField) return;
   
    playerX = (float)env->GetDoubleField(player, posXField);
    playerY = (float)env->GetDoubleField(player, posYField);
    playerZ = (float)env->GetDoubleField(player, posZField);
    playerYaw = env->GetFloatField(player, rotYawField);
    playerPitch = env->GetFloatField(player, rotPitchField);

    // Получаем мир
    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;

    // Получаем ширину и высоту сущности
    jfieldID widthField = env->GetFieldID(entityClass, "field_70130_N", "F"); // width
    jfieldID heightField = env->GetFieldID(entityClass, "field_70131_O", "F"); // height
    if (!widthField || !heightField) 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);
        jfloat yaw = env->GetFloatField(entity, rotYawField);
        jfloat pitch = env->GetFloatField(entity, rotPitchField);
        jfloat width = env->GetFloatField(entity, widthField);
        jfloat height = env->GetFloatField(entity, heightField);
        jint entityId = env->CallIntMethod(entity, getEntityIdMethod);

        Entity entityInfo;
        entityInfo.x = (float)x;
        entityInfo.y = (float)y;
        entityInfo.z = (float)z;
        entityInfo.yaw = yaw;
        entityInfo.pitch = pitch;
        entityInfo.width = width;
        entityInfo.height = height;

        tempEntities[entityId] = entityInfo;
    }

    // Безопасно обновляем глобальную переменную
    std::lock_guard<std::mutex> lock(entitiesMutex);
    sheepEntities = std::move(tempEntities);
   
    // Обновляем матрицы, если нужно отображать ESP
    if (showSheep) {
        GetMinecraftMatrices(env, loader);
    }
}

// Обновленная функция отрисовки ESP
void Render2DESP() {
    if (!showSheep || !g_matricesInitialized) return;

    ImGuiIO& io = ImGui::GetIO();
    float screenWidth = io.DisplaySize.x;
    float screenHeight = io.DisplaySize.y;

    // Если размеры viewport'а не получены, используем размеры ImGui окна
    if (g_viewportWidth <= 0 || g_viewportHeight <= 0) {
        g_viewportWidth = (int)screenWidth;
        g_viewportHeight = (int)screenHeight;
    }

    ImDrawList* drawList = ImGui::GetBackgroundDrawList();

    std::lock_guard<std::mutex> lock(entitiesMutex);
    for (const auto& pair : sheepEntities) {
        const Entity& sheep = pair.second;
       
        // Создаем точки верха и низа овцы (с учетом её высоты)
        ImVec3 topPos(sheep.x, sheep.y + sheep.height, sheep.z);
        ImVec3 bottomPos(sheep.x, sheep.y, sheep.z);
       
        // Преобразуем в экранные координаты
        ImVec2 screenTop, screenBottom;
        bool topVisible = WorldToScreen(g_modelViewMatrix, g_projectionMatrix, g_viewportWidth, g_viewportHeight, topPos, screenTop);
        bool bottomVisible = WorldToScreen(g_modelViewMatrix, g_projectionMatrix, g_viewportWidth, g_viewportHeight, bottomPos, screenBottom);
       
        // Если хотя бы одна из точек видима, рисуем ESP
        if (topVisible || bottomVisible) {
            // Если верхняя точка не видна, предполагаем, что она выше экрана
            if (!topVisible) {
                screenTop.x = screenBottom.x;
                screenTop.y = 0;
            }
           
            // Если нижняя точка не видна, предполагаем, что она ниже экрана
            if (!bottomVisible) {
                screenBottom.x = screenTop.x;
                screenBottom.y = screenHeight;
            }
           
            float height = screenBottom.y - screenTop.y;
            float width = height * 0.5f;
           
            // Ограничиваем минимальные размеры бокса
            if (width < 10.0f) width = 10.0f;
            if (height < 20.0f) height = 20.0f;
           
            // Рассчитываем позицию и размеры бокса
            ImVec2 boxTopLeft(screenTop.x - width * 0.5f, screenTop.y);
            ImVec2 boxBottomRight(screenTop.x + width * 0.5f, screenBottom.y);
           
            // Рисуем прямоугольник с выбранным цветом
            drawList->AddRect(boxTopLeft, boxBottomRight, espColor, 0.0f, 0, 2.0f);
           
            // Опционально отображаем расстояние
            if (showDistance) {
                float distance = sqrt(
                    (sheep.x - playerX) * (sheep.x - playerX) +
                    (sheep.y - playerY) * (sheep.y - playerY) +
                    (sheep.z - playerZ) * (sheep.z - playerZ)
                );
               
                char distText[32];
                sprintf_s(distText, "%.1fm", distance);
                ImVec2 textPos(boxTopLeft.x, boxTopLeft.y - 15);
                drawList->AddText(textPos, IM_COL32(255, 255, 255, 255), distText);
            }
        }
    }
}

void ShowError(const char* message) {
    MessageBoxA(NULL, message, "Error", MB_OK | MB_ICONERROR);
}

// Функция для получения LaunchClassLoader
jobject getLaunchClassLoader(JNIEnv* env) {
    // Сначала пытаемся найти класс Launch
    jclass launchClass = env->FindClass("net/minecraft/launchwrapper/Launch");
    if (!launchClass) {
        // Если не нашли, возможно, мы не на правильном classpath
        return nullptr;
    }
   
    // Получаем статическое поле classLoader
    jfieldID classLoaderField = env->GetStaticFieldID(launchClass, "classLoader", "Lnet/minecraft/launchwrapper/LaunchClassLoader;");
    if (!classLoaderField) {
        return nullptr;
    }
   
    // Получаем объект classLoader
    jobject classLoader = env->GetStaticObjectField(launchClass, classLoaderField);
    return classLoader;
}

// Ищем класс для Forge Minecraft
jclass findForgeClass(JNIEnv* env, const char* name) {
    jclass clazz = env->FindClass(name);
    if (clazz) return clazz;
   
    // Если не нашли напрямую, пытаемся через classLoader
    jobject classLoader = getLaunchClassLoader(env);
    if (!classLoader) return nullptr;
   
    // Получаем метод findClass в LaunchClassLoader
    jclass classLoaderClass = env->GetObjectClass(classLoader);
    jmethodID findClassMethod = env->GetMethodID(classLoaderClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
    if (!findClassMethod) return nullptr;
   
    // Вызываем findClass
    jstring className = env->NewStringUTF(name);
    jclass result = (jclass)env->CallObjectMethod(classLoader, findClassMethod, className);
    env->DeleteLocalRef(className);
   
    return result;
}

// Обертка для поиска класса через Forge LaunchClassLoader
jclass getJVMFindClass(JNIEnv* env, const char* name, jboolean initialize, jobject loader, jboolean ignoreError) {
    return findForgeClass(env, name);
}

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");
   
    if (!jvmModule || !openglModule) {
        ShowError("Не удалось найти необходимые модули");
        return;
    }
   
    FARPROC target = GetProcAddress(jvmModule, "JNI_GetCreatedJavaVMs");
    pSwapBuffers = reinterpret_cast<T_SwapBuffers>(GetProcAddress(openglModule, "wglSwapBuffers"));
   
    if (!target || !pSwapBuffers) {
        ShowError("Не удалось найти необходимые функции");
        return;
    }
   
    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) {
    // Инициализируем функцию поиска классов
    getJVMFindClass = &::getJVMFindClass;
   
    initHooks();

    if (!g_jvm) {
        HMODULE jvmModule = GetModuleHandleA("jvm.dll");
        if (!jvmModule) {
            ShowError("Не удалось получить jvm.dll");
            return 0;
        }
       
        auto pGetCreatedJavaVMs = (JNI_GetCreatedJavaVMs_t)GetProcAddress(jvmModule, "JNI_GetCreatedJavaVMs");
        if (!pGetCreatedJavaVMs) {
            ShowError("Не удалось найти JNI_GetCreatedJavaVMs");
            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 {
            ShowError("Не удалось получить JavaVM");
            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;
    }
   
    // Делаем g_loader глобальной ссылкой, чтобы она не была освобождена сборщиком мусора
    g_loader = g_env->NewGlobalRef(g_loader);

    // Цикл обновления данных об овцах
    while (true) {
        UpdateEntities(g_env, g_loader);
        Sleep(50); // Обновляем примерно 20 раз в секунду
    }

    if (g_loader) {
        g_env->DeleteGlobalRef(g_loader);
        g_loader = nullptr;
    }
   
    if (attached) g_jvm->DetachCurrentThread();
    return 0;
}

void RenderMain() {
    // Обработка нажатия клавиши Insert для открытия/закрытия меню
    if (GetAsyncKeyState(VK_INSERT) & 1) {
        menu = !menu;
    }
   
    // Отрисовка ESP в любом случае, даже если меню закрыто
    if (showSheep) {
        Render2DESP();
    }
   
    // Отрисовка меню только если оно открыто
    if (menu) {
        ImGui::Begin("ESP Settings", &menu);
       
        // Чекбокс для включения/выключения ESP
        ImGui::Checkbox("ESP Sheep", &showSheep);
       
        // Чекбокс для отображения расстояния
        ImGui::Checkbox("Show Distance", &showDistance);
       
        // Выбор цвета для ESP
        ImGui::ColorEdit4("ESP Color", (float*)&espColor);
       
        // Дополнительная информация
        ImGui::Separator();
        ImGui::Text("Game Info:");
        ImGui::Text("Player Pos: %.1f, %.1f, %.1f", playerX, playerY, playerZ);
        ImGui::Text("Player Rotation: %.1f, %.1f", playerYaw, playerPitch);
        ImGui::Text("Sheep Count: %d", (int)sheepEntities.size());
        ImGui::Text("Matrices Initialized: %s", g_matricesInitialized ? "Yes" : "No");
       
        ImGui::End();
    }
}

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;
}
У меня есть фикс этого же кода только:
  • Убраны повторяющиеся проверки на nullptr и оптимизированы ветвления.
  • Сокращены повторные вызовы FindClass и GetMethodID, кэшируя их результаты.
  • Уменьшено количество вызовов ImGui и упрощена логика WorldToScreen.
  • Использованы более эффективные структуры данных и синхронизация.
  • Убраны закомментированные участки и неиспользуемые переменные.
  • Заменил магические числа и упростил макросы.
 
Начинающий
Статус
Оффлайн
Регистрация
23 Май 2023
Сообщения
70
Реакции[?]
11
Поинты[?]
11K
У меня есть фикс этого же кода только:
  • Убраны повторяющиеся проверки на nullptr и оптимизированы ветвления.
  • Сокращены повторные вызовы FindClass и GetMethodID, кэшируя их результаты.
  • Уменьшено количество вызовов ImGui и упрощена логика WorldToScreen.
  • Использованы более эффективные структуры данных и синхронизация.
  • Убраны закомментированные участки и неиспользуемые переменные.
  • Заменил магические числа и упростил макросы.
ai coding 🗣🗣🗣
 
Начинающий
Статус
Онлайн
Регистрация
22 Окт 2022
Сообщения
12
Реакции[?]
0
Поинты[?]
0
привет я в душе не знаю эти плюсы если не ошибаюсь

но вот что мне выдал другой ии хз попробуй этот полный код


Попробуй это:
#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;

// Структура для 3D координат
struct ImVec3 {
    float x, y, z;
    ImVec3(float _x = 0.0f, float _y = 0.0f, float _z = 0.0f) : x(_x), y(_y), z(_z) {}
};

// Глобальные переменные
JNIEnv* g_env = nullptr;
jobject g_loader = nullptr;
JavaVM* g_jvm = nullptr;

// Матрицы и состояние для ESP
float g_modelViewMatrix[16] = {0};
float g_projectionMatrix[16] = {0};
bool g_matricesInitialized = false;
int g_viewportWidth = 0;
int g_viewportHeight = 0;

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;
bool showDistance = true;
ImColor espColor = ImColor(255, 0, 0, 255); // Красный

void RenderMain();

// Структура для овец
struct Entity {
    float x, y, z; // Координаты в мире
    float yaw, pitch; // Угол поворота
    float width, height; // Размеры
};

// Глобальные переменные для координат игрока и овец
std::unordered_map<jlong, Entity> sheepEntities;
float playerX = 0.0f, playerY = 0.0f, playerZ = 0.0f;
float playerYaw = 0.0f, playerPitch = 0.0f;
std::mutex entitiesMutex; // Для синхронизации доступа к sheepEntities

// Глобальная переменная для хранения getJVMFindClass
typedef jclass ([I]getJVMFindClass_t)(JNIEnv[/I], const char*, jboolean, jobject, jboolean);
getJVMFindClass_t getJVMFindClass = nullptr;

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);
}

// Получение матриц из LWJGL
bool GetMinecraftMatrices(JNIEnv* env, jobject loader) {
    if (!env || !loader || !getJVMFindClass) return false;
   
    // Найдем класс LWJGL GL11
    jclass gl11Class = getJVMFindClass(env, "org/lwjgl/opengl/GL11", JNI_TRUE, loader, JNI_FALSE);
    if (!gl11Class) return false;
   
    // Находим bufferutils для создания буферов
    jclass bufferUtilsClass = getJVMFindClass(env, "org/lwjgl/BufferUtils", JNI_TRUE, loader, JNI_FALSE);
    if (!bufferUtilsClass) return false;
   
    // Находим класс FloatBuffer
    jclass floatBufferClass = env->FindClass("java/nio/FloatBuffer");
    if (!floatBufferClass) return false;
   
    // Получаем размеры viewport
    jmethodID glGetIntegerMethod = env->GetStaticMethodID(gl11Class, "glGetInteger", "(I)I");
    if (!glGetIntegerMethod) return false;
   
    // GL_VIEWPORT = 0x0BA2
    jint GL_VIEWPORT = 0x0BA2;
   
    // Создаем буфер для viewport
    jmethodID createIntBufferMethod = env->GetStaticMethodID(bufferUtilsClass, "createIntBuffer", "(I)Ljava/nio/IntBuffer;");
    if (!createIntBufferMethod) return false;
    jobject viewportBuffer = env->CallStaticObjectMethod(bufferUtilsClass, createIntBufferMethod, 16);
   
    // Получаем viewport
    jmethodID glGetIntegervMethod = env->GetStaticMethodID(gl11Class, "glGetIntegerv", "(ILjava/nio/IntBuffer;)V");
    if (!glGetIntegervMethod) return false;
    env->CallStaticVoidMethod(gl11Class, glGetIntegervMethod, GL_VIEWPORT, viewportBuffer);
   
    // Получаем размеры viewport
    jclass intBufferClass = env->FindClass("java/nio/IntBuffer");
    if (!intBufferClass) return false;
    jmethodID getMethod = env->GetMethodID(intBufferClass, "get", "(I)I");
    if (!getMethod) return false;
   
    g_viewportWidth = env->CallIntMethod(viewportBuffer, getMethod, 2);
    g_viewportHeight = env->CallIntMethod(viewportBuffer, getMethod, 3);
   
    // Методы для получения матриц
    jmethodID createFloatBufferMethod = env->GetStaticMethodID(bufferUtilsClass, "createFloatBuffer", "(I)Ljava/nio/FloatBuffer;");
    if (!createFloatBufferMethod) return false;
   
    // Создаем буферы для матриц
    jobject modelViewBuffer = env->CallStaticObjectMethod(bufferUtilsClass, createFloatBufferMethod, 16);
    jobject projectionBuffer = env->CallStaticObjectMethod(bufferUtilsClass, createFloatBufferMethod, 16);
   
    // Получаем метод для glGetFloat
    jmethodID glGetFloatMethod = env->GetStaticMethodID(gl11Class, "glGetFloat", "(ILjava/nio/FloatBuffer;)V");
    if (!glGetFloatMethod) return false;
   
    // Константы для матриц в OpenGL
    jint GL_MODELVIEW_MATRIX = 0x0BA6;
    jint GL_PROJECTION_MATRIX = 0x0BA7;
   
    // Получаем матрицы
    env->CallStaticVoidMethod(gl11Class, glGetFloatMethod, GL_MODELVIEW_MATRIX, modelViewBuffer);
    env->CallStaticVoidMethod(gl11Class, glGetFloatMethod, GL_PROJECTION_MATRIX, projectionBuffer);
   
    // Получаем метод get для FloatBuffer
    jmethodID getFloatMethod = env->GetMethodID(floatBufferClass, "get", "(I)F");
    if (!getFloatMethod) return false;
   
    // Извлекаем матрицы
    for (int i = 0; i < 16; i++) {
        g_modelViewMatrix[i] = env->CallFloatMethod(modelViewBuffer, getFloatMethod, i);
        g_projectionMatrix[i] = env->CallFloatMethod(projectionBuffer, getFloatMethod, i);
    }
   
    g_matricesInitialized = true;
    return true;
}

BOOL __stdcall mySwapBuffers(HDC hDC)
{
    InitOpenGL2(hDC, &initImGui, nullptr);
    RenderOpenGL2(g_WglContext, hDC, RenderWin32, RenderMain, nullptr);
    return pSwapBuffers(hDC);
}

// Улучшенная функция WorldToScreen
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] = projection[3] * clipCoords[0] + projection[7] * clipCoords[1] + projection[11] * clipCoords[2] + projection[15] * clipCoords[3];
   
    // Проверка, находится ли объект перед камерой
    if (clipCoordsProjected[3] < 0.1f) {
        return false; // Объект позади камеры или слишком близко
    }
   
    // Перспективное деление
    float ndcX = clipCoordsProjected[0] / clipCoordsProjected[3];
    float ndcY = clipCoordsProjected[1] / clipCoordsProjected[3];
    float ndcZ = clipCoordsProjected[2] / clipCoordsProjected[3];
   
    // Проверка, находится ли объект в пределах видимой области
    if (ndcX < -1.0f || ndcX > 1.0f || ndcY < -1.0f || ndcY > 1.0f) {
        return false; // Объект вне видимой области
    }
   
    // Преобразование в экранные координаты
    screenPos.x = (ndcX + 1.0f) * 0.5f * viewportWidth;
    screenPos.y = (1.0f - (ndcY + 1.0f) * 0.5f) * viewportHeight;
   
    return true;
}

// Получаем координаты игрока и овец (вызывается в 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
    jfieldID rotYawField = env->GetFieldID(entityClass, "field_70177_z", "F"); // rotationYaw
    jfieldID rotPitchField = env->GetFieldID(entityClass, "field_70125_A", "F"); // rotationPitch
    if (!posXField || !posYField || !posZField || !rotYawField || !rotPitchField) return;
   
    playerX = (float)env->GetDoubleField(player, posXField);
    playerY = (float)env->GetDoubleField(player, posYField);
    playerZ = (float)env->GetDoubleField(player, posZField);
    playerYaw = env->GetFloatField(player, rotYawField);
    playerPitch = env->GetFloatField(player, rotPitchField);

    // Получаем мир
    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;

    // Получаем ширину и высоту сущности
    jfieldID widthField = env->GetFieldID(entityClass, "field_70130_N", "F"); // width
    jfieldID heightField = env->GetFieldID(entityClass, "field_70131_O", "F"); // height
    if (!widthField || !heightField) 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);
        jfloat yaw = env->GetFloatField(entity, rotYawField);
        jfloat pitch = env->GetFloatField(entity, rotPitchField);
        jfloat width = env->GetFloatField(entity, widthField);
        jfloat height = env->GetFloatField(entity, heightField);
        jint entityId = env->CallIntMethod(entity, getEntityIdMethod);

        Entity entityInfo;
        entityInfo.x = (float)x;
        entityInfo.y = (float)y;
        entityInfo.z = (float)z;
        entityInfo.yaw = yaw;
        entityInfo.pitch = pitch;
        entityInfo.width = width;
        entityInfo.height = height;

        tempEntities[entityId] = entityInfo;
    }

    // Безопасно обновляем глобальную переменную
    std::lock_guard<std::mutex> lock(entitiesMutex);
    sheepEntities = std::move(tempEntities);
   
    // Обновляем матрицы, если нужно отображать ESP
    if (showSheep) {
        GetMinecraftMatrices(env, loader);
    }
}

// Обновленная функция отрисовки ESP
void Render2DESP() {
    if (!showSheep || !g_matricesInitialized) return;

    ImGuiIO& io = ImGui::GetIO();
    float screenWidth = io.DisplaySize.x;
    float screenHeight = io.DisplaySize.y;

    // Если размеры viewport'а не получены, используем размеры ImGui окна
    if (g_viewportWidth <= 0 || g_viewportHeight <= 0) {
        g_viewportWidth = (int)screenWidth;
        g_viewportHeight = (int)screenHeight;
    }

    ImDrawList* drawList = ImGui::GetBackgroundDrawList();

    std::lock_guard<std::mutex> lock(entitiesMutex);
    for (const auto& pair : sheepEntities) {
        const Entity& sheep = pair.second;
       
        // Создаем точки верха и низа овцы (с учетом её высоты)
        ImVec3 topPos(sheep.x, sheep.y + sheep.height, sheep.z);
        ImVec3 bottomPos(sheep.x, sheep.y, sheep.z);
       
        // Преобразуем в экранные координаты
        ImVec2 screenTop, screenBottom;
        bool topVisible = WorldToScreen(g_modelViewMatrix, g_projectionMatrix, g_viewportWidth, g_viewportHeight, topPos, screenTop);
        bool bottomVisible = WorldToScreen(g_modelViewMatrix, g_projectionMatrix, g_viewportWidth, g_viewportHeight, bottomPos, screenBottom);
       
        // Если хотя бы одна из точек видима, рисуем ESP
        if (topVisible || bottomVisible) {
            // Если верхняя точка не видна, предполагаем, что она выше экрана
            if (!topVisible) {
                screenTop.x = screenBottom.x;
                screenTop.y = 0;
            }
           
            // Если нижняя точка не видна, предполагаем, что она ниже экрана
            if (!bottomVisible) {
                screenBottom.x = screenTop.x;
                screenBottom.y = screenHeight;
            }
           
            float height = screenBottom.y - screenTop.y;
            float width = height * 0.5f;
           
            // Ограничиваем минимальные размеры бокса
            if (width < 10.0f) width = 10.0f;
            if (height < 20.0f) height = 20.0f;
           
            // Рассчитываем позицию и размеры бокса
            ImVec2 boxTopLeft(screenTop.x - width * 0.5f, screenTop.y);
            ImVec2 boxBottomRight(screenTop.x + width * 0.5f, screenBottom.y);
           
            // Рисуем прямоугольник с выбранным цветом
            drawList->AddRect(boxTopLeft, boxBottomRight, espColor, 0.0f, 0, 2.0f);
           
            // Опционально отображаем расстояние
            if (showDistance) {
                float distance = sqrt(
                    (sheep.x - playerX) * (sheep.x - playerX) +
                    (sheep.y - playerY) * (sheep.y - playerY) +
                    (sheep.z - playerZ) * (sheep.z - playerZ)
                );
               
                char distText[32];
                sprintf_s(distText, "%.1fm", distance);
                ImVec2 textPos(boxTopLeft.x, boxTopLeft.y - 15);
                drawList->AddText(textPos, IM_COL32(255, 255, 255, 255), distText);
            }
        }
    }
}

void ShowError(const char* message) {
    MessageBoxA(NULL, message, "Error", MB_OK | MB_ICONERROR);
}

// Функция для получения LaunchClassLoader
jobject getLaunchClassLoader(JNIEnv* env) {
    // Сначала пытаемся найти класс Launch
    jclass launchClass = env->FindClass("net/minecraft/launchwrapper/Launch");
    if (!launchClass) {
        // Если не нашли, возможно, мы не на правильном classpath
        return nullptr;
    }
   
    // Получаем статическое поле classLoader
    jfieldID classLoaderField = env->GetStaticFieldID(launchClass, "classLoader", "Lnet/minecraft/launchwrapper/LaunchClassLoader;");
    if (!classLoaderField) {
        return nullptr;
    }
   
    // Получаем объект classLoader
    jobject classLoader = env->GetStaticObjectField(launchClass, classLoaderField);
    return classLoader;
}

// Ищем класс для Forge Minecraft
jclass findForgeClass(JNIEnv* env, const char* name) {
    jclass clazz = env->FindClass(name);
    if (clazz) return clazz;
   
    // Если не нашли напрямую, пытаемся через classLoader
    jobject classLoader = getLaunchClassLoader(env);
    if (!classLoader) return nullptr;
   
    // Получаем метод findClass в LaunchClassLoader
    jclass classLoaderClass = env->GetObjectClass(classLoader);
    jmethodID findClassMethod = env->GetMethodID(classLoaderClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
    if (!findClassMethod) return nullptr;
   
    // Вызываем findClass
    jstring className = env->NewStringUTF(name);
    jclass result = (jclass)env->CallObjectMethod(classLoader, findClassMethod, className);
    env->DeleteLocalRef(className);
   
    return result;
}

// Обертка для поиска класса через Forge LaunchClassLoader
jclass getJVMFindClass(JNIEnv* env, const char* name, jboolean initialize, jobject loader, jboolean ignoreError) {
    return findForgeClass(env, name);
}

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");
   
    if (!jvmModule || !openglModule) {
        ShowError("Не удалось найти необходимые модули");
        return;
    }
   
    FARPROC target = GetProcAddress(jvmModule, "JNI_GetCreatedJavaVMs");
    pSwapBuffers = reinterpret_cast<T_SwapBuffers>(GetProcAddress(openglModule, "wglSwapBuffers"));
   
    if (!target || !pSwapBuffers) {
        ShowError("Не удалось найти необходимые функции");
        return;
    }
   
    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) {
    // Инициализируем функцию поиска классов
    getJVMFindClass = &::getJVMFindClass;
   
    initHooks();

    if (!g_jvm) {
        HMODULE jvmModule = GetModuleHandleA("jvm.dll");
        if (!jvmModule) {
            ShowError("Не удалось получить jvm.dll");
            return 0;
        }
       
        auto pGetCreatedJavaVMs = (JNI_GetCreatedJavaVMs_t)GetProcAddress(jvmModule, "JNI_GetCreatedJavaVMs");
        if (!pGetCreatedJavaVMs) {
            ShowError("Не удалось найти JNI_GetCreatedJavaVMs");
            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 {
            ShowError("Не удалось получить JavaVM");
            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;
    }
   
    // Делаем g_loader глобальной ссылкой, чтобы она не была освобождена сборщиком мусора
    g_loader = g_env->NewGlobalRef(g_loader);

    // Цикл обновления данных об овцах
    while (true) {
        UpdateEntities(g_env, g_loader);
        Sleep(50); // Обновляем примерно 20 раз в секунду
    }

    if (g_loader) {
        g_env->DeleteGlobalRef(g_loader);
        g_loader = nullptr;
    }
   
    if (attached) g_jvm->DetachCurrentThread();
    return 0;
}

void RenderMain() {
    // Обработка нажатия клавиши Insert для открытия/закрытия меню
    if (GetAsyncKeyState(VK_INSERT) & 1) {
        menu = !menu;
    }
   
    // Отрисовка ESP в любом случае, даже если меню закрыто
    if (showSheep) {
        Render2DESP();
    }
   
    // Отрисовка меню только если оно открыто
    if (menu) {
        ImGui::Begin("ESP Settings", &menu);
       
        // Чекбокс для включения/выключения ESP
        ImGui::Checkbox("ESP Sheep", &showSheep);
       
        // Чекбокс для отображения расстояния
        ImGui::Checkbox("Show Distance", &showDistance);
       
        // Выбор цвета для ESP
        ImGui::ColorEdit4("ESP Color", (float*)&espColor);
       
        // Дополнительная информация
        ImGui::Separator();
        ImGui::Text("Game Info:");
        ImGui::Text("Player Pos: %.1f, %.1f, %.1f", playerX, playerY, playerZ);
        ImGui::Text("Player Rotation: %.1f, %.1f", playerYaw, playerPitch);
        ImGui::Text("Sheep Count: %d", (int)sheepEntities.size());
        ImGui::Text("Matrices Initialized: %s", g_matricesInitialized ? "Yes" : "No");
       
        ImGui::End();
    }
}

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;
}
в идеале ещё перенести UpdateEntities в отдельный поток с использованием std::condition_variable для уведомления рендера, использовать SSE/AVX для ускорения матричных вычислений (что требует рефакторинга) и использовать инструменты вроде Intel VTune для поиска узких мест.
каков запрос, таков и ответ :grimacing:
 
Пользователь
Статус
Оффлайн
Регистрация
26 Май 2019
Сообщения
151
Реакции[?]
35
Поинты[?]
17K
в идеале ещё перенести UpdateEntities в отдельный поток с использованием std::condition_variable для уведомления рендера, использовать SSE/AVX для ускорения матричных вычислений (что требует рефакторинга) и использовать инструменты вроде Intel VTune для поиска узких мест.

каков запрос, таков и ответ :grimacing:
хватит мне ИИ отвечать.
1. Я вопрос задавал не через ИИ.
2. Дельного ответа/помощи тут не вижу
привет я в душе не знаю эти плюсы если не ошибаюсь

но вот что мне выдал другой ии хз попробуй этот полный код


Попробуй это:
#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;

// Структура для 3D координат
struct ImVec3 {
    float x, y, z;
    ImVec3(float _x = 0.0f, float _y = 0.0f, float _z = 0.0f) : x(_x), y(_y), z(_z) {}
};

// Глобальные переменные
JNIEnv* g_env = nullptr;
jobject g_loader = nullptr;
JavaVM* g_jvm = nullptr;

// Матрицы и состояние для ESP
float g_modelViewMatrix[16] = {0};
float g_projectionMatrix[16] = {0};
bool g_matricesInitialized = false;
int g_viewportWidth = 0;
int g_viewportHeight = 0;

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;
bool showDistance = true;
ImColor espColor = ImColor(255, 0, 0, 255); // Красный

void RenderMain();

// Структура для овец
struct Entity {
    float x, y, z; // Координаты в мире
    float yaw, pitch; // Угол поворота
    float width, height; // Размеры
};

// Глобальные переменные для координат игрока и овец
std::unordered_map<jlong, Entity> sheepEntities;
float playerX = 0.0f, playerY = 0.0f, playerZ = 0.0f;
float playerYaw = 0.0f, playerPitch = 0.0f;
std::mutex entitiesMutex; // Для синхронизации доступа к sheepEntities

// Глобальная переменная для хранения getJVMFindClass
typedef jclass ([I]getJVMFindClass_t)(JNIEnv[/I], const char*, jboolean, jobject, jboolean);
getJVMFindClass_t getJVMFindClass = nullptr;

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);
}

// Получение матриц из LWJGL
bool GetMinecraftMatrices(JNIEnv* env, jobject loader) {
    if (!env || !loader || !getJVMFindClass) return false;
  
    // Найдем класс LWJGL GL11
    jclass gl11Class = getJVMFindClass(env, "org/lwjgl/opengl/GL11", JNI_TRUE, loader, JNI_FALSE);
    if (!gl11Class) return false;
  
    // Находим bufferutils для создания буферов
    jclass bufferUtilsClass = getJVMFindClass(env, "org/lwjgl/BufferUtils", JNI_TRUE, loader, JNI_FALSE);
    if (!bufferUtilsClass) return false;
  
    // Находим класс FloatBuffer
    jclass floatBufferClass = env->FindClass("java/nio/FloatBuffer");
    if (!floatBufferClass) return false;
  
    // Получаем размеры viewport
    jmethodID glGetIntegerMethod = env->GetStaticMethodID(gl11Class, "glGetInteger", "(I)I");
    if (!glGetIntegerMethod) return false;
  
    // GL_VIEWPORT = 0x0BA2
    jint GL_VIEWPORT = 0x0BA2;
  
    // Создаем буфер для viewport
    jmethodID createIntBufferMethod = env->GetStaticMethodID(bufferUtilsClass, "createIntBuffer", "(I)Ljava/nio/IntBuffer;");
    if (!createIntBufferMethod) return false;
    jobject viewportBuffer = env->CallStaticObjectMethod(bufferUtilsClass, createIntBufferMethod, 16);
  
    // Получаем viewport
    jmethodID glGetIntegervMethod = env->GetStaticMethodID(gl11Class, "glGetIntegerv", "(ILjava/nio/IntBuffer;)V");
    if (!glGetIntegervMethod) return false;
    env->CallStaticVoidMethod(gl11Class, glGetIntegervMethod, GL_VIEWPORT, viewportBuffer);
  
    // Получаем размеры viewport
    jclass intBufferClass = env->FindClass("java/nio/IntBuffer");
    if (!intBufferClass) return false;
    jmethodID getMethod = env->GetMethodID(intBufferClass, "get", "(I)I");
    if (!getMethod) return false;
  
    g_viewportWidth = env->CallIntMethod(viewportBuffer, getMethod, 2);
    g_viewportHeight = env->CallIntMethod(viewportBuffer, getMethod, 3);
  
    // Методы для получения матриц
    jmethodID createFloatBufferMethod = env->GetStaticMethodID(bufferUtilsClass, "createFloatBuffer", "(I)Ljava/nio/FloatBuffer;");
    if (!createFloatBufferMethod) return false;
  
    // Создаем буферы для матриц
    jobject modelViewBuffer = env->CallStaticObjectMethod(bufferUtilsClass, createFloatBufferMethod, 16);
    jobject projectionBuffer = env->CallStaticObjectMethod(bufferUtilsClass, createFloatBufferMethod, 16);
  
    // Получаем метод для glGetFloat
    jmethodID glGetFloatMethod = env->GetStaticMethodID(gl11Class, "glGetFloat", "(ILjava/nio/FloatBuffer;)V");
    if (!glGetFloatMethod) return false;
  
    // Константы для матриц в OpenGL
    jint GL_MODELVIEW_MATRIX = 0x0BA6;
    jint GL_PROJECTION_MATRIX = 0x0BA7;
  
    // Получаем матрицы
    env->CallStaticVoidMethod(gl11Class, glGetFloatMethod, GL_MODELVIEW_MATRIX, modelViewBuffer);
    env->CallStaticVoidMethod(gl11Class, glGetFloatMethod, GL_PROJECTION_MATRIX, projectionBuffer);
  
    // Получаем метод get для FloatBuffer
    jmethodID getFloatMethod = env->GetMethodID(floatBufferClass, "get", "(I)F");
    if (!getFloatMethod) return false;
  
    // Извлекаем матрицы
    for (int i = 0; i < 16; i++) {
        g_modelViewMatrix[i] = env->CallFloatMethod(modelViewBuffer, getFloatMethod, i);
        g_projectionMatrix[i] = env->CallFloatMethod(projectionBuffer, getFloatMethod, i);
    }
  
    g_matricesInitialized = true;
    return true;
}

BOOL __stdcall mySwapBuffers(HDC hDC)
{
    InitOpenGL2(hDC, &initImGui, nullptr);
    RenderOpenGL2(g_WglContext, hDC, RenderWin32, RenderMain, nullptr);
    return pSwapBuffers(hDC);
}

// Улучшенная функция WorldToScreen
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] = projection[3] * clipCoords[0] + projection[7] * clipCoords[1] + projection[11] * clipCoords[2] + projection[15] * clipCoords[3];
  
    // Проверка, находится ли объект перед камерой
    if (clipCoordsProjected[3] < 0.1f) {
        return false; // Объект позади камеры или слишком близко
    }
  
    // Перспективное деление
    float ndcX = clipCoordsProjected[0] / clipCoordsProjected[3];
    float ndcY = clipCoordsProjected[1] / clipCoordsProjected[3];
    float ndcZ = clipCoordsProjected[2] / clipCoordsProjected[3];
  
    // Проверка, находится ли объект в пределах видимой области
    if (ndcX < -1.0f || ndcX > 1.0f || ndcY < -1.0f || ndcY > 1.0f) {
        return false; // Объект вне видимой области
    }
  
    // Преобразование в экранные координаты
    screenPos.x = (ndcX + 1.0f) * 0.5f * viewportWidth;
    screenPos.y = (1.0f - (ndcY + 1.0f) * 0.5f) * viewportHeight;
  
    return true;
}

// Получаем координаты игрока и овец (вызывается в 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
    jfieldID rotYawField = env->GetFieldID(entityClass, "field_70177_z", "F"); // rotationYaw
    jfieldID rotPitchField = env->GetFieldID(entityClass, "field_70125_A", "F"); // rotationPitch
    if (!posXField || !posYField || !posZField || !rotYawField || !rotPitchField) return;
  
    playerX = (float)env->GetDoubleField(player, posXField);
    playerY = (float)env->GetDoubleField(player, posYField);
    playerZ = (float)env->GetDoubleField(player, posZField);
    playerYaw = env->GetFloatField(player, rotYawField);
    playerPitch = env->GetFloatField(player, rotPitchField);

    // Получаем мир
    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;

    // Получаем ширину и высоту сущности
    jfieldID widthField = env->GetFieldID(entityClass, "field_70130_N", "F"); // width
    jfieldID heightField = env->GetFieldID(entityClass, "field_70131_O", "F"); // height
    if (!widthField || !heightField) 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);
        jfloat yaw = env->GetFloatField(entity, rotYawField);
        jfloat pitch = env->GetFloatField(entity, rotPitchField);
        jfloat width = env->GetFloatField(entity, widthField);
        jfloat height = env->GetFloatField(entity, heightField);
        jint entityId = env->CallIntMethod(entity, getEntityIdMethod);

        Entity entityInfo;
        entityInfo.x = (float)x;
        entityInfo.y = (float)y;
        entityInfo.z = (float)z;
        entityInfo.yaw = yaw;
        entityInfo.pitch = pitch;
        entityInfo.width = width;
        entityInfo.height = height;

        tempEntities[entityId] = entityInfo;
    }

    // Безопасно обновляем глобальную переменную
    std::lock_guard<std::mutex> lock(entitiesMutex);
    sheepEntities = std::move(tempEntities);
  
    // Обновляем матрицы, если нужно отображать ESP
    if (showSheep) {
        GetMinecraftMatrices(env, loader);
    }
}

// Обновленная функция отрисовки ESP
void Render2DESP() {
    if (!showSheep || !g_matricesInitialized) return;

    ImGuiIO& io = ImGui::GetIO();
    float screenWidth = io.DisplaySize.x;
    float screenHeight = io.DisplaySize.y;

    // Если размеры viewport'а не получены, используем размеры ImGui окна
    if (g_viewportWidth <= 0 || g_viewportHeight <= 0) {
        g_viewportWidth = (int)screenWidth;
        g_viewportHeight = (int)screenHeight;
    }

    ImDrawList* drawList = ImGui::GetBackgroundDrawList();

    std::lock_guard<std::mutex> lock(entitiesMutex);
    for (const auto& pair : sheepEntities) {
        const Entity& sheep = pair.second;
      
        // Создаем точки верха и низа овцы (с учетом её высоты)
        ImVec3 topPos(sheep.x, sheep.y + sheep.height, sheep.z);
        ImVec3 bottomPos(sheep.x, sheep.y, sheep.z);
      
        // Преобразуем в экранные координаты
        ImVec2 screenTop, screenBottom;
        bool topVisible = WorldToScreen(g_modelViewMatrix, g_projectionMatrix, g_viewportWidth, g_viewportHeight, topPos, screenTop);
        bool bottomVisible = WorldToScreen(g_modelViewMatrix, g_projectionMatrix, g_viewportWidth, g_viewportHeight, bottomPos, screenBottom);
      
        // Если хотя бы одна из точек видима, рисуем ESP
        if (topVisible || bottomVisible) {
            // Если верхняя точка не видна, предполагаем, что она выше экрана
            if (!topVisible) {
                screenTop.x = screenBottom.x;
                screenTop.y = 0;
            }
          
            // Если нижняя точка не видна, предполагаем, что она ниже экрана
            if (!bottomVisible) {
                screenBottom.x = screenTop.x;
                screenBottom.y = screenHeight;
            }
          
            float height = screenBottom.y - screenTop.y;
            float width = height * 0.5f;
          
            // Ограничиваем минимальные размеры бокса
            if (width < 10.0f) width = 10.0f;
            if (height < 20.0f) height = 20.0f;
          
            // Рассчитываем позицию и размеры бокса
            ImVec2 boxTopLeft(screenTop.x - width * 0.5f, screenTop.y);
            ImVec2 boxBottomRight(screenTop.x + width * 0.5f, screenBottom.y);
          
            // Рисуем прямоугольник с выбранным цветом
            drawList->AddRect(boxTopLeft, boxBottomRight, espColor, 0.0f, 0, 2.0f);
          
            // Опционально отображаем расстояние
            if (showDistance) {
                float distance = sqrt(
                    (sheep.x - playerX) * (sheep.x - playerX) +
                    (sheep.y - playerY) * (sheep.y - playerY) +
                    (sheep.z - playerZ) * (sheep.z - playerZ)
                );
              
                char distText[32];
                sprintf_s(distText, "%.1fm", distance);
                ImVec2 textPos(boxTopLeft.x, boxTopLeft.y - 15);
                drawList->AddText(textPos, IM_COL32(255, 255, 255, 255), distText);
            }
        }
    }
}

void ShowError(const char* message) {
    MessageBoxA(NULL, message, "Error", MB_OK | MB_ICONERROR);
}

// Функция для получения LaunchClassLoader
jobject getLaunchClassLoader(JNIEnv* env) {
    // Сначала пытаемся найти класс Launch
    jclass launchClass = env->FindClass("net/minecraft/launchwrapper/Launch");
    if (!launchClass) {
        // Если не нашли, возможно, мы не на правильном classpath
        return nullptr;
    }
  
    // Получаем статическое поле classLoader
    jfieldID classLoaderField = env->GetStaticFieldID(launchClass, "classLoader", "Lnet/minecraft/launchwrapper/LaunchClassLoader;");
    if (!classLoaderField) {
        return nullptr;
    }
  
    // Получаем объект classLoader
    jobject classLoader = env->GetStaticObjectField(launchClass, classLoaderField);
    return classLoader;
}

// Ищем класс для Forge Minecraft
jclass findForgeClass(JNIEnv* env, const char* name) {
    jclass clazz = env->FindClass(name);
    if (clazz) return clazz;
  
    // Если не нашли напрямую, пытаемся через classLoader
    jobject classLoader = getLaunchClassLoader(env);
    if (!classLoader) return nullptr;
  
    // Получаем метод findClass в LaunchClassLoader
    jclass classLoaderClass = env->GetObjectClass(classLoader);
    jmethodID findClassMethod = env->GetMethodID(classLoaderClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
    if (!findClassMethod) return nullptr;
  
    // Вызываем findClass
    jstring className = env->NewStringUTF(name);
    jclass result = (jclass)env->CallObjectMethod(classLoader, findClassMethod, className);
    env->DeleteLocalRef(className);
  
    return result;
}

// Обертка для поиска класса через Forge LaunchClassLoader
jclass getJVMFindClass(JNIEnv* env, const char* name, jboolean initialize, jobject loader, jboolean ignoreError) {
    return findForgeClass(env, name);
}

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");
  
    if (!jvmModule || !openglModule) {
        ShowError("Не удалось найти необходимые модули");
        return;
    }
  
    FARPROC target = GetProcAddress(jvmModule, "JNI_GetCreatedJavaVMs");
    pSwapBuffers = reinterpret_cast<T_SwapBuffers>(GetProcAddress(openglModule, "wglSwapBuffers"));
  
    if (!target || !pSwapBuffers) {
        ShowError("Не удалось найти необходимые функции");
        return;
    }
  
    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) {
    // Инициализируем функцию поиска классов
    getJVMFindClass = &::getJVMFindClass;
  
    initHooks();

    if (!g_jvm) {
        HMODULE jvmModule = GetModuleHandleA("jvm.dll");
        if (!jvmModule) {
            ShowError("Не удалось получить jvm.dll");
            return 0;
        }
      
        auto pGetCreatedJavaVMs = (JNI_GetCreatedJavaVMs_t)GetProcAddress(jvmModule, "JNI_GetCreatedJavaVMs");
        if (!pGetCreatedJavaVMs) {
            ShowError("Не удалось найти JNI_GetCreatedJavaVMs");
            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 {
            ShowError("Не удалось получить JavaVM");
            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;
    }
  
    // Делаем g_loader глобальной ссылкой, чтобы она не была освобождена сборщиком мусора
    g_loader = g_env->NewGlobalRef(g_loader);

    // Цикл обновления данных об овцах
    while (true) {
        UpdateEntities(g_env, g_loader);
        Sleep(50); // Обновляем примерно 20 раз в секунду
    }

    if (g_loader) {
        g_env->DeleteGlobalRef(g_loader);
        g_loader = nullptr;
    }
  
    if (attached) g_jvm->DetachCurrentThread();
    return 0;
}

void RenderMain() {
    // Обработка нажатия клавиши Insert для открытия/закрытия меню
    if (GetAsyncKeyState(VK_INSERT) & 1) {
        menu = !menu;
    }
  
    // Отрисовка ESP в любом случае, даже если меню закрыто
    if (showSheep) {
        Render2DESP();
    }
  
    // Отрисовка меню только если оно открыто
    if (menu) {
        ImGui::Begin("ESP Settings", &menu);
      
        // Чекбокс для включения/выключения ESP
        ImGui::Checkbox("ESP Sheep", &showSheep);
      
        // Чекбокс для отображения расстояния
        ImGui::Checkbox("Show Distance", &showDistance);
      
        // Выбор цвета для ESP
        ImGui::ColorEdit4("ESP Color", (float*)&espColor);
      
        // Дополнительная информация
        ImGui::Separator();
        ImGui::Text("Game Info:");
        ImGui::Text("Player Pos: %.1f, %.1f, %.1f", playerX, playerY, playerZ);
        ImGui::Text("Player Rotation: %.1f, %.1f", playerYaw, playerPitch);
        ImGui::Text("Sheep Count: %d", (int)sheepEntities.size());
        ImGui::Text("Matrices Initialized: %s", g_matricesInitialized ? "Yes" : "No");
      
        ImGui::End();
    }
}

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;
}
Спасибо, но не надо мне от ИИ отвечать. я уже от неё всё перепробовал. И да...
"
// Константы для матриц в OpenGL
jint GL_MODELVIEW_MATRIX = 0x0BA6;
jint GL_PROJECTION_MATRIX = 0x0BA7;

"

пиздец.. Естественно оно не будет работать
У меня был вариант использовать получение матриц на гл'е с исходников ESP&Tracers от ауренекса(noad)
но всё равно не пашет
C++:
void savePosition(Position& position, float offsetX, float offsetY, float offsetZ)
{
    float projection[16]{};
    glGetFloatv(GL_PROJECTION_MATRIX, projection);

    float modelview[16]{};
    glGetFloatv(GL_MODELVIEW_MATRIX, modelview);

    // Position adjustment (Taken from the source code of the GLM library)
    float m3[4]{};

    for (int i = 0; i < 4; ++i)
    {
        m3[i] = modelview[i] * offsetX
                + modelview[i + 4] * offsetY
                + modelview[i + 8] * offsetZ
                + modelview[i + 12];
    }

    memcpy(modelview + 12, m3, sizeof(m3));

    position.projection.insert(position.projection.end(), begin(projection), end(projection));
    position.modelview.insert(position.modelview.end(), begin(modelview), end(modelview));
}
 
Начинающий
Статус
Онлайн
Регистрация
22 Окт 2022
Сообщения
12
Реакции[?]
0
Поинты[?]
0
хватит мне ИИ отвечать.
1. Я вопрос задавал не через ИИ.
2. Дельного ответа/помощи тут не вижу

Спасибо, но не надо мне от ИИ отвечать. я уже от неё всё перепробовал. И да...
"
// Константы для матриц в OpenGL
jint GL_MODELVIEW_MATRIX = 0x0BA6;
jint GL_PROJECTION_MATRIX = 0x0BA7;

"

пиздец.. Естественно оно не будет работать
Из самого банального, посмотри на строку WTS - clipCoordsProjected[3] = -clipCoords[2]; ОНО полностью игнорирует матрицу проекции для этой компоненты, т.к. присваивается отрицательное значение, скорее всего это приводит к неправильным экранным координатам. *Только сейчас подумал, что можно ещё проверку границ добавить
Привет. Прошу помочь с отрисовкой 2D ESP на entity (как пример, хотел отрисовывать на овцах). Координаты овец получаю. Свои тоже получаю. Скорее всего проблема в WorldToScreen, но я не понимаю что тут фиксить нужно. Пытался через ChatGPT платный сделать, она мне хуйню всякую советует. Вот пришёл сюда. Скриншот прилагаю.

[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;
}
Возможно этот WorldToScreen сработает, но я не знаю как его вставить в свой код, так как я просто паcтер.
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;
}
Если говорить ещё то, у тебя переменная RenderMains есть, но не вижу чтобы использовалась, не реализована функция для получения LaunchClassLoader
*Дальше уже лень смотреть :disappointed:
 
Последнее редактирование:
Пользователь
Статус
Оффлайн
Регистрация
26 Май 2019
Сообщения
151
Реакции[?]
35
Поинты[?]
17K
Из самого банального, посмотри на строку WTS - clipCoordsProjected[3] = -clipCoords[2]; ОНО полностью игнорирует матрицу проекции для этой компоненты, т.к. присваивается отрицательное значение, скорее всего это приводит к неправильным экранным координатам. *Только сейчас подумал, что можно ещё проверку границ добавить

Если говорить ещё то, у тебя переменная RenderMains есть, но не вижу чтобы использовалась, не реализована функция для получения LaunchClassLoader
*Дальше уже лень смотреть :disappointed:
забыл её удалить ( RenderMains )
" не реализована функция для получения LaunchClassLoader " я её специально убрал чтобы не пастили
 
Начинающий
Статус
Оффлайн
Регистрация
16 Сен 2024
Сообщения
102
Реакции[?]
3
Поинты[?]
1K
У меня есть фикс этого же кода только:
  • Убраны повторяющиеся проверки на nullptr и оптимизированы ветвления.
  • Сокращены повторные вызовы FindClass и GetMethodID, кэшируя их результаты.
  • Уменьшено количество вызовов ImGui и упрощена логика WorldToScreen.
  • Использованы более эффективные структуры данных и синхронизация.
  • Убраны закомментированные участки и неиспользуемые переменные.
  • Заменил магические числа и упростил макросы.
ало вы че ебанулись? вы мало того что код с нейронки пастите вы еще и отвечаете друг другу через нейронку
нахуя вы тут нужны тогда если за вас всё ии делает?
 
PoC Life
Пользователь
Статус
Оффлайн
Регистрация
22 Авг 2022
Сообщения
455
Реакции[?]
54
Поинты[?]
46K
ало вы че ебанулись? вы мало того что код с нейронки пастите вы еще и отвечаете друг другу через нейронку
нахуя вы тут нужны тогда если за вас всё ии делает?
Путь к успеху: из yougame.biz в AIgame.biz
 
splyxclient
EXCLUSIVE
Статус
Онлайн
Регистрация
15 Мар 2021
Сообщения
181
Реакции[?]
35
Поинты[?]
37K
ало вы че ебанулись? вы мало того что код с нейронки пастите вы еще и отвечаете друг другу через нейронку
нахуя вы тут нужны тогда если за вас всё ии делает?
все на югейме пастят с нейронки просто не говорят об этом, а тут хотя бы это не скрывают)
 
Пользователь
Статус
Оффлайн
Регистрация
26 Май 2019
Сообщения
151
Реакции[?]
35
Поинты[?]
17K
Решение:
Проблема была всё таки с WorldToScreen
Код:
ImVec2 WorldToScreenSimple(float entX, float entY, float entZ,
    float camX, float camY, float camZ,
    float yawDeg, float pitchDeg, float fovDeg,
    float screenWidth, float screenHeight)
{
    // Смещаем овцу относительно камеры
    float dx = entX - camX;
    float dy = entY - camY;
    float dz = entZ - camZ;

    // Поворот по yaw/pitch
    float yawRad = Deg2Rad(yawDeg);
    float pitchRad = Deg2Rad(pitchDeg);

    // Вычисляем компоненты после поворота вокруг Y (yaw)
    float cosYaw = cosf(yawRad);
    float sinYaw = sinf(yawRad);

    float xzX = dx * cosYaw + dz * sinYaw;
    float xzZ = -dx * sinYaw + dz * cosYaw;

    // Поворот вокруг X (pitch)
    float cosPitch = cosf(-pitchRad);
    float sinPitch = sinf(-pitchRad);

    float yCam = (dy * cosPitch) - (xzZ * sinPitch);
    float zCam = (dy * sinPitch) + (xzZ * cosPitch);

    float xCam = xzX;

    // Если объект за камерой, не отображаем его
    if (zCam <= 0.01f) {
        return ImVec2(-1, -1);
    }

    // Простая перспектива
    float halfFovRad = Deg2Rad(fovDeg * 0.5f);
    float tanHalfFov = tanf(halfFovRad);
    float aspect = screenWidth / screenHeight;

    float yNdc = yCam / (zCam * tanHalfFov);
    float xNdc = (xCam / (zCam * tanHalfFov)) / aspect;

    float screenX = (xNdc + 1.0f) * 0.5f * screenWidth;
    float screenY = (1.0f - yNdc) * 0.5f * screenHeight;

    // Отзеркаливаем координату X
    screenX = screenWidth - screenX;

    // Если за пределами экрана, не отображаем
    if (screenX < 0.f || screenX > screenWidth || screenY < 0.f || screenY > screenHeight) {
        return ImVec2(-1, -1);
    }

    return ImVec2(screenX, screenY);
}
1742428833296.png
 
Последнее редактирование:
Начинающий
Статус
Онлайн
Регистрация
15 Янв 2022
Сообщения
145
Реакции[?]
20
Поинты[?]
10K
Решение:
Проблема была всё таки с WorldToScreen
Код:
ImVec2 WorldToScreenSimple(float entX, float entY, float entZ,
    float camX, float camY, float camZ,
    float yawDeg, float pitchDeg, float fovDeg,
    float screenWidth, float screenHeight)
{
    // Смещаем овцу относительно камеры
    float dx = entX - camX;
    float dy = entY - camY;
    float dz = entZ - camZ;

    // Поворот по yaw/pitch
    float yawRad = Deg2Rad(yawDeg);
    float pitchRad = Deg2Rad(pitchDeg);

    // Вычисляем компоненты после поворота вокруг Y (yaw)
    float cosYaw = cosf(yawRad);
    float sinYaw = sinf(yawRad);

    float xzX = dx * cosYaw + dz * sinYaw;
    float xzZ = -dx * sinYaw + dz * cosYaw;

    // Поворот вокруг X (pitch)
    float cosPitch = cosf(-pitchRad);
    float sinPitch = sinf(-pitchRad);

    float yCam = (dy * cosPitch) - (xzZ * sinPitch);
    float zCam = (dy * sinPitch) + (xzZ * cosPitch);

    float xCam = xzX;

    // Если объект за камерой, не отображаем его
    if (zCam <= 0.01f) {
        return ImVec2(-1, -1);
    }

    // Простая перспектива
    float halfFovRad = Deg2Rad(fovDeg * 0.5f);
    float tanHalfFov = tanf(halfFovRad);
    float aspect = screenWidth / screenHeight;

    float yNdc = yCam / (zCam * tanHalfFov);
    float xNdc = (xCam / (zCam * tanHalfFov)) / aspect;

    float screenX = (xNdc + 1.0f) * 0.5f * screenWidth;
    float screenY = (1.0f - yNdc) * 0.5f * screenHeight;

    // Отзеркаливаем координату X
    screenX = screenWidth - screenX;

    // Если за пределами экрана, не отображаем
    if (screenX < 0.f || screenX > screenWidth || screenY < 0.f || screenY > screenHeight) {
        return ImVec2(-1, -1);
    }

    return ImVec2(screenX, screenY);
}
C++:
auto CheatTools::world_to_screen(glm::vec2& position_2d, const glm::vec4& world_pos, const glm::mat4& view_matrix, const glm::mat4& projection_matrix) -> bool
{
    const glm::vec4 clipPos = projection_matrix * view_matrix * world_pos;

    if (clipPos.w == 0) {
        return false;
    }

    const glm::vec3 ndc = glm::vec3(clipPos) / clipPos.w;

    const float x = (ndc.x + 1.0f) * 0.5f * overlay->self_width;
    const float y = (1.0f - ndc.y) * 0.5f * overlay->self_height;

    if (x < 0 || x > overlay->self_width || y < 0 || y > overlay->self_height)
        return false;

    position_2d = { x,y };

    return true;
}

                                                    //{0,0,0}
glm::vec4 vertexPos_world = model_matrix * glm::vec4(vertexPos_model, 1.0);

не знаю как в деф. майне, но по идее в сталкрафте та же хуйня
 
OllyDbg
Пользователь
Статус
Оффлайн
Регистрация
24 Дек 2018
Сообщения
327
Реакции[?]
45
Поинты[?]
10K
Решение:
Проблема была всё таки с WorldToScreen
Код:
ImVec2 WorldToScreenSimple(float entX, float entY, float entZ,
    float camX, float camY, float camZ,
    float yawDeg, float pitchDeg, float fovDeg,
    float screenWidth, float screenHeight)
{
    // Смещаем овцу относительно камеры
    float dx = entX - camX;
    float dy = entY - camY;
    float dz = entZ - camZ;

    // Поворот по yaw/pitch
    float yawRad = Deg2Rad(yawDeg);
    float pitchRad = Deg2Rad(pitchDeg);

    // Вычисляем компоненты после поворота вокруг Y (yaw)
    float cosYaw = cosf(yawRad);
    float sinYaw = sinf(yawRad);

    float xzX = dx * cosYaw + dz * sinYaw;
    float xzZ = -dx * sinYaw + dz * cosYaw;

    // Поворот вокруг X (pitch)
    float cosPitch = cosf(-pitchRad);
    float sinPitch = sinf(-pitchRad);

    float yCam = (dy * cosPitch) - (xzZ * sinPitch);
    float zCam = (dy * sinPitch) + (xzZ * cosPitch);

    float xCam = xzX;

    // Если объект за камерой, не отображаем его
    if (zCam <= 0.01f) {
        return ImVec2(-1, -1);
    }

    // Простая перспектива
    float halfFovRad = Deg2Rad(fovDeg * 0.5f);
    float tanHalfFov = tanf(halfFovRad);
    float aspect = screenWidth / screenHeight;

    float yNdc = yCam / (zCam * tanHalfFov);
    float xNdc = (xCam / (zCam * tanHalfFov)) / aspect;

    float screenX = (xNdc + 1.0f) * 0.5f * screenWidth;
    float screenY = (1.0f - yNdc) * 0.5f * screenHeight;

    // Отзеркаливаем координату X
    screenX = screenWidth - screenX;

    // Если за пределами экрана, не отображаем
    if (screenX < 0.f || screenX > screenWidth || screenY < 0.f || screenY > screenHeight) {
        return ImVec2(-1, -1);
    }

    return ImVec2(screenX, screenY);
}
Так, блять, это было понятно, что у тебя проблема с WorldScreen
 
splyxclient
EXCLUSIVE
Статус
Онлайн
Регистрация
15 Мар 2021
Сообщения
181
Реакции[?]
35
Поинты[?]
37K
Сверху Снизу