feat: add Lua 5.1 addon system with .toc loader and /run command

Foundation for WoW-compatible addon support:

- Vendor Lua 5.1.5 source as a static library (extern/lua-5.1.5)
- TocParser: parses .toc files (## directives + file lists)
- LuaEngine: Lua 5.1 VM with sandboxed stdlib (no io/os/debug),
  WoW-compatible print() that outputs to chat, GetTime() stub
- AddonManager: scans Data/interface/AddOns/ for .toc files,
  loads .lua files on world entry, skips LoadOnDemand addons
- /run <code> slash command for inline Lua execution
- HelloWorld test addon that prints to chat on load

Integration: AddonManager initialized after asset manager, addons
loaded once on first world entry, reset on logout. XML frame
parsing is deferred to a future step.
This commit is contained in:
Kelsi 2026-03-20 11:12:07 -07:00
parent 52064eb438
commit 290e9bfbd8
115 changed files with 29035 additions and 2 deletions

View file

@ -2,6 +2,7 @@
#include "rendering/character_preview.hpp"
#include "rendering/vk_context.hpp"
#include "core/application.hpp"
#include "addons/addon_manager.hpp"
#include "core/coordinates.hpp"
#include "core/spawn_presets.hpp"
#include "core/input.hpp"
@ -2629,7 +2630,7 @@ void GameScreen::renderChatWindow(game::GameHandler& gameHandler) {
"/p", "/party", "/petaggressive", "/petattack", "/petdefensive",
"/petdismiss", "/petfollow", "/pethalt", "/petpassive", "/petstay",
"/played", "/pvp",
"/r", "/raid", "/raidinfo", "/raidwarning", "/random", "/reply", "/roll",
"/r", "/raid", "/raidinfo", "/raidwarning", "/random", "/reply", "/roll", "/run",
"/s", "/say", "/screenshot", "/setloot", "/shout", "/sit", "/stand",
"/startattack", "/stopattack", "/stopcasting", "/stopfollow", "/stopmacro",
"/t", "/target", "/threat", "/time", "/trade",
@ -5993,6 +5994,19 @@ void GameScreen::sendChatMessage(game::GameHandler& gameHandler) {
std::string cmdLower = cmd;
for (char& c : cmdLower) c = std::tolower(c);
// /run <lua code> — execute Lua script via addon system
if ((cmdLower == "run" || cmdLower == "script") && spacePos != std::string::npos) {
std::string luaCode = command.substr(spacePos + 1);
auto* am = core::Application::getInstance().getAddonManager();
if (am) {
am->runScript(luaCode);
} else {
gameHandler.addUIError("Addon system not initialized.");
}
chatInputBuffer[0] = '\0';
return;
}
// Special commands
if (cmdLower == "logout") {
core::Application::getInstance().logoutToLogin();