Browse Source

Add Lua support

pull/6697/head
Anders Jenbo 2 years ago
parent
commit
706010ee45
  1. 24
      3rdParty/Lua/CMakeLists.txt
  2. 1
      CMake/Assets.cmake
  3. 24
      CMake/Dependencies.cmake
  4. 26
      Packaging/resources/assets/lua/init.lua
  5. 3
      Source/CMakeLists.txt
  6. 4
      Source/diablo.cpp
  7. 147
      Source/utils/lua.cpp
  8. 11
      Source/utils/lua.hpp
  9. 2
      test/timedemo_test.cpp
  10. 8
      uwp-project/devilutionx.vcxproj
  11. 3
      vcpkg.json

24
3rdParty/Lua/CMakeLists.txt vendored

@ -0,0 +1,24 @@
include(functions/FetchContent_MakeAvailableExcludeFromAll)
set(LUA_ENABLE_TESTING OFF)
set(LUA_BUILD_COMPILER OFF)
if(DEVILUTIONX_STATIC_LUA)
set(LUA_ENABLE_SHARED OFF)
else()
set(LUA_ENABLE_SHARED ON)
endif()
include(FetchContent)
FetchContent_Declare(Lua
URL https://github.com/walterschell/Lua/archive/88246d621abf7b6fba9332f49229d507f020e450.tar.gz
URL_HASH MD5=03b76927cb5341ffc53bea12c37ddcca
)
FetchContent_MakeAvailableExcludeFromAll(Lua)
if(ANDROID AND ("${ANDROID_ABI}" STREQUAL "armeabi-v7a" OR "${ANDROID_ABI}" STREQUAL "x86"))
target_compile_definitions(lua_internal INTERFACE -DLUA_USE_C89)
elseif(NINTENDO_3DS OR VITA OR NINTENDO_SWITCH OR NXDK)
target_compile_definitions(lua_static PUBLIC -DLUA_USE_C89)
elseif(IOS)
target_compile_definitions(lua_static PUBLIC -DLUA_USE_IOS)
endif()

1
CMake/Assets.cmake

@ -137,6 +137,7 @@ set(devilutionx_assets
levels/l2data/bonechat.dun levels/l2data/bonechat.dun
levels/towndata/automap.dun levels/towndata/automap.dun
levels/towndata/automap.amp levels/towndata/automap.amp
lua/init.lua
nlevels/cutl5w.clx nlevels/cutl5w.clx
nlevels/cutl6w.clx nlevels/cutl6w.clx
nlevels/l5data/cornerstone.dun nlevels/l5data/cornerstone.dun

24
CMake/Dependencies.cmake

@ -24,6 +24,30 @@ if(SUPPORTS_MPQ)
endif() endif()
endif() endif()
find_package(Lua 5.4 QUIET)
if(LUA_FOUND)
message("-- Found Lua ${LUA_VERSION_STRING}")
# No clear way to statically link from the system lib
set(DEVILUTIONX_STATIC_LUA OFF)
else()
if(NOT DEFINED DEVILUTIONX_SYSTEM_LUA)
message("-- Suitable system Lua package not found, will use Lua from source")
set(DEVILUTIONX_SYSTEM_LUA OFF)
endif()
endif()
dependency_options("lua" DEVILUTIONX_SYSTEM_LUA ON DEVILUTIONX_STATIC_LUA)
if(NOT DEVILUTIONX_SYSTEM_LUA)
add_subdirectory(3rdParty/Lua)
if(DEVILUTIONX_STATIC_LUA)
set(LUA_LIBRARIES lua_static)
else()
set(LUA_LIBRARIES lua_shared)
endif()
else()
find_package(Lua 5.4 REQUIRED)
include_directories(${LUA_INCLUDE_DIR})
endif()
if(SCREEN_READER_INTEGRATION) if(SCREEN_READER_INTEGRATION)
if(WIN32) if(WIN32)
add_subdirectory(3rdParty/tolk) add_subdirectory(3rdParty/tolk)

26
Packaging/resources/assets/lua/init.lua

@ -0,0 +1,26 @@
Events = {}
function Events:RegisterEvent(eventName)
self[eventName] = {
Functions = {},
Add = function(func)
table.insert(self[eventName].Functions, func)
end,
Remove = function(func)
for i, f in ipairs(self[eventName].Functions) do
if f == func then
table.remove(self[eventName].Functions, i)
break
end
end
end,
Trigger = function()
for _, func in ipairs(self[eventName].Functions) do
func()
end
end,
}
end
Events:RegisterEvent("OnGameBoot")
Events:RegisterEvent("OnGameStart")

3
Source/CMakeLists.txt

@ -159,6 +159,7 @@ set(libdevilutionx_SRCS
utils/format_int.cpp utils/format_int.cpp
utils/language.cpp utils/language.cpp
utils/logged_fstream.cpp utils/logged_fstream.cpp
utils/lua.cpp
utils/paths.cpp utils/paths.cpp
utils/parse_int.cpp utils/parse_int.cpp
utils/pcx_to_clx.cpp utils/pcx_to_clx.cpp
@ -287,6 +288,8 @@ if(DISCORD_INTEGRATION)
target_link_libraries(libdevilutionx PRIVATE discord discord_game_sdk) target_link_libraries(libdevilutionx PRIVATE discord discord_game_sdk)
endif() endif()
target_link_libraries(libdevilutionx PRIVATE ${LUA_LIBRARIES})
if(SCREEN_READER_INTEGRATION AND WIN32) if(SCREEN_READER_INTEGRATION AND WIN32)
target_compile_definitions(libdevilutionx PRIVATE Tolk) target_compile_definitions(libdevilutionx PRIVATE Tolk)
endif() endif()

4
Source/diablo.cpp

@ -81,6 +81,7 @@
#include "utils/console.h" #include "utils/console.h"
#include "utils/display.h" #include "utils/display.h"
#include "utils/language.h" #include "utils/language.h"
#include "utils/lua.hpp"
#include "utils/parse_int.hpp" #include "utils/parse_int.hpp"
#include "utils/paths.h" #include "utils/paths.h"
#include "utils/screen_reader.hpp" #include "utils/screen_reader.hpp"
@ -822,6 +823,7 @@ void RunGameLoop(interface_mode uMsg)
nthread_ignore_mutex(false); nthread_ignore_mutex(false);
discord_manager::StartGame(); discord_manager::StartGame();
LuaEvent("OnGameStart");
#ifdef GPERF_HEAP_FIRST_GAME_ITERATION #ifdef GPERF_HEAP_FIRST_GAME_ITERATION
unsigned run_game_iteration = 0; unsigned run_game_iteration = 0;
#endif #endif
@ -1230,6 +1232,7 @@ void DiabloDeinit()
{ {
FreeItemGFX(); FreeItemGFX();
LuaShutdown();
ShutDownScreenReader(); ShutDownScreenReader();
if (gbSndInited) if (gbSndInited)
@ -2449,6 +2452,7 @@ int DiabloMain(int argc, char **argv)
LoadLanguageArchive(); LoadLanguageArchive();
ApplicationInit(); ApplicationInit();
LuaInitialize();
SaveOptions(); SaveOptions();
// Finally load game data // Finally load game data

147
Source/utils/lua.cpp

@ -0,0 +1,147 @@
#include "utils/lua.hpp"
#include <string_view>
extern "C" {
#include "lauxlib.h"
#include "lua.h"
#include "lualib.h"
}
#include "engine/assets.hpp"
#include "plrmsg.h"
#include "utils/console.h"
namespace devilution {
namespace {
lua_State *LuaState;
int LuaPrint(lua_State *state)
{
int nargs = lua_gettop(state);
if (nargs >= 1 && lua_isstring(state, 1)) {
std::string msg = lua_tostring(state, 1);
msg += "\n";
printInConsole(msg);
}
return 0;
}
int LuaPlayerMessage(lua_State *state)
{
int nargs = lua_gettop(state);
if (nargs >= 1 && lua_isstring(state, 1)) {
std::string_view msg = lua_tostring(state, 1);
EventPlrMsg(msg, UiFlags::ColorRed);
}
return 0;
}
void RunScript(std::string_view path)
{
AssetRef ref = FindAsset(path);
if (!ref.ok())
return;
const size_t size = ref.size();
std::unique_ptr<char[]> luaScript { new char[size + 1] };
AssetHandle handle = OpenAsset(std::move(ref));
if (!handle.ok())
return;
if (size > 0 && !handle.read(luaScript.get(), size))
return;
luaScript[size] = '\0'; // Terminate string
int status = luaL_loadstring(LuaState, luaScript.get());
if (status == LUA_OK)
status = lua_pcall(LuaState, 0, 0, 0);
if (status != LUA_OK)
SDL_Log("%s", lua_tostring(LuaState, -1));
}
} // namespace
void LuaInitialize()
{
LuaState = luaL_newstate();
// Load libraries
luaL_requiref(LuaState, LUA_GNAME, luaopen_base, 1);
lua_pop(LuaState, 1);
luaL_requiref(LuaState, LUA_LOADLIBNAME, luaopen_package, 1);
lua_pop(LuaState, 1);
luaL_requiref(LuaState, LUA_COLIBNAME, luaopen_coroutine, 1);
lua_pop(LuaState, 1);
luaL_requiref(LuaState, LUA_TABLIBNAME, luaopen_table, 1);
lua_pop(LuaState, 1);
luaL_requiref(LuaState, LUA_STRLIBNAME, luaopen_string, 1);
lua_pop(LuaState, 1);
luaL_requiref(LuaState, LUA_MATHLIBNAME, luaopen_math, 1);
lua_pop(LuaState, 1);
luaL_requiref(LuaState, LUA_UTF8LIBNAME, luaopen_utf8, 1);
lua_pop(LuaState, 1);
#ifdef _DEBUG
luaL_requiref(LuaState, LUA_DBLIBNAME, luaopen_debug, 1);
lua_pop(LuaState, 1);
#endif
// Registering globals
lua_register(LuaState, "print", LuaPrint);
lua_pushstring(LuaState, LUA_VERSION);
lua_setglobal(LuaState, "_VERSION");
// Registering devilutionx object table
lua_newtable(LuaState);
lua_pushcfunction(LuaState, LuaPlayerMessage);
lua_setfield(LuaState, -2, "message");
lua_setglobal(LuaState, "devilutionx");
RunScript("lua/init.lua");
RunScript("lua/user.lua");
LuaEvent("OnGameBoot");
}
void LuaShutdown()
{
if (LuaState == nullptr)
return;
lua_close(LuaState);
}
void LuaEvent(std::string name)
{
lua_getglobal(LuaState, "Events");
if (!lua_istable(LuaState, -1)) {
lua_pop(LuaState, 1);
SDL_Log("Events table missing!");
return;
}
lua_getfield(LuaState, -1, name.c_str());
if (!lua_istable(LuaState, -1)) {
lua_pop(LuaState, 2);
SDL_Log("Events.%s event not registered", name.c_str());
return;
}
lua_getfield(LuaState, -1, "Trigger");
if (!lua_isfunction(LuaState, -1)) {
lua_pop(LuaState, 3);
SDL_Log("Events.%s.Trigger is not a function", name.c_str());
return;
}
if (lua_pcall(LuaState, 0, 0, 0) != LUA_OK) {
SDL_Log("%s", lua_tostring(LuaState, -1));
}
lua_pop(LuaState, 2);
}
} // namespace devilution

11
Source/utils/lua.hpp

@ -0,0 +1,11 @@
#pragma once
#include <string>
namespace devilution {
void LuaInitialize();
void LuaShutdown();
void LuaEvent(std::string name);
} // namespace devilution

2
test/timedemo_test.cpp

@ -8,6 +8,7 @@
#include "pfile.h" #include "pfile.h"
#include "playerdat.hpp" #include "playerdat.hpp"
#include "utils/display.h" #include "utils/display.h"
#include "utils/lua.hpp"
#include "utils/paths.h" #include "utils/paths.h"
using namespace devilution; using namespace devilution;
@ -33,6 +34,7 @@ void RunTimedemo(std::string timedemoFolderName)
InitKeymapActions(); InitKeymapActions();
LoadOptions(); LoadOptions();
LuaInitialize();
const int demoNumber = 0; const int demoNumber = 0;

8
uwp-project/devilutionx.vcxproj

@ -73,8 +73,8 @@
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link> <Link>
<AdditionalDependencies>sdl_image.lib;libpng16_staticd.lib;pkware.lib;fmtd.lib;zlibstatic.lib;bzip2.lib;libsmackerdec.lib;libmpq.lib;libdevilutionx.lib;sdl2.lib;sdl_audiolib.lib;asio.lib;sodium.lib;zt.lib;lwip_pic.lib;miniupnpc_pic.lib;natpmp_pic.lib;zt_pic.lib;zto_pic.lib;shlwapi.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>sdl_image.lib;libpng16_staticd.lib;pkware.lib;fmtd.lib;zlibstatic.lib;bzip2.lib;libsmackerdec.lib;libmpq.lib;libdevilutionx.lib;lua_static.lib;sdl2.lib;sdl_audiolib.lib;asio.lib;sodium.lib;zt.lib;lwip_pic.lib;miniupnpc_pic.lib;natpmp_pic.lib;zt_pic.lib;zto_pic.lib;shlwapi.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\build\SDL\VisualC-WinRT\x64\Debug\SDL-UWP;..\build\3rdParty\SDL_image\Debug;..\build\_deps\zlib-build\Debug;..\build\3rdParty\PKWare\Debug;..\build\3rdParty\bzip2\Debug;..\build\3rdParty\libsmackerdec\Debug;..\build\3rdParty\libmpq\Debug;..\build\_deps\sdl_audiolib-build\Debug;..\build\3rdParty\asio\Release;..\build\_deps\libsodium-build\Debug;..\build\_deps\libzt-build\lib\Debug;..\build\_deps\libfmt-build\Debug;..\build\_deps\libpng-build\Debug;..\build\Source\libdevilutionx.dir\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>..\build\SDL\VisualC-WinRT\x64\Debug\SDL-UWP;..\build\3rdParty\SDL_image\Debug;..\build\_deps\zlib-build\Debug;..\build\3rdParty\PKWare\Debug;..\build\3rdParty\bzip2\Debug;..\build\3rdParty\libsmackerdec\Debug;..\build\3rdParty\libmpq\Debug;..\build\_deps\lua-build\lua-5.4.6\Debug;..\build\_deps\sdl_audiolib-build\Debug;..\build\3rdParty\asio\Debug;..\build\_deps\libsodium-build\Debug;..\build\_deps\libzt-build\lib\Debug;..\build\_deps\libfmt-build\Debug;..\build\_deps\libpng-build\Debug;..\build\Source\libdevilutionx.dir\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link> </Link>
<ClCompile> <ClCompile>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
@ -92,8 +92,8 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Link> <Link>
<AdditionalDependencies>sdl_image.lib;libpng16_static.lib;pkware.lib;fmt.lib;zlibstatic.lib;bzip2.lib;libsmackerdec.lib;libmpq.lib;libdevilutionx.lib;sdl2.lib;sdl_audiolib.lib;asio.lib;sodium.lib;zt.lib;lwip_pic.lib;miniupnpc_pic.lib;natpmp_pic.lib;zt_pic.lib;zto_pic.lib;shlwapi.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>sdl_image.lib;libpng16_static.lib;pkware.lib;fmt.lib;zlibstatic.lib;bzip2.lib;libsmackerdec.lib;libmpq.lib;libdevilutionx.lib;lua_static.lib;sdl2.lib;sdl_audiolib.lib;asio.lib;sodium.lib;zt.lib;lwip_pic.lib;miniupnpc_pic.lib;natpmp_pic.lib;zt_pic.lib;zto_pic.lib;shlwapi.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\build\SDL\VisualC-WinRT\x64\Release\SDL-UWP;..\build\3rdParty\SDL_image\Release;..\build\_deps\zlib-build\Release;..\build\3rdParty\PKWare\Release;..\build\3rdParty\bzip2\Release;..\build\3rdParty\libsmackerdec\Release;..\build\3rdParty\libmpq\Release;..\build\_deps\sdl_audiolib-build\Release;..\build\3rdParty\asio\Release;..\build\_deps\libsodium-build\Release;..\build\_deps\libzt-build\lib\Release;..\build\_deps\libfmt-build\Release;..\build\_deps\libpng-build\Release;..\build\Source\libdevilutionx.dir\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>..\build\SDL\VisualC-WinRT\x64\Release\SDL-UWP;..\build\3rdParty\SDL_image\Release;..\build\_deps\zlib-build\Release;..\build\3rdParty\PKWare\Release;..\build\3rdParty\bzip2\Release;..\build\3rdParty\libsmackerdec\Release;..\build\3rdParty\libmpq\Release;..\build\_deps\lua-build\lua-5.4.6\Release;..\build\_deps\sdl_audiolib-build\Release;..\build\3rdParty\asio\Release;..\build\_deps\libsodium-build\Release;..\build\_deps\libzt-build\lib\Release;..\build\_deps\libfmt-build\Release;..\build\_deps\libpng-build\Release;..\build\Source\libdevilutionx.dir\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link> </Link>
<ClCompile> <ClCompile>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>

3
vcpkg.json

@ -4,7 +4,8 @@
"dependencies": [ "dependencies": [
"fmt", "fmt",
"bzip2", "bzip2",
"simpleini" "simpleini",
"lua"
], ],
"builtin-baseline": "e8c2a04eb7ca058b6e2f0e6e33c67fdbffeee846", "builtin-baseline": "e8c2a04eb7ca058b6e2f0e6e33c67fdbffeee846",
"features": { "features": {

Loading…
Cancel
Save