Подпишитесь на наш Telegram-канал, чтобы всегда быть в курсе важных обновлений! Перейти

Вопрос DLL, LUA, DOTA 2 | Помогите

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
3 Ноя 2024
Сообщения
3
Реакции
0
Всем привет, хотел обратиться за помощью, возможно кто-то из вас откликнется, чему я очень буду благодарен.

У меня есть injector написанный за несколько дней на C++ (свою функцию он выполняет), так же у меня есть DLL, которая в свою очередь инжектит LUA скрипт в процесс игры dota2.exe, сама DLL загружается, но ожидаемого результата в игре не происходит, то есть скрипт не работает.

То, что я пытаюсь заинжектить в процесс, это изначально написанный для ботов ward helper, который говорит ботам куда нужно расставлять варды, моя идея заключается в том, чтобы сделать эту функцию для обычного игрока.
Условно ты запускаешь игру, спавнишься инжектишь скрипт, а после скрипт автоматически идет расставлять варды, круто да)):hearteyecat:

Если кто-то шарит в LUA и/или C++ и готов на волонтерских началах помочь, буду очень благодарен.
Можно написать в лс на форуме или ответить в топике.
 
Всем привет, хотел обратиться за помощью, возможно кто-то из вас откликнется, чему я очень буду благодарен.

У меня есть injector написанный за несколько дней на C++ (свою функцию он выполняет), так же у меня есть DLL, которая в свою очередь инжектит LUA скрипт в процесс игры dota2.exe, сама DLL загружается, но ожидаемого результата в игре не происходит, то есть скрипт не работает.

То, что я пытаюсь заинжектить в процесс, это изначально написанный для ботов ward helper, который говорит ботам куда нужно расставлять варды, моя идея заключается в том, чтобы сделать эту функцию для обычного игрока.
Условно ты запускаешь игру, спавнишься инжектишь скрипт, а после скрипт автоматически идет расставлять варды, круто да)):hearteyecat:

Если кто-то шарит в LUA и/или C++ и готов на волонтерских началах помочь, буду очень благодарен.
Можно написать в лс на форуме или ответить в топике.
ты код то покажи, как нам понять что не так?
 
ты код то покажи, как нам понять что не так?

Ниже код С++

C++:
Expand Collapse Copy
#include <windows.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <iostream>
#include <string>

#pragma comment(lib, "Psapi.lib")

// Opredelyaem strukturu dlya peredachi argumentov
struct RunParams {
    char windowTitle[256]; // Zagolovok okna
    char keyName[16];      // Nazvanie klavishi
};

// Funktsiya dlya polucheniya ID protsessa po ego imeni
DWORD GetProcessID(const wchar_t* processName) {
    PROCESSENTRY32W pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32W);

    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnapshot == INVALID_HANDLE_VALUE) return 0;

    if (Process32FirstW(hSnapshot, &pe32)) {
        do {
            if (wcscmp(pe32.szExeFile, processName) == 0) {
                CloseHandle(hSnapshot);
                return pe32.th32ProcessID;
            }
        } while (Process32NextW(hSnapshot, &pe32));
    }
    CloseHandle(hSnapshot);
    return 0;
}

// Funktsiya dlya in'ektsii DLL v protsess
void InjectDLL(HANDLE hProcess, const wchar_t* dllPath) {
    void* pDllPath = VirtualAllocEx(hProcess, NULL, (wcslen(dllPath) + 1) * sizeof(wchar_t), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if (!pDllPath) {
        std::cout << "Ne udalos' vydelit' pamyat' v protsesse." << std::endl;
        return;
    }

    WriteProcessMemory(hProcess, pDllPath, dllPath, (wcslen(dllPath) + 1) * sizeof(wchar_t), NULL);

    HANDLE hLoadThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryW"), pDllPath, 0, NULL);
    if (hLoadThread) {
        WaitForSingleObject(hLoadThread, INFINITE);
        CloseHandle(hLoadThread);
        std::cout << "DLL uspeshno zagruzheno v protsess." << std::endl;
    }
    else {
        std::cout << "Ne udalos' sozdать potok dlya zagruzki DLL." << std::endl;
    }

    VirtualFreeEx(hProcess, pDllPath, 0, MEM_RELEASE);
}

// Funktsiya dlya vyzova funktsii Run i peredachi parametrov
void CallRunFunction(HANDLE hProcess, const wchar_t* dllPath, const char* windowTitle, const char* keyName) {
    HMODULE hModule = LoadLibraryW(dllPath);
    if (!hModule) {
        std::cout << "Ne udalos' zagruzit' DLL v tekushchiy protsess." << std::endl;
        return;
    }

    FARPROC pRun = GetProcAddress(hModule, "Run");
    if (!pRun) {
        std::cout << "Ne udalos' nayti funktsiyu Run." << std::endl;
        FreeLibrary(hModule);
        return;
    }

    // Vydelyaem pamyat' dlya struktury parametrov
    void* pRunParams = VirtualAllocEx(hProcess, NULL, sizeof(RunParams), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if (!pRunParams) {
        std::cerr << "Ne udalos' vydelit' pamyat' dlya parametrov." << std::endl;
        FreeLibrary(hModule);
        return;
    }

    // Zapolnyaem strukturu parametrov
    RunParams params;
    strncpy_s(params.windowTitle, windowTitle, sizeof(params.windowTitle) - 1);
    strncpy_s(params.keyName, keyName, sizeof(params.keyName) - 1);

    // Zapisyvayem parametry v vydelennuyu pamyat'
    WriteProcessMemory(hProcess, pRunParams, &params, sizeof(RunParams), NULL);

    // Sozdaem potok dlya vyzova funktsii Run
    HANDLE hRunThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRun, pRunParams, 0, NULL);
    if (hRunThread) {
        WaitForSingleObject(hRunThread, INFINITE);
        CloseHandle(hRunThread);
        std::cout << "Funktsiya Run uspeshno vyzvana." << std::endl;
    }
    else {
        std::cout << "Ne udalos' sozdать potok dlya vyzova funktsii Run." << std::endl;
    }

    // Osvobozhdaem pamyat'
    VirtualFreeEx(hProcess, pRunParams, 0, MEM_RELEASE);
    FreeLibrary(hModule);
}

int main() {
    const wchar_t* processName = L"dota2.exe";
    const wchar_t* dllPath = L"C:\\Users\\sun\\source\\repos\\lua_loader_dll\\x64\\Debug\\lua_loader_dll.dll";
    const char* windowTitle = "Dota 2"; // Nazvanie okna, kuda budet in'ektirovatsya DLL
    const char* keyName = "B";                      // Nazvanie klavishi dlya nazhatiya

    DWORD processID = GetProcessID(processName);
    if (processID == 0) {
        std::cout << "Cannot find process Dota 2" << std::endl;
        return 1;
    }

    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
    if (!hProcess) {
        std::cout << "Cannot open process." << std::endl;
        return 1;
    }

    InjectDLL(hProcess, dllPath);
    CallRunFunction(hProcess, dllPath, windowTitle, keyName);

    CloseHandle(hProcess);
    return 0;
}

Ниже код DLL, которая подгружает LUA (это говнокод, но даже когда там был на первый взгляд норм код, он все равно не работал)
C++:
Expand Collapse Copy
#include "pch.h"
#include <windows.h>
#include <lua.hpp>
#include <iostream>

const char* luaCode = R"(-- Функция для проверки наличия Observer Wards в инвентаре
local function hasObserverWard(inventory)
    for i = 0, 5 do -- Индексы предметов в инвентаре
        local item = inventory:GetItemInSlot(i)
        if item and item:GetName() == "item_observer_ward" then
            return true -- Найдены Observer Wards
        end
    end
    return false -- Observer Wards не найдены
end

-- Функция для размещения Observer Wards
local function placeObserverWards()
    local hero = Entities:GetLocalPlayer():GetAssignedHero() -- Получаем локального героя
    if not hero then
        print("Hero not found!")
        return
    end

    local inventory = hero:GetInventory() -- Получаем инвентарь героя
    if hasObserverWard(inventory) then
        print("Observer Wards found in inventory.")
        
        -- Ищем позицию для размещения
        local targetPosition = Vector(0, 0, 0) -- Здесь вы можете указать координаты, где хотите разместить варды
        -- Логика размещения варда
        hero:CastAbilityOnPosition(targetPosition, hero:FindAbilityByName("item_observer_ward"), 0)
        
        print("Placing Observer Ward at position: ", targetPosition)
    else
        print("No Observer Wards found in inventory.")
    end
end

-- Основная функция, которая будет вызвана при запуске скрипта
local function main()
    print("Lua script is running.")
    placeObserverWards() -- Вызываем функцию размещения варда
end

-- Запускаем основной процесс
main()
)";

void ExecuteLuaScript() {
    lua_State* L = luaL_newstate(); // Create a new Lua state
    luaL_openlibs(L);                // Open standard Lua libraries

    // Load the Lua code from the string
    if (luaL_dostring(L, luaCode) != LUA_OK) {
        MessageBoxA(NULL, lua_tostring(L, -1), "Lua Error", MB_OK | MB_ICONERROR);
        lua_pop(L, 1); // Remove error message from the stack
        lua_close(L);  // Close Lua state
        return;
    }

    lua_close(L); // Close Lua state after execution
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
    if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
        ExecuteLuaScript(); // Execute Lua script on DLL attach
    }
    return TRUE;
}
 
Всем привет, хотел обратиться за помощью, возможно кто-то из вас откликнется, чему я очень буду благодарен.

У меня есть injector написанный за несколько дней на C++ (свою функцию он выполняет), так же у меня есть DLL, которая в свою очередь инжектит LUA скрипт в процесс игры dota2.exe, сама DLL загружается, но ожидаемого результата в игре не происходит, то есть скрипт не работает.

То, что я пытаюсь заинжектить в процесс, это изначально написанный для ботов ward helper, который говорит ботам куда нужно расставлять варды, моя идея заключается в том, чтобы сделать эту функцию для обычного игрока.
Условно ты запускаешь игру, спавнишься инжектишь скрипт, а после скрипт автоматически идет расставлять варды, круто да)):hearteyecat:

Если кто-то шарит в LUA и/или C++ и готов на волонтерских началах помочь, буду очень благодарен.
Можно написать в лс на форуме или ответить в топике.
попробуй другой инжектор мб - процесс хакер, екстрим инжектор
 
Ниже код С++

C++:
Expand Collapse Copy
#include <windows.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <iostream>
#include <string>

#pragma comment(lib, "Psapi.lib")

// Opredelyaem strukturu dlya peredachi argumentov
struct RunParams {
    char windowTitle[256]; // Zagolovok okna
    char keyName[16];      // Nazvanie klavishi
};

// Funktsiya dlya polucheniya ID protsessa po ego imeni
DWORD GetProcessID(const wchar_t* processName) {
    PROCESSENTRY32W pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32W);

    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnapshot == INVALID_HANDLE_VALUE) return 0;

    if (Process32FirstW(hSnapshot, &pe32)) {
        do {
            if (wcscmp(pe32.szExeFile, processName) == 0) {
                CloseHandle(hSnapshot);
                return pe32.th32ProcessID;
            }
        } while (Process32NextW(hSnapshot, &pe32));
    }
    CloseHandle(hSnapshot);
    return 0;
}

// Funktsiya dlya in'ektsii DLL v protsess
void InjectDLL(HANDLE hProcess, const wchar_t* dllPath) {
    void* pDllPath = VirtualAllocEx(hProcess, NULL, (wcslen(dllPath) + 1) * sizeof(wchar_t), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if (!pDllPath) {
        std::cout << "Ne udalos' vydelit' pamyat' v protsesse." << std::endl;
        return;
    }

    WriteProcessMemory(hProcess, pDllPath, dllPath, (wcslen(dllPath) + 1) * sizeof(wchar_t), NULL);

    HANDLE hLoadThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryW"), pDllPath, 0, NULL);
    if (hLoadThread) {
        WaitForSingleObject(hLoadThread, INFINITE);
        CloseHandle(hLoadThread);
        std::cout << "DLL uspeshno zagruzheno v protsess." << std::endl;
    }
    else {
        std::cout << "Ne udalos' sozdать potok dlya zagruzki DLL." << std::endl;
    }

    VirtualFreeEx(hProcess, pDllPath, 0, MEM_RELEASE);
}

// Funktsiya dlya vyzova funktsii Run i peredachi parametrov
void CallRunFunction(HANDLE hProcess, const wchar_t* dllPath, const char* windowTitle, const char* keyName) {
    HMODULE hModule = LoadLibraryW(dllPath);
    if (!hModule) {
        std::cout << "Ne udalos' zagruzit' DLL v tekushchiy protsess." << std::endl;
        return;
    }

    FARPROC pRun = GetProcAddress(hModule, "Run");
    if (!pRun) {
        std::cout << "Ne udalos' nayti funktsiyu Run." << std::endl;
        FreeLibrary(hModule);
        return;
    }

    // Vydelyaem pamyat' dlya struktury parametrov
    void* pRunParams = VirtualAllocEx(hProcess, NULL, sizeof(RunParams), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if (!pRunParams) {
        std::cerr << "Ne udalos' vydelit' pamyat' dlya parametrov." << std::endl;
        FreeLibrary(hModule);
        return;
    }

    // Zapolnyaem strukturu parametrov
    RunParams params;
    strncpy_s(params.windowTitle, windowTitle, sizeof(params.windowTitle) - 1);
    strncpy_s(params.keyName, keyName, sizeof(params.keyName) - 1);

    // Zapisyvayem parametry v vydelennuyu pamyat'
    WriteProcessMemory(hProcess, pRunParams, &params, sizeof(RunParams), NULL);

    // Sozdaem potok dlya vyzova funktsii Run
    HANDLE hRunThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRun, pRunParams, 0, NULL);
    if (hRunThread) {
        WaitForSingleObject(hRunThread, INFINITE);
        CloseHandle(hRunThread);
        std::cout << "Funktsiya Run uspeshno vyzvana." << std::endl;
    }
    else {
        std::cout << "Ne udalos' sozdать potok dlya vyzova funktsii Run." << std::endl;
    }

    // Osvobozhdaem pamyat'
    VirtualFreeEx(hProcess, pRunParams, 0, MEM_RELEASE);
    FreeLibrary(hModule);
}

int main() {
    const wchar_t* processName = L"dota2.exe";
    const wchar_t* dllPath = L"C:\\Users\\sun\\source\\repos\\lua_loader_dll\\x64\\Debug\\lua_loader_dll.dll";
    const char* windowTitle = "Dota 2"; // Nazvanie okna, kuda budet in'ektirovatsya DLL
    const char* keyName = "B";                      // Nazvanie klavishi dlya nazhatiya

    DWORD processID = GetProcessID(processName);
    if (processID == 0) {
        std::cout << "Cannot find process Dota 2" << std::endl;
        return 1;
    }

    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
    if (!hProcess) {
        std::cout << "Cannot open process." << std::endl;
        return 1;
    }

    InjectDLL(hProcess, dllPath);
    CallRunFunction(hProcess, dllPath, windowTitle, keyName);

    CloseHandle(hProcess);
    return 0;
}

Ниже код DLL, которая подгружает LUA (это говнокод, но даже когда там был на первый взгляд норм код, он все равно не работал)
C++:
Expand Collapse Copy
#include "pch.h"
#include <windows.h>
#include <lua.hpp>
#include <iostream>

const char* luaCode = R"(-- Функция для проверки наличия Observer Wards в инвентаре
local function hasObserverWard(inventory)
    for i = 0, 5 do -- Индексы предметов в инвентаре
        local item = inventory:GetItemInSlot(i)
        if item and item:GetName() == "item_observer_ward" then
            return true -- Найдены Observer Wards
        end
    end
    return false -- Observer Wards не найдены
end

-- Функция для размещения Observer Wards
local function placeObserverWards()
    local hero = Entities:GetLocalPlayer():GetAssignedHero() -- Получаем локального героя
    if not hero then
        print("Hero not found!")
        return
    end

    local inventory = hero:GetInventory() -- Получаем инвентарь героя
    if hasObserverWard(inventory) then
        print("Observer Wards found in inventory.")
       
        -- Ищем позицию для размещения
        local targetPosition = Vector(0, 0, 0) -- Здесь вы можете указать координаты, где хотите разместить варды
        -- Логика размещения варда
        hero:CastAbilityOnPosition(targetPosition, hero:FindAbilityByName("item_observer_ward"), 0)
       
        print("Placing Observer Ward at position: ", targetPosition)
    else
        print("No Observer Wards found in inventory.")
    end
end

-- Основная функция, которая будет вызвана при запуске скрипта
local function main()
    print("Lua script is running.")
    placeObserverWards() -- Вызываем функцию размещения варда
end

-- Запускаем основной процесс
main()
)";

void ExecuteLuaScript() {
    lua_State* L = luaL_newstate(); // Create a new Lua state
    luaL_openlibs(L);                // Open standard Lua libraries

    // Load the Lua code from the string
    if (luaL_dostring(L, luaCode) != LUA_OK) {
        MessageBoxA(NULL, lua_tostring(L, -1), "Lua Error", MB_OK | MB_ICONERROR);
        lua_pop(L, 1); // Remove error message from the stack
        lua_close(L);  // Close Lua state
        return;
    }

    lua_close(L); // Close Lua state after execution
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
    if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
        ExecuteLuaScript(); // Execute Lua script on DLL attach
    }
    return TRUE;
}
ты вызываешь функции и используешь переменные которых не существует - Entities, GetLocalPlayer и т.д.
как оно по-твоему должно работать?
луа джаваскрипт питон джава и тд это языки которые совершенно ничего серьезного не умеют делать и сами по себе они абсолютно бесполезны, весь их прикол в том что к ним можно привязать прослойку написанную на С(++)(некоторые прослойки зачастую уже сразу при запуске привязываются, например часть стандартной библиотеки(например как luaL_openlibs это делает) и т.д.) которая уже будет делать работу, а язык будет ей "управлять"(давать ей работу).
имплементируй сам эти функции на С(++) и привязывай к луа машине.
если ты хочешь использовать луа апи доты -
1) она онли для сервера поэтому она на клиенте у тебя не будет работать. она предназначена для написания плагинов для сереров(кастомок кароче).
2) она привязана к дотовской луа машине а не к твоей собственной
 
ты вызываешь функции и используешь переменные которых не существует - Entities, GetLocalPlayer и т.д.
как оно по-твоему должно работать?
луа джаваскрипт питон джава и тд это языки которые совершенно ничего серьезного не умеют делать и сами по себе они абсолютно бесполезны, весь их прикол в том что к ним можно привязать прослойку написанную на С(++)(некоторые прослойки зачастую уже сразу при запуске привязываются, например часть стандартной библиотеки(например как luaL_openlibs это делает) и т.д.) которая уже будет делать работу, а язык будет ей "управлять"(давать ей работу).
имплементируй сам эти функции на С(++) и привязывай к луа машине.
если ты хочешь использовать луа апи доты -
1) она онли для сервера поэтому она на клиенте у тебя не будет работать. она предназначена для написания плагинов для сереров(кастомок кароче).
2) она привязана к дотовской луа машине а не к твоей собственной
спасибо
 
(некоторые прослойки зачастую уже сразу при запуске привязываются, например часть стандартной библиотеки(например как luaL_openlibs это делает) и т.д.) которая уже будет делать работу, а язык будет ей "управлять"(давать ей работу).
прикольно, получил ответ на свой вопрос не задавая его.
Хотел спросить за счёт чего вообще код написанный на LUA будет выполняться в Доте, если Lua API никакого под доту не написано, а ты говоришь, что и так что-то подтягивается
а какая вообще строчка кода отвечает за include lua в доту?
 
прикольно, получил ответ на свой вопрос не задавая его.
Хотел спросить за счёт чего вообще код написанный на LUA будет выполняться в Доте, если Lua API никакого под доту не написано, а ты говоришь, что и так что-то подтягивается
а какая вообще строчка кода отвечает за include lua в доту?
код написанный на луа(или джаваскрипт/питон/джава и т.д. там всё одинаково устроено) будет:
1) компилироваться в байткод, то есть: подвергаться лексическому анализу(простыми словами - разбиение по пробелам и знакам пунктуации и т.д. чтобы непрерывный поток символов разбить на лексемы/токены(слова)), подвергаться синтаксическому анализу(слова должны идти в правильном порядке и в правильной структуре/форме(ну например у функций скобочки должны быть, там аргументы и так далее, если нарушил синтаксис то ошибка)), подвергаться семантическому анализу(правильная структура еще не гарантия смысловой нагрузки, например, условно код в стиле int abc = "govno"; явно бессмысленный(из строки "говно" число нормально не делается), хоть и синтаксически правильный(тип есть, имя есть, присвоение есть, правая сторона присвоения есть) - ну т.е. тут проверка типов масштабов и прочей хрени(хотя у динамически типированных языков эта стадия компиляции слабая(по задумке), там ошибки этого класса в основном на рантайме(после запуска) тебе в ебало прилетают а не на стадии компиляции)), потом различные трансформации(оптимизация, линеаризация(из дерева(которое после всех анализов получилось. дерево сложно и неудобно выполнять) делается линейная последовательность(друг за другом) инструкций, всякие прыжки и так далее) и т.д.), потом генерируется байткод(виртуальные инструкции для виртуальной машины(интерпретатора байткода, а не гипервизора)) (у нативных языков вместо байткода обычно будет IR, потом его ассемблирование(в asm) и потом линкинг(несколько кусков asm(с разных сурс файлов) в одну большую кучу соединяется) и генерация исполняемого файла(PE(.exe/.dll), ELF, Mach-O))
2) интерпретироваться(полученный байткод скармливается интерпретатору и он в итоге делает какието нативные(asm, т.е. непосредственно на твоём процессоре) действия которые приводят к желаемому эффекту, условно есть виртуальная инструкция "умножить на два", и когда интерпретатор ее видит то он может прибавить число к самому себе, может поделить на 0.5, может сдвинуть влево на 1 бит и так далее не важно главное чтобы эффект был нужный(число в итоге в два раза больше стало)) (интерпретаторы обычно представляют собой stack- или register-based виртуальные машины(ну в основном stack-based))
3) один из самых важных механизмов скриптовых языков это привязка(native, binding и т. д. каждый язык по-своему называет); интерпретатору под каким-то именем привязывается С(++)-шная функция, и когда он видит это имя в (байт)коде то он вызывает соответствующую функцию на С(++)(интерпретатор обычно тоже на С(++) написан поэтому тут проблем нет никаких). без этого все бесполезно абсолютно(не сможешь ничего полезного сделать - ни файлы открывать, ни в консоль писать, нихуя вообще, кроме базовой арифметики всякой и всего остального что встроенно в сам язык)
4) есть ещё bytecode-to-asm(или source-to-asm сразу но обычно bytecode-to-asm так проще в разы) компиляторы(JIT их в простонародье называют хотя это просто класс компиляторов(AOT ещё есть) и одно другому не мешает, можно и AOT bytecode-to-asm компилить. не суть), они из байткода делают напрямую асм(но обычно требуют рантайму(кусок интерпретатора) в той или иной форме энивей - всякие гарбаж коллекторы и т.д.). ну они опциональны.
5) есть абсолютно древнее говно в котором построчно интерпретируется сурс(т.е. там сурс интерпретатор), но никто щас так уже не делает(там синтаксические и другие ошибки не репортит пока не дойдешь до этой строки, неудобно, да и сложно и неэффективно слишком). во всех нормальных языках(включая луа) там байткод интерпретируется(сурс -> AST(синтаксическое дерево) -> байткод -> интерпретатор).

соответственно тебе нужны компилятор в байткод и интерпретатор этого байткода(обычно в одном комплекте идут)
вот они например
Пожалуйста, авторизуйтесь для просмотра ссылки.
ты инитишь интерпретатор, компилишь свой луа сурс код, и кормишь полученный байткод этому интерпретатору.
перед этим, если надо, привязываешь свои С-шные функции к интерпретатору(стандартная библиотека тоже привязывается, через luaL_openlibs) (я своим высказыванием которые ты цитируешь имел ввиду что стандартная библиотека это точно такая же прослойка привязываемая, просто ее уже авторы предусмотрели и тебе ее писать не надо она в комплекте идёт, но написана она на С(++) и точно так же требует привязки. луа написан не на луа, и питон тоже написан не на питоне. у них у всех основная часть(как и сам язык, так и большая часть стандартной библиотеки) написана на С(++))
(это ты всё делаешь в своем интернал чите(.dll) который в доту инжектишь)
C++:
Expand Collapse Copy
#include <iostream>
#include <string>
#include <intrin.h>

extern "C"
{
#include "luacore/lua.h"
#include "luacore/lauxlib.h"
#include "luacore/lualib.h"
}

int main()
{
    lua_State* L = luaL_newstate();
    if (L)
    {
        std::cout << "created lua state." << std::endl;

        luaL_openlibs(L);

        struct WinUtils
        {
            static int GetVersion(lua_State* L)
            {
                static_assert(sizeof(void*) == 8); // VVV
                const auto* PEB = (const char*)__readgsqword(0x60);//AMD64
                if (PEB)
                {
                    unsigned long OSMajorVersion = *(unsigned long*)(PEB + 0x118);
                    unsigned long OSMinorVersion = *(unsigned long*)(PEB + 0x11C);
                    unsigned short OSBuildNumber = *(unsigned short*)(PEB + 0x120);
                    lua_newtable(L);

                    lua_pushstring(L, "OSMajorVersion");
                    lua_pushinteger(L, OSMajorVersion);
                    lua_settable(L, -3);

                    lua_pushstring(L, "OSMinorVersion");
                    lua_pushinteger(L, OSMinorVersion);
                    lua_settable(L, -3);

                    lua_pushstring(L, "OSBuildNumber");
                    lua_pushinteger(L, OSBuildNumber);
                    lua_settable(L, -3);
                    return 1;
                }
                return 0;
            }

            static int SetVersion(lua_State* L)
            {
                lua_getfield(L, 1, "OSMinorVersion");
                unsigned long OSMinorVersion = lua_tointeger(L, -1);

                lua_getfield(L, 1, "OSMajorVersion");
                unsigned long OSMajorVersion = lua_tointeger(L, -1);

                lua_getfield(L, 1, "OSBuildNumber");
                unsigned long OSBuildNumber = lua_tointeger(L, -1);

                std::cout << "OSMinorVersion " << OSMinorVersion << '\n';
                std::cout << "OSMajorVersion " << OSMajorVersion << '\n';
                std::cout << "OSBuildNumber " << OSBuildNumber << '\n';

                return 0;
            }

        };

        lua_newtable(L);

        lua_pushstring(L, "VersionUtils");
        lua_newtable(L);

        lua_pushstring(L, "GetVersion");
        lua_pushcclosure(L, WinUtils::GetVersion, 0);
        lua_settable(L, -3);

        lua_pushstring(L, "SetVersion");
        lua_pushcclosure(L, WinUtils::SetVersion, 0);
        lua_settable(L, -3);

        lua_settable(L, -3);

        lua_setglobal(L, "WinUtils");

        std::string_view script
        {
            R"(
            local ver = WinUtils.VersionUtils.GetVersion()
            for k,v in pairs(ver) do print(k, " : ", v) end
            ver.OSBuildNumber = 9999
            WinUtils.VersionUtils.SetVersion(ver)
            )"
        };
        if (!luaL_loadbufferx(L, script.data(), script.size(), "myscript", nullptr))
        {
            if (lua_pcallk(L, 0, 0, 0, 0, nullptr))
            {
                std::cout << "lua_pcallk error: " << lua_tolstring(L, -1, nullptr) << std::endl;
                lua_pop(L, 1);
            }
        }
        else
        {
            std::cout << "luaL_loadbufferx error: " << lua_tolstring(L, -1, nullptr) << std::endl;
            lua_pop(L, 1);
        }

        lua_close(L);
    }

    return 0;
}
(это не полный код, сам код луа компилятора и интерпретатора находится в куче .c файлов с гитхаба)
Код:
Expand Collapse Copy
    <ClCompile Include="luacore\lapi.c" />
    <ClCompile Include="luacore\lauxlib.c" />
    <ClCompile Include="luacore\lbaselib.c" />
    <ClCompile Include="luacore\lcode.c" />
    <ClCompile Include="luacore\lcorolib.c" />
    <ClCompile Include="luacore\lctype.c" />
    <ClCompile Include="luacore\ldblib.c" />
    <ClCompile Include="luacore\ldebug.c" />
    <ClCompile Include="luacore\ldo.c" />
    <ClCompile Include="luacore\ldump.c" />
    <ClCompile Include="luacore\lfunc.c" />
    <ClCompile Include="luacore\lgc.c" />
    <ClCompile Include="luacore\linit.c" />
    <ClCompile Include="luacore\liolib.c" />
    <ClCompile Include="luacore\llex.c" />
    <ClCompile Include="luacore\lmathlib.c" />
    <ClCompile Include="luacore\lmem.c" />
    <ClCompile Include="luacore\loadlib.c" />
    <ClCompile Include="luacore\lobject.c" />
    <ClCompile Include="luacore\lopcodes.c" />
    <ClCompile Include="luacore\loslib.c" />
    <ClCompile Include="luacore\lparser.c" />
    <ClCompile Include="luacore\lstate.c" />
    <ClCompile Include="luacore\lstring.c" />
    <ClCompile Include="luacore\lstrlib.c" />
    <ClCompile Include="luacore\ltable.c" />
    <ClCompile Include="luacore\ltablib.c" />
    <ClCompile Include="luacore\ltm.c" />
    <ClCompile Include="luacore\lundump.c" />
    <ClCompile Include="luacore\lutf8lib.c" />
    <ClCompile Include="luacore\lvm.c" />
    <ClCompile Include="luacore\lzio.c" />

в доте уже есть луа компилятор и интерпретатор НО там не привязано никаких интересностей(там серверные функции привязаны они тебе не нужны, это для серверной части кастомок используется). ты можешь либо из своего интернала насильно юзать дотовскую луа вм(но смысла нет ибо там нихуя не привязано интересного), либо сделать свою кастомку(и в ней свои луа скрипты) и загрузить её в доте(но в пабе это естественно не будет запускаться, и даже если бы запускалось то нихуя полезного не привязано все равно)
в двух словах - код в доте будет запускаться добровольно только если сама дота его захочет запустить(например если ты кастомку в доте загрузишь), либо это будет насильно(из твоего интернал чита). если насильно то лучше уж свою вм юзать(и не обязательно луа, можно джаваскрипт, питон, что захочешь, они практически все имеют embeddable имплементации). и если уж насильно то можно спокойно и без луа обойтись(всё равно на С(++) основная часть чита у тебя будет неизбежно). все скриптовые языки это необязательный беспомощный мусор(по задумке. это не техническое ограничение, это специально упрощённый и облегчённый дизайн, это авторы так сами придумывают.) который управляет С(++)-ной виртуальной машиной. вся работа всегда на С(++), скрипты лишь описывают что должно быть сделано(в абстрактном виде) а машина реально делает. без машины этими скриптами можно токо жопу подтереть, а машина на С(++), а на С(++) можно и без машины то же самое всё руками сделать если захотеть(ну скриптовые языки ориентированы на лёгкие задачи и они проще чем нативные и не требуют столько знаний и навыков) (это я не к тому что скриптовые языки говно или что-то ещё, а к тому что они работают поверх С(++) а не сами по себе(сами по себе они нихуя не могут и нихуя не делают))
 
Назад
Сверху Снизу