aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSmallJoker <mk939@ymail.com>2019-06-25 21:18:08 +0200
committerSmallJoker <mk939@ymail.com>2019-09-14 19:42:25 +0200
commit23677be951b4dc2b9cc174ceb92f0e0b8e8eb867 (patch)
tree87e8a9bee105bbe77d964e109d0cefd1102f07e7
parent720aedb46740ba203b4a0f3e049e368abc4932b3 (diff)
downloadminetest-23677be951b4dc2b9cc174ceb92f0e0b8e8eb867.tar.gz
minetest-23677be951b4dc2b9cc174ceb92f0e0b8e8eb867.tar.bz2
minetest-23677be951b4dc2b9cc174ceb92f0e0b8e8eb867.zip
Load CSM environment after the restrictions are known
Safety-guards for CSM callbacks to abort on a bad implementation Only run callbacks when the mods are loaded (and with it: builtin) Duplication checks inside constructors
-rw-r--r--src/client/camera.cpp4
-rw-r--r--src/client/client.cpp35
-rw-r--r--src/client/client.h1
-rw-r--r--src/client/game.cpp20
-rw-r--r--src/network/clientpackethandler.cpp5
-rw-r--r--src/script/cpp_api/s_base.cpp7
-rw-r--r--src/script/cpp_api/s_security.cpp1
-rw-r--r--src/script/lua_api/l_camera.cpp21
-rw-r--r--src/script/lua_api/l_localplayer.cpp22
-rw-r--r--src/script/scripting_client.cpp3
10 files changed, 64 insertions, 55 deletions
diff --git a/src/client/camera.cpp b/src/client/camera.cpp
index 7e953d4c7..025bd081d 100644
--- a/src/client/camera.cpp
+++ b/src/client/camera.cpp
@@ -99,9 +99,9 @@ bool Camera::successfullyCreated(std::string &error_message)
error_message.clear();
}
- if (g_settings->getBool("enable_client_modding")) {
+ if (m_client->modsLoaded())
m_client->getScript()->on_camera_ready(this);
- }
+
return error_message.empty();
}
diff --git a/src/client/client.cpp b/src/client/client.cpp
index 4c5485325..9535acc8e 100644
--- a/src/client/client.cpp
+++ b/src/client/client.cpp
@@ -108,15 +108,6 @@ Client::Client(
m_minimap = new Minimap(this);
}
m_cache_save_interval = g_settings->getU16("server_map_save_interval");
-
- m_modding_enabled = g_settings->getBool("enable_client_modding");
- // Only create the client script environment if client scripting is enabled by the
- // client.
- if (m_modding_enabled) {
- m_script = new ClientScripting(this);
- m_env.setScript(m_script);
- m_script->setEnv(&m_env);
- }
}
void Client::loadMods()
@@ -124,9 +115,8 @@ void Client::loadMods()
// Don't load mods twice.
// If client scripting is disabled by the client, don't load builtin or
// client-provided mods.
- if (m_mods_loaded || !m_modding_enabled) {
+ if (m_mods_loaded || !g_settings->getBool("enable_client_modding"))
return;
- }
// If client scripting is disabled by the server, don't load builtin or
// client-provided mods.
@@ -135,11 +125,13 @@ void Client::loadMods()
if (checkCSMRestrictionFlag(CSMRestrictionFlags::CSM_RF_LOAD_CLIENT_MODS)) {
warningstream << "Client-provided mod loading is disabled by server." <<
std::endl;
- // This line is needed because builtin is not loaded
- m_modding_enabled = false;
return;
}
+ m_script = new ClientScripting(this);
+ m_env.setScript(m_script);
+ m_script->setEnv(&m_env);
+
// Load builtin
scanModIntoMemory(BUILTIN_MOD_NAME, getBuiltinLuaPath());
m_script->loadModFromMemory(BUILTIN_MOD_NAME);
@@ -185,9 +177,15 @@ void Client::loadMods()
for (const ModSpec &mod : m_mods)
m_script->loadModFromMemory(mod.name);
+ // Mods are done loading. Unlock callbacks
+ m_mods_loaded = true;
+
// Run a callback when mods are loaded
m_script->on_mods_loaded();
- m_mods_loaded = true;
+ if (m_state == LC_Ready)
+ m_script->on_client_ready(m_env.getLocalPlayer());
+ if (m_camera)
+ m_script->on_camera_ready(m_camera);
}
bool Client::checkBuiltinIntegrity()
@@ -239,7 +237,7 @@ const ModSpec* Client::getModSpec(const std::string &modname) const
void Client::Stop()
{
m_shutdown = true;
- if (m_modding_enabled)
+ if (m_mods_loaded)
m_script->on_shutdown();
//request all client managed threads to stop
m_mesh_update_thread.stop();
@@ -249,7 +247,7 @@ void Client::Stop()
m_localdb->endSave();
}
- if (m_modding_enabled)
+ if (m_mods_loaded)
delete m_script;
}
@@ -1497,7 +1495,7 @@ void Client::typeChatMessage(const std::wstring &message)
return;
// If message was consumed by script API, don't send it to server
- if (m_modding_enabled && m_script->on_sending_message(wide_to_utf8(message)))
+ if (m_mods_loaded && m_script->on_sending_message(wide_to_utf8(message)))
return;
// Send to others
@@ -1693,9 +1691,8 @@ void Client::afterContentReceived()
m_state = LC_Ready;
sendReady();
- if (g_settings->getBool("enable_client_modding")) {
+ if (m_mods_loaded)
m_script->on_client_ready(m_env.getLocalPlayer());
- }
text = wgettext("Done!");
RenderingEngine::draw_load_screen(text, guienv, m_tsrc, 0, 100);
diff --git a/src/client/client.h b/src/client/client.h
index 85456fe4d..6dad48c3d 100644
--- a/src/client/client.h
+++ b/src/client/client.h
@@ -397,7 +397,6 @@ public:
}
ClientScripting *getScript() { return m_script; }
- const bool moddingEnabled() const { return m_modding_enabled; }
const bool modsLoaded() const { return m_mods_loaded; }
void pushToEventQueue(ClientEvent *event);
diff --git a/src/client/game.cpp b/src/client/game.cpp
index 5bf41bcd6..b5508f2cb 100644
--- a/src/client/game.cpp
+++ b/src/client/game.cpp
@@ -184,7 +184,7 @@ struct LocalFormspecHandler : public TextDest
return;
}
- if (m_client && m_client->moddingEnabled())
+ if (m_client && m_client->modsLoaded())
m_client->getScript()->on_formspec_input(m_formname, fields);
}
@@ -1870,7 +1870,7 @@ void Game::processKeyInput()
} else if (wasKeyDown(KeyType::CMD)) {
openConsole(0.2, L"/");
} else if (wasKeyDown(KeyType::CMD_LOCAL)) {
- if (client->moddingEnabled())
+ if (client->modsLoaded())
openConsole(0.2, L".");
else
m_game_ui->showStatusText(wgettext("Client side scripting is disabled"));
@@ -2026,7 +2026,7 @@ void Game::openInventory()
InventoryLocation inventoryloc;
inventoryloc.setCurrentPlayer();
- if (!client->moddingEnabled()
+ if (!client->modsLoaded()
|| !client->getScript()->on_inventory_open(fs_src->m_client->getInventory(inventoryloc))) {
TextDest *txt_dst = new TextDestPlayerInventory(client);
auto *&formspec = m_game_ui->updateFormspec("");
@@ -2516,9 +2516,8 @@ void Game::handleClientEvent_None(ClientEvent *event, CameraOrientation *cam)
void Game::handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam)
{
- if (client->moddingEnabled()) {
+ if (client->modsLoaded())
client->getScript()->on_damage_taken(event->player_damage.amount);
- }
// Damage flash and hurt tilt are not used at death
if (client->getHP() > 0) {
@@ -2546,7 +2545,7 @@ void Game::handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation *
{
// If client scripting is enabled, deathscreen is handled by CSM code in
// builtin/client/init.lua
- if (client->moddingEnabled())
+ if (client->modsLoaded())
client->getScript()->on_death();
else
showDeathFormspec();
@@ -3033,9 +3032,8 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug)
else
runData.repeat_rightclick_timer = 0;
-
if (selected_def.usable && input->getLeftState()) {
- if (input->getLeftClicked() && (!client->moddingEnabled()
+ if (input->getLeftClicked() && (!client->modsLoaded()
|| !client->getScript()->on_item_use(selected_item, pointed)))
client->interact(INTERACT_USE, pointed);
} else if (pointed.type == POINTEDTHING_NODE) {
@@ -3240,7 +3238,7 @@ void Game::handlePointingAtNode(const PointedThing &pointed,
soundmaker->m_player_rightpunch_sound =
def.sound_place;
- if (client->moddingEnabled())
+ if (client->modsLoaded())
client->getScript()->on_placenode(pointed, def);
} else {
soundmaker->m_player_rightpunch_sound =
@@ -3496,7 +3494,7 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
if (!runData.digging) {
infostream << "Started digging" << std::endl;
runData.dig_instantly = runData.dig_time_complete == 0;
- if (client->moddingEnabled() && client->getScript()->on_punchnode(nodepos, n))
+ if (client->modsLoaded() && client->getScript()->on_punchnode(nodepos, n))
return;
client->interact(INTERACT_START_DIGGING, pointed);
runData.digging = true;
@@ -3556,7 +3554,7 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
bool is_valid_position;
MapNode wasnode = map.getNode(nodepos, &is_valid_position);
if (is_valid_position) {
- if (client->moddingEnabled() &&
+ if (client->modsLoaded() &&
client->getScript()->on_dignode(nodepos, wasnode)) {
return;
}
diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp
index 91829474e..a8ae8a5ef 100644
--- a/src/network/clientpackethandler.cpp
+++ b/src/network/clientpackethandler.cpp
@@ -415,7 +415,7 @@ void Client::handleCommand_ChatMessage(NetworkPacket *pkt)
chatMessage->type = (ChatMessageType) message_type;
// @TODO send this to CSM using ChatMessage object
- if (moddingEnabled() && m_script->on_receiving_message(
+ if (modsLoaded() && m_script->on_receiving_message(
wide_to_utf8(chatMessage->message))) {
// Message was consumed by CSM and should not be handled by client
delete chatMessage;
@@ -532,9 +532,8 @@ void Client::handleCommand_HP(NetworkPacket* pkt)
player->hp = hp;
- if (moddingEnabled()) {
+ if (modsLoaded())
m_script->on_hp_modification(hp);
- }
if (hp < oldhp) {
// Add to ClientEvent queue
diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp
index e73f613ce..caa335d76 100644
--- a/src/script/cpp_api/s_base.cpp
+++ b/src/script/cpp_api/s_base.cpp
@@ -232,6 +232,13 @@ void ScriptApiBase::loadModFromMemory(const std::string &mod_name)
void ScriptApiBase::runCallbacksRaw(int nargs,
RunCallbacksMode mode, const char *fxn)
{
+#ifndef SERVER
+ // Hard fail for bad guarded callbacks
+ // Only run callbacks when the scripting enviroment is loaded
+ FATAL_ERROR_IF(m_type == ScriptingType::Client &&
+ !getClient()->modsLoaded(), fxn);
+#endif
+
#ifdef SCRIPTAPI_LOCK_DEBUG
assert(m_lock_recursion_count > 0);
#endif
diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp
index 876c7761a..d972be980 100644
--- a/src/script/cpp_api/s_security.cpp
+++ b/src/script/cpp_api/s_security.cpp
@@ -264,6 +264,7 @@ void ScriptApiSecurity::initializeSecurityClient()
};
static const char *debug_whitelist[] = {
"getinfo",
+ "traceback"
};
#if USE_LUAJIT
diff --git a/src/script/lua_api/l_camera.cpp b/src/script/lua_api/l_camera.cpp
index 462006777..80071b3b8 100644
--- a/src/script/lua_api/l_camera.cpp
+++ b/src/script/lua_api/l_camera.cpp
@@ -31,19 +31,24 @@ LuaCamera::LuaCamera(Camera *m) : m_camera(m)
void LuaCamera::create(lua_State *L, Camera *m)
{
+ lua_getglobal(L, "core");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ int objectstable = lua_gettop(L);
+ lua_getfield(L, -1, "camera");
+
+ // Duplication check
+ if (lua_type(L, -1) == LUA_TUSERDATA) {
+ lua_pop(L, 1);
+ return;
+ }
+
LuaCamera *o = new LuaCamera(m);
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
luaL_getmetatable(L, className);
lua_setmetatable(L, -2);
- int camera_object = lua_gettop(L);
-
- lua_getglobal(L, "core");
- luaL_checktype(L, -1, LUA_TTABLE);
- int coretable = lua_gettop(L);
-
- lua_pushvalue(L, camera_object);
- lua_setfield(L, coretable, "camera");
+ lua_pushvalue(L, lua_gettop(L));
+ lua_setfield(L, objectstable, "camera");
}
int LuaCamera::l_set_camera_mode(lua_State *L)
diff --git a/src/script/lua_api/l_localplayer.cpp b/src/script/lua_api/l_localplayer.cpp
index 7444d0e88..3e14e48e4 100644
--- a/src/script/lua_api/l_localplayer.cpp
+++ b/src/script/lua_api/l_localplayer.cpp
@@ -30,20 +30,24 @@ LuaLocalPlayer::LuaLocalPlayer(LocalPlayer *m) : m_localplayer(m)
void LuaLocalPlayer::create(lua_State *L, LocalPlayer *m)
{
+ lua_getglobal(L, "core");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ int objectstable = lua_gettop(L);
+ lua_getfield(L, -1, "localplayer");
+
+ // Duplication check
+ if (lua_type(L, -1) == LUA_TUSERDATA) {
+ lua_pop(L, 1);
+ return;
+ }
+
LuaLocalPlayer *o = new LuaLocalPlayer(m);
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
luaL_getmetatable(L, className);
lua_setmetatable(L, -2);
- // Keep localplayer object stack id
- int localplayer_object = lua_gettop(L);
-
- lua_getglobal(L, "core");
- luaL_checktype(L, -1, LUA_TTABLE);
- int coretable = lua_gettop(L);
-
- lua_pushvalue(L, localplayer_object);
- lua_setfield(L, coretable, "localplayer");
+ lua_pushvalue(L, lua_gettop(L));
+ lua_setfield(L, objectstable, "localplayer");
}
int LuaLocalPlayer::l_get_velocity(lua_State *L)
diff --git a/src/script/scripting_client.cpp b/src/script/scripting_client.cpp
index 86e5f2874..239c98e57 100644
--- a/src/script/scripting_client.cpp
+++ b/src/script/scripting_client.cpp
@@ -84,8 +84,7 @@ void ClientScripting::InitializeModApi(lua_State *L, int top)
void ClientScripting::on_client_ready(LocalPlayer *localplayer)
{
- lua_State *L = getStack();
- LuaLocalPlayer::create(L, localplayer);
+ LuaLocalPlayer::create(getStack(), localplayer);
}
void ClientScripting::on_camera_ready(Camera *camera)