diff --git a/.github/workflows/PS5.yml b/.github/workflows/PS5.yml index 567f8301956..7b3532158bf 100644 --- a/.github/workflows/PS5.yml +++ b/.github/workflows/PS5.yml @@ -38,7 +38,7 @@ jobs: sudo apt install cmake pkg-config clang-15 lld-15 sudo apt install build-essential autoconf libtool yasm nasm sudo apt install smpq gperf pkgconf libarchive-tools autopoint po4a git curl doxygen wget - wget https://github.com/ps5-payload-dev/pacbrew-repo/releases/download/v0.18/ps5-payload-dev.tar.gz + wget https://github.com/ps5-payload-dev/pacbrew-repo/releases/download/v0.27/ps5-payload-dev.tar.gz sudo tar -xf ps5-payload-dev.tar.gz -C / - name: Build diff --git a/.github/workflows/vita.yml b/.github/workflows/vita.yml index 33d0e9a43c6..6308a86bb2c 100644 --- a/.github/workflows/vita.yml +++ b/.github/workflows/vita.yml @@ -36,7 +36,8 @@ jobs: apk add \ gettext \ git \ - samurai + samurai \ + patch - name: Configure CMake run: | diff --git a/3rdParty/Lua/CMakeLists.txt b/3rdParty/Lua/CMakeLists.txt index bc9c6f42811..fffed7ca87a 100644 --- a/3rdParty/Lua/CMakeLists.txt +++ b/3rdParty/Lua/CMakeLists.txt @@ -13,11 +13,14 @@ endif() include(FetchContent) FetchContent_Declare_ExcludeFromAll(Lua - URL https://github.com/walterschell/Lua/archive/88246d621abf7b6fba9332f49229d507f020e450.tar.gz - URL_HASH MD5=03b76927cb5341ffc53bea12c37ddcca + URL https://github.com/walterschell/Lua/archive/3ed55a56eaa05c9221f40b3c07d0e908eb1067b0.tar.gz + URL_HASH MD5=77907b8209f77c65cb681a5012f2d804 ) FetchContent_MakeAvailable_ExcludeFromAll(Lua) +# Needed for sol2 +set(LUA_VERSION_STRING "5.4.7" PARENT_SCOPE) + if(CMAKE_SYSTEM_NAME MATCHES "Darwin" AND DARWIN_MAJOR_VERSION VERSION_EQUAL 8) # We need legacy-support from MacPorts for: # localtime_r gmtime_r diff --git a/3rdParty/sol2/CMakeLists.txt b/3rdParty/sol2/CMakeLists.txt index c2b1a0c8dd2..3b1d4259182 100644 --- a/3rdParty/sol2/CMakeLists.txt +++ b/3rdParty/sol2/CMakeLists.txt @@ -1,11 +1,33 @@ include(functions/FetchContent_ExcludeFromAll_backport) +include(FetchContent) + +find_package(Patch REQUIRED) set(SOL2_ENABLE_INSTALL OFF) +set(SOL2_BUILD_LUA OFF) +set(SOL2_LUA_VERSION "${LUA_VERSION_STRING}") -include(FetchContent) FetchContent_Declare_ExcludeFromAll(sol2 - URL https://github.com/ThePhD/sol2/archive/2b0d2fe8ba0074e16b499940c4f3126b9c7d3471.tar.gz - URL_HASH MD5=869937e96e7c739b89920d12256fef4f + URL https://github.com/ThePhD/sol2/archive/c1f95a773c6f8f4fde8ca3efe872e7286afe4444.tar.gz + URL_HASH MD5=845ce869733636632d857d8517ac3eb5 + # https://github.com/ThePhD/sol2/pull/1712 + PATCH_COMMAND "${Patch_EXECUTABLE}" -p0 -N < ${CMAKE_CURRENT_LIST_DIR}/patches/0001-Reduce-cmake_minimum_required-to-3.22.patch || true + # https://github.com/ThePhD/sol2/pull/1722 + COMMAND "${Patch_EXECUTABLE}" -p0 -N < ${CMAKE_CURRENT_LIST_DIR}/patches/0002-Fix-array-index-out-of-bounds-in-stack_field.hpp.patch || true + # https://github.com/ThePhD/sol2/pull/1676 + COMMAND "${Patch_EXECUTABLE}" -p0 -N < ${CMAKE_CURRENT_LIST_DIR}/patches/0003-Change-end-to-sen-in-usertype_container.hpp.patch || true + # https://github.com/ThePhD/sol2/pull/1704 + COMMAND "${Patch_EXECUTABLE}" -p0 -N < ${CMAKE_CURRENT_LIST_DIR}/patches/0004-Fix-missing-Lua-Lua-target-when-using-system-Lua.patch || true + # https://github.com/ThePhD/sol2/pull/1705 + COMMAND "${Patch_EXECUTABLE}" -p0 -N < ${CMAKE_CURRENT_LIST_DIR}/patches/0005-fix-INTERFACE_LINK_LIBRARIES-property-for-lualib.patch || true + # https://github.com/ThePhD/sol2/pull/1716 + COMMAND "${Patch_EXECUTABLE}" -p0 -N < ${CMAKE_CURRENT_LIST_DIR}/patches/0006-Overload-stateless_reference_equals-and-stateless_re.patch || true + # https://github.com/ThePhD/sol2/pull/1716 + COMMAND "${Patch_EXECUTABLE}" -p0 -N < ${CMAKE_CURRENT_LIST_DIR}/patches/0007-Add-Nerixyz-s-test-and-fix-for-C-17.patch || true + # https://github.com/ThePhD/sol2/pull/1674 + COMMAND "${Patch_EXECUTABLE}" -p0 -N < ${CMAKE_CURRENT_LIST_DIR}/patches/0008-Faster-track-for-lightuserdata_value.patch || true + # https://github.com/ThePhD/sol2/pull/1722 + COMMAND "${Patch_EXECUTABLE}" -p0 -N < ${CMAKE_CURRENT_LIST_DIR}/patches/0009-Work-around-1581.patch || true ) FetchContent_MakeAvailable_ExcludeFromAll(sol2) diff --git a/3rdParty/sol2/patches/0001-Reduce-cmake_minimum_required-to-3.22.patch b/3rdParty/sol2/patches/0001-Reduce-cmake_minimum_required-to-3.22.patch new file mode 100644 index 00000000000..8c93fd16622 --- /dev/null +++ b/3rdParty/sol2/patches/0001-Reduce-cmake_minimum_required-to-3.22.patch @@ -0,0 +1,56 @@ +From d81d82dbea310f8491ec7a6e2cbcb78516c52b8d Mon Sep 17 00:00:00 2001 +From: Gleb Mazovetskiy +Date: Fri, 4 Jul 2025 18:44:27 +0100 +Subject: [PATCH 1/9] Reduce `cmake_minimum_required` to 3.22 + +Ubuntu 22.04 CMake is 3.22. +Debian stable CMake is 3.25. +Debian oldstable (EOL in 2026) has CMake 3.25 in bullseye-backports. +--- + CMakeLists.txt | 2 +- + documentation/CMakeLists.txt | 2 +- + single/CMakeLists.txt | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git CMakeLists.txt CMakeLists.txt +index b54f71a3..507d9be5 100644 +--- CMakeLists.txt ++++ CMakeLists.txt +@@ -22,7 +22,7 @@ + + # # # # sol2 + # # # Required minimum version statement +-cmake_minimum_required(VERSION 3.26.0) ++cmake_minimum_required(VERSION 3.22) + # # # Project Include - file that is included after project declaration is finished + set(CMAKE_PROJECT_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Includes/Project.cmake") + +diff --git documentation/CMakeLists.txt documentation/CMakeLists.txt +index 1c7b6758..ba780c0f 100644 +--- documentation/CMakeLists.txt ++++ documentation/CMakeLists.txt +@@ -22,7 +22,7 @@ + + # # # # sol2, documentation generation + # # # Required minimum version statement +-cmake_minimum_required(VERSION 3.26.0) ++cmake_minimum_required(VERSION 3.22) + + find_package(Doxygen REQUIRED) + find_package(Python3 REQUIRED) +diff --git single/CMakeLists.txt single/CMakeLists.txt +index 2d55fe32..a16926de 100644 +--- single/CMakeLists.txt ++++ single/CMakeLists.txt +@@ -22,7 +22,7 @@ + + # # # # sol3, single + # # # Required minimum version statement +-cmake_minimum_required(VERSION 3.26.0) ++cmake_minimum_required(VERSION 3.22) + + find_package(Python3 REQUIRED) + +-- +2.48.1 + diff --git a/3rdParty/sol2/patches/0002-Fix-array-index-out-of-bounds-in-stack_field.hpp.patch b/3rdParty/sol2/patches/0002-Fix-array-index-out-of-bounds-in-stack_field.hpp.patch new file mode 100644 index 00000000000..e79cdafd778 --- /dev/null +++ b/3rdParty/sol2/patches/0002-Fix-array-index-out-of-bounds-in-stack_field.hpp.patch @@ -0,0 +1,35 @@ +From 24241c564783a8dc9bca24aac69e0fb9cee76949 Mon Sep 17 00:00:00 2001 +From: martin nylin +Date: Tue, 11 Mar 2025 21:28:44 +0100 +Subject: [PATCH 2/9] Fix array index out of bounds in stack_field.hpp + +--- + include/sol/stack_field.hpp | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git include/sol/stack_field.hpp include/sol/stack_field.hpp +index 9dd66e2e..3b815225 100644 +--- include/sol/stack_field.hpp ++++ include/sol/stack_field.hpp +@@ -113,7 +113,17 @@ namespace sol { namespace stack { + lua_getglobal(L, &key[0]); + } + else { +- lua_getfield(L, tableindex, &key[0]); ++ if constexpr (std::is_same_v, const char*>) { ++ // Handle const char* case ++ if (key != nullptr) { ++ lua_getfield(L, tableindex, key); ++ } else { ++ push(L, lua_nil); ++ } ++ } else { ++ // Handle std::string case ++ lua_getfield(L, tableindex, key.c_str()); ++ } + } + } + else if constexpr (std::is_same_v) { +-- +2.48.1 + diff --git a/3rdParty/sol2/patches/0003-Change-end-to-sen-in-usertype_container.hpp.patch b/3rdParty/sol2/patches/0003-Change-end-to-sen-in-usertype_container.hpp.patch new file mode 100644 index 00000000000..79b6884f2f1 --- /dev/null +++ b/3rdParty/sol2/patches/0003-Change-end-to-sen-in-usertype_container.hpp.patch @@ -0,0 +1,25 @@ +From 12a596d1b592acccd0ddee7df3b4e33f25550ff8 Mon Sep 17 00:00:00 2001 +From: martin nylin +Date: Tue, 11 Mar 2025 20:58:43 +0100 +Subject: [PATCH 3/9] Change end() to sen() in usertype_container.hpp + +--- + include/sol/usertype_container.hpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git include/sol/usertype_container.hpp include/sol/usertype_container.hpp +index 6d25d2a8..3ff81724 100644 +--- include/sol/usertype_container.hpp ++++ include/sol/usertype_container.hpp +@@ -1189,7 +1189,7 @@ namespace sol { + static int next_associative(std::true_type, lua_State* L_) { + iter& i = stack::unqualified_get>(L_, 1); + auto& it = i.it(); +- auto& end = i.end(); ++ auto& end = i.sen(); + if (it == end) { + return stack::push(L_, lua_nil); + } +-- +2.48.1 + diff --git a/3rdParty/sol2/patches/0004-Fix-missing-Lua-Lua-target-when-using-system-Lua.patch b/3rdParty/sol2/patches/0004-Fix-missing-Lua-Lua-target-when-using-system-Lua.patch new file mode 100644 index 00000000000..a43079b5a68 --- /dev/null +++ b/3rdParty/sol2/patches/0004-Fix-missing-Lua-Lua-target-when-using-system-Lua.patch @@ -0,0 +1,27 @@ +From c5496869eab66dbf2ee1cb6d7f10536da809ace0 Mon Sep 17 00:00:00 2001 +From: syzygial <67280346+syzygial@users.noreply.github.com> +Date: Sat, 31 May 2025 22:38:52 -0400 +Subject: [PATCH 4/9] Fix missing Lua::Lua target when using system Lua + +--- + CMakeLists.txt | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git CMakeLists.txt CMakeLists.txt +index 507d9be5..ed1a6b59 100644 +--- CMakeLists.txt ++++ CMakeLists.txt +@@ -276,6 +276,10 @@ if (sol2-is-top-level-project) + set(LUA_LIBRARIES ${lualib}) + endif() + ++ if(NOT TARGET Lua::Lua) ++ add_library(Lua::Lua ALIAS ${lualib}) ++ endif() ++ + if (NOT LUA_FOUND AND NOT LUABUILD_FOUND) + message(FATAL_ERROR "sol2 Lua \"${SOL2_LUA_VERSION}\" not found and could not be targeted for building") + endif() +-- +2.48.1 + diff --git a/3rdParty/sol2/patches/0005-fix-INTERFACE_LINK_LIBRARIES-property-for-lualib.patch b/3rdParty/sol2/patches/0005-fix-INTERFACE_LINK_LIBRARIES-property-for-lualib.patch new file mode 100644 index 00000000000..4412a66f2e5 --- /dev/null +++ b/3rdParty/sol2/patches/0005-fix-INTERFACE_LINK_LIBRARIES-property-for-lualib.patch @@ -0,0 +1,25 @@ +From f433abdad78bf7601563674f292ac4c96b042220 Mon Sep 17 00:00:00 2001 +From: syzygial <67280346+syzygial@users.noreply.github.com> +Date: Sat, 31 May 2025 12:04:26 -0400 +Subject: [PATCH 5/9] fix INTERFACE_LINK_LIBRARIES property for lualib + +--- + CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git CMakeLists.txt CMakeLists.txt +index ed1a6b59..1e2edf9a 100644 +--- CMakeLists.txt ++++ CMakeLists.txt +@@ -270,7 +270,7 @@ if (sol2-is-top-level-project) + set_target_properties(${lualib} + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${LUA_INCLUDE_DIR} +- INTERFACE_LINK_LIBRARIES "${LUA_SEARCH_DEPENDENCY_LIBS} ${CMAKE_DL_LIBS}" ++ INTERFACE_LINK_LIBRARIES "${LUA_SEARCH_DEPENDENCY_LIBS};${CMAKE_DL_LIBS}" + IMPORTED_LINK_INTERFACE_LANGUAGES C + IMPORTED_LOCATION ${lualiblocation}) + set(LUA_LIBRARIES ${lualib}) +-- +2.48.1 + diff --git a/3rdParty/sol2/patches/0006-Overload-stateless_reference_equals-and-stateless_re.patch b/3rdParty/sol2/patches/0006-Overload-stateless_reference_equals-and-stateless_re.patch new file mode 100644 index 00000000000..f1542feff66 --- /dev/null +++ b/3rdParty/sol2/patches/0006-Overload-stateless_reference_equals-and-stateless_re.patch @@ -0,0 +1,51 @@ +From ee5af5e0564d1dad7d37e9849404b5be0849142f Mon Sep 17 00:00:00 2001 +From: Evil Eye +Date: Thu, 10 Jul 2025 17:53:18 +0200 +Subject: [PATCH 6/9] Overload stateless_reference_equals and + stateless_reference_hash to prevent implicit conversion of stack_reference to + stateless_reference + +--- + include/sol/reference.hpp | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git include/sol/reference.hpp include/sol/reference.hpp +index c7781552..e7be661a 100644 +--- include/sol/reference.hpp ++++ include/sol/reference.hpp +@@ -828,6 +828,8 @@ namespace sol { + stateless_reference_equals(lua_State* L_) noexcept : stateless_stack_reference_equals(L_) { + } + ++ using stateless_stack_reference_equals::operator(); ++ + bool operator()(const lua_nil_t& lhs, const stateless_reference& rhs) const noexcept { + return rhs.equals(lua_state(), lhs); + } +@@ -839,6 +841,14 @@ namespace sol { + bool operator()(const stateless_reference& lhs, const stateless_reference& rhs) const noexcept { + return lhs.equals(lua_state(), rhs); + } ++ ++ bool operator()(const stateless_stack_reference& lhs, const stateless_reference& rhs) const noexcept { ++ return rhs.equals(lua_state(), lhs); ++ } ++ ++ bool operator()(const stateless_reference& lhs, const stateless_stack_reference& rhs) const noexcept { ++ return lhs.equals(lua_state(), rhs); ++ } + }; + + struct reference_equals : public stack_reference_equals { +@@ -878,6 +888,8 @@ namespace sol { + stateless_reference_hash(lua_State* L_) noexcept : stateless_stack_reference_hash(L_) { + } + ++ using stateless_stack_reference_hash::operator(); ++ + result_type operator()(const stateless_reference& lhs) const noexcept { + std::hash h; + return h(lhs.pointer(lua_state())); +-- +2.48.1 + diff --git a/3rdParty/sol2/patches/0007-Add-Nerixyz-s-test-and-fix-for-C-17.patch b/3rdParty/sol2/patches/0007-Add-Nerixyz-s-test-and-fix-for-C-17.patch new file mode 100644 index 00000000000..69d232a9a86 --- /dev/null +++ b/3rdParty/sol2/patches/0007-Add-Nerixyz-s-test-and-fix-for-C-17.patch @@ -0,0 +1,200 @@ +From 6ec30440f64de88a2ac1e909532c99ae0c3ee61f Mon Sep 17 00:00:00 2001 +From: Evil Eye +Date: Sat, 12 Jul 2025 15:33:54 +0200 +Subject: [PATCH 7/9] Add Nerixyz's test and fix for C++17 + +--- + include/sol/usertype_storage.hpp | 4 ++ + tests/regression_tests/1716/CMakeLists.txt | 45 ++++++++++++++ + .../source/1716 - registry indexing leak.cpp | 61 +++++++++++++++++++ + tests/regression_tests/1716/source/main.cpp | 31 ++++++++++ + tests/regression_tests/CMakeLists.txt | 1 + + 5 files changed, 142 insertions(+) + create mode 100644 tests/regression_tests/1716/CMakeLists.txt + create mode 100644 tests/regression_tests/1716/source/1716 - registry indexing leak.cpp + create mode 100644 tests/regression_tests/1716/source/main.cpp + +diff --git include/sol/usertype_storage.hpp include/sol/usertype_storage.hpp +index bdca6146..691a025b 100644 +--- include/sol/usertype_storage.hpp ++++ include/sol/usertype_storage.hpp +@@ -502,7 +502,11 @@ namespace sol { namespace u_detail { + stateless_reference* target = nullptr; + { + stack_reference k = stack::get(L, 2); ++#if __cpp_lib_generic_unordered_lookup >= 201811L + auto it = self.auxiliary_keys.find(k); ++#else ++ auto it = self.auxiliary_keys.find(basic_reference(k)); ++#endif + if (it != self.auxiliary_keys.cend()) { + target = &it->second; + } +diff --git tests/regression_tests/1716/CMakeLists.txt tests/regression_tests/1716/CMakeLists.txt +new file mode 100644 +index 00000000..33ca975c +--- /dev/null ++++ tests/regression_tests/1716/CMakeLists.txt +@@ -0,0 +1,45 @@ ++# # # # sol2 ++# The MIT License (MIT) ++# ++# Copyright (c) 2013-2022 Rapptz, ThePhD, and contributors ++# ++# Permission is hereby granted, free of charge, to any person obtaining a copy of ++# this software and associated documentation files (the "Software"), to deal in ++# the Software without restriction, including without limitation the rights to ++# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ++# the Software, and to permit persons to whom the Software is furnished to do so, ++# subject to the following conditions: ++# ++# The above copyright notice and this permission notice shall be included in all ++# copies or substantial portions of the Software. ++# ++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ++# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ++# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ++# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ++# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ ++# # # # sol2 tests - simple regression tests ++ ++file(GLOB_RECURSE sources ++ LIST_DIRECTORIES FALSE ++ CONFIG_DEPENDS source/*.cpp) ++ ++sol2_create_basic_test(sol2.tests.regression_1716 sol2::sol2 ${sources}) ++sol2_create_basic_test(sol2.tests.regression_1716.SOL_ALL_SAFETIES_ON sol2::sol2 ${sources}) ++target_compile_options(sol2.tests.regression_1716 ++ PRIVATE ++ ${--allow-unreachable-code}) ++target_compile_definitions(sol2.tests.regression_1716.SOL_ALL_SAFETIES_ON ++ PRIVATE ++ SOL_ALL_SAFETIES_ON=1) ++target_compile_options(sol2.tests.regression_1716.SOL_ALL_SAFETIES_ON ++ PRIVATE ++ ${--allow-unreachable-code}) ++if (SOL2_TESTS_SINGLE) ++ sol2_create_basic_test(sol2.single.tests.regression_1716 sol2::sol2::single ${sources}) ++ target_compile_options(sol2.single.tests.regression_1716 ++ PRIVATE ++ ${--allow-unreachable-code}) ++endif() +diff --git tests/regression_tests/1716/source/1716 - registry indexing leak.cpp tests/regression_tests/1716/source/1716 - registry indexing leak.cpp +new file mode 100644 +index 00000000..9bc263f6 +--- /dev/null ++++ tests/regression_tests/1716/source/1716 - registry indexing leak.cpp +@@ -0,0 +1,61 @@ ++// sol2 ++ ++// The MIT License (MIT) ++ ++// Copyright (c) 2013-2022 Rapptz, ThePhD and contributors ++ ++// Permission is hereby granted, free of charge, to any person obtaining a copy of ++// this software and associated documentation files (the "Software"), to deal in ++// the Software without restriction, including without limitation the rights to ++// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ++// the Software, and to permit persons to whom the Software is furnished to do so, ++// subject to the following conditions: ++ ++// The above copyright notice and this permission notice shall be included in all ++// copies or substantial portions of the Software. ++ ++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ++// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ++// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ++// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ++// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ ++#include ++ ++#include ++ ++TEST_CASE("#1716 - index and newindex should not leak values into the registry", "[sol2][regression][issue1716]") { ++ class vector { ++ public: ++ vector() = default; ++ ++ static int my_index(vector&, int) { ++ return 0; ++ } ++ ++ static void my_new_index(vector&, int, int) { ++ return; ++ } ++ }; ++ ++ sol::state lua; ++ lua.open_libraries(sol::lib::base); ++ lua.new_usertype("vector", ++ sol::constructors>(), // ++ sol::meta_function::index, ++ &vector::my_index, // ++ sol::meta_function::new_index, ++ &vector::my_new_index); ++ auto begin = lua.registry().size(); ++ lua.script(R"( ++ local v = vector.new() ++ local unused = 0 ++ for i=1,100 do ++ unused = v[1] ++ v[1] = 1 ++ end ++ )"); ++ ++ REQUIRE(lua.registry().size() <= begin + 1); ++} +diff --git tests/regression_tests/1716/source/main.cpp tests/regression_tests/1716/source/main.cpp +new file mode 100644 +index 00000000..43e1e320 +--- /dev/null ++++ tests/regression_tests/1716/source/main.cpp +@@ -0,0 +1,31 @@ ++// sol2 ++ ++// The MIT License (MIT) ++ ++// Copyright (c) 2013-2022 Rapptz, ThePhD and contributors ++ ++// Permission is hereby granted, free of charge, to any person obtaining a copy of ++// this software and associated documentation files (the "Software"), to deal in ++// the Software without restriction, including without limitation the rights to ++// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ++// the Software, and to permit persons to whom the Software is furnished to do so, ++// subject to the following conditions: ++ ++// The above copyright notice and this permission notice shall be included in all ++// copies or substantial portions of the Software. ++ ++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ++// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ++// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ++// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ++// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ ++#define CATCH_CONFIG_RUNNER ++ ++#include ++ ++int main(int argc, char* argv[]) { ++ int result = Catch::Session().run(argc, argv); ++ return result; ++} +diff --git tests/regression_tests/CMakeLists.txt tests/regression_tests/CMakeLists.txt +index 7af8ed61..31400503 100644 +--- tests/regression_tests/CMakeLists.txt ++++ tests/regression_tests/CMakeLists.txt +@@ -23,4 +23,5 @@ + # # # # sol2 tests + + add_subdirectory(1011) ++add_subdirectory(1716) + add_subdirectory(simple) +-- +2.48.1 + diff --git a/3rdParty/sol2/patches/0008-Faster-track-for-lightuserdata_value.patch b/3rdParty/sol2/patches/0008-Faster-track-for-lightuserdata_value.patch new file mode 100644 index 00000000000..4c5bc339c46 --- /dev/null +++ b/3rdParty/sol2/patches/0008-Faster-track-for-lightuserdata_value.patch @@ -0,0 +1,65 @@ +From f0d0ef4007c64a5a91146d834375a1684d27241c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pawe=C5=82=20Per=C5=82akowski?= +Date: Tue, 25 Feb 2025 17:39:39 +0100 +Subject: [PATCH 8/9] Faster track for lightuserdata_value + +--- + include/sol/stack_check_qualified.hpp | 2 +- + include/sol/stack_check_unqualified.hpp | 4 +--- + include/sol/stack_core.hpp | 5 ++--- + 3 files changed, 4 insertions(+), 7 deletions(-) + +diff --git include/sol/stack_check_qualified.hpp include/sol/stack_check_qualified.hpp +index cc2394af..3ce5b642 100644 +--- include/sol/stack_check_qualified.hpp ++++ include/sol/stack_check_qualified.hpp +@@ -28,7 +28,7 @@ + + namespace sol { namespace stack { + +- template ++ template + struct qualified_checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { +diff --git include/sol/stack_check_unqualified.hpp include/sol/stack_check_unqualified.hpp +index d75557c4..18974987 100644 +--- include/sol/stack_check_unqualified.hpp ++++ include/sol/stack_check_unqualified.hpp +@@ -389,9 +389,7 @@ namespace sol { namespace stack { + return success; + } + else if constexpr (meta::is_specialization_of_v) { +- unqualified_checker c; +- (void)c; +- return c.check(L_, index, std::forward(handler), tracking); ++ return stack::unqualified_check>(L_, index, std::forward(handler), tracking); + } + else { + if constexpr (std::is_pointer_v) { +diff --git include/sol/stack_core.hpp include/sol/stack_core.hpp +index c4f5e203..2ce3ca2b 100644 +--- include/sol/stack_core.hpp ++++ include/sol/stack_core.hpp +@@ -571,7 +571,7 @@ namespace sol { + + template + struct unqualified_checker; +- template ++ template + struct qualified_checker; + + template +@@ -1002,8 +1002,7 @@ namespace sol { + return sol_lua_check(types(), L, index, std::forward(handler), tracking); + } + else { +- using Tu = meta::unqualified_t; +- qualified_checker> c{}; ++ qualified_checker c{}; + return c.check(L, index, std::forward(handler), tracking); + } + } +-- +2.48.1 + diff --git a/3rdParty/sol2/patches/0009-Work-around-1581.patch b/3rdParty/sol2/patches/0009-Work-around-1581.patch new file mode 100644 index 00000000000..328535588a2 --- /dev/null +++ b/3rdParty/sol2/patches/0009-Work-around-1581.patch @@ -0,0 +1,47 @@ +From 56cef1c15fb6f5b78e5debcb62d8ac914a0f007c Mon Sep 17 00:00:00 2001 +From: Gleb Mazovetskiy +Date: Sun, 20 Jul 2025 09:03:08 +0100 +Subject: [PATCH 9/9] Work around #1581 + +See https://github.com/ThePhD/sol2/issues/1581#issuecomment-2103463524 +--- + include/sol/function_types_stateless.hpp | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git include/sol/function_types_stateless.hpp include/sol/function_types_stateless.hpp +index a2f66ba0..fe0f3f0b 100644 +--- include/sol/function_types_stateless.hpp ++++ include/sol/function_types_stateless.hpp +@@ -320,7 +320,13 @@ namespace sol { namespace function_detail { + } + + template +- static int call(lua_State* L) noexcept(std::is_nothrow_copy_assignable_v) { ++ static int call(lua_State* L) ++#if SOL_IS_ON(SOL_COMPILER_CLANG) ++ // apparent regression in clang 18 - llvm/llvm-project#91362 ++#else ++ noexcept(std::is_nothrow_copy_assignable_v) ++#endif ++ { + int nr; + if constexpr (no_trampoline) { + nr = real_call(L); +@@ -360,7 +366,13 @@ namespace sol { namespace function_detail { + } + + template +- static int call(lua_State* L) noexcept(std::is_nothrow_copy_assignable_v) { ++ static int call(lua_State* L) ++#if SOL_IS_ON(SOL_COMPILER_CLANG) ++ // apparent regression in clang 18 - llvm/llvm-project#91362 ++#else ++ noexcept(std::is_nothrow_copy_assignable_v) ++#endif ++ { + int nr; + if constexpr (no_trampoline) { + nr = real_call(L); +-- +2.48.1 + diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 99747fcff70..cf6bf79305f 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -97,7 +97,7 @@ set(libdevilutionx_SRCS levels/trigs.cpp lua/autocomplete.cpp - lua/lua.cpp + lua/lua_global.cpp lua/modules/audio.cpp lua/modules/hellfire.cpp lua/modules/dev.cpp diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 2cba929e6b3..ea71166e72a 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -60,7 +60,7 @@ #include "levels/trigs.h" #include "lighting.h" #include "loadsave.h" -#include "lua/lua.hpp" +#include "lua/lua_global.hpp" #include "menu.h" #include "minitext.h" #include "missiles.h" diff --git a/Source/discord/discord.cpp b/Source/discord/discord.cpp index c4d3f546757..52f227a78d2 100644 --- a/Source/discord/discord.cpp +++ b/Source/discord/discord.cpp @@ -19,7 +19,7 @@ #include "config.h" #include "levels/gendung.h" #include "levels/setmaps.h" -#include "lua/lua.hpp" +#include "lua/lua_global.hpp" #include "multi.h" #include "panels/charpanel.hpp" #include "player.h" diff --git a/Source/engine/render/scrollrt.cpp b/Source/engine/render/scrollrt.cpp index 31c36a16465..3f77eb882c5 100644 --- a/Source/engine/render/scrollrt.cpp +++ b/Source/engine/render/scrollrt.cpp @@ -40,7 +40,7 @@ #include "levels/gendung.h" #include "levels/tile_properties.hpp" #include "lighting.h" -#include "lua/lua.hpp" +#include "lua/lua_global.hpp" #include "minitext.h" #include "missiles.h" #include "nthread.h" diff --git a/Source/lua/autocomplete.cpp b/Source/lua/autocomplete.cpp index 61279aaacff..2e8fe2c7398 100644 --- a/Source/lua/autocomplete.cpp +++ b/Source/lua/autocomplete.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -13,7 +14,7 @@ #include "appfat.h" #include "engine/assets.hpp" -#include "lua/lua.hpp" +#include "lua/lua_global.hpp" #include "lua/metadoc.hpp" #include "utils/algorithm/container.hpp" #include "utils/str_cat.hpp" @@ -121,8 +122,36 @@ ValueInfo GetValueInfo(const sol::table &table, std::string_view key, const sol: return info; } +ValueInfo GetValueInfoForUserdata(const sol::userdata &obj, std::string_view key, const sol::object &value, std::optional memberType) +{ + ValueInfo info; + if (value.get_type() == sol::type::userdata) { + info.callable = false; + return info; + } + + if (std::optional signature = GetLuaUserdataSignature(obj, key); signature.has_value()) { + info.signature = *std::move(signature); + } + if (std::optional docstring = GetLuaUserdataDocstring(obj, key); docstring.has_value()) { + info.docstring = *std::move(docstring); + } + if (memberType.has_value()) { + info.callable = *memberType == LuaUserdataMemberType::MemberFunction; + } else { + info.callable = value.get_type() == sol::type::function; + } + return info; +} + +struct UserdataQuery { + const sol::userdata *obj; + bool colonAccess; +}; + void SuggestionsFromTable(const sol::table &table, std::string_view prefix, - size_t maxSuggestions, ankerl::unordered_dense::set &out) + size_t maxSuggestions, ankerl::unordered_dense::set &out, + std::optional userdataQuery = std::nullopt) { for (const auto &[key, value] : table) { if (key.get_type() == sol::type::string) { @@ -136,7 +165,20 @@ void SuggestionsFromTable(const sol::table &table, std::string_view prefix, || keyStr.find("☢") != std::string::npos || keyStr.find("🔩") != std::string::npos) continue; - ValueInfo info = GetValueInfo(table, keyStr, value); + ValueInfo info; + std::optional memberType; + if (userdataQuery.has_value()) { + memberType = GetLuaUserdataMemberType(*userdataQuery->obj, keyStr, value); + const bool requiresColonAccess = memberType.has_value() + ? *memberType == LuaUserdataMemberType::MemberFunction + : value.get_type() == sol::type::function; + if (userdataQuery->colonAccess != requiresColonAccess) { + continue; + } + info = GetValueInfoForUserdata(*userdataQuery->obj, keyStr, value, memberType); + } else { + info = GetValueInfo(table, keyStr, value); + } std::string completionText = keyStr.substr(prefix.size()); LuaAutocompleteSuggestion suggestion { std::move(keyStr), std::move(completionText) }; if (info.callable) { @@ -144,6 +186,9 @@ void SuggestionsFromTable(const sol::table &table, std::string_view prefix, suggestion.cursorAdjust = -1; } if (!info.signature.empty()) { + if (memberType.has_value() && memberType != LuaUserdataMemberType::MemberFunction) { + StrAppend(suggestion.displayText, ": "); + } StrAppend(suggestion.displayText, info.signature); } if (!info.docstring.empty()) { @@ -164,18 +209,52 @@ void SuggestionsFromTable(const sol::table &table, std::string_view prefix, } } +void SuggestionsFromUserdata(UserdataQuery query, std::string_view prefix, + size_t maxSuggestions, ankerl::unordered_dense::set &out) +{ + const auto &meta = query.obj->get>(sol::metatable_key); + if (meta.has_value() && meta->get_type() == sol::type::table) { + SuggestionsFromTable(meta->as(), prefix, maxSuggestions, out, query); + } +} + +bool IsAlnum(char c) +{ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); +} + +bool IsIdentifierChar(char c) +{ + return IsAlnum(c) || c == '_'; +} + +bool IsIdentifierOrExprChar(char c) +{ + return IsIdentifierChar(c) || c == '-' || c == '+' || c == '*' || c == '/' || c == '='; +} + } // namespace -void GetLuaAutocompleteSuggestions(std::string_view text, const sol::environment &lua, +void GetLuaAutocompleteSuggestions(std::string_view text, size_t cursorPos, const sol::environment &lua, size_t maxSuggestions, std::vector &out) { out.clear(); - if (text.empty()) return; - std::string_view token = GetLastToken(text); - const char prevChar = token.data() == text.data() ? '\0' : *(token.data() - 1); + const std::string_view textPrefix = text.substr(0, cursorPos); + if (textPrefix.empty()) return; + const std::string_view textSuffix = text.substr(cursorPos); + if (!textSuffix.empty()) { + const char c = textSuffix[0]; + if (IsIdentifierOrExprChar(c) || (c == ' ' && textSuffix.size() > 1)) return; + } + if (textPrefix.size() >= 2 && textPrefix.back() == ' ' && IsIdentifierChar(textPrefix[textPrefix.size() - 2])) { + return; + } + std::string_view token = GetLastToken(textPrefix); + const char prevChar = token.data() == textPrefix.data() ? '\0' : *(token.data() - 1); if (prevChar == '(' || prevChar == ',') return; - const size_t dotPos = token.rfind('.'); + const size_t dotPos = token.find_last_of(".:"); const std::string_view prefix = token.substr(dotPos + 1); + const char completionChar = dotPos != std::string_view::npos ? token[dotPos] : '\0'; token.remove_suffix(token.size() - (dotPos == std::string_view::npos ? 0 : dotPos)); ankerl::unordered_dense::set suggestions; @@ -192,13 +271,20 @@ void GetLuaAutocompleteSuggestions(std::string_view text, const sol::environment } } else { std::optional obj = lua; - for (const std::string_view part : SplitByChar(token, '.')) { - obj = obj->as().get>(part); - if (!obj.has_value() || obj->get_type() != sol::type::table) - return; + for (const std::string_view partDot : SplitByChar(token, '.')) { + for (const std::string_view part : SplitByChar(partDot, ':')) { + obj = obj->as().get>(part); + if (!obj.has_value() || !(obj->get_type() == sol::type::table || obj->get_type() == sol::type::userdata)) { + return; + } + } } if (obj->get_type() == sol::type::table) { addSuggestions(obj->as()); + } else if (obj->get_type() == sol::type::userdata) { + const sol::userdata &data = obj->as(); + SuggestionsFromUserdata(UserdataQuery { .obj = &data, .colonAccess = completionChar == ':' }, + prefix, maxSuggestions, suggestions); } } diff --git a/Source/lua/autocomplete.hpp b/Source/lua/autocomplete.hpp index 464d40039f6..6d0cdb63e73 100644 --- a/Source/lua/autocomplete.hpp +++ b/Source/lua/autocomplete.hpp @@ -26,7 +26,7 @@ struct LuaAutocompleteSuggestion { }; void GetLuaAutocompleteSuggestions( - std::string_view text, const sol::environment &lua, + std::string_view text, size_t cursorPos, const sol::environment &lua, size_t maxSuggestions, std::vector &out); } // namespace devilution diff --git a/Source/lua/lua.cpp b/Source/lua/lua_global.cpp similarity index 96% rename from Source/lua/lua.cpp rename to Source/lua/lua_global.cpp index 33acf5e49e8..767147836aa 100644 --- a/Source/lua/lua.cpp +++ b/Source/lua/lua_global.cpp @@ -1,9 +1,10 @@ -#include "lua/lua.hpp" +#include "lua/lua_global.hpp" #include #include #include +#include #include #include diff --git a/Source/lua/lua.hpp b/Source/lua/lua_global.hpp similarity index 100% rename from Source/lua/lua.hpp rename to Source/lua/lua_global.hpp diff --git a/Source/lua/metadoc.hpp b/Source/lua/metadoc.hpp index c3baf04bd96..7be85291f3b 100644 --- a/Source/lua/metadoc.hpp +++ b/Source/lua/metadoc.hpp @@ -1,13 +1,23 @@ #pragma once -#include - +#include +#include +#include #include +#include + #include "utils/str_cat.hpp" namespace devilution { +enum class LuaUserdataMemberType : uint8_t { + ReadonlyProperty, + Property, + MemberFunction, + Constructor, +}; + inline std::string LuaSignatureKey(std::string_view key) { return StrCat("__sig_", key); @@ -18,33 +28,74 @@ inline std::string LuaDocstringKey(std::string_view key) return StrCat("__doc_", key); } +inline std::string LuaUserdataMemberTypeKey(std::string_view key) +{ + return StrCat("__udt_", key); +} + +namespace lua_metadoc_internal { +template +void SetUsertypeSignatureAndDocstring(sol::usertype &table, std::string_view key, const char *signature, const char *doc, LuaUserdataMemberType memberType) +{ + table.set(LuaSignatureKey(key), sol::var(signature)); + table.set(LuaDocstringKey(key), sol::var(doc)); + table.set(LuaUserdataMemberTypeKey(key), sol::var(static_cast(memberType))); +} + +inline void SetSignatureAndDocstring(sol::table &table, std::string_view key, const char *signature, const char *doc) +{ + table.set(LuaSignatureKey(key), signature); + table.set(LuaDocstringKey(key), doc); +} +} // namespace lua_metadoc_internal + template -void SetDocumented(sol::usertype &table, std::string_view key, std::string_view signature, std::string_view doc, T &&value) +void LuaSetDocFn(sol::usertype &table, std::string_view key, const char *signature, const char *doc, T &&value) +{ + table.set_function(key, std::forward(value)); + lua_metadoc_internal::SetUsertypeSignatureAndDocstring(table, key, signature, doc, LuaUserdataMemberType::MemberFunction); +} + +template +void LuaSetDocReadonlyProperty(sol::usertype &table, std::string_view key, const char *type, const char *doc, G &&getter) { - table[key] = std::forward(value); - // TODO: figure out a way to set signature and docstring. + table.set(key, sol::readonly_property(std::forward(getter))); + lua_metadoc_internal::SetUsertypeSignatureAndDocstring(table, key, type, doc, LuaUserdataMemberType::ReadonlyProperty); } template -void SetDocumented(sol::usertype &table, std::string_view key, std::string_view signature, std::string_view doc, G &&getter, S &&setter) +void LuaSetDocProperty(sol::usertype &table, std::string_view key, const char *type, const char *doc, G &&getter, S &&setter) { - table[key] = sol::property(std::forward(getter), std::forward(setter)); - // TODO: figure out a way to set signature and docstring. + table.set(key, sol::property(std::forward(getter), std::forward(setter))); + lua_metadoc_internal::SetUsertypeSignatureAndDocstring(table, key, type, doc, LuaUserdataMemberType::Property); +} + +template +void LuaSetDocProperty(sol::usertype &table, std::string_view key, const char *type, const char *doc, F U::*&&value) +{ + table.set(key, value); + lua_metadoc_internal::SetUsertypeSignatureAndDocstring(table, key, type, doc, LuaUserdataMemberType::Property); +} + +template +void LuaSetDoc(sol::table &table, std::string_view key, const char *signature, const char *doc, T &&value) +{ + table.set(key, std::forward(value)); + lua_metadoc_internal::SetSignatureAndDocstring(table, key, signature, doc); } template -void SetDocumented(sol::table &table, std::string_view key, std::string_view signature, std::string_view doc, T &&value) +void LuaSetDocFn(sol::table &table, std::string_view key, const char *signature, const char *doc, T &&value) { - table[key] = std::forward(value); - table[LuaSignatureKey(key)] = signature; - table[LuaDocstringKey(key)] = doc; + table.set_function(key, std::forward(value)); + lua_metadoc_internal::SetSignatureAndDocstring(table, key, signature, doc); } template -void SetWithSignature(sol::table &table, std::string_view key, std::string_view signature, T &&value) +void LuaSetDocFn(sol::table &table, std::string_view key, const char *signature, T &&value) { - table[key] = std::forward(value); - table[LuaSignatureKey(key)] = signature; + table.set_function(key, std::forward(value)); + table.set(LuaSignatureKey(key), signature); } inline std::optional GetSignature(const sol::table &table, std::string_view key) @@ -57,4 +108,25 @@ inline std::optional GetDocstring(const sol::table &table, std::str return table.get>(LuaDocstringKey(key)); } +inline std::optional GetLuaUserdataSignature(const sol::userdata &obj, std::string_view key) +{ + return obj.get>(LuaSignatureKey(key)); +} + +inline std::optional GetLuaUserdataDocstring(const sol::userdata &obj, std::string_view key) +{ + return obj.get>(LuaDocstringKey(key)); +} + +inline std::optional GetLuaUserdataMemberType(const sol::userdata &obj, std::string_view key, const sol::object &value) +{ + std::optional result = obj.get>(LuaUserdataMemberTypeKey(key)); + if (!result.has_value()) { + if (value.get_type() == sol::type::userdata) return LuaUserdataMemberType::Property; + if (value.get_type() == sol::type::function && key == "new") return LuaUserdataMemberType::Constructor; + return std::nullopt; + } + return static_cast(*result); +} + } // namespace devilution diff --git a/Source/lua/modules/audio.cpp b/Source/lua/modules/audio.cpp index 8e486fcd541..f8ab0a7e230 100644 --- a/Source/lua/modules/audio.cpp +++ b/Source/lua/modules/audio.cpp @@ -19,10 +19,10 @@ bool IsValidSfx(int16_t psfx) sol::table LuaAudioModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetWithSignature(table, + LuaSetDocFn(table, "playSfx", "(id: number)", [](int16_t psfx) { if (IsValidSfx(psfx)) PlaySFX(static_cast(psfx)); }); - SetWithSignature(table, + LuaSetDocFn(table, "playSfxLoc", "(id: number, x: number, y: number)", [](int16_t psfx, int x, int y) { if (IsValidSfx(psfx)) PlaySfxLoc(static_cast(psfx), { x, y }); }); return table; diff --git a/Source/lua/modules/dev.cpp b/Source/lua/modules/dev.cpp index e3de74633d7..2778cdf1bca 100644 --- a/Source/lua/modules/dev.cpp +++ b/Source/lua/modules/dev.cpp @@ -18,14 +18,14 @@ namespace devilution { sol::table LuaDevModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "display", "", "Debugging HUD and rendering commands.", LuaDevDisplayModule(lua)); - SetDocumented(table, "items", "", "Item-related commands.", LuaDevItemsModule(lua)); - SetDocumented(table, "level", "", "Level-related commands.", LuaDevLevelModule(lua)); - SetDocumented(table, "monsters", "", "Monster-related commands.", LuaDevMonstersModule(lua)); - SetDocumented(table, "player", "", "Player-related commands.", LuaDevPlayerModule(lua)); - SetDocumented(table, "quests", "", "Quest-related commands.", LuaDevQuestsModule(lua)); - SetDocumented(table, "search", "", "Search the map for monsters / items / objects.", LuaDevSearchModule(lua)); - SetDocumented(table, "towners", "", "Town NPC commands.", LuaDevTownersModule(lua)); + LuaSetDoc(table, "display", "", "Debugging HUD and rendering commands.", LuaDevDisplayModule(lua)); + LuaSetDoc(table, "items", "", "Item-related commands.", LuaDevItemsModule(lua)); + LuaSetDoc(table, "level", "", "Level-related commands.", LuaDevLevelModule(lua)); + LuaSetDoc(table, "monsters", "", "Monster-related commands.", LuaDevMonstersModule(lua)); + LuaSetDoc(table, "player", "", "Player-related commands.", LuaDevPlayerModule(lua)); + LuaSetDoc(table, "quests", "", "Quest-related commands.", LuaDevQuestsModule(lua)); + LuaSetDoc(table, "search", "", "Search the map for monsters / items / objects.", LuaDevSearchModule(lua)); + LuaSetDoc(table, "towners", "", "Town NPC commands.", LuaDevTownersModule(lua)); return table; } diff --git a/Source/lua/modules/dev/display.cpp b/Source/lua/modules/dev/display.cpp index 2e4f44f4afd..c00f9965a8b 100644 --- a/Source/lua/modules/dev/display.cpp +++ b/Source/lua/modules/dev/display.cpp @@ -121,13 +121,13 @@ std::string DebugCmdToggleFPS(std::optional on) sol::table LuaDevDisplayModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "fps", "(name: string = nil)", "Toggle FPS display.", &DebugCmdToggleFPS); - SetDocumented(table, "fullbright", "(on: boolean = nil)", "Toggle light shading.", &DebugCmdFullbright); - SetDocumented(table, "grid", "(on: boolean = nil)", "Toggle showing the grid.", &DebugCmdShowGrid); - SetDocumented(table, "path", "(on: boolean = nil)", "Toggle path debug rendering.", &DebugCmdPath); - SetDocumented(table, "scrollView", "(on: boolean = nil)", "Toggle view scrolling via Shift+Mouse.", &DebugCmdScrollView); - SetDocumented(table, "tileData", "(name: string = nil)", "Toggle showing tile data.", &DebugCmdShowTileData); - SetDocumented(table, "vision", "(on: boolean = nil)", "Toggle vision debug rendering.", &DebugCmdVision); + LuaSetDocFn(table, "fps", "(name: string = nil)", "Toggle FPS display.", &DebugCmdToggleFPS); + LuaSetDocFn(table, "fullbright", "(on: boolean = nil)", "Toggle light shading.", &DebugCmdFullbright); + LuaSetDocFn(table, "grid", "(on: boolean = nil)", "Toggle showing the grid.", &DebugCmdShowGrid); + LuaSetDocFn(table, "path", "(on: boolean = nil)", "Toggle path debug rendering.", &DebugCmdPath); + LuaSetDocFn(table, "scrollView", "(on: boolean = nil)", "Toggle view scrolling via Shift+Mouse.", &DebugCmdScrollView); + LuaSetDocFn(table, "tileData", "(name: string = nil)", "Toggle showing tile data.", &DebugCmdShowTileData); + LuaSetDocFn(table, "vision", "(on: boolean = nil)", "Toggle vision debug rendering.", &DebugCmdVision); return table; } diff --git a/Source/lua/modules/dev/items.cpp b/Source/lua/modules/dev/items.cpp index da989c2ccbe..6a8dd46bcb0 100644 --- a/Source/lua/modules/dev/items.cpp +++ b/Source/lua/modules/dev/items.cpp @@ -20,21 +20,24 @@ namespace devilution { namespace { -std::string DebugCmdItemInfo() +const Item *DebugCmdGetItem() { - Player &myPlayer = *MyPlayer; - Item *pItem = nullptr; - if (!myPlayer.HoldItem.isEmpty()) { - pItem = &myPlayer.HoldItem; - } else if (pcursinvitem != -1) { - if (pcursinvitem <= INVITEM_INV_LAST) - pItem = &myPlayer.InvList[pcursinvitem - INVITEM_INV_FIRST]; - else - pItem = &myPlayer.SpdList[pcursinvitem - INVITEM_BELT_FIRST]; - } else if (pcursitem != -1) { - pItem = &Items[pcursitem]; + const Player &myPlayer = *MyPlayer; + if (!myPlayer.HoldItem.isEmpty()) return &myPlayer.HoldItem; + if (pcursinvitem != -1) { + if (pcursinvitem < INVITEM_INV_FIRST) return &myPlayer.InvBody[pcursinvitem]; + if (pcursinvitem <= INVITEM_INV_LAST) return &myPlayer.InvList[pcursinvitem - INVITEM_INV_FIRST]; + return &myPlayer.SpdList[pcursinvitem - INVITEM_BELT_FIRST]; } + if (pcursitem != -1) return &Items[pcursitem]; + return nullptr; +} + +std::string DebugCmdItemInfo() +{ + const Item *pItem = DebugCmdGetItem(); if (pItem != nullptr) { + const Player &myPlayer = *MyPlayer; std::string_view netPackValidation { "N/A" }; if (gbIsMultiplayer) { ItemNetPack itemPack; @@ -194,9 +197,10 @@ std::string DebugSpawnUniqueItem(std::string itemName) sol::table LuaDevItemsModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "info", "()", "Show info of currently selected item.", &DebugCmdItemInfo); - SetDocumented(table, "spawn", "(name: string)", "Attempt to generate an item.", &DebugSpawnItem); - SetDocumented(table, "spawnUnique", "(name: string)", "Attempt to generate a unique item.", &DebugSpawnUniqueItem); + LuaSetDocFn(table, "get", "() -> Item", "Get the currently selected item.", &DebugCmdGetItem); + LuaSetDocFn(table, "info", "()", "Show info of currently selected item.", &DebugCmdItemInfo); + LuaSetDocFn(table, "spawn", "(name: string)", "Attempt to generate an item.", &DebugSpawnItem); + LuaSetDocFn(table, "spawnUnique", "(name: string)", "Attempt to generate a unique item.", &DebugSpawnUniqueItem); return table; } diff --git a/Source/lua/modules/dev/level.cpp b/Source/lua/modules/dev/level.cpp index 0a102a3a1f6..e75a34b2a17 100644 --- a/Source/lua/modules/dev/level.cpp +++ b/Source/lua/modules/dev/level.cpp @@ -122,11 +122,11 @@ std::string DebugCmdLevelSeed(std::optional level) sol::table LuaDevLevelModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "exportDun", "()", "Save the current level as a dun-file.", &ExportDun); - SetDocumented(table, "map", "", "Automap-related commands.", LuaDevLevelMapModule(lua)); - SetDocumented(table, "reset", "(n: number, seed: number = nil)", "Resets specified level.", &DebugCmdResetLevel); - SetDocumented(table, "seed", "(level: number = nil)", "Get the seed of the current or given level.", &DebugCmdLevelSeed); - SetDocumented(table, "warp", "", "Warp to a level or a custom map.", LuaDevLevelWarpModule(lua)); + LuaSetDocFn(table, "exportDun", "()", "Save the current level as a dun-file.", &ExportDun); + LuaSetDocFn(table, "map", "", "Automap-related commands.", LuaDevLevelMapModule(lua)); + LuaSetDocFn(table, "reset", "(n: number, seed: number = nil)", "Resets specified level.", &DebugCmdResetLevel); + LuaSetDocFn(table, "seed", "(level: number = nil)", "Get the seed of the current or given level.", &DebugCmdLevelSeed); + LuaSetDocFn(table, "warp", "", "Warp to a level or a custom map.", LuaDevLevelWarpModule(lua)); return table; } diff --git a/Source/lua/modules/dev/level/map.cpp b/Source/lua/modules/dev/level/map.cpp index b1067fcad5b..f63b49a08eb 100644 --- a/Source/lua/modules/dev/level/map.cpp +++ b/Source/lua/modules/dev/level/map.cpp @@ -32,8 +32,8 @@ std::string DebugCmdMapHide() sol::table LuaDevLevelMapModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "hide", "()", "Hide the map.", &DebugCmdMapHide); - SetDocumented(table, "reveal", "()", "Reveal the map.", &DebugCmdMapReveal); + LuaSetDocFn(table, "hide", "()", "Hide the map.", &DebugCmdMapHide); + LuaSetDocFn(table, "reveal", "()", "Reveal the map.", &DebugCmdMapReveal); return table; } diff --git a/Source/lua/modules/dev/level/warp.cpp b/Source/lua/modules/dev/level/warp.cpp index 655a36289f0..0582db6ccee 100644 --- a/Source/lua/modules/dev/level/warp.cpp +++ b/Source/lua/modules/dev/level/warp.cpp @@ -72,9 +72,9 @@ std::string DebugCmdWarpToCustomMap(std::string_view path, int dunType, int x, i sol::table LuaDevLevelWarpModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "dungeon", "(n: number)", "Go to dungeon level (0 for town).", &DebugCmdWarpToDungeonLevel); - SetDocumented(table, "map", "(path: string, dunType: number, x: number, y: number)", "Go to custom {path}.dun level", &DebugCmdWarpToCustomMap); - SetDocumented(table, "quest", "(n: number)", "Go to quest level.", &DebugCmdWarpToQuestLevel); + LuaSetDocFn(table, "dungeon", "(n: number)", "Go to dungeon level (0 for town).", &DebugCmdWarpToDungeonLevel); + LuaSetDocFn(table, "map", "(path: string, dunType: number, x: number, y: number)", "Go to custom {path}.dun level", &DebugCmdWarpToCustomMap); + LuaSetDocFn(table, "quest", "(n: number)", "Go to quest level.", &DebugCmdWarpToQuestLevel); return table; } diff --git a/Source/lua/modules/dev/monsters.cpp b/Source/lua/modules/dev/monsters.cpp index d9ee171fa1f..bb5a64a20e1 100644 --- a/Source/lua/modules/dev/monsters.cpp +++ b/Source/lua/modules/dev/monsters.cpp @@ -172,8 +172,8 @@ std::string DebugCmdSpawnMonster(std::string name, std::optional count sol::table LuaDevMonstersModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "spawn", "(name: string, count: number = 1)", "Spawn monster(s)", &DebugCmdSpawnMonster); - SetDocumented(table, "spawnUnique", "(name: string, count: number = 1)", "Spawn unique monster(s)", &DebugCmdSpawnUniqueMonster); + LuaSetDocFn(table, "spawn", "(name: string, count: number = 1)", "Spawn monster(s)", &DebugCmdSpawnMonster); + LuaSetDocFn(table, "spawnUnique", "(name: string, count: number = 1)", "Spawn unique monster(s)", &DebugCmdSpawnUniqueMonster); return table; } diff --git a/Source/lua/modules/dev/player.cpp b/Source/lua/modules/dev/player.cpp index 8bea5d50f17..c019f2b01a5 100644 --- a/Source/lua/modules/dev/player.cpp +++ b/Source/lua/modules/dev/player.cpp @@ -81,11 +81,11 @@ std::string DebugSetPlayerTrn(std::string_view path) sol::table LuaDevPlayerTrnModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "mon", "(name: string)", "Set player TRN to monsters\\${name}.trn", + LuaSetDocFn(table, "mon", "(name: string)", "Set player TRN to monsters\\${name}.trn", [](std::string_view name) { return DebugSetPlayerTrn(StrCat("monsters\\", name, ".trn")); }); - SetDocumented(table, "plr", "(name: string)", "Set player TRN to plrgfx\\${name}.trn", + LuaSetDocFn(table, "plr", "(name: string)", "Set player TRN to plrgfx\\${name}.trn", [](std::string_view name) { return DebugSetPlayerTrn(StrCat("plrgfx\\", name, ".trn")); }); - SetDocumented(table, "clear", "()", "Unset player TRN", + LuaSetDocFn(table, "clear", "()", "Unset player TRN", []() { return DebugSetPlayerTrn(""); }); return table; } @@ -101,14 +101,14 @@ std::string DebugCmdInvisible(std::optional on) sol::table LuaDevPlayerModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "arrow", "(effect: 'normal'|'fire'|'lightning'|'explosion')", "Set arrow effect.", &DebugCmdArrow); - SetDocumented(table, "god", "(on: boolean = nil)", "Toggle god mode.", &DebugCmdGodMode); - SetDocumented(table, "gold", "", "Adjust player gold.", LuaDevPlayerGoldModule(lua)); - SetDocumented(table, "info", "(id: number = 0)", "Show player info.", &DebugCmdPlayerInfo); - SetDocumented(table, "spells", "", "Adjust player spells.", LuaDevPlayerSpellsModule(lua)); - SetDocumented(table, "stats", "", "Adjust player stats (Strength, HP, etc).", LuaDevPlayerStatsModule(lua)); - SetDocumented(table, "trn", "", "Set player TRN to '${name}.trn'", LuaDevPlayerTrnModule(lua)); - SetDocumented(table, "invisible", "(on: boolean = nil)", "Toggle invisibility.", &DebugCmdInvisible); + LuaSetDocFn(table, "arrow", "(effect: 'normal'|'fire'|'lightning'|'explosion')", "Set arrow effect.", &DebugCmdArrow); + LuaSetDocFn(table, "god", "(on: boolean = nil)", "Toggle god mode.", &DebugCmdGodMode); + LuaSetDoc(table, "gold", "", "Adjust player gold.", LuaDevPlayerGoldModule(lua)); + LuaSetDocFn(table, "info", "(id: number = 0)", "Show player info.", &DebugCmdPlayerInfo); + LuaSetDoc(table, "spells", "", "Adjust player spells.", LuaDevPlayerSpellsModule(lua)); + LuaSetDoc(table, "stats", "", "Adjust player stats (Strength, HP, etc).", LuaDevPlayerStatsModule(lua)); + LuaSetDoc(table, "trn", "", "Set player TRN to '${name}.trn'", LuaDevPlayerTrnModule(lua)); + LuaSetDocFn(table, "invisible", "(on: boolean = nil)", "Toggle invisibility.", &DebugCmdInvisible); return table; } diff --git a/Source/lua/modules/dev/player/gold.cpp b/Source/lua/modules/dev/player/gold.cpp index 679f2a0479b..c6a39e099de 100644 --- a/Source/lua/modules/dev/player/gold.cpp +++ b/Source/lua/modules/dev/player/gold.cpp @@ -92,8 +92,8 @@ std::string DebugCmdTakeGoldCheat(std::optional amount) sol::table LuaDevPlayerGoldModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "give", "(amount: number = MAX)", "Gives the player gold.", &DebugCmdGiveGoldCheat); - SetDocumented(table, "take", "(amount: number = MAX)", "Takes the player's gold away.", &DebugCmdTakeGoldCheat); + LuaSetDocFn(table, "give", "(amount: number = MAX)", "Gives the player gold.", &DebugCmdGiveGoldCheat); + LuaSetDocFn(table, "take", "(amount: number = MAX)", "Takes the player's gold away.", &DebugCmdTakeGoldCheat); return table; } diff --git a/Source/lua/modules/dev/player/spells.cpp b/Source/lua/modules/dev/player/spells.cpp index c46700a888b..ab7be2e4e33 100644 --- a/Source/lua/modules/dev/player/spells.cpp +++ b/Source/lua/modules/dev/player/spells.cpp @@ -31,7 +31,7 @@ std::string DebugCmdSetSpellsLevel(uint8_t level) sol::table LuaDevPlayerSpellsModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "setLevel", "(level: number)", "Set spell level for all spells.", &DebugCmdSetSpellsLevel); + LuaSetDocFn(table, "setLevel", "(level: number)", "Set spell level for all spells.", &DebugCmdSetSpellsLevel); return table; } diff --git a/Source/lua/modules/dev/player/stats.cpp b/Source/lua/modules/dev/player/stats.cpp index daea36b8b19..0451e520b6c 100644 --- a/Source/lua/modules/dev/player/stats.cpp +++ b/Source/lua/modules/dev/player/stats.cpp @@ -87,12 +87,12 @@ std::string DebugCmdChangeMana(int change) sol::table LuaDevPlayerStatsModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "adjustHealth", "(amount: number)", "Adjust HP (amount can be negative)", &DebugCmdChangeHealth); - SetDocumented(table, "adjustMana", "(amount: number)", "Adjust mana (amount can be negative)", &DebugCmdChangeMana); - SetDocumented(table, "levelUp", "(amount: number = 1)", "Level the player up.", &DebugCmdLevelUp); - SetDocumented(table, "rejuvenate", "()", "Refill health", &DebugCmdRefillHealthMana); - SetDocumented(table, "setAttrToMax", "()", "Set Str, Mag, Dex, and Vit to maximum.", &DebugCmdMaxStats); - SetDocumented(table, "setAttrToMin", "()", "Set Str, Mag, Dex, and Vit to minimum.", &DebugCmdMinStats); + LuaSetDocFn(table, "adjustHealth", "(amount: number)", "Adjust HP (amount can be negative)", &DebugCmdChangeHealth); + LuaSetDocFn(table, "adjustMana", "(amount: number)", "Adjust mana (amount can be negative)", &DebugCmdChangeMana); + LuaSetDocFn(table, "levelUp", "(amount: number = 1)", "Level the player up.", &DebugCmdLevelUp); + LuaSetDocFn(table, "rejuvenate", "()", "Refill health", &DebugCmdRefillHealthMana); + LuaSetDocFn(table, "setAttrToMax", "()", "Set Str, Mag, Dex, and Vit to maximum.", &DebugCmdMaxStats); + LuaSetDocFn(table, "setAttrToMin", "()", "Set Str, Mag, Dex, and Vit to minimum.", &DebugCmdMinStats); return table; } diff --git a/Source/lua/modules/dev/quests.cpp b/Source/lua/modules/dev/quests.cpp index b4b9148c9ca..4acef02d746 100644 --- a/Source/lua/modules/dev/quests.cpp +++ b/Source/lua/modules/dev/quests.cpp @@ -63,10 +63,10 @@ std::string DebugCmdQuestsInfo() sol::table LuaDevQuestsModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "activate", "(id: number)", "Activate the given quest.", &DebugCmdEnableQuest); - SetDocumented(table, "activateAll", "()", "Activate all available quests.", &DebugCmdEnableQuests); - SetDocumented(table, "all", "()", "Information on all available quest.", &DebugCmdQuestsInfo); - SetDocumented(table, "info", "(id: number)", "Information on the given quest.", &DebugCmdQuestInfo); + LuaSetDocFn(table, "activate", "(id: number)", "Activate the given quest.", &DebugCmdEnableQuest); + LuaSetDocFn(table, "activateAll", "()", "Activate all available quests.", &DebugCmdEnableQuests); + LuaSetDocFn(table, "all", "()", "Information on all available quest.", &DebugCmdQuestsInfo); + LuaSetDocFn(table, "info", "(id: number)", "Information on the given quest.", &DebugCmdQuestInfo); return table; } diff --git a/Source/lua/modules/dev/search.cpp b/Source/lua/modules/dev/search.cpp index 5718af21500..851e2991d1d 100644 --- a/Source/lua/modules/dev/search.cpp +++ b/Source/lua/modules/dev/search.cpp @@ -45,10 +45,10 @@ std::string DebugCmdClearSearch() sol::table LuaDevSearchModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "clear", "()", "Clear search results from the map.", &DebugCmdClearSearch); - SetDocumented(table, "item", "(name: string)", "Search the map for an item.", &DebugCmdSearchItem); - SetDocumented(table, "monster", "(name: string)", "Search the map for a monster.", &DebugCmdSearchMonster); - SetDocumented(table, "object", "(name: string)", "Search the map for an object.", &DebugCmdSearchObject); + LuaSetDocFn(table, "clear", "()", "Clear search results from the map.", &DebugCmdClearSearch); + LuaSetDocFn(table, "item", "(name: string)", "Search the map for an item.", &DebugCmdSearchItem); + LuaSetDocFn(table, "monster", "(name: string)", "Search the map for a monster.", &DebugCmdSearchMonster); + LuaSetDocFn(table, "object", "(name: string)", "Search the map for an object.", &DebugCmdSearchObject); return table; } diff --git a/Source/lua/modules/dev/towners.cpp b/Source/lua/modules/dev/towners.cpp index 6895a9efbcb..f473262d156 100644 --- a/Source/lua/modules/dev/towners.cpp +++ b/Source/lua/modules/dev/towners.cpp @@ -99,8 +99,8 @@ std::string DebugCmdTalkToTowner(std::string_view name) sol::table LuaDevTownersModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "talk", "(name: string)", "Talk to towner.", &DebugCmdTalkToTowner); - SetDocumented(table, "visit", "(name: string)", "Teleport to towner.", &DebugCmdVisitTowner); + LuaSetDocFn(table, "talk", "(name: string)", "Talk to towner.", &DebugCmdTalkToTowner); + LuaSetDocFn(table, "visit", "(name: string)", "Teleport to towner.", &DebugCmdVisitTowner); return table; } diff --git a/Source/lua/modules/hellfire.cpp b/Source/lua/modules/hellfire.cpp index 20c64f5dbc4..0b0452b0b21 100644 --- a/Source/lua/modules/hellfire.cpp +++ b/Source/lua/modules/hellfire.cpp @@ -10,8 +10,8 @@ namespace devilution { sol::table LuaHellfireModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetWithSignature(table, "loadData", "()", []() { LoadHellfireArchives(); }); - SetWithSignature(table, "enable", "()", []() { gbIsHellfire = true; }); + LuaSetDocFn(table, "loadData", "()", LoadHellfireArchives); + LuaSetDocFn(table, "enable", "()", []() { gbIsHellfire = true; }); return table; } diff --git a/Source/lua/modules/i18n.cpp b/Source/lua/modules/i18n.cpp index c7d90757885..9891e209101 100644 --- a/Source/lua/modules/i18n.cpp +++ b/Source/lua/modules/i18n.cpp @@ -13,17 +13,17 @@ namespace devilution { sol::table LuaI18nModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "language_code", "()", + LuaSetDocFn(table, "language_code", "()", "Returns the current language code", GetLanguageCode); - SetDocumented(table, "translate", "(text: string)", + LuaSetDocFn(table, "translate", "(text: string)", "Translates the given string", [](const char *key) { return LanguageTranslate(key); }); - SetDocumented(table, "plural_translate", "(singular: string, plural: string, count: integer)", + LuaSetDocFn(table, "plural_translate", "(singular: string, plural: string, count: integer)", "Returns a singular or plural translation for the given keys and count", [](const char *singular, std::string_view plural, int count) { return fmt::format(fmt::runtime(LanguagePluralTranslate(singular, plural, count)), count); }); - SetDocumented(table, "particular_translate", "(context: string, text: string)", + LuaSetDocFn(table, "particular_translate", "(context: string, text: string)", "Returns the translation for the given context identifier and key.", LanguageParticularTranslate); - SetDocumented(table, "is_small_font_tall", "()", + LuaSetDocFn(table, "is_small_font_tall", "()", "Whether the language's small font is tall (16px)", IsSmallFontTall); return table; } diff --git a/Source/lua/modules/items.cpp b/Source/lua/modules/items.cpp index 181838c16ad..a2e34acb44c 100644 --- a/Source/lua/modules/items.cpp +++ b/Source/lua/modules/items.cpp @@ -1,12 +1,13 @@ #include "lua/modules/items.hpp" -#include +#include #include #include "items.h" #include "lua/metadoc.hpp" #include "player.h" +#include "utils/utf8.hpp" namespace devilution { @@ -18,98 +19,94 @@ void InitItemUserType(sol::state_view &lua) sol::usertype itemType = lua.new_usertype(sol::no_constructor); // Member variables - SetDocumented(itemType, "seed", "number", "Randomly generated identifier", [](const Item &i) { return i._iSeed; }, [](Item &i, unsigned int val) { i._iSeed = val; }); - SetDocumented(itemType, "createInfo", "number", "Creation flags", [](const Item &i) { return i._iCreateInfo; }, [](Item &i, unsigned int val) { i._iCreateInfo = val; }); - SetDocumented(itemType, "type", "ItemType", "Item type", [](const Item &i) { return i._itype; }, [](Item &i, int val) { i._itype = static_cast(val); }); - SetDocumented(itemType, "animFlag", "boolean", "Animation flag", [](const Item &i) { return i._iAnimFlag; }, [](Item &i, bool val) { i._iAnimFlag = val; }); - SetDocumented(itemType, "position", "Point", "Item world position", [](const Item &i) { return i.position; }, [](Item &i, Point val) { i.position = val; }); + LuaSetDocProperty(itemType, "seed", "number", "Randomly generated identifier", &Item::_iSeed); + LuaSetDocProperty(itemType, "createInfo", "number", "Creation flags", &Item::_iCreateInfo); + LuaSetDocProperty(itemType, "type", "ItemType", "Item type", &Item::_itype); + LuaSetDocProperty(itemType, "animFlag", "boolean", "Animation flag", &Item::_iAnimFlag); + LuaSetDocProperty(itemType, "position", "Point", "Item world position", &Item::position); // TODO: Add AnimationInfo usertype - // SetDocumented(itemType, "animInfo", "AnimationInfo", "Animation information", [](const Item &i) { return i.AnimInfo; }, [](Item &i, AnimationInfo val) { i.AnimInfo = val; }); - SetDocumented(itemType, "delFlag", "boolean", "Deletion flag", [](const Item &i) { return i._iDelFlag; }, [](Item &i, bool val) { i._iDelFlag = val; }); - SetDocumented(itemType, "selectionRegion", "number", "Selection region", [](const Item &i) { return static_cast(i.selectionRegion); }, [](Item &i, int val) { i.selectionRegion = static_cast(val); }); - SetDocumented(itemType, "postDraw", "boolean", "Post-draw flag", [](const Item &i) { return i._iPostDraw; }, [](Item &i, bool val) { i._iPostDraw = val; }); - SetDocumented(itemType, "identified", "boolean", "Identified flag", [](const Item &i) { return i._iIdentified; }, [](Item &i, bool val) { i._iIdentified = val; }); - SetDocumented(itemType, "magical", "number", "Item quality", [](const Item &i) { return static_cast(i._iMagical); }, [](Item &i, int val) { i._iMagical = static_cast(val); }); - SetDocumented(itemType, "name", "string", "Item name", [](const Item &i) { return std::string(i._iName); }, [](Item &i, const std::string &val) { - std::strncpy(i._iName, val.c_str(), sizeof(i._iName)); - i._iName[sizeof(i._iName) - 1] = '\0'; }); - SetDocumented(itemType, "iName", "string", "Identified item name", [](const Item &i) { return std::string(i._iIName); }, [](Item &i, const std::string &val) { - std::strncpy(i._iIName, val.c_str(), sizeof(i._iIName)); - i._iIName[sizeof(i._iIName) - 1] = '\0'; }); - SetDocumented(itemType, "loc", "ItemEquipType", "Equipment location", [](const Item &i) { return i._iLoc; }, [](Item &i, int val) { i._iLoc = static_cast(val); }); - SetDocumented(itemType, "class", "ItemClass", "Item class", [](const Item &i) { return i._iClass; }, [](Item &i, int val) { i._iClass = static_cast(val); }); - SetDocumented(itemType, "curs", "number", "Cursor index", [](const Item &i) { return i._iCurs; }, [](Item &i, int val) { i._iCurs = val; }); - SetDocumented(itemType, "value", "number", "Item value", [](const Item &i) { return i._ivalue; }, [](Item &i, int val) { i._ivalue = val; }); - SetDocumented(itemType, "ivalue", "number", "Identified item value", [](const Item &i) { return i._iIvalue; }, [](Item &i, int val) { i._iIvalue = val; }); - SetDocumented(itemType, "minDam", "number", "Minimum damage", [](const Item &i) { return i._iMinDam; }, [](Item &i, int val) { i._iMinDam = val; }); - SetDocumented(itemType, "maxDam", "number", "Maximum damage", [](const Item &i) { return i._iMaxDam; }, [](Item &i, int val) { i._iMaxDam = val; }); - SetDocumented(itemType, "AC", "number", "Armor class", [](const Item &i) { return i._iAC; }, [](Item &i, int val) { i._iAC = val; }); - SetDocumented(itemType, "flags", "ItemSpecialEffect", "Special effect flags", [](const Item &i) { return static_cast(i._iFlags); }, [](Item &i, int val) { i._iFlags = static_cast(val); }); - SetDocumented(itemType, "miscId", "ItemMiscID", "Miscellaneous ID", [](const Item &i) { return i._iMiscId; }, [](Item &i, int val) { i._iMiscId = static_cast(val); }); - SetDocumented(itemType, "spell", "SpellID", "Spell", [](const Item &i) { return i._iSpell; }, [](Item &i, int val) { i._iSpell = static_cast(val); }); - SetDocumented(itemType, "IDidx", "ItemIndex", "Base item index", [](const Item &i) { return i.IDidx; }, [](Item &i, int val) { i.IDidx = static_cast<_item_indexes>(val); }); - SetDocumented(itemType, "charges", "number", "Number of charges", [](const Item &i) { return i._iCharges; }, [](Item &i, int val) { i._iCharges = val; }); - SetDocumented(itemType, "maxCharges", "number", "Maximum charges", [](const Item &i) { return i._iMaxCharges; }, [](Item &i, int val) { i._iMaxCharges = val; }); - SetDocumented(itemType, "durability", "number", "Durability", [](const Item &i) { return i._iDurability; }, [](Item &i, int val) { i._iDurability = val; }); - SetDocumented(itemType, "maxDur", "number", "Maximum durability", [](const Item &i) { return i._iMaxDur; }, [](Item &i, int val) { i._iMaxDur = val; }); - SetDocumented(itemType, "PLDam", "number", "Damage % bonus", [](const Item &i) { return i._iPLDam; }, [](Item &i, int val) { i._iPLDam = val; }); - SetDocumented(itemType, "PLToHit", "number", "Chance to hit bonus", [](const Item &i) { return i._iPLToHit; }, [](Item &i, int val) { i._iPLToHit = val; }); - SetDocumented(itemType, "PLAC", "number", "Armor class % bonus", [](const Item &i) { return i._iPLAC; }, [](Item &i, int val) { i._iPLAC = val; }); - SetDocumented(itemType, "PLStr", "number", "Strength bonus", [](const Item &i) { return i._iPLStr; }, [](Item &i, int val) { i._iPLStr = val; }); - SetDocumented(itemType, "PLMag", "number", "Magic bonus", [](const Item &i) { return i._iPLMag; }, [](Item &i, int val) { i._iPLMag = val; }); - SetDocumented(itemType, "PLDex", "number", "Dexterity bonus", [](const Item &i) { return i._iPLDex; }, [](Item &i, int val) { i._iPLDex = val; }); - SetDocumented(itemType, "PLVit", "number", "Vitality bonus", [](const Item &i) { return i._iPLVit; }, [](Item &i, int val) { i._iPLVit = val; }); - SetDocumented(itemType, "PLFR", "number", "Fire resistance bonus", [](const Item &i) { return i._iPLFR; }, [](Item &i, int val) { i._iPLFR = val; }); - SetDocumented(itemType, "PLLR", "number", "Lightning resistance bonus", [](const Item &i) { return i._iPLLR; }, [](Item &i, int val) { i._iPLLR = val; }); - SetDocumented(itemType, "PLMR", "number", "Magic resistance bonus", [](const Item &i) { return i._iPLMR; }, [](Item &i, int val) { i._iPLMR = val; }); - SetDocumented(itemType, "PLMana", "number", "Mana bonus", [](const Item &i) { return i._iPLMana; }, [](Item &i, int val) { i._iPLMana = val; }); - SetDocumented(itemType, "PLHP", "number", "Life bonus", [](const Item &i) { return i._iPLHP; }, [](Item &i, int val) { i._iPLHP = val; }); - SetDocumented(itemType, "PLDamMod", "number", "Damage modifier bonus", [](const Item &i) { return i._iPLDamMod; }, [](Item &i, int val) { i._iPLDamMod = val; }); - SetDocumented(itemType, "PLGetHit", "number", "Damage from enemies bonus", [](const Item &i) { return i._iPLGetHit; }, [](Item &i, int val) { i._iPLGetHit = val; }); - SetDocumented(itemType, "PLLight", "number", "Light bonus", [](const Item &i) { return i._iPLLight; }, [](Item &i, int val) { i._iPLLight = val; }); - SetDocumented(itemType, "splLvlAdd", "number", "Spell level bonus", [](const Item &i) { return i._iSplLvlAdd; }, [](Item &i, int val) { i._iSplLvlAdd = val; }); - SetDocumented(itemType, "request", "boolean", "Request flag", [](const Item &i) { return i._iRequest; }, [](Item &i, bool val) { i._iRequest = val; }); - SetDocumented(itemType, "uid", "number", "Unique item ID", [](const Item &i) { return i._iUid; }, [](Item &i, int val) { i._iUid = val; }); - SetDocumented(itemType, "fMinDam", "number", "Fire minimum damage", [](const Item &i) { return i._iFMinDam; }, [](Item &i, int val) { i._iFMinDam = val; }); - SetDocumented(itemType, "fMaxDam", "number", "Fire maximum damage", [](const Item &i) { return i._iFMaxDam; }, [](Item &i, int val) { i._iFMaxDam = val; }); - SetDocumented(itemType, "lMinDam", "number", "Lightning minimum damage", [](const Item &i) { return i._iLMinDam; }, [](Item &i, int val) { i._iLMinDam = val; }); - SetDocumented(itemType, "lMaxDam", "number", "Lightning maximum damage", [](const Item &i) { return i._iLMaxDam; }, [](Item &i, int val) { i._iLMaxDam = val; }); - SetDocumented(itemType, "PLEnAc", "number", "Damage target AC bonus", [](const Item &i) { return i._iPLEnAc; }, [](Item &i, int val) { i._iPLEnAc = val; }); - SetDocumented(itemType, "prePower", "ItemEffectType", "Prefix power", [](const Item &i) { return i._iPrePower; }, [](Item &i, int val) { i._iPrePower = static_cast(val); }); - SetDocumented(itemType, "sufPower", "ItemEffectType", "Suffix power", [](const Item &i) { return i._iSufPower; }, [](Item &i, int val) { i._iSufPower = static_cast(val); }); - SetDocumented(itemType, "vAdd1", "number", "Value addition 1", [](const Item &i) { return i._iVAdd1; }, [](Item &i, int val) { i._iVAdd1 = val; }); - SetDocumented(itemType, "vMult1", "number", "Value multiplier 1", [](const Item &i) { return i._iVMult1; }, [](Item &i, int val) { i._iVMult1 = val; }); - SetDocumented(itemType, "vAdd2", "number", "Value addition 2", [](const Item &i) { return i._iVAdd2; }, [](Item &i, int val) { i._iVAdd2 = val; }); - SetDocumented(itemType, "vMult2", "number", "Value multiplier 2", [](const Item &i) { return i._iVMult2; }, [](Item &i, int val) { i._iVMult2 = val; }); - SetDocumented(itemType, "minStr", "number", "Minimum strength required", [](const Item &i) { return i._iMinStr; }, [](Item &i, int val) { i._iMinStr = val; }); - SetDocumented(itemType, "minMag", "number", "Minimum magic required", [](const Item &i) { return i._iMinMag; }, [](Item &i, int val) { i._iMinMag = val; }); - SetDocumented(itemType, "minDex", "number", "Minimum dexterity required", [](const Item &i) { return i._iMinDex; }, [](Item &i, int val) { i._iMinDex = val; }); - SetDocumented(itemType, "statFlag", "boolean", "Equippable flag", [](const Item &i) { return i._iStatFlag; }, [](Item &i, bool val) { i._iStatFlag = val; }); - SetDocumented(itemType, "damAcFlags", "ItemSpecialEffectHf", "Secondary special effect flags", [](const Item &i) { return i._iDamAcFlags; }, [](Item &i, int val) { i._iDamAcFlags = static_cast(val); }); - SetDocumented(itemType, "buff", "number", "Secondary creation flags", [](const Item &i) { return i.dwBuff; }, [](Item &i, int val) { i.dwBuff = val; }); + // LuaSetDocProperty(itemType, "animInfo", "AnimationInfo", "Animation information", &Item::AnimInfo); + LuaSetDocProperty(itemType, "delFlag", "boolean", "Deletion flag", &Item::_iDelFlag); + LuaSetDocProperty(itemType, "selectionRegion", "number", "Selection region", &Item::selectionRegion); + LuaSetDocProperty(itemType, "postDraw", "boolean", "Post-draw flag", &Item::_iPostDraw); + LuaSetDocProperty(itemType, "identified", "boolean", "Identified flag", &Item::_iIdentified); + LuaSetDocProperty(itemType, "magical", "number", "Item quality", &Item::_iMagical); + LuaSetDocProperty(itemType, "name", "string", "Item name", [](const Item &i) { return std::string_view(i._iName); }, [](Item &i, std::string_view val) { CopyUtf8(i._iName, val, sizeof(i._iName)); }); + LuaSetDocProperty(itemType, "iName", "string", "Identified item name", [](const Item &i) { return std::string_view(i._iIName); }, [](Item &i, std::string_view val) { CopyUtf8(i._iIName, val, sizeof(i._iIName)); }); + LuaSetDocProperty(itemType, "loc", "ItemEquipType", "Equipment location", &Item::_iLoc); + LuaSetDocProperty(itemType, "class", "ItemClass", "Item class", &Item::_iClass); + LuaSetDocProperty(itemType, "curs", "number", "Cursor index", &Item::_iCurs); + LuaSetDocProperty(itemType, "value", "number", "Item value", &Item::_ivalue); + LuaSetDocProperty(itemType, "ivalue", "number", "Identified item value", &Item::_iIvalue); + LuaSetDocProperty(itemType, "minDam", "number", "Minimum damage", &Item::_iMinDam); + LuaSetDocProperty(itemType, "maxDam", "number", "Maximum damage", &Item::_iMaxDam); + LuaSetDocProperty(itemType, "AC", "number", "Armor class", &Item::_iAC); + LuaSetDocProperty(itemType, "flags", "ItemSpecialEffect", "Special effect flags", &Item::_iFlags); + LuaSetDocProperty(itemType, "miscId", "ItemMiscID", "Miscellaneous ID", &Item::_iMiscId); + LuaSetDocProperty(itemType, "spell", "SpellID", "Spell", &Item::_iSpell); + LuaSetDocProperty(itemType, "IDidx", "ItemIndex", "Base item index", &Item::IDidx); + LuaSetDocProperty(itemType, "charges", "number", "Number of charges", &Item::_iCharges); + LuaSetDocProperty(itemType, "maxCharges", "number", "Maximum charges", &Item::_iMaxCharges); + LuaSetDocProperty(itemType, "durability", "number", "Durability", &Item::_iDurability); + LuaSetDocProperty(itemType, "maxDur", "number", "Maximum durability", &Item::_iMaxDur); + LuaSetDocProperty(itemType, "PLDam", "number", "Damage % bonus", &Item::_iPLDam); + LuaSetDocProperty(itemType, "PLToHit", "number", "Chance to hit bonus", &Item::_iPLToHit); + LuaSetDocProperty(itemType, "PLAC", "number", "Armor class % bonus", &Item::_iPLAC); + LuaSetDocProperty(itemType, "PLStr", "number", "Strength bonus", &Item::_iPLStr); + LuaSetDocProperty(itemType, "PLMag", "number", "Magic bonus", &Item::_iPLMag); + LuaSetDocProperty(itemType, "PLDex", "number", "Dexterity bonus", &Item::_iPLDex); + LuaSetDocProperty(itemType, "PLVit", "number", "Vitality bonus", &Item::_iPLVit); + LuaSetDocProperty(itemType, "PLFR", "number", "Fire resistance bonus", &Item::_iPLFR); + LuaSetDocProperty(itemType, "PLLR", "number", "Lightning resistance bonus", &Item::_iPLLR); + LuaSetDocProperty(itemType, "PLMR", "number", "Magic resistance bonus", &Item::_iPLMR); + LuaSetDocProperty(itemType, "PLMana", "number", "Mana bonus", &Item::_iPLMana); + LuaSetDocProperty(itemType, "PLHP", "number", "Life bonus", &Item::_iPLHP); + LuaSetDocProperty(itemType, "PLDamMod", "number", "Damage modifier bonus", &Item::_iPLDamMod); + LuaSetDocProperty(itemType, "PLGetHit", "number", "Damage from enemies bonus", &Item::_iPLGetHit); + LuaSetDocProperty(itemType, "PLLight", "number", "Light bonus", &Item::_iPLLight); + LuaSetDocProperty(itemType, "splLvlAdd", "number", "Spell level bonus", &Item::_iSplLvlAdd); + LuaSetDocProperty(itemType, "request", "boolean", "Request flag", &Item::_iRequest); + LuaSetDocProperty(itemType, "uid", "number", "Unique item ID", &Item::_iUid); + LuaSetDocProperty(itemType, "fMinDam", "number", "Fire minimum damage", &Item::_iFMinDam); + LuaSetDocProperty(itemType, "fMaxDam", "number", "Fire maximum damage", &Item::_iFMaxDam); + LuaSetDocProperty(itemType, "lMinDam", "number", "Lightning minimum damage", &Item::_iLMinDam); + LuaSetDocProperty(itemType, "lMaxDam", "number", "Lightning maximum damage", &Item::_iLMaxDam); + LuaSetDocProperty(itemType, "PLEnAc", "number", "Damage target AC bonus", &Item::_iPLEnAc); + LuaSetDocProperty(itemType, "prePower", "ItemEffectType", "Prefix power", &Item::_iPrePower); + LuaSetDocProperty(itemType, "sufPower", "ItemEffectType", "Suffix power", &Item::_iSufPower); + LuaSetDocProperty(itemType, "vAdd1", "number", "Value addition 1", &Item::_iVAdd1); + LuaSetDocProperty(itemType, "vMult1", "number", "Value multiplier 1", &Item::_iVMult1); + LuaSetDocProperty(itemType, "vAdd2", "number", "Value addition 2", &Item::_iVAdd2); + LuaSetDocProperty(itemType, "vMult2", "number", "Value multiplier 2", &Item::_iVMult2); + LuaSetDocProperty(itemType, "minStr", "number", "Minimum strength required", &Item::_iMinStr); + LuaSetDocProperty(itemType, "minMag", "number", "Minimum magic required", &Item::_iMinMag); + LuaSetDocProperty(itemType, "minDex", "number", "Minimum dexterity required", &Item::_iMinDex); + LuaSetDocProperty(itemType, "statFlag", "boolean", "Equippable flag", &Item::_iStatFlag); + LuaSetDocProperty(itemType, "damAcFlags", "ItemSpecialEffectHf", "Secondary special effect flags", &Item::_iDamAcFlags); + LuaSetDocProperty(itemType, "buff", "number", "Secondary creation flags", &Item::dwBuff); // Member functions - SetDocumented(itemType, "pop", "() -> Item", "Clears this item and returns the old value", &Item::pop); - SetDocumented(itemType, "clear", "() -> void", "Resets the item", &Item::clear); - SetDocumented(itemType, "isEmpty", "() -> boolean", "Checks whether this item is empty", &Item::isEmpty); - SetDocumented(itemType, "isEquipment", "() -> boolean", "Checks if item is equipment", &Item::isEquipment); - SetDocumented(itemType, "isWeapon", "() -> boolean", "Checks if item is a weapon", &Item::isWeapon); - SetDocumented(itemType, "isArmor", "() -> boolean", "Checks if item is armor", &Item::isArmor); - SetDocumented(itemType, "isGold", "() -> boolean", "Checks if item is gold", &Item::isGold); - SetDocumented(itemType, "isHelm", "() -> boolean", "Checks if item is a helm", &Item::isHelm); - SetDocumented(itemType, "isShield", "() -> boolean", "Checks if item is a shield", &Item::isShield); - SetDocumented(itemType, "isJewelry", "() -> boolean", "Checks if item is jewelry", &Item::isJewelry); - SetDocumented(itemType, "isScroll", "() -> boolean", "Checks if item is a scroll", &Item::isScroll); - SetDocumented(itemType, "isScrollOf", "(spell: SpellID) -> boolean", "Checks if item is a scroll of a given spell", &Item::isScrollOf); - SetDocumented(itemType, "isRune", "() -> boolean", "Checks if item is a rune", &Item::isRune); - SetDocumented(itemType, "isRuneOf", "(spell: SpellID) -> boolean", "Checks if item is a rune of a given spell", &Item::isRuneOf); - SetDocumented(itemType, "isUsable", "() -> boolean", "Checks if item is usable", &Item::isUsable); - SetDocumented(itemType, "keyAttributesMatch", "(seed: number, idx: number, createInfo: number) -> boolean", "Checks if key attributes match", &Item::keyAttributesMatch); - SetDocumented(itemType, "getTextColor", "() -> UiFlags", "Gets the text color", &Item::getTextColor); - SetDocumented(itemType, "getTextColorWithStatCheck", "() -> UiFlags", "Gets the text color with stat check", &Item::getTextColorWithStatCheck); - SetDocumented(itemType, "setNewAnimation", "(showAnimation: boolean) -> void", "Sets the new animation", &Item::setNewAnimation); - SetDocumented(itemType, "updateRequiredStatsCacheForPlayer", "(player: Player) -> void", "Updates the required stats cache", &Item::updateRequiredStatsCacheForPlayer); - SetDocumented(itemType, "getName", "() -> string", "Gets the translated item name", &Item::getName); + LuaSetDocFn(itemType, "pop", "() -> Item", "Clears this item and returns the old value", &Item::pop); + LuaSetDocFn(itemType, "clear", "() -> void", "Resets the item", &Item::clear); + LuaSetDocFn(itemType, "isEmpty", "() -> boolean", "Checks whether this item is empty", &Item::isEmpty); + LuaSetDocFn(itemType, "isEquipment", "() -> boolean", "Checks if item is equipment", &Item::isEquipment); + LuaSetDocFn(itemType, "isWeapon", "() -> boolean", "Checks if item is a weapon", &Item::isWeapon); + LuaSetDocFn(itemType, "isArmor", "() -> boolean", "Checks if item is armor", &Item::isArmor); + LuaSetDocFn(itemType, "isGold", "() -> boolean", "Checks if item is gold", &Item::isGold); + LuaSetDocFn(itemType, "isHelm", "() -> boolean", "Checks if item is a helm", &Item::isHelm); + LuaSetDocFn(itemType, "isShield", "() -> boolean", "Checks if item is a shield", &Item::isShield); + LuaSetDocFn(itemType, "isJewelry", "() -> boolean", "Checks if item is jewelry", &Item::isJewelry); + LuaSetDocFn(itemType, "isScroll", "() -> boolean", "Checks if item is a scroll", &Item::isScroll); + LuaSetDocFn(itemType, "isScrollOf", "(spell: SpellID) -> boolean", "Checks if item is a scroll of a given spell", &Item::isScrollOf); + LuaSetDocFn(itemType, "isRune", "() -> boolean", "Checks if item is a rune", &Item::isRune); + LuaSetDocFn(itemType, "isRuneOf", "(spell: SpellID) -> boolean", "Checks if item is a rune of a given spell", &Item::isRuneOf); + LuaSetDocFn(itemType, "isUsable", "() -> boolean", "Checks if item is usable", &Item::isUsable); + LuaSetDocFn(itemType, "keyAttributesMatch", "(seed: number, idx: number, createInfo: number) -> boolean", "Checks if key attributes match", &Item::keyAttributesMatch); + LuaSetDocFn(itemType, "getTextColor", "() -> UiFlags", "Gets the text color", &Item::getTextColor); + LuaSetDocFn(itemType, "getTextColorWithStatCheck", "() -> UiFlags", "Gets the text color with stat check", &Item::getTextColorWithStatCheck); + LuaSetDocFn(itemType, "setNewAnimation", "(showAnimation: boolean) -> void", "Sets the new animation", &Item::setNewAnimation); + LuaSetDocFn(itemType, "updateRequiredStatsCacheForPlayer", "(player: Player) -> void", "Updates the required stats cache", &Item::updateRequiredStatsCacheForPlayer); + LuaSetDocFn(itemType, "getName", "() -> string", "Gets the translated item name", &Item::getName); } void RegisterItemTypeEnum(sol::state_view &lua) diff --git a/Source/lua/modules/player.cpp b/Source/lua/modules/player.cpp index ad2b72d310e..28a0e2ccaaf 100644 --- a/Source/lua/modules/player.cpp +++ b/Source/lua/modules/player.cpp @@ -13,10 +13,10 @@ namespace { void InitPlayerUserType(sol::state_view &lua) { sol::usertype playerType = lua.new_usertype(sol::no_constructor); - SetDocumented(playerType, "name", "", + LuaSetDocReadonlyProperty(playerType, "name", "string", "Player's name (readonly)", - sol::readonly_property(&Player::name)); - SetDocumented(playerType, "addExperience", "(experience: integer, monsterLevel: integer = nil)", + &Player::name); + LuaSetDocFn(playerType, "addExperience", "(experience: integer, monsterLevel: integer = nil)", "Adds experience to this player based on the current game mode", [](Player &player, uint32_t experience, std::optional monsterLevel) { if (monsterLevel.has_value()) { @@ -25,9 +25,9 @@ void InitPlayerUserType(sol::state_view &lua) player.addExperience(experience); } }); - SetDocumented(playerType, "characterLevel", "", + LuaSetDocProperty(playerType, "characterLevel", "number", "Character level (writeable)", - sol::property(&Player::getCharacterLevel, &Player::setCharacterLevel)); + &Player::getCharacterLevel, &Player::setCharacterLevel); } } // namespace @@ -35,12 +35,12 @@ sol::table LuaPlayerModule(sol::state_view &lua) { InitPlayerUserType(lua); sol::table table = lua.create_table(); - SetDocumented(table, "self", "()", + LuaSetDocFn(table, "self", "()", "The current player", []() { return MyPlayer; }); - SetDocumented(table, "walk_to", "(x: integer, y: integer)", + LuaSetDocFn(table, "walk_to", "(x: integer, y: integer)", "Walk to the given coordinates", [](int x, int y) { NetSendCmdLoc(MyPlayerId, true, CMD_WALKXY, Point { x, y }); diff --git a/Source/lua/modules/render.cpp b/Source/lua/modules/render.cpp index cf618063fd5..99bd550fa6f 100644 --- a/Source/lua/modules/render.cpp +++ b/Source/lua/modules/render.cpp @@ -12,12 +12,12 @@ namespace devilution { sol::table LuaRenderModule(sol::state_view &lua) { sol::table table = lua.create_table(); - SetDocumented(table, "string", "(text: string, x: integer, y: integer)", + LuaSetDocFn(table, "string", "(text: string, x: integer, y: integer)", "Renders a string at the given coordinates", [](std::string_view text, int x, int y) { DrawString(GlobalBackBuffer(), text, { x, y }); }); - SetDocumented(table, "screen_width", "()", + LuaSetDocFn(table, "screen_width", "()", "Returns the screen width", []() { return gnScreenWidth; }); - SetDocumented(table, "screen_height", "()", + LuaSetDocFn(table, "screen_height", "()", "Returns the screen height", []() { return gnScreenHeight; }); return table; } diff --git a/Source/lua/modules/towners.cpp b/Source/lua/modules/towners.cpp index 48e55ade902..b04704b5de7 100644 --- a/Source/lua/modules/towners.cpp +++ b/Source/lua/modules/towners.cpp @@ -31,7 +31,7 @@ const char *const TownerTableNames[NUM_TOWNER_TYPES] { void PopulateTownerTable(_talker_id townerId, sol::table &out) { - SetDocumented(out, "position", "()", + LuaSetDocFn(out, "position", "()", "Returns towner coordinates", [townerId]() -> std::optional> { const Towner *towner = GetTowner(townerId); @@ -47,7 +47,7 @@ sol::table LuaTownersModule(sol::state_view &lua) for (uint8_t townerId = TOWN_SMITH; townerId < NUM_TOWNER_TYPES; ++townerId) { sol::table townerTable = lua.create_table(); PopulateTownerTable(static_cast<_talker_id>(townerId), townerTable); - SetDocumented(table, TownerTableNames[townerId], /*signature=*/"", TownerLongNames[townerId], std::move(townerTable)); + LuaSetDoc(table, TownerTableNames[townerId], /*signature=*/"", TownerLongNames[townerId], std::move(townerTable)); } return table; } diff --git a/Source/lua/repl.cpp b/Source/lua/repl.cpp index 3d60a8198a3..425fb311f75 100644 --- a/Source/lua/repl.cpp +++ b/Source/lua/repl.cpp @@ -10,7 +10,7 @@ #include #include -#include "lua/lua.hpp" +#include "lua/lua_global.hpp" #include "panels/console.hpp" #include "utils/str_cat.hpp" diff --git a/Source/panels/console.cpp b/Source/panels/console.cpp index fb76abbf213..d922e639668 100644 --- a/Source/panels/console.cpp +++ b/Source/panels/console.cpp @@ -560,7 +560,7 @@ void DrawConsole(const Surface &out) if (CurrentInputTextState == InputTextState::RestoredFromHistory) { AutocompleteSuggestions.clear(); } else { - GetLuaAutocompleteSuggestions(originalInputText.substr(0, ConsoleInputCursor.position), GetLuaReplEnvironment(), /*maxSuggestions=*/MaxSuggestions, AutocompleteSuggestions); + GetLuaAutocompleteSuggestions(originalInputText, ConsoleInputCursor.position, GetLuaReplEnvironment(), /*maxSuggestions=*/MaxSuggestions, AutocompleteSuggestions); } AutocompleteSuggestionsMaxWidth = -1; AutocompleteSuggestionFocusIndex = AutocompleteSuggestions.empty() ? -1 : 0; diff --git a/test/timedemo_test.cpp b/test/timedemo_test.cpp index 07e5c87f7e6..ad8010eced5 100644 --- a/test/timedemo_test.cpp +++ b/test/timedemo_test.cpp @@ -7,7 +7,7 @@ #include "game_mode.hpp" #include "headless_mode.hpp" #include "init.hpp" -#include "lua/lua.hpp" +#include "lua/lua_global.hpp" #include "monstdat.h" #include "options.h" #include "pfile.h" diff --git a/uwp-project/devilutionx.vcxproj b/uwp-project/devilutionx.vcxproj index f2ddbeec194..06ac0352aaa 100644 --- a/uwp-project/devilutionx.vcxproj +++ b/uwp-project/devilutionx.vcxproj @@ -74,7 +74,7 @@ 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) - ..\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) + ..\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.7\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) pch.h @@ -93,7 +93,7 @@ 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;sheenbidi.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) - ..\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\_deps\sheenbidi-build\Release;..\build\Source\libdevilutionx.dir\Release;%(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.7\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\_deps\sheenbidi-build\Release;..\build\Source\libdevilutionx.dir\Release;%(AdditionalLibraryDirectories) pch.h