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

Пользователь
Пользователь
Статус
Оффлайн
Регистрация
26 Май 2019
Сообщения
204
Реакции
39

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

  • бесплатные читы для Майнкрафт — любое использование на свой страх и риск;
  • маркетплейс Майнкрафт — абсолютно любая коммерция, связанная с игрой, за исключением продажи читов (аккаунты, предоставления услуг, поиск кодеров читов и так далее);
  • приватные читы для 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;
}
 
Последнее редактирование:
привет я в душе не знаю эти плюсы если не ошибаюсь

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


Попробуй это:
Expand Collapse Copy
#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;
}
 
собрались юзеры ии для написания кода для кубов на плюсах :screamcat:
 
привет я в душе не знаю эти плюсы если не ошибаюсь

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


Попробуй это:
Expand Collapse Copy
#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.
  • Использованы более эффективные структуры данных и синхронизация.
  • Убраны закомментированные участки и неиспользуемые переменные.
  • Заменил магические числа и упростил макросы.
 
У меня есть фикс этого же кода только:
  • Убраны повторяющиеся проверки на nullptr и оптимизированы ветвления.
  • Сокращены повторные вызовы FindClass и GetMethodID, кэшируя их результаты.
  • Уменьшено количество вызовов ImGui и упрощена логика WorldToScreen.
  • Использованы более эффективные структуры данных и синхронизация.
  • Убраны закомментированные участки и неиспользуемые переменные.
  • Заменил магические числа и упростил макросы.
ai coding ?️?️?️
 
привет я в душе не знаю эти плюсы если не ошибаюсь

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


Попробуй это:
Expand Collapse Copy
#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:
 
в идеале ещё перенести UpdateEntities в отдельный поток с использованием std::condition_variable для уведомления рендера, использовать SSE/AVX для ускорения матричных вычислений (что требует рефакторинга) и использовать инструменты вроде Intel VTune для поиска узких мест.

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

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


Попробуй это:
Expand Collapse Copy
#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++:
Expand Collapse Copy
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));
}
 
хватит мне ИИ отвечать.
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:
 
Последнее редактирование:
Из самого банального, посмотри на строку WTS - clipCoordsProjected[3] = -clipCoords[2]; ОНО полностью игнорирует матрицу проекции для этой компоненты, т.к. присваивается отрицательное значение, скорее всего это приводит к неправильным экранным координатам. *Только сейчас подумал, что можно ещё проверку границ добавить

Если говорить ещё то, у тебя переменная RenderMains есть, но не вижу чтобы использовалась, не реализована функция для получения LaunchClassLoader
*Дальше уже лень смотреть :disappointed:
забыл её удалить ( RenderMains )
" не реализована функция для получения LaunchClassLoader " я её специально убрал чтобы не пастили
 
У меня есть фикс этого же кода только:
  • Убраны повторяющиеся проверки на nullptr и оптимизированы ветвления.
  • Сокращены повторные вызовы FindClass и GetMethodID, кэшируя их результаты.
  • Уменьшено количество вызовов ImGui и упрощена логика WorldToScreen.
  • Использованы более эффективные структуры данных и синхронизация.
  • Убраны закомментированные участки и неиспользуемые переменные.
  • Заменил магические числа и упростил макросы.
ало вы че ебанулись? вы мало того что код с нейронки пастите вы еще и отвечаете друг другу через нейронку
нахуя вы тут нужны тогда если за вас всё ии делает?
 
ало вы че ебанулись? вы мало того что код с нейронки пастите вы еще и отвечаете друг другу через нейронку
нахуя вы тут нужны тогда если за вас всё ии делает?
Путь к успеху: из yougame.biz в AIgame.biz
 
ало вы че ебанулись? вы мало того что код с нейронки пастите вы еще и отвечаете друг другу через нейронку
нахуя вы тут нужны тогда если за вас всё ии делает?
все на югейме пастят с нейронки просто не говорят об этом, а тут хотя бы это не скрывают)
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Ебанутая ебанушка
 
сюдаа, чатгпт знает про югейм
1742421527238.png
 
Решение:
Проблема была всё таки с WorldToScreen
Код:
Expand Collapse Copy
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
 
Последнее редактирование:
Решение:
Проблема была всё таки с WorldToScreen
Код:
Expand Collapse Copy
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++:
Expand Collapse Copy
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);

не знаю как в деф. майне, но по идее в сталкрафте та же хуйня
 
Решение:
Проблема была всё таки с WorldToScreen
Код:
Expand Collapse Copy
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
 
Назад
Сверху Снизу