tibia-rme/source/lua/lua_api_json.cpp
Humberto Gontijo c136a75263
fix: make macOS build with modern sol2 and wxGL (#201)
Bug Fixes:
- Improved Lua scripting: Lua-visible nil is now consistent for missing/empty values across storage, JSON parsing, item/map/tile APIs, dialogs, app properties, and overlay hover.
- Improved macOS graphics reliability (OpenGL context/linking) and safer background/thread handling for streaming and SQLite bootstrap.
- Fixed client asset loading paths and improved SQLite migration input paths.

UI Improvements:
- Replaced “Missing …” modal dialogs with inline text boxes.
- Made “Client directory” editable; added macOS app-picker browse flow.

CI:
- Added compile-scoped macOS builds via reusable workflow and a new build-macos job.
2026-07-29 19:44:25 -03:00

141 lines
3.8 KiB
C++

#include "main.h"
#include "lua_api_json.h"
#include <nlohmann/json.hpp>
namespace LuaAPI {
// Forward declarations
sol::object valueToLua(const nlohmann::json &val, sol::state_view &lua);
nlohmann::json luaToValue(const sol::object &obj);
// Convert nlohmann::json to Lua Object
sol::object valueToLua(const nlohmann::json &val, sol::state_view &lua) {
if (val.is_null()) {
return sol::lua_nil;
} else if (val.is_boolean()) {
return sol::make_object(lua, val.get<bool>());
} else if (val.is_number_integer()) {
return sol::make_object(lua, val.get<int64_t>());
} else if (val.is_number_float()) {
return sol::make_object(lua, val.get<double>());
} else if (val.is_string()) {
return sol::make_object(lua, val.get<std::string>());
} else if (val.is_array()) {
sol::table t = lua.create_table();
for (size_t i = 0; i < val.size(); ++i) {
t[i + 1] = valueToLua(val[i], lua); // Lua 1-based indexing
}
return t;
} else if (val.is_object()) {
sol::table t = lua.create_table();
for (auto &[key, value] : val.items()) {
t[key] = valueToLua(value, lua);
}
return t;
}
return sol::lua_nil;
}
// Convert Lua Object to nlohmann::json
nlohmann::json luaToValue(const sol::object &obj) {
switch (obj.get_type()) {
case sol::type::lua_nil:
return nullptr;
case sol::type::boolean:
return obj.as<bool>();
case sol::type::number: {
double d = obj.as<double>();
if (d == static_cast<int64_t>(d)) {
return static_cast<int64_t>(d);
}
return d;
}
case sol::type::string:
return obj.as<std::string>();
case sol::type::table: {
sol::table t = obj.as<sol::table>();
bool isArray = true;
size_t maxKey = 0;
size_t count = 0;
for (auto &pair : t) {
count++;
if (pair.first.get_type() == sol::type::number) {
double k = pair.first.as<double>();
if (k >= 1 && k == static_cast<size_t>(k)) {
size_t idx = static_cast<size_t>(k);
if (idx > maxKey) {
maxKey = idx;
}
} else {
isArray = false;
break;
}
} else {
isArray = false;
break;
}
}
if (isArray && count > 0 && maxKey != count) {
isArray = false;
}
if (count == 0) {
isArray = false;
}
if (isArray) {
nlohmann::json arr = nlohmann::json::array();
for (size_t i = 1; i <= count; ++i) {
arr.push_back(t[i].valid() ? luaToValue(t[i]) : nlohmann::json(nullptr));
}
return arr;
} else {
nlohmann::json objVal = nlohmann::json::object();
for (auto &pair : t) {
std::string key;
if (pair.first.get_type() == sol::type::string) {
key = pair.first.as<std::string>();
} else if (pair.first.get_type() == sol::type::number) {
key = std::to_string(pair.first.as<int64_t>());
} else {
continue;
}
objVal[key] = luaToValue(pair.second);
}
return objVal;
}
}
default:
return nullptr;
}
}
void registerJson(sol::state &lua) {
sol::table jsonTable = lua.create_table();
jsonTable.set_function("encode", [](sol::object obj, sol::this_state s) -> std::string {
nlohmann::json val = luaToValue(obj);
return val.dump(); // minified output
});
jsonTable.set_function("encode_pretty", [](sol::object obj, sol::this_state s) -> std::string {
nlohmann::json val = luaToValue(obj);
return val.dump(4); // pretty-printed with 4-space indent
});
jsonTable.set_function("decode", [](std::string jsonStr, sol::this_state s) -> sol::object {
try {
nlohmann::json val = nlohmann::json::parse(jsonStr);
sol::state_view lua(s);
return valueToLua(val, lua);
} catch (const nlohmann::json::parse_error &) {
return sol::lua_nil;
}
});
lua["json"] = jsonTable;
}
} // namespace LuaAPI