2024-10-28 15:57:39 +01:00
|
|
|
// Luanti
|
|
|
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
// Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
2013-05-25 00:51:02 +02:00
|
|
|
|
|
|
|
#include "lua_api/l_base.h"
|
2013-08-11 04:09:45 +02:00
|
|
|
#include "lua_api/l_internal.h"
|
|
|
|
#include "cpp_api/s_base.h"
|
2018-04-17 14:54:50 +01:00
|
|
|
#include "content/mods.h"
|
2018-07-01 12:31:49 +02:00
|
|
|
#include "profiler.h"
|
2018-05-31 22:52:08 +02:00
|
|
|
#include "server.h"
|
2018-07-01 12:31:49 +02:00
|
|
|
#include <algorithm>
|
2018-05-31 22:52:08 +02:00
|
|
|
#include <cmath>
|
2024-02-12 22:58:26 +01:00
|
|
|
#include <sstream>
|
2013-08-11 04:09:45 +02:00
|
|
|
|
2015-04-07 23:04:48 -04:00
|
|
|
ScriptApiBase *ModApiBase::getScriptApiBase(lua_State *L)
|
|
|
|
{
|
2013-08-11 04:09:45 +02:00
|
|
|
// Get server from registry
|
2015-08-25 07:00:56 +02:00
|
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_SCRIPTAPI);
|
2020-04-08 20:14:08 +02:00
|
|
|
ScriptApiBase *sapi_ptr;
|
|
|
|
#if INDIRECT_SCRIPTAPI_RIDX
|
|
|
|
sapi_ptr = (ScriptApiBase*) *(void**)(lua_touserdata(L, -1));
|
|
|
|
#else
|
|
|
|
sapi_ptr = (ScriptApiBase*) lua_touserdata(L, -1);
|
|
|
|
#endif
|
2013-08-11 04:09:45 +02:00
|
|
|
lua_pop(L, 1);
|
|
|
|
return sapi_ptr;
|
2013-05-25 00:51:02 +02:00
|
|
|
}
|
|
|
|
|
2015-04-07 23:04:48 -04:00
|
|
|
Server *ModApiBase::getServer(lua_State *L)
|
|
|
|
{
|
2013-08-11 04:09:45 +02:00
|
|
|
return getScriptApiBase(L)->getServer();
|
2013-05-25 00:51:02 +02:00
|
|
|
}
|
|
|
|
|
2020-05-07 22:38:41 +02:00
|
|
|
ServerInventoryManager *ModApiBase::getServerInventoryMgr(lua_State *L)
|
|
|
|
{
|
|
|
|
return getScriptApiBase(L)->getServer()->getInventoryMgr();
|
|
|
|
}
|
|
|
|
|
2024-10-15 15:47:23 +02:00
|
|
|
#if CHECK_CLIENT_BUILD()
|
2017-01-21 21:44:37 +00:00
|
|
|
Client *ModApiBase::getClient(lua_State *L)
|
|
|
|
{
|
|
|
|
return getScriptApiBase(L)->getClient();
|
|
|
|
}
|
|
|
|
#endif
|
2017-01-31 13:18:52 +00:00
|
|
|
|
|
|
|
IGameDef *ModApiBase::getGameDef(lua_State *L)
|
|
|
|
{
|
|
|
|
return getScriptApiBase(L)->getGameDef();
|
|
|
|
}
|
|
|
|
|
2015-04-07 23:04:48 -04:00
|
|
|
Environment *ModApiBase::getEnv(lua_State *L)
|
|
|
|
{
|
2013-08-11 04:09:45 +02:00
|
|
|
return getScriptApiBase(L)->getEnv();
|
2013-05-25 00:51:02 +02:00
|
|
|
}
|
|
|
|
|
2024-10-15 15:47:23 +02:00
|
|
|
#if CHECK_CLIENT_BUILD()
|
2015-04-07 23:04:48 -04:00
|
|
|
GUIEngine *ModApiBase::getGuiEngine(lua_State *L)
|
|
|
|
{
|
2013-08-11 04:09:45 +02:00
|
|
|
return getScriptApiBase(L)->getGuiEngine();
|
2013-05-25 00:51:02 +02:00
|
|
|
}
|
2020-04-26 20:57:27 +02:00
|
|
|
#endif
|
2013-05-25 00:51:02 +02:00
|
|
|
|
2024-02-13 22:47:30 +01:00
|
|
|
EmergeThread *ModApiBase::getEmergeThread(lua_State *L)
|
|
|
|
{
|
|
|
|
return getScriptApiBase(L)->getEmergeThread();
|
|
|
|
}
|
|
|
|
|
2015-04-07 23:04:48 -04:00
|
|
|
std::string ModApiBase::getCurrentModPath(lua_State *L)
|
|
|
|
{
|
2024-02-14 13:29:53 +01:00
|
|
|
std::string current_mod_name = ScriptApiBase::getCurrentModNameInsecure(L);
|
2018-06-30 17:11:38 +02:00
|
|
|
if (current_mod_name.empty())
|
2015-04-07 23:04:48 -04:00
|
|
|
return ".";
|
|
|
|
|
2015-05-16 19:09:53 -04:00
|
|
|
const ModSpec *mod = getServer(L)->getModSpec(current_mod_name);
|
2015-04-07 23:04:48 -04:00
|
|
|
if (!mod)
|
|
|
|
return ".";
|
|
|
|
|
|
|
|
return mod->path;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-12-12 14:49:19 -05:00
|
|
|
bool ModApiBase::registerFunction(lua_State *L, const char *name,
|
|
|
|
lua_CFunction func, int top)
|
2015-04-07 23:04:48 -04:00
|
|
|
{
|
2014-12-12 14:49:19 -05:00
|
|
|
// TODO: Check presence first!
|
2013-05-25 00:51:02 +02:00
|
|
|
|
2014-12-12 14:49:19 -05:00
|
|
|
lua_pushcfunction(L, func);
|
|
|
|
lua_setfield(L, top, name);
|
2013-05-25 00:51:02 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2018-07-01 12:31:49 +02:00
|
|
|
|
2020-10-31 18:19:23 +00:00
|
|
|
int ModApiBase::l_deprecated_function(lua_State *L, const char *good, const char *bad, lua_CFunction func)
|
2018-07-01 12:31:49 +02:00
|
|
|
{
|
|
|
|
thread_local std::vector<u64> deprecated_logged;
|
|
|
|
|
2020-10-31 18:19:23 +00:00
|
|
|
DeprecatedHandlingMode dep_mode = get_deprecated_handling_mode();
|
|
|
|
if (dep_mode == DeprecatedHandlingMode::Ignore)
|
|
|
|
return func(L);
|
|
|
|
|
2018-07-01 12:31:49 +02:00
|
|
|
u64 start_time = porting::getTimeUs();
|
|
|
|
lua_Debug ar;
|
2025-04-23 21:41:18 +02:00
|
|
|
std::string backtrace;
|
2018-07-01 12:31:49 +02:00
|
|
|
|
2020-10-31 18:19:23 +00:00
|
|
|
// Get caller name with line and script backtrace
|
2025-04-23 21:41:18 +02:00
|
|
|
if (lua_getstack(L, 1, &ar) && lua_getinfo(L, "Sl", &ar)) {
|
|
|
|
// Get backtrace and hash it to reduce the warning flood
|
|
|
|
backtrace = ar.short_src;
|
|
|
|
backtrace.append(":").append(std::to_string(ar.currentline));
|
|
|
|
} else {
|
|
|
|
backtrace = "<tail call optimized coroutine> ";
|
|
|
|
backtrace.append(script_get_backtrace(L));
|
|
|
|
}
|
2018-07-01 12:31:49 +02:00
|
|
|
|
|
|
|
u64 hash = murmur_hash_64_ua(backtrace.data(), backtrace.length(), 0xBADBABE);
|
|
|
|
|
|
|
|
if (std::find(deprecated_logged.begin(), deprecated_logged.end(), hash)
|
|
|
|
== deprecated_logged.end()) {
|
|
|
|
|
|
|
|
deprecated_logged.emplace_back(hash);
|
2024-02-12 22:58:26 +01:00
|
|
|
|
|
|
|
std::stringstream msg;
|
|
|
|
msg << "Call to deprecated function '" << bad << "', use '" << good << "' instead";
|
|
|
|
|
|
|
|
warningstream << msg.str() << " at " << backtrace << std::endl;
|
2018-07-01 12:31:49 +02:00
|
|
|
|
2020-10-31 18:19:23 +00:00
|
|
|
if (dep_mode == DeprecatedHandlingMode::Error)
|
2024-02-12 22:58:26 +01:00
|
|
|
throw LuaError(msg.str());
|
2018-07-01 12:31:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
u64 end_time = porting::getTimeUs();
|
|
|
|
g_profiler->avg("l_deprecated_function", end_time - start_time);
|
|
|
|
|
2020-10-31 18:19:23 +00:00
|
|
|
return func(L);
|
2018-07-01 12:31:49 +02:00
|
|
|
}
|
|
|
|
|