Files
fs2open.github.com/code/scripting/lua.cpp
T
asarium 4a6628e16f Unify and clean up Lua documentation generation
I added a pretty generic container structure for the scripting
documentation when adding JSON output. However, I did not use that new
structure for the HTML output since that was just too much work.

This moves the HTML output over to the new structure so now the
scripting API handling code is independent from how the resulting
documentation is generated. I also moved that code out of the main
scripting code which removes quite a lot of clutter in those files.

This is mostly a straight port of the old code with no significant
changes (except the changes to make it use the new data).
2020-06-13 16:46:26 +02:00

234 lines
6.7 KiB
C++

#include "scripting/scripting.h"
#include "scripting_doc.h"
#include "scripting/lua/LuaUtil.h"
/**
* IMPORTANT!
*
* For various compiler reasons, all scripting API classes and libraries need to be referenced here! The easiest way to
* do this is to declare the API elements in the header with the DECLARE_* macros and then include them here
*/
#include "scripting/api/objs/asteroid.h"
#include "scripting/api/objs/background_element.h"
#include "scripting/api/objs/beam.h"
#include "scripting/api/objs/camera.h"
#include "scripting/api/objs/cockpit_display.h"
#include "scripting/api/objs/control_info.h"
#include "scripting/api/objs/controls.h"
#include "scripting/api/objs/debris.h"
#include "scripting/api/objs/enums.h"
#include "scripting/api/objs/event.h"
#include "scripting/api/objs/eye.h"
#include "scripting/api/objs/file.h"
#include "scripting/api/objs/font.h"
#include "scripting/api/objs/gameevent.h"
#include "scripting/api/objs/gamestate.h"
#include "scripting/api/objs/hudgauge.h"
#include "scripting/api/objs/mc_info.h"
#include "scripting/api/objs/message.h"
#include "scripting/api/objs/model.h"
#include "scripting/api/objs/object.h"
#include "scripting/api/objs/option.h"
#include "scripting/api/objs/order.h"
#include "scripting/api/objs/particle.h"
#include "scripting/api/objs/model_path.h"
#include "scripting/api/objs/physics_info.h"
#include "scripting/api/objs/player.h"
#include "scripting/api/objs/promise.h"
#include "scripting/api/objs/sexpvar.h"
#include "scripting/api/objs/shields.h"
#include "scripting/api/objs/ship.h"
#include "scripting/api/objs/ship_bank.h"
#include "scripting/api/objs/shipclass.h"
#include "scripting/api/objs/shiptype.h"
#include "scripting/api/objs/sound.h"
#include "scripting/api/objs/species.h"
#include "scripting/api/objs/streaminganim.h"
#include "scripting/api/objs/subsystem.h"
#include "scripting/api/objs/team.h"
#include "scripting/api/objs/texture.h"
#include "scripting/api/objs/texturemap.h"
#include "scripting/api/objs/time_obj.h"
#include "scripting/api/objs/vecmath.h"
#include "scripting/api/objs/waypoint.h"
#include "scripting/api/objs/weapon.h"
#include "scripting/api/objs/weaponclass.h"
#include "scripting/api/objs/wing.h"
#include "scripting/api/libs/audio.h"
#include "scripting/api/libs/async.h"
#include "scripting/api/libs/base.h"
#include "scripting/api/libs/bitops.h"
#include "scripting/api/libs/cfile.h"
#include "scripting/api/libs/engine.h"
#include "scripting/api/libs/graphics.h"
#include "scripting/api/libs/hookvars.h"
#include "scripting/api/libs/hud.h"
#include "scripting/api/libs/mission.h"
#include "scripting/api/libs/options.h"
#include "scripting/api/libs/parse.h"
#include "scripting/api/libs/tables.h"
#include "scripting/api/libs/testing.h"
#include "scripting/api/libs/time_lib.h"
#include "scripting/api/libs/ui.h"
#include "scripting/api/libs/utf8.h"
// End of definitions includes
using namespace scripting;
using namespace scripting::api;
// *************************Housekeeping*************************
static void *vm_lua_alloc(void*, void *ptr, size_t, size_t nsize) {
if (nsize == 0)
{
vm_free(ptr);
return NULL;
}
else
{
return vm_realloc(ptr, nsize);
}
}
//Inits LUA
//Note that "libraries" must end with a {NULL, NULL}
//element
int script_state::CreateLuaState()
{
mprintf(("LUA: Opening LUA state...\n"));
lua_State *L = lua_newstate(vm_lua_alloc, nullptr);
if(L == NULL)
{
Warning(LOCATION, "Could not initialize Lua");
return 0;
}
//*****INITIALIZE AUXILIARY LIBRARIES
mprintf(("LUA: Initializing base Lua libraries...\n"));
luaL_openlibs(L);
//*****INITIALIZE OUR SUPPORT LIBRARY
luacpp::util::initializeLuaSupportLib(L);
//*****DISABLE DANGEROUS COMMANDS
lua_pushstring(L, "os");
lua_rawget(L, LUA_GLOBALSINDEX);
int os_ldx = lua_gettop(L);
if(lua_istable(L, os_ldx))
{
lua_pushstring(L, "execute");
lua_pushnil(L);
lua_rawset(L, os_ldx);
lua_pushstring(L, "remove");
lua_pushnil(L);
lua_rawset(L, os_ldx);
lua_pushstring(L, "rename");
lua_pushnil(L);
lua_rawset(L, os_ldx);
}
lua_pop(L, 1); //os table
//*****INITIALIZE ADE
uint i;
mprintf(("LUA: Beginning ADE initialization\n"));
for(i = 0; i < ade_manager::getInstance()->getNumEntries(); i++)
{
//WMC - Do only toplevel table entries, doi
if(ade_manager::getInstance()->getEntry(i).ParentIdx == UINT_MAX) //WMC - oh hey, we're done with the meaty point in < 10 lines.
ade_manager::getInstance()->getEntry(i).SetTable(L, LUA_GLOBALSINDEX, LUA_GLOBALSINDEX); //Oh the miracles of OOP.
}
//*****INITIALIZE ENUMERATION CONSTANTS
mprintf(("ADE: Initializing enumeration constants...\n"));
enum_h eh;
for(i = 0; i < Num_enumerations; i++)
{
eh.index = Enumerations[i].def;
eh.is_constant = true;
ade_set_args(L, "o", l_Enum.Set(eh));
lua_setglobal(L, Enumerations[i].name);
}
//*****ASSIGN LUA SESSION
mprintf(("ADE: Assigning Lua session...\n"));
SetLuaSession(L);
//***** LOAD DEFAULT SCRIPTS
mprintf(("ADE: Loading default scripts...\n"));
load_default_script(L, "cfile_require.lua");
return 1;
}
void script_state::EndLuaFrame()
{
scripting::api::graphics_on_frame();
}
static bool sort_table_entries(const ade_table_entry* left, const ade_table_entry* right) {
const char* leftCmp = left->Name != nullptr ? left->Name : left->ShortName;
const char* rightCmp = right->Name != nullptr ? right->Name : left->ShortName;
if (leftCmp == nullptr) {
return false;
}
if (rightCmp == nullptr) {
return false;
}
SCP_string leftStr(leftCmp);
std::transform(std::begin(leftStr), std::end(leftStr), std::begin(leftStr),
[](char c) { return (char)::tolower(c); });
SCP_string rightStr(rightCmp);
std::transform(std::begin(rightStr), std::end(rightStr), std::begin(rightStr),
[](char c) { return (char)::tolower(c); });
return leftStr < rightStr;
}
static bool sort_doc_entries(const ade_table_entry* left, const ade_table_entry* right) {
if (left->Instanced == right->Instanced) {
// Same type -> compare as normal
return sort_table_entries(left, right);
}
if (left->Instanced) {
return true;
}
return false;
}
void script_state::OutputLuaDocumentation(ScriptingDocumentation& doc)
{
SCP_vector<ade_table_entry*> table_entries;
//***Everything
for (uint32_t i = 0; i < ade_manager::getInstance()->getNumEntries(); i++) {
auto ate = &ade_manager::getInstance()->getEntry(i);
if (ate->ParentIdx == UINT_MAX)
table_entries.push_back(ate);
}
std::sort(std::begin(table_entries), std::end(table_entries), sort_doc_entries);
for (auto entry : table_entries) {
doc.elements.emplace_back(entry->ToDocumentationElement());
}
//***Enumerations
for (uint32_t i = 0; i < Num_enumerations; i++) {
DocumentationEnum e;
e.name = Enumerations[i].name;
e.value = Enumerations[i].def;
doc.enumerations.push_back(e);
}
}