mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
[CSM] Client side modding
* rename GameScripting to ServerScripting * Make getBuiltinLuaPath static serverside * Add on_shutdown callback * Add on_receiving_chat_message & on_sending_chat_message callbacks * ScriptApiBase: use IGameDef instead of Server This permits to share common attribute between client & server * Enable mod security in client side modding without conditions
This commit is contained in:
parent
c9492b4d37
commit
2efae3ffd7
37 changed files with 488 additions and 64 deletions
|
@ -13,6 +13,7 @@ set(common_SCRIPT_CPP_API_SRCS
|
|||
PARENT_SCOPE)
|
||||
|
||||
set(client_SCRIPT_CPP_API_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/s_client.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/s_mainmenu.cpp
|
||||
PARENT_SCOPE)
|
||||
|
||||
|
|
|
@ -23,12 +23,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "lua_api/l_object.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "serverobject.h"
|
||||
#include "debug.h"
|
||||
#include "filesys.h"
|
||||
#include "log.h"
|
||||
#include "mods.h"
|
||||
#include "porting.h"
|
||||
#include "util/string.h"
|
||||
#include "server.h"
|
||||
#ifndef SERVER
|
||||
#include "client.h"
|
||||
#endif
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
@ -69,7 +71,8 @@ public:
|
|||
*/
|
||||
|
||||
ScriptApiBase::ScriptApiBase() :
|
||||
m_luastackmutex()
|
||||
m_luastackmutex(),
|
||||
m_gamedef(NULL)
|
||||
{
|
||||
#ifdef SCRIPTAPI_LOCK_DEBUG
|
||||
m_lock_recursion_count = 0;
|
||||
|
@ -113,7 +116,6 @@ ScriptApiBase::ScriptApiBase() :
|
|||
// Default to false otherwise
|
||||
m_secure = false;
|
||||
|
||||
m_server = NULL;
|
||||
m_environment = NULL;
|
||||
m_guiengine = NULL;
|
||||
}
|
||||
|
@ -333,3 +335,14 @@ void ScriptApiBase::objectrefGet(lua_State *L, u16 id)
|
|||
lua_remove(L, -2); // object_refs
|
||||
lua_remove(L, -2); // core
|
||||
}
|
||||
|
||||
Server* ScriptApiBase::getServer()
|
||||
{
|
||||
return dynamic_cast<Server *>(m_gamedef);
|
||||
}
|
||||
#ifndef SERVER
|
||||
Client* ScriptApiBase::getClient()
|
||||
{
|
||||
return dynamic_cast<Client *>(m_gamedef);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -55,6 +55,10 @@ extern "C" {
|
|||
setOriginFromTableRaw(index, __FUNCTION__)
|
||||
|
||||
class Server;
|
||||
#ifndef SERVER
|
||||
class Client;
|
||||
#endif
|
||||
class IGameDef;
|
||||
class Environment;
|
||||
class GUIEngine;
|
||||
class ServerActiveObject;
|
||||
|
@ -75,7 +79,11 @@ public:
|
|||
void addObjectReference(ServerActiveObject *cobj);
|
||||
void removeObjectReference(ServerActiveObject *cobj);
|
||||
|
||||
Server* getServer() { return m_server; }
|
||||
IGameDef *getGameDef() { return m_gamedef; }
|
||||
Server* getServer();
|
||||
#ifndef SERVER
|
||||
Client* getClient();
|
||||
#endif
|
||||
|
||||
std::string getOrigin() { return m_last_run_mod; }
|
||||
void setOriginDirect(const char *origin);
|
||||
|
@ -98,7 +106,7 @@ protected:
|
|||
void scriptError(int result, const char *fxn);
|
||||
void stackDump(std::ostream &o);
|
||||
|
||||
void setServer(Server* server) { m_server = server; }
|
||||
void setGameDef(IGameDef* gamedef) { m_gamedef = gamedef; }
|
||||
|
||||
Environment* getEnv() { return m_environment; }
|
||||
void setEnv(Environment* env) { m_environment = env; }
|
||||
|
@ -122,7 +130,7 @@ private:
|
|||
|
||||
lua_State* m_luastack;
|
||||
|
||||
Server* m_server;
|
||||
IGameDef* m_gamedef;
|
||||
Environment* m_environment;
|
||||
GUIEngine* m_guiengine;
|
||||
};
|
||||
|
|
61
src/script/cpp_api/s_client.cpp
Normal file
61
src/script/cpp_api/s_client.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "s_client.h"
|
||||
#include "s_internal.h"
|
||||
|
||||
void ScriptApiClient::on_shutdown()
|
||||
{
|
||||
SCRIPTAPI_PRECHECKHEADER
|
||||
|
||||
// Get registered shutdown hooks
|
||||
lua_getglobal(L, "core");
|
||||
lua_getfield(L, -1, "registered_on_shutdown");
|
||||
// Call callbacks
|
||||
runCallbacks(0, RUN_CALLBACKS_MODE_FIRST);
|
||||
}
|
||||
|
||||
bool ScriptApiClient::on_sending_message(const std::string &message)
|
||||
{
|
||||
SCRIPTAPI_PRECHECKHEADER
|
||||
|
||||
// Get core.registered_on_chat_messages
|
||||
lua_getglobal(L, "core");
|
||||
lua_getfield(L, -1, "registered_on_sending_chat_messages");
|
||||
// Call callbacks
|
||||
lua_pushstring(L, message.c_str());
|
||||
runCallbacks(1, RUN_CALLBACKS_MODE_OR_SC);
|
||||
bool ate = lua_toboolean(L, -1);
|
||||
return ate;
|
||||
}
|
||||
|
||||
bool ScriptApiClient::on_receiving_message(const std::string &message)
|
||||
{
|
||||
SCRIPTAPI_PRECHECKHEADER
|
||||
|
||||
// Get core.registered_on_chat_messages
|
||||
lua_getglobal(L, "core");
|
||||
lua_getfield(L, -1, "registered_on_receiving_chat_messages");
|
||||
// Call callbacks
|
||||
lua_pushstring(L, message.c_str());
|
||||
runCallbacks(1, RUN_CALLBACKS_MODE_OR_SC);
|
||||
bool ate = lua_toboolean(L, -1);
|
||||
return ate;
|
||||
}
|
36
src/script/cpp_api/s_client.h
Normal file
36
src/script/cpp_api/s_client.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef S_CLIENT_H_
|
||||
#define S_CLIENT_H_
|
||||
|
||||
#include "cpp_api/s_base.h"
|
||||
|
||||
class ScriptApiClient: virtual public ScriptApiBase
|
||||
{
|
||||
public:
|
||||
// Calls on_shutdown handlers
|
||||
void on_shutdown();
|
||||
|
||||
// Chat message handlers
|
||||
bool on_sending_message(const std::string &message);
|
||||
bool on_receiving_message(const std::string &message);
|
||||
};
|
||||
#endif
|
|
@ -382,9 +382,9 @@ bool ScriptApiSecurity::checkPath(lua_State *L, const char *path,
|
|||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_SCRIPTAPI);
|
||||
ScriptApiBase *script = (ScriptApiBase *) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
const Server *server = script->getServer();
|
||||
|
||||
if (!server) return false;
|
||||
const IGameDef *gamedef = script->getGameDef();
|
||||
if (!gamedef)
|
||||
return false;
|
||||
|
||||
// Get mod name
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
|
||||
|
@ -400,7 +400,7 @@ bool ScriptApiSecurity::checkPath(lua_State *L, const char *path,
|
|||
// Allow paths in mod path
|
||||
// Don't bother if write access isn't important, since it will be handled later
|
||||
if (write_required || write_allowed != NULL) {
|
||||
const ModSpec *mod = server->getModSpec(mod_name);
|
||||
const ModSpec *mod = gamedef->getModSpec(mod_name);
|
||||
if (mod) {
|
||||
str = fs::AbsolutePath(mod->path);
|
||||
if (!str.empty() && fs::PathStartsWith(abs_path, str)) {
|
||||
|
@ -414,7 +414,7 @@ bool ScriptApiSecurity::checkPath(lua_State *L, const char *path,
|
|||
|
||||
// Allow read-only access to all mod directories
|
||||
if (!write_required) {
|
||||
const std::vector<ModSpec> mods = server->getMods();
|
||||
const std::vector<ModSpec> mods = gamedef->getMods();
|
||||
for (size_t i = 0; i < mods.size(); ++i) {
|
||||
str = fs::AbsolutePath(mods[i].path);
|
||||
if (!str.empty() && fs::PathStartsWith(abs_path, str)) {
|
||||
|
@ -423,7 +423,7 @@ bool ScriptApiSecurity::checkPath(lua_State *L, const char *path,
|
|||
}
|
||||
}
|
||||
|
||||
str = fs::AbsolutePath(server->getWorldPath());
|
||||
str = fs::AbsolutePath(gamedef->getWorldPath());
|
||||
if (!str.empty()) {
|
||||
// Don't allow access to other paths in the world mod/game path.
|
||||
// These have to be blocked so you can't override a trusted mod
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue